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)