From 73f36bfe71b68d241a6802e0396dc6d6822cb520 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Tue, 11 Sep 2018 13:07:05 +0000 Subject: [PATCH 01/10] Unity 2018.3.0b1 C# reference source code --- Editor/Mono/AssetStore/AssetStoreContext.cs | 17 + .../GUI/AudioMixerExposedParameterView.cs | 4 + .../GUI/AudioMixerExposedParametersPopup.cs | 2 +- Editor/Mono/BuildPipeline/AssemblyStripper.cs | 2 +- Editor/Mono/Collab/Collab.bindings.cs | 5 + Editor/Mono/Collab/Collab.cs | 10 +- Editor/Mono/Commands/GOCreationCommands.cs | 7 +- Editor/Mono/ContainerWindow.bindings.cs | 6 +- Editor/Mono/ContainerWindow.cs | 14 +- Editor/Mono/EditorApplication.cs | 11 + Editor/Mono/EditorGUI.cs | 65 +++- .../BoundsHandle/PrimitiveBoundsHandle.cs | 4 +- .../EditorHandles/JointAngularLimitHandle.cs | 8 +- .../Mono/EditorUserBuildSettings.bindings.cs | 9 + Editor/Mono/EditorUtility.cs | 10 +- Editor/Mono/EditorWindow.cs | 22 +- .../GI/LightmapEditorSettings.bindings.cs | 7 +- Editor/Mono/GUI/ColorPicker.cs | 23 +- Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs | 4 +- Editor/Mono/GUI/Toolbar.cs | 1 + .../TreeView/GameObjectTreeViewDataSource.cs | 4 - Editor/Mono/GUI/WindowLayout.cs | 11 +- Editor/Mono/GameView/GameViewSizes.cs | 8 +- Editor/Mono/HandleUtility.cs | 11 +- Editor/Mono/Handles.cs | 4 +- .../Inspector/Avatar/AvatarMappingEditor.cs | 14 +- Editor/Mono/Inspector/CameraEditor.cs | 2 +- Editor/Mono/Inspector/LabelGUI.cs | 4 +- .../Inspector/LightingSettingsInspector.cs | 12 +- .../Inspector/MaterialEditorGUIHelpers.cs | 1 + .../PlayerSettingsEditor.cs | 42 +-- Editor/Mono/Inspector/RectTransformEditor.cs | 2 +- Editor/Mono/Inspector/TagManagerInspector.cs | 2 +- Editor/Mono/Inspector/TextureInspector.cs | 103 ++++- Editor/Mono/LookDevView/LookDevView.cs | 2 +- Editor/Mono/Prefabs/PrefabUtility.bindings.cs | 38 +- Editor/Mono/Prefabs/PrefabUtility.cs | 79 ++-- Editor/Mono/ProjectBrowser.cs | 2 +- .../Mono/ProjectWindow/ProjectWindowUtil.cs | 15 - Editor/Mono/SceneHierarchy.cs | 4 +- Editor/Mono/SceneHierarchyStageHandling.cs | 26 +- .../StageManager/PrefabStage/PrefabStage.cs | 54 ++- .../DefaultLightingExplorerExtension.cs | 14 +- .../LightingWindowBakeSettings.cs | 37 +- Editor/Mono/SceneView/SceneView.cs | 4 +- .../Mono/Scripting/Compilers/UWPReferences.cs | 10 +- .../ScriptCompilation/EditorCompilation.cs | 26 +- .../EditorScriptCompilationOptions.cs | 3 +- Editor/Mono/TooltipView/TooltipView.cs | 2 +- .../SolutionSynchronizer.cs | 6 + .../AssetImporterTabbedEditor.cs | 2 + .../Manipulators/SelectionDragger.cs | 2 + Modules/GraphViewEditor/Views/GraphView.cs | 1 + .../GridEditor/Managed/GridEditorUtility.cs | 40 +- Modules/IMGUI/GUILayout.cs | 5 + .../ImageConversion.bindings.cs | 2 +- .../MemoryProfiler/MemorySnapshot.cs | 20 +- .../ProfilerWindow/NetworkDetailStats.cs | 4 + .../ProfilerFrameHierarchyView.cs | 104 ++--- .../ProfilerWindow/ProfilerTimelineGUI.cs | 355 +++++++++--------- .../ProfilerWindow/ProfilerWindow.cs | 303 ++++++++------- .../Public/ProfilerAPI.bindings.cs | 2 +- .../ProfilerFrameDataIterator.bindings.cs | 8 + .../ShortcutController.cs | 11 + Modules/ShortcutManagerEditor/Trigger.cs | 5 + Modules/Tilemap/Managed/GridBrushBase.cs | 3 + .../Editor/Managed/Grid/GridBrush.cs | 1 + .../Managed/Grid/GridBrushEditorBase.cs | 6 + .../Managed/Grid/GridPaintPaletteClipboard.cs | 39 +- .../Managed/Grid/GridPaintPaletteWindow.cs | 80 +++- .../Editor/Managed/Grid/GridPaintingState.cs | 13 +- .../Editor/Managed/Grid/PaintableGrid.cs | 50 ++- .../Managed/Grid/PaintableSceneViewGrid.cs | 10 +- .../Editor/Managed/TilemapEditor.cs | 31 +- Modules/TreeEditor/TreeEditor.cs | 2 - .../EditorAnalytics.bindings.cs | 2 + .../Public/DownloadHandlerAudio.bindings.cs | 1 + Modules/XR/ScriptBindings/XRInput.bindings.cs | 95 +++-- README.md | 2 +- Runtime/Export/Camera.bindings.cs | 6 +- Runtime/Export/GI/DynamicGI.bindings.cs | 3 + Runtime/Export/GraphicsEnums.cs | 11 + Runtime/Export/SystemInfo.bindings.cs | 8 + Runtime/Export/Vector3Int.cs | 4 +- .../Networking/Managed/MatchMakingClient.cs | 7 +- .../Managed/NetworkTransportConfig.cs | 5 + .../UNETTransportConfig.bindings.cs | 2 + .../ScriptBindings/UNETworking.bindings.cs | 1 + .../MemoryProfiling.bindings.cs | 5 + 89 files changed, 1240 insertions(+), 784 deletions(-) diff --git a/Editor/Mono/AssetStore/AssetStoreContext.cs b/Editor/Mono/AssetStore/AssetStoreContext.cs index 068e39c522..7669651041 100644 --- a/Editor/Mono/AssetStore/AssetStoreContext.cs +++ b/Editor/Mono/AssetStore/AssetStoreContext.cs @@ -12,6 +12,7 @@ using System.Linq; using System.IO; using UnityEditor.Web; +using UnityEditor.Analytics; namespace UnityEditor { @@ -163,6 +164,15 @@ public void OpenBrowser(string url) Application.OpenURL(url); } + [Serializable] + public struct DownloadAssetInfo + { + public string package_id; + public string package_name; + public string publisher_name; + public string category_name; + } + public void Download(Package package, DownloadInfo downloadInfo) { Download( @@ -205,6 +215,13 @@ public static void Download(string package_id, string url, string key, string pa parameters["download"] = download; AssetStoreUtils.Download(package_id, url, dest, key, parameters.ToString(), resumeOK, doneCallback); + EditorAnalytics.SendAssetDownloadEvent(new DownloadAssetInfo() + { + package_id = package_id, + package_name = package_name, + publisher_name = publisher_name, + category_name = category_name + }); } /// diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs index 9832a5c637..8c86a45d7a 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParameterView.cs @@ -106,6 +106,10 @@ void DrawElement(Rect rect, int index, bool isActive, bool isFocused) public Vector2 CalcSize() { + if (m_ReorderableListWithRenameAndScrollView.list.count != m_Controller.exposedParameters.Length) + { + RecreateListControl(); + } float maxWidth = 0; for (int index = 0; index < m_ReorderableListWithRenameAndScrollView.list.count; index++) { diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs index c2935d9343..b06409045d 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerExposedParametersPopup.cs @@ -18,7 +18,7 @@ internal static void Popup(AudioMixerController controller, GUIStyle style, para Rect buttonRect = GUILayoutUtility.GetRect(content, style, options); if (EditorGUI.DropdownButton(buttonRect, content, FocusType.Passive, style)) { - PopupWindow.Show(buttonRect, new AudioMixerExposedParametersPopup(controller), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(buttonRect, new AudioMixerExposedParametersPopup(controller)); } } diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index 69c450511f..3f9223838c 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -77,7 +77,7 @@ private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, args.AddRange(additionalBlacklist.Select(path => "-x \"" + path + "\"")); args.AddRange(searchDirs.Select(d => "-d \"" + d + "\"")); - args.AddRange(assemblies.Select(assembly => "-a \"" + Path.GetFullPath(assembly) + "\"")); + args.AddRange(assemblies.Select(assembly => "--include-unity-root-assembly=\"" + Path.GetFullPath(assembly) + "\"")); args.Add($"--dotnetruntime={GetRuntimeArgumentValueForLinker(buildTargetGroup)}"); args.Add($"--dotnetprofile={GetProfileArgumentValueForLinker(buildTargetGroup)}"); args.Add("--use-editor-options"); diff --git a/Editor/Mono/Collab/Collab.bindings.cs b/Editor/Mono/Collab/Collab.bindings.cs index e2755d5759..253f72c7b9 100644 --- a/Editor/Mono/Collab/Collab.bindings.cs +++ b/Editor/Mono/Collab/Collab.bindings.cs @@ -206,12 +206,17 @@ public extern void TestClearSoftLockAsCollaborator(string projectGuid, string pr [NativeMethod(HasExplicitThis = true, ThrowsException = true, IsThreadSafe = true)] extern void SetChangesToPublishInternal(ChangeItem[] changes); + [NativeMethod(HasExplicitThis = true, ThrowsException = true, IsThreadSafe = true)] + extern Change[] GetSelectedChangesInternal(); + [NativeMethod(Name = "GetJobProgress", HasExplicitThis = true, ThrowsException = true)] extern bool GetJobProgressInternal([Out] ProgressInfo info, int jobId); [NativeMethod(HasExplicitThis = true, ThrowsException = true)] public extern void Publish(string comment, bool useSelectedAssets, bool confirmMatchesPrevious); + [NativeMethod(HasExplicitThis = true, ThrowsException = true, IsThreadSafe = true)] + public extern void ClearSelectedChangesToPublish(); [NativeMethod(HasExplicitThis = true, ThrowsException = true)] public extern SoftLock[] GetSoftLocks(string assetGuid); diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs index 2ab706e9eb..80ec1bd2c5 100644 --- a/Editor/Mono/Collab/Collab.cs +++ b/Editor/Mono/Collab/Collab.cs @@ -364,11 +364,17 @@ public bool SetConflictsResolvedTheirs(string[] paths) public PublishInfo GetChangesToPublish() { - Change[] changes = GetChangesToPublishInternal(); + Change[] changes = GetSelectedChangesInternal(); + bool isFiltered = false; + if (Toolbar.isLastShowRequestPartial) + { + isFiltered = true; + } + return new PublishInfo() { changes = changes, - filter = false + filter = isFiltered }; } diff --git a/Editor/Mono/Commands/GOCreationCommands.cs b/Editor/Mono/Commands/GOCreationCommands.cs index bc37a4b193..17755458d3 100644 --- a/Editor/Mono/Commands/GOCreationCommands.cs +++ b/Editor/Mono/Commands/GOCreationCommands.cs @@ -52,7 +52,12 @@ static void CreateEmptyChild(MenuCommand menuCommand) { var parent = menuCommand.context as GameObject; if (parent == null) - parent = Selection.activeGameObject; + { + var activeGO = Selection.activeGameObject; + if (activeGO != null && !EditorUtility.IsPersistent(activeGO)) + parent = activeGO; + } + var go = ObjectFactory.CreateGameObject("GameObject"); Place(go, parent); } diff --git a/Editor/Mono/ContainerWindow.bindings.cs b/Editor/Mono/ContainerWindow.bindings.cs index 2c427c9ead..d070126ab3 100644 --- a/Editor/Mono/ContainerWindow.bindings.cs +++ b/Editor/Mono/ContainerWindow.bindings.cs @@ -12,7 +12,7 @@ internal enum ShowMode { // Show as a normal window with max, min & close buttons. NormalWindow = 0, - // Used for a popup menu and tooltip. On mac this means light shadow and no titlebar. + // Used for a popup menu. On mac this means light shadow and no titlebar. PopupMenu = 1, // Utility window - floats above the app. Disappears when app loses focus. Utility = 2, @@ -22,8 +22,8 @@ internal enum ShowMode MainWindow = 4, // Aux windows. The ones that close the moment you move the mouse out of them. AuxWindow = 5, - // Like PopupMenu, but allows keyboard focus (e.g. AddComponentWindow) - PopupMenuWithKeyboardFocus = 6 + // Like PopupMenu, but without keyboard focus + Tooltip = 6 } //[StaticAccessor("ContainerWindowBindings", StaticAccessorType.DoubleColon)] diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index dea9694434..248f7b566c 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -59,14 +59,24 @@ internal void __internalAwake() internal static bool IsPopup(ShowMode mode) { - return (ShowMode.PopupMenu == mode || ShowMode.PopupMenuWithKeyboardFocus == mode); + return (ShowMode.PopupMenu == mode); } internal bool isPopup { get { return IsPopup((ShowMode)m_ShowMode); } } internal void ShowPopup() { - m_ShowMode = (int)ShowMode.PopupMenu; + ShowPopupWithMode(ShowMode.PopupMenu); + } + + internal void ShowTooltip() + { + ShowPopupWithMode(ShowMode.Tooltip); + } + + internal void ShowPopupWithMode(ShowMode mode) + { + m_ShowMode = (int)mode; Internal_Show(m_PixelRect, m_ShowMode, m_MinSize, m_MaxSize); if (m_RootView) m_RootView.SetWindowRecurse(this); diff --git a/Editor/Mono/EditorApplication.cs b/Editor/Mono/EditorApplication.cs index ef237e355f..58680a1ff7 100644 --- a/Editor/Mono/EditorApplication.cs +++ b/Editor/Mono/EditorApplication.cs @@ -187,6 +187,9 @@ public static void DirtyHierarchyWindowSorting() // Global key up/down event that was not handled by anyone internal static CallbackFunction globalEventHandler; + // Returns true when the pressed keys are defined in the Trigger + internal static Func doPressedKeysTriggerAnyShortcut; + // Windows were reordered internal static CallbackFunction windowsReordered; @@ -313,6 +316,14 @@ static void Internal_CallWindowsReordered() windowsReordered(); } + [RequiredByNativeCode] + static bool DoPressedKeysTriggerAnyShortcutHandler() + { + if (doPressedKeysTriggerAnyShortcut != null) + return doPressedKeysTriggerAnyShortcut(); + return false; + } + [RequiredByNativeCode] static void Internal_CallGlobalEventHandler() { diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index 6b63726c98..0494d380d8 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -18,6 +18,7 @@ using UnityEditor.Build; using UnityEditor.StyleSheets; using UnityEngine.Internal; +using UnityEngine.Rendering; using DescriptionAttribute = System.ComponentModel.DescriptionAttribute; namespace UnityEditor @@ -1050,6 +1051,7 @@ internal static string DoTextField(RecycledTextEditor editor, int id, Rect posit // Note, OS X send characters for the following keys that we need to eat: // ASCII 25: "End Of Medium" on pressing shift tab // ASCII 27: "Escape" on pressing ESC + nonPrintableTab = true; } else if (editor.IsEditingControl(id)) { @@ -4337,6 +4339,14 @@ private static Color DoColorField(Rect position, int id, Color value, bool showE break; case EventType.ExecuteCommand: + + // Cancel EyeDropper if we change focus. + if (showEyedropper && Event.current.commandName == EventCommandNames.NewKeyboardFocus) + { + EyeDropper.End(); + s_ColorPickID = 0; + } + // when ColorPicker sends an event back to this control's GUIView, it someties retains keyboardControl if (GUIUtility.keyboardControl == id || ColorPicker.originalKeyboardControl == id) { @@ -5639,11 +5649,11 @@ internal static void ShowRepaints() // Draws the alpha channel of a texture within a rectangle. internal static void DrawTextureAlphaInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) { - DrawPreviewTextureInternal(position, image, alphaMaterial, scaleMode, imageAspect, mipLevel); + DrawPreviewTextureInternal(position, image, alphaMaterial, scaleMode, imageAspect, mipLevel, ColorWriteMask.All); } // Draws texture transparently using the alpha channel. - internal static void DrawTextureTransparentInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) + internal static void DrawTextureTransparentInternal(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask) { if (imageAspect == 0f && image == null) { @@ -5656,7 +5666,7 @@ internal static void DrawTextureTransparentInternal(Rect position, Texture image DrawTransparencyCheckerTexture(position, scaleMode, imageAspect); if (image != null) - DrawPreviewTexture(position, image, transparentMaterial, scaleMode, imageAspect, mipLevel); + DrawPreviewTexture(position, image, transparentMaterial, scaleMode, imageAspect, mipLevel, colorWriteMask); } internal static void DrawTransparencyCheckerTexture(Rect position, ScaleMode scaleMode, float imageAspect) @@ -5678,15 +5688,27 @@ internal static void DrawTransparencyCheckerTexture(Rect position, ScaleMode sca } // Draws the texture within a rectangle. - internal static void DrawPreviewTextureInternal(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel) + internal static void DrawPreviewTextureInternal(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel, ColorWriteMask colorWriteMask) { if (Event.current.type == EventType.Repaint) { if (imageAspect == 0) imageAspect = image.width / (float)image.height; + Color colorMask = new Color(1, 1, 1, 1); + + if ((colorWriteMask & ColorWriteMask.Red) == 0) + colorMask.r = 0; + if ((colorWriteMask & ColorWriteMask.Green) == 0) + colorMask.g = 0; + if ((colorWriteMask & ColorWriteMask.Blue) == 0) + colorMask.b = 0; + if ((colorWriteMask & ColorWriteMask.Alpha) == 0) + colorMask.a = 0; + if (mat == null) mat = GetMaterialForSpecialTexture(image, colorMaterial); + mat.SetColor("_ColorMask", colorMask); mat.SetFloat("_Mip", mipLevel); RenderTexture rt = image as RenderTexture; @@ -6343,9 +6365,9 @@ public static void DrawTextureAlpha(Rect position, Texture image, ScaleMode scal } // Draws texture transparently using the alpha channel. - public static void DrawTextureTransparent(Rect position, Texture image, [DefaultValue("ScaleMode.StretchToFill")] ScaleMode scaleMode, [DefaultValue("0")] float imageAspect, [DefaultValue("-1")] float mipLevel) + public static void DrawTextureTransparent(Rect position, Texture image, [DefaultValue("ScaleMode.StretchToFill")] ScaleMode scaleMode, [DefaultValue("0")] float imageAspect, [DefaultValue("-1")] float mipLevel, [DefaultValue("ColorWriteMask.All")] ColorWriteMask colorWriteMask) { - DrawTextureTransparentInternal(position, image, scaleMode, imageAspect, mipLevel); + DrawTextureTransparentInternal(position, image, scaleMode, imageAspect, mipLevel, colorWriteMask); } [ExcludeFromDocs] @@ -6360,16 +6382,35 @@ public static void DrawTextureTransparent(Rect position, Texture image) DrawTextureTransparent(position, image, ScaleMode.StretchToFill, 0); } + [ExcludeFromDocs] public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode, float imageAspect) { - DrawTextureTransparentInternal(position, image, scaleMode, imageAspect, -1); + DrawTextureTransparent(position, image, scaleMode, imageAspect, -1); + } + + [ExcludeFromDocs] + public static void DrawTextureTransparent(Rect position, Texture image, ScaleMode scaleMode, float imageAspect, float mipLevel) + { + DrawTextureTransparent(position, image, scaleMode, imageAspect, mipLevel, ColorWriteMask.All); } // Draws the texture within a rectangle. public static void DrawPreviewTexture(Rect position, Texture image, [DefaultValue("null")] Material mat, [DefaultValue("ScaleMode.StretchToFill")] ScaleMode scaleMode, - [DefaultValue("0")] float imageAspect, [DefaultValue("-1")] float mipLevel) + [DefaultValue("0")] float imageAspect, [DefaultValue("-1")] float mipLevel, [DefaultValue("ColorWriteMask.All")] ColorWriteMask colorWriteMask) { - DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, mipLevel); + DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, mipLevel, colorWriteMask); + } + + [ExcludeFromDocs] + public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect, float mipLevel) + { + DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, mipLevel, ColorWriteMask.All); + } + + [ExcludeFromDocs] + public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect) + { + DrawPreviewTexture(position, image, mat, scaleMode, imageAspect, -1); } [ExcludeFromDocs] @@ -6390,12 +6431,6 @@ public static void DrawPreviewTexture(Rect position, Texture image) DrawPreviewTexture(position, image, null, ScaleMode.StretchToFill, 0); } - [ExcludeFromDocs] - public static void DrawPreviewTexture(Rect position, Texture image, Material mat, ScaleMode scaleMode, float imageAspect) - { - DrawPreviewTextureInternal(position, image, mat, scaleMode, imageAspect, -1); - } - [ExcludeFromDocs] public static void LabelField(Rect position, string label) { diff --git a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs b/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs index f10253d950..7f9efafb9a 100644 --- a/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs +++ b/Editor/Mono/EditorHandles/BoundsHandle/PrimitiveBoundsHandle.cs @@ -122,8 +122,8 @@ public void DrawHandle() // handles int prevHotControl = GUIUtility.hotControl; - Vector3 cameraLocalPos = Handles.inverseMatrix.MultiplyPoint(Camera.current.transform.position); - bool isCameraInsideBox = m_Bounds.Contains(cameraLocalPos); + bool isCameraInsideBox = Camera.current != null + && m_Bounds.Contains(Handles.inverseMatrix.MultiplyPoint(Camera.current.transform.position)); EditorGUI.BeginChangeCheck(); using (new Handles.DrawingScope(Handles.color * handleColor)) MidpointHandles(ref minPos, ref maxPos, isCameraInsideBox); diff --git a/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs b/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs index 10c838a157..9bbe0c21c8 100644 --- a/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs +++ b/Editor/Mono/EditorHandles/JointAngularLimitHandle.cs @@ -26,10 +26,12 @@ private static float GetSortingDistance(ArcHandle handle) Vector3 worldPosition = Handles.matrix.MultiplyPoint3x4( Quaternion.AngleAxis(handle.angle, Vector3.up) * Vector3.forward * handle.radius ); - Vector3 toHandle = worldPosition - Camera.current.transform.position; - if (Camera.current.orthographic) + Vector3 toHandle = Camera.current == null + ? worldPosition + : worldPosition - Camera.current.transform.position; + if (Camera.current == null || Camera.current.orthographic) { - Vector3 lookVector = Camera.current.transform.forward; + Vector3 lookVector = Camera.current == null ? Vector3.forward : Camera.current.transform.forward; toHandle = lookVector * Vector3.Dot(lookVector, toHandle); } return toHandle.sqrMagnitude; diff --git a/Editor/Mono/EditorUserBuildSettings.bindings.cs b/Editor/Mono/EditorUserBuildSettings.bindings.cs index 04b6e3a25a..f7bddf49a9 100644 --- a/Editor/Mono/EditorUserBuildSettings.bindings.cs +++ b/Editor/Mono/EditorUserBuildSettings.bindings.cs @@ -626,6 +626,15 @@ public static extern bool switchNVNShaderDebugging set; } + // Enable debug validation of NVN drawcalls + public static extern bool switchNVNDrawValidation + { + [NativeMethod("GetNVNDrawValidation")] + get; + [NativeMethod("SetNVNDrawValidation")] + set; + } + // Enable linkage of the Heap inspector tool for Nintendo Switch. public static extern bool switchEnableHeapInspector { diff --git a/Editor/Mono/EditorUtility.cs b/Editor/Mono/EditorUtility.cs index b197a5a8c8..5ebdd84813 100644 --- a/Editor/Mono/EditorUtility.cs +++ b/Editor/Mono/EditorUtility.cs @@ -198,25 +198,25 @@ public static Object InstantiatePrefab(Object target) return PrefabUtility.InstantiatePrefab(target); } - [Obsolete("Use PrefabUtility.ReplacePrefab", false)] + [Obsolete("Use PrefabUtility.SaveAsPrefabAsset with a path instead.", false)] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, ReplacePrefabOptions options) { return PrefabUtility.ReplacePrefab(go, targetPrefab, options); } - [Obsolete("Use PrefabUtility.ReplacePrefab", false)] + [Obsolete("Use PrefabUtility.SaveAsPrefabAsset or PrefabUtility.SaveAsPrefabAssetAndConnect with a path instead.", false)] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab) { return PrefabUtility.ReplacePrefab(go, targetPrefab, ReplacePrefabOptions.Default); } - [Obsolete("Use PrefabUtility.CreateEmptyPrefab", false)] + [Obsolete("The concept of creating a completely empty Prefab has been discontinued. You can however use PrefabUtility.SaveAsPrefabAsset with an empty GameObject.", false)] public static Object CreateEmptyPrefab(string path) { return PrefabUtility.CreateEmptyPrefab(path); } - [Obsolete("Use PrefabUtility.RevertPrefabInstance", false)] + [Obsolete("Use PrefabUtility.RevertPrefabInstance.", false)] public static bool ReconnectToLastPrefab(GameObject go) { return PrefabUtility.ReconnectToLastPrefab(go); @@ -240,7 +240,7 @@ public static GameObject FindPrefabRoot(GameObject source) return PrefabUtility.FindPrefabRoot(source); } - [Obsolete("Use PrefabUtility.ResetToPrefabState", false)] + [Obsolete("Use PrefabUtility.RevertObjectOverride.", false)] public static bool ResetToPrefabState(Object source) { return PrefabUtility.ResetToPrefabState(source); diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index 1b17962e0f..00590ec4be 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -478,8 +478,18 @@ public void ShowUtility() ShowWithMode(ShowMode.Utility); } - // Used for popup style windows. + internal void ShowTooltip() + { + ShowPopupWithMode(ShowMode.Tooltip); + } + public void ShowPopup() + { + ShowPopupWithMode(ShowMode.PopupMenu); + } + + // Used for popup style windows. + internal void ShowPopupWithMode(ShowMode mode) { if (m_Parent == null) { @@ -494,7 +504,7 @@ public void ShowPopup() cw.position = r; cw.rootView = host; MakeParentsSettingsMatchMe(); - cw.ShowPopup(); + cw.ShowPopupWithMode(mode); } } @@ -531,7 +541,7 @@ public void ShowAsDropDown(Rect buttonRect, Vector2 windowSize) internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder) { - ShowAsDropDown(buttonRect, windowSize, locationPriorityOrder, ShowMode.PopupMenuWithKeyboardFocus); + ShowAsDropDown(buttonRect, windowSize, locationPriorityOrder, ShowMode.PopupMenu); } internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[] locationPriorityOrder, ShowMode mode) @@ -550,9 +560,9 @@ internal void ShowAsDropDown(Rect buttonRect, Vector2 windowSize, PopupLocation[ position = ShowAsDropDownFitToScreen(buttonRect, windowSize, locationPriorityOrder); // ShowWithMode() always grabs window focus so we use ShowPopup() for popup windows so PopupWindowWithoutFocus - // will work correctly (no focus when opened) - if (ContainerWindow.IsPopup(mode) && mode != ShowMode.PopupMenuWithKeyboardFocus) - ShowPopup(); + // will work correctly (no focus when opened). + if (ContainerWindow.IsPopup(mode)) + ShowPopupWithMode(mode); else ShowWithMode(mode); diff --git a/Editor/Mono/GI/LightmapEditorSettings.bindings.cs b/Editor/Mono/GI/LightmapEditorSettings.bindings.cs index 4f841a6632..2a28803785 100644 --- a/Editor/Mono/GI/LightmapEditorSettings.bindings.cs +++ b/Editor/Mono/GI/LightmapEditorSettings.bindings.cs @@ -29,8 +29,11 @@ public enum Lightmapper [Obsolete("Use Lightmapper.ProgressiveCPU instead. (UnityUpgradable) -> UnityEditor.LightmapEditorSettings/Lightmapper.ProgressiveCPU", true)] PathTracer = 1, - // Lightmaps are baked by the Progressive lightmapper (Wintermute + OpenRL based). - ProgressiveCPU = 1 + // Lightmaps are baked by the CPU Progressive lightmapper (Wintermute + OpenRL based). + ProgressiveCPU = 1, + + // Lightmaps are baked by the GPU Progressive lightmapper (RadeonRays + OpenCL based). + ProgressiveGPU = 2 } // Which path tracer sampling scheme is used. diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index 453514fc52..d2ef8314f7 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -570,7 +570,7 @@ void DoColorSwatchAndEyedropper() if (GUILayout.Button(Styles.eyeDropper, GUIStyle.none, GUILayout.Width(40), GUILayout.ExpandWidth(false))) { GUIUtility.keyboardControl = 0; - EyeDropper.Start(m_Parent, false); + EyeDropper.Start(m_Parent); m_ColorBoxMode = ColorBoxMode.EyeDropper; GUIUtility.ExitGUI(); } @@ -958,6 +958,15 @@ void OnGUI() } } + // Cancel EyeDropper if we change focus. + if (m_ColorBoxMode == ColorBoxMode.EyeDropper && + Event.current.type == EventType.ExecuteCommand && + Event.current.commandName == EventCommandNames.NewKeyboardFocus) + { + EyeDropper.End(); + OnEyedropperCancelled(); + } + // Remove keyfocus when clicked outside any control if ((Event.current.type == EventType.MouseDown && Event.current.button != 1) || Event.current.type == EventType.ContextClick) { @@ -1229,17 +1238,17 @@ internal class EyeDropper : GUIView private bool m_Focused = false; private Action m_ColorPickedCallback; - public static void Start(GUIView viewToUpdate, bool stealFocus = true) + public static void Start(GUIView viewToUpdate) { - Start(viewToUpdate, null, stealFocus); + Start(viewToUpdate, null); } - public static void Start(Action colorPickedCallback, bool stealFocus = true) + public static void Start(Action colorPickedCallback) { - Start(null, colorPickedCallback, stealFocus); + Start(null, colorPickedCallback); } - static void Start(GUIView viewToUpdate, Action colorPickedCallback, bool stealFocus) + static void Start(GUIView viewToUpdate, Action colorPickedCallback) { instance.m_DelegateView = viewToUpdate; instance.m_ColorPickedCallback = colorPickedCallback; @@ -1255,8 +1264,6 @@ static void Start(GUIView viewToUpdate, Action colorPickedCallback, bool win.position = new Rect(-kDummyWindowSize / 2, -kDummyWindowSize / 2, kDummyWindowSize, kDummyWindowSize); instance.wantsMouseMove = true; instance.StealMouseCapture(); - if (stealFocus) - instance.Focus(); } public static void End() diff --git a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs index b060fcdea7..8cdfc53eb2 100644 --- a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs +++ b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenu.cs @@ -243,7 +243,7 @@ void CreateNewItemButton(Rect itemRect) SelectItem(newIndex); EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI) }); - PopupWindow.Show(plusRect, m_ModifyItemUI, null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(plusRect, m_ModifyItemUI); } } @@ -261,7 +261,7 @@ void EditExistingItem(Rect itemRect, int index) m_ItemProvider.Replace(index, obj); EditorApplication.RequestRepaintAllViews(); // We want to repaint the flexible menu (currently in modifyItemUI) }); - PopupWindow.Show(itemRect, m_ModifyItemUI, null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(itemRect, m_ModifyItemUI); } void DeleteItem(int index) diff --git a/Editor/Mono/GUI/Toolbar.cs b/Editor/Mono/GUI/Toolbar.cs index 22e979d006..12cebecd4d 100644 --- a/Editor/Mono/GUI/Toolbar.cs +++ b/Editor/Mono/GUI/Toolbar.cs @@ -137,6 +137,7 @@ protected override void OnDisable() public static Toolbar get = null; public static bool requestShowCollabToolbar = false; + public static bool isLastShowRequestPartial = true; internal static string lastLoadedLayoutName { diff --git a/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs index 26f2ba9e37..1182c65d9d 100644 --- a/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs +++ b/Editor/Mono/GUI/TreeView/GameObjectTreeViewDataSource.cs @@ -208,10 +208,6 @@ void CreateRootItem(HierarchyProperty property) // All game objects m_RootItem = new GameObjectTreeViewItem(m_RootInstanceID, rootDepth, null, "RootOfAll"); } - - // Ensure root is expanded if not shown - if (!showRootItem) - SetExpanded(m_RootItem, true); } void ClearSearchFilter() diff --git a/Editor/Mono/GUI/WindowLayout.cs b/Editor/Mono/GUI/WindowLayout.cs index 7ce55f3e21..047ce599c4 100644 --- a/Editor/Mono/GUI/WindowLayout.cs +++ b/Editor/Mono/GUI/WindowLayout.cs @@ -356,10 +356,13 @@ internal static void MaximizeKeyHandler(ShortcutArguments args) var mouseOverWindow = EditorWindow.mouseOverWindow; - if (IsMaximized(mouseOverWindow)) - Unmaximize(mouseOverWindow); - else - Maximize(mouseOverWindow); + if (mouseOverWindow != null) + { + if (IsMaximized(mouseOverWindow)) + Unmaximize(mouseOverWindow); + else + Maximize(mouseOverWindow); + } } public static void AddSplitViewAndChildrenRecurse(View splitview, ArrayList list) diff --git a/Editor/Mono/GameView/GameViewSizes.cs b/Editor/Mono/GameView/GameViewSizes.cs index 6a326192d2..72b896eda3 100644 --- a/Editor/Mono/GameView/GameViewSizes.cs +++ b/Editor/Mono/GameView/GameViewSizes.cs @@ -239,9 +239,10 @@ private void InitBuiltinGroups() k_4_3_Landscape, k_4_3_Portrait, k_iPhone4_Portrait, k_iPhone4_Landscape, k_iPhone5_Portrait, k_iPhone5_Landscape, - k_iPad_768p_Landscape, k_iPad_768p_Portrait); + k_iPad_768p_Landscape, k_iPad_768p_Portrait, + m_Remote); - m_Android.AddBuiltinSizes(kFree, m_Remote, + m_Android.AddBuiltinSizes(kFree, k_800x480_Portrait, k_800x480_Landscape, k_720p_Portrait, k_720p_Landscape, k_1080p_Portrait, k_1080p_Landscape, @@ -249,7 +250,8 @@ private void InitBuiltinGroups() k_2560x1440_Portrait, k_2560x1440_Landscape, k_2960x1440_Portrait, k_2960x1440_Landscape, k_16_9_Portrait, k_16_9_Landscape, - k_18_9_Portrait, k_18_9_Landscape); + k_18_9_Portrait, k_18_9_Landscape, + m_Remote); m_HMD.AddBuiltinSizes(kFree, m_Remote); } diff --git a/Editor/Mono/HandleUtility.cs b/Editor/Mono/HandleUtility.cs index 8fc8f52881..2e87d2449c 100644 --- a/Editor/Mono/HandleUtility.cs +++ b/Editor/Mono/HandleUtility.cs @@ -26,7 +26,7 @@ public static float CalcLineTranslation(Vector2 src, Vector2 dest, Vector3 srcPo // The constrained direction is facing towards the camera, THATS BAD when the handle is close to the camera // The srcPosition goes through to the other side of the camera float invert = 1.0F; - Vector3 cameraForward = Camera.current.transform.forward; + Vector3 cameraForward = Camera.current == null ? Vector3.forward : Camera.current.transform.forward; if (Vector3.Dot(constraintDir, cameraForward) < 0.0F) invert = -1.0F; @@ -36,8 +36,13 @@ public static float CalcLineTranslation(Vector2 src, Vector2 dest, Vector3 srcPo Vector3 cd = constraintDir; cd.y = -cd.y; Camera cam = Camera.current; - Vector2 p1 = EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition)); - Vector2 p2 = EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition + constraintDir * invert)); + // if camera is null, then we are drawing in OnGUI, where y-coordinate goes top-to-bottom + Vector2 p1 = cam == null + ? Vector2.Scale(srcPosition, new Vector2(1f, -1f)) + : EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition)); + Vector2 p2 = cam == null + ? Vector2.Scale(srcPosition + constraintDir * invert, new Vector2(1f, -1f)) + : EditorGUIUtility.PixelsToPoints(cam.WorldToScreenPoint(srcPosition + constraintDir * invert)); Vector2 p3 = dest; Vector2 p4 = src; diff --git a/Editor/Mono/Handles.cs b/Editor/Mono/Handles.cs index 4dd97995b5..db89421be6 100644 --- a/Editor/Mono/Handles.cs +++ b/Editor/Mono/Handles.cs @@ -550,8 +550,8 @@ public static void DotHandleCap(int controlID, Vector3 position, Quaternion rota // Only apply matrix to the position because DotCap is camera facing position = matrix.MultiplyPoint(position); - Vector3 sideways = Camera.current.transform.right * size; - Vector3 up = Camera.current.transform.up * size; + Vector3 sideways = (Camera.current == null ? Vector3.right : Camera.current.transform.right) * size; + Vector3 up = (Camera.current == null ? Vector3.up : Camera.current.transform.up) * size; Color col = color * new Color(1, 1, 1, 0.99f); HandleUtility.ApplyWireMaterial(Handles.zTest); diff --git a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs index 50ceac4111..9cf9bfb61a 100644 --- a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs +++ b/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs @@ -251,15 +251,27 @@ private void HandleBodyView(int bodyView) Vector2 m_FoldoutScroll = Vector2.zero; - public override void OnInspectorGUI() + private void SetupInternalProperties() + { + m_HumanBoneArray = serializedObject.FindProperty("m_HumanDescription.m_Human"); + m_Skeleton = serializedObject.FindProperty("m_HumanDescription.m_Skeleton"); + } + + private void HandleUndoPerformed() { if (Event.current.type == EventType.ValidateCommand && Event.current.commandName == EventCommandNames.UndoRedoPerformed) { + SetupInternalProperties(); + AvatarSetupTool.TransferPoseToDescription(m_Skeleton, root); for (int i = 0; i < m_Bones.Length; i++) m_Bones[i].Serialize(m_HumanBoneArray); } + } + public override void OnInspectorGUI() + { + HandleUndoPerformed(); UpdateSelectedBone(); // case 837655. GUI.keyboardControl is overriden when changing scene selection. diff --git a/Editor/Mono/Inspector/CameraEditor.cs b/Editor/Mono/Inspector/CameraEditor.cs index 1cd244ae15..81e164090d 100644 --- a/Editor/Mono/Inspector/CameraEditor.cs +++ b/Editor/Mono/Inspector/CameraEditor.cs @@ -213,7 +213,7 @@ public void DrawProjection() GUIContent content = EditorGUI.BeginProperty(EditorGUILayout.BeginHorizontal(), Styles.fieldOfView, fieldOfView); EditorGUI.BeginDisabled(projectionMatrixMode.hasMultipleDifferentValues || isPhysicalCamera && (focalLength.hasMultipleDifferentValues || sensorSize.hasMultipleDifferentValues)); EditorGUI.BeginChangeCheck(); - float fovNewValue = EditorGUILayout.Slider(content, fieldOfView.floatValue, 1f, 179f); + float fovNewValue = EditorGUILayout.Slider(content, fieldOfView.floatValue, 0.00001f, 179f); bool fovChanged = EditorGUI.EndChangeCheck(); EditorGUI.EndDisabled(); EditorGUILayout.EndHorizontal(); diff --git a/Editor/Mono/Inspector/LabelGUI.cs b/Editor/Mono/Inspector/LabelGUI.cs index c7b69c305f..7ef70781c2 100644 --- a/Editor/Mono/Inspector/LabelGUI.cs +++ b/Editor/Mono/Inspector/LabelGUI.cs @@ -189,7 +189,7 @@ public void OnLabelGUI(Object[] assets) r.x = widthProbeRect.xMax + labelButton.margin.left; if (EditorGUI.DropdownButton(r, GUIContent.none, FocusType.Passive, labelButton)) { - PopupWindow.Show(r, new PopupList(m_AssetLabels), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(r, new PopupList(m_AssetLabels)); } EditorGUILayout.EndHorizontal(); @@ -209,7 +209,7 @@ private void DrawLabelList(bool partiallySelected, float xMax) { evt.Use(); rt.x = xMax; - PopupWindow.Show(rt, new PopupList(m_AssetLabels, content.text), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(rt, new PopupList(m_AssetLabels, content.text)); } } } diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index afe116b735..0f5d45dffb 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -56,7 +56,6 @@ static class Styles public static readonly GUIContent CastShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "Specifies whether a geometry creates shadows or not when a shadow-casting Light shines on it."); public static readonly GUIContent ReceiveShadows = EditorGUIUtility.TrTextContent("Receive Shadows", "When enabled, any shadows cast from other objects are drawn on the geometry."); public static readonly GUIContent MotionVectors = EditorGUIUtility.TrTextContent("Motion Vectors", "Specifies whether the Mesh renders 'Per Object Motion', 'Camera Motion', or 'No Motion' vectors to the Camera Motion Vector Texture."); - public static readonly GUIContent LightmapInfoBox = EditorGUIUtility.TrTextContent("To enable generation of lightmaps for this Mesh Renderer, please enable the 'Lightmap Static' property."); public static readonly GUIContent TerrainLightmapInfoBox = EditorGUIUtility.TrTextContent("To enable generation of lightmaps for this Mesh Renderer, please enable the 'Lightmap Static' property."); public static readonly GUIContent ResolutionTooHighWarning = EditorGUIUtility.TrTextContent("Precompute/indirect resolution for this terrain is probably too high. Use a lower realtime/indirect resolution setting in the Lighting window or assign LightmapParameters that use a lower resolution setting. Otherwise it may take a very long time to bake and memory consumption during and after the bake may be very high."); @@ -157,13 +156,20 @@ public void RenderMeshSettings(bool showLightmapSettings) m_GameObjectsSerializedObject.Update(); m_LightmapSettings.Update(); - EditorGUILayout.PropertyField(m_CastShadows, Styles.CastShadows, true); + // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. + if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.PropertyField(m_CastShadows, Styles.CastShadows, true); + bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); if (SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) { using (new EditorGUI.DisabledScope(isDeferredRenderingPath)) - EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); + { + // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. + if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); + } } if (SupportedRenderingFeatures.active.rendererSupportsMotionVectors) diff --git a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs index 77dcd09308..f585af937f 100644 --- a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs +++ b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs @@ -163,6 +163,7 @@ public bool DoubleSidedGIField() } else { + // TODO(RadeonRays): change this to (lightmapper == Enlighten) once Double Sided GI works with GPU lightmapper. using (new EditorGUI.DisabledScope(LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveCPU)) EditorGUI.Toggle(r, Styles.doubleSidedGILabel, false); } diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 2c022b45dc..7d97663c9a 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -168,6 +168,7 @@ class SettingsContent public static readonly GUIContent managedStrippingLevel = EditorGUIUtility.TrTextContent("Managed Stripping Level", "If scripting backend is IL2CPP, managed stripping can't be disabled."); public static readonly GUIContent il2cppCompilerConfiguration = EditorGUIUtility.TrTextContent("C++ Compiler Configuration"); public static readonly GUIContent scriptingMono2x = EditorGUIUtility.TrTextContent("Mono"); + public static readonly GUIContent scriptingMono2xDeprecated = EditorGUIUtility.TrTextContent("Mono (Deprecated)"); public static readonly GUIContent scriptingWinRTDotNET = EditorGUIUtility.TrTextContent(".NET"); public static readonly GUIContent scriptingIL2CPP = EditorGUIUtility.TrTextContent("IL2CPP"); public static readonly GUIContent scriptingDefault = EditorGUIUtility.TrTextContent("Default"); @@ -1697,10 +1698,10 @@ private void OtherSectionRenderingGUI(BuildPlatform platform, BuildTargetGroup t EditorGUI.BeginChangeCheck(); LightmapEncodingQuality encodingQuality = PlayerSettings.GetLightmapEncodingQualityForPlatformGroup(targetGroup); LightmapEncodingQuality[] lightmapEncodingValues = {LightmapEncodingQuality.Normal, LightmapEncodingQuality.High}; - encodingQuality = BuildEnumPopup(SettingsContent.lightmapEncodingLabel, encodingQuality, lightmapEncodingValues, SettingsContent.lightmapEncodingNames); - if (EditorGUI.EndChangeCheck()) + LightmapEncodingQuality newEncodingQuality = BuildEnumPopup(SettingsContent.lightmapEncodingLabel, encodingQuality, lightmapEncodingValues, SettingsContent.lightmapEncodingNames); + if (EditorGUI.EndChangeCheck() && encodingQuality != newEncodingQuality) { - PlayerSettings.SetLightmapEncodingQualityForPlatformGroup(targetGroup, encodingQuality); + PlayerSettings.SetLightmapEncodingQualityForPlatformGroup(targetGroup, newEncodingQuality); Lightmapping.OnUpdateLightmapEncoding(targetGroup); @@ -1961,6 +1962,7 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting ScriptingImplementation currBackend = PlayerSettings.GetScriptingBackend(targetGroup); currentBackendIsIl2Cpp = currBackend == ScriptingImplementation.IL2CPP; ScriptingImplementation newBackend; + var mono2xDeprecated = targetGroup == BuildTargetGroup.iOS; if (targetGroup == BuildTargetGroup.tvOS) { @@ -1970,11 +1972,11 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting else if (backends.Length == 1) { newBackend = backends[0]; - BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0]), SettingsContent.scriptingBackend); + BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0], mono2xDeprecated), SettingsContent.scriptingBackend); } else { - newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends)); + newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends, mono2xDeprecated)); } if (targetGroup == BuildTargetGroup.iOS && newBackend == ScriptingImplementation.Mono2x) @@ -2313,7 +2315,6 @@ private void OtherSectionLegacyGUI() EditorGUILayout.Space(); } - private static Dictionary m_NiceScriptingBackendNames; private static Dictionary m_NiceApiCompatibilityLevelNames; private static Dictionary m_NiceManagedStrippingLevelNames; @@ -2331,31 +2332,26 @@ private static GUIContent[] GetGUIContentsForValues(Dictionary return names; } - private static GUIContent[] GetNiceScriptingBackendNames(ScriptingImplementation[] scriptingBackends) + static GUIContent[] GetNiceScriptingBackendNames(ScriptingImplementation[] scriptingBackends, bool mono2xDeprecated) { - InitializeNiceScriptingBackendNames(); - return GetGUIContentsForValues(m_NiceScriptingBackendNames, scriptingBackends); + return scriptingBackends.Select(s => GetNiceScriptingBackendName(s, mono2xDeprecated)).ToArray(); } - static void InitializeNiceScriptingBackendNames() + static GUIContent GetNiceScriptingBackendName(ScriptingImplementation scriptingBackend, bool mono2xDeprecated) { - if (m_NiceScriptingBackendNames == null) + switch (scriptingBackend) { - m_NiceScriptingBackendNames = new Dictionary - { - { ScriptingImplementation.Mono2x, SettingsContent.scriptingMono2x }, - { ScriptingImplementation.WinRTDotNET, SettingsContent.scriptingWinRTDotNET }, - { ScriptingImplementation.IL2CPP, SettingsContent.scriptingIL2CPP } - }; + case ScriptingImplementation.Mono2x: + return mono2xDeprecated ? SettingsContent.scriptingMono2xDeprecated : SettingsContent.scriptingMono2x; + case ScriptingImplementation.IL2CPP: + return SettingsContent.scriptingIL2CPP; + case ScriptingImplementation.WinRTDotNET: + return SettingsContent.scriptingWinRTDotNET; + default: + throw new ArgumentException($"Scripting backend value {scriptingBackend} is not supported.", nameof(scriptingBackend)); } } - private static GUIContent GetNiceScriptingBackendName(ScriptingImplementation scriptingBackend) - { - InitializeNiceScriptingBackendNames(); - return GetGUIContentsForValues(m_NiceScriptingBackendNames, new[] { scriptingBackend }).First(); - } - private static GUIContent[] GetNiceApiCompatibilityLevelNames(ApiCompatibilityLevel[] apiCompatibilityLevels) { if (m_NiceApiCompatibilityLevelNames == null) diff --git a/Editor/Mono/Inspector/RectTransformEditor.cs b/Editor/Mono/Inspector/RectTransformEditor.cs index 3ee6543a67..a98c23be5b 100644 --- a/Editor/Mono/Inspector/RectTransformEditor.cs +++ b/Editor/Mono/Inspector/RectTransformEditor.cs @@ -298,7 +298,7 @@ void LayoutDropdownButton(bool anyWithoutParent) { GUIUtility.keyboardControl = 0; m_DropdownWindow = new LayoutDropdownWindow(serializedObject); - PopupWindow.Show(dropdownPosition, m_DropdownWindow, null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(dropdownPosition, m_DropdownWindow); } GUI.color = oldColor; } diff --git a/Editor/Mono/Inspector/TagManagerInspector.cs b/Editor/Mono/Inspector/TagManagerInspector.cs index 4d6d4b4f38..b4548b6da4 100644 --- a/Editor/Mono/Inspector/TagManagerInspector.cs +++ b/Editor/Mono/Inspector/TagManagerInspector.cs @@ -175,7 +175,7 @@ void NewElement(Rect buttonRect, ReorderableList list) { buttonRect.x -= 400; buttonRect.y -= 13; - PopupWindow.Show(buttonRect, new EnterNamePopup(m_Tags, s => { InternalEditorUtility.AddTag(s); }), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(buttonRect, new EnterNamePopup(m_Tags, s => { InternalEditorUtility.AddTag(s); })); } private void RemoveFromTagsList(ReorderableList list) diff --git a/Editor/Mono/Inspector/TextureInspector.cs b/Editor/Mono/Inspector/TextureInspector.cs index 86ba109b6e..ab99053c9b 100644 --- a/Editor/Mono/Inspector/TextureInspector.cs +++ b/Editor/Mono/Inspector/TextureInspector.cs @@ -2,8 +2,10 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System.Collections.Generic; using UnityEngine; using UnityEditor; +using UnityEngine.Rendering; namespace UnityEditor @@ -48,8 +50,9 @@ internal class TextureInspector : Editor { class Styles { - public GUIContent smallZoom, largeZoom, alphaIcon, RGBIcon; + public GUIContent smallZoom, largeZoom; public GUIStyle previewButton, previewSlider, previewSliderThumb, previewLabel; + public GUIStyle previewButtonRed, previewButtonGreen, previewButtonBlue; public readonly GUIContent wrapModeLabel = EditorGUIUtility.TrTextContent("Wrap Mode"); public readonly GUIContent wrapU = EditorGUIUtility.TrTextContent("U axis"); @@ -77,9 +80,11 @@ public Styles() { smallZoom = EditorGUIUtility.IconContent("PreTextureMipMapLow"); largeZoom = EditorGUIUtility.IconContent("PreTextureMipMapHigh"); - alphaIcon = EditorGUIUtility.IconContent("PreTextureAlpha"); - RGBIcon = EditorGUIUtility.IconContent("PreTextureRGB"); + previewButton = "preButton"; + previewButtonRed = "preButtonRed"; + previewButtonGreen = "preButtonGreen"; + previewButtonBlue = "preButtonBlue"; previewSlider = "preSlider"; previewSliderThumb = "preSliderThumb"; previewLabel = "preLabelUpper"; @@ -87,8 +92,20 @@ public Styles() } static Styles s_Styles; - private bool m_ShowAlpha; - public bool showAlpha { get { return m_ShowAlpha; } } + enum PreviewMode + { + RGB, + R, + G, + B, + A, + }; + + private PreviewMode m_PreviewMode = PreviewMode.RGB; + public bool showAlpha + { + get { return m_PreviewMode == PreviewMode.A; } + } // Plain Texture protected SerializedProperty m_WrapU; @@ -410,7 +427,6 @@ public override void OnPreviewSettings() // and while it's being shown the actual texture object might disappear -- // make sure to handle null targets. Texture tex = target as Texture; - bool showMode = true; bool alphaOnly = false; bool hasAlpha = true; int mipCount = 1; @@ -448,19 +464,53 @@ public override void OnPreviewSettings() mipCount = Mathf.Max(mipCount, TextureUtil.GetMipmapCount(t)); } + + List previewCandidates = new List(5); + previewCandidates.Add(PreviewMode.RGB); + previewCandidates.Add(PreviewMode.R); + previewCandidates.Add(PreviewMode.G); + previewCandidates.Add(PreviewMode.B); + previewCandidates.Add(PreviewMode.A); + if (alphaOnly) { - m_ShowAlpha = true; - showMode = false; + previewCandidates.Clear(); + previewCandidates.Add(PreviewMode.A); + m_PreviewMode = PreviewMode.A; } else if (!hasAlpha) { - m_ShowAlpha = false; - showMode = false; + previewCandidates.Remove(PreviewMode.A); } - if (showMode && tex != null && !IsNormalMap(tex)) - m_ShowAlpha = GUILayout.Toggle(m_ShowAlpha, m_ShowAlpha ? s_Styles.alphaIcon : s_Styles.RGBIcon, s_Styles.previewButton); + + if (previewCandidates.Count > 1 && tex != null && !IsNormalMap(tex)) + { + int selectedIndex = previewCandidates.IndexOf(m_PreviewMode); + if (selectedIndex == -1) + selectedIndex = 0; + + if (previewCandidates.Contains(PreviewMode.RGB)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.RGB, "RGB", s_Styles.previewButton) + ? PreviewMode.RGB + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.R)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.R, "R", s_Styles.previewButtonRed) + ? PreviewMode.R + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.G)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.G, "G", s_Styles.previewButtonGreen) + ? PreviewMode.G + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.B)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.B, "B", s_Styles.previewButtonBlue) + ? PreviewMode.B + : m_PreviewMode; + if (previewCandidates.Contains(PreviewMode.A)) + m_PreviewMode = GUILayout.Toggle(m_PreviewMode == PreviewMode.A, "A", s_Styles.previewButton) + ? PreviewMode.A + : m_PreviewMode; + } if (mipCount > 1) { @@ -512,14 +562,33 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) PreviewGUI.BeginScrollView(r, m_Pos, wantedRect, "PreHorizontalScrollbar", "PreHorizontalScrollbarThumb"); FilterMode oldFilter = t.filterMode; TextureUtil.SetFilterModeNoDirty(t, FilterMode.Point); - Texture2D t2d = t as Texture2D; - if (m_ShowAlpha) + ColorWriteMask colorWriteMask = ColorWriteMask.All; + + switch (m_PreviewMode) + { + case PreviewMode.R: + colorWriteMask = ColorWriteMask.Red | ColorWriteMask.Alpha; + break; + case PreviewMode.G: + colorWriteMask = ColorWriteMask.Green | ColorWriteMask.Alpha; + break; + case PreviewMode.B: + colorWriteMask = ColorWriteMask.Blue | ColorWriteMask.Alpha; + break; + } + + if (m_PreviewMode == PreviewMode.A) + { EditorGUI.DrawTextureAlpha(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel); - else if (t2d != null && t2d.alphaIsTransparency) - EditorGUI.DrawTextureTransparent(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel); + } else - EditorGUI.DrawPreviewTexture(wantedRect, t, null, ScaleMode.StretchToFill, 0, mipLevel); + { + if (t2d != null && t2d.alphaIsTransparency) + EditorGUI.DrawTextureTransparent(wantedRect, t, ScaleMode.StretchToFill, 0, mipLevel, colorWriteMask); + else + EditorGUI.DrawPreviewTexture(wantedRect, t, null, ScaleMode.StretchToFill, 0, mipLevel, colorWriteMask); + } // TODO: Less hacky way to prevent sprite rects to not appear in smaller previews like icons. if (wantedRect.width > 32 && wantedRect.height > 32) diff --git a/Editor/Mono/LookDevView/LookDevView.cs b/Editor/Mono/LookDevView/LookDevView.cs index ceadf35366..4709caf02b 100644 --- a/Editor/Mono/LookDevView/LookDevView.cs +++ b/Editor/Mono/LookDevView/LookDevView.cs @@ -1676,7 +1676,7 @@ private void HandleDragging() } GameObject go = o as GameObject; - if (go && EditorUtility.IsPersistent(go) && PrefabUtility.GetPrefabObject(go) != null) + if (go && EditorUtility.IsPersistent(go) && PrefabUtility.IsPartOfPrefabAsset(go)) { if (GameObjectInspector.HasRenderableParts(go)) { diff --git a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs index 7953e088d2..499f70164c 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs @@ -30,6 +30,7 @@ public sealed partial class PrefabUtility extern private static Object GetCorrespondingObjectFromSourceAtPath_internal([NotNull] Object obj, string prefabAssetPath); // Retrieves the prefab object representation. + [Obsolete("Use GetPrefabInstanceHandle for Prefab instances. Handles for Prefab Assets has been discontinued.")] [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] extern public static Object GetPrefabObject(Object targetObject); @@ -72,6 +73,7 @@ public sealed partial class PrefabUtility extern public static void MergeAllPrefabInstances(Object targetObject); // Disconnects the prefab instance from its parent prefab. + [Obsolete("The concept of disconnecting Prefab instances has been deprecated.")] [FreeFunction] extern public static void DisconnectPrefabInstance(Object targetObject); @@ -88,6 +90,7 @@ public sealed partial class PrefabUtility extern public static void LoadPrefabContentsIntoPreviewScene(string prefabPath, Scene scene); // Connect the source prefab to the game object, which replaces the instance content with the content of the prefab + [Obsolete("Use RevertPrefabInstance. Prefabs instances can no longer be connected to Prefab Assets they are not an instance of to begin with.")] [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] [NativeThrows] extern public static GameObject ConnectGameObjectToPrefab([NotNull] GameObject go, [NotNull] GameObject sourcePrefab); @@ -105,26 +108,35 @@ public sealed partial class PrefabUtility // Connects the game object to the prefab that it was last connected to. [FreeFunction] + [Obsolete("Use RevertPrefabInstance.")] extern public static bool ReconnectToLastPrefab(GameObject go); // Resets the properties of the component or game object to the parent prefab state + [Obsolete("Use RevertObjectOverride.")] [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] extern public static bool ResetToPrefabState(Object obj); + // Resets the properties of the component or game object to the parent prefab state + [NativeMethod("PrefabUtilityBindings::ResetToPrefabState", IsFreeFunction = true)] + extern private static bool RevertObjectOverride_Internal(Object obj); + [FreeFunction] extern public static bool IsAddedComponentOverride([NotNull] Object component); // Resets the properties of all objects in the prefab, including child game objects and components that were added to the prefab instance + [Obsolete("Use the overload that takes an InteractionMode parameter.")] [FreeFunction] extern public static bool RevertPrefabInstance([NotNull] GameObject go); + // Resets the properties of all objects in the prefab, including child game objects and components that were added to the prefab instance + [NativeMethod("RevertPrefabInstance", IsFreeFunction = true)] + extern private static bool RevertPrefabInstance_Internal([NotNull] GameObject go); + // Helper function to find the prefab root of an object [FreeFunction] [Obsolete("Use GetOutermostPrefabInstanceRoot if source is a Prefab instance or source.transform.root.gameObject if source is a Prefab Asset object.")] extern public static GameObject FindPrefabRoot([NotNull] GameObject source); -#pragma warning disable 0618 // Type or member is obsolete - internal static GameObject CreateVariant(GameObject assetRoot, string path) { if (assetRoot == null) @@ -146,11 +158,16 @@ internal static GameObject CreateVariant(GameObject assetRoot, string path) if (!Paths.IsValidAssetPath(path, ".prefab")) throw new ArgumentException("Given path is not valid: '" + path + "'"); +#pragma warning disable 0618 // Type or member is obsolete return CreateVariant_Internal(assetRoot, path, ReplacePrefabOptions.Default); +#pragma warning restore 0618 // Type or member is obsolete } + // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. [NativeMethod("CreateVariant", IsFreeFunction = true)] +#pragma warning disable 0618 // Type or member is obsolete extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path, ReplacePrefabOptions replaceOptions); +#pragma warning restore 0618 // Type or member is obsolete private enum PrefabCreationFlags { @@ -158,6 +175,8 @@ private enum PrefabCreationFlags CreateVariant = 1, } + // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. +#pragma warning disable 0618 // Type or member is obsolete private static GameObject SavePrefab(GameObject inputObject, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags creationFlags) { if (inputObject == null) @@ -175,13 +194,17 @@ private static GameObject SavePrefab(GameObject inputObject, string path, Replac throw new ArgumentException("Given path does not exist: '" + path + "'"); string prefabGUID = AssetDatabase.AssetPathToGUID(path); - if (!VerifyNestingFromScript(new GameObject[] {inputObject}, prefabGUID, PrefabUtility.GetPrefabObject(inputObject))) + if (!VerifyNestingFromScript(new GameObject[] {inputObject}, prefabGUID, PrefabUtility.GetPrefabInstanceHandle(inputObject))) throw new ArgumentException("Cyclic nesting detected"); return SavePrefab_Internal(inputObject, path, replaceOptions, creationFlags); } +#pragma warning restore 0618 // Type or member is obsolete + + // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. [NativeMethod("SavePrefab", IsFreeFunction = true)] +#pragma warning disable 0618 // Type or member is obsolete extern private static GameObject SavePrefab_Internal([NotNull] GameObject root, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags createOptions); #pragma warning restore 0618 // Type or member is obsolete @@ -201,7 +224,7 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, Object targetPrefabInstance = null; - var targetPrefabObject = PrefabUtility.GetPrefabObject(targetPrefab); + var targetPrefabObject = PrefabUtility.GetPrefabAssetHandle(targetPrefab); foreach (GameObject go in gameObjects) { @@ -232,7 +255,7 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, if (PrefabUtility.IsPartOfNonAssetPrefabInstance(go)) { var correspondingGO = PrefabUtility.GetCorrespondingObjectFromSource(go); - var correspondingGOPrefabObject = PrefabUtility.GetPrefabObject(correspondingGO); + var correspondingGOPrefabObject = PrefabUtility.GetPrefabAssetHandle(correspondingGO); if (targetPrefabObject == correspondingGOPrefabObject) throw new ArgumentException("GameObject is already part of target prefab"); } @@ -299,6 +322,11 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, [FreeFunction] extern public static bool IsPartOfVariantPrefab([NotNull] Object componentOrGameObject); + // Returns true if the object is from a Prefab Asset which is not editable, or an instance of such a Prefab + // Examples are Model Prefabs and Prefabs in read-only folders. + [FreeFunction] + extern public static bool IsPartOfImmutablePrefab([NotNull] Object componentOrGameObject); + [FreeFunction] extern public static bool IsDisconnectedFromPrefabAsset([NotNull] Object componentOrGameObject); diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 8279a9f737..869694c941 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -296,10 +296,7 @@ public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode CheckInstanceIsNotPersistent(instanceRoot); - // The concept of disconnecting are being deprecated. For now use FindRootGameObjectWithSameParentPrefab - // to re-connect existing disconnected prefabs. - #pragma warning disable 0618 // Type or member is obsolete - GameObject prefabInstanceRoot = FindRootGameObjectWithSameParentPrefab(instanceRoot); + GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); var actionName = "Revert Prefab Instance"; HashSet hierarchy = null; @@ -313,13 +310,13 @@ public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode if (isDisconnected) { - ReconnectToLastPrefab(prefabInstanceRoot); + RevertPrefabInstance_Internal(prefabInstanceRoot); if (action == InteractionMode.UserAction) Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(prefabInstanceRoot), actionName); } - RevertPrefabInstance(prefabInstanceRoot); + RevertPrefabInstance_Internal(prefabInstanceRoot); if (action == InteractionMode.UserAction) { @@ -333,10 +330,7 @@ public static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode CheckInstanceIsNotPersistent(instanceRoot); - // The concept of disconnecting are being deprecated. For now use FindRootGameObjectWithSameParentPrefab - // to re-connect existing disconnected prefabs. - #pragma warning disable 0618 // Type or member is obsolete - GameObject prefabInstanceRoot = FindRootGameObjectWithSameParentPrefab(instanceRoot); + GameObject prefabInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); var actionName = "Apply instance to prefab"; Object correspondingSourceObject = GetCorrespondingObjectFromSource(prefabInstanceRoot); @@ -525,7 +519,7 @@ public static void RevertObjectOverride(Object instanceComponentOrGameObject, In if (action == InteractionMode.UserAction) Undo.RegisterCompleteObjectUndo(instanceComponentOrGameObject, "Revert component property overrides"); - PrefabUtility.ResetToPrefabState(instanceComponentOrGameObject); + PrefabUtility.RevertObjectOverride_Internal(instanceComponentOrGameObject); } public static void ApplyAddedComponent(Component component, string assetPath, InteractionMode action) @@ -598,7 +592,7 @@ private static bool IsPrefabInstanceObjectOf(Object instance, Object source) return true; } - if (GetPrefabObject(o) == source) + if (GetPrefabAssetHandle(o) == source) { return true; } @@ -641,7 +635,7 @@ public static void ApplyRemovedComponent(GameObject instanceGameObject, Componen SavePrefabAsset(prefabAsset); } - var prefabInstanceObject = PrefabUtility.GetPrefabObject(instanceGameObject); + var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(instanceGameObject); if (action == InteractionMode.UserAction) Undo.RegisterCompleteObjectUndo(prefabInstanceObject, actionName); @@ -682,7 +676,7 @@ public static void RevertRemovedComponent(GameObject instanceGameObject, Compone CheckInstanceIsNotPersistent(instanceGameObject); var actionName = "Revert Prefab removed component"; - var prefabInstanceObject = PrefabUtility.GetPrefabObject(instanceGameObject); + var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(instanceGameObject); if (action == InteractionMode.UserAction) Undo.RegisterCompleteObjectUndo(instanceGameObject, actionName); @@ -928,7 +922,7 @@ public static Object GetPrefabParent(Object obj) } // Creates an empty prefab at given path. - // TODO Steen Lund 2017 11 28 This needs to be marked OBSOLETE + [Obsolete("The concept of creating a completely empty Prefab has been discontinued. You can however use SaveAsPrefabAsset with an empty GameObject.")] public static Object CreateEmptyPrefab(string path) { // This is here to simulate previous behaviour @@ -944,8 +938,6 @@ public static Object CreateEmptyPrefab(string path) return PrefabUtility.GetPrefabObject(assetObject); } -#pragma warning disable CS0618 // Type or member is obsolete - public static GameObject SavePrefabAsset(GameObject asset) { if (asset == null) @@ -966,7 +958,9 @@ public static GameObject SavePrefabAsset(GameObject asset) if (root != asset) throw new ArgumentException("GameObject to save Prefab from must be a Prefab root"); +#pragma warning disable CS0618 // Type or member is obsolete return SavePrefab(root, path, ReplacePrefabOptions.Default, PrefabCreationFlags.None); +#pragma warning restore CS0618 // Type or member is obsolete } private static void SaveAsPrefabAssetArgumentCheck(GameObject root) @@ -1002,7 +996,9 @@ public static GameObject SaveAsPrefabAsset(GameObject root, string assetPath) if (IsPrefabInstanceRoot(root)) creationFlags = PrefabCreationFlags.CreateVariant; +#pragma warning disable CS0618 // Type or member is obsolete return SavePrefab(root, assetPath, ReplacePrefabOptions.Default, creationFlags); +#pragma warning restore CS0618 // Type or member is obsolete } public static GameObject SaveAsPrefabAssetAndConnect(GameObject root, string assetPath, InteractionMode action) @@ -1020,7 +1016,9 @@ public static GameObject SaveAsPrefabAssetAndConnect(GameObject root, string ass if (IsPrefabInstanceRoot(root)) creationFlags = PrefabCreationFlags.CreateVariant; +#pragma warning disable CS0618 // Type or member is obsolete var assetRoot = SavePrefab(root, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags); +#pragma warning restore CS0618 // Type or member is obsolete if (action == InteractionMode.UserAction) { @@ -1049,7 +1047,7 @@ internal static void ApplyPrefabInstance(GameObject instance) { // The concept of disconnecting are being deprecated. For now use FindRootGameObjectWithSameParentPrefab // to re-connect existing disconnected prefabs. - var validRoot = PrefabUtility.FindValidUploadPrefabInstanceRoot(instance); + var validRoot = PrefabUtility.GetOutermostPrefabInstanceRoot(instance); var ok = validRoot == instance; if (!ok && PrefabUtility.GetCorrespondingObjectFromOriginalSource(instance) != PrefabUtility.GetCorrespondingObjectFromSource(instance)) throw new ArgumentException("Can't save Prefab from an object that originates from a nested Prefab"); @@ -1063,11 +1061,17 @@ internal static void ApplyPrefabInstance(GameObject instance) var assetObject = GetCorrespondingObjectFromSource(instance); string path = AssetDatabase.GetAssetPath(assetObject); + +#pragma warning disable CS0618 // Type or member is obsolete SavePrefab(instance, path, ReplacePrefabOptions.ConnectToPrefab, PrefabCreationFlags.None); +#pragma warning restore CS0618 // Type or member is obsolete } + // TOOO: Remove entirely once regular methods handle merging + // based on both ids and names on a smarter and more granular level. internal static GameObject ReplacePrefabAssetNameBased(GameObject root, string targetPrefab, bool connectToInstance) { +#pragma warning disable CS0618 // Type or member is obsolete var options = ReplacePrefabOptions.ReplaceNameBased; if (connectToInstance) options |= ReplacePrefabOptions.ConnectToPrefab; @@ -1076,8 +1080,7 @@ internal static GameObject ReplacePrefabAssetNameBased(GameObject root, string t if (IsPartOfNonAssetPrefabInstance(root)) { - var instanceRoot = PrefabUtility.GetPrefabInstanceRootGameObject(root); - if (root != instanceRoot) + if (!IsOutermostPrefabInstanceRoot(root)) throw new ArgumentException("Can't replace with part of Prefab instance. Please specify instance root object or a non-instance object."); createOptions = PrefabCreationFlags.CreateVariant; @@ -1087,18 +1090,17 @@ internal static GameObject ReplacePrefabAssetNameBased(GameObject root, string t throw new ArgumentException("Argument connectToInstance is true but root object is an asset not an instance"); return SavePrefab(root, targetPrefab, options, createOptions); - } - #pragma warning restore CS0618 // Type or member is obsolete + } - //[Obsolete("CreatePrefab() has been deprecated. Use SavePrefab() instead (UnityUpgradable) -> SavePrefab(go, path, ReplacePrefabOptions.Default)")] + // Can't use UnityUpgradable since it doesn't currently support swapping parameter order. + [Obsolete("Use SaveAsPrefabAsset instead.")] public static GameObject CreatePrefab(string path, GameObject go) { return SaveAsPrefabAsset(go, path); } - //[Obsolete("CreatePrefab() has been deprecated. Use SavePrefab() instead (UnityUpgradable) -> SavePrefab(go, path, options)")] -#pragma warning disable CS0618 // Type or member is obsolete + [Obsolete("Use SaveAsPrefabAsset or SaveAsPrefabAssetAndConnect instead.")] public static GameObject CreatePrefab(string path, GameObject go, ReplacePrefabOptions options) { if (options == ReplacePrefabOptions.ConnectToPrefab) @@ -1119,11 +1121,13 @@ public static Object InstantiatePrefab(Object assetComponentOrGameObject, Scene return InstantiatePrefab_internal(assetComponentOrGameObject, destinationScene); } + [Obsolete("Use SaveAsPrefabAsset with a path instead.")] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab) { return ReplacePrefab(go, targetPrefab, ReplacePrefabOptions.Default); } + [Obsolete("Use SaveAsPrefabAsset or SaveAsPrefabAssetAndConnect with a path instead.")] public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, ReplacePrefabOptions replaceOptions) { var targetPrefabObject = PrefabUtility.GetPrefabObject(targetPrefab); @@ -1163,8 +1167,6 @@ public static GameObject ReplacePrefab(GameObject go, Object targetPrefab, Repla return SavePrefab(go, assetPath, replaceOptions, PrefabCreationFlags.None); } -#pragma warning restore CS0618 // Type or member is obsolete - // Returns the corresponding object from its immediate source, or null if it can't be found. public static TObject GetCorrespondingObjectFromSource(TObject componentOrGameObject) where TObject : Object { @@ -1211,7 +1213,6 @@ private static Object GetCorrespondingObjectFromOriginalSource_Internal(Object i } // Given an object, returns its prefab type (None, if it's not a prefab) -#pragma warning disable CS0618 // Type or member is obsolete [Obsolete("Use GetPrefabAssetType and GetPrefabInstanceStatus to get the full picture about Prefab types.")] public static PrefabType GetPrefabType(Object target) { @@ -1251,8 +1252,6 @@ public static PrefabType GetPrefabType(Object target) return PrefabType.PrefabInstance; } -#pragma warning restore CS0618 // Type or member is obsolete - // Called after prefab instances in the scene have been updated public delegate void PrefabInstanceUpdated(GameObject instance); public static PrefabInstanceUpdated prefabInstanceUpdated; @@ -1328,7 +1327,7 @@ public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpack if (!IsPartOfNonAssetPrefabInstance(root)) throw new ArgumentException("UnpackPrefabInstance must be called with a Prefab instance."); - if (GetPrefabInstanceRootGameObject(root) != root) + if (!IsOutermostPrefabInstanceRoot(root)) throw new ArgumentException("UnpackPrefabInstance must be called with a root Prefab instance GameObject."); if (action == InteractionMode.UserAction) @@ -1351,24 +1350,6 @@ public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpack } } - public static bool IsPartOfImmutablePrefab(Object gameObjectOrComponent) - { - if (IsPartOfModelPrefab(gameObjectOrComponent)) - return true; - - // If prefab instance, get the prefab asset. - if (!EditorUtility.IsPersistent(gameObjectOrComponent)) - gameObjectOrComponent = GetCorrespondingObjectFromSource(gameObjectOrComponent); - - string prefabAssetPath = AssetDatabase.GetAssetPath(gameObjectOrComponent); - bool isRootFolder, isReadonly; - bool validPath = AssetDatabase.GetAssetFolderInfo(prefabAssetPath, out isRootFolder, out isReadonly); - if (validPath && isReadonly) - return true; - - return false; - } - internal static bool HasInvalidComponent(Object gameObjectOrComponent) { if (gameObjectOrComponent == null) diff --git a/Editor/Mono/ProjectBrowser.cs b/Editor/Mono/ProjectBrowser.cs index 513ebb2d6e..fd04e054d5 100644 --- a/Editor/Mono/ProjectBrowser.cs +++ b/Editor/Mono/ProjectBrowser.cs @@ -2266,7 +2266,7 @@ void AssetLabelsDropDown() Rect r = GUILayoutUtility.GetRect(s_Styles.m_FilterByLabel, EditorStyles.toolbarButton); if (EditorGUI.DropdownButton(r, s_Styles.m_FilterByLabel, FocusType.Passive, EditorStyles.toolbarButton)) { - PopupWindow.Show(r, new PopupList(m_AssetLabels), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(r, new PopupList(m_AssetLabels)); } } diff --git a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs index f1543afe72..9277fffd56 100644 --- a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs +++ b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs @@ -107,15 +107,6 @@ public override void Action(int instanceId, string pathName, string resourceFile } } - internal class DoCreatePrefab : EndNameEditAction - { - public override void Action(int instanceId, string pathName, string resourceFile) - { - Object o = PrefabUtility.CreateEmptyPrefab(pathName); - ProjectWindowUtil.ShowCreatedAsset(o); - } - } - internal class DoCreatePrefabVariant : EndNameEditAction { public override void Action(int instanceId, string pathName, string resourceFile) @@ -257,12 +248,6 @@ public static void CreateScene() StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Scene.unity", EditorGUIUtility.FindTexture(typeof(SceneAsset)), null); } - // Create a prefab - public static void CreatePrefab() - { - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Prefab.prefab", EditorGUIUtility.IconContent("Prefab Icon").image as Texture2D, null); - } - [MenuItem("Assets/Create/Prefab Variant", true)] static bool CreatePrefabVariantValidation() { diff --git a/Editor/Mono/SceneHierarchy.cs b/Editor/Mono/SceneHierarchy.cs index dec6f48fed..1f5e4ed5a8 100644 --- a/Editor/Mono/SceneHierarchy.cs +++ b/Editor/Mono/SceneHierarchy.cs @@ -485,8 +485,6 @@ public virtual void OnEnable() EditorSceneManager.newSceneCreated += OnSceneCreated; EditorSceneManager.sceneOpened += OnSceneOpened; - DoPingRequest(); - m_AllowAlphaNumericalSort = EditorPrefs.GetBool("AllowAlphaNumericHierarchy", false) || !InternalEditorUtility.isHumanControllingUs; // Always allow alphasorting when running automated tests so we can test alpha sorting SetUpSortMethodLists(); @@ -495,6 +493,8 @@ public virtual void OnEnable() if (m_TreeViewKeyboardControlID == 0) m_TreeViewKeyboardControlID = EditorGUIUtility.GetPermanentControlID(); + + DoPingRequest(); } public virtual void OnDisable() diff --git a/Editor/Mono/SceneHierarchyStageHandling.cs b/Editor/Mono/SceneHierarchyStageHandling.cs index a633173992..b0dffebe74 100644 --- a/Editor/Mono/SceneHierarchyStageHandling.cs +++ b/Editor/Mono/SceneHierarchyStageHandling.cs @@ -105,8 +105,30 @@ void HandleFirstTimePrefabStageIsOpened(StageNavigationItem stage) { if (stage.isPrefabStage && GetStoredHierarchyState(m_SceneHierarchyWindow, stage) == null) { - var visibleRootID = stage.prefabStage.prefabContentsRoot.GetInstanceID(); - m_SceneHierarchy.SetExpandedRecursive(visibleRootID, true); + SetDefaultExpandedStateForOpenedPrefab(stage.prefabStage.prefabContentsRoot); + } + } + + void SetDefaultExpandedStateForOpenedPrefab(GameObject root) + { + var expandedIDs = new List(); + AddParentsBelowButIgnoreNestedPrefabsRecursive(root.transform, expandedIDs); + expandedIDs.Sort(); + m_SceneHierarchy.treeViewState.expandedIDs = expandedIDs; + } + + void AddParentsBelowButIgnoreNestedPrefabsRecursive(Transform transform, List gameObjectInstanceIDs) + { + gameObjectInstanceIDs.Add(transform.gameObject.GetInstanceID()); + + int count = transform.childCount; + for (int i = 0; i < count; ++i) + { + var child = transform.GetChild(i); + if (child.childCount > 0 && !PrefabUtility.IsAnyPrefabInstanceRoot(child.gameObject)) + { + AddParentsBelowButIgnoreNestedPrefabsRecursive(child, gameObjectInstanceIDs); + } } } diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index 3bee757397..6de9a6e44c 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -61,7 +61,7 @@ public GameObject prefabContentsRoot get { if (m_PrefabContentsRoot == null) - throw new InvalidOperationException("Requesting 'prefabContentsRoot' from Awake and OnEnable are not supported"); // The preview scene is not fully loaded when we call Awake and OnEnable on user scripts + throw new InvalidOperationException("Requesting 'prefabContentsRoot' from Awake and OnEnable are not supported"); // The prefab stage's m_PrefabContentsRoot is not yet set when we call Awake and OnEnable on user scripts when loading a prefab return m_PrefabContentsRoot; } } @@ -261,7 +261,7 @@ bool isTextFieldCaretShowing bool readyToAutoSave { - get { return m_PrefabContentsRoot != null && HasSceneBeenModified() && GUIUtility.hotControl == 0 && !isTextFieldCaretShowing; } + get { return m_PrefabContentsRoot != null && HasSceneBeenModified() && GUIUtility.hotControl == 0 && !isTextFieldCaretShowing && !EditorApplication.isCompiling; } } void HandleAutoSave() @@ -313,11 +313,15 @@ internal void SavePrefab() if (prefabSaving != null) prefabSaving(m_PrefabContentsRoot); - ClearDirtiness(); - PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath); + var prefabAssetRoot = PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath); - if (prefabSaved != null) - prefabSaved(m_PrefabContentsRoot); + if (prefabAssetRoot != null) + { + ClearDirtiness(); + + if (prefabSaved != null) + prefabSaved(m_PrefabContentsRoot); + } if (SceneHierarchy.s_DebugPrefabStage) Debug.Log("SAVE PREFAB ended"); @@ -393,32 +397,26 @@ internal bool SaveAsNewPrefabWithSavePanel() // Returns true if prefab was saved. internal bool SavePrefabWithVersionControlDialogAndRenameDialog() { - Assert.IsTrue(m_PrefabContentsRoot != null, "We should have a valid m_PrefabContentsRoot when saving to prefab asset"); - bool editablePrefab = !AnimationMode.InAnimationMode(); - - //bool editablePrefab = UnityEditor.VersionControl.Provider.PromptAndCheckoutIfNeeded( - // new string[] {context.assetPath}, - // "The version control requires you to check out the prefab before applying changes."); - - if (editablePrefab) + if (m_PrefabContentsRoot == null) { - if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(m_PrefabAssetPath, PrefabUtility.SaveVerb.Save)) - { - // If user doesn't want to check out prefab asset, or it cannot be, - // it doesn't make sense to keep auto save on. - m_TemporarilyDisableAutoSave = true; - return false; - } - - bool showCancelButton = !autoSave; - if (!CheckRenamedPrefabRootWhenSaving(showCancelButton)) - return false; + Debug.LogError("We should have a valid m_PrefabContentsRoot when saving to prefab asset"); + return false; + } - SavePrefab(); - return true; + if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(m_PrefabAssetPath, PrefabUtility.SaveVerb.Save)) + { + // If user doesn't want to check out prefab asset, or it cannot be, + // it doesn't make sense to keep auto save on. + m_TemporarilyDisableAutoSave = true; + return false; } - return false; + bool showCancelButton = !autoSave; + if (!CheckRenamedPrefabRootWhenSaving(showCancelButton)) + return false; + + SavePrefab(); + return true; } // Returns true if we should continue saving diff --git a/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs b/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs index b3f4b6ffa8..c546825ccd 100644 --- a/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs +++ b/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs @@ -14,7 +14,7 @@ private static class Styles public static readonly GUIContent[] ProjectionStrings = { EditorGUIUtility.TrTextContent("Infinite"), EditorGUIUtility.TrTextContent("Box") }; public static readonly GUIContent[] LightmapEmissiveStrings = { EditorGUIUtility.TrTextContent("Realtime"), EditorGUIUtility.TrTextContent("Baked") }; public static readonly GUIContent Name = EditorGUIUtility.TrTextContent("Name"); - public static readonly GUIContent On = EditorGUIUtility.TrTextContent("On"); + public static readonly GUIContent Enabled = EditorGUIUtility.TrTextContent("Enabled"); public static readonly GUIContent Type = EditorGUIUtility.TrTextContent("Type"); public static readonly GUIContent Shape = EditorGUIUtility.TrTextContent("Shape"); public static readonly GUIContent Mode = EditorGUIUtility.TrTextContent("Mode"); @@ -69,8 +69,8 @@ protected virtual LightingExplorerTableColumn[] GetLightColumns() { return new[] { - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 0: Name - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.On, "m_Enabled", 25), // 1: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, "m_Enabled", 50), // 0: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Enum, Styles.Type, "m_Type", 120, (r, prop, dep) => { // To the user, we will only display it as a area light, but under the hood, we have Rectangle and Disc. This is not to confuse people @@ -168,8 +168,8 @@ protected virtual LightingExplorerTableColumn[] GetReflectionProbeColumns() { return new[] { - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 0: Name - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.On, "m_Enabled", 25), // 1: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, "m_Enabled", 50), // 0: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Int, Styles.Mode, "m_Mode", 70, (r, prop, dep) => { EditorGUI.IntPopup(r, prop, ReflectionProbeEditor.Styles.reflectionProbeMode, ReflectionProbeEditor.Styles.reflectionProbeModeValues, GUIContent.none); @@ -195,8 +195,8 @@ protected virtual LightingExplorerTableColumn[] GetLightProbeColumns() { return new[] { - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 0: Name - new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.On, "m_Enabled", 25), // 1: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Checkbox, Styles.Enabled, "m_Enabled", 50), // 0: Enabled + new LightingExplorerTableColumn(LightingExplorerTableColumn.DataType.Name, Styles.Name, null, 200), // 1: Name }; } diff --git a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs index 79ac29a750..64c5a47251 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs @@ -71,7 +71,6 @@ internal class LightingWindowBakeSettings SerializedProperty m_PVRFilteringAtrousPositionSigmaAO; SerializedProperty m_BounceScale; - SerializedProperty m_UpdateThreshold; static bool PlayerHasSM20Support() { @@ -131,7 +130,6 @@ private void InitSettings() //dev debug properties m_BounceScale = so.FindProperty("m_GISettings.m_BounceScale"); - m_UpdateThreshold = so.FindProperty("m_GISettings.m_TemporalCoherenceThreshold"); } public void OnEnable() @@ -351,7 +349,6 @@ public void DeveloperBuildSettingsGUI() Lightmapping.filterMode = (FilterMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TempContent("Filter Mode"), Lightmapping.filterMode); EditorGUILayout.Slider(m_BounceScale, 0.0f, 10.0f, Styles.BounceScale); - EditorGUILayout.Slider(m_UpdateThreshold, 0.0f, 1.0f, Styles.UpdateThreshold); if (GUILayout.Button("Clear disk cache", GUILayout.Width(LightingWindow.kButtonWidth))) { @@ -371,6 +368,16 @@ public void DeveloperBuildSettingsGUI() DynamicGI.UpdateEnvironment(); } + private void ClampFilterType(SerializedProperty filter) + { + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + { + // Force unsupported A-Trous filter back to Gaussian. + if (filter.intValue == 1) + filter.intValue = 0; + } + } + void GeneralLightmapSettingsGUI() { bool bakedGISupported = SupportedRenderingFeatures.IsLightmapBakeTypeSupported(LightmapBakeType.Baked); @@ -453,7 +460,16 @@ void GeneralLightmapSettingsGUI() { EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.PVRFilterTypeDirect); + // TODO(RadeonRays): Hiding A-trous until it is implemented. + var filterOptions = new[] { EditorGUIUtility.TextContent("Gaussian"), EditorGUIUtility.TextContent("None") }; + var filterInts = new[] { 0, 2 }; + + ClampFilterType(m_PVRFilterTypeDirect); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.IntPopup(m_PVRFilterTypeDirect, filterOptions, filterInts, Styles.PVRFilterTypeDirect); + else + EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.PVRFilterTypeDirect); + DrawFilterSettingField(m_PVRFilteringGaussRadiusDirect, m_PVRFilteringAtrousPositionSigmaDirect, Styles.PVRFilteringGaussRadiusDirect, @@ -462,7 +478,11 @@ void GeneralLightmapSettingsGUI() EditorGUILayout.Space(); - EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.PVRFilterTypeIndirect); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.IntPopup(m_PVRFilterTypeIndirect, filterOptions, filterInts, Styles.PVRFilterTypeIndirect); + else + EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.PVRFilterTypeIndirect); + ClampFilterType(m_PVRFilterTypeIndirect); DrawFilterSettingField(m_PVRFilteringGaussRadiusIndirect, m_PVRFilteringAtrousPositionSigmaIndirect, Styles.PVRFilteringGaussRadiusIndirect, @@ -472,8 +492,11 @@ void GeneralLightmapSettingsGUI() using (new EditorGUI.DisabledScope(!m_AmbientOcclusion.boolValue)) { EditorGUILayout.Space(); - - EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.PVRFilterTypeAO); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.IntPopup(m_PVRFilterTypeAO, filterOptions, filterInts, Styles.PVRFilterTypeAO); + else + EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.PVRFilterTypeAO); + ClampFilterType(m_PVRFilterTypeAO); DrawFilterSettingField(m_PVRFilteringGaussRadiusAO, m_PVRFilteringAtrousPositionSigmaAO, Styles.PVRFilteringGaussRadiusAO, Styles.PVRFilteringAtrousPositionSigmaAO, diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index ab9c61444e..7adc6e7d02 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -741,7 +741,7 @@ void ToolbarDisplayStateGUI() if (EditorGUI.DropdownButton(modeRect, modeContent, FocusType.Passive, EditorStyles.toolbarDropDown)) { Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new SceneRenderModeWindow(this), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(rect, new SceneRenderModeWindow(this)); GUIUtility.ExitGUI(); } @@ -768,7 +768,7 @@ void ToolbarDisplayStateGUI() if (EditorGUI.DropdownButton(fxRightRect, GUIContent.none, FocusType.Passive, GUIStyle.none)) { Rect rect = GUILayoutUtility.topLevel.GetLast(); - PopupWindow.Show(rect, new SceneFXWindow(this), null, ShowMode.PopupMenuWithKeyboardFocus); + PopupWindow.Show(rect, new SceneFXWindow(this)); GUIUtility.ExitGUI(); } diff --git a/Editor/Mono/Scripting/Compilers/UWPReferences.cs b/Editor/Mono/Scripting/Compilers/UWPReferences.cs index f057f616bf..da1105c3a5 100644 --- a/Editor/Mono/Scripting/Compilers/UWPReferences.cs +++ b/Editor/Mono/Scripting/Compilers/UWPReferences.cs @@ -174,15 +174,11 @@ public static IEnumerable(); @@ -495,14 +496,14 @@ Exception[] UpdateCustomTargetAssemblies() { try { - if (m_PackageAssemblies != null && !assembly.PackageAssembly.HasValue) + if (packageAssemblies != null && !assembly.PackageAssembly.HasValue) { var pathPrefix = assembly.PathPrefix.ToLowerInvariant(); - foreach (var packageAssembly in m_PackageAssemblies) + foreach (var packageAssembly in packageAssemblies) { - var lower = AssetPath.ReplaceSeparators(packageAssembly.DirectoryPath).ToLowerInvariant(); - if (pathPrefix.StartsWith(lower)) + var lower = AssetPath.ReplaceSeparators(packageAssembly.DirectoryPath + AssetPath.Separator).ToLowerInvariant(); + if (pathPrefix.StartsWith(lower, StringComparison.Ordinal)) { assembly.PackageAssembly = packageAssembly; break; @@ -521,11 +522,22 @@ Exception[] UpdateCustomTargetAssemblies() } catch (Exception e) { - SetCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); exceptions.Add(e); } } + return exceptions.ToArray(); + } + + Exception[] UpdateCustomTargetAssemblies() + { + var exceptions = UpdateCustomScriptAssemblies(customScriptAssemblies, m_PackageAssemblies); + + if (exceptions.Length > 0) + { + SetCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); + } + customTargetAssemblies = EditorBuildRules.CreateTargetAssemblies(customScriptAssemblies, precompiledAssemblies); ClearCompilationSetupErrorFlags(CompilationSetupErrorFlags.cyclicReferences); @@ -533,7 +545,7 @@ Exception[] UpdateCustomTargetAssemblies() // customTargetAssemblies being updated. UpdateDirtyTargetAssemblies(); - return exceptions.ToArray(); + return exceptions; } void UpdateDirtyTargetAssemblies() diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs index 54d00b3510..c2cc1d0136 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs @@ -17,6 +17,7 @@ enum EditorScriptCompilationOptions BuildingForIl2Cpp = 1 << 3, BuildingWithAsserts = 1 << 4, BuildingIncludingTestAssemblies = 1 << 5, - BuildingPredefinedAssembliesAllowUnsafeCode = (1 << 6) + BuildingPredefinedAssembliesAllowUnsafeCode = (1 << 6), + BuildingForHeadlessPlayer = 1 << 7 }; } diff --git a/Editor/Mono/TooltipView/TooltipView.cs b/Editor/Mono/TooltipView/TooltipView.cs index 4a9b6242c8..bc3f53b210 100644 --- a/Editor/Mono/TooltipView/TooltipView.cs +++ b/Editor/Mono/TooltipView/TooltipView.cs @@ -66,7 +66,7 @@ void Setup(string tooltip, Rect rect) position = new Rect(0, 0, m_optimalSize.x, m_optimalSize.y); - window.ShowPopup(); + window.ShowTooltip(); window.SetAlpha(1.0f); s_guiView.mouseRayInvisible = true; diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index 5392398c9f..ec051304c7 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -205,6 +205,12 @@ private bool ShouldSyncOnReimportedAsset(string asset) public void Sync() { + // Do not sync solution until all Unity extensions are registered and initialized. + // Otherwise Unity might emit errors when VSTU tries to generate the solution and + // get all managed extensions, which not yet initialized. + if (!InternalEditorUtility.IsUnityExtensionsInitialized()) + return; + SetupProjectSupportedExtensions(); bool externalCodeAlreadyGeneratedProjects = AssetPostprocessingInternal.OnPreGeneratingCSProjectFiles(); diff --git a/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs index e3ec3ddce3..129af826f3 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/AssetImporterTabbedEditor.cs @@ -88,6 +88,8 @@ public override void OnInspectorGUI() // the activeTab can get destroyed when opening particular sub-editors (such as the Avatar configuration editor on the Rig tab) if (activeTab != null) { + GUILayout.Space(EditorGUI.kSpacing); + activeTab.OnInspectorGUI(); } diff --git a/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs b/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs index 790fb52601..56e112b8af 100644 --- a/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs +++ b/Modules/GraphViewEditor/Manipulators/SelectionDragger.cs @@ -453,6 +453,8 @@ void MoveElement(GraphElement element, Rect originalPos) var graphView = target as GraphView; if (graphView != null && graphView.graphViewChanged != null) { + KeyValuePair firstPos = m_OriginalPos.First(); + m_GraphViewChange.moveDelta = firstPos.Key.GetPosition().position - firstPos.Value.pos.position; graphView.graphViewChanged(m_GraphViewChange); } } diff --git a/Modules/GraphViewEditor/Views/GraphView.cs b/Modules/GraphViewEditor/Views/GraphView.cs index e65244ab2c..a22ce0220b 100644 --- a/Modules/GraphViewEditor/Views/GraphView.cs +++ b/Modules/GraphViewEditor/Views/GraphView.cs @@ -44,6 +44,7 @@ public struct GraphViewChange // Operations Completed public List movedElements; + public Vector2 moveDelta; } public struct NodeCreationContext diff --git a/Modules/GridEditor/Managed/GridEditorUtility.cs b/Modules/GridEditor/Managed/GridEditorUtility.cs index 7516832bc6..59891615e0 100644 --- a/Modules/GridEditor/Managed/GridEditorUtility.cs +++ b/Modules/GridEditor/Managed/GridEditorUtility.cs @@ -216,10 +216,10 @@ public static void DrawGridMarquee(GridLayout gridLayout, BoundsInt area, Color Vector3[] cellLocals = { - gridLayout.CellToLocal(new Vector3Int(area.xMin, area.yMin, 0)), - gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMin, 0)), - gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMax - 1 + cellGap.y, 0)), - gridLayout.CellToLocalInterpolated(new Vector3(area.xMin, area.yMax - 1 + cellGap.y, 0)) + gridLayout.CellToLocal(new Vector3Int(area.xMin, area.yMin, area.zMin)), + gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMin, area.zMin)), + gridLayout.CellToLocalInterpolated(new Vector3(area.xMax - 1 + cellGap.x, area.yMax - 1 + cellGap.y, area.zMin)), + gridLayout.CellToLocalInterpolated(new Vector3(area.xMin, area.yMax - 1 + cellGap.y, area.zMin)) }; HandleUtility.ApplyWireMaterial(); @@ -252,34 +252,34 @@ public static void DrawSelectedHexGridArea(GridLayout gridLayout, BoundsInt area int right = horizontalCount; Vector3[] cellOffset = { - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, gridLayout.cellSize.y / 2, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, -gridLayout.cellSize.y / 2, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, 0)), - Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, 0)) + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, gridLayout.cellSize.y / 2, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(0, -gridLayout.cellSize.y / 2, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, -gridLayout.cellSize.y / 4, area.zMin)), + Grid.Swizzle(gridLayout.cellSwizzle, new Vector3(-gridLayout.cellSize.x / 2, gridLayout.cellSize.y / 4, area.zMin)) }; // Fill Top and Bottom Vertices for (int x = area.min.x; x < area.max.x; x++) { - cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, 0)) + cellOffset[4]; - cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, 0)) + cellOffset[3]; - cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, 0)) + cellOffset[0]; - cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, 0)) + cellOffset[1]; + cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, area.zMin)) + cellOffset[4]; + cellLocals[bottom++] = gridLayout.CellToLocal(new Vector3Int(x, area.min.y, area.zMin)) + cellOffset[3]; + cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, area.zMin)) + cellOffset[0]; + cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(x, area.max.y - 1, area.zMin)) + cellOffset[1]; } // Fill first Left and Right Vertices - cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, area.min.y, 0)) + cellOffset[5]; - cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, area.max.y - 1, 0)) + cellOffset[2]; + cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, area.min.y, area.zMin)) + cellOffset[5]; + cellLocals[top--] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, area.max.y - 1, area.zMin)) + cellOffset[2]; // Fill Left and Right Vertices for (int y = area.min.y + 1; y < area.max.y; y++) { - cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, 0)) + cellOffset[4]; - cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, 0)) + cellOffset[5]; + cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, area.zMin)) + cellOffset[4]; + cellLocals[left--] = gridLayout.CellToLocal(new Vector3Int(area.min.x, y, area.zMin)) + cellOffset[5]; } for (int y = area.min.y; y < (area.max.y - 1); y++) { - cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, 0)) + cellOffset[2]; - cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, 0)) + cellOffset[1]; + cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, area.zMin)) + cellOffset[2]; + cellLocals[right++] = gridLayout.CellToLocal(new Vector3Int(area.max.x - 1, y, area.zMin)) + cellOffset[1]; } HandleUtility.ApplyWireMaterial(); GL.PushMatrix(); diff --git a/Modules/IMGUI/GUILayout.cs b/Modules/IMGUI/GUILayout.cs index 193026aef4..f204f4e28a 100644 --- a/Modules/IMGUI/GUILayout.cs +++ b/Modules/IMGUI/GUILayout.cs @@ -242,6 +242,11 @@ static public void FlexibleSpace() op.value = 10000; GUILayoutUtility.GetRect(0, 0, GUILayoutUtility.spaceStyle, op); + + if (Event.current.type == EventType.Layout) + { + GUILayoutUtility.current.topLevel.entries[GUILayoutUtility.current.topLevel.entries.Count - 1].consideredForMargin = false; + } } public static void BeginHorizontal(params GUILayoutOption[] options) { BeginHorizontal(GUIContent.none, GUIStyle.none, options); } diff --git a/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs b/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs index 86ce9a075e..d5ea21ea9c 100644 --- a/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs +++ b/Modules/ImageConversion/ScriptBindings/ImageConversion.bindings.cs @@ -32,7 +32,7 @@ public static byte[] EncodeToEXR(this Texture2D tex) } [NativeMethod(Name = "ImageConversionBindings::LoadImage", IsFreeFunction = true)] - extern public static bool LoadImage(this Texture2D tex, byte[] data, bool markNonReadable); + extern public static bool LoadImage([NotNull] this Texture2D tex, byte[] data, bool markNonReadable); public static bool LoadImage(this Texture2D tex, byte[] data) { return LoadImage(tex, data, false); diff --git a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs index c61d4a7ef8..3ca57653be 100644 --- a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs @@ -121,15 +121,21 @@ public UnityEngine.Profiling.Memory.Experimental.MetaData metadata // [opt: screenshot_width ] // [opt: screenshot_height ] // [opt: screenshot_format ] + var data = new UnityEngine.Profiling.Memory.Experimental.MetaData(); - var metaData = new UnityEngine.Profiling.Memory.Experimental.MetaData(); + if (array.Length == 0) + { + data.content = ""; + data.platform = ""; + return data; + } int offset = 0; int dataLength = 0; offset = ReadIntFromByteArray(array, offset, out dataLength); - offset = ReadStringFromByteArray(array, offset, dataLength, out metaData.content); + offset = ReadStringFromByteArray(array, offset, dataLength, out data.content); offset = ReadIntFromByteArray(array, offset, out dataLength); - offset = ReadStringFromByteArray(array, offset, dataLength, out metaData.platform); + offset = ReadStringFromByteArray(array, offset, dataLength, out data.platform); offset = ReadIntFromByteArray(array, offset, out dataLength); if (dataLength > 0) @@ -146,14 +152,14 @@ public UnityEngine.Profiling.Memory.Experimental.MetaData metadata offset = ReadIntFromByteArray(array, offset, out height); offset = ReadIntFromByteArray(array, offset, out format); - metaData.screenshot = new Texture2D(width, height, (TextureFormat)format, false); - metaData.screenshot.LoadRawTextureData(screenshot); - metaData.screenshot.Apply(); + data.screenshot = new Texture2D(width, height, (TextureFormat)format, false); + data.screenshot.LoadRawTextureData(screenshot); + data.screenshot.Apply(); } UnityEngine.Assertions.Assert.AreEqual(array.Length, offset); - return metaData; + return data; } } diff --git a/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs b/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs index 16ccf7806d..e8ba9d056b 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/NetworkDetailStats.cs @@ -119,8 +119,10 @@ public void NewProfilerTick(int tickId) { entry.NewProfilerTick(tickId); } +#pragma warning disable 618 NetworkTransport.SetPacketStat(0, MsgId, (int)totalIn, 1); NetworkTransport.SetPacketStat(1, MsgId, (int)totalOut, 1); +#pragma warning restore 618 totalIn = 0; totalOut = 0; } @@ -253,8 +255,10 @@ static public void ResetAll() { foreach (var detail in m_NetworkOperations.Values) { +#pragma warning disable 618 NetworkTransport.SetPacketStat(0, detail.MsgId, 0, 1); NetworkTransport.SetPacketStat(1, detail.MsgId, 0, 1); +#pragma warning restore 618 } m_NetworkOperations.Clear(); } diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs index 4850a99fb8..f7f1f41a83 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerFrameHierarchyView.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using UnityEditor; using UnityEditor.IMGUI.Controls; +using Unity.Profiling; namespace UnityEditorInternal.Profiling { @@ -111,6 +112,8 @@ public bool sortedProfilerColumnAscending public delegate void SearchChangedCallback(string newSearch); public event SearchChangedCallback searchChanged; + static readonly ProfilerMarker m_DoGUIMarker = new ProfilerMarker(nameof(ProfilerFrameDataHierarchyView) + ".DoGUI"); + public ProfilerFrameDataHierarchyView() { m_Initialized = false; @@ -275,70 +278,73 @@ static string GetProfilerColumnName(ProfilerColumn column) public void DoGUI(FrameDataView frameDataView) { - InitIfNeeded(); + using (m_DoGUIMarker.Auto()) + { + InitIfNeeded(); - var collectingSamples = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying); - var isSearchAllowed = string.IsNullOrEmpty(treeView.searchString) || !(collectingSamples && ProfilerDriver.deepProfiling); + var collectingSamples = ProfilerDriver.enabled && (ProfilerDriver.profileEditor || EditorApplication.isPlaying); + var isSearchAllowed = string.IsNullOrEmpty(treeView.searchString) || !(collectingSamples && ProfilerDriver.deepProfiling); - var isDataAvailable = frameDataView != null && frameDataView.IsValid(); - if (isDataAvailable && isSearchAllowed) - if (isDataAvailable) - m_TreeView.SetFrameDataView(frameDataView); + var isDataAvailable = frameDataView != null && frameDataView.IsValid(); + if (isDataAvailable && isSearchAllowed) + if (isDataAvailable) + m_TreeView.SetFrameDataView(frameDataView); - var showDetailedView = isDataAvailable && m_DetailedViewType != DetailedViewType.None; - if (showDetailedView) - SplitterGUILayout.BeginHorizontalSplit(m_DetailedViewSpliterState); + var showDetailedView = isDataAvailable && m_DetailedViewType != DetailedViewType.None; + if (showDetailedView) + SplitterGUILayout.BeginHorizontalSplit(m_DetailedViewSpliterState); - // Hierarchy view area - GUILayout.BeginVertical(); + // Hierarchy view area + GUILayout.BeginVertical(); - DrawToolbar(frameDataView, showDetailedView); + DrawToolbar(frameDataView, showDetailedView); - if (!isDataAvailable) - { - GUILayout.Label(BaseStyles.noData, BaseStyles.label); - } - else if (!isSearchAllowed) - { - GUILayout.Label(BaseStyles.disabledSearchText, BaseStyles.label); - } - else - { - var rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true), GUILayout.ExpandHeight(true)); - m_TreeView.OnGUI(rect); - } + if (!isDataAvailable) + { + GUILayout.Label(BaseStyles.noData, BaseStyles.label); + } + else if (!isSearchAllowed) + { + GUILayout.Label(BaseStyles.disabledSearchText, BaseStyles.label); + } + else + { + var rect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true), GUILayout.ExpandHeight(true)); + m_TreeView.OnGUI(rect); + } - GUILayout.EndVertical(); + GUILayout.EndVertical(); - if (showDetailedView) - { - GUILayout.BeginVertical(); + if (showDetailedView) + { + GUILayout.BeginVertical(); - // Detailed view area - EditorGUILayout.BeginHorizontal(BaseStyles.toolbar); + // Detailed view area + EditorGUILayout.BeginHorizontal(BaseStyles.toolbar); - DrawDetailedViewPopup(); - GUILayout.FlexibleSpace(); + DrawDetailedViewPopup(); + GUILayout.FlexibleSpace(); - DrawOptionsMenuPopup(); - EditorGUILayout.EndHorizontal(); + DrawOptionsMenuPopup(); + EditorGUILayout.EndHorizontal(); - switch (m_DetailedViewType) - { - case DetailedViewType.Objects: - detailedObjectsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); - break; - case DetailedViewType.CallersAndCallees: - detailedCallsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); - break; - } + switch (m_DetailedViewType) + { + case DetailedViewType.Objects: + detailedObjectsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); + break; + case DetailedViewType.CallersAndCallees: + detailedCallsView.DoGUI(BaseStyles.header, frameDataView, m_TreeView.GetSelection()); + break; + } - GUILayout.EndVertical(); + GUILayout.EndVertical(); - SplitterGUILayout.EndHorizontalSplit(); - } + SplitterGUILayout.EndHorizontalSplit(); + } - HandleKeyboardEvents(); + HandleKeyboardEvents(); + } } void DrawSearchBar() diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs index 9d60438ccd..ee29b6a242 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs @@ -9,6 +9,7 @@ using UnityEditorInternal.Profiling; using Object = UnityEngine.Object; using UnityEditor.AnimatedValues; +using Unity.Profiling; namespace UnityEditorInternal { @@ -36,12 +37,13 @@ internal class ThreadInfo public int threadIndex; public string name; public bool alive; - public int maxDepth = 1; - public ThreadInfo(string name, int threadIndex, int linesToDisplay) + public int maxDepth; + public ThreadInfo(string name, int threadIndex, int maxDepth, int linesToDisplay) { this.name = name; this.threadIndex = threadIndex; this.linesToDisplay = linesToDisplay; + this.maxDepth = Mathf.Max(1, maxDepth); } } @@ -227,6 +229,8 @@ struct RangeSelectionInfo RangeSelectionInfo m_RangeSelection = new RangeSelectionInfo(); + static readonly ProfilerMarker m_DoGUIMarker = new ProfilerMarker(nameof(ProfilerTimelineGUI) + ".DoGUI"); + public ProfilerTimelineGUI(IProfilerWindowController window) { m_Window = window; @@ -265,43 +269,21 @@ private void UpdateGroupAndThreadInfo(ref ProfilerFrameDataIterator iter, int fr ThreadInfo thread = threads.Find(t => t.threadIndex == i); if (thread == null) { - thread = new ThreadInfo(iter.GetThreadName(), i, group.defaultLineCountPerThread); + // ProfilerFrameDataIterator.maxDepth includes the thread sample which is not getting displayed, so we store it at -1 for all intents and purposes + thread = new ThreadInfo(iter.GetThreadName(), i, iter.maxDepth - 1, group.defaultLineCountPerThread); // the main thread gets double the size if (i == 0) thread.linesToDisplay *= 2; group.threads.Add(thread); } - thread.alive = true; - } - - if (m_LastSelectedFrameID != frameIndex) - { - foreach (var group in m_Groups) + else if (m_LastSelectedFrameID != frameIndex) { - foreach (var thread in group.threads) - { - thread.maxDepth = GetThreadMaxDepth(thread, frameIndex); - } - } - m_LastSelectedFrameID = frameIndex; - } - } - - int GetThreadMaxDepth(ThreadInfo thread, int frame) - { - int maxDepth = 1; - using (var iter = new ProfilerFrameDataIterator()) - { - iter.SetRoot(frame, thread.threadIndex); - - while (iter.Next(true)) - { - if (iter.depth > maxDepth) - maxDepth = iter.depth; + thread.maxDepth = iter.maxDepth; } + thread.alive = true; } - return maxDepth; + m_LastSelectedFrameID = frameIndex; } private float CalculateHeightForAllBars(Rect fullRect, out float combinedHeaderHeight, out float combinedThreadHeight) @@ -1190,200 +1172,203 @@ void HandleThreadSplitterFoldoutButtons(GroupInfo group, ThreadInfo thread, Rect public void DoGUI(FrameDataView frameDataView, float width, float ypos, float height) { - if (frameDataView == null || !frameDataView.IsValid()) + using (m_DoGUIMarker.Auto()) { - GUILayout.Label(BaseStyles.noData, BaseStyles.label); - return; - } - - Rect fullRect = new Rect(0, ypos - 1, width, height + 1); - float sideWidth = Chart.kSideWidth - 1; + if (frameDataView == null || !frameDataView.IsValid()) + { + GUILayout.Label(BaseStyles.noData, BaseStyles.label); + return; + } - Rect timeRulerRect = new Rect(fullRect.x + sideWidth, fullRect.y, fullRect.width - sideWidth, k_LineHeight); + Rect fullRect = new Rect(0, ypos - 1, width, height + 1); + float sideWidth = Chart.kSideWidth - 1; - Rect timeAreaRect = new Rect(fullRect.x + sideWidth, fullRect.y + timeRulerRect.height, fullRect.width - sideWidth, fullRect.height - timeRulerRect.height); + Rect timeRulerRect = new Rect(fullRect.x + sideWidth, fullRect.y, fullRect.width - sideWidth, k_LineHeight); - bool initializing = false; - if (m_TimeArea == null) - { - initializing = true; - m_TimeArea = new ZoomableArea(); - m_TimeArea.hRangeLocked = false; - m_TimeArea.vRangeLocked = false; - m_TimeArea.hSlider = true; - m_TimeArea.vSlider = true; - m_TimeArea.vAllowExceedBaseRangeMax = false; - m_TimeArea.vAllowExceedBaseRangeMin = false; - m_TimeArea.hBaseRangeMin = 0; - m_TimeArea.vBaseRangeMin = 0; - m_TimeArea.vScaleMax = 1f; - m_TimeArea.vScaleMin = 1f; - m_TimeArea.scaleWithWindow = true; - m_TimeArea.margin = 10; - m_TimeArea.topmargin = 0; - m_TimeArea.bottommargin = 0; - m_TimeArea.upDirection = ZoomableArea.YDirection.Negative; - m_TimeArea.vZoomLockedByDefault = true; - } + Rect timeAreaRect = new Rect(fullRect.x + sideWidth, fullRect.y + timeRulerRect.height, fullRect.width - sideWidth, fullRect.height - timeRulerRect.height); - m_TimeArea.rect = timeAreaRect; + bool initializing = false; + if (m_TimeArea == null) + { + initializing = true; + m_TimeArea = new ZoomableArea(); + m_TimeArea.hRangeLocked = false; + m_TimeArea.vRangeLocked = false; + m_TimeArea.hSlider = true; + m_TimeArea.vSlider = true; + m_TimeArea.vAllowExceedBaseRangeMax = false; + m_TimeArea.vAllowExceedBaseRangeMin = false; + m_TimeArea.hBaseRangeMin = 0; + m_TimeArea.vBaseRangeMin = 0; + m_TimeArea.vScaleMax = 1f; + m_TimeArea.vScaleMin = 1f; + m_TimeArea.scaleWithWindow = true; + m_TimeArea.margin = 10; + m_TimeArea.topmargin = 0; + m_TimeArea.bottommargin = 0; + m_TimeArea.upDirection = ZoomableArea.YDirection.Negative; + m_TimeArea.vZoomLockedByDefault = true; + } - Rect bottomLeftFillRect = new Rect(0, ypos + height - m_TimeArea.vSliderWidth, sideWidth, m_TimeArea.vSliderWidth); + m_TimeArea.rect = timeAreaRect; - if (Event.current.type == EventType.Repaint) - { - styles.profilerGraphBackground.Draw(fullRect, false, false, false, false); - // The bar in the lower left side that fills the space next to the horizontal scrollbar. - EditorStyles.toolbar.Draw(bottomLeftFillRect, false, false, false, false); - } + Rect bottomLeftFillRect = new Rect(0, ypos + height - m_TimeArea.vSliderWidth, sideWidth, m_TimeArea.vSliderWidth); - if (initializing) - { - NativeProfilerTimeline_InitializeArgs args = new NativeProfilerTimeline_InitializeArgs(); - args.Reset(); - args.ghostAlpha = 0.3f; - args.nonSelectedAlpha = 0.75f; - args.guiStyle = styles.bar.m_Ptr; - args.lineHeight = k_LineHeight; - args.textFadeOutWidth = k_TextFadeOutWidth; - args.textFadeStartWidth = k_TextFadeStartWidth; - - NativeProfilerTimeline.Initialize(ref args); - } - // Prepare group and Thread Info - var iter = new ProfilerFrameDataIterator(); - int threadCount = iter.GetThreadCount(frameDataView.frameIndex); - iter.SetRoot(frameDataView.frameIndex, 0); - UpdateGroupAndThreadInfo(ref iter, frameDataView.frameIndex); - MarkDeadOrClearThread(); + if (Event.current.type == EventType.Repaint) + { + styles.profilerGraphBackground.Draw(fullRect, false, false, false, false); + // The bar in the lower left side that fills the space next to the horizontal scrollbar. + EditorStyles.toolbar.Draw(bottomLeftFillRect, false, false, false, false); + } - HandleFrameSelected(iter.frameTimeMS); + if (initializing) + { + NativeProfilerTimeline_InitializeArgs args = new NativeProfilerTimeline_InitializeArgs(); + args.Reset(); + args.ghostAlpha = 0.3f; + args.nonSelectedAlpha = 0.75f; + args.guiStyle = styles.bar.m_Ptr; + args.lineHeight = k_LineHeight; + args.textFadeOutWidth = k_TextFadeOutWidth; + args.textFadeStartWidth = k_TextFadeStartWidth; + + NativeProfilerTimeline.Initialize(ref args); + } + // Prepare group and Thread Info + var iter = new ProfilerFrameDataIterator(); + int threadCount = iter.GetThreadCount(frameDataView.frameIndex); + iter.SetRoot(frameDataView.frameIndex, 0); + UpdateGroupAndThreadInfo(ref iter, frameDataView.frameIndex); + MarkDeadOrClearThread(); - // update time area to new bounds - float combinedHeaderHeight, combinedThreadHeight; - float heightForAllBars = CalculateHeightForAllBars(fullRect, out combinedHeaderHeight, out combinedThreadHeight); - float emptySpaceBelowBars = k_LineHeight * 3f; + HandleFrameSelected(iter.frameTimeMS); - // if needed, take up more empty space below, to fill up the ZoomableArea - emptySpaceBelowBars = Mathf.Max(emptySpaceBelowBars, timeAreaRect.height - heightForAllBars); + // update time area to new bounds + float combinedHeaderHeight, combinedThreadHeight; + float heightForAllBars = CalculateHeightForAllBars(fullRect, out combinedHeaderHeight, out combinedThreadHeight); + float emptySpaceBelowBars = k_LineHeight * 3f; - heightForAllBars += emptySpaceBelowBars; + // if needed, take up more empty space below, to fill up the ZoomableArea + emptySpaceBelowBars = Mathf.Max(emptySpaceBelowBars, timeAreaRect.height - heightForAllBars); - m_TimeArea.hBaseRangeMax = iter.frameTimeMS; - m_TimeArea.vBaseRangeMax = heightForAllBars; + heightForAllBars += emptySpaceBelowBars; - if (Mathf.Abs(heightForAllBars - m_LastHeightForAllBars) >= 0.5f || Mathf.Abs(fullRect.height - m_LastFullRectHeight) >= 0.5f) - { - m_LastHeightForAllBars = heightForAllBars; - m_LastFullRectHeight = fullRect.height; + m_TimeArea.hBaseRangeMax = iter.frameTimeMS; + m_TimeArea.vBaseRangeMax = heightForAllBars; - // set V range to enforce scale of 1 and to shift the shown area up in case the drawn area shrunk down - m_TimeArea.SetShownVRange(m_TimeArea.shownArea.y, m_TimeArea.shownArea.y + m_TimeArea.drawRect.height); - } + if (Mathf.Abs(heightForAllBars - m_LastHeightForAllBars) >= 0.5f || Mathf.Abs(fullRect.height - m_LastFullRectHeight) >= 0.5f) + { + m_LastHeightForAllBars = heightForAllBars; + m_LastFullRectHeight = fullRect.height; - // frame the selection if needed and before drawing the time area - if (initializing) - PerformFrameSelected(iter.frameTimeMS); + // set V range to enforce scale of 1 and to shift the shown area up in case the drawn area shrunk down + m_TimeArea.SetShownVRange(m_TimeArea.shownArea.y, m_TimeArea.shownArea.y + m_TimeArea.drawRect.height); + } - DoTimeRulerGUI(timeRulerRect, sideWidth, iter.frameTimeMS); - DoTimeArea(); + // frame the selection if needed and before drawing the time area + if (initializing) + PerformFrameSelected(iter.frameTimeMS); - Rect fullThreadsRect = new Rect(fullRect.x, fullRect.y + timeRulerRect.height, fullRect.width - m_TimeArea.vSliderWidth, fullRect.height - timeRulerRect.height - m_TimeArea.hSliderHeight); + DoTimeRulerGUI(timeRulerRect, sideWidth, iter.frameTimeMS); + DoTimeArea(); - Rect fullThreadsRectWithoutSidebar = fullThreadsRect; - fullThreadsRectWithoutSidebar.x += sideWidth; - fullThreadsRectWithoutSidebar.width -= sideWidth; + Rect fullThreadsRect = new Rect(fullRect.x, fullRect.y + timeRulerRect.height, fullRect.width - m_TimeArea.vSliderWidth, fullRect.height - timeRulerRect.height - m_TimeArea.hSliderHeight); - // The splitters need to be handled after the time area so that they don't interfere with the input for panning/scrolling the ZoomableArea - DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitter); + Rect fullThreadsRectWithoutSidebar = fullThreadsRect; + fullThreadsRectWithoutSidebar.x += sideWidth; + fullThreadsRectWithoutSidebar.width -= sideWidth; - Rect barsUIRect = m_TimeArea.drawRect; + // The splitters need to be handled after the time area so that they don't interfere with the input for panning/scrolling the ZoomableArea + DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitter); - DrawGrid(barsUIRect, iter.frameTimeMS); + Rect barsUIRect = m_TimeArea.drawRect; - Rect barsAndSidebarUIRect = new Rect(barsUIRect.x - sideWidth, barsUIRect.y, barsUIRect.width + sideWidth, barsUIRect.height); + DrawGrid(barsUIRect, iter.frameTimeMS); - GUI.BeginClip(barsAndSidebarUIRect); + Rect barsAndSidebarUIRect = new Rect(barsUIRect.x - sideWidth, barsUIRect.y, barsUIRect.width + sideWidth, barsUIRect.height); - Rect shownBarsUIRect = barsUIRect; - shownBarsUIRect.y = scrollOffsetY; + GUI.BeginClip(barsAndSidebarUIRect); - // since the scale is not applied to the group headers, there would be some height unaccounted for - // this calculation applies that height to the threads via scaleForThreadHeight - float heightUnaccountedForDueToNotScalingHeaders = m_TimeArea.scale.y * combinedHeaderHeight - combinedHeaderHeight; - float scaleForThreadHeight = (combinedThreadHeight * m_TimeArea.scale.y + heightUnaccountedForDueToNotScalingHeaders) / combinedThreadHeight; + Rect shownBarsUIRect = barsUIRect; + shownBarsUIRect.y = scrollOffsetY; - DrawBars(shownBarsUIRect, scaleForThreadHeight); - GUI.EndClip(); + // since the scale is not applied to the group headers, there would be some height unaccounted for + // this calculation applies that height to the threads via scaleForThreadHeight + float heightUnaccountedForDueToNotScalingHeaders = m_TimeArea.scale.y * combinedHeaderHeight - combinedHeaderHeight; + float scaleForThreadHeight = (combinedThreadHeight * m_TimeArea.scale.y + heightUnaccountedForDueToNotScalingHeaders) / combinedThreadHeight; - DoRangeSelection(barsUIRect); + DrawBars(shownBarsUIRect, scaleForThreadHeight); + GUI.EndClip(); - GUI.BeginClip(barsUIRect); - shownBarsUIRect.x = 0; + DoRangeSelection(barsUIRect); - bool oldEnabled = GUI.enabled; - GUI.enabled = false; - // Walk backwards to find how many previous frames we need to show. - int maxContextFramesToShow = m_Window.IsRecording() ? 1 : 3; - int numContextFramesToShow = maxContextFramesToShow; - int currentFrame = frameDataView.frameIndex; - float currentTime = 0; - do - { - int prevFrame = ProfilerDriver.GetPreviousFrameIndex(currentFrame); - if (prevFrame == -1) - break; - iter.SetRoot(prevFrame, 0); - currentTime -= iter.frameTimeMS; - currentFrame = prevFrame; - --numContextFramesToShow; - } - while (currentTime > m_TimeArea.shownArea.x && numContextFramesToShow > 0); + GUI.BeginClip(barsUIRect); + shownBarsUIRect.x = 0; - // Draw previous frames - while (currentFrame != -1 && currentFrame != frameDataView.frameIndex) - { - iter.SetRoot(currentFrame, 0); - DoProfilerFrame(currentFrame, shownBarsUIRect, true, threadCount, currentTime, scaleForThreadHeight); - currentTime += iter.frameTimeMS; - currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); - } + bool oldEnabled = GUI.enabled; + GUI.enabled = false; + // Walk backwards to find how many previous frames we need to show. + int maxContextFramesToShow = m_Window.IsRecording() ? 1 : 3; + int numContextFramesToShow = maxContextFramesToShow; + int currentFrame = frameDataView.frameIndex; + float currentTime = 0; + do + { + int prevFrame = ProfilerDriver.GetPreviousFrameIndex(currentFrame); + if (prevFrame == -1) + break; + iter.SetRoot(prevFrame, 0); + currentTime -= iter.frameTimeMS; + currentFrame = prevFrame; + --numContextFramesToShow; + } + while (currentTime > m_TimeArea.shownArea.x && numContextFramesToShow > 0); - // Draw next frames - numContextFramesToShow = maxContextFramesToShow; - currentFrame = frameDataView.frameIndex; - currentTime = 0; - while (currentTime < m_TimeArea.shownArea.x + m_TimeArea.shownArea.width && numContextFramesToShow >= 0) - { - if (frameDataView.frameIndex != currentFrame) + // Draw previous frames + while (currentFrame != -1 && currentFrame != frameDataView.frameIndex) + { + iter.SetRoot(currentFrame, 0); DoProfilerFrame(currentFrame, shownBarsUIRect, true, threadCount, currentTime, scaleForThreadHeight); - iter.SetRoot(currentFrame, 0); - currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); - if (currentFrame == -1) - break; - currentTime += iter.frameTimeMS; - --numContextFramesToShow; - } + currentTime += iter.frameTimeMS; + currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); + } + + // Draw next frames + numContextFramesToShow = maxContextFramesToShow; + currentFrame = frameDataView.frameIndex; + currentTime = 0; + while (currentTime < m_TimeArea.shownArea.x + m_TimeArea.shownArea.width && numContextFramesToShow >= 0) + { + if (frameDataView.frameIndex != currentFrame) + DoProfilerFrame(currentFrame, shownBarsUIRect, true, threadCount, currentTime, scaleForThreadHeight); + iter.SetRoot(currentFrame, 0); + currentFrame = ProfilerDriver.GetNextFrameIndex(currentFrame); + if (currentFrame == -1) + break; + currentTime += iter.frameTimeMS; + --numContextFramesToShow; + } - GUI.enabled = oldEnabled; + GUI.enabled = oldEnabled; - // Draw center frame last to get on top - threadCount = 0; - DoProfilerFrame(frameDataView.frameIndex, shownBarsUIRect, false, threadCount, 0, scaleForThreadHeight); + // Draw center frame last to get on top + threadCount = 0; + DoProfilerFrame(frameDataView.frameIndex, shownBarsUIRect, false, threadCount, 0, scaleForThreadHeight); - GUI.EndClip(); + GUI.EndClip(); - // Draw Foldout Buttons on top of natively drawn bars - DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitterFoldoutButtons); + // Draw Foldout Buttons on top of natively drawn bars + DoThreadSplitters(fullThreadsRect, fullThreadsRectWithoutSidebar, frameDataView.frameIndex, ThreadSplitterCommand.HandleThreadSplitterFoldoutButtons); - // Draw tooltips on top of clip to be able to extend outside of timeline area - DoSelectionTooltip(frameDataView.frameIndex, m_TimeArea.drawRect); + // Draw tooltips on top of clip to be able to extend outside of timeline area + DoSelectionTooltip(frameDataView.frameIndex, m_TimeArea.drawRect); - if (Event.current.type == EventType.Repaint) - { - // Reset all flags once Repaint finished on this view - m_LastRepaintProcessedInputs = m_CurrentlyProcessedInputs; - m_CurrentlyProcessedInputs = 0; + if (Event.current.type == EventType.Repaint) + { + // Reset all flags once Repaint finished on this view + m_LastRepaintProcessedInputs = m_CurrentlyProcessedInputs; + m_CurrentlyProcessedInputs = 0; + } } } diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs index 1228f2fe70..127ff30dbb 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs @@ -107,7 +107,8 @@ static Styles() private Vector2 m_GraphPos = Vector2.zero; private Vector2[] m_PaneScroll = new Vector2[Profiler.areaCount]; private Vector2 m_PaneScroll_AudioChannels = Vector2.zero; - private Vector2 m_PaneScroll_AudioDSP = Vector2.zero; + private Vector2 m_PaneScroll_AudioDSPLeft = Vector2.zero; + private Vector2 m_PaneScroll_AudioDSPRight = Vector2.zero; private Vector2 m_PaneScroll_AudioClips = Vector2.zero; [SerializeField] @@ -122,7 +123,7 @@ static Styles() ProfilerArea? m_CurrentArea = ProfilerArea.CPU; ProfilerMemoryView m_ShowDetailedMemoryPane = ProfilerMemoryView.Simple; - ProfilerAudioView m_ShowDetailedAudioPane = ProfilerAudioView.Stats; + ProfilerAudioView m_ShowDetailedAudioPane = ProfilerAudioView.Channels; [SerializeField] bool m_ShowInactiveDSPChains = false; @@ -837,194 +838,192 @@ void DrawNetworkOperationsPane() } - private void AudioProfilerToggle(ProfilerCaptureFlags toggleFlag) + private enum ProfilerAudioPopupItems { - bool oldState = (AudioSettings.profilerCaptureFlags & (int)toggleFlag) != 0; - bool newState = GUILayout.Toggle(oldState, "Record", EditorStyles.toolbarButton); - if (oldState != newState) - ProfilerDriver.SetAudioCaptureFlags((AudioSettings.profilerCaptureFlags & ~(int)toggleFlag) | (newState - ? (int)toggleFlag - : 0)); + Simple = 0, + Detailed = 1 + } + + private bool AudioDeepProfileToggle() + { + int toggleFlags = (int)ProfilerCaptureFlags.Channels; + if (Unsupported.IsDeveloperMode()) + toggleFlags |= (int)ProfilerCaptureFlags.Clips | (int)ProfilerCaptureFlags.DSPNodes; + ProfilerAudioPopupItems oldShowDetailedAudioPane = (AudioSettings.profilerCaptureFlags & toggleFlags) != 0 ? ProfilerAudioPopupItems.Detailed : ProfilerAudioPopupItems.Simple; + ProfilerAudioPopupItems newShowDetailedAudioPane = (ProfilerAudioPopupItems)EditorGUILayout.EnumPopup(oldShowDetailedAudioPane, EditorStyles.toolbarDropDown, GUILayout.Width(70f)); + if (oldShowDetailedAudioPane != newShowDetailedAudioPane) + ProfilerDriver.SetAudioCaptureFlags((AudioSettings.profilerCaptureFlags & ~toggleFlags) | (newShowDetailedAudioPane == ProfilerAudioPopupItems.Detailed ? toggleFlags : 0)); + return (AudioSettings.profilerCaptureFlags & toggleFlags) != 0; + } + + private Rect DrawAudioStatsPane(ref Vector2 scrollPos) + { + var totalRect = GUILayoutUtility.GetRect(20f, 20000f, 10, 10000f); + var statsRect = new Rect(totalRect.x, totalRect.y, 230f, totalRect.height); + var rightRect = new Rect(statsRect.xMax, totalRect.y, totalRect.width - statsRect.width, totalRect.height); + + // STATS + var content = ProfilerDriver.GetOverviewText(m_CurrentArea.Value, GetActiveVisibleFrameIndex()); + var textSize = EditorStyles.wordWrappedLabel.CalcSize(GUIContent.Temp(content)); + scrollPos = GUI.BeginScrollView(statsRect, scrollPos, new Rect(0, 0, textSize.x, textSize.y)); + GUI.Label(new Rect(3, 3, textSize.x, textSize.y), content, EditorStyles.wordWrappedLabel); + GUI.EndScrollView(); + EditorGUI.DrawRect(new Rect(statsRect.xMax - 1, statsRect.y, 1, statsRect.height), Color.black); + + return rightRect; } private void DrawAudioPane() { EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); ProfilerAudioView newShowDetailedAudioPane = m_ShowDetailedAudioPane; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Stats, "Stats", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Stats; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Channels, "Channels", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Channels; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Groups, "Groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Groups; - if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.ChannelsAndGroups, "Channels and groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.ChannelsAndGroups; - if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.DSPGraph, "DSP Graph", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.DSPGraph; - if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Clips, "Clips", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Clips; - if (newShowDetailedAudioPane != m_ShowDetailedAudioPane) - { - m_ShowDetailedAudioPane = newShowDetailedAudioPane; - m_LastAudioProfilerFrame = -1; // force update - } - if (m_ShowDetailedAudioPane == ProfilerAudioView.Stats) - { - GUILayout.Space(5); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - DrawOverviewText(m_CurrentArea); - } - else if (m_ShowDetailedAudioPane == ProfilerAudioView.DSPGraph) + if (AudioDeepProfileToggle()) { - GUILayout.Space(5); - AudioProfilerToggle(ProfilerCaptureFlags.DSPNodes); - GUILayout.Space(5); - m_ShowInactiveDSPChains = GUILayout.Toggle(m_ShowInactiveDSPChains, "Show inactive", EditorStyles.toolbarButton); - if (m_ShowInactiveDSPChains) - m_HighlightAudibleDSPChains = GUILayout.Toggle(m_HighlightAudibleDSPChains, "Highlight audible", EditorStyles.toolbarButton); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); + if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Channels, "Channels", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Channels; + if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Groups, "Groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Groups; + if (GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.ChannelsAndGroups, "Channels and groups", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.ChannelsAndGroups; + if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.DSPGraph, "DSP Graph", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.DSPGraph; + if (Unsupported.IsDeveloperMode() && GUILayout.Toggle(newShowDetailedAudioPane == ProfilerAudioView.Clips, "Clips", EditorStyles.toolbarButton)) newShowDetailedAudioPane = ProfilerAudioView.Clips; + if (newShowDetailedAudioPane != m_ShowDetailedAudioPane) + { + m_ShowDetailedAudioPane = newShowDetailedAudioPane; + m_LastAudioProfilerFrame = -1; // force update + } + if (m_ShowDetailedAudioPane == ProfilerAudioView.DSPGraph) + { + m_ShowInactiveDSPChains = GUILayout.Toggle(m_ShowInactiveDSPChains, "Show inactive", EditorStyles.toolbarButton); + if (m_ShowInactiveDSPChains) + m_HighlightAudibleDSPChains = GUILayout.Toggle(m_HighlightAudibleDSPChains, "Highlight audible", EditorStyles.toolbarButton); + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); - var totalRect = GUILayoutUtility.GetRect(20f, 10000f, 10, 20000f); + var graphRect = DrawAudioStatsPane(ref m_PaneScroll_AudioDSPLeft); - m_PaneScroll_AudioDSP = GUI.BeginScrollView(totalRect, m_PaneScroll_AudioDSP, new Rect(0, 0, 10000, 20000)); + m_PaneScroll_AudioDSPRight = GUI.BeginScrollView(graphRect, m_PaneScroll_AudioDSPRight, new Rect(0, 0, 10000, 20000)); - var clippingRect = new Rect(m_PaneScroll_AudioDSP.x, m_PaneScroll_AudioDSP.y, totalRect.width, totalRect.height); + var clippingRect = new Rect(m_PaneScroll_AudioDSPRight.x, m_PaneScroll_AudioDSPRight.y, graphRect.width, graphRect.height); - if (m_AudioProfilerDSPView == null) - m_AudioProfilerDSPView = new AudioProfilerDSPView(); + if (m_AudioProfilerDSPView == null) + m_AudioProfilerDSPView = new AudioProfilerDSPView(); - ProfilerProperty property = CreateProperty(); - if (CheckFrameData(property)) - { - m_AudioProfilerDSPView.OnGUI(clippingRect, property, m_ShowInactiveDSPChains, m_HighlightAudibleDSPChains, ref m_DSPGraphZoomFactor, ref m_PaneScroll_AudioDSP); - } - if (property != null) - property.Dispose(); + ProfilerProperty property = CreateProperty(); + if (CheckFrameData(property)) + { + m_AudioProfilerDSPView.OnGUI(clippingRect, property, m_ShowInactiveDSPChains, m_HighlightAudibleDSPChains, ref m_DSPGraphZoomFactor, ref m_PaneScroll_AudioDSPRight); + } + if (property != null) + property.Dispose(); - GUI.EndScrollView(); + GUI.EndScrollView(); - Repaint(); - } - else if (m_ShowDetailedAudioPane == ProfilerAudioView.Clips) - { - GUILayout.Space(5); - AudioProfilerToggle(ProfilerCaptureFlags.Clips); - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - - var totalRect = GUILayoutUtility.GetRect(20f, 20000f, 10, 10000f); - var statsRect = new Rect(totalRect.x, totalRect.y, 230f, totalRect.height); - var treeRect = new Rect(statsRect.xMax, totalRect.y, totalRect.width - statsRect.width, totalRect.height); + Repaint(); + } + else if (m_ShowDetailedAudioPane == ProfilerAudioView.Clips) + { + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); - // STATS - var content = ProfilerDriver.GetOverviewText(m_CurrentArea.Value, GetActiveVisibleFrameIndex()); - var textSize = EditorStyles.wordWrappedLabel.CalcSize(GUIContent.Temp(content)); - m_PaneScroll_AudioClips = GUI.BeginScrollView(statsRect, m_PaneScroll_AudioClips, new Rect(0, 0, textSize.x, textSize.y)); - GUI.Label(new Rect(3, 3, textSize.x, textSize.y), content, EditorStyles.wordWrappedLabel); - GUI.EndScrollView(); - EditorGUI.DrawRect(new Rect(statsRect.xMax - 1, statsRect.y, 1, statsRect.height), Color.black); + var treeRect = DrawAudioStatsPane(ref m_PaneScroll_AudioClips); - // TREE - if (m_AudioProfilerClipTreeViewState == null) - m_AudioProfilerClipTreeViewState = new AudioProfilerClipTreeViewState(); + // TREE + if (m_AudioProfilerClipTreeViewState == null) + m_AudioProfilerClipTreeViewState = new AudioProfilerClipTreeViewState(); - if (m_AudioProfilerClipViewBackend == null) - m_AudioProfilerClipViewBackend = new AudioProfilerClipViewBackend(m_AudioProfilerClipTreeViewState); + if (m_AudioProfilerClipViewBackend == null) + m_AudioProfilerClipViewBackend = new AudioProfilerClipViewBackend(m_AudioProfilerClipTreeViewState); - ProfilerProperty property = CreateProperty(); - if (CheckFrameData(property)) - { - if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) + ProfilerProperty property = CreateProperty(); + if (CheckFrameData(property)) { - m_LastAudioProfilerFrame = m_CurrentFrame; - var sourceItems = property.GetAudioProfilerClipInfo(); - if (sourceItems != null && sourceItems.Length > 0) + if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) { - var items = new List(); - foreach (var s in sourceItems) - { - items.Add(new AudioProfilerClipInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset))); - } - m_AudioProfilerClipViewBackend.SetData(items); - if (m_AudioProfilerClipView == null) + m_LastAudioProfilerFrame = m_CurrentFrame; + var sourceItems = property.GetAudioProfilerClipInfo(); + if (sourceItems != null && sourceItems.Length > 0) { - m_AudioProfilerClipView = new AudioProfilerClipView(this, m_AudioProfilerClipTreeViewState); - m_AudioProfilerClipView.Init(treeRect, m_AudioProfilerClipViewBackend); + var items = new List(); + foreach (var s in sourceItems) + { + items.Add(new AudioProfilerClipInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset))); + } + m_AudioProfilerClipViewBackend.SetData(items); + if (m_AudioProfilerClipView == null) + { + m_AudioProfilerClipView = new AudioProfilerClipView(this, m_AudioProfilerClipTreeViewState); + m_AudioProfilerClipView.Init(treeRect, m_AudioProfilerClipViewBackend); + } } } + if (m_AudioProfilerClipView != null) + m_AudioProfilerClipView.OnGUI(treeRect); } - if (m_AudioProfilerClipView != null) - m_AudioProfilerClipView.OnGUI(treeRect); + if (property != null) + property.Dispose(); } - if (property != null) - property.Dispose(); - } - else - { - GUILayout.Space(5); - AudioProfilerToggle(ProfilerCaptureFlags.Channels); - GUILayout.Space(5); - bool resetAllAudioClipPlayCountsOnPlay = GUILayout.Toggle(AudioUtil.resetAllAudioClipPlayCountsOnPlay, "Reset play count on play", EditorStyles.toolbarButton); - if (resetAllAudioClipPlayCountsOnPlay != AudioUtil.resetAllAudioClipPlayCountsOnPlay) - AudioUtil.resetAllAudioClipPlayCountsOnPlay = resetAllAudioClipPlayCountsOnPlay; - if (Unsupported.IsDeveloperMode()) + else { - GUILayout.Space(5); - bool showAllGroups = EditorPrefs.GetBool("AudioProfilerShowAllGroups"); - bool newShowAllGroups = GUILayout.Toggle(showAllGroups, "Show all groups (dev mode only)", EditorStyles.toolbarButton); - if (showAllGroups != newShowAllGroups) - EditorPrefs.SetBool("AudioProfilerShowAllGroups", newShowAllGroups); - } - GUILayout.FlexibleSpace(); - EditorGUILayout.EndHorizontal(); - - var totalRect = GUILayoutUtility.GetRect(20f, 20000f, 10, 10000f); - var statsRect = new Rect(totalRect.x, totalRect.y, 230f, totalRect.height); - var treeRect = new Rect(statsRect.xMax, totalRect.y, totalRect.width - statsRect.width, totalRect.height); + bool resetAllAudioClipPlayCountsOnPlay = GUILayout.Toggle(AudioUtil.resetAllAudioClipPlayCountsOnPlay, "Reset play count on play", EditorStyles.toolbarButton); + if (resetAllAudioClipPlayCountsOnPlay != AudioUtil.resetAllAudioClipPlayCountsOnPlay) + AudioUtil.resetAllAudioClipPlayCountsOnPlay = resetAllAudioClipPlayCountsOnPlay; + if (Unsupported.IsDeveloperMode()) + { + GUILayout.Space(5); + bool showAllGroups = EditorPrefs.GetBool("AudioProfilerShowAllGroups"); + bool newShowAllGroups = GUILayout.Toggle(showAllGroups, "Show all groups (dev mode only)", EditorStyles.toolbarButton); + if (showAllGroups != newShowAllGroups) + EditorPrefs.SetBool("AudioProfilerShowAllGroups", newShowAllGroups); + } + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); - // STATS - var content = ProfilerDriver.GetOverviewText(m_CurrentArea.Value, GetActiveVisibleFrameIndex()); - var textSize = EditorStyles.wordWrappedLabel.CalcSize(GUIContent.Temp(content)); - m_PaneScroll_AudioChannels = GUI.BeginScrollView(statsRect, m_PaneScroll_AudioChannels, new Rect(0, 0, textSize.x, textSize.y)); - GUI.Label(new Rect(3, 3, textSize.x, textSize.y), content, EditorStyles.wordWrappedLabel); - GUI.EndScrollView(); - EditorGUI.DrawRect(new Rect(statsRect.xMax - 1, statsRect.y, 1, statsRect.height), Color.black); + var treeRect = DrawAudioStatsPane(ref m_PaneScroll_AudioChannels); - // TREE - if (m_AudioProfilerGroupTreeViewState == null) - m_AudioProfilerGroupTreeViewState = new AudioProfilerGroupTreeViewState(); + // TREE + if (m_AudioProfilerGroupTreeViewState == null) + m_AudioProfilerGroupTreeViewState = new AudioProfilerGroupTreeViewState(); - if (m_AudioProfilerGroupViewBackend == null) - m_AudioProfilerGroupViewBackend = new AudioProfilerGroupViewBackend(m_AudioProfilerGroupTreeViewState); + if (m_AudioProfilerGroupViewBackend == null) + m_AudioProfilerGroupViewBackend = new AudioProfilerGroupViewBackend(m_AudioProfilerGroupTreeViewState); - ProfilerProperty property = CreateProperty(); - if (CheckFrameData(property)) - { - if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) + ProfilerProperty property = CreateProperty(); + if (CheckFrameData(property)) { - m_LastAudioProfilerFrame = m_CurrentFrame; - var sourceItems = property.GetAudioProfilerGroupInfo(); - if (sourceItems != null && sourceItems.Length > 0) + if (m_CurrentFrame == -1 || m_LastAudioProfilerFrame != m_CurrentFrame) { - var items = new List(); - foreach (var s in sourceItems) - { - bool isGroup = (s.flags & AudioProfilerGroupInfoHelper.AUDIOPROFILER_FLAGS_GROUP) != 0; - if (m_ShowDetailedAudioPane == ProfilerAudioView.Channels && isGroup) - continue; - if (m_ShowDetailedAudioPane == ProfilerAudioView.Groups && !isGroup) - continue; - items.Add(new AudioProfilerGroupInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset), property.GetAudioProfilerNameByOffset(s.objectNameOffset), m_ShowDetailedAudioPane == ProfilerAudioView.Channels)); - } - m_AudioProfilerGroupViewBackend.SetData(items); - if (m_AudioProfilerGroupView == null) + m_LastAudioProfilerFrame = m_CurrentFrame; + var sourceItems = property.GetAudioProfilerGroupInfo(); + if (sourceItems != null && sourceItems.Length > 0) { - m_AudioProfilerGroupView = new AudioProfilerGroupView(this, m_AudioProfilerGroupTreeViewState); - m_AudioProfilerGroupView.Init(treeRect, m_AudioProfilerGroupViewBackend); + var items = new List(); + foreach (var s in sourceItems) + { + bool isGroup = (s.flags & AudioProfilerGroupInfoHelper.AUDIOPROFILER_FLAGS_GROUP) != 0; + if (m_ShowDetailedAudioPane == ProfilerAudioView.Channels && isGroup) + continue; + if (m_ShowDetailedAudioPane == ProfilerAudioView.Groups && !isGroup) + continue; + items.Add(new AudioProfilerGroupInfoWrapper(s, property.GetAudioProfilerNameByOffset(s.assetNameOffset), property.GetAudioProfilerNameByOffset(s.objectNameOffset), m_ShowDetailedAudioPane == ProfilerAudioView.Channels)); + } + m_AudioProfilerGroupViewBackend.SetData(items); + if (m_AudioProfilerGroupView == null) + { + m_AudioProfilerGroupView = new AudioProfilerGroupView(this, m_AudioProfilerGroupTreeViewState); + m_AudioProfilerGroupView.Init(treeRect, m_AudioProfilerGroupViewBackend); + } } } + if (m_AudioProfilerGroupView != null) + m_AudioProfilerGroupView.OnGUI(treeRect, m_ShowDetailedAudioPane == ProfilerAudioView.Channels); } - if (m_AudioProfilerGroupView != null) - m_AudioProfilerGroupView.OnGUI(treeRect, m_ShowDetailedAudioPane == ProfilerAudioView.Channels); + if (property != null) + property.Dispose(); } - if (property != null) - property.Dispose(); + } + else + { + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + DrawOverviewText(m_CurrentArea); } } diff --git a/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs b/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs index b2b687f222..75bb8169db 100644 --- a/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs +++ b/Modules/ProfilerEditor/Public/ProfilerAPI.bindings.cs @@ -54,7 +54,7 @@ public enum ProfilerMemoryView public enum ProfilerAudioView { - Stats = 0, + [Obsolete("This has been made obsolete. Audio stats are now shown on every subpane.", true)] Stats = 0, Channels = 1, Groups = 2, ChannelsAndGroups = 3, diff --git a/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs b/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs index 19037e8a21..c2ddb37866 100644 --- a/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs +++ b/Modules/ProfilerEditor/Public/ProfilerFrameDataIterator.bindings.cs @@ -63,6 +63,14 @@ public extern int depth get; } + /// + /// The maximal depth of the stacked samples. This count includes the thread root as well as counters. + /// + public extern int maxDepth + { + get; + } + public extern string path { [NativeMethod("GetFunctionPath")] diff --git a/Modules/ShortcutManagerEditor/ShortcutController.cs b/Modules/ShortcutManagerEditor/ShortcutController.cs index 068fe5f33c..f551108c50 100644 --- a/Modules/ShortcutManagerEditor/ShortcutController.cs +++ b/Modules/ShortcutManagerEditor/ShortcutController.cs @@ -16,11 +16,17 @@ static ShortcutIntegration() { InitializeController(); EditorApplication.globalEventHandler += EventHandler; + EditorApplication.doPressedKeysTriggerAnyShortcut += HasAnyEntriesHandler; // Need to reinitialize after project load if we want menu items EditorApplication.projectWasLoaded += InitializeController; } + static bool HasAnyEntriesHandler() + { + return instance.HasAnyEntries(Event.current); + } + static void EventHandler() { instance.contextManager.SetFocusedWindow(EditorWindow.focusedWindow); @@ -67,6 +73,11 @@ internal void Initialize(IShortcutProfileManager sender) m_Trigger = new Trigger(directory, new ConflictResolver()); } + internal bool HasAnyEntries(Event evt) + { + return m_Trigger.HasAnyEntries(); + } + internal void HandleKeyEvent(Event evt) { m_Trigger.HandleKeyEvent(evt, contextManager); diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index 3aaf584b68..b388a2588a 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -130,6 +130,11 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) } } + public bool HasAnyEntries() + { + return m_Entries.Any(); + } + // filtered entries are expected to all be in the same context and/or null context and they all are known to share the prefix bool HasConflicts(List filteredEntries, List prefix) { diff --git a/Modules/Tilemap/Managed/GridBrushBase.cs b/Modules/Tilemap/Managed/GridBrushBase.cs index 73c38221d0..9b7bf651bb 100644 --- a/Modules/Tilemap/Managed/GridBrushBase.cs +++ b/Modules/Tilemap/Managed/GridBrushBase.cs @@ -49,5 +49,8 @@ public virtual void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsIn public virtual void Move(GridLayout gridLayout, GameObject brushTarget, BoundsInt from, BoundsInt to) {} public virtual void MoveStart(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) {} public virtual void MoveEnd(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) {} + + public virtual void ChangeZPosition(int change) {} + public virtual void ResetZPosition() {} } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs index 9e14183cba..978133932c 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs @@ -453,6 +453,7 @@ public override int GetHashCode() { hash = tile != null ? tile.GetInstanceID() : 0; hash = hash * 33 + matrix.GetHashCode(); + hash = hash * 33 + matrix.rotation.GetHashCode(); hash = hash * 33 + color.GetHashCode(); } return hash; diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs index 80d520831b..72ceacb7d1 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs @@ -56,6 +56,12 @@ internal static void OnPaintSceneGUIInternal(GridLayout gridLayout, GameObject b } GridEditorUtility.DrawGridMarquee(gridLayout, position, color); + if (position.zMin != 0) + { + var zeroBounds = position; + zeroBounds.zMin = 0; + GridEditorUtility.DrawGridMarquee(gridLayout, zeroBounds, Color.blue); + } } } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs index 74278db16c..fcdb778094 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteClipboard.cs @@ -353,7 +353,7 @@ protected override void OnDisable() public override void OnGUI() { - if (guiRect.width == 0f || guiRect.height == 0f) + if (Mathf.Approximately(guiRect.width, 0f) || Mathf.Approximately(guiRect.height, 0f)) return; UpdateMouseGridPosition(); @@ -389,7 +389,7 @@ public override void OnGUI() public void OnViewSizeChanged(Rect oldSize, Rect newSize) { - if (oldSize.height * oldSize.width * newSize.height * newSize.width == 0f) + if (Mathf.Approximately(oldSize.height * oldSize.width * newSize.height * newSize.width, 0f)) return; Camera cam = previewUtility.camera; @@ -625,13 +625,13 @@ private void RenderDragAndDropPreview() RectInt rect = TileDragAndDrop.GetMinMaxRect(m_HoverData.Keys.ToList()); rect.position += mouseGridPosition; DragAndDrop.visualMode = DragAndDropVisualMode.Copy; - GridEditorUtility.DrawGridMarquee(grid, new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.width, rect.height, 1)), Color.white); + GridEditorUtility.DrawGridMarquee(grid, new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.width, rect.height, 1)), Color.white); } private void RenderGrid() { // MeshTopology.Lines doesn't give nice pixel perfect grid so we have to have separate codepath with MeshTopology.Quads specially for palette window here - if (m_GridMesh == null && grid.cellLayout == Grid.CellLayout.Rectangle) + if (m_GridMesh == null && grid.cellLayout == GridLayout.CellLayout.Rectangle) m_GridMesh = GridEditorUtility.GenerateCachedGridMesh(grid, k_GridColor, 1f / LocalToScreenRatio(), paddedBoundsInt, MeshTopology.Quads); GridEditorUtility.DrawGridGizmo(grid, grid.transform, k_GridColor, ref m_GridMesh, ref m_GridMaterial); @@ -750,7 +750,7 @@ public void SetEditorPreviewTile(Tilemap tilemap, Vector2Int position, TileBase public void SetTile(Tilemap tilemap, Vector2Int position, TileBase tile, Color color, Matrix4x4 matrix) { - Vector3Int pos3 = new Vector3Int(position.x, position.y, 0); + Vector3Int pos3 = new Vector3Int(position.x, position.y, zPosition); tilemap.SetTile(pos3, tile); tilemap.SetColor(pos3, color); tilemap.SetTransformMatrix(pos3, matrix); @@ -809,7 +809,7 @@ protected override void PickBrush(BoundsInt position, Vector3Int pickingStart) gridBrush.Pick(grid, brushTarget, position, pickingStart); if (!PaintableGrid.InGridEditMode()) - EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridPainting, new Bounds(), GridPaintingState.instance); + EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridPainting, GridPaintingState.instance); m_ActivePick = new RectInt(position.min.x, position.min.y, position.size.x, position.size.y); } @@ -873,7 +873,7 @@ private void PingTileAsset(RectInt rect) // Only able to ping asset if only one asset is selected if (rect.size == Vector2Int.zero && tilemap != null) { - TileBase tile = tilemap.GetTile(new Vector3Int(rect.xMin, rect.yMin, 0)); + TileBase tile = tilemap.GetTile(new Vector3Int(rect.xMin, rect.yMin, zPosition)); EditorGUIUtility.PingObject(tile); Selection.activeObject = tile; } @@ -931,29 +931,6 @@ protected void DrawSelectionGizmo(RectInt rect) private void HandleMouseEnterLeave() { - if (Event.current.type == EventType.MouseEnterWindow) - { - if (PaintableGrid.InGridEditMode()) - { - GridPaintingState.activeGrid = this; - Event.current.Use(); - } - } - else if (Event.current.type == EventType.MouseLeaveWindow) - { - if (m_PreviousMousePosition.HasValue && guiRect.Contains(m_PreviousMousePosition.Value) && GridPaintingState.activeBrushEditor != null) - { - GridPaintingState.activeBrushEditor.OnMouseLeave(); - } - m_PreviousMousePosition = null; - if (PaintableGrid.InGridEditMode()) - { - GridPaintingState.activeGrid = null; - Event.current.Use(); - Repaint(); - } - } - if (guiRect.Contains(Event.current.mousePosition)) { if (m_PreviousMousePosition.HasValue && !guiRect.Contains(m_PreviousMousePosition.Value) || !m_PreviousMousePosition.HasValue) @@ -998,7 +975,7 @@ private void CallOnPaintSceneGUI(Vector2Int position) rect = new RectInt(GridSelection.position.xMin, GridSelection.position.yMin, GridSelection.position.size.x, GridSelection.position.size.y); var gridLayout = tilemap != null ? tilemap as GridLayout : grid as GridLayout; - BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, 0), new Vector3Int(rect.width, rect.height, 1)); + BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, zPosition), new Vector3Int(rect.width, rect.height, 1)); if (GridPaintingState.activeBrushEditor != null) GridPaintingState.activeBrushEditor.OnPaintSceneGUI(gridLayout, brushTarget, brushBounds, EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs index 04dc841fa8..4cf48e9b5b 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs @@ -97,6 +97,8 @@ static class Styles public static readonly GUIContent tilePalette = EditorGUIUtility.TrTextContent("Tile Palette"); public static readonly GUIContent edit = EditorGUIUtility.TrTextContent("Edit"); public static readonly GUIContent editModified = EditorGUIUtility.TrTextContent("Edit*"); + public static readonly GUIContent zPosition = EditorGUIUtility.TrTextContent("Z Position"); + public static readonly GUIContent resetZPosition = EditorGUIUtility.TrTextContent("Reset"); public static readonly GUIStyle ToolbarTitleStyle = "Toolbar"; public static readonly GUIStyle dragHandle = "RL DragHandle"; public static readonly float dragPadding = 3f; @@ -280,6 +282,31 @@ static void FlipBrushY() FlipBrush(GridBrush.FlipAxis.Y); } + static void ChangeBrushZ(int change) + { + GridPaintingState.gridBrush.ChangeZPosition(change); + GridPaintingState.activeGrid.ChangeZPosition(change); + GridPaintingState.activeGrid.Repaint(); + foreach (var window in GridPaintPaletteWindow.instances) + { + window.Repaint(); + } + } + + [Shortcut("Grid Painting/Increase Z", typeof(ShortcutContext), "-")] + static void IncreaseBrushZ() + { + if (GridPaintingState.gridBrush != null && GridPaintingState.activeGrid != null) + ChangeBrushZ(1); + } + + [Shortcut("Grid Painting/Decrease Z", typeof(ShortcutContext), "=")] + static void DecreaseBrushZ() + { + if (GridPaintingState.gridBrush != null && GridPaintingState.activeGrid != null) + ChangeBrushZ(-1); + } + [SettingsProvider] internal static SettingsProvider CreateSettingsProvider() { @@ -556,7 +583,9 @@ public void SavePalette() GridPaintingState.savingPalette = true; SetHideFlagsRecursivelyIgnoringTilemapChildren(paletteInstance, HideFlags.HideInHierarchy); string path = AssetDatabase.GetAssetPath(palette); + #pragma warning disable CS0618 // Type or member is obsolete PrefabUtility.ReplacePrefabAssetNameBased(paletteInstance, path, true); + #pragma warning restore CS0618 // Type or member is obsolete SetHideFlagsRecursivelyIgnoringTilemapChildren(paletteInstance, HideFlags.HideAndDontSave); GridPaintingState.savingPalette = false; } @@ -688,6 +717,7 @@ public void OnEnable() GridPaintingState.brushChanged += OnBrushChanged; SceneView.onSceneGUIDelegate += OnSceneViewGUI; PrefabUtility.prefabInstanceUpdated += PrefabInstanceUpdated; + EditorApplication.projectWasLoaded += OnProjectLoaded; AssetPreview.SetPreviewTextureCacheSize(256, GetInstanceID()); wantsMouseMove = true; @@ -726,6 +756,12 @@ private void PrefabInstanceUpdated(GameObject updatedPrefab) } } + private void OnProjectLoaded() + { + // ShortcutIntegration instance is recreated after LoadLayout which wipes the OnEnable registration + ShortcutIntegration.instance.contextManager.RegisterToolContext(m_ShortcutContext); + } + private void OnBrushChanged(GridBrushBase brush) { DisableFocus(); @@ -774,6 +810,7 @@ public void OnDisable() GridPaintingState.brushChanged -= OnBrushChanged; GridPaintingState.UnregisterPainterInterest(this); PrefabUtility.prefabInstanceUpdated -= PrefabInstanceUpdated; + EditorApplication.projectWasLoaded -= OnProjectLoaded; ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_ShortcutContext); } @@ -787,7 +824,7 @@ private void OnScenePaintTargetChanged(GameObject scenePaintTarget) public void ChangeToTool(GridBrushBase.Tool tool) { - EditMode.ChangeEditMode(PaintableGrid.BrushToolToEditMode(tool), new Bounds(Vector3.zero, Vector3.positiveInfinity), GridPaintingState.instance); + EditMode.ChangeEditMode(PaintableGrid.BrushToolToEditMode(tool), GridPaintingState.instance); Repaint(); } @@ -838,12 +875,18 @@ private void CallOnToolDeactivated() } } + internal void ResetZPosition() + { + GridPaintingState.gridBrush.ResetZPosition(); + GridPaintingState.lastActiveGrid.ResetZPosition(); + } + private void OnBrushInspectorGUI() { - var brush = GridPaintingState.gridBrush; - if (brush == null) + if (GridPaintingState.gridBrush == null) return; + // Brush Inspector GUI EditorGUI.BeginChangeCheck(); if (GridPaintingState.activeBrushEditor != null) GridPaintingState.activeBrushEditor.OnPaintInspectorGUI(); @@ -853,6 +896,25 @@ private void OnBrushInspectorGUI() { GridPaletteBrushes.ActiveGridBrushAssetChanged(); } + + // Z Position Inspector + var hasLastActiveGrid = GridPaintingState.lastActiveGrid != null; + using (new EditorGUI.DisabledScope(!hasLastActiveGrid)) + { + EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); + var zPosition = EditorGUILayout.DelayedIntField(Styles.zPosition, hasLastActiveGrid ? GridPaintingState.lastActiveGrid.zPosition : 0); + if (EditorGUI.EndChangeCheck()) + { + GridPaintingState.gridBrush.ChangeZPosition(zPosition - GridPaintingState.lastActiveGrid.zPosition); + GridPaintingState.lastActiveGrid.zPosition = zPosition; + } + if (GUILayout.Button(Styles.resetZPosition)) + { + ResetZPosition(); + } + EditorGUILayout.EndHorizontal(); + } } private bool IsObjectPrefabInstance(Object target) @@ -938,19 +1000,19 @@ private void SelectTarget(int i, object o) var option = EditorUtility.DisplayDialogComplex(TilePaletteProperties.targetEditModeDialogTitle , TilePaletteProperties.targetEditModeDialogMessage , TilePaletteProperties.targetEditModeDialogYes - , TilePaletteProperties.targetEditModeDialogChange - , TilePaletteProperties.targetEditModeDialogNo); + , TilePaletteProperties.targetEditModeDialogNo + , TilePaletteProperties.targetEditModeDialogChange); switch (option) { case 0: GoToPrefabMode(obj); return; case 1: - var settingsWindow = SettingsWindow.Show(SettingsScopes.User); - settingsWindow.FilterProviders(TilePaletteProperties.targetEditModeLookup); + // Do nothing here for "No" break; case 2: - // Do nothing here for "No" + var settingsWindow = SettingsWindow.Show(SettingsScopes.User); + settingsWindow.FilterProviders(TilePaletteProperties.targetEditModeLookup); break; } } @@ -1037,7 +1099,7 @@ private void OpenAddPalettePopup(Rect rect) private void OnClipboardGUI(Rect position) { - if (Event.current.type != EventType.Layout && position.Contains(Event.current.mousePosition) && GridPaintingState.activeGrid != clipboardView) + if (Event.current.type != EventType.Layout && position.Contains(Event.current.mousePosition) && GridPaintingState.activeGrid != clipboardView && clipboardView.unlocked) { GridPaintingState.activeGrid = clipboardView; SceneView.RepaintAll(); diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs index 7f25f4a305..9010374679 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs @@ -15,6 +15,7 @@ internal class GridPaintingState : ScriptableSingleton, ITool [SerializeField] private GameObject m_ScenePaintTarget; // Which GameObject in scene is considered as painting target [SerializeField] private GridBrushBase m_Brush; // Which brush will handle painting callbacks [SerializeField] private PaintableGrid m_ActiveGrid; // Grid that has painting focus (can be palette, too) + [SerializeField] private PaintableGrid m_LastActiveGrid; // Grid that last had painting focus (can be palette, too) [SerializeField] private HashSet m_InterestedPainters = new HashSet(); // A list of objects that can paint using the GridPaintingState private GameObject[] m_CachedPaintTargets = null; @@ -145,7 +146,17 @@ public static Editor fallbackEditor public static PaintableGrid activeGrid { get { return instance.m_ActiveGrid; } - set { instance.m_ActiveGrid = value; } + set + { + instance.m_ActiveGrid = value; + if (instance.m_ActiveGrid != null) + instance.m_LastActiveGrid = value; + } + } + + public static PaintableGrid lastActiveGrid + { + get { return instance.m_LastActiveGrid; } } public static bool ValidatePaintTarget(GameObject candidate) diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs index b1dced7da9..4003031a24 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs @@ -53,11 +53,13 @@ protected virtual void OnBrushPickCancelled() {} private MarqueeType m_MarqueeType = MarqueeType.None; private bool m_IsExecuting; private EditMode.SceneViewEditMode m_ModeBeforePicking; + private int m_ZPosition; public Vector2Int mouseGridPosition { get { return m_MouseGridPosition; } } public bool isPicking { get { return m_MarqueeType == MarqueeType.Pick; } } public bool isBoxing { get { return m_MarqueeType == MarqueeType.Box; } } public Grid.CellLayout cellLayout { get { return CellLayout(); } } + public int zPosition { get { return m_ZPosition; } set { m_ZPosition = value; } } protected bool executing { get { return m_IsExecuting; } set { m_IsExecuting = value && isHotControl; } } @@ -118,12 +120,17 @@ protected void UpdateMouseGridPosition() newGridPosition.y = m_MouseGridPosition.y + Math.Sign(delta.y) * k_MaxMouseCellDelta; m_PreviousMouseGridPosition = m_MouseGridPosition; m_MouseGridPosition = newGridPosition; - m_MouseGridPositionChanged = true; - m_PositionChangeRepaintDone = false; + MouseGridPositionChanged(); } } } + private void MouseGridPositionChanged() + { + m_MouseGridPositionChanged = true; + m_PositionChangeRepaintDone = false; + } + private void HandleEditModeChange() { // Handles changes in EditMode while tool is expected to be in the same mode @@ -178,7 +185,7 @@ private void HandleBrushPicking() if (evt.type == EventType.MouseDrag && isHotControl && m_MarqueeStart.HasValue && m_MarqueeType == MarqueeType.Pick && IsPickingEvent(evt)) { RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); - OnBrushPickDragged(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.size.x, rect.size.y, 1))); + OnBrushPickDragged(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.size.x, rect.size.y, 1))); Event.current.Use(); GUI.changed = true; } @@ -189,7 +196,7 @@ private void HandleBrushPicking() { RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); Vector2Int pivot = GetMarqueePivot(m_MarqueeStart.Value, mouseGridPosition); - PickBrush(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.size.x, rect.size.y, 1)), new Vector3Int(pivot.x, pivot.y, 0)); + PickBrush(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.size.x, rect.size.y, 1)), new Vector3Int(pivot.x, pivot.y, 0)); if (inEditMode && EditMode.editMode != m_ModeBeforePicking) { @@ -245,7 +252,7 @@ private void HandleSelectTool() if (evt.type == EventType.MouseUp && m_MarqueeType == MarqueeType.Select) { RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); - Select(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, 0), new Vector3Int(rect.size.x, rect.size.y, 1))); + Select(new BoundsInt(new Vector3Int(rect.xMin, rect.yMin, zPosition), new Vector3Int(rect.size.x, rect.size.y, 1))); Event.current.Use(); } if (evt.control) @@ -288,7 +295,7 @@ private void HandleMoveTool() { executing = true; BoundsInt previousRect = GridSelection.position; - BoundsInt previousBounds = new BoundsInt(new Vector3Int(previousRect.xMin, previousRect.yMin, 0), new Vector3Int(previousRect.size.x, previousRect.size.y, 1)); + BoundsInt previousBounds = new BoundsInt(new Vector3Int(previousRect.xMin, previousRect.yMin, GridSelection.position.zMin), new Vector3Int(previousRect.size.x, previousRect.size.y, 1)); Vector2Int direction = mouseGridPosition - m_PreviousMove.Value; BoundsInt pos = GridSelection.position; @@ -326,13 +333,13 @@ private void HandleBrushPaintAndErase() { if (EditMode.editMode != EditMode.SceneViewEditMode.GridEraser) EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridEraser, GridPaintingState.instance); - Erase(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, 0)); + Erase(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); } else { if (EditMode.editMode != EditMode.SceneViewEditMode.GridPainting) EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridPainting, GridPaintingState.instance); - Paint(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, 0)); + Paint(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); } Event.current.Use(); @@ -350,9 +357,9 @@ private void HandleBrushPaintAndErase() for (int i = 1; i < points.Count; i++) { if (IsErasingEvent(evt)) - Erase(new Vector3Int(points[i].x, points[i].y, 0)); + Erase(new Vector3Int(points[i].x, points[i].y, zPosition)); else - Paint(new Vector3Int(points[i].x, points[i].y, 0)); + Paint(new Vector3Int(points[i].x, points[i].y, zPosition)); } Event.current.Use(); GUI.changed = true; @@ -405,7 +412,7 @@ private void HandleFloodFill() { executing = false; RegisterUndo(); - FloodFill(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, 0)); + FloodFill(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); GUI.changed = true; Event.current.Use(); GUIUtility.hotControl = 0; @@ -442,9 +449,9 @@ private void HandleBoxTool() RegisterUndo(); RectInt rect = GridEditorUtility.GetMarqueeRect(m_MarqueeStart.Value, mouseGridPosition); if (evt.shift) - BoxErase(new BoundsInt(rect.x, rect.y, 0, rect.size.x, rect.size.y, 1)); + BoxErase(new BoundsInt(rect.x, rect.y, zPosition, rect.size.x, rect.size.y, 1)); else - BoxFill(new BoundsInt(rect.x, rect.y, 0, rect.size.x, rect.size.y, 1)); + BoxFill(new BoundsInt(rect.x, rect.y, zPosition, rect.size.x, rect.size.y, 1)); Event.current.Use(); executing = false; GUI.changed = true; @@ -464,6 +471,23 @@ private Vector2Int GetMarqueePivot(Vector2Int start, Vector2Int end) return pivot; } + public void ChangeZPosition(int change) + { + m_ZPosition += change; + MouseGridPositionChanged(); + Repaint(); + } + + public void ResetZPosition() + { + if (m_ZPosition == 0) + return; + + m_ZPosition = 0; + MouseGridPositionChanged(); + Repaint(); + } + public static bool InGridEditMode() { return diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs index f8f53f27df..4e5f28982b 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs @@ -320,16 +320,16 @@ void CallOnPaintSceneGUI() rect = new RectInt(GridSelection.position.xMin, GridSelection.position.yMin, GridSelection.position.size.x, GridSelection.position.size.y); var layoutGrid = tilemap != null ? tilemap as GridLayout : grid as GridLayout; - + BoundsInt brushBounds = new BoundsInt(new Vector3Int(rect.x, rect.y, zPosition), new Vector3Int(rect.width, rect.height, 1)); if (GridPaintingState.activeBrushEditor != null) { - GridPaintingState.activeBrushEditor.OnPaintSceneGUI(layoutGrid, brushTarget, - new BoundsInt(new Vector3Int(rect.x, rect.y, 0), new Vector3Int(rect.width, rect.height, 1)), - EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); + GridPaintingState.activeBrushEditor.OnPaintSceneGUI(layoutGrid, brushTarget, brushBounds + , EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); } else // Fallback when user hasn't defined custom editor { - GridBrushEditorBase.OnPaintSceneGUIInternal(layoutGrid, brushTarget, new BoundsInt(new Vector3Int(rect.x, rect.y, 0), new Vector3Int(rect.width, rect.height, 1)), EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); + GridBrushEditorBase.OnPaintSceneGUIInternal(layoutGrid, brushTarget, brushBounds + , EditModeToBrushTool(EditMode.editMode), m_MarqueeStart.HasValue || executing); } } diff --git a/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs b/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs index 36b436c627..292b2177bc 100644 --- a/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs +++ b/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs @@ -30,8 +30,10 @@ private static class Styles public static readonly GUIContent tilemapColorLabel = EditorGUIUtility.TrTextContent("Color", "Color tinting all Sprites from tiles in the tilemap"); public static readonly GUIContent tileAnchorLabel = EditorGUIUtility.TrTextContent("Tile Anchor", "Anchoring position for Sprites from tiles in the tilemap"); public static readonly GUIContent orientationLabel = EditorGUIUtility.TrTextContent("Orientation", "Orientation for tiles in the tilemap"); - public static readonly GUIContent pointTopHexagonCreateUndo = EditorGUIUtility.TrTextContent("Hexagonal Point Top Tilemap"); - public static readonly GUIContent flatTopHexagonCreateUndo = EditorGUIUtility.TrTextContent("Hexagonal Flat Top Tilemap"); + public static readonly string pointTopHexagonCreateUndo = L10n.Tr("Hexagonal Point Top Tilemap"); + public static readonly string flatTopHexagonCreateUndo = L10n.Tr("Hexagonal Flat Top Tilemap"); + public static readonly string isometricCreateUndo = L10n.Tr("Isometric Tilemap"); + public static readonly string isometricZAsYCreateUndo = L10n.Tr("Isometric Z As Y Tilemap"); } private void OnEnable() @@ -89,17 +91,28 @@ internal static void CreateRectangularTilemap() [MenuItem("GameObject/2D Object/Hexagonal Point Top Tilemap")] internal static void CreateHexagonalPointTopTilemap() { - CreateHexagonalTilemap(GridLayout.CellSwizzle.XYZ, Styles.pointTopHexagonCreateUndo.text); + CreateHexagonalTilemap(GridLayout.CellSwizzle.XYZ, Styles.pointTopHexagonCreateUndo); } [MenuItem("GameObject/2D Object/Hexagonal Flat Top Tilemap")] internal static void CreateHexagonalFlatTopTilemap() { - CreateHexagonalTilemap(GridLayout.CellSwizzle.YXZ, Styles.flatTopHexagonCreateUndo.text); + CreateHexagonalTilemap(GridLayout.CellSwizzle.YXZ, Styles.flatTopHexagonCreateUndo); } [MenuItem("GameObject/2D Object/Isometric Tilemap")] internal static void CreateIsometricTilemap() + { + CreateIsometricTilemap(GridLayout.CellLayout.Isometric, Styles.isometricCreateUndo); + } + + [MenuItem("GameObject/2D Object/Isometric Z As Y Tilemap")] + internal static void CreateIsometricZAsYTilemap() + { + CreateIsometricTilemap(GridLayout.CellLayout.IsometricZAsY, Styles.isometricZAsYCreateUndo); + } + + private static void CreateIsometricTilemap(GridLayout.CellLayout isometricLayout, string undoMessage) { var root = FindOrCreateRootGrid(); var uniqueName = GameObjectUtility.GetUniqueNameForSibling(root.transform, "Tilemap"); @@ -108,12 +121,16 @@ internal static void CreateIsometricTilemap() tilemapGO.transform.position = Vector3.zero; var grid = root.GetComponent(); - grid.cellLayout = Grid.CellLayout.Isometric; - grid.cellSize = new Vector3(1.0f, 0.5f, 0.0f); + // Case 1071703: Do not reset cell size if adding a new Tilemap to an existing Grid of the same layout + if (isometricLayout != grid.cellLayout) + { + grid.cellLayout = isometricLayout; + grid.cellSize = new Vector3(1.0f, 0.5f, 0.0f); + } var tilemapRenderer = tilemapGO.GetComponent(); tilemapRenderer.sortOrder = TilemapRenderer.SortOrder.TopRight; - Undo.RegisterCreatedObjectUndo(tilemapGO, "Create Isometric Tilemap"); + Undo.RegisterCreatedObjectUndo(tilemapGO, undoMessage); } private static void CreateHexagonalTilemap(GridLayout.CellSwizzle swizzle, string undoMessage) diff --git a/Modules/TreeEditor/TreeEditor.cs b/Modules/TreeEditor/TreeEditor.cs index 23a43f22f9..8ee5d00614 100644 --- a/Modules/TreeEditor/TreeEditor.cs +++ b/Modules/TreeEditor/TreeEditor.cs @@ -310,8 +310,6 @@ static void CreateNewTree(MenuCommand menuCommand) AssetDatabase.AddObjectToAsset(materialCutoutAsset, prefabAsset); AssetDatabase.AddObjectToAsset(data, prefabAsset); - PrefabUtility.ApplyPrefabInstance(prefabInstance); - GameObjectUtility.SetParentAndAlign(prefabInstance, menuCommand.context as GameObject); // Store Creation undo diff --git a/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs b/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs index 5bd23f2bf8..56e7db50de 100644 --- a/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs +++ b/Modules/UnityEditorAnalyticsEditor/EditorAnalytics.bindings.cs @@ -83,6 +83,8 @@ internal static bool SendCollabOperation(object parameters) return EditorAnalytics.SendEvent("collabOperation", parameters); } + internal extern static bool SendAssetDownloadEvent(object parameters); + public extern static bool enabled { get; diff --git a/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs b/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs index dbc8c4accb..75c3447496 100644 --- a/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs +++ b/Modules/UnityWebRequestAudio/Public/DownloadHandlerAudio.bindings.cs @@ -40,6 +40,7 @@ protected override string GetText() throw new System.NotSupportedException("String access is not supported for audio clips"); } + [NativeThrows] public extern AudioClip audioClip { get; } public extern bool streamAudio { get; set; } diff --git a/Modules/XR/ScriptBindings/XRInput.bindings.cs b/Modules/XR/ScriptBindings/XRInput.bindings.cs index 461c5f7a68..b836986d97 100644 --- a/Modules/XR/ScriptBindings/XRInput.bindings.cs +++ b/Modules/XR/ScriptBindings/XRInput.bindings.cs @@ -20,13 +20,11 @@ public struct HapticCapabilities : IEquatable bool m_SupportsImpulse; bool m_SupportsBuffer; uint m_BufferFrequencyHz; - uint m_BufferMaxSize; public uint numChannels { get { return m_NumChannels; } internal set { m_NumChannels = value; } } public bool supportsImpulse { get { return m_SupportsImpulse; } internal set { m_SupportsImpulse = value; } } public bool supportsBuffer { get { return m_SupportsBuffer; } internal set { m_SupportsBuffer = value; } } public uint bufferFrequencyHz { get { return m_BufferFrequencyHz; } internal set { m_BufferFrequencyHz = value; } } - public uint bufferMaxSize { get { return m_BufferMaxSize; } internal set { m_BufferMaxSize = value; } } public override bool Equals(object obj) { @@ -41,8 +39,7 @@ public bool Equals(HapticCapabilities other) return numChannels == other.numChannels && supportsImpulse == other.supportsImpulse && supportsBuffer == other.supportsBuffer && - bufferFrequencyHz == other.bufferFrequencyHz && - bufferMaxSize == other.bufferMaxSize; + bufferFrequencyHz == other.bufferFrequencyHz; } public override int GetHashCode() @@ -50,68 +47,78 @@ public override int GetHashCode() return numChannels.GetHashCode() ^ (supportsImpulse.GetHashCode() << 1) ^ (supportsBuffer.GetHashCode() >> 1) ^ - (bufferFrequencyHz.GetHashCode() << 2) ^ - (bufferMaxSize.GetHashCode() >> 2); + (bufferFrequencyHz.GetHashCode() << 2); + } + + public static bool operator==(HapticCapabilities a, HapticCapabilities b) + { + return a.Equals(b); + } + + public static bool operator!=(HapticCapabilities a, HapticCapabilities b) + { + return !(a == b); } } + [UsedByNativeCode] [StructLayout(LayoutKind.Sequential)] [NativeConditional("ENABLE_VR")] - public struct HapticState : IEquatable + [NativeHeader("Modules/XR/Subsystems/Input/Public/XRInputTrackingFacade.h")] + public struct InputDevice : IEquatable { - uint m_SamplesQueued; - uint m_SamplesAvailable; + private UInt64 m_DeviceId; - public uint samplesQueued { get { return m_SamplesQueued; } internal set { m_SamplesQueued = value; } } - public uint samplesAvailable { get { return m_SamplesAvailable; } internal set { m_SamplesAvailable = value; } } + internal InputDevice(UInt64 deviceId) { m_DeviceId = deviceId; } + + public bool IsValid { get { return InputTracking.IsDeviceValid(m_DeviceId); } } + + // Haptics + public bool SendHapticImpulse(uint channel, float amplitude, float duration = 1.0f) { return InputTracking.SendHapticImpulse(m_DeviceId, channel, amplitude, duration); } + public bool SendHapticBuffer(uint channel, byte[] buffer) { return InputTracking.SendHapticBuffer(m_DeviceId, channel, buffer); } + public bool TryGetHapticCapabilities(out HapticCapabilities capabilities) { return InputTracking.TryGetHapticCapabilities(m_DeviceId, out capabilities); } + public void StopHaptics() { InputTracking.StopHaptics(m_DeviceId); } public override bool Equals(object obj) { - if (!(obj is HapticState)) + if (!(obj is InputDevice)) return false; - return Equals((HapticState)obj); + return Equals((InputDevice)obj); } - public bool Equals(HapticState other) + public bool Equals(InputDevice other) { - return samplesQueued == other.samplesQueued && - samplesAvailable == other.samplesAvailable; + return m_DeviceId == other.m_DeviceId; } public override int GetHashCode() { - return samplesQueued.GetHashCode() ^ (samplesAvailable.GetHashCode() << 2); + return m_DeviceId.GetHashCode(); + } + + public static bool operator==(InputDevice a, InputDevice b) + { + return a.Equals(b); + } + + public static bool operator!=(InputDevice a, InputDevice b) + { + return !(a == b); } } [NativeHeader("Modules/XR/Subsystems/Input/Public/XRInputTrackingFacade.h")] [NativeConditional("ENABLE_VR")] [StaticAccessor("XRInputTrackingFacade::Get()", StaticAccessorType.Dot)] - public partial class InputHaptic + public partial class InputDevices { - [NativeConditional("ENABLE_VR")] - bool SendImpulse(XRNode node, uint channel, float amplitude) { return SendImpulse(node, channel, amplitude, 1.0f); } - - [NativeConditional("ENABLE_VR")] - [NativeMethod("SendHapticImpulse")] - extern public static bool SendImpulse(XRNode node, uint channel, float amplitude, [UnityEngine.Internal.DefaultValue("1.0f")] float frequency); - - [NativeConditional("ENABLE_VR")] - [NativeMethod("SendHapticBuffer")] - extern public static bool SendBuffer(XRNode node, uint channel, byte[] buffer); - - [NativeConditional("ENABLE_VR", "false")] - [NativeMethod("TryGetHapticCapabilities")] - extern public static bool TryGetCapabilities(XRNode node, out HapticCapabilities capabilities); - - [NativeConditional("ENABLE_VR", "false")] - [NativeMethod("TryGetHapticState")] - extern public static bool TryGetState(XRNode node, out HapticState state); - - [NativeConditional("ENABLE_VR")] - [NativeMethod("StopHaptics")] - extern public static void Stop(XRNode node); + [NativeConditional("ENABLE_VR", "InputDevice::Identity")] + public static InputDevice GetDeviceAtXRNode(XRNode node) + { + UInt64 deviceId = InputTracking.GetDeviceIdAtXRNode(node); + return new InputDevice(deviceId); + } } [NativeHeader("Modules/XR/Subsystems/Input/Public/XRInputTrackingFacade.h")] @@ -156,5 +163,13 @@ extern public static bool disablePositionalTracking [NativeName("SetPositionalTrackingDisabled")] set; } + + internal static extern bool SendHapticImpulse(UInt64 deviceId, uint channel, float amplitude, float duration); + internal static extern bool SendHapticBuffer(UInt64 deviceId, uint channel, byte[] buffer); + internal static extern bool TryGetHapticCapabilities(UInt64 deviceId, out HapticCapabilities capabilities); + internal static extern void StopHaptics(UInt64 deviceId); + + internal static extern bool IsDeviceValid(UInt64 deviceId); + internal static extern UInt64 GetDeviceIdAtXRNode(XRNode node); } } diff --git a/README.md b/README.md index b8559e74df..f414498bbd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0a11 C# reference source code +## Unity 2018.3.0b1 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Camera.bindings.cs b/Runtime/Export/Camera.bindings.cs index a34e8b2ccf..c27dd8219c 100644 --- a/Runtime/Export/Camera.bindings.cs +++ b/Runtime/Export/Camera.bindings.cs @@ -274,7 +274,7 @@ public bool RenderToCubemap(RenderTexture cubemap, int faceMask, MonoOrStereosco public void AddCommandBuffer(CameraEvent evt, CommandBuffer buffer) { - if (!Enum.IsDefined(typeof(CameraEvent), evt)) + if (!Rendering.CameraEventUtils.IsValid(evt)) throw new ArgumentException(string.Format(@"Invalid CameraEvent value ""{0}"".", (int)evt), "evt"); if (buffer == null) throw new NullReferenceException("buffer is null"); AddCommandBufferImpl(evt, buffer); @@ -282,7 +282,7 @@ public void AddCommandBuffer(CameraEvent evt, CommandBuffer buffer) public void AddCommandBufferAsync(CameraEvent evt, CommandBuffer buffer, ComputeQueueType queueType) { - if (!Enum.IsDefined(typeof(CameraEvent), evt)) + if (!Rendering.CameraEventUtils.IsValid(evt)) throw new ArgumentException(string.Format(@"Invalid CameraEvent value ""{0}"".", (int)evt), "evt"); if (buffer == null) throw new NullReferenceException("buffer is null"); AddCommandBufferAsyncImpl(evt, buffer, queueType); @@ -290,7 +290,7 @@ public void AddCommandBufferAsync(CameraEvent evt, CommandBuffer buffer, Compute public void RemoveCommandBuffer(CameraEvent evt, CommandBuffer buffer) { - if (!Enum.IsDefined(typeof(CameraEvent), evt)) + if (!Rendering.CameraEventUtils.IsValid(evt)) throw new ArgumentException(string.Format(@"Invalid CameraEvent value ""{0}"".", (int)evt), "evt"); if (buffer == null) throw new NullReferenceException("buffer is null"); RemoveCommandBufferImpl(evt, buffer); diff --git a/Runtime/Export/GI/DynamicGI.bindings.cs b/Runtime/Export/GI/DynamicGI.bindings.cs index 04a31065e6..b4e134a2a3 100644 --- a/Runtime/Export/GI/DynamicGI.bindings.cs +++ b/Runtime/Export/GI/DynamicGI.bindings.cs @@ -12,10 +12,13 @@ public sealed partial class DynamicGI { public static float indirectScale { get { return 0.0f; } set {} } public static float updateThreshold { get { return 0.0f; } set {} } + public static int materialUpdateTimeSlice { get { return 0; } set {} } public static void SetEmissive(Renderer renderer, Color color) {} public static void SetEnvironmentData(float[] input) {} public static bool synchronousMode { get { return false; } set {} } public static bool isConverged { get { return false; } } + + internal static int scheduledMaterialUpdatesCount { get { return 0; } } public static extern void UpdateEnvironment(); [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] diff --git a/Runtime/Export/GraphicsEnums.cs b/Runtime/Export/GraphicsEnums.cs index 1546184f20..b1ac63f5e6 100644 --- a/Runtime/Export/GraphicsEnums.cs +++ b/Runtime/Export/GraphicsEnums.cs @@ -961,6 +961,17 @@ public enum CameraEvent AfterHaloAndLensFlares } + internal static class CameraEventUtils + { + const CameraEvent k_MinimumValue = CameraEvent.BeforeDepthTexture; + const CameraEvent k_MaximumValue = CameraEvent.AfterHaloAndLensFlares; + + public static bool IsValid(CameraEvent value) + { + return value >= k_MinimumValue && value <= k_MaximumValue; + } + } + // Keep in sync with RenderLightEventType in Runtime/Graphics/CommandBuffer/RenderingEvents.h public enum LightEvent { diff --git a/Runtime/Export/SystemInfo.bindings.cs b/Runtime/Export/SystemInfo.bindings.cs index 6125bb74a1..23fa6dc4ed 100644 --- a/Runtime/Export/SystemInfo.bindings.cs +++ b/Runtime/Export/SystemInfo.bindings.cs @@ -214,6 +214,11 @@ public static bool graphicsMultiThreaded get { return GetGraphicsMultiThreaded(); } } + public static bool hasHiddenSurfaceRemovalOnGPU + { + get { return HasHiddenSurfaceRemovalOnGPU(); } + } + // Are built-in shadows supported? (RO) public static bool supportsShadows { @@ -527,6 +532,9 @@ public static int graphicsPixelFillrate [FreeFunction("ScriptingGraphicsCaps::GetGraphicsMultiThreaded")] static extern bool GetGraphicsMultiThreaded(); + [FreeFunction("ScriptingGraphicsCaps::HasHiddenSurfaceRemovalOnGPU")] + static extern bool HasHiddenSurfaceRemovalOnGPU(); + [FreeFunction("ScriptingGraphicsCaps::SupportsShadows")] static extern bool SupportsShadows(); diff --git a/Runtime/Export/Vector3Int.cs b/Runtime/Export/Vector3Int.cs index d7871a42a8..15e21aa1f8 100644 --- a/Runtime/Export/Vector3Int.cs +++ b/Runtime/Export/Vector3Int.cs @@ -177,7 +177,9 @@ public bool Equals(Vector3Int other) public override int GetHashCode() { - return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2); + var yHash = y.GetHashCode(); + var zHash = z.GetHashCode(); + return x.GetHashCode() ^ (yHash << 4) ^ (yHash >> 28) ^ (zHash >> 4) ^ (zHash << 28); } public override string ToString() diff --git a/Runtime/Networking/Managed/MatchMakingClient.cs b/Runtime/Networking/Managed/MatchMakingClient.cs index 79df91f44d..4725689b0a 100644 --- a/Runtime/Networking/Managed/MatchMakingClient.cs +++ b/Runtime/Networking/Managed/MatchMakingClient.cs @@ -12,6 +12,7 @@ namespace UnityEngine.Networking.Match { // returned when you create or join a match (private info) //[Serializable] //TODO: enabled this when 64 bit enum issue is resolved + [Obsolete("The matchmaker and relay feature will be removed in the future, minimal support will continue until this can be safely done.")] public class MatchInfo { public string address { get; private set; } @@ -53,6 +54,7 @@ public override string ToString() } } + [Obsolete("The matchmaker and relay feature will be removed in the future, minimal support will continue until this can be safely done.")] public class MatchInfoSnapshot { public NetworkID networkId { get; private set; } @@ -109,6 +111,7 @@ internal MatchInfoSnapshot(MatchDesc matchDesc) } } + [Obsolete("The matchmaker and relay feature will be removed in the future, minimal support will continue until this can be safely done.")] public class NetworkMatch : MonoBehaviour { public delegate void BasicResponseDelegate(bool success, string extendedInfo); @@ -137,11 +140,9 @@ public Coroutine CreateMatch(string matchName, uint matchSize, bool matchAdverti Debug.LogError("Matchmaking is not supported on WebGL player."); return null; } - else - return CreateMatch(new CreateMatchRequest { name = matchName, size = matchSize, advertise = matchAdvertise, password = matchPassword, publicAddress = publicClientAddress, privateAddress = privateClientAddress, eloScore = eloScoreForMatch, domain = requestDomain }, callback); + return CreateMatch(new CreateMatchRequest { name = matchName, size = matchSize, advertise = matchAdvertise, password = matchPassword, publicAddress = publicClientAddress, privateAddress = privateClientAddress, eloScore = eloScoreForMatch, domain = requestDomain }, callback); } - // Begin Create a match internal Coroutine CreateMatch(CreateMatchRequest req, DataResponseDelegate callback) { if (callback == null) diff --git a/Runtime/Networking/Managed/NetworkTransportConfig.cs b/Runtime/Networking/Managed/NetworkTransportConfig.cs index 9bdf9f3b57..84450263db 100644 --- a/Runtime/Networking/Managed/NetworkTransportConfig.cs +++ b/Runtime/Networking/Managed/NetworkTransportConfig.cs @@ -68,6 +68,7 @@ public enum ConnectionAcksType }; [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class ChannelQOS { [SerializeField] @@ -105,6 +106,7 @@ public ChannelQOS(ChannelQOS channel) //to allow user manipulate channel info via property with parameter (using array interface) //all fields are defined for direct access from HLAPI (it it needed) [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class ConnectionConfig { private const int g_MinPacketSize = 128; @@ -502,6 +504,7 @@ public IList GetSharedOrderChannels(byte idx) //and array of special connection (with special configuration) //AddSpecialConnection will return connection id which user should use when he call connect to identify special configuration for this connection [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class HostTopology { [SerializeField] @@ -589,6 +592,7 @@ public int AddSpecialConnectionConfig(ConnectionConfig config) } [Serializable] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class GlobalConfig { private const uint g_MaxTimerTimeout = 12000; //before changing check UNETConfiguration.h file @@ -753,6 +757,7 @@ public Action ConnectionReadyForSend } } + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public class ConnectionSimulatorConfig : IDisposable { internal int m_OutMinDelay; diff --git a/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs b/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs index a170c1b9ed..10e043cef8 100644 --- a/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs +++ b/Runtime/Networking/ScriptBindings/UNETTransportConfig.bindings.cs @@ -13,6 +13,7 @@ namespace UnityEngine.Networking { +#pragma warning disable 618 [NativeHeader("Runtime/Networking/UNETManager.h")] [NativeHeader("Runtime/Networking/UNetTypes.h")] @@ -308,4 +309,5 @@ public void Dispose() [NativeProperty("m_MaxNetSimulatorTimeout", TargetType.Field)] private extern uint MaxNetSimulatorTimeout { set; } } +#pragma warning restore 618 } diff --git a/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs b/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs index c5eafd5400..0d8523ddf3 100644 --- a/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs +++ b/Runtime/Networking/ScriptBindings/UNETworking.bindings.cs @@ -19,6 +19,7 @@ namespace UnityEngine.Networking [NativeHeader("Runtime/Networking/UNetTypes.h")] [NativeHeader("Runtime/Networking/UNETConfiguration.h")] [NativeConditional("ENABLE_NETWORK && ENABLE_UNET", true)] + [Obsolete("The UNET transport will be removed in the future as soon a replacement is ready.")] public sealed partial class NetworkTransport { private NetworkTransport() {} diff --git a/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs b/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs index dc9144cefa..38177b0d47 100644 --- a/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs +++ b/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs @@ -61,6 +61,7 @@ public static void TakeTempSnapshot(Action finishCallback, Captur TakeSnapshot(path, finishCallback, captureFlags); } + [RequiredByNativeCode] static byte[] PrepareMetadata() { if (createMetaData == null) @@ -71,6 +72,9 @@ static byte[] PrepareMetadata() MetaData data = new MetaData(); createMetaData(data); + if (data.content == null) data.content = ""; + if (data.platform == null) data.platform = ""; + int contentLength = sizeof(char) * data.content.Length; int platformLength = sizeof(char) * data.platform.Length; @@ -164,6 +168,7 @@ private static int WriteStringToByteArray(byte[] array, int offset, string value return offset; } + [RequiredByNativeCode] static void FinalizeSnapshot(string path, bool result) { if (snapshotFinished != null) From 198807ef34ab2add31864ce43a1b84ba79b57762 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 26 Sep 2018 13:21:30 +0000 Subject: [PATCH 02/10] Unity 2018.3.0b3 C# reference source code --- .../Mono/Animation/AnimationMode.bindings.cs | 3 + .../Animation/AnimationUtility.bindings.cs | 6 + .../AnimationWindow/AddCurvesPopup.cs | 23 +- .../AddCurvesPopupHierarchy.cs | 13 +- .../AddCurvesPopupHierarchyDataSource.cs | 1 + .../AddCurvesPopupHierarchyGUI.cs | 84 ++++++- Editor/Mono/Animation/ZoomableArea.cs | 17 +- .../AssetPipeline/TextureImporter.bindings.cs | 30 ++- Editor/Mono/AssetPostprocessor.cs | 14 +- Editor/Mono/BuildPipeline/AssemblyStripper.cs | 10 - Editor/Mono/ContainerWindow.cs | 4 +- Editor/Mono/EditorWindow.cs | 15 +- Editor/Mono/GUI/ColorPicker.cs | 2 +- Editor/Mono/GUI/DockArea.cs | 48 ++-- Editor/Mono/GUI/MainView.cs | 2 +- Editor/Mono/GUI/PaneDragTab.cs | 4 +- Editor/Mono/GUI/SplitView.cs | 4 +- Editor/Mono/GUI/WindowLayout.cs | 4 +- Editor/Mono/HostView.cs | 75 +++--- .../ImportSettings/AssetImporterEditor.cs | 4 +- .../DesktopPluginImporterExtension.cs | 2 +- Editor/Mono/Inspector/AnimationClipEditor.cs | 8 +- Editor/Mono/Inspector/GameObjectInspector.cs | 105 ++++---- Editor/Mono/Inspector/InspectorWindow.cs | 2 +- .../Inspector/LightingSettingsInspector.cs | 19 +- Editor/Mono/Inspector/MaterialEditor.cs | 1 + .../Inspector/MaterialEditorGUIHelpers.cs | 4 + Editor/Mono/Menu.bindings.cs | 3 + Editor/Mono/PackageUtility.bindings.cs | 3 + .../ParticleSystemModules/InitialModuleUI.cs | 12 + .../ParticleSystemEditor/ParticleSystemUI.cs | 2 +- Editor/Mono/Prefabs/PrefabImporterEditor.cs | 13 + .../PrefabOverrides/PrefabOverridesWindow.cs | 227 ++++++++++++----- Editor/Mono/Prefabs/PrefabUtility.bindings.cs | 14 +- Editor/Mono/Prefabs/PrefabUtility.cs | 231 ++++++++++++------ Editor/Mono/ProjectBrowser.cs | 7 + .../StageManager/PrefabStage/PrefabStage.cs | 40 ++- .../LightingWindowBakeSettings.cs | 26 +- .../Mono/SceneView/SceneViewStageHandling.cs | 25 +- .../Compilers/MicrosoftCSharpCompiler.cs | 3 +- .../ScriptCompilation/EditorCompilation.cs | 4 +- .../Providers/AssetSettingsProvider.cs | 12 + Editor/Mono/Settings/SettingsService.cs | 27 +- .../Mono/SpriteEditor/SpriteEditorWindow.cs | 25 +- Editor/Mono/UIElements/Controls/CurveField.cs | 5 +- Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 10 + Modules/AI/NavMesh/NavMesh.bindings.cs | 2 +- .../ImportSettings/ModelImporterEditor.cs | 13 + Modules/IMGUI/GUIStyle.cs | 5 + Modules/PresetsEditor/PresetManagerEditor.cs | 1 + .../ShortcutManagerEditor/ConflictResolver.cs | 2 +- .../ShortcutManagerEditor/ContextManager.cs | 15 +- Modules/ShortcutManagerEditor/Directory.cs | 6 + .../IConflictResolver.cs | 2 +- Modules/ShortcutManagerEditor/Trigger.cs | 24 +- Modules/UIElements/ImmediateStylePainter.cs | 14 +- Modules/UIElements/StylePainter.cs | 4 +- Projects/CSharp/UnityEngine.csproj | 3 + README.md | 2 +- .../SpriteDataAccess.bindings.cs | 2 +- Runtime/Export/AnimationCurve.bindings.cs | 12 + .../Scripting/GarbageCollector.bindings.cs | 46 ++++ Runtime/Export/Texture.cs | 1 + .../Managed/ParticleSystem.deprecated.cs | 45 ++-- .../Managed/ParticleSystemEnums.cs | 9 + .../ScriptBindings/ParticleSystem.bindings.cs | 2 +- .../Editor/ModuleMetadataBindings.gen.cs | 8 + .../ParticleSystemBindings.gen.cs | 9 + 68 files changed, 1034 insertions(+), 386 deletions(-) create mode 100644 Runtime/Export/Scripting/GarbageCollector.bindings.cs diff --git a/Editor/Mono/Animation/AnimationMode.bindings.cs b/Editor/Mono/Animation/AnimationMode.bindings.cs index c3b411f482..2b30484c29 100644 --- a/Editor/Mono/Animation/AnimationMode.bindings.cs +++ b/Editor/Mono/Animation/AnimationMode.bindings.cs @@ -146,6 +146,9 @@ internal static void StartAnimationRecording() [NativeThrows] extern public static void AddPropertyModification(EditorCurveBinding binding, PropertyModification modification, bool keepPrefabOverride); + [NativeThrows] + extern public static void AddEditorCurveBinding([NotNull] GameObject gameObject, EditorCurveBinding binding); + [NativeThrows] extern internal static void AddTransformTR([NotNull] GameObject root, string path); diff --git a/Editor/Mono/Animation/AnimationUtility.bindings.cs b/Editor/Mono/Animation/AnimationUtility.bindings.cs index dd22c87e44..b2ede18a80 100644 --- a/Editor/Mono/Animation/AnimationUtility.bindings.cs +++ b/Editor/Mono/Animation/AnimationUtility.bindings.cs @@ -143,8 +143,14 @@ internal static EditorCurveBinding[] GetAnimatableBindings(ScriptableObject scri return Internal_GetScriptableObjectAnimatableBindings(scriptableObject); } + internal static EditorCurveBinding[] GetAdditionalAnimatorBindings(GameObject targetObject) + { + return Internal_GetAdditionalAnimatorBindings(targetObject); + } + extern private static EditorCurveBinding[] Internal_GetGameObjectAnimatableBindings([NotNull] GameObject targetObject, [NotNull] GameObject root); extern private static EditorCurveBinding[] Internal_GetScriptableObjectAnimatableBindings([NotNull] ScriptableObject scriptableObject); + extern private static EditorCurveBinding[] Internal_GetAdditionalAnimatorBindings([NotNull] GameObject targetObject); // Binds the property and returns the type of the bound value (Can be used to display special UI for it and to enforce correct drag and drop) // null if it can't be bound. diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs index 84e4b40e80..7bece927e0 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopup.cs @@ -13,6 +13,11 @@ namespace UnityEditorInternal internal class AddCurvesPopup : EditorWindow { const float k_WindowPadding = 3; + const float k_SpaceForSlider = 16; + + const float k_WindowMaxWidth = 450; + const float k_WindowMinWidth = 240; + const float k_WindowFixedHeight = 250; internal static AnimationWindowState s_State; @@ -20,16 +25,25 @@ internal class AddCurvesPopup : EditorWindow private static long s_LastClosedTime; private static AddCurvesPopupHierarchy s_Hierarchy; - private static Vector2 windowSize = new Vector2(240, 250); - public delegate void OnNewCurveAdded(AddCurvesPopupPropertyNode node); private static OnNewCurveAdded NewCurveAddedCallback; + Vector2 GetWindowSize() + { + float contentWidth = s_Hierarchy.GetContentWidth(); + float width = Mathf.Clamp(contentWidth + k_SpaceForSlider + k_WindowPadding, k_WindowMinWidth, k_WindowMaxWidth); + return new Vector2(width, k_WindowFixedHeight); + } + void Init(Rect buttonRect) { + s_Hierarchy = new AddCurvesPopupHierarchy(); + s_Hierarchy.InitIfNeeded(this, new Rect(0, 0, k_WindowMinWidth, k_WindowFixedHeight)); + buttonRect = GUIUtility.GUIToScreenRect(buttonRect); - ShowAsDropDown(buttonRect, windowSize, new[] { PopupLocation.Right }); + + ShowAsDropDown(buttonRect, GetWindowSize(), new[] { PopupLocation.Right }); } void OnEnable() @@ -77,8 +91,7 @@ internal void OnGUI() if (Event.current.type == EventType.Layout) return; - if (s_Hierarchy == null) - s_Hierarchy = new AddCurvesPopupHierarchy(); + Vector2 windowSize = GetWindowSize(); Rect rect = new Rect(1, 1, windowSize.x - k_WindowPadding, windowSize.y - k_WindowPadding); GUI.Box(new Rect(0, 0, windowSize.x, windowSize.y), GUIContent.none, "grey_border"); diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs index 3f69454e6f..4adb9ff208 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchy.cs @@ -14,9 +14,16 @@ internal class AddCurvesPopupHierarchy private TreeViewState m_TreeViewState; private AddCurvesPopupHierarchyDataSource m_TreeViewDataSource; + private float m_ContentWidth = 0f; + + public float GetContentWidth() + { + return m_ContentWidth; + } + public void OnGUI(Rect position, EditorWindow owner) { - InitIfNeeded(owner, position); + m_TreeView.SetTotalRect(position); m_TreeView.OnEvent(); m_TreeView.OnGUI(position, GUIUtility.GetControlID(FocusType.Keyboard)); } @@ -33,7 +40,7 @@ public void InitIfNeeded(EditorWindow owner, Rect rect) m_TreeView.deselectOnUnhandledMouseDown = true; m_TreeViewDataSource = new AddCurvesPopupHierarchyDataSource(m_TreeView); - TreeViewGUI gui = new AddCurvesPopupHierarchyGUI(m_TreeView, owner); + AddCurvesPopupHierarchyGUI gui = new AddCurvesPopupHierarchyGUI(m_TreeView, owner); m_TreeView.Init(rect, m_TreeViewDataSource, @@ -42,6 +49,8 @@ public void InitIfNeeded(EditorWindow owner, Rect rect) ); m_TreeViewDataSource.UpdateData(); + + m_ContentWidth = gui.GetContentWidth(); } internal virtual bool IsRenamingNodeAllowed(TreeViewItem node) diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs index b944bfb74b..5bea4058b3 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs @@ -31,6 +31,7 @@ private void SetupRootNodeSettings() public override void FetchData() { + m_RootItem = null; if (AddCurvesPopup.s_State.selection.canAddCurves) { GameObject rootGameObject = AddCurvesPopup.s_State.activeRootGameObject; diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs index 37a14c36a6..939b21cf85 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs @@ -5,6 +5,7 @@ using UnityEditor; using UnityEditor.IMGUI.Controls; using UnityEngine; +using System.Collections.Generic; namespace UnityEditorInternal { @@ -14,6 +15,7 @@ internal class AddCurvesPopupHierarchyGUI : TreeViewGUI public bool showPlusButton { get; set; } private GUIStyle plusButtonStyle = "OL Plus"; private GUIStyle plusButtonBackgroundStyle = "Tag MenuItem"; + private GUIContent addPropertiesContent = EditorGUIUtility.TrTextContent("Add Properties"); private const float plusButtonWidth = 17; public AddCurvesPopupHierarchyGUI(TreeViewController treeView, EditorWindow owner) @@ -25,7 +27,12 @@ public AddCurvesPopupHierarchyGUI(TreeViewController treeView, EditorWindow owne public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool selected, bool focused) { base.OnRowGUI(rowRect, node, row, selected, focused); + DoAddCurveButton(rowRect, node); + HandleContextMenu(rowRect, node); + } + private void DoAddCurveButton(Rect rowRect, TreeViewItem node) + { // Is it propertynode. If not, then we don't need plusButton so quit here AddCurvesPopupPropertyNode hierarchyNode = node as AddCurvesPopupPropertyNode; if (hierarchyNode == null || hierarchyNode.curveBindings == null || hierarchyNode.curveBindings.Length == 0) @@ -41,10 +48,85 @@ public override void OnRowGUI(Rect rowRect, TreeViewItem node, int row, bool sel if (GUI.Button(buttonRect, GUIContent.none, plusButtonStyle)) { AddCurvesPopup.AddNewCurve(hierarchyNode); - owner.Close(); + + // Hold shift key to add new curves and keep window opened. + if (Event.current.shift) + m_TreeView.ReloadData(); + else + owner.Close(); } } + private void HandleContextMenu(Rect rowRect, TreeViewItem node) + { + if (Event.current.type != EventType.ContextClick) + return; + + if (rowRect.Contains(Event.current.mousePosition)) + { + // Add current node to selection + var ids = new List(m_TreeView.GetSelection()); + ids.Add(node.id); + m_TreeView.SetSelection(ids.ToArray(), false, false); + + GenerateMenu().ShowAsContext(); + Event.current.Use(); + } + } + + private GenericMenu GenerateMenu() + { + GenericMenu menu = new GenericMenu(); + menu.AddItem(addPropertiesContent, false, AddPropertiesFromSelectedNodes); + + return menu; + } + + private void AddPropertiesFromSelectedNodes() + { + int[] ids = m_TreeView.GetSelection(); + for (int i = 0; i < ids.Length; ++i) + { + var node = m_TreeView.FindItem(ids[i]); + var propertyNode = node as AddCurvesPopupPropertyNode; + + if (propertyNode != null) + { + AddCurvesPopup.AddNewCurve(propertyNode); + } + else if (node.hasChildren) + { + foreach (var childNode in node.children) + { + var childPropertyNode = childNode as AddCurvesPopupPropertyNode; + if (childPropertyNode != null) + { + AddCurvesPopup.AddNewCurve(childPropertyNode); + } + } + } + } + + m_TreeView.ReloadData(); + } + + public float GetContentWidth() + { + IList rows = m_TreeView.data.GetRows(); + List allRows = new List(); + allRows.AddRange(rows); + + for (int i = 0; i < allRows.Count; ++i) + { + var row = allRows[i]; + if (row.hasChildren) + allRows.AddRange(row.children); + } + + float rowWidth = GetMaxWidth(allRows); + return rowWidth + plusButtonWidth; + } + override protected void SyncFakeItem() { //base.SyncFakeItem(); diff --git a/Editor/Mono/Animation/ZoomableArea.cs b/Editor/Mono/Animation/ZoomableArea.cs index 80017a2a7e..2bc23ff956 100644 --- a/Editor/Mono/Animation/ZoomableArea.cs +++ b/Editor/Mono/Animation/ZoomableArea.cs @@ -377,14 +377,20 @@ public void SetShownHRange(float min, float max) public void SetShownVRangeInsideMargins(float min, float max) { + float heightInsideMargins = drawRect.height - topmargin - bottommargin; + if (heightInsideMargins < kMinHeight) heightInsideMargins = kMinHeight; + + float denum = max - min; + if (denum < kMinHeight) denum = kMinHeight; + if (m_UpDirection == YDirection.Positive) { - m_Scale.y = -(drawRect.height - topmargin - bottommargin) / (max - min); + m_Scale.y = -heightInsideMargins / denum; m_Translation.y = drawRect.height - min * m_Scale.y - topmargin; } else { - m_Scale.y = (drawRect.height - topmargin - bottommargin) / (max - min); + m_Scale.y = heightInsideMargins / denum; m_Translation.y = -min * m_Scale.y - bottommargin; } EnforceScaleAndRange(); @@ -392,14 +398,17 @@ public void SetShownVRangeInsideMargins(float min, float max) public void SetShownVRange(float min, float max) { + float denum = max - min; + if (denum < kMinHeight) denum = kMinHeight; + if (m_UpDirection == YDirection.Positive) { - m_Scale.y = -drawRect.height / (max - min); + m_Scale.y = -drawRect.height / denum; m_Translation.y = drawRect.height - min * m_Scale.y; } else { - m_Scale.y = drawRect.height / (max - min); + m_Scale.y = drawRect.height / denum; m_Translation.y = -min * m_Scale.y; } EnforceScaleAndRange(); diff --git a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs index 001ec95022..90bdb7af92 100644 --- a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs @@ -20,6 +20,14 @@ namespace UnityEditor [NativeHeader("Editor/Src/EditorUserBuildSettings.h")] public sealed partial class TextureImporter : AssetImporter, ISpriteEditorDataProvider { + private string GetFixedPlatformName(string platform) + { + var targetGroup = BuildPipeline.GetBuildTargetGroupByName(platform); + if (targetGroup != BuildTargetGroup.Unknown) + return BuildPipeline.GetBuildTargetGroupName(targetGroup); + return platform; + } + [Obsolete("textureFormat is no longer accessible at the TextureImporter level. For old 'simple' formats use the textureCompression property for the equivalent automatic choice (Uncompressed for TrueColor, Compressed and HQCommpressed for 16 bits). For platform specific formats use the [[PlatformTextureSettings]] API. Using this setter will setup various parameters to match the new automatic system as well as possible. Getter will return the last value set.")] public extern TextureImporterFormat textureFormat { @@ -96,6 +104,9 @@ public bool GetPlatformTextureSettings(string platform, out int maxTextureSize, // public API will always return a valid TextureImporterPlatformSettings, creating it based on the default one if it did not exist. public TextureImporterPlatformSettings GetPlatformTextureSettings(string platform) { + // make sure we are converting the settings to use the proper BuildTargetGroupName to get them (the way it works on other importers) + platform = GetFixedPlatformName(platform); + TextureImporterPlatformSettings dest = GetPlatformTextureSetting_Internal(platform); if (platform != dest.name) { @@ -112,6 +123,7 @@ public TextureImporterPlatformSettings GetDefaultPlatformTextureSettings() public TextureImporterFormat GetAutomaticFormat(string platform) { + platform = GetFixedPlatformName(platform); TextureImporterSettings settings = new TextureImporterSettings(); ReadTextureSettings(settings); TextureImporterPlatformSettings platformSettings = GetPlatformTextureSettings(platform); @@ -161,11 +173,25 @@ public void SetPlatformTextureSettings(string platform, int maxTextureSize, Text SetPlatformTextureSettings(dest); } + [NativeName("SetPlatformTextureSettings")] + private extern void SetPlatformTextureSettings_Internal(TextureImporterPlatformSettings platformSettings); + // Set specific target platform settings - public extern void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings); + public void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings) + { + // we need to fix the name in case the user changed it to some mismatching value + platformSettings.name = GetFixedPlatformName(platformSettings.name); + SetPlatformTextureSettings_Internal(platformSettings); + } // Clear specific target platform settings - public extern void ClearPlatformTextureSettings(string platform); + [NativeName("ClearPlatformTextureSettings")] + private extern void ClearPlatformTextureSettings_Internal(string platform); + + public void ClearPlatformTextureSettings(string platform) + { + ClearPlatformTextureSettings_Internal(GetFixedPlatformName(platform)); + } [FreeFunction] internal static extern TextureImporterFormat DefaultFormatFromTextureParameters([NotNull] TextureImporterSettings settings, TextureImporterPlatformSettings platformSettings, bool doesTextureContainAlpha, bool sourceWasHDR, BuildTarget destinationPlatform); diff --git a/Editor/Mono/AssetPostprocessor.cs b/Editor/Mono/AssetPostprocessor.cs index 798978522f..00ba6ae26f 100644 --- a/Editor/Mono/AssetPostprocessor.cs +++ b/Editor/Mono/AssetPostprocessor.cs @@ -263,10 +263,10 @@ static string GetMeshProcessorsHashString() var inst = Activator.CreateInstance(assetPostprocessorClass) as AssetPostprocessor; var type = inst.GetType(); bool hasPreProcessMethod = type.GetMethod("OnPreprocessModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; - bool hasProcessMeshAssignMethod = type.GetMethod("OnProcessMeshAssingModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; + bool hasPostprocessMeshHierarchy = type.GetMethod("OnPostprocessMeshHierarchy", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; bool hasPostProcessMethod = type.GetMethod("OnPostprocessModel", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) != null; uint version = inst.GetVersion(); - if (version != 0 && (hasPreProcessMethod || hasProcessMeshAssignMethod || hasPostProcessMethod)) + if (version != 0 && (hasPreProcessMethod || hasPostprocessMeshHierarchy || hasPostProcessMethod)) { versionsByType.Add(type.FullName, version); } @@ -356,6 +356,16 @@ static bool ProcessMeshHasAssignMaterial() return false; } + [RequiredByNativeCode] + static void PostprocessMeshHierarchy(GameObject root) + { + foreach (AssetPostprocessor inst in m_ImportProcessors) + { + object[] args = { root }; + AttributeHelper.InvokeMemberIfAvailable(inst, "OnPostprocessMeshHierarchy", args); + } + } + static void PostprocessMesh(GameObject gameObject) { foreach (AssetPostprocessor inst in m_ImportProcessors) diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index 3f9223838c..94da574fe4 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -270,7 +270,6 @@ private static void RunAssemblyStripper(IEnumerable assemblies, string managedAs blacklists = blacklists.Concat(new[] { WriteMethodsToPreserveBlackList(rcr, platformProvider.target), - WriteUnityEngineBlackList(), MonoAssemblyStripping.GenerateLinkXmlToPreserveDerivedTypes(managedAssemblyFolderPath, rcr) }); } @@ -377,15 +376,6 @@ private static string WriteMethodsToPreserveBlackList(RuntimeClassRegistry rcr, return methodPerserveBlackList; } - private static string WriteUnityEngineBlackList() - { - // UnityEngine.dll would be stripped, as it contains no referenced symbols, only type forwarders. - // Since we need those type forwarders, we generate blacklist to preserve the assembly (but no members). - var unityEngineBlackList = Path.GetTempFileName(); - File.WriteAllText(unityEngineBlackList, ""); - return unityEngineBlackList; - } - private static string GetMethodPreserveBlacklistContents(RuntimeClassRegistry rcr, BuildTarget target) { if (rcr.GetMethodsToPreserve().Count == 0) diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index 248f7b566c..638f8c1b8a 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -94,7 +94,7 @@ static Color skinBackgroundColor } // Show the editor window. - public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately) + public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately, bool setFocus) { if (showMode == ShowMode.AuxWindow) showMode = ShowMode.Utility; @@ -117,7 +117,7 @@ public void Show(ShowMode showMode, bool loadPosition, bool displayImmediately) SetBackgroundColor(skinBackgroundColor); - Internal_BringLiveAfterCreation(displayImmediately, true); + Internal_BringLiveAfterCreation(displayImmediately, setFocus); // Window could be killed by now in user callbacks... if (!this) diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index 00590ec4be..ba8446b436 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -525,7 +525,7 @@ internal void ShowWithMode(ShowMode mode) cw.position = r; cw.rootView = host; MakeParentsSettingsMatchMe(); - cw.Show(mode, true, false); + cw.Show(mode, loadPosition: true, displayImmediately: false, setFocus: true); // set min/max size now that native window is not null so that it will e.g., use proper styleMask on macOS cw.SetMinMaxSizes(minSize, maxSize); @@ -1068,24 +1068,19 @@ private void OnDisableINTERNAL() // Internal stuff: // Helper to show this EditorWindow - internal static void CreateNewWindowForEditorWindow(EditorWindow window, bool loadPosition, bool showImmediately) - { - CreateNewWindowForEditorWindow(window, new Vector2(window.position.x, window.position.y), loadPosition, showImmediately); - } - - internal static void CreateNewWindowForEditorWindow(EditorWindow window, Vector2 screenPosition, bool loadPosition, bool showImmediately) + internal static void CreateNewWindowForEditorWindow(EditorWindow window, bool loadPosition, bool showImmediately, bool setFocus = true) { ContainerWindow cw = ScriptableObject.CreateInstance(); SplitView sw = ScriptableObject.CreateInstance(); cw.rootView = sw; DockArea da = ScriptableObject.CreateInstance(); - da.AddTab(window); + da.AddTab(window, setFocus); sw.AddChild(da); - Rect r = window.m_Parent.borderSize.Add(new Rect(screenPosition.x, screenPosition.y, window.position.width, window.position.height)); + Rect r = window.m_Parent.borderSize.Add(window.position); cw.position = r; sw.position = new Rect(0, 0, r.width, r.height); window.MakeParentsSettingsMatchMe(); - cw.Show(ShowMode.NormalWindow, loadPosition, showImmediately); + cw.Show(ShowMode.NormalWindow, loadPosition, showImmediately, setFocus: true); //Need this, as show my change the size of the window, due to screen constraints cw.OnResize(); } diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index d2ef8314f7..58d0173fd8 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -1257,7 +1257,7 @@ static void Start(GUIView viewToUpdate, Action colorPickedCallback) win.title = "EyeDropper"; win.hideFlags = HideFlags.DontSave; win.rootView = instance; - win.Show(ShowMode.PopupMenu, true, false); + win.Show(ShowMode.PopupMenu, loadPosition: true, displayImmediately: false, setFocus: true); instance.AddToAuxWindowList(); win.SetInvisible(); instance.SetMinMaxSizes(new Vector2(0, 0), new Vector2(kDummyWindowSize, kDummyWindowSize)); diff --git a/Editor/Mono/GUI/DockArea.cs b/Editor/Mono/GUI/DockArea.cs index e64688792e..fad669b4b6 100644 --- a/Editor/Mono/GUI/DockArea.cs +++ b/Editor/Mono/GUI/DockArea.cs @@ -82,14 +82,16 @@ private static class Styles public int selected { get { return m_Selected; } - set - { - if (m_Selected != value) - m_LastSelected = m_Selected; - m_Selected = value; - if (m_Selected >= 0 && m_Selected < m_Panes.Count) - actualView = m_Panes[m_Selected]; - } + set { SetSelectedPrivate(value, sendEvents: true); } + } + + private void SetSelectedPrivate(int value, bool sendEvents) + { + if (m_Selected != value) + m_LastSelected = m_Selected; + m_Selected = value; + if (m_Selected >= 0 && m_Selected < m_Panes.Count) + SetActualViewInternal(m_Panes[m_Selected], sendEvents); } public DockArea() @@ -173,16 +175,16 @@ protected override void UpdateViewMargins(EditorWindow view) style.positionType = PositionType.Absolute; } - public void AddTab(EditorWindow pane) + public void AddTab(EditorWindow pane, bool sendPaneEvents = true) { - AddTab(m_Panes.Count, pane); + AddTab(m_Panes.Count, pane, sendPaneEvents); } - public void AddTab(int idx, EditorWindow pane) + public void AddTab(int idx, EditorWindow pane, bool sendPaneEvents = true) { - DeregisterSelectedPane(true); + DeregisterSelectedPane(clearActualView: true, sendEvents: true); m_Panes.Insert(idx, pane); - selected = idx; + SetSelectedPrivate(idx, sendPaneEvents); s_GUIContents.Clear(); var sp = parent as SplitView; @@ -192,11 +194,11 @@ public void AddTab(int idx, EditorWindow pane) Repaint(); } - public void RemoveTab(EditorWindow pane) { RemoveTab(pane, true); } - public void RemoveTab(EditorWindow pane, bool killIfEmpty) + public void RemoveTab(EditorWindow pane) { RemoveTab(pane, killIfEmpty: true); } + public void RemoveTab(EditorWindow pane, bool killIfEmpty, bool sendEvents = true) { if (actualView == pane) - DeregisterSelectedPane(true); + DeregisterSelectedPane(clearActualView: true, sendEvents: sendEvents); int idx = m_Panes.IndexOf(pane); if (idx == -1) return; // Pane is not in the window @@ -222,7 +224,7 @@ public void RemoveTab(EditorWindow pane, bool killIfEmpty) pane.m_Parent = null; if (killIfEmpty) KillIfEmpty(); - RegisterSelectedPane(); + RegisterSelectedPane(sendEvents: true); } private void KillIfEmpty() @@ -279,9 +281,10 @@ public DropInfo DragOver(EditorWindow window, Vector2 mouseScreenPosition) public bool PerformDrop(EditorWindow w, DropInfo info, Vector2 screenPos) { - s_OriginalDragSource.RemoveTab(w, s_OriginalDragSource != this); + // Don't send focus events to the tab being moved + s_OriginalDragSource.RemoveTab(w, killIfEmpty: s_OriginalDragSource != this, sendEvents: false); int tabInsertIndex = s_PlaceholderPos == -1 || s_PlaceholderPos > m_Panes.Count ? m_Panes.Count : s_PlaceholderPos; - AddTab(tabInsertIndex, w); + AddTab(tabInsertIndex, w, sendPaneEvents: false); selected = tabInsertIndex; return true; } @@ -891,7 +894,9 @@ private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle) ResetDragVars(); - RemoveTab(w); + // The active tab that we're moving to the new window stays focused at all times. + // Do not remove focus from the tab being detached. + RemoveTab(w, killIfEmpty: true, sendEvents: false); Rect wPos = w.position; wPos.x = screenMousePos.x - wPos.width * .5f; wPos.y = screenMousePos.y - wPos.height * .5f; @@ -900,7 +905,8 @@ private float DragTab(Rect tabAreaRect, float scrollOffset, GUIStyle tabStyle) if (Application.platform == RuntimePlatform.WindowsEditor) wPos.y = Mathf.Max(InternalEditorUtility.GetBoundsOfDesktopAtPoint(screenMousePos).y, wPos.y); - EditorWindow.CreateNewWindowForEditorWindow(w, false, false); + // Don't call OnFocus on the tab when it is moved to the new window + EditorWindow.CreateNewWindowForEditorWindow(w, loadPosition: false, showImmediately: false, setFocus: false); w.position = w.m_Parent.window.FitWindowRectToScreen(wPos, true, true); diff --git a/Editor/Mono/GUI/MainView.cs b/Editor/Mono/GUI/MainView.cs index 24f90a0854..1f41368a2a 100644 --- a/Editor/Mono/GUI/MainView.cs +++ b/Editor/Mono/GUI/MainView.cs @@ -56,7 +56,7 @@ public static void MakeMain() int height = Mathf.Clamp(res.height * 3 / 4, 600, 950); cw.position = new Rect(60, 20, width, height); - cw.Show(ShowMode.MainWindow, true, true); + cw.Show(ShowMode.MainWindow, loadPosition: true, displayImmediately: true, setFocus: true); cw.DisplayAllViews(); } diff --git a/Editor/Mono/GUI/PaneDragTab.cs b/Editor/Mono/GUI/PaneDragTab.cs index 935cdd2932..ce5ca74804 100644 --- a/Editor/Mono/GUI/PaneDragTab.cs +++ b/Editor/Mono/GUI/PaneDragTab.cs @@ -131,7 +131,9 @@ public void Show(Rect pixelPos, GUIContent content, Vector2 viewSize, Vector2 mo { SetWindowPos(pixelPos); } - m_Window.Show(ShowMode.NoShadow, true, false); + + // Do not steal focus from the pane + m_Window.Show(ShowMode.NoShadow, loadPosition: true, displayImmediately: false, setFocus: false); m_TargetRect = pixelPos; } diff --git a/Editor/Mono/GUI/SplitView.cs b/Editor/Mono/GUI/SplitView.cs index 2c3682beb7..f0fc43a7ff 100644 --- a/Editor/Mono/GUI/SplitView.cs +++ b/Editor/Mono/GUI/SplitView.cs @@ -445,9 +445,9 @@ public bool PerformDrop(EditorWindow dropWindow, DropInfo dropInfo, Vector2 scre parentForDrop.MakeRoomForRect(dropRect); parentForDrop.AddChild(newDockArea, dropIndex); newDockArea.position = dropRect; - DockArea.s_OriginalDragSource.RemoveTab(dropWindow); + DockArea.s_OriginalDragSource.RemoveTab(dropWindow, killIfEmpty: true, sendEvents: false); dropWindow.m_Parent = newDockArea; - newDockArea.AddTab(dropWindow); + newDockArea.AddTab(dropWindow, sendPaneEvents: false); Reflow(); RecalcMinMaxAndReflowAll(this); newDockArea.MakeVistaDWMHappyDance(); diff --git a/Editor/Mono/GUI/WindowLayout.cs b/Editor/Mono/GUI/WindowLayout.cs index 047ce599c4..0b3d4ea174 100644 --- a/Editor/Mono/GUI/WindowLayout.cs +++ b/Editor/Mono/GUI/WindowLayout.cs @@ -600,7 +600,7 @@ public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated throw new System.Exception(); } - mainWindow.Show(mainWindow.showMode, true, true); + mainWindow.Show(mainWindow.showMode, loadPosition: true, displayImmediately: true, setFocus: true); // Show other windows for (int i = 0; i < newWindows.Count; i++) @@ -611,7 +611,7 @@ public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated ContainerWindow containerWindow = newWindows[i] as ContainerWindow; if (containerWindow && containerWindow != mainWindow) - containerWindow.Show(containerWindow.showMode, true, true); + containerWindow.Show(containerWindow.showMode, loadPosition: true, displayImmediately: true, setFocus: true); } // Unmaximize maximized GameView if maximize on play is enabled diff --git a/Editor/Mono/HostView.cs b/Editor/Mono/HostView.cs index ceccdc8cc7..bcd640d654 100644 --- a/Editor/Mono/HostView.cs +++ b/Editor/Mono/HostView.cs @@ -32,22 +32,24 @@ internal class HostView : GUIView internal EditorWindow actualView { get { return m_ActualView; } - set - { - if (m_ActualView == value) - return; - DeregisterSelectedPane(true); - m_ActualView = value; - m_IsGameView = m_ActualView is GameView; - RegisterSelectedPane(); - actualViewChanged?.Invoke(this); - } + set { SetActualViewInternal(value, sendEvents: true); } + } + + internal void SetActualViewInternal(EditorWindow value, bool sendEvents) + { + if (m_ActualView == value) + return; + DeregisterSelectedPane(clearActualView: true, sendEvents: true); + m_ActualView = value; + m_IsGameView = m_ActualView is GameView; + RegisterSelectedPane(sendEvents); + actualViewChanged?.Invoke(this); } internal void ResetActiveView() { - DeregisterSelectedPane(false); - RegisterSelectedPane(); + DeregisterSelectedPane(clearActualView: false, sendEvents: true); + RegisterSelectedPane(sendEvents: true); if (actualViewChanged != null) actualViewChanged(this); } @@ -94,7 +96,7 @@ protected override void OnEnable() EditorPrefs.onValueWasUpdated += PlayModeTintColorChangedCallback; base.OnEnable(); background = null; - RegisterSelectedPane(); + RegisterSelectedPane(sendEvents: true); } protected override void OnDisable() @@ -102,7 +104,7 @@ protected override void OnDisable() EditorApplication.playModeStateChanged -= PlayModeStateChangedCallback; EditorPrefs.onValueWasUpdated -= PlayModeTintColorChangedCallback; base.OnDisable(); - DeregisterSelectedPane(false); + DeregisterSelectedPane(clearActualView: false, sendEvents: true); } protected override void OldOnGUI() @@ -159,6 +161,11 @@ internal void OnLostFocus() { EditorGUI.EndEditingActiveTextField(); Invoke("OnLostFocus"); + + // Callback could have killed us + if (!this) + return; + Repaint(); } @@ -339,7 +346,7 @@ protected void Invoke(string methodName, object obj) mi?.Invoke(obj, null); } - protected void RegisterSelectedPane() + protected void RegisterSelectedPane(bool sendEvents) { if (!m_ActualView) return; @@ -368,24 +375,27 @@ protected void RegisterSelectedPane() EditorApplication.update += m_ActualView.CheckForWindowRepaint; } - try - { - Invoke("OnBecameVisible"); - EditorModes.OnBecameVisible(m_ActualView); - Invoke("OnFocus"); - EditorModes.OnFocus(m_ActualView); - } - catch (TargetInvocationException ex) + if (sendEvents) { - // We need to catch these so the window initialization doesn't get screwed - if (ex.InnerException != null) - Debug.LogError(ex.InnerException.GetType().Name + ":" + ex.InnerException.Message); + try + { + Invoke("OnBecameVisible"); + EditorModes.OnBecameVisible(m_ActualView); + Invoke("OnFocus"); + EditorModes.OnFocus(m_ActualView); + } + catch (TargetInvocationException ex) + { + // We need to catch these so the window initialization doesn't get screwed + if (ex.InnerException != null) + Debug.LogError(ex.InnerException.GetType().Name + ":" + ex.InnerException.Message); + } } UpdateViewMargins(m_ActualView); } - protected void DeregisterSelectedPane(bool clearActualView) + protected void DeregisterSelectedPane(bool clearActualView, bool sendEvents) { if (!m_ActualView) return; @@ -417,10 +427,13 @@ protected void DeregisterSelectedPane(bool clearActualView) { EditorWindow oldActualView = m_ActualView; m_ActualView = null; - Invoke("OnLostFocus", oldActualView); - EditorModes.OnLostFocus(m_ActualView); - Invoke("OnBecameInvisible", oldActualView); - EditorModes.OnBecameInvisible(oldActualView); + if (sendEvents) + { + Invoke("OnLostFocus", oldActualView); + EditorModes.OnLostFocus(m_ActualView); + Invoke("OnBecameInvisible", oldActualView); + EditorModes.OnBecameInvisible(oldActualView); + } } } diff --git a/Editor/Mono/ImportSettings/AssetImporterEditor.cs b/Editor/Mono/ImportSettings/AssetImporterEditor.cs index d2e0537a7b..f981e73479 100644 --- a/Editor/Mono/ImportSettings/AssetImporterEditor.cs +++ b/Editor/Mono/ImportSettings/AssetImporterEditor.cs @@ -22,11 +22,13 @@ internal void InternalSetAssetImporterTargetEditor(Object editor) protected internal Object assetTarget { get { return m_AssetEditor != null ? m_AssetEditor.target : null; } } protected internal SerializedObject assetSerializedObject { get { return m_AssetEditor != null ? m_AssetEditor.serializedObject : null; } } + static string s_LocalizedTitleString = L10n.Tr("{0} Import Settings"); + internal override string targetTitle { get { - return string.Format(L10n.Tr("{0} Import Settings"), m_AssetEditor == null ? string.Empty : m_AssetEditor.targetTitle); + return string.Format(s_LocalizedTitleString, m_AssetEditor == null ? string.Empty : m_AssetEditor.targetTitle); } } diff --git a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs index b2e66d701a..2264c4dac2 100644 --- a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs +++ b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs @@ -49,7 +49,7 @@ internal override void OnGUI(PluginImporterInspector inspector) // This toggle controls two things: // * Is platform enabled/disabled? // * Platform CPU value - bool isTargetEnabled = EditorGUILayout.Toggle(name, IsTargetEnabled(inspector)); + bool isTargetEnabled = EditorGUILayout.Toggle(name, IsTargetEnabled(inspector) && value.ToString() == defaultValue.ToString()); if (EditorGUI.EndChangeCheck()) { value = isTargetEnabled ? defaultValue : DesktopPluginCPUArchitecture.None; diff --git a/Editor/Mono/Inspector/AnimationClipEditor.cs b/Editor/Mono/Inspector/AnimationClipEditor.cs index 23fc6cffb2..93bbbb54b9 100644 --- a/Editor/Mono/Inspector/AnimationClipEditor.cs +++ b/Editor/Mono/Inspector/AnimationClipEditor.cs @@ -217,6 +217,7 @@ public bool needsToGenerateClipInfo const int kPosition = 3; Vector2[][][] m_QualityCurves = new Vector2[4][][]; bool m_DirtyQualityCurves = false; + bool m_FirstInitialization = true; private void InitController() { @@ -269,7 +270,12 @@ private void InitController() { m_AvatarPreview.Animator.Play(0, 0, 0); m_AvatarPreview.Animator.Update(0); - m_AvatarPreview.ResetPreviewFocus(); + + if (m_FirstInitialization) + { + m_AvatarPreview.ResetPreviewFocus(); + m_FirstInitialization = false; + } } } } diff --git a/Editor/Mono/Inspector/GameObjectInspector.cs b/Editor/Mono/Inspector/GameObjectInspector.cs index bb5d9782ce..ef7ccf6d4f 100644 --- a/Editor/Mono/Inspector/GameObjectInspector.cs +++ b/Editor/Mono/Inspector/GameObjectInspector.cs @@ -131,11 +131,14 @@ public void Dispose() Dictionary m_PreviewInstances = new Dictionary(); + bool m_PlayModeObjects; bool m_IsAsset; bool m_ImmutableSelf; bool m_ImmutableSourceAsset; - bool m_IsPrefabInstanceAnyRoot = false; - bool m_IsPrefabInstanceOutermostRoot = false; + bool m_IsDisconnected; + bool m_IsMissing; + bool m_IsPrefabInstanceAnyRoot; + bool m_IsPrefabInstanceOutermostRoot; bool m_AllOfSamePrefabType = true; public void OnEnable() @@ -157,8 +160,14 @@ public void OnEnable() void CalculatePrefabStatus() { - m_IsPrefabInstanceAnyRoot = false; + m_PlayModeObjects = false; m_IsAsset = false; + m_ImmutableSelf = false; + m_ImmutableSourceAsset = false; + m_IsDisconnected = false; + m_IsMissing = false; + m_IsPrefabInstanceAnyRoot = true; + m_IsPrefabInstanceOutermostRoot = true; m_AllOfSamePrefabType = true; PrefabAssetType firstType = PrefabUtility.GetPrefabAssetType(targets[0]); PrefabInstanceStatus firstStatus = PrefabUtility.GetPrefabInstanceStatus(targets[0]); @@ -170,17 +179,23 @@ void CalculatePrefabStatus() if (type != firstType || status != firstStatus) m_AllOfSamePrefabType = false; - if (PrefabUtility.IsAnyPrefabInstanceRoot(go)) - m_IsPrefabInstanceAnyRoot = true; - if (m_IsPrefabInstanceAnyRoot) - m_IsPrefabInstanceOutermostRoot = PrefabUtility.IsOutermostPrefabInstanceRoot(go); + if (Application.IsPlaying(go)) + m_PlayModeObjects = true; + if (!PrefabUtility.IsAnyPrefabInstanceRoot(go)) + m_IsPrefabInstanceAnyRoot = false; // Conservative is false if any is false + if (!m_IsPrefabInstanceAnyRoot || !PrefabUtility.IsOutermostPrefabInstanceRoot(go)) + m_IsPrefabInstanceOutermostRoot = false; // Conservative is false if any is false if (PrefabUtility.IsPartOfPrefabAsset(go)) - m_IsAsset = true; + m_IsAsset = true; // Conservative is true if any is true if (m_IsAsset && PrefabUtility.IsPartOfImmutablePrefab(go)) - m_ImmutableSelf = true; + m_ImmutableSelf = true; // Conservative is true if any is true GameObject originalSourceOrVariant = PrefabUtility.GetOriginalSourceOrVariantRoot(go); if (originalSourceOrVariant != null && PrefabUtility.IsPartOfImmutablePrefab(originalSourceOrVariant)) - m_ImmutableSourceAsset = true; + m_ImmutableSourceAsset = true; // Conservative is true if any is true + if (PrefabUtility.IsDisconnectedFromPrefabAsset(go)) + m_IsDisconnected = true; + if (PrefabUtility.IsPrefabAssetMissing(go)) + m_IsMissing = true; } } @@ -298,7 +313,7 @@ internal bool DrawInspector() // Prefab Toolbar if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None) { - DoPrefabButtons(go); + DoPrefabButtons(); } serializedObject.ApplyModifiedProperties(); @@ -306,19 +321,18 @@ internal bool DrawInspector() return true; } - private void DoPrefabButtons(GameObject go) + private void DoPrefabButtons() { - // @TODO: If/when we support multi-editing of prefab/model instances, - // handle it here. Only show prefab bar if all are same type? - if (!m_IsPrefabInstanceAnyRoot) return; + if (!m_IsPrefabInstanceAnyRoot) + return; - using (new EditorGUI.DisabledScope(EditorApplication.isPlayingOrWillChangePlaymode && PrefabStageUtility.GetPrefabStage(go) == null)) + using (new EditorGUI.DisabledScope(m_PlayModeObjects)) { EditorGUILayout.BeginHorizontal(s_Styles.prefabButtonsHorizontalLayout); // Prefab information - PrefabAssetType prefabType = PrefabUtility.GetPrefabAssetType(go); - PrefabInstanceStatus instanceStatus = PrefabUtility.GetPrefabInstanceStatus(go); + PrefabAssetType singlePrefabType = PrefabUtility.GetPrefabAssetType(target); + PrefabInstanceStatus singleInstanceStatus = PrefabUtility.GetPrefabInstanceStatus(target); GUIContent prefixLabel; if (targets.Length > 1) { @@ -326,14 +340,14 @@ private void DoPrefabButtons(GameObject go) } else { - prefixLabel = s_Styles.goTypeLabel[(int)prefabType, (int)instanceStatus]; + prefixLabel = s_Styles.goTypeLabel[(int)singlePrefabType, (int)singleInstanceStatus]; } if (prefixLabel != null) { EditorGUILayout.BeginHorizontal(GUILayout.Width(kIconSize + s_Styles.tagFieldWidth)); GUILayout.FlexibleSpace(); - if (PrefabUtility.IsDisconnectedFromPrefabAsset(go) || PrefabUtility.IsPrefabAssetMissing(go)) + if (m_IsDisconnected || m_IsMissing) { GUI.contentColor = GUI.skin.GetStyle("CN StatusWarn").normal.textColor; GUILayout.Label(prefixLabel, EditorStyles.whiteLabel, GUILayout.ExpandWidth(false)); @@ -344,13 +358,11 @@ private void DoPrefabButtons(GameObject go) EditorGUILayout.EndHorizontal(); } - if (targets.Length > 1) - GUILayout.Label("Instance Management Disabled", s_Styles.instanceManagementInfo); - else + if (!m_IsMissing) { - if (!PrefabUtility.IsPrefabAssetMissing(go)) + using (new EditorGUI.DisabledScope(targets.Length > 1)) { - if (prefabType == PrefabAssetType.Model) + if (singlePrefabType == PrefabAssetType.Model) { // Open Model Prefab if (GUILayout.Button("Open", "MiniButtonLeft")) @@ -373,11 +385,15 @@ private void DoPrefabButtons(GameObject go) } } } + } - // Select prefab - if (GUILayout.Button("Select", "MiniButtonRight")) + // Select prefab + if (GUILayout.Button("Select", "MiniButtonRight")) + { + HashSet selectedAssets = new HashSet(); + for (int i = 0; i < targets.Length; i++) { - Selection.activeObject = PrefabUtility.GetOriginalSourceOrVariantRoot(target); + GameObject prefabGo = PrefabUtility.GetOriginalSourceOrVariantRoot(targets[i]); // Because of legacy prefab references we have to have this extra step // to make sure we ping the prefab asset correctly. @@ -385,25 +401,30 @@ private void DoPrefabButtons(GameObject go) // will reference prefabs as if they are serialized assets. Those references // works fine but we are not able to ping objects loaded directly from the asset // file, so we have to make sure we ping the metadata version of the prefab. - var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject); - Selection.activeObject = AssetDatabase.LoadMainAssetAtPath(assetPath); + var assetPath = AssetDatabase.GetAssetPath(prefabGo); + selectedAssets.Add((GameObject)AssetDatabase.LoadMainAssetAtPath(assetPath)); + } + Selection.objects = selectedAssets.ToArray(); + if (Selection.gameObjects.Length == 1) EditorGUIUtility.PingObject(Selection.activeObject); - } + } - // Should be EditorGUILayout.Space, except it does not have ExpandWidth set to false. - // Maybe we can change that? - GUILayoutUtility.GetRect(6, 6, GUILayout.ExpandWidth(false)); + // Should be EditorGUILayout.Space, except it does not have ExpandWidth set to false. + // Maybe we can change that? + GUILayoutUtility.GetRect(6, 6, GUILayout.ExpandWidth(false)); - // Reserve space regardless of whether the button is there or not to avoid jumps in button sizes. - Rect rect = GUILayoutUtility.GetRect(s_Styles.overridesContent, s_Styles.overridesDropdown); - if (m_IsPrefabInstanceOutermostRoot) + // Reserve space regardless of whether the button is there or not to avoid jumps in button sizes. + Rect rect = GUILayoutUtility.GetRect(s_Styles.overridesContent, s_Styles.overridesDropdown); + if (m_IsPrefabInstanceOutermostRoot) + { + if (EditorGUI.DropdownButton(rect, s_Styles.overridesContent, FocusType.Passive)) { - if (EditorGUI.DropdownButton(rect, s_Styles.overridesContent, FocusType.Passive)) - { - PopupWindow.Show(rect, new PrefabOverridesWindow(go)); - GUIUtility.ExitGUI(); - } + if (targets.Length > 1) + PopupWindow.Show(rect, new PrefabOverridesWindow(targets.Select(e => (GameObject)e).ToArray())); + else + PopupWindow.Show(rect, new PrefabOverridesWindow((GameObject)target)); + GUIUtility.ExitGUI(); } } } diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 9c685ac9ae..1464161d4b 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -1241,7 +1241,7 @@ private void DrawEditor(Editor[] editors, int editorIndex, bool rebuildOptimized Rect contentRect = new Rect(); bool excludedClass = ModuleMetadata.GetModuleIncludeSettingForObject(target) == ModuleIncludeSetting.ForceExclude; if (excludedClass) - EditorGUILayout.HelpBox("The built-in package which implements this component type has been disabled in Package Manager. This object will be removed in play mode and from any builds you make.", MessageType.Warning); + EditorGUILayout.HelpBox("The built-in package '" + ModuleMetadata.GetExcludingModuleForObject(target) + "', which is required this component type has been disabled in Package Manager. This object will be removed in play mode and from any builds you make.", MessageType.Warning); using (new EditorGUI.DisabledScope(!editor.IsEnabled() || excludedClass)) { diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index 0f5d45dffb..ae164fd643 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -61,6 +61,8 @@ static class Styles public static readonly GUIContent ResolutionTooHighWarning = EditorGUIUtility.TrTextContent("Precompute/indirect resolution for this terrain is probably too high. Use a lower realtime/indirect resolution setting in the Lighting window or assign LightmapParameters that use a lower resolution setting. Otherwise it may take a very long time to bake and memory consumption during and after the bake may be very high."); public static readonly GUIContent ResolutionTooLowWarning = EditorGUIUtility.TrTextContent("Precompute/indirect resolution for this terrain is probably too low. If the Clustering stage takes a long time, try using a higher realtime/indirect resolution setting in the Lighting window or assign LightmapParameters that use a higher resolution setting."); public static readonly GUIContent GINotEnabledInfo = EditorGUIUtility.TrTextContent("Lightmapping settings are currently disabled. Enable Baked Global Illumination or Realtime Global Illumination to display these settings."); + public static readonly GUIContent CastShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Cast Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); + public static readonly GUIContent ReceiveShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Receive Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); } bool m_ShowChartingSettings = true; @@ -156,20 +158,25 @@ public void RenderMeshSettings(bool showLightmapSettings) m_GameObjectsSerializedObject.Update(); m_LightmapSettings.Update(); - // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. - if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) + // TODO(RadeonRays): remove scope for GPU lightmapper once the feature has been implemented. + using (new EditorGUI.DisabledScope(LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU)) + { EditorGUILayout.PropertyField(m_CastShadows, Styles.CastShadows, true); + } + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.HelpBox(Styles.CastShadowsProgressiveGPUWarning.text, MessageType.Info); bool isDeferredRenderingPath = SceneView.IsUsingDeferredRenderingPath(); if (SupportedRenderingFeatures.active.rendererSupportsReceiveShadows) { - using (new EditorGUI.DisabledScope(isDeferredRenderingPath)) + // TODO(RadeonRays): remove scope for GPU lightmapper once the feature has been implemented. + using (new EditorGUI.DisabledScope(isDeferredRenderingPath || LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU)) { - // TODO(RadeonRays): remove if GPU lightmapper once the feature has been implemented. - if (LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); + EditorGUILayout.PropertyField(m_ReceiveShadows, Styles.ReceiveShadows, true); } + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.HelpBox(Styles.ReceiveShadowsProgressiveGPUWarning.text, MessageType.Info); } if (SupportedRenderingFeatures.active.rendererSupportsMotionVectors) diff --git a/Editor/Mono/Inspector/MaterialEditor.cs b/Editor/Mono/Inspector/MaterialEditor.cs index ad6c71cf1f..30628d6d4f 100644 --- a/Editor/Mono/Inspector/MaterialEditor.cs +++ b/Editor/Mono/Inspector/MaterialEditor.cs @@ -60,6 +60,7 @@ private static class Styles public static readonly GUIContent enableInstancingLabel = EditorGUIUtility.TrTextContent("Enable GPU Instancing"); public static readonly GUIContent doubleSidedGILabel = EditorGUIUtility.TrTextContent("Double Sided Global Illumination", "When enabled, the lightmapper accounts for both sides of the geometry when calculating Global Illumination. Backfaces are not rendered or added to lightmaps, but get treated as valid when seen from other objects. When using the Progressive Lightmapper backfaces bounce light using the same emission and albedo as frontfaces."); public static readonly GUIContent emissionLabel = EditorGUIUtility.TrTextContent("Emission"); + public static readonly GUIContent ProgressiveGPUWarning = EditorGUIUtility.TrTextContent("The Double Sided Global Illumination feature is not implemented in the Progressive GPU lightmapper yet. Use the CPU lightmapper instead if you need this functionality."); } private static readonly List s_MaterialEditors = new List(4); diff --git a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs index f585af937f..6ff78840fe 100644 --- a/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs +++ b/Editor/Mono/Inspector/MaterialEditorGUIHelpers.cs @@ -166,6 +166,10 @@ public bool DoubleSidedGIField() // TODO(RadeonRays): change this to (lightmapper == Enlighten) once Double Sided GI works with GPU lightmapper. using (new EditorGUI.DisabledScope(LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.ProgressiveCPU)) EditorGUI.Toggle(r, Styles.doubleSidedGILabel, false); + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + { + EditorGUILayout.HelpBox(Styles.ProgressiveGPUWarning.text, MessageType.Info); + } } return false; } diff --git a/Editor/Mono/Menu.bindings.cs b/Editor/Mono/Menu.bindings.cs index aaa3b83298..cf50afc6d6 100644 --- a/Editor/Mono/Menu.bindings.cs +++ b/Editor/Mono/Menu.bindings.cs @@ -21,5 +21,8 @@ public sealed class Menu [FreeFunction("MenuController::SetMenuItemHotkey")] internal static extern void SetHotkey(string menuPath, string hotkey); + + [FreeFunction("MenuController::ExtractSubmenus")] + internal static extern string[] ExtractSubmenus(string menuPath); } } diff --git a/Editor/Mono/PackageUtility.bindings.cs b/Editor/Mono/PackageUtility.bindings.cs index ddc81d4910..c548a47068 100644 --- a/Editor/Mono/PackageUtility.bindings.cs +++ b/Editor/Mono/PackageUtility.bindings.cs @@ -68,5 +68,8 @@ internal class PackageUtility public static extern void ImportPackageAssets(string packageName, ImportPackageItem[] items, bool performReInstall); [FreeFunction("ImportPackageAssets")] public static extern void ImportPackageAssetsImmediately(string packageName, ImportPackageItem[] items, bool performReInstall); + + [FreeFunction("TickPackageImport")] + public static extern void TickPackageImport(); } } diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs index 0f20879f08..87217b8985 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/InitialModuleUI.cs @@ -38,6 +38,7 @@ internal class InitialModuleUI : ModuleUI public SerializedProperty m_AutoRandomSeed; public SerializedProperty m_RandomSeed; public SerializedProperty m_StopAction; + public SerializedProperty m_CullingMode; public SerializedProperty m_RingBufferMode; public SerializedProperty m_RingBufferLoopRange; @@ -68,6 +69,7 @@ class Texts public GUIContent randomSeed = EditorGUIUtility.TrTextContent("Random Seed", "Randomize the look of the Particle System. Using the same seed will make the Particle System play identically each time. After changing this value, restart the Particle System to see the changes, or check the Resimulate box."); public GUIContent emitterVelocity = EditorGUIUtility.TrTextContent("Emitter Velocity", "When the Particle System is moving, should we use its Transform, or Rigidbody Component, to calculate its velocity?"); public GUIContent stopAction = EditorGUIUtility.TrTextContent("Stop Action", "When the Particle System is stopped and all particles have died, should the GameObject automatically disable/destroy itself?"); + public GUIContent cullingMode = EditorGUIUtility.TrTextContent("Culling Mode", "Choose whether to continue simulating the Particle System when offscreen. Catch-up mode pauses offscreen simulations, but performs a large simulation step when they become visible, giving the appearance that they were never paused. Automatic uses Pause mode for looping systems, and AlwaysSimulate if not looping."); public GUIContent ringBufferMode = EditorGUIUtility.TrTextContent("Ring Buffer Mode", "Rather than dying when their lifetime has elapsed, particles will remain alive until the Max Particles buffer is full, at which point new particles will replace the oldest."); public GUIContent ringBufferLoopRange = EditorGUIUtility.TrTextContent("Loop Range", "Particle lifetimes may loop between a fade-in and fade-out time, in order to use curves for the entire time they are alive. Values are in the 0-1 range."); public GUIContent x = EditorGUIUtility.TextContent("X"); @@ -96,6 +98,14 @@ class Texts EditorGUIUtility.TrTextContent("Callback") }; + public GUIContent[] cullingModes = new GUIContent[] + { + EditorGUIUtility.TrTextContent("Automatic"), + EditorGUIUtility.TrTextContent("Pause and Catch-up"), + EditorGUIUtility.TrTextContent("Pause"), + EditorGUIUtility.TrTextContent("Always Simulate") + }; + public GUIContent[] ringBufferModes = new GUIContent[] { EditorGUIUtility.TrTextContent("Disabled"), @@ -146,6 +156,7 @@ protected override void Init() m_AutoRandomSeed = GetProperty0("autoRandomSeed"); m_RandomSeed = GetProperty0("randomSeed"); m_StopAction = GetProperty0("stopAction"); + m_CullingMode = GetProperty0("cullingMode"); m_RingBufferMode = GetProperty0("ringBufferMode"); m_RingBufferLoopRange = GetProperty0("ringBufferLoopRange"); @@ -307,6 +318,7 @@ override public void OnInspectorGUI(InitialModuleUI initial) } GUIPopup(s_Texts.stopAction, m_StopAction, s_Texts.stopActions); + GUIPopup(s_Texts.cullingMode, m_CullingMode, s_Texts.cullingModes); ParticleSystemRingBufferMode ringBufferMode = (ParticleSystemRingBufferMode)GUIPopup(s_Texts.ringBufferMode, m_RingBufferMode, s_Texts.ringBufferModes); if (!m_RingBufferMode.hasMultipleDifferentValues && ringBufferMode == ParticleSystemRingBufferMode.LoopUntilReplaced) diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs index 8fa5a25abb..6311362d91 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemUI.cs @@ -427,7 +427,7 @@ void UpdateParticleSystemInfoString() if (supportsCullingText != m_SupportsCullingText || m_SupportsCullingTextLabel == null) { m_SupportsCullingText = supportsCullingText; - m_SupportsCullingTextLabel = "Automatic culling is disabled because: " + supportsCullingText.Replace("\n", "\n" + s_Texts.bulletPoint); + m_SupportsCullingTextLabel = "Procedural simulation is not supported because: " + supportsCullingText.Replace("\n", "\n" + s_Texts.bulletPoint); } } else diff --git a/Editor/Mono/Prefabs/PrefabImporterEditor.cs b/Editor/Mono/Prefabs/PrefabImporterEditor.cs index b5cc37005b..d95d7175aa 100644 --- a/Editor/Mono/Prefabs/PrefabImporterEditor.cs +++ b/Editor/Mono/Prefabs/PrefabImporterEditor.cs @@ -15,6 +15,8 @@ internal class PrefabImporterEditor : AssetImporterEditor { static GUIContent s_OpenContent = EditorGUIUtility.TrTextContent("Open Prefab"); static GUIContent s_BaseContent = EditorGUIUtility.TrTextContent("Base"); + static string s_LocalizedTitleMultiplePrefabs = L10n.Tr("Prefab Assets"); + static string s_LocalizedTitleSinglePrefab = L10n.Tr("Prefab Asset"); int m_HasMixedBaseVariants = -1; @@ -41,6 +43,17 @@ void CacheHasMixedBaseVariants() public override bool showImportedObject { get { return false; } } + internal override string targetTitle + { + get + { + if (assetTargets == null || assetTargets.Length == 1 || !m_AllowMultiObjectAccess) + return assetTarget != null ? assetTarget.name : s_LocalizedTitleSinglePrefab; + else + return assetTargets.Length + " " + s_LocalizedTitleMultiplePrefabs; + } + } + internal override void OnHeaderControlsGUI() { var variantBase = PrefabUtility.GetCorrespondingObjectFromSource(assetTarget); diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs index e14e7d536a..1d23d08821 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs @@ -17,19 +17,28 @@ internal class PrefabOverridesWindow : PopupWindowContent const float k_HeaderHeight = 32f; const float k_ButtonWidth = 120; const float k_HeaderLeftMargin = 6; + const float k_NoOverridesLabelHeight = 26f; + const float k_ApplyButtonHeight = 32f; + const float k_HelpBoxHeight = 40f; + GameObject[] m_SelectedGameObjects = null; + + // TreeView not used when there are multiple Prefabs. TreeViewState m_TreeViewState; PrefabOverridesTreeView m_TreeView; - GameObject m_SelectedGameObject; GUIContent m_StageContent = new GUIContent(); GUIContent m_InstanceContent = new GUIContent(); GUIContent m_RevertAllContent = new GUIContent(); GUIContent m_ApplyAllContent = new GUIContent(); - bool m_Immutable; + bool m_AnyOverrides; + bool m_Disconnected; bool m_InvalidComponentOnInstance; + bool m_ModelPrefab; + bool m_Immutable; bool m_InvalidComponentOnAsset; + static class Styles { public static GUIContent revertAllContent = EditorGUIUtility.TrTextContent("Revert All", "Revert all overrides."); @@ -49,46 +58,76 @@ static Styles() internal PrefabOverridesWindow(GameObject selectedGameObject) { - m_SelectedGameObject = selectedGameObject; + m_SelectedGameObjects = new GameObject[] { selectedGameObject }; m_TreeViewState = new TreeViewState(); m_TreeView = new PrefabOverridesTreeView(selectedGameObject, m_TreeViewState); - GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(m_SelectedGameObject); + GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(selectedGameObject); - m_TreeView.SetApplyTarget(m_SelectedGameObject, prefabAssetRoot, AssetDatabase.GetAssetPath(prefabAssetRoot)); + m_TreeView.SetApplyTarget(selectedGameObject, prefabAssetRoot, AssetDatabase.GetAssetPath(prefabAssetRoot)); - UpdateText(prefabAssetRoot); + UpdateTextSingle(prefabAssetRoot); + UpdateStatusChecks(selectedGameObject); + } - m_Immutable = PrefabUtility.IsPartOfImmutablePrefab(prefabAssetRoot); - m_InvalidComponentOnInstance = PrefabUtility.HasInvalidComponent(m_SelectedGameObject); - m_InvalidComponentOnAsset = PrefabUtility.HasInvalidComponent(prefabAssetRoot); + internal PrefabOverridesWindow(GameObject[] selectedGameObjects) + { + m_SelectedGameObjects = selectedGameObjects; + UpdateTextMultiple(); + for (int i = 0; i < m_SelectedGameObjects.Length; i++) + UpdateStatusChecks(m_SelectedGameObjects[i]); } - bool IsDisconnected() + void UpdateStatusChecks(GameObject prefabInstanceRoot) { - return PrefabUtility.IsDisconnectedFromPrefabAsset(m_SelectedGameObject); + if (PrefabUtility.HasPrefabInstanceAnyOverrides(prefabInstanceRoot, false)) + m_AnyOverrides = true; + if (PrefabUtility.IsDisconnectedFromPrefabAsset(prefabInstanceRoot)) + m_Disconnected = true; + if (PrefabUtility.HasInvalidComponent(prefabInstanceRoot)) + m_InvalidComponentOnInstance = true; + + GameObject prefabAssetRoot = PrefabUtility.GetCorrespondingObjectFromSource(prefabInstanceRoot); + + if (PrefabUtility.IsPartOfModelPrefab(prefabAssetRoot)) + m_ModelPrefab = true; + if (PrefabUtility.IsPartOfImmutablePrefab(prefabAssetRoot)) + m_Immutable = true; + if (PrefabUtility.HasInvalidComponent(prefabAssetRoot)) + m_InvalidComponentOnAsset = true; } bool IsShowingActionButton() { - if (m_TreeView.hasModifications || IsDisconnected()) - return true; + return m_AnyOverrides || m_Disconnected; + } - return false; + bool HasMultiSelection() + { + return m_SelectedGameObjects.Length > 1; + } + + bool DisplayingTreeView() + { + return m_AnyOverrides && !HasMultiSelection(); } public override Vector2 GetWindowSize() { var height = k_HeaderHeight; - if (!IsDisconnected()) - height += k_TreeViewPadding.top + m_TreeView.totalHeight + k_TreeViewPadding.bottom; + if (!IsShowingActionButton()) + { + height += k_NoOverridesLabelHeight; + } + else + { + if (DisplayingTreeView()) + height += k_TreeViewPadding.top + m_TreeView.totalHeight + k_TreeViewPadding.bottom; - const float applyButtonHeight = 32f; - if (IsShowingActionButton()) - height += applyButtonHeight; - if (m_TreeView.hasModifications || IsDisconnected()) - height += 40; + if (IsShowingActionButton()) + height += k_ApplyButtonHeight + k_HelpBoxHeight; + } // Width should be no smaller than minimum width, but we could potentially improve // width handling by making it expand if needed based on tree view content. @@ -99,6 +138,13 @@ public override Vector2 GetWindowSize() public override void OnGUI(Rect rect) { + // Escape closes the window + if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) + { + editorWindow.Close(); + GUIUtility.ExitGUI(); + } + Rect headerRect = GUILayoutUtility.GetRect(20, 10000, k_HeaderHeight, k_HeaderHeight); EditorGUI.DrawRect(headerRect, headerBgColor); @@ -120,20 +166,36 @@ public override void OnGUI(Rect rect) GUILayout.Space(k_TreeViewPadding.top); - if (!IsDisconnected()) + // If we know there are no overrides and thus no meaningful actions we just show that and nothing more. + if (!IsShowingActionButton()) { - Rect treeViewRect = GUILayoutUtility.GetRect(100, 1000, 0, 1000); - m_TreeView.OnGUI(treeViewRect); + EditorGUILayout.LabelField("No Overrides"); + return; } - if (IsShowingActionButton()) + // Display tree view and/or instructions related to it. + if (HasMultiSelection()) { - if (IsDisconnected()) + if (m_InvalidComponentOnAsset || m_InvalidComponentOnInstance || m_ModelPrefab || m_Immutable) + EditorGUILayout.HelpBox( + "Multiple Prefabs selected. Cannot show overrides.\nApplying is not possible for one or more Prefabs. Select individual Prefabs for details.", + MessageType.Info); + else + EditorGUILayout.HelpBox( + "Multiple Prefabs selected. Cannot show overrides.", + MessageType.Info); + } + else + { + if (m_Disconnected) { EditorGUILayout.HelpBox("Disconnected. Cannot show overrides.", MessageType.Warning); } - else if (m_TreeView.hasModifications) + else if (m_AnyOverrides) { + Rect treeViewRect = GUILayoutUtility.GetRect(100, 1000, 0, 1000); + m_TreeView.OnGUI(treeViewRect); + if (m_InvalidComponentOnAsset) EditorGUILayout.HelpBox( "Click on individual items to review and revert.\nThe Prefab file contains an invalid script. Applying is not possible. Enter Prefab Mode and remove the script.", @@ -142,7 +204,7 @@ public override void OnGUI(Rect rect) EditorGUILayout.HelpBox( "Click on individual items to review and revert.\nThe Prefab instance contains an invalid script. Applying is not possible. Remove the script.", MessageType.Info); - else if (PrefabUtility.IsPartOfModelPrefab(m_SelectedGameObject)) + else if (m_ModelPrefab) EditorGUILayout.HelpBox( "Click on individual items to review and revert.\nApplying to a model Prefab is not possible.", MessageType.Info); @@ -154,54 +216,93 @@ public override void OnGUI(Rect rect) EditorGUILayout.HelpBox("Click on individual items to review, revert and apply.", MessageType.Info); } + } - GUILayout.BeginHorizontal(); - - GUILayout.FlexibleSpace(); - - using (new EditorGUI.DisabledScope(m_InvalidComponentOnAsset)) + // Display action buttons (Revert All and Apply All) + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + using (new EditorGUI.DisabledScope(m_InvalidComponentOnAsset)) + { + if (GUILayout.Button(m_RevertAllContent, GUILayout.Width(k_ButtonWidth))) { - if (GUILayout.Button(m_RevertAllContent, GUILayout.Width(k_ButtonWidth))) + if (RevertAll() && editorWindow != null) { - PrefabUtility.RevertPrefabInstance(m_SelectedGameObject, InteractionMode.UserAction); - - if (editorWindow != null) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } + editorWindow.Close(); + GUIUtility.ExitGUI(); } + } - using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + { + if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(k_ButtonWidth))) { - if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(k_ButtonWidth))) + if (ApplyAll() && editorWindow != null) { - string assetPath = - PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(m_SelectedGameObject); - if (PrefabUtility.PromptAndCheckoutPrefabIfNeeded(assetPath, PrefabUtility.SaveVerb.Apply)) - { - PrefabUtility.ApplyPrefabInstance(m_SelectedGameObject, InteractionMode.UserAction); - - if (editorWindow != null) - { - editorWindow.Close(); - GUIUtility.ExitGUI(); - } - } + editorWindow.Close(); + GUIUtility.ExitGUI(); } } } } + GUILayout.EndHorizontal(); + } - // Escape closes the window - if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) + bool ApplyAll() + { + // Collect Prefab Asset paths and also check if there's more than one of the same. + HashSet prefabAssetPaths = new HashSet(); + bool multipleOfSame = false; + for (int i = 0; i < m_SelectedGameObjects.Length; i++) { - editorWindow.Close(); - GUIUtility.ExitGUI(); + string prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(m_SelectedGameObjects[i]); + if (prefabAssetPaths.Contains(prefabAssetPath)) + multipleOfSame = true; + else + prefabAssetPaths.Add(prefabAssetPath); } + + // If more than one instance of the same Prefab Asset, show dialog to user. + if (multipleOfSame && !EditorUtility.DisplayDialog( + "Multiple instances of same Prefab Asset", + "Multiple instances of the same Prefab Asset were detected. Potentially conflicting overrides will be applied sequentially and will overwrite each other.", + "OK", + "Cancel")) + return false; + + // Make sure assets are checked out in version control. + if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(prefabAssetPaths.ToArray(), PrefabUtility.SaveVerb.Apply)) + return false; + + // Apply sequentially. + for (int i = 0; i < m_SelectedGameObjects.Length; i++) + PrefabUtility.ApplyPrefabInstance(m_SelectedGameObjects[i], InteractionMode.UserAction); + + return true; + } + + bool RevertAll() + { + for (int i = 0; i < m_SelectedGameObjects.Length; i++) + PrefabUtility.RevertPrefabInstance(m_SelectedGameObjects[i], InteractionMode.UserAction); + + return true; + } + + void UpdateTextSingle(GameObject prefabAsset) + { + Texture2D icon = (Texture2D)AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(prefabAsset)); + string name = prefabAsset.name; + UpdateText(icon, name); + } + + void UpdateTextMultiple() + { + Texture icon = EditorGUIUtility.IconContent("Prefab Icon").image; + string name = "(Multiple Prefabs)"; + UpdateText(icon, name); } - void UpdateText(GameObject prefabAsset) + void UpdateText(Texture assetIcon, string assetName) { var stage = SceneManagement.StageNavigationManager.instance.currentItem; if (stage.isMainStage) @@ -215,8 +316,8 @@ void UpdateText(GameObject prefabAsset) m_StageContent.text = stage.displayName; } - m_InstanceContent.image = (Texture2D)AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(prefabAsset)); - m_InstanceContent.text = prefabAsset.name; + m_InstanceContent.image = assetIcon; + m_InstanceContent.text = assetName; m_RevertAllContent.text = Styles.revertAllContent.text; m_RevertAllContent.tooltip = Styles.revertAllContent.tooltip; @@ -226,7 +327,7 @@ void UpdateText(GameObject prefabAsset) applyAllContent = Styles.applyAllToBaseContent; m_ApplyAllContent.text = applyAllContent.text; - m_ApplyAllContent.tooltip = string.Format(applyAllContent.tooltip, prefabAsset.name); + m_ApplyAllContent.tooltip = string.Format(applyAllContent.tooltip, assetName); } } } diff --git a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs index 499f70164c..728dd0a803 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs @@ -57,6 +57,9 @@ public sealed partial class PrefabUtility [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] extern public static void SetPropertyModifications(Object targetPrefab, PropertyModification[] modifications); + [FreeFunction] + extern public static bool HasPrefabInstanceAnyOverrides(GameObject instanceRoot, bool includeDefaultOverrides); + // Instantiate an asset that is referenced by a prefab and use it on the prefab instance. [FreeFunction] [NativeHeader("Editor/Src/Prefabs/AttachedPrefabAsset.h")] @@ -79,7 +82,7 @@ public sealed partial class PrefabUtility [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] [NativeThrows] - extern public static GameObject[] UnpackPrefabInstanceAndReturnNewOutermostRoots(GameObject root, PrefabUnpackMode unpackMode); + extern public static GameObject[] UnpackPrefabInstanceAndReturnNewOutermostRoots(GameObject instanceRoot, PrefabUnpackMode unpackMode); [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] [NativeThrows] @@ -158,16 +161,11 @@ internal static GameObject CreateVariant(GameObject assetRoot, string path) if (!Paths.IsValidAssetPath(path, ".prefab")) throw new ArgumentException("Given path is not valid: '" + path + "'"); -#pragma warning disable 0618 // Type or member is obsolete - return CreateVariant_Internal(assetRoot, path, ReplacePrefabOptions.Default); -#pragma warning restore 0618 // Type or member is obsolete + return CreateVariant_Internal(assetRoot, path); } - // TODO: Having an non-obsolete method that takes an obsolete enum types as parameter is no good. [NativeMethod("CreateVariant", IsFreeFunction = true)] -#pragma warning disable 0618 // Type or member is obsolete - extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path, ReplacePrefabOptions replaceOptions); -#pragma warning restore 0618 // Type or member is obsolete + extern private static GameObject CreateVariant_Internal([NotNull] GameObject original, string path); private enum PrefabCreationFlags { diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 869694c941..695db44170 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -385,21 +385,91 @@ private static void MapObjectReferencePropertyToSourceIfApplicable(SerializedPro } public static void ApplyPropertyOverride(SerializedProperty instanceProperty, string assetPath, InteractionMode action) - { - ApplyPropertyOverride(instanceProperty, assetPath, action, true); - } - - static void ApplyPropertyOverride(SerializedProperty instanceProperty, string assetPath, InteractionMode action, bool singlePropertyOnly) { DateTime startTime = DateTime.UtcNow; Object prefabInstanceObject = instanceProperty.serializedObject.targetObject; + CheckInstanceIsNotPersistent(prefabInstanceObject); + + ApplyPropertyOverrides(prefabInstanceObject, instanceProperty, assetPath, action); + + Analytics.SendApplyEvent( + Analytics.ApplyScope.PropertyOverride, + prefabInstanceObject, + assetPath, + action, + startTime, + IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty) + ); + } + + // This method is called both from ApplyPropertyOverride (one time) and ApplyObjectOverride (many times). + // In the former case, optionalSingleInstanceProperty is passed along as is the only property that should be processed. + // In the latter, all properties in the prefabInstanceObject are iterated. + // An alternative approach was considered where the method takes an array of SerializedProperties, + // but since there can be thousands of those in a component, and they would each have to be copied from the iterator, + // it's better to handle properties inline as the iterator iterates over them. + // This does mean that we need to cache the SerializedObjects that end up being touched. + // Those are that of the prefabInstanceObject itself, and the chain of corresponding object + // all the way to the Prefab at the specified assetPath. + // Since calling ApplyModifiedProperties on a SerializedObject can trigger a whole chain of imports, + // we don't want to create and call ApplyModifiedProperties more than once for each SerializedObject, hence the caching. + // We also can't swap the inner and outer loop, iterating the chain of corresponding objects in the outer loop + // and the SerializedProperties in the inner loop, since we only process overridden properties, so it would + // again require storing information about that for each property in some kind of list, which we want to avoid. + static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProperty optionalSingleInstanceProperty, string assetPath, InteractionMode action) + { + bool singleProperty = optionalSingleInstanceProperty != null; Object prefabSourceObject = GetCorrespondingObjectFromSourceAtPath(prefabInstanceObject, assetPath); if (prefabSourceObject == null) return; - if (IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty) && IsObjectOnRootInAsset(prefabInstanceObject, assetPath)) + SerializedObject prefabSourceSerializedObject = new SerializedObject(prefabSourceObject); + + // Cache SerializedObjects used. + List serializedObjects = new List(); + + bool isObjectOnRootInAsset = IsObjectOnRootInAsset(prefabInstanceObject, assetPath); + if (singleProperty) + { + if (optionalSingleInstanceProperty.prefabOverride) + ApplySingleProperty(optionalSingleInstanceProperty, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, true, serializedObjects, action); + } + else + { + SerializedObject so = new SerializedObject(prefabInstanceObject); + SerializedProperty property = so.GetIterator(); + while (property.Next(property.hasChildren)) + { + if (property.prefabOverride) + ApplySingleProperty(property, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, false, serializedObjects, action); + } + } + + // Write modified value to prefab source object. + for (int i = 0; i < serializedObjects.Count; i++) + { + serializedObjects[i].ApplyModifiedProperties(); + if (action == InteractionMode.UserAction) + Undo.FlushUndoRecordObjects(); // flush'es ensure that SavePrefab() on undo/redo on the source happens in the right order + } + } + + // Since method is called for each overridden property in a component. + // That may be thousands of times if a component has lots of array data. + // We provide as much information as possible to the method as parameters + // so we don't have to recalculate it for each call. + static void ApplySingleProperty( + SerializedProperty instanceProperty, + SerializedObject prefabSourceSerializedObject, + string assetPath, + bool isObjectOnRootInAsset, + bool singlePropertyOnly, + List serializedObjects, + InteractionMode action) + { + if (isObjectOnRootInAsset && IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty)) { if (singlePropertyOnly) { @@ -408,12 +478,14 @@ static void ApplyPropertyOverride(SerializedProperty instanceProperty, string as if (action == InteractionMode.AutomatedAction) Debug.LogWarning("Cannot apply default-override property, since it is protected from being applied or reverted."); else - EditorUtility.DisplayDialog("Cannot apply default-override property", "Default-override properties are protected from being applied or reverted.", "OK"); + EditorUtility.DisplayDialog( + "Cannot apply default-override property", + "Default-override properties are protected from being applied or reverted.", + "OK"); } return; } - SerializedObject prefabSourceSerializedObject = new SerializedObject(prefabSourceObject); prefabSourceSerializedObject.CopyFromSerializedProperty(instanceProperty); SerializedProperty sourceProperty = prefabSourceSerializedObject.FindProperty(instanceProperty.propertyPath); @@ -432,47 +504,46 @@ static void ApplyPropertyOverride(SerializedProperty instanceProperty, string as if (action == InteractionMode.AutomatedAction) Debug.LogWarning("Cannot apply reference to scene object that is not part of apply target prefab."); else - EditorUtility.DisplayDialog("Cannot apply reference to object in scene", "A reference to an object in the scene cannot be applied to the Prefab asset.", "OK"); + EditorUtility.DisplayDialog( + "Cannot apply reference to object in scene", + "A reference to an object in the scene cannot be applied to the Prefab asset.", + "OK"); } return; } } - // Write modified value to prefab source object. - prefabSourceSerializedObject.ApplyModifiedProperties(); + // Apply target SerializedObject should get ApplyModifiedProperties called first. + if (serializedObjects.Count == 0) + serializedObjects.Add(prefabSourceSerializedObject); - if (action == InteractionMode.UserAction) - Undo.FlushUndoRecordObjects(); // flush'es ensure that SavePrefab() on undo/redo on the source happens in the right order - - // Clear overrides for property in prefab instance and outer prefabs that are using(nesting) the prefab source. + // Clear overrides for property in Prefab instance and outer Prefabs that are using(nesting) the Prefab source. // Otherwise applied modification would appear to jump back to the value it had before applying. + Object prefabInstanceObject = instanceProperty.serializedObject.targetObject; + Object prefabSourceObject = prefabSourceSerializedObject.targetObject; Object outerPrefabObject = prefabInstanceObject; + int sourceIndex = 1; while (outerPrefabObject != prefabSourceObject) { - SerializedObject outerPrefabSerializedObject = new SerializedObject(outerPrefabObject); + SerializedObject outerPrefabSerializedObject; + if (sourceIndex >= serializedObjects.Count) + { + outerPrefabSerializedObject = new SerializedObject(outerPrefabObject); + serializedObjects.Add(outerPrefabSerializedObject); + } + else + { + outerPrefabSerializedObject = serializedObjects[sourceIndex]; + } + SerializedProperty outerPrefabProp = outerPrefabSerializedObject.FindProperty(instanceProperty.propertyPath); if (outerPrefabProp.prefabOverride) { outerPrefabProp.prefabOverride = false; - outerPrefabSerializedObject.ApplyModifiedProperties(); - - if (action == InteractionMode.UserAction) - Undo.FlushUndoRecordObjects(); } - outerPrefabObject = PrefabUtility.GetCorrespondingObjectFromSource(outerPrefabObject); - } - // If this method is called as part of ApplyObjectOverride, we don't want to send analytics here too. - if (singlePropertyOnly) - { - Analytics.SendApplyEvent( - Analytics.ApplyScope.PropertyOverride, - prefabInstanceObject, - assetPath, - action, - startTime, - IsPropertyOverrideDefaultOverrideComparedToAnySource(instanceProperty) - ); + outerPrefabObject = PrefabUtility.GetCorrespondingObjectFromSource(outerPrefabObject); + sourceIndex++; } } @@ -492,13 +563,7 @@ public static void ApplyObjectOverride(Object instanceComponentOrGameObject, str CheckInstanceIsNotPersistent(instanceComponentOrGameObject); - SerializedObject so = new SerializedObject(instanceComponentOrGameObject); - SerializedProperty property = so.GetIterator(); - while (property.Next(property.hasChildren)) - { - if (property.prefabOverride) - ApplyPropertyOverride(property, assetPath, action, false); - } + ApplyPropertyOverrides(instanceComponentOrGameObject, null, assetPath, action); Analytics.SendApplyEvent( Analytics.ApplyScope.ObjectOverride, @@ -963,21 +1028,21 @@ public static GameObject SavePrefabAsset(GameObject asset) #pragma warning restore CS0618 // Type or member is obsolete } - private static void SaveAsPrefabAssetArgumentCheck(GameObject root) + private static void SaveAsPrefabAssetArgumentCheck(GameObject instanceRoot) { - if (root == null) + if (instanceRoot == null) throw new ArgumentNullException("Parameter root is null"); - if (EditorUtility.IsPersistent(root)) + if (EditorUtility.IsPersistent(instanceRoot)) throw new ArgumentException("Can't save persistent object as a Prefab asset"); - if (IsPrefabAssetMissing(root)) + if (IsPrefabAssetMissing(instanceRoot)) throw new ArgumentException("Can't save Prefab instance with missing asset as a Prefab. You may unpack the instance and save the unpacked GameObjects as a Prefab."); - var instanceRoot = GetOutermostPrefabInstanceRoot(root); - if (instanceRoot) + var actualInstanceRoot = GetOutermostPrefabInstanceRoot(instanceRoot); + if (actualInstanceRoot) { - if (instanceRoot != root) + if (actualInstanceRoot != instanceRoot) throw new ArgumentException("Can't save part of a Prefab instance as a Prefab"); } } @@ -988,41 +1053,41 @@ private static bool IsPrefabInstanceRoot(GameObject gameObject) return instanceRoot != null && instanceRoot == gameObject; } - public static GameObject SaveAsPrefabAsset(GameObject root, string assetPath) + public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath) { - SaveAsPrefabAssetArgumentCheck(root); + SaveAsPrefabAssetArgumentCheck(instanceRoot); PrefabCreationFlags creationFlags = PrefabCreationFlags.None; - if (IsPrefabInstanceRoot(root)) + if (IsPrefabInstanceRoot(instanceRoot)) creationFlags = PrefabCreationFlags.CreateVariant; #pragma warning disable CS0618 // Type or member is obsolete - return SavePrefab(root, assetPath, ReplacePrefabOptions.Default, creationFlags); + return SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.Default, creationFlags); #pragma warning restore CS0618 // Type or member is obsolete } - public static GameObject SaveAsPrefabAssetAndConnect(GameObject root, string assetPath, InteractionMode action) + public static GameObject SaveAsPrefabAssetAndConnect(GameObject instanceRoot, string assetPath, InteractionMode action) { - SaveAsPrefabAssetArgumentCheck(root); + SaveAsPrefabAssetArgumentCheck(instanceRoot); var actionName = "Connect to Prefab"; if (action == InteractionMode.UserAction) { - Undo.RegisterFullObjectHierarchyUndo(root, actionName); + Undo.RegisterFullObjectHierarchyUndo(instanceRoot, actionName); } PrefabCreationFlags creationFlags = PrefabCreationFlags.None; - if (IsPrefabInstanceRoot(root)) + if (IsPrefabInstanceRoot(instanceRoot)) creationFlags = PrefabCreationFlags.CreateVariant; #pragma warning disable CS0618 // Type or member is obsolete - var assetRoot = SavePrefab(root, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags); + var assetRoot = SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags); #pragma warning restore CS0618 // Type or member is obsolete if (action == InteractionMode.UserAction) { - Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(root), actionName); + Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(instanceRoot), actionName); } return assetRoot; @@ -1105,6 +1170,11 @@ public static GameObject CreatePrefab(string path, GameObject go, ReplacePrefabO { if (options == ReplacePrefabOptions.ConnectToPrefab) return SaveAsPrefabAssetAndConnect(go, path, InteractionMode.AutomatedAction); + else if ((options & ReplacePrefabOptions.ReplaceNameBased) != 0) + { + bool connectToPrefab = (options & ReplacePrefabOptions.ConnectToPrefab) != 0; + return ReplacePrefabAssetNameBased(go, path, connectToPrefab); + } else return SaveAsPrefabAsset(go, path); } @@ -1300,44 +1370,55 @@ internal enum SaveVerb Save, Apply } + internal static bool PromptAndCheckoutPrefabIfNeeded(string assetPath, SaveVerb saveVerb) { + return PromptAndCheckoutPrefabIfNeeded(new string[] { assetPath }, saveVerb); + } + + internal static bool PromptAndCheckoutPrefabIfNeeded(string[] assetPaths, SaveVerb saveVerb) + { + string prefabNoun = assetPaths.Length > 1 ? "Prefabs" : "Prefab"; bool result = Provider.PromptAndCheckoutIfNeeded( - new string[] { assetPath }, + assetPaths, String.Format( - "The version control requires you to check out the Prefab before {0} changes.", - saveVerb == SaveVerb.Save ? "saving" : "applying") + "The version control requires you to check out the {1} before {0} changes.", + saveVerb == SaveVerb.Save ? "saving" : "applying", + prefabNoun + ) ); if (!result) EditorUtility.DisplayDialog( String.Format( - "Could not {0} Prefab", - saveVerb == SaveVerb.Save ? "save" : "apply to"), + "Could not {0} {1}", + saveVerb == SaveVerb.Save ? "save" : "apply to", + prefabNoun), String.Format( - "It was not possible to check out the Prefab so the {0} operation has been canceled.", - saveVerb == SaveVerb.Save ? "save" : "apply"), + "It was not possible to check out the {1} so the {0} operation has been canceled.", + saveVerb == SaveVerb.Save ? "save" : "apply", + prefabNoun), "OK"); return result; } - public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpackMode, InteractionMode action) + public static void UnpackPrefabInstance(GameObject instanceRoot, PrefabUnpackMode unpackMode, InteractionMode action) { - if (!IsPartOfNonAssetPrefabInstance(root)) + if (!IsPartOfNonAssetPrefabInstance(instanceRoot)) throw new ArgumentException("UnpackPrefabInstance must be called with a Prefab instance."); - if (!IsOutermostPrefabInstanceRoot(root)) + if (!IsOutermostPrefabInstanceRoot(instanceRoot)) throw new ArgumentException("UnpackPrefabInstance must be called with a root Prefab instance GameObject."); if (action == InteractionMode.UserAction) { var undoActionName = "Unpack Prefab instance"; - Undo.RegisterFullObjectHierarchyUndo(root, undoActionName); - var instanceRoots = UnpackPrefabInstanceAndReturnNewOutermostRoots(root, unpackMode); - foreach (var instanceRoot in instanceRoots) + Undo.RegisterFullObjectHierarchyUndo(instanceRoot, undoActionName); + var newInstanceRoots = UnpackPrefabInstanceAndReturnNewOutermostRoots(instanceRoot, unpackMode); + foreach (var newInstanceRoot in newInstanceRoots) { - var prefabInstance = PrefabUtility.GetPrefabInstanceHandle(instanceRoot); + var prefabInstance = PrefabUtility.GetPrefabInstanceHandle(newInstanceRoot); if (prefabInstance) { Undo.RegisterCreatedObjectUndo(prefabInstance, undoActionName); @@ -1346,7 +1427,7 @@ public static void UnpackPrefabInstance(GameObject root, PrefabUnpackMode unpack } else { - UnpackPrefabInstanceAndReturnNewOutermostRoots(root, unpackMode); + UnpackPrefabInstanceAndReturnNewOutermostRoots(instanceRoot, unpackMode); } } @@ -1428,13 +1509,13 @@ public static GameObject LoadPrefabContents(string assetPath) return roots[0]; } - public static void UnloadPrefabContents(GameObject root) + public static void UnloadPrefabContents(GameObject contentsRoot) { - if (!EditorSceneManager.IsPreviewSceneObject(root)) + if (!EditorSceneManager.IsPreviewSceneObject(contentsRoot)) { throw new ArgumentException("Specified object is not part of Prefab contents"); } - var scene = root.scene; + var scene = contentsRoot.scene; EditorSceneManager.ClosePreviewScene(scene); } diff --git a/Editor/Mono/ProjectBrowser.cs b/Editor/Mono/ProjectBrowser.cs index fd04e054d5..6229ff1dda 100644 --- a/Editor/Mono/ProjectBrowser.cs +++ b/Editor/Mono/ProjectBrowser.cs @@ -1277,6 +1277,13 @@ void AssetTreeKeyboardInputCallback() OpenAssetSelection(Selection.instanceIDs); } break; + case KeyCode.Delete: + if (Event.current.shift) + { + DeleteSelectedAssets(false); + Event.current.Use(); + } + break; } } } diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index 6de9a6e44c..0b3f63498a 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -38,6 +38,8 @@ public class PrefabStage HideFlagUtility m_HideFlagUtility; Texture2D m_PrefabFileIcon; bool m_TemporarilyDisableAutoSave; + float m_LastSavingDuration = 0f; + const float kDurationBeforeShowingSavingBadge = 1.0f; bool m_AnalyticsDidUserModify; bool m_AnalyticsDidUserSave; @@ -91,6 +93,12 @@ public string prefabAssetPath get { return m_PrefabAssetPath; } } + internal bool showingSavingLabel + { + get; + private set; + } + internal Texture2D prefabFileIcon { get { return m_PrefabFileIcon; } @@ -268,7 +276,7 @@ void HandleAutoSave() { if (autoSave && readyToAutoSave) { - SavePrefabWithVersionControlDialogAndRenameDialog(); + AutoSave(); } } @@ -298,7 +306,7 @@ public void ClearDirtiness() m_InitialSceneDirtyID = m_PreviewScene.dirtyID; } - // Not private so we use it in Tests + // Is internal so we can use it in Tests internal void SavePrefab() { if (!initialized) @@ -313,7 +321,9 @@ internal void SavePrefab() if (prefabSaving != null) prefabSaving(m_PrefabContentsRoot); + var startTime = EditorApplication.timeSinceStartup; var prefabAssetRoot = PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath); + m_LastSavingDuration = (float)(EditorApplication.timeSinceStartup - startTime); if (prefabAssetRoot != null) { @@ -325,6 +335,8 @@ internal void SavePrefab() if (SceneHierarchy.s_DebugPrefabStage) Debug.Log("SAVE PREFAB ended"); + + showingSavingLabel = false; } internal bool SaveAsNewPrefab(string newPath, bool asCopy) @@ -394,6 +406,30 @@ internal bool SaveAsNewPrefabWithSavePanel() return SaveAsNewPrefab(relativePath, false); } + void PerformDelayedAutoSave() + { + EditorApplication.update -= PerformDelayedAutoSave; + SavePrefabWithVersionControlDialogAndRenameDialog(); + } + + void AutoSave() + { + showingSavingLabel = m_LastSavingDuration > kDurationBeforeShowingSavingBadge; + if (showingSavingLabel) + { + // Save delayed if we want to show the save badge while saving. + foreach (SceneView sceneView in SceneView.sceneViews) + sceneView.Repaint(); + + EditorApplication.update += PerformDelayedAutoSave; + } + else + { + // Save directly if we don't want to show the saving badge + SavePrefabWithVersionControlDialogAndRenameDialog(); + } + } + // Returns true if prefab was saved. internal bool SavePrefabWithVersionControlDialogAndRenameDialog() { diff --git a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs index 64c5a47251..3479ab3321 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs @@ -373,8 +373,8 @@ private void ClampFilterType(SerializedProperty filter) if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) { // Force unsupported A-Trous filter back to Gaussian. - if (filter.intValue == 1) - filter.intValue = 0; + if (filter.intValue == (int)LightmapEditorSettings.FilterType.ATrous) + filter.intValue = (int)LightmapEditorSettings.FilterType.Gaussian; } } @@ -397,11 +397,10 @@ void GeneralLightmapSettingsGUI() { EditorGUI.BeginChangeCheck(); - //TODO(RadeonRays) Remove this when GPU lightmapper is public. - - if (Unsupported.IsDeveloperMode() && (Application.platform == RuntimePlatform.WindowsEditor)) + //TODO(RadeonRays): Remove this when GPU lightmapper works on macOS and Linux. + if (Application.platform != RuntimePlatform.WindowsEditor) { - var backendOptions = new[] { "Enlighten", "Progressive CPU", "Progressive GPU (Preview)" }; + var backendOptions = new[] { "Enlighten", "Progressive CPU" }; m_BakeBackend.intValue = EditorGUILayout.Popup(Styles.BakeBackend, m_BakeBackend.intValue, backendOptions); } else @@ -460,13 +459,12 @@ void GeneralLightmapSettingsGUI() { EditorGUI.indentLevel++; - // TODO(RadeonRays): Hiding A-trous until it is implemented. - var filterOptions = new[] { EditorGUIUtility.TextContent("Gaussian"), EditorGUIUtility.TextContent("None") }; - var filterInts = new[] { 0, 2 }; + if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) + EditorGUILayout.HelpBox(Styles.ProgressiveGPUWarning.text, MessageType.Info); ClampFilterType(m_PVRFilterTypeDirect); if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.IntPopup(m_PVRFilterTypeDirect, filterOptions, filterInts, Styles.PVRFilterTypeDirect); + EditorGUILayout.IntPopup(m_PVRFilterTypeDirect, Styles.GPUFilterOptions, Styles.GPUFilterInts, Styles.PVRFilterTypeDirect); else EditorGUILayout.PropertyField(m_PVRFilterTypeDirect, Styles.PVRFilterTypeDirect); @@ -479,7 +477,7 @@ void GeneralLightmapSettingsGUI() EditorGUILayout.Space(); if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.IntPopup(m_PVRFilterTypeIndirect, filterOptions, filterInts, Styles.PVRFilterTypeIndirect); + EditorGUILayout.IntPopup(m_PVRFilterTypeIndirect, Styles.GPUFilterOptions, Styles.GPUFilterInts, Styles.PVRFilterTypeIndirect); else EditorGUILayout.PropertyField(m_PVRFilterTypeIndirect, Styles.PVRFilterTypeIndirect); ClampFilterType(m_PVRFilterTypeIndirect); @@ -493,7 +491,7 @@ void GeneralLightmapSettingsGUI() { EditorGUILayout.Space(); if (LightmapEditorSettings.lightmapper == LightmapEditorSettings.Lightmapper.ProgressiveGPU) - EditorGUILayout.IntPopup(m_PVRFilterTypeAO, filterOptions, filterInts, Styles.PVRFilterTypeAO); + EditorGUILayout.IntPopup(m_PVRFilterTypeAO, Styles.GPUFilterOptions, Styles.GPUFilterInts, Styles.PVRFilterTypeAO); else EditorGUILayout.PropertyField(m_PVRFilterTypeAO, Styles.PVRFilterTypeAO); ClampFilterType(m_PVRFilterTypeAO); @@ -711,6 +709,10 @@ static class Styles public static readonly GUIContent PVRFilteringAtrousPositionSigmaIndirect = EditorGUIUtility.TrTextContent("Indirect Sigma", "Controls the threshold of the filter for indirect light stored in the lightmap. A higher value will increase the threshold, reducing noise in the indirect layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap."); public static readonly GUIContent PVRFilteringAtrousPositionSigmaAO = EditorGUIUtility.TrTextContent("Ambient Occlusion Sigma", "Controls the threshold of the filter for ambient occlusion stored in the lightmap. A higher value will increase the threshold, reducing noise in the ambient occlusion layer of the lightmap. Too high of a value can cause a loss of detail in the lightmap."); public static readonly GUIContent PVRCulling = EditorGUIUtility.TrTextContent("Prioritize View", "Specifies whether the lightmapper should prioritize baking texels within the scene view. When disabled, objects outside the scene view will have the same priority as those in the scene view."); + // TODO(RadeonRays): Used for hiding A-trous filtering option until it is implemented. + public static readonly GUIContent[] GPUFilterOptions = new[] { EditorGUIUtility.TrTextContent("Gaussian"), EditorGUIUtility.TrTextContent("None") }; + public static readonly int[] GPUFilterInts = new[] { (int)LightmapEditorSettings.FilterType.Gaussian, (int)LightmapEditorSettings.FilterType.None }; + public static readonly GUIContent ProgressiveGPUWarning = EditorGUIUtility.TrTextContent("A-Trous filtering is not implemented in the Progressive GPU lightmapper yet. Use the CPU lightmapper instead if you need this functionality."); } } } // namespace diff --git a/Editor/Mono/SceneView/SceneViewStageHandling.cs b/Editor/Mono/SceneView/SceneViewStageHandling.cs index 9f45d1315c..4173497993 100644 --- a/Editor/Mono/SceneView/SceneViewStageHandling.cs +++ b/Editor/Mono/SceneView/SceneViewStageHandling.cs @@ -36,11 +36,13 @@ static bool autoSave static class Styles { - public static GUIContent autoSaveGUIContent = EditorGUIUtility.TrTextContent("Auto Save"); + public static GUIContent autoSaveGUIContent = EditorGUIUtility.TrTextContent("Auto Save", "When Auto Save is enabled, every change you make is automatically saved to the Prefab Asset. Disable Auto Save if you experience long import times."); public static GUIContent saveButtonContent = EditorGUIUtility.TrTextContent("Save"); public static GUIContent checkoutButtonContent = EditorGUIUtility.TrTextContent("Check Out"); + public static GUIContent autoSavingBadgeContent = EditorGUIUtility.TrTextContent("Auto Saving..."); public static GUIStyle saveToggle; public static GUIStyle button; + public static GUIStyle savingBadge = "Badge"; static Styles() { @@ -232,16 +234,14 @@ void AutoSaveButtons() { StatusQueryOptions opts = EditorUserSettings.allowAsyncStatusUpdate ? StatusQueryOptions.UseCachedAsync : StatusQueryOptions.UseCachedIfPossible; bool openForEdit = AssetDatabase.IsOpenForEdit(item.prefabAssetPath, opts); - if (!openForEdit) + + PrefabStage stage = item.prefabStage; + if (stage.showingSavingLabel) { - if (GUILayout.Button(Styles.checkoutButtonContent, Styles.button)) - { - Task task = Provider.Checkout(AssetDatabase.LoadAssetAtPath(item.prefabAssetPath), CheckoutMode.Both); - task.Wait(); - } + GUILayout.Label(Styles.autoSavingBadgeContent, Styles.savingBadge); + GUILayout.Space(4); } - PrefabStage stage = item.prefabStage; if (!stage.autoSave) { using (new EditorGUI.DisabledScope(!openForEdit || !PrefabStageUtility.GetCurrentPrefabStage().HasSceneBeenModified())) @@ -259,6 +259,15 @@ void AutoSaveButtons() if (EditorGUI.EndChangeCheck()) stage.autoSave = autoSaveForScene; } + + if (!openForEdit) + { + if (GUILayout.Button(Styles.checkoutButtonContent, Styles.button)) + { + Task task = Provider.Checkout(AssetDatabase.LoadAssetAtPath(item.prefabAssetPath), CheckoutMode.Both); + task.Wait(); + } + } } } diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs index 19a5762ed3..fb95d0cfa4 100644 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs @@ -183,7 +183,8 @@ protected override Program StartCompiler() arguments.Add("/unsafe"); var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); - if (!_island._development_player) + var disableOptimizations = _island._development_player || (_island._editor && EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true)); + if (!disableOptimizations) { if (PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) arguments.Add("/debug:pdbonly"); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index d9ea366d92..6cab818501 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -148,7 +148,9 @@ public override void PostprocessMessage(ref CompilerMessage message) var index = message.message.IndexOf(EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest ? "Consider adding a reference to that assembly." : "Consider adding a reference to assembly"); if (index != -1) message.message = message.message.Substring(0, index); - var moduleName = GetNiceDisplayNameForModule(match.Groups[1].Value); + var moduleName = match.Groups[1].Value; + moduleName = ModuleMetadata.GetExcludingModule(moduleName); + moduleName = GetNiceDisplayNameForModule(moduleName); message.message += string.Format("Enable the built in package '{0}' in the Package Manager window to fix this error.", moduleName); } diff --git a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs index c00bc409b7..7063a34d06 100644 --- a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs +++ b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs @@ -8,6 +8,7 @@ using UnityEngine.Experimental.UIElements; using UnityEngine.Internal; using UnityEditor.StyleSheets; +using UnityEditorInternal; namespace UnityEditor { @@ -68,9 +69,20 @@ public override void OnDeactivate() public override void OnGUI(string searchContext) { if (m_SettingsEditor != null) + { using (new SettingsWindow.GUIScope()) m_SettingsEditor.OnInspectorGUI(); + // Emulate the Inspector by handling DnD at the native level. + var remainingRect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true)); + if ((Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && remainingRect.Contains(Event.current.mousePosition)) + { + DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(new[] { m_SettingsEditor.target }, Event.current.type == EventType.DragPerform); + if (Event.current.type == EventType.DragPerform) + DragAndDrop.AcceptDrag(); + } + } + base.OnGUI(searchContext); } diff --git a/Editor/Mono/Settings/SettingsService.cs b/Editor/Mono/Settings/SettingsService.cs index 61c625bdeb..8ca28cfcb2 100644 --- a/Editor/Mono/Settings/SettingsService.cs +++ b/Editor/Mono/Settings/SettingsService.cs @@ -6,14 +6,23 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Text; using UnityEngine; using UnityEngine.Internal; namespace UnityEditor { [ExcludeFromDocs] + [InitializeOnLoad] public class SettingsService { + const string k_ProjectSettings = "Edit/Project Settings"; + static SettingsService() + { + EditorApplication.update -= CheckProjectSettings; + EditorApplication.update += CheckProjectSettings; + } + public static event Action settingsProviderChanged; public static SettingsProvider[] FetchSettingsProviders() @@ -31,6 +40,22 @@ public static void NotifySettingsProviderChanged() settingsProviderChanged?.Invoke(); } + private static void CheckProjectSettings() + { + EditorApplication.update -= CheckProjectSettings; + + var deprecatedMenuItems = Menu.ExtractSubmenus(k_ProjectSettings); + if (deprecatedMenuItems.Length > 0) + { + var sb = new StringBuilder(); + sb.Append("There are menu items registered under Edit/Project Settings: "); + sb.Append(string.Join(", ", deprecatedMenuItems.Select(item => item.Replace(k_ProjectSettings + "/", "")).ToArray())); + sb.Append("\n"); + sb.AppendLine("Consider using [SettingsProvider] attribute to register in the Unified Settings Window."); + Debug.LogWarning(sb); + } + } + private static IEnumerable FetchPreferenceItems() { var methods = AttributeHelper.GetMethodsWithAttribute(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); @@ -39,8 +64,8 @@ private static IEnumerable FetchPreferenceItems() var callback = Delegate.CreateDelegate(typeof(Action), method.info) as Action; if (callback != null) { - Debug.LogWarning("PreferenceItem is deprecated. Use [SettingsProvider] instead"); var attributeName = (method.attribute as PreferenceItem).name; + Debug.LogWarning($"Trying to register preference item: \"{attributeName}\". [PreferenceItem] attribute is deprecated. Use [SettingsProvider] attribute instead."); return new SettingsProvider("Preferences/" + attributeName) { guiHandler = searchContext => callback(), scopes = SettingsScopes.User }; } diff --git a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs index e62e1ea2e5..d507ba77b3 100644 --- a/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs +++ b/Editor/Mono/SpriteEditor/SpriteEditorWindow.cs @@ -103,8 +103,8 @@ private void OnFocus() public void RefreshPropertiesCache() { - m_SpriteDataProvider = AssetImporter.GetAtPath(m_SelectedAssetPath) as ISpriteEditorDataProvider; - if (m_SpriteDataProvider == null) + m_SpriteDataProvider = AssetImporter.GetAtPath(m_SelectedAssetPath) as ISpriteEditorDataProvider; + if (!IsSpriteDataProviderValid()) { m_SelectedAssetPath = ""; return; @@ -156,7 +156,7 @@ private Rect warningMessageRect public SpriteImportMode spriteImportMode { - get { return m_SpriteDataProvider == null ? SpriteImportMode.None : m_SpriteDataProvider.spriteImportMode; } + get { return !IsSpriteDataProviderValid() ? SpriteImportMode.None : m_SpriteDataProvider.spriteImportMode; } } bool activeDataProviderSelected @@ -352,7 +352,7 @@ void OnEditorApplicationQuit() void HandleApplyRevertDialog(string dialogTitle, string dialogContent) { - if (textureIsDirty && m_SpriteDataProvider != null) + if (textureIsDirty && IsSpriteDataProviderValid()) { if (EditorUtility.DisplayDialog(dialogTitle, dialogContent, SpriteEditorWindowStyles.applyButtonLabel.text, SpriteEditorWindowStyles.revertButtonLabel.text)) @@ -364,10 +364,15 @@ void HandleApplyRevertDialog(string dialogTitle, string dialogContent) } } + bool IsSpriteDataProviderValid() + { + return m_SpriteDataProvider != null && !m_SpriteDataProvider.Equals(null); + } + void RefreshRects() { m_RectsCache = null; - if (m_SpriteDataProvider != null) + if (IsSpriteDataProviderValid()) { m_RectsCache = m_SpriteDataProvider.GetSpriteRects().ToList(); } @@ -379,7 +384,7 @@ private void Update() { if (m_ResetOnNextRepaint || selectedProviderChanged) { - if (selectedProviderChanged || m_SpriteDataProvider == null) + if (selectedProviderChanged || !IsSpriteDataProviderValid()) m_SelectedAssetPath = GetSelectionAssetPath(); RebuildCache(); } @@ -393,7 +398,6 @@ private void RebuildCache() RefreshPropertiesCache(); RefreshRects(); UpdateAvailableModules(); - SetupModule(m_CurrentModuleIndex); } private void DoTextureAndModulesGUI() @@ -735,7 +739,7 @@ void UpdateAvailableModules() } m_RegisteredModuleNames = new GUIContent[m_RegisteredModules.Count]; - int lastUsedModuleIndex = -1; + int lastUsedModuleIndex = 0; for (int i = 0; i < m_RegisteredModules.Count; i++) { m_RegisteredModuleNames[i] = new GUIContent(m_RegisteredModules[i].moduleName); @@ -745,10 +749,7 @@ void UpdateAvailableModules() } } - if (lastUsedModuleIndex >= 0) - SetupModule(lastUsedModuleIndex); - else - SetupModule(0); + SetupModule(lastUsedModuleIndex); } void InitModules() diff --git a/Editor/Mono/UIElements/Controls/CurveField.cs b/Editor/Mono/UIElements/Controls/CurveField.cs index a6c6f02794..e6a2f58051 100644 --- a/Editor/Mono/UIElements/Controls/CurveField.cs +++ b/Editor/Mono/UIElements/Controls/CurveField.cs @@ -149,6 +149,7 @@ public override void SetValueWithoutNotify(AnimationCurve newValue) m_Value.postWrapMode = WrapMode.Once; } m_TextureDirty = true; + CurveEditorWindow.curve = m_Value; IncrementVersion(VersionChangeType.Repaint); @@ -237,8 +238,8 @@ void FillCurveData() normals = new Vector3[k_HorizontalCurveResolution * 2]; } - float startTime = 0; - float endTime = curve.keys.Length > 0 ? curve.keys[curve.keys.Length - 1].time : 1.0f; + float startTime = curve.keys[0].time; + float endTime = curve.keys[curve.keys.Length - 1].time; float duration = endTime - startTime; float minValue = Mathf.Infinity; diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs index 69162be0eb..2cb70ecd12 100644 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs @@ -101,6 +101,7 @@ private void RefreshVRDeviceList(BuildTargetGroup targetGroup) customOptions = new VRCustomOptionsNone(); } customOptions.Initialize(m_Settings.serializedObject); + customOptions.IsExpanded = true; m_CustomOptions.Add(deviceInfo.deviceNameKey, customOptions); } } @@ -390,7 +391,16 @@ private void AddVRDeviceElement(BuildTargetGroup target, Rect rect, ReorderableL private void RemoveVRDeviceElement(BuildTargetGroup target, ReorderableList list) { var devices = VREditor.GetVREnabledDevicesOnTargetGroup(target).ToList(); + var device = devices[list.index]; devices.RemoveAt(list.index); + + VRCustomOptions customOptions; + if (m_CustomOptions.TryGetValue(device, out customOptions)) + { + customOptions.IsExpanded = true; + } + + ApplyChangedVRDeviceList(target, devices.ToArray()); } diff --git a/Modules/AI/NavMesh/NavMesh.bindings.cs b/Modules/AI/NavMesh/NavMesh.bindings.cs index 0074c422aa..86023f6ec2 100644 --- a/Modules/AI/NavMesh/NavMesh.bindings.cs +++ b/Modules/AI/NavMesh/NavMesh.bindings.cs @@ -10,7 +10,7 @@ namespace UnityEngine.AI public static partial class NavMesh { [StaticAccessor("GetNavMeshManager()")] - [NativeName("Cleanup")] + [NativeName("CleanupAfterCarving")] public static extern void RemoveAllNavMeshData(); } } diff --git a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs index f11f5c3c8d..af951453d3 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterEditor.cs @@ -11,6 +11,8 @@ namespace UnityEditor [CanEditMultipleObjects] internal class ModelImporterEditor : AssetImporterTabbedEditor { + static string s_LocalizedTitle = L10n.Tr("Model Import Settings"); + public override void OnEnable() { if (tabs == null) @@ -47,5 +49,16 @@ public override GUIContent GetPreviewTitle() // Only show the imported GameObject when the Model tab is active; not when the Animation tab is active public override bool showImportedObject { get { return activeTab is ModelImporterModelEditor; } } + + internal override string targetTitle + { + get + { + if (assetTargets == null || assetTargets.Length == 1 || !m_AllowMultiObjectAccess) + return base.targetTitle; + else + return assetTargets.Length + " " + s_LocalizedTitle; + } + } } } diff --git a/Modules/IMGUI/GUIStyle.cs b/Modules/IMGUI/GUIStyle.cs index 074efdb66a..7e90f54d74 100644 --- a/Modules/IMGUI/GUIStyle.cs +++ b/Modules/IMGUI/GUIStyle.cs @@ -80,6 +80,11 @@ public GUIStyle() // Constructs GUIStyle identical to given other GUIStyle. public GUIStyle(GUIStyle other) { + if (other == null) + { + Debug.LogError("Copied style is null. Using StyleNotFound instead."); + other = GUISkin.error; + } m_Ptr = Internal_Copy(this, other); } diff --git a/Modules/PresetsEditor/PresetManagerEditor.cs b/Modules/PresetsEditor/PresetManagerEditor.cs index 7a91f1785f..31d983ae32 100644 --- a/Modules/PresetsEditor/PresetManagerEditor.cs +++ b/Modules/PresetsEditor/PresetManagerEditor.cs @@ -147,6 +147,7 @@ void DrawElementCallback(Rect rect, int index, bool isActive, bool isFocused) case EventType.MouseDown: if (buttonRect.Contains(Event.current.mousePosition)) { + RefreshAddList(); var menu = new GenericMenu(); if (m_DiscoveredPresets.ContainsKey(keyType)) { diff --git a/Modules/ShortcutManagerEditor/ConflictResolver.cs b/Modules/ShortcutManagerEditor/ConflictResolver.cs index e54fc6df84..0a6cde0f5a 100644 --- a/Modules/ShortcutManagerEditor/ConflictResolver.cs +++ b/Modules/ShortcutManagerEditor/ConflictResolver.cs @@ -12,7 +12,7 @@ namespace UnityEditor.ShortcutManagement { class ConflictResolver : IConflictResolver { - public void ResolveConflict(List keyCombinationSequence, List entries) + public void ResolveConflict(IEnumerable keyCombinationSequence, IEnumerable entries) { var builder = new StringBuilder(); diff --git a/Modules/ShortcutManagerEditor/ContextManager.cs b/Modules/ShortcutManagerEditor/ContextManager.cs index 9a0de4c520..c6709cd1f7 100644 --- a/Modules/ShortcutManagerEditor/ContextManager.cs +++ b/Modules/ShortcutManagerEditor/ContextManager.cs @@ -16,6 +16,7 @@ interface IContextManager bool HasAnyPriorityContext(); bool HasPriorityContextOfType(Type type); bool HasActiveContextOfType(Type type); + bool playModeContextIsActive { get; } object GetContextInstanceOfType(Type type); } @@ -32,7 +33,19 @@ internal class GlobalContext {} List m_ToolContexts = new List(); - public int activeContextCount => 1 + ((m_FocusedWindow != null && m_FocusedWindow.IsAlive && m_FocusedWindow.Target != null) ? 1 : 0) + m_PriorityContexts.Count(c => c.active) + m_ToolContexts.Count(c => c.active); + public int activeContextCount => 1 + ((focusedWindow != null) ? 1 : 0) + m_PriorityContexts.Count(c => c.active) + m_ToolContexts.Count(c => c.active); + + public bool playModeContextIsActive => focusedWindow is GameView && EditorApplication.isPlaying; + + private EditorWindow focusedWindow + { + get + { + if (m_FocusedWindow != null && m_FocusedWindow.IsAlive && m_FocusedWindow.Target != null) + return m_FocusedWindow.Target as EditorWindow; + return null; + } + } public void SetFocusedWindow(EditorWindow window) { diff --git a/Modules/ShortcutManagerEditor/Directory.cs b/Modules/ShortcutManagerEditor/Directory.cs index e718465fd2..05f04b2292 100644 --- a/Modules/ShortcutManagerEditor/Directory.cs +++ b/Modules/ShortcutManagerEditor/Directory.cs @@ -56,6 +56,12 @@ public void FindShortcutEntries(List combinationSequence, IConte { if (!contextManager.HasActiveContextOfType(shortcutEntry.context)) continue; + if (shortcutEntry.type != ShortcutType.Menu && contextManager.playModeContextIsActive) + // Emulate old play mode shortcut behavior + // * Menu shortcuts are always active + // * Non-menu shortcuts only apply when the game view does not have focus + continue; + outputShortcuts.Add(shortcutEntry); } } diff --git a/Modules/ShortcutManagerEditor/IConflictResolver.cs b/Modules/ShortcutManagerEditor/IConflictResolver.cs index 06f79d4fdf..845e86f5e0 100644 --- a/Modules/ShortcutManagerEditor/IConflictResolver.cs +++ b/Modules/ShortcutManagerEditor/IConflictResolver.cs @@ -8,5 +8,5 @@ interface IConflictResolver { - void ResolveConflict(List keyCombinationSequence, List entries); + void ResolveConflict(IEnumerable keyCombinationSequence, IEnumerable entries); } diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index b388a2588a..e6ccda2c44 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -64,26 +64,24 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) return; m_Directory.FindShortcutEntries(m_KeyCombinationSequence, contextManager, m_Entries); + IEnumerable entries = m_Entries; // Deal ONLY with prioritycontext - if (m_Entries.Count > 1 && contextManager.HasAnyPriorityContext()) + if (entries.Count() > 1 && contextManager.HasAnyPriorityContext()) { - var entry = m_Entries.FindAll(a => contextManager.HasPriorityContextOfType(a.context)); - if (entry.Any()) - { - m_Entries.Clear(); - m_Entries.AddRange(entry); - } + entries = m_Entries.FindAll(a => contextManager.HasPriorityContextOfType(a.context)); + if (!entries.Any()) + entries = m_Entries; } - switch (m_Entries.Count) + switch (entries.Count()) { case 0: Reset(); break; case 1: - var shortcutEntry = m_Entries.Single(); + var shortcutEntry = entries.Single(); if (ShortcutFullyMatchesKeyCombination(shortcutEntry)) { if (evt.keyCode != m_KeyCombinationSequence.Last().keyCode) @@ -121,9 +119,9 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) break; default: - if (HasConflicts(m_Entries, m_KeyCombinationSequence)) + if (HasConflicts(entries, m_KeyCombinationSequence)) { - m_ConflictResolver.ResolveConflict(m_KeyCombinationSequence, m_Entries); + m_ConflictResolver.ResolveConflict(m_KeyCombinationSequence, entries); Reset(); } break; @@ -136,10 +134,10 @@ public bool HasAnyEntries() } // filtered entries are expected to all be in the same context and/or null context and they all are known to share the prefix - bool HasConflicts(List filteredEntries, List prefix) + bool HasConflicts(IEnumerable filteredEntries, List prefix) { if (filteredEntries.Any(e => e.FullyMatches(prefix))) - return filteredEntries.Count > 1; + return filteredEntries.Count() > 1; return false; } diff --git a/Modules/UIElements/ImmediateStylePainter.cs b/Modules/UIElements/ImmediateStylePainter.cs index 56e15fffdf..e6b037476e 100644 --- a/Modules/UIElements/ImmediateStylePainter.cs +++ b/Modules/UIElements/ImmediateStylePainter.cs @@ -119,18 +119,18 @@ public void DrawBackground() { IStyle style = currentElement.style; - // The background color is embedded in the texture/background image - if (style.backgroundImage.value != null) + if (style.backgroundColor != Color.clear) { - var painterParams = TextureStylePainterParameters.GetDefault(currentElement); + var painterParams = RectStylePainterParameters.GetDefault(currentElement); painterParams.border.SetWidth(0.0f); - DrawTexture(painterParams); + DrawRect(painterParams); } - else if (style.backgroundColor != Color.clear) + + if (style.backgroundImage.value != null) { - var painterParams = RectStylePainterParameters.GetDefault(currentElement); + var painterParams = TextureStylePainterParameters.GetDefault(currentElement); painterParams.border.SetWidth(0.0f); - DrawRect(painterParams); + DrawTexture(painterParams); } } diff --git a/Modules/UIElements/StylePainter.cs b/Modules/UIElements/StylePainter.cs index 29c4cc0fe4..0bca9f788a 100644 --- a/Modules/UIElements/StylePainter.cs +++ b/Modules/UIElements/StylePainter.cs @@ -114,9 +114,7 @@ public static TextureStylePainterParameters GetDefault(VisualElement ve) { rect = GUIUtility.AlignRectToDevice(ve.rect), uv = new Rect(0, 0, 1, 1), - // When the background color is not clear, we have to embed it into the texture... - // whereas if the color is clear, the white color is used... - color = (style.backgroundColor != Color.clear) ? (Color)style.backgroundColor : (Color)Color.white, + color = (Color)Color.white, texture = style.backgroundImage, scaleMode = style.backgroundScaleMode, sliceLeft = style.sliceLeft, diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index b285e968a3..baadafe1cf 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -792,6 +792,9 @@ Runtime\Export\Scripting\ExtensionOfNativeClassAttribute.cs + + Runtime\Export\Scripting\GarbageCollector.bindings.cs + Runtime\Export\Scripting\PreserveAttribute.cs diff --git a/README.md b/README.md index f414498bbd..c330049458 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b1 C# reference source code +## Unity 2018.3.0b3 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs index feea57170f..7db928fc8d 100644 --- a/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs +++ b/Runtime/2D/Common/ScriptBindings/SpriteDataAccess.bindings.cs @@ -185,7 +185,7 @@ public static void SetBones(this Sprite sprite, SpriteBone[] src) extern private static SpriteChannelInfo GetBoneWeightsInfo(Sprite sprite); unsafe extern private static void SetBoneWeightsData(Sprite sprite, void* src, int count); - extern private static AtomicSafetyHandle GetSafetyHandle(this Sprite sprite); + extern internal static AtomicSafetyHandle GetSafetyHandle(this Sprite sprite); } [NativeHeader("Runtime/2D/Common/SpriteDataAccess.h")] diff --git a/Runtime/Export/AnimationCurve.bindings.cs b/Runtime/Export/AnimationCurve.bindings.cs index e8f0051e65..9262cff54b 100644 --- a/Runtime/Export/AnimationCurve.bindings.cs +++ b/Runtime/Export/AnimationCurve.bindings.cs @@ -227,6 +227,12 @@ public static AnimationCurve Constant(float timeStart, float timeEnd, float valu // A straight Line starting at /timeStart/, /valueStart/ and ending at /timeEnd/, /valueEnd/ public static AnimationCurve Linear(float timeStart, float valueStart, float timeEnd, float valueEnd) { + if (timeStart == timeEnd) + { + Keyframe key = new Keyframe(timeStart, valueStart); + return new AnimationCurve(new Keyframe[] {key}); + } + float tangent = (valueEnd - valueStart) / (timeEnd - timeStart); Keyframe[] keys = { new Keyframe(timeStart, valueStart, 0.0F, tangent), new Keyframe(timeEnd, valueEnd, tangent, 0.0F) }; return new AnimationCurve(keys); @@ -235,6 +241,12 @@ public static AnimationCurve Linear(float timeStart, float valueStart, float tim // An ease-in and out curve starting at /timeStart/, /valueStart/ and ending at /timeEnd/, /valueEnd/. public static AnimationCurve EaseInOut(float timeStart, float valueStart, float timeEnd, float valueEnd) { + if (timeStart == timeEnd) + { + Keyframe key = new Keyframe(timeStart, valueStart); + return new AnimationCurve(new Keyframe[] {key}); + } + Keyframe[] keys = { new Keyframe(timeStart, valueStart, 0.0F, 0.0F), new Keyframe(timeEnd, valueEnd, 0.0F, 0.0F) }; return new AnimationCurve(keys); } diff --git a/Runtime/Export/Scripting/GarbageCollector.bindings.cs b/Runtime/Export/Scripting/GarbageCollector.bindings.cs new file mode 100644 index 0000000000..3ed1d0271e --- /dev/null +++ b/Runtime/Export/Scripting/GarbageCollector.bindings.cs @@ -0,0 +1,46 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine.Bindings; + +namespace UnityEngine.Scripting +{ + [NativeHeader("Runtime/Scripting/GarbageCollector.h")] + [VisibleToOtherModules] + public static class GarbageCollector + { + public enum Mode + { + Disabled = 0, + Enabled = 1, + } + + public static Action GCModeChanged; + + public static Mode GCMode + { + get + { + return GetMode(); + } + + set + { + if (value == GetMode()) + return; + + SetMode(value); + + if (GCModeChanged != null) + GCModeChanged(value); + } + } + + [NativeThrows] + extern static void SetMode(Mode mode); + [NativeThrows] + extern static Mode GetMode(); + } +} diff --git a/Runtime/Export/Texture.cs b/Runtime/Export/Texture.cs index 06d0730b91..972e0c25ee 100644 --- a/Runtime/Export/Texture.cs +++ b/Runtime/Export/Texture.cs @@ -739,6 +739,7 @@ public void Apply([uei.DefaultValue("true")] bool updateMipmaps, [uei.DefaultVal public sealed partial class CubemapArray : Texture { + [RequiredByNativeCode] public CubemapArray(int width, int cubemapCount, GraphicsFormat format, TextureCreationFlags flags) { if (ValidateFormat(format, FormatUsage.Sample)) diff --git a/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs b/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs index 462a1bf79b..a0611e5bc6 100644 --- a/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs +++ b/Runtime/ParticleSystem/Managed/ParticleSystem.deprecated.cs @@ -44,7 +44,7 @@ public partial struct ShapeModule // Scale. (Meshes) [Obsolete("meshScale property is deprecated.Please use scale instead.", false)] public float meshScale { get { return scale.x; } set { scale = new Vector3(value, value, value); } } - [Obsolete("randomDirection property is deprecated.Use randomDirectionAmount instead.", false)] + [Obsolete("randomDirection property is deprecated. Use randomDirectionAmount instead.", false)] public bool randomDirection { get { return (randomDirectionAmount >= 0.5f); } set { randomDirectionAmount = value ? 1.0f : 0.0f; } } } @@ -82,11 +82,11 @@ public partial struct Particle { [Obsolete("Please use Particle.remainingLifetime instead. (UnityUpgradable) -> UnityEngine.ParticleSystem/Particle.remainingLifetime", false)] public float lifetime { get { return remainingLifetime; } set { remainingLifetime = value; } } - [Obsolete("randomValue property is deprecated.Use randomSeed instead to control random behavior of particles.", false)] + [Obsolete("randomValue property is deprecated. Use randomSeed instead to control random behavior of particles.", false)] public float randomValue { get { return BitConverter.ToSingle(BitConverter.GetBytes(m_RandomSeed), 0); } set { m_RandomSeed = BitConverter.ToUInt32(BitConverter.GetBytes(value), 0); } } - [Obsolete("size property is deprecated.Use startSize or GetCurrentSize() instead.", false)] + [Obsolete("size property is deprecated. Use startSize or GetCurrentSize() instead.", false)] public float size { get { return startSize; } set { startSize = value; } } - [Obsolete("color property is deprecated.Use startColor or GetCurrentColor() instead.", false)] + [Obsolete("color property is deprecated. Use startColor or GetCurrentColor() instead.", false)] public Color32 color { get { return startColor; } set { startColor = value; } } } @@ -125,56 +125,59 @@ public void Emit(ParticleSystem.Particle particle) Internal_EmitOld(ref particle); } - [Obsolete("startDelay property is deprecated.Use main.startDelay or main.startDelayMultiplier instead.", false)] + [Obsolete("startDelay property is deprecated. Use main.startDelay or main.startDelayMultiplier instead.", false)] public float startDelay { get { return main.startDelayMultiplier; } set { var m = main; m.startDelayMultiplier = value; } } - [Obsolete("loop property is deprecated.Use main.loop instead.", false)] + [Obsolete("loop property is deprecated. Use main.loop instead.", false)] public bool loop { get { return main.loop; } set { var m = main; m.loop = value; } } - [Obsolete("playOnAwake property is deprecated.Use main.playOnAwake instead.", false)] + [Obsolete("playOnAwake property is deprecated. Use main.playOnAwake instead.", false)] public bool playOnAwake { get { return main.playOnAwake; } set { var m = main; m.playOnAwake = value; } } - [Obsolete("duration property is deprecated.Use main.duration instead.", false)] + [Obsolete("duration property is deprecated. Use main.duration instead.", false)] public float duration { get { return main.duration; } } - [Obsolete("playbackSpeed property is deprecated.Use main.simulationSpeed instead.", false)] + [Obsolete("playbackSpeed property is deprecated. Use main.simulationSpeed instead.", false)] public float playbackSpeed { get { return main.simulationSpeed; } set { var m = main; m.simulationSpeed = value; } } - [Obsolete("enableEmission property is deprecated.Use emission.enabled instead.", false)] + [Obsolete("enableEmission property is deprecated. Use emission.enabled instead.", false)] public bool enableEmission { get { return emission.enabled; } set { var em = emission; em.enabled = value; } } - [Obsolete("emissionRate property is deprecated.Use emission.rateOverTime, emission.rateOverDistance, emission.rateOverTimeMultiplier or emission.rateOverDistanceMultiplier instead.", false)] + [Obsolete("emissionRate property is deprecated. Use emission.rateOverTime, emission.rateOverDistance, emission.rateOverTimeMultiplier or emission.rateOverDistanceMultiplier instead.", false)] public float emissionRate { get { return emission.rateOverTimeMultiplier; } set { var em = emission; em.rateOverTime = value; } } - [Obsolete("startSpeed property is deprecated.Use main.startSpeed or main.startSpeedMultiplier instead.", false)] + [Obsolete("startSpeed property is deprecated. Use main.startSpeed or main.startSpeedMultiplier instead.", false)] public float startSpeed { get { return main.startSpeedMultiplier; } set { var m = main; m.startSpeedMultiplier = value; } } - [Obsolete("startSize property is deprecated.Use main.startSize or main.startSizeMultiplier instead.", false)] + [Obsolete("startSize property is deprecated. Use main.startSize or main.startSizeMultiplier instead.", false)] public float startSize { get { return main.startSizeMultiplier; } set { var m = main; m.startSizeMultiplier = value; } } - [Obsolete("startColor property is deprecated.Use main.startColor instead.", false)] + [Obsolete("startColor property is deprecated. Use main.startColor instead.", false)] public Color startColor { get { return main.startColor.color; } set { var m = main; m.startColor = value; } } - [Obsolete("startRotation property is deprecated.Use main.startRotation or main.startRotationMultiplier instead.", false)] + [Obsolete("startRotation property is deprecated. Use main.startRotation or main.startRotationMultiplier instead.", false)] public float startRotation { get { return main.startRotationMultiplier; } set { var m = main; m.startRotationMultiplier = value; } } - [Obsolete("startRotation3D property is deprecated.Use main.startRotationX, main.startRotationY and main.startRotationZ instead. (Or main.startRotationXMultiplier, main.startRotationYMultiplier and main.startRotationZMultiplier).", false)] + [Obsolete("startRotation3D property is deprecated. Use main.startRotationX, main.startRotationY and main.startRotationZ instead. (Or main.startRotationXMultiplier, main.startRotationYMultiplier and main.startRotationZMultiplier).", false)] public Vector3 startRotation3D { get { return new Vector3(main.startRotationXMultiplier, main.startRotationYMultiplier, main.startRotationZMultiplier); } set { var m = main; m.startRotationXMultiplier = value.x; m.startRotationYMultiplier = value.y; m.startRotationZMultiplier = value.z; } } - [Obsolete("startLifetime property is deprecated.Use main.startLifetime or main.startLifetimeMultiplier instead.", false)] + [Obsolete("startLifetime property is deprecated. Use main.startLifetime or main.startLifetimeMultiplier instead.", false)] public float startLifetime { get { return main.startLifetimeMultiplier; } set { var m = main; m.startLifetimeMultiplier = value; } } - [Obsolete("gravityModifier property is deprecated.Use main.gravityModifier or main.gravityModifierMultiplier instead.", false)] + [Obsolete("gravityModifier property is deprecated. Use main.gravityModifier or main.gravityModifierMultiplier instead.", false)] public float gravityModifier { get { return main.gravityModifierMultiplier; } set { var m = main; m.gravityModifierMultiplier = value; } } - [Obsolete("maxParticles property is deprecated.Use main.maxParticles instead.", false)] + [Obsolete("maxParticles property is deprecated. Use main.maxParticles instead.", false)] public int maxParticles { get { return main.maxParticles; } set { var m = main; m.maxParticles = value; } } - [Obsolete("simulationSpace property is deprecated.Use main.simulationSpace instead.", false)] + [Obsolete("simulationSpace property is deprecated. Use main.simulationSpace instead.", false)] public ParticleSystemSimulationSpace simulationSpace { get { return main.simulationSpace; } set { var m = main; m.simulationSpace = value; } } - [Obsolete("scalingMode property is deprecated.Use main.scalingMode instead.", false)] + [Obsolete("scalingMode property is deprecated. Use main.scalingMode instead.", false)] public ParticleSystemScalingMode scalingMode { get { return main.scalingMode; } set { var m = main; m.scalingMode = value; } } + + [Obsolete("automaticCullingEnabled property is deprecated. Use proceduralSimulationSupported instead (UnityUpgradable) -> proceduralSimulationSupported", true)] + public bool automaticCullingEnabled { get { return proceduralSimulationSupported; } } } public static partial class ParticlePhysicsExtensions diff --git a/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs b/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs index c1a37bb876..432ca9b435 100644 --- a/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs +++ b/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs @@ -188,6 +188,15 @@ public enum ParticleSystemStopAction Callback = 3 // Calls OnParticleSystemStopped. } + // The action to perform when a particle system is offscreen + public enum ParticleSystemCullingMode + { + Automatic = 0, + PauseAndCatchup = 1, + Pause = 2, + AlwaysSimulate = 3 + } + // The emitter velocity mode for particle systems public enum ParticleSystemEmitterVelocityMode { diff --git a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs index cde478662b..591e257949 100644 --- a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs +++ b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs @@ -64,7 +64,7 @@ extern public bool useAutoRandomSeed set; } - extern public bool automaticCullingEnabled + extern public bool proceduralSimulationSupported { get; } diff --git a/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs index 91ff96bb6b..51484d3ada 100644 --- a/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs @@ -54,6 +54,14 @@ public static UnityType[] GetModuleTypes(string moduleName) [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static ModuleIncludeSetting GetModuleIncludeSettingForObject (Object o) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern internal static string GetExcludingModuleForObject (Object o) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern internal static string GetExcludingModule (string module) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static uint[] GetModuleTypeIndices (string moduleName) ; diff --git a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs index a95bdccce4..dfa7f7c180 100644 --- a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs @@ -63,6 +63,7 @@ public partial struct MainModule public int maxParticles { get { return GetMaxParticles(m_ParticleSystem); } set { SetMaxParticles(m_ParticleSystem, value); } } public ParticleSystemEmitterVelocityMode emitterVelocityMode { get { return GetUseRigidbodyForVelocity(m_ParticleSystem) ? ParticleSystemEmitterVelocityMode.Rigidbody : ParticleSystemEmitterVelocityMode.Transform; } set { SetUseRigidbodyForVelocity(m_ParticleSystem, value == ParticleSystemEmitterVelocityMode.Rigidbody); } } public ParticleSystemStopAction stopAction { get { return GetStopAction(m_ParticleSystem); } set { SetStopAction(m_ParticleSystem, value); } } + public ParticleSystemCullingMode cullingMode { get { return GetCullingMode(m_ParticleSystem); } set { SetCullingMode(m_ParticleSystem, value); } } public ParticleSystemRingBufferMode ringBufferMode { get { return GetRingBufferMode(m_ParticleSystem); } set { SetRingBufferMode(m_ParticleSystem, value); } } public Vector2 ringBufferLoopRange { get { return GetRingBufferLoopRange(m_ParticleSystem); } set { SetRingBufferLoopRange(m_ParticleSystem, value); } } @@ -363,6 +364,14 @@ public partial struct MainModule [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern private static ParticleSystemStopAction GetStopAction (ParticleSystem system) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static void SetCullingMode (ParticleSystem system, ParticleSystemCullingMode value) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static ParticleSystemCullingMode GetCullingMode (ParticleSystem system) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern private static void SetRingBufferMode (ParticleSystem system, ParticleSystemRingBufferMode value) ; From 86ce57f70f76576207924c1757dca4d310fcfca7 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 10 Oct 2018 08:17:14 +0000 Subject: [PATCH 03/10] Unity 2018.3.0b5 C# reference source code --- .../2D/SpriteAtlas/SpriteAtlasInspector.cs | 8 +- .../Animation/GameObjectRecorder.bindings.cs | 12 +- Editor/Mono/BuildPipeline.bindings.cs | 2 + .../BuiltinBakedReflectionSystem.bindings.cs | 9 + .../IScriptableBakedReflectionSystem.cs | 1 + .../Camera/ScriptableBakedReflectionSystem.cs | 1 + ...leBakedReflectionSystemWrapper.bindings.cs | 12 + Editor/Mono/EditorApplication.cs | 8 + Editor/Mono/EditorGUI.cs | 2 +- .../Mono/GI/LightmapVisualization.bindings.cs | 3 + Editor/Mono/GUI/ColorPicker.cs | 2 +- Editor/Mono/GUIView.cs | 1 - Editor/Mono/Inspector/AudioClipInspector.cs | 64 +- .../Inspector/LightingSettingsInspector.cs | 184 ++--- .../PlayerSettingsEditor.cs | 6 +- Editor/Mono/Inspector/PreviewRenderUtility.cs | 2 +- .../Mono/Inspector/QualitySettingsEditor.cs | 2 + .../Inspector/StandardParticlesShaderGUI.cs | 20 +- Editor/Mono/Menu.bindings.cs | 4 +- .../ParticleSystemModules/RendererModuleUI.cs | 9 +- .../ParticleSystemModules/TrailModuleUI.cs | 4 + Editor/Mono/PerformanceTools/FrameDebugger.cs | 2 +- Editor/Mono/PlayerSettings.bindings.cs | 6 + Editor/Mono/PlayerSettingsAndroid.bindings.cs | 3 + Editor/Mono/PlayerSettingsSwitch.bindings.cs | 6 +- .../PreferencesSettingsProviders.cs | 13 +- Editor/Mono/SceneHierarchy.cs | 2 - .../LightingWindowLightmapPreviewTab.cs | 30 +- .../SceneModeWindows/LightmapPreviewWindow.cs | 61 +- Editor/Mono/SceneView/SceneView.cs | 100 ++- .../Mono/Scripting/Compilers/UWPReferences.cs | 88 ++- .../CSharpNamespaceParser.cs | 42 +- Editor/Mono/UIElements/UXMLEditorFactories.cs | 3 +- .../Mono/UIElements/VisualTreeAssetEditor.cs | 1 - .../SolutionSynchronizer.cs | 2 +- .../Mono/GoogleVR/VRCustomOptionsGoogleVR.cs | 10 +- .../VR/Mono/Oculus/VRCustomOptionsOculus.cs | 57 +- Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 30 +- Editor/Src/VR/Mono/VRCustomOptions.cs | 4 +- .../VRCustomOptionsWindowsHolographic.cs | 2 +- .../Public/PluginImporter.bindings.cs | 3 + .../MemoryProfiler/MemorySnapshot.cs | 47 +- .../ProfilerWindow/MemorySnapshot.cs | 21 +- .../ShortcutAttributeDiscoveryProvider.cs | 12 +- .../ShortcutController.cs | 15 + .../ShortcutManagerEditor/ShortcutEntry.cs | 4 +- Modules/ShortcutManagerEditor/Trigger.cs | 30 +- Modules/TextCore/Managed/AssemblyInfo.cs | 2 + Modules/TextCore/Managed/FaceInfo.cs | 261 +++++++ Modules/TextCore/Managed/Glyph.cs | 404 +++++++---- .../ScriptBindings/FontEngine.bindings.cs | 636 +++++++++++++++++- .../ScriptBindings/GlyphMarshallingStruct.cs | 74 ++ .../TextRendering/TextRendering.bindings.cs | 9 +- .../Managed/Grid/GridPaintPaletteWindow.cs | 12 +- .../Managed/Grid/GridPaletteAddPopup.cs | 4 + .../Editor/Managed/Grid/PaintableGrid.cs | 22 +- .../Managed/Grid/PaintableSceneViewGrid.cs | 10 +- .../ScriptBindings/VFXEnums.bindings.cs | 7 +- .../ScriptBindings/VisualEffect.bindings.cs | 26 +- .../VFXMemorySerializer.bindings.cs | 19 +- .../VisualEffectResource.bindings.cs | 1 + Projects/CSharp/UnityEngine.csproj | 6 + README.md | 2 +- Runtime/Export/Camera.bindings.cs | 3 + Runtime/Export/GraphicsManagers.bindings.cs | 2 + .../ScriptBindings/ParticleSystem.bindings.cs | 18 +- .../ScriptBindings/Transform.bindings.cs | 5 +- .../ParticleSystemBindings.gen.cs | 18 + 68 files changed, 2002 insertions(+), 489 deletions(-) create mode 100644 Modules/TextCore/Managed/FaceInfo.cs create mode 100644 Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs index 3ff20a742e..90218d3f3e 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs @@ -61,7 +61,8 @@ class Styles public readonly GUIContent variantMultiplierLabel = EditorGUIUtility.TrTextContent("Scale", "Down scale ratio."); public readonly GUIContent copyMasterButton = EditorGUIUtility.TrTextContent("Copy Master's Settings", "Copy all master's settings into this variant."); public readonly GUIContent packButton = EditorGUIUtility.TrTextContent("Pack Preview", "Pack this atlas."); - public readonly GUIContent disabledPackLabel = EditorGUIUtility.TrTextContent("Sprite Atlas packing is disabled. Enable it in Edit > Project Settings > Editor."); + + public readonly GUIContent disabledPackLabel = EditorGUIUtility.TrTextContent("Sprite Atlas packing is disabled. Enable it in Edit > Settings > Editor.", null, EditorGUIUtility.GetHelpIcon(MessageType.Info)); public readonly GUIContent packableListLabel = EditorGUIUtility.TrTextContent("Objects for Packing", "Only accept Folder, Sprite Sheet(Texture) and Sprite."); public readonly GUIContent notPowerOfTwoWarning = EditorGUIUtility.TrTextContent("This scale will produce a Sprite Atlas variant with a packed texture that is NPOT (non - power of two). This may cause visual artifacts in certain compression/texture formats."); @@ -310,7 +311,10 @@ public override void OnInspectorGUI() } else { - EditorGUILayout.HelpBox(s_Styles.disabledPackLabel.text, MessageType.Info); + if (GUILayout.Button(s_Styles.disabledPackLabel, EditorStyles.helpBox)) + { + SettingsWindow.OpenProjectSettings("Project/Editor"); + } } serializedObject.ApplyModifiedProperties(); diff --git a/Editor/Mono/Animation/GameObjectRecorder.bindings.cs b/Editor/Mono/Animation/GameObjectRecorder.bindings.cs index c5ee0ddd49..de7c75bede 100644 --- a/Editor/Mono/Animation/GameObjectRecorder.bindings.cs +++ b/Editor/Mono/Animation/GameObjectRecorder.bindings.cs @@ -46,7 +46,17 @@ public void BindComponentsOfType(GameObject target, Type componentType, bool rec extern public GameObject root { get; } // Bindings. - extern public void Bind(EditorCurveBinding binding); + public void Bind(EditorCurveBinding binding) + { + if (!binding.type.IsSubclassOf(typeof(UnityEngine.Object))) + throw new InvalidCastException("Binding type should derive from Unity type."); + + BindInternal(binding); + } + + [NativeMethod("Bind")] + extern private void BindInternal(EditorCurveBinding binding); + extern public void BindAll(GameObject target, bool recursive); extern public void BindComponent([NotNull] Component component); diff --git a/Editor/Mono/BuildPipeline.bindings.cs b/Editor/Mono/BuildPipeline.bindings.cs index 87dd7ed3cc..64e3257ace 100644 --- a/Editor/Mono/BuildPipeline.bindings.cs +++ b/Editor/Mono/BuildPipeline.bindings.cs @@ -9,6 +9,7 @@ using UnityEngine.Bindings; using UnityEditor.Build.Reporting; using Mono.Cecil; +using UnityEditor.Scripting.ScriptCompilation; namespace UnityEditor { @@ -179,6 +180,7 @@ public class BuildPipeline internal static extern BuildTargetGroup GetBuildTargetGroupByName(string platform); internal static extern BuildTarget GetBuildTargetByName(string platform); + internal static extern EditorScriptCompilationOptions GetScriptCompileFlags(BuildOptions buildOptions, BuildTarget buildTarget); [FreeFunction] internal static extern string GetBuildTargetGroupDisplayName(BuildTargetGroup targetPlatformGroup); diff --git a/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs b/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs index 7928108d9b..c2e20ef94f 100644 --- a/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs +++ b/Editor/Mono/Camera/BuiltinBakedReflectionSystem.bindings.cs @@ -64,6 +64,14 @@ public void Clear() Internal_Clear(); } + public bool BakeAllReflectionProbes() + { + if (disposed) + throw new ObjectDisposedException("BuiltinBakedReflectionSystem"); + + return Internal_BakeAllReflectionProbes(); + } + public void Cancel() { // Cancel is empty on purpose @@ -120,5 +128,6 @@ void Internal_BuiltinBakedReflectionSystem_SetIsDone(bool isDone) extern void Internal_SynchronizeReflectionProbes(); extern void Internal_Clear(); extern void Internal_SetPtr(BuiltinBakedReflectionSystem ptr); + extern bool Internal_BakeAllReflectionProbes(); } } diff --git a/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs b/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs index bcb1c439d4..2557f60973 100644 --- a/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs +++ b/Editor/Mono/Camera/IScriptableBakedReflectionSystem.cs @@ -16,5 +16,6 @@ public interface IScriptableBakedReflectionSystem : IDisposable void SynchronizeReflectionProbes(); void Clear(); void Cancel(); + bool BakeAllReflectionProbes(); } } diff --git a/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs b/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs index 45f1f55623..416f7574a1 100644 --- a/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs +++ b/Editor/Mono/Camera/ScriptableBakedReflectionSystem.cs @@ -21,6 +21,7 @@ public virtual void Tick(SceneStateHash sceneStateHash, IScriptableBakedReflecti public virtual void SynchronizeReflectionProbes() {} public virtual void Clear() {} public virtual void Cancel() {} + public virtual bool BakeAllReflectionProbes() { return false; } protected virtual void Dispose(bool disposing) {} diff --git a/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs b/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs index e2c26a0746..96d7c7cdcc 100644 --- a/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs +++ b/Editor/Mono/Camera/ScriptableBakedReflectionSystemWrapper.bindings.cs @@ -118,6 +118,18 @@ void Internal_ScriptableBakedReflectionSystemWrapper_Cancel() implementation.Cancel(); } + [RequiredByNativeCode] + bool Internal_ScriptableBakedReflectionSystemWrapper_BakeAllReflectionProbes() + { + if (Disposed) + throw new ObjectDisposedException("ScriptableBakedReflectionSystemWrapper"); + + if (implementation != null) + return implementation.BakeAllReflectionProbes(); + + return false; + } + [StaticAccessor("ScriptableBakedReflectionSystem", StaticAccessorType.DoubleColon)] static extern void ScriptingEnterStage(IntPtr objPtr, int stage, string progressMessage, float progress); diff --git a/Editor/Mono/EditorApplication.cs b/Editor/Mono/EditorApplication.cs index 58680a1ff7..9d941b3959 100644 --- a/Editor/Mono/EditorApplication.cs +++ b/Editor/Mono/EditorApplication.cs @@ -190,6 +190,8 @@ public static void DirtyHierarchyWindowSorting() // Returns true when the pressed keys are defined in the Trigger internal static Func doPressedKeysTriggerAnyShortcut; + internal static event Action focusChanged; + // Windows were reordered internal static CallbackFunction windowsReordered; @@ -335,5 +337,11 @@ static void Internal_CallGlobalEventHandler() Event.current = null; } + + [RequiredByNativeCode] + static void Internal_FocusChanged(bool isFocused) + { + focusChanged?.Invoke(isFocused); + } } } diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index 0494d380d8..8fad8a4c1f 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -2536,7 +2536,7 @@ private static float DoSlider( if (sliderBackground != null && Event.current.type == EventType.Repaint) { var bgRect = sliderStyle.overflow.Add(sliderStyle.padding.Remove(sliderRect)); - Graphics.DrawTexture(bgRect, sliderBackground, new Rect(.5f / sliderBackground.width, .5f / sliderBackground.height, 1 - 1f / sliderBackground.width, 1 - 1f / sliderBackground.height), 0, 0, 0, 0, Color.grey); + Graphics.DrawTexture(bgRect, sliderBackground, new Rect(.5f / sliderBackground.width, .5f / sliderBackground.height, 1 - 1f / sliderBackground.width, 1 - 1f / sliderBackground.height), 0, 0, 0, 0, new Color(0.5f, 0.5f, 0.5f, 0.5f)); } newSliderValue = GUI.Slider(sliderRect, newSliderValue, 0, remapLeft, remapRight, sliderStyle, showMixedValue ? "SliderMixed" : thumbStyle, true, sliderId); diff --git a/Editor/Mono/GI/LightmapVisualization.bindings.cs b/Editor/Mono/GI/LightmapVisualization.bindings.cs index 95cdebbaf8..435a75b001 100644 --- a/Editor/Mono/GI/LightmapVisualization.bindings.cs +++ b/Editor/Mono/GI/LightmapVisualization.bindings.cs @@ -31,6 +31,9 @@ internal sealed partial class LightmapVisualizationUtility [StaticAccessor("VisualisationManager::Get()", StaticAccessorType.Arrow)] internal extern static bool IsBakedTextureType(GITextureType textureType); + [StaticAccessor("VisualisationManager::Get()", StaticAccessorType.Arrow)] + internal extern static bool IsAtlasTextureType(GITextureType textureType); + [StaticAccessor("VisualisationManager::Get()", StaticAccessorType.Arrow)] public extern static VisualisationGITexture[] GetRealtimeGITextures(GITextureType textureType); diff --git a/Editor/Mono/GUI/ColorPicker.cs b/Editor/Mono/GUI/ColorPicker.cs index 58d0173fd8..670789bce6 100644 --- a/Editor/Mono/GUI/ColorPicker.cs +++ b/Editor/Mono/GUI/ColorPicker.cs @@ -448,7 +448,7 @@ void DrawColorSpaceBox(Rect colorBoxRect, float constantValue) m_LastConstant = constantValue; m_TextureColorBoxMode = (int)m_ColorBoxMode; } - Graphics.DrawTexture(colorBoxRect, m_ColorBox, new Rect(.5f / m_ColorBox.width, .5f / m_ColorBox.height, 1 - 1f / m_ColorBox.width, 1 - 1f / m_ColorBox.height), 0, 0, 0, 0, Color.grey); + Graphics.DrawTexture(colorBoxRect, m_ColorBox, new Rect(.5f / m_ColorBox.width, .5f / m_ColorBox.height, 1 - 1f / m_ColorBox.width, 1 - 1f / m_ColorBox.height), 0, 0, 0, 0, new Color(.5f, .5f, .5f, .5f)); } static class Styles diff --git a/Editor/Mono/GUIView.cs b/Editor/Mono/GUIView.cs index 2398aec6e2..a86b7dd95c 100644 --- a/Editor/Mono/GUIView.cs +++ b/Editor/Mono/GUIView.cs @@ -36,7 +36,6 @@ protected Panel panel { if (m_Panel == null) { - UXMLEditorFactories.RegisterAll(); m_Panel = UIElementsUtility.FindOrCreatePanel(this, ContextType.Editor, DataWatchService.sharedInstance); m_Panel.cursorManager = m_CursorManager; m_Panel.contextualMenuManager = s_ContextualMenuManager; diff --git a/Editor/Mono/Inspector/AudioClipInspector.cs b/Editor/Mono/Inspector/AudioClipInspector.cs index 1ac6c24213..d4304d9698 100644 --- a/Editor/Mono/Inspector/AudioClipInspector.cs +++ b/Editor/Mono/Inspector/AudioClipInspector.cs @@ -120,29 +120,26 @@ public override void OnPreviewSettings() AudioClip clip = target as AudioClip; + bool isEditingMultipleObjects = targets.Length > 1; + using (new EditorGUI.DisabledScope(AudioUtil.IsMovieAudio(clip))) { - bool isEditingMultipleObjects = targets.Length > 1; - - using (new EditorGUI.DisabledScope(isEditingMultipleObjects)) + bool oldAutoPlay = m_bAutoPlay; + bool newAutoPlay = PreviewGUI.CycleButton(oldAutoPlay ? 1 : 0, s_AutoPlayIcons) != 0; + if (oldAutoPlay != newAutoPlay) { - bool oldAutoPlay = isEditingMultipleObjects ? false : m_bAutoPlay; - bool newAutoPlay = PreviewGUI.CycleButton(oldAutoPlay ? 1 : 0, s_AutoPlayIcons) != 0; - if (oldAutoPlay != newAutoPlay) - { - m_bAutoPlay = newAutoPlay; - InspectorWindow.RepaintAllInspectors(); - } + m_bAutoPlay = newAutoPlay; + InspectorWindow.RepaintAllInspectors(); + } - bool oldLoop = isEditingMultipleObjects ? false : m_bLoop; - bool newLoop = PreviewGUI.CycleButton(oldLoop ? 1 : 0, s_LoopIcons) != 0; - if (oldLoop != newLoop) - { - m_bLoop = newLoop; - if (playing) - AudioUtil.LoopClip(clip, newLoop); - InspectorWindow.RepaintAllInspectors(); - } + bool oldLoop = m_bLoop; + bool newLoop = PreviewGUI.CycleButton(oldLoop ? 1 : 0, s_LoopIcons) != 0; + if (oldLoop != newLoop) + { + m_bLoop = newLoop; + if (playing) + AudioUtil.LoopClip(clip, newLoop); + InspectorWindow.RepaintAllInspectors(); } using (new EditorGUI.DisabledScope(isEditingMultipleObjects && !playing && m_PlayingInspector != this)) @@ -153,8 +150,10 @@ public override void OnPreviewSettings() if (newPlaying != curPlaying) { AudioUtil.StopAllClips(); + m_PlayingClip = null; + m_PlayingInspector = null; - if (newPlaying) + if (newPlaying && !isEditingMultipleObjects) { AudioUtil.PlayClip(clip, 0, m_bLoop); m_PlayingClip = clip; @@ -163,6 +162,21 @@ public override void OnPreviewSettings() } } } + + // autoplay start? + if (m_bAutoPlay && m_PlayingClip != clip && m_PlayingInspector == this && !isEditingMultipleObjects) + { + AudioUtil.StopAllClips(); + m_PlayingClip = null; + m_PlayingInspector = null; + + if (!isEditingMultipleObjects) + { + AudioUtil.PlayClip(clip, 0, m_bLoop); + m_PlayingClip = clip; + m_PlayingInspector = this; + } + } } // Passing in clip and importer separately as we're not completely done with the asset setup at the time we're asked to generate the preview. @@ -314,16 +328,6 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) PreviewGUI.EndScrollView(); } - - // autoplay start? - if (m_bAutoPlay && m_PlayingClip != clip && m_PlayingInspector == this) - { - AudioUtil.StopAllClips(); - AudioUtil.PlayClip(clip, 0, m_bLoop); - m_PlayingClip = clip; - m_PlayingInspector = this; - } - // force update GUI if (playing) GUIView.current.Repaint(); diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index ae164fd643..0f27dbf8aa 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -63,12 +63,18 @@ static class Styles public static readonly GUIContent GINotEnabledInfo = EditorGUIUtility.TrTextContent("Lightmapping settings are currently disabled. Enable Baked Global Illumination or Realtime Global Illumination to display these settings."); public static readonly GUIContent CastShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Cast Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); public static readonly GUIContent ReceiveShadowsProgressiveGPUWarning = EditorGUIUtility.TrTextContent("Receive Shadows is forced to 'On' when using the GPU lightmapper (Preview), it will be supported in a later version. Use the CPU lightmapper instead if you need this functionality."); + public static readonly GUIContent OpenPreview = EditorGUIUtility.TrTextContent("Open Preview"); + + public static readonly GUIStyle OpenPreviewStyle = EditorStyles.objectFieldThumb.name + "LightmapPreviewOverlay"; + + public static readonly int PreviewPadding = 30; + public static readonly int PreviewWidth = 104; } bool m_ShowChartingSettings = true; bool m_ShowLightmapSettings = true; - bool m_ShowBakedLM = false; - bool m_ShowRealtimeLM = false; + bool m_ShowBakedLM = true; + bool m_ShowRealtimeLM = true; SerializedObject m_SerializedObject; SerializedObject m_GameObjectsSerializedObject; @@ -240,13 +246,8 @@ public void RenderMeshSettings(bool showLightmapSettings) { EditorGUI.indentLevel += 1; - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, Styles.Atlas, true); - if (m_ShowBakedLM) - ShowAtlasGUI(m_Renderers[0].GetInstanceID()); - - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); - if (m_ShowRealtimeLM) - ShowRealtimeLMGUI(m_Renderers[0]); + ShowAtlasGUI(m_Renderers[0].GetInstanceID()); + ShowRealtimeLMGUI(m_Renderers[0]); EditorGUI.indentLevel -= 1; } @@ -312,13 +313,8 @@ public void RenderTerrainSettings() if (GUI.enabled && m_Terrains.Length == 1 && m_Terrains[0].terrainData != null) ShowBakePerformanceWarning(m_Terrains[0]); - m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, Styles.Atlas, true); - if (m_ShowBakedLM) - ShowAtlasGUI(m_Terrains[0].GetInstanceID()); - - m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); - if (m_ShowRealtimeLM) - ShowRealtimeLMGUI(m_Terrains[0]); + ShowAtlasGUI(m_Terrains[0].GetInstanceID()); + ShowRealtimeLMGUI(m_Terrains[0]); m_SerializedObject.ApplyModifiedProperties(); } @@ -413,44 +409,29 @@ void ShowAtlasGUI(int instanceID) if (m_CachedBakedTexture.texture == null) return; - EditorGUI.indentLevel += 1; + m_ShowBakedLM = EditorGUILayout.Foldout(m_ShowBakedLM, Styles.Atlas, true); - GUILayout.BeginHorizontal(); - GUILayout.Space(30); - - Rect rect = GUILayoutUtility.GetRect(100, 100, EditorStyles.objectField); + if (!m_ShowBakedLM) + return; - EditorGUI.Toggle(rect, false, EditorStyles.objectFieldThumb); + EditorGUI.indentLevel += 1; - if (rect.Contains(Event.current.mousePosition)) - { - Object actualTargetObject = m_CachedBakedTexture.texture; - Component com = actualTargetObject as Component; + GUILayout.BeginHorizontal(); - if (com) - actualTargetObject = com.gameObject; + DrawLightmapPreview(m_CachedBakedTexture.texture, false, instanceID); - if (Event.current.clickCount == 2) - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_Renderers[0].GetInstanceID(), false, false); - else if (Event.current.clickCount == 1) - EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, GUILayoutUtility.GetLastRect()); - } + GUILayout.BeginVertical(); - if (Event.current.type == EventType.Repaint) - { - rect = EditorStyles.objectFieldThumb.padding.Remove(rect); - EditorGUI.DrawPreviewTexture(rect, m_CachedBakedTexture.texture); - } + GUILayout.Label(Styles.AtlasIndex.text + ": " + m_LightmapIndex.intValue.ToString()); + GUILayout.Label(Styles.AtlasTilingX.text + ": " + m_LightmapTilingOffsetX.floatValue.ToString()); + GUILayout.Label(Styles.AtlasTilingY.text + ": " + m_LightmapTilingOffsetY.floatValue.ToString()); + GUILayout.Label(Styles.AtlasOffsetX.text + ": " + m_LightmapTilingOffsetZ.floatValue.ToString()); + GUILayout.Label(Styles.AtlasOffsetY.text + ": " + m_LightmapTilingOffsetW.floatValue.ToString()); + GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); - EditorGUILayout.LabelField(Styles.AtlasIndex, GUIContent.Temp(m_LightmapIndex.intValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasTilingX, GUIContent.Temp(m_LightmapTilingOffsetX.floatValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasTilingY, GUIContent.Temp(m_LightmapTilingOffsetY.floatValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasOffsetX, GUIContent.Temp(m_LightmapTilingOffsetZ.floatValue.ToString())); - EditorGUILayout.LabelField(Styles.AtlasOffsetY, GUIContent.Temp(m_LightmapTilingOffsetW.floatValue.ToString())); - bool showProgressiveInfo = isPrefabAsset || (m_EnabledBakedGI.boolValue && LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.Enlighten); if (showProgressiveInfo && Unsupported.IsDeveloperMode()) @@ -467,19 +448,32 @@ void ShowAtlasGUI(int instanceID) LightmapEditorSettings.GetPVRAtlasInstanceOffset(instanceID, out atlasInstanceOffset); EditorGUILayout.LabelField(Styles.PVRAtlasInstanceOffset, GUIContent.Temp(atlasInstanceOffset.ToString())); } - EditorGUI.indentLevel -= 1; + + GUILayout.Space(5); } void ShowRealtimeLMGUI(Terrain terrain) { + Hash128 inputSystemHash; + if (terrain == null || !LightmapEditorSettings.GetInputSystemHash(terrain.GetInstanceID(), out inputSystemHash) || inputSystemHash == new Hash128()) + return; // early return since we don't have any lightmaps for it + + if (!UpdateRealtimeTexture(inputSystemHash, terrain.GetInstanceID())) + return; + + m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); + + if (!m_ShowRealtimeLM) + return; + EditorGUI.indentLevel += 1; - Hash128 inputSystemHash; - if (terrain != null && LightmapEditorSettings.GetInputSystemHash(terrain.GetInstanceID(), out inputSystemHash)) - { - ShowRealtimeLightmapPreview(inputSystemHash); - } + GUILayout.BeginHorizontal(); + + DrawLightmapPreview(m_CachedRealtimeTexture.texture, true, terrain.GetInstanceID()); + + GUILayout.BeginVertical(); // Resolution of the system. int width, height; @@ -489,34 +483,56 @@ void ShowRealtimeLMGUI(Terrain terrain) var str = width.ToString() + "x" + height.ToString(); if (numChunksInX > 1 || numChunksInY > 1) str += string.Format(" ({0}x{1} chunks)", numChunksInX, numChunksInY); - EditorGUILayout.LabelField(Styles.RealtimeLMResolution, GUIContent.Temp(str)); + GUILayout.Label(Styles.RealtimeLMResolution.text + ": " + str); } + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + EditorGUI.indentLevel -= 1; + + GUILayout.Space(5); } void ShowRealtimeLMGUI(Renderer renderer) { + Hash128 inputSystemHash; + if (renderer == null || !LightmapEditorSettings.GetInputSystemHash(renderer.GetInstanceID(), out inputSystemHash) || inputSystemHash == new Hash128()) + return; // early return since we don't have any lightmaps for it + + if (!UpdateRealtimeTexture(inputSystemHash, renderer.GetInstanceID())) + return; + + m_ShowRealtimeLM = EditorGUILayout.Foldout(m_ShowRealtimeLM, Styles.RealtimeLM, true); + + if (!m_ShowRealtimeLM) + return; + EditorGUI.indentLevel += 1; - Hash128 inputSystemHash = new Hash128(); - if (renderer != null && LightmapEditorSettings.GetInputSystemHash(renderer.GetInstanceID(), out inputSystemHash)) - { - ShowRealtimeLightmapPreview(inputSystemHash); - } + GUILayout.BeginHorizontal(); + + DrawLightmapPreview(m_CachedRealtimeTexture.texture, true, renderer.GetInstanceID()); + + GUILayout.BeginVertical(); int instWidth, instHeight; if (LightmapEditorSettings.GetInstanceResolution(renderer, out instWidth, out instHeight)) { - EditorGUILayout.LabelField(Styles.RealtimeLMInstanceResolution, GUIContent.Temp(instWidth.ToString() + "x" + instHeight.ToString())); + GUILayout.Label(Styles.RealtimeLMInstanceResolution.text + ": " + instWidth.ToString() + "x" + instHeight.ToString()); } int width, height; if (LightmapEditorSettings.GetSystemResolution(renderer, out width, out height)) { - EditorGUILayout.LabelField(Styles.RealtimeLMResolution, GUIContent.Temp(width.ToString() + "x" + height.ToString())); + GUILayout.Label(Styles.RealtimeLMResolution.text + ": " + width.ToString() + "x" + height.ToString()); } + GUILayout.EndVertical(); + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + if (Unsupported.IsDeveloperMode()) { Hash128 instanceHash; @@ -535,12 +551,14 @@ void ShowRealtimeLMGUI(Renderer renderer) } EditorGUI.indentLevel -= 1; + + GUILayout.Space(5); } - void ShowRealtimeLightmapPreview(Hash128 inputSystemHash) + bool UpdateRealtimeTexture(Hash128 inputSystemHash, int instanceId) { if (inputSystemHash == new Hash128()) - return; + return false; Hash128 contentHash = LightmapVisualizationUtility.GetRealtimeGITextureHash(inputSystemHash, GITextureType.Irradiance); @@ -549,35 +567,51 @@ void ShowRealtimeLightmapPreview(Hash128 inputSystemHash) m_CachedRealtimeTexture = LightmapVisualizationUtility.GetRealtimeGITexture(inputSystemHash, GITextureType.Irradiance); if (m_CachedRealtimeTexture.texture == null) - return; + return false; - GUILayout.BeginHorizontal(); - GUILayout.Space(30); + return true; + } - Rect rect = GUILayoutUtility.GetRect(100, 100, EditorStyles.objectField); + private void DrawLightmapPreview(Texture2D texture, bool realtimeLightmap, int instanceId) + { + GUILayout.Space(Styles.PreviewPadding); - EditorGUI.Toggle(rect, false, EditorStyles.objectFieldThumb); + int previewWidth = Styles.PreviewWidth - 4; // padding - if (rect.Contains(Event.current.mousePosition)) + Rect rect = GUILayoutUtility.GetRect(previewWidth, previewWidth, EditorStyles.objectField); + Rect buttonRect = new Rect(rect.xMax - 70, rect.yMax - 14, 70, 14); + + if (Event.current.type == EventType.MouseDown) { - Object actualTargetObject = m_CachedRealtimeTexture.texture; - Component com = actualTargetObject as Component; + if ((buttonRect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) || + (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 2)) + { + LightmapPreviewWindow.CreateLightmapPreviewWindow(instanceId, realtimeLightmap, false); + } + else if (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) + { + Object actualTargetObject = texture; + Component com = actualTargetObject as Component; - if (com) - actualTargetObject = com.gameObject; + if (com) + actualTargetObject = com.gameObject; - if (Event.current.clickCount == 2) - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_Renderers[0].GetInstanceID(), true, false); + EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, rect); + } } + EditorGUI.Toggle(rect, false, EditorStyles.objectFieldThumb); + if (Event.current.type == EventType.Repaint) { rect = EditorStyles.objectFieldThumb.padding.Remove(rect); - EditorGUI.DrawPreviewTexture(rect, m_CachedRealtimeTexture.texture); + EditorGUI.DrawPreviewTexture(rect, texture); + + Styles.OpenPreviewStyle.Draw(rect, Styles.OpenPreview, false, false, false, false); } - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); + float spacing = Mathf.Max(5.0f, EditorGUIUtility.labelWidth - Styles.PreviewPadding - Styles.PreviewWidth); + GUILayout.Space(spacing); } static bool HasNormals(Renderer renderer) diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 7d97663c9a..6b8786ffff 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -142,9 +142,9 @@ class SettingsContent public static readonly GUIContent appleDeveloperTeamID = EditorGUIUtility.TrTextContent("iOS Developer Team ID", "Developers can retrieve their Team ID by visiting the Apple Developer site under Account > Membership."); public static readonly GUIContent useOnDemandResources = EditorGUIUtility.TrTextContent("Use on demand resources*"); public static readonly GUIContent accelerometerFrequency = EditorGUIUtility.TrTextContent("Accelerometer Frequency*"); - public static readonly GUIContent cameraUsageDescription = EditorGUIUtility.TrTextContent("Camera Usage Description*"); - public static readonly GUIContent locationUsageDescription = EditorGUIUtility.TrTextContent("Location Usage Description*"); - public static readonly GUIContent microphoneUsageDescription = EditorGUIUtility.TrTextContent("Microphone Usage Description*"); + public static readonly GUIContent cameraUsageDescription = EditorGUIUtility.TrTextContent("Camera Usage Description*", "String shown to the user when requesting permission to use the device camera. Written to the NSCameraUsageDescription field in Xcode project's info.plist file"); + public static readonly GUIContent locationUsageDescription = EditorGUIUtility.TrTextContent("Location Usage Description*", "String shown to the user when requesting permission to access the device location. Written to the NSLocationWhenInUseUsageDescription field in Xcode project's info.plist file."); + public static readonly GUIContent microphoneUsageDescription = EditorGUIUtility.TrTextContent("Microphone Usage Description*", "String shown to the user when requesting to use the device microphone. Written to the NSMicrophoneUsageDescription field in Xcode project's info.plist file"); public static readonly GUIContent muteOtherAudioSources = EditorGUIUtility.TrTextContent("Mute Other Audio Sources*"); public static readonly GUIContent prepareIOSForRecording = EditorGUIUtility.TrTextContent("Prepare iOS for Recording"); public static readonly GUIContent forceIOSSpeakersWhenRecording = EditorGUIUtility.TrTextContent("Force iOS Speakers when Recording"); diff --git a/Editor/Mono/Inspector/PreviewRenderUtility.cs b/Editor/Mono/Inspector/PreviewRenderUtility.cs index 783603be1a..0417154154 100644 --- a/Editor/Mono/Inspector/PreviewRenderUtility.cs +++ b/Editor/Mono/Inspector/PreviewRenderUtility.cs @@ -229,7 +229,7 @@ public void BeginPreview(Rect r, GUIStyle previewBackground) new Rect(0, 0, 1, 1), previewBackground.border.left, previewBackground.border.right, previewBackground.border.top, previewBackground.border.bottom, - new Color(.5f, .5f, .5f, 1), + new Color(.5f, .5f, .5f, 0.5f), null ); diff --git a/Editor/Mono/Inspector/QualitySettingsEditor.cs b/Editor/Mono/Inspector/QualitySettingsEditor.cs index d079c972d7..495fd0a4a9 100644 --- a/Editor/Mono/Inspector/QualitySettingsEditor.cs +++ b/Editor/Mono/Inspector/QualitySettingsEditor.cs @@ -503,6 +503,7 @@ public override void OnInspectorGUI() var particleRaycastBudgetProperty = currentSettings.FindPropertyRelative("particleRaycastBudget"); var asyncUploadTimeSliceProperty = currentSettings.FindPropertyRelative("asyncUploadTimeSlice"); var asyncUploadBufferSizeProperty = currentSettings.FindPropertyRelative("asyncUploadBufferSize"); + var asyncUploadPersistentBufferProperty = currentSettings.FindPropertyRelative("asyncUploadPersistentBuffer"); var resolutionScalingFixedDPIFactorProperty = currentSettings.FindPropertyRelative("resolutionScalingFixedDPIFactor"); bool usingSRP = GraphicsSettings.renderPipelineAsset != null; @@ -586,6 +587,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(particleRaycastBudgetProperty); EditorGUILayout.PropertyField(asyncUploadTimeSliceProperty); EditorGUILayout.PropertyField(asyncUploadBufferSizeProperty); + EditorGUILayout.PropertyField(asyncUploadPersistentBufferProperty); asyncUploadTimeSliceProperty.intValue = Mathf.Clamp(asyncUploadTimeSliceProperty.intValue, kMinAsyncUploadTimeSlice, kMaxAsyncUploadTimeSlice); asyncUploadBufferSizeProperty.intValue = Mathf.Clamp(asyncUploadBufferSizeProperty.intValue, kMinAsyncRingBufferSize, kMaxAsyncRingBufferSize); diff --git a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs b/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs index 656b97c002..760f41840b 100644 --- a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs +++ b/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs @@ -54,20 +54,18 @@ private static class Styles public static GUIContent colorMode = EditorGUIUtility.TrTextContent("Color Mode", "Determines the blending mode between the particle color and the texture albedo."); public static GUIContent[] colorNames = Array.ConvertAll(Enum.GetNames(typeof(ColorMode)), item => new GUIContent(item)); - public static GUIContent flipbookMode = EditorGUIUtility.TrTextContent("Flip-Book Mode", "Determines the blending mode used for animated texture sheets."); - public static GUIContent[] flipbookNames = Array.ConvertAll(Enum.GetNames(typeof(FlipbookMode)), item => new GUIContent(item)); - + public static GUIContent flipbookBlending = EditorGUIUtility.TrTextContent("Flip-Book Frame Blending", "Enables blending between the frames of animated texture sheets."); public static GUIContent twoSidedEnabled = EditorGUIUtility.TrTextContent("Two Sided", "Render both front and back faces of the particle geometry."); - public static GUIContent distortionEnabled = EditorGUIUtility.TrTextContent("Enable Distortion", "Use a grab pass and normal map to simulate refraction."); + public static GUIContent distortionEnabled = EditorGUIUtility.TrTextContent("Distortion", "Use a grab pass and normal map to simulate refraction."); public static GUIContent distortionStrengthText = EditorGUIUtility.TrTextContent("Strength", "Distortion Strength."); public static GUIContent distortionBlendText = EditorGUIUtility.TrTextContent("Blend", "Weighting between albedo and grab pass."); - public static GUIContent softParticlesEnabled = EditorGUIUtility.TrTextContent("Enable Soft Particles", "Fade out particle geometry when it gets close to the surface of objects written into the depth buffer."); + public static GUIContent softParticlesEnabled = EditorGUIUtility.TrTextContent("Soft Particles", "Fade out particle geometry when it gets close to the surface of objects written into the depth buffer."); public static GUIContent softParticlesNearFadeDistanceText = EditorGUIUtility.TrTextContent("Near fade", "Soft Particles near fade distance."); public static GUIContent softParticlesFarFadeDistanceText = EditorGUIUtility.TrTextContent("Far fade", "Soft Particles far fade distance."); - public static GUIContent cameraFadingEnabled = EditorGUIUtility.TrTextContent("Enable Camera Fading", "Fade out particle geometry when it gets close to the camera."); + public static GUIContent cameraFadingEnabled = EditorGUIUtility.TrTextContent("Camera Fading", "Fade out particle geometry when it gets close to the camera."); public static GUIContent cameraNearFadeDistanceText = EditorGUIUtility.TrTextContent("Near fade", "Camera near fade distance."); public static GUIContent cameraFarFadeDistanceText = EditorGUIUtility.TrTextContent("Far fade", "Camera far fade distance."); @@ -184,7 +182,7 @@ public void ShaderPropertiesGUI(Material material) EditorGUILayout.Space(); GUILayout.Label(Styles.mainOptionsText, EditorStyles.boldLabel); - FlipbookModePopup(); + FlipbookBlendingPopup(); TwoSidedPopup(material); FadingPopup(material); DistortionPopup(material); @@ -296,17 +294,17 @@ void ColorModePopup() } } - void FlipbookModePopup() + void FlipbookBlendingPopup() { EditorGUI.showMixedValue = flipbookMode.hasMixedValue; - var mode = (FlipbookMode)flipbookMode.floatValue; + var enabled = (flipbookMode.floatValue == (float)FlipbookMode.Blended); EditorGUI.BeginChangeCheck(); - mode = (FlipbookMode)EditorGUILayout.Popup(Styles.flipbookMode, (int)mode, Styles.flipbookNames); + enabled = EditorGUILayout.Toggle(Styles.flipbookBlending, enabled); if (EditorGUI.EndChangeCheck()) { m_MaterialEditor.RegisterPropertyChangeUndo("Flip-Book Mode"); - flipbookMode.floatValue = (float)mode; + flipbookMode.floatValue = enabled ? (float)FlipbookMode.Blended : (float)FlipbookMode.Simple; } EditorGUI.showMixedValue = false; diff --git a/Editor/Mono/Menu.bindings.cs b/Editor/Mono/Menu.bindings.cs index cf50afc6d6..c8cbee328f 100644 --- a/Editor/Mono/Menu.bindings.cs +++ b/Editor/Mono/Menu.bindings.cs @@ -16,8 +16,8 @@ public sealed class Menu [NativeMethod("MenuController::GetChecked", true)] public static extern bool GetChecked(string menuPath); - [FreeFunction("MenuController::GetMenuItemShortcuts")] - internal static extern void GetMenuItemShortcuts(List outItemNames, List outItemShortcuts); + [FreeFunction("MenuController::GetMenuItemDefaultShortcuts")] + internal static extern void GetMenuItemDefaultShortcuts(List outItemNames, List outItemDefaultShortcuts); [FreeFunction("MenuController::SetMenuItemHotkey")] internal static extern void SetHotkey(string menuPath, string hotkey); diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs index ff4c3926cd..35f83e7f67 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/RendererModuleUI.cs @@ -274,12 +274,15 @@ override public void OnInspectorGUI(InitialModuleUI initial) { if (renderMode != RenderMode.Mesh) GUIFloat(s_Texts.normalDirection, m_NormalDirection); - - if (m_Material != null) // The renderer's material list could be empty - GUIObject(s_Texts.material, m_Material); } } + if (renderMode != RenderMode.None) + { + if (m_Material != null) // The renderer's material list could be empty + GUIObject(s_Texts.material, m_Material); + } + if (m_TrailMaterial != null) // The renderer's material list could be empty GUIObject(s_Texts.trailMaterial, m_TrailMaterial); diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs index d0db6cc3c1..bdb29270c0 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/TrailModuleUI.cs @@ -28,6 +28,7 @@ class Texts public GUIContent shadowBias = EditorGUIUtility.TrTextContent("Shadow Bias", "Apply a shadow bias to prevent self-shadowing artifacts. The specified value is the proportion of the trail width at each segment."); public GUIContent ribbonCount = EditorGUIUtility.TrTextContent("Ribbon Count", "Select how many ribbons to render throughout the Particle System."); public GUIContent splitSubEmitterRibbons = EditorGUIUtility.TrTextContent("Split Sub Emitter Ribbons", "When used on a sub emitter, ribbons will connect particles from each parent particle independently."); + public GUIContent attachRibbonsToTransform = EditorGUIUtility.TrTextContent("Attach Ribbons to Transform", "Connect each ribbon to the position of the Transform Component."); public GUIContent[] trailModeOptions = { @@ -62,6 +63,7 @@ class Texts SerializedProperty m_ShadowBias; SerializedProperty m_RibbonCount; SerializedProperty m_SplitSubEmitterRibbons; + SerializedProperty m_AttachRibbonsToTransform; public TrailModuleUI(ParticleSystemUI owner, SerializedObject o, string displayName) : base(owner, o, "TrailModule", displayName) @@ -94,6 +96,7 @@ protected override void Init() m_ShadowBias = GetProperty("shadowBias"); m_RibbonCount = GetProperty("ribbonCount"); m_SplitSubEmitterRibbons = GetProperty("splitSubEmitterRibbons"); + m_AttachRibbonsToTransform = GetProperty("attachRibbonsToTransform"); } override public void OnInspectorGUI(InitialModuleUI initial) @@ -113,6 +116,7 @@ override public void OnInspectorGUI(InitialModuleUI initial) { GUIInt(s_Texts.ribbonCount, m_RibbonCount); GUIToggle(s_Texts.splitSubEmitterRibbons, m_SplitSubEmitterRibbons); + GUIToggle(s_Texts.attachRibbonsToTransform, m_AttachRibbonsToTransform); } } diff --git a/Editor/Mono/PerformanceTools/FrameDebugger.cs b/Editor/Mono/PerformanceTools/FrameDebugger.cs index e7501eb423..2cca28353c 100644 --- a/Editor/Mono/PerformanceTools/FrameDebugger.cs +++ b/Editor/Mono/PerformanceTools/FrameDebugger.cs @@ -127,7 +127,7 @@ internal struct FrameDebuggerEventData public int subShaderIndex; public int shaderPassIndex; public string shaderKeywords; - public int rendererInstanceID; + public int componentInstanceID; public Mesh mesh; public int meshInstanceID; public int meshSubset; diff --git a/Editor/Mono/PlayerSettings.bindings.cs b/Editor/Mono/PlayerSettings.bindings.cs index 9f9d15dda8..fb1edb4611 100644 --- a/Editor/Mono/PlayerSettings.bindings.cs +++ b/Editor/Mono/PlayerSettings.bindings.cs @@ -1098,5 +1098,11 @@ public static extern bool enableMetalAPIValidation [StaticAccessor("GetPlayerSettings().GetEditorOnly()")] internal static extern bool RelaunchProjectIfScriptRuntimeVersionHasChanged(); + + [StaticAccessor("GetPlayerSettings()")] + public static extern bool GetWsaHolographicRemotingEnabled(); + + [StaticAccessor("GetPlayerSettings()")] + public static extern void SetWsaHolographicRemotingEnabled(bool enabled); } } diff --git a/Editor/Mono/PlayerSettingsAndroid.bindings.cs b/Editor/Mono/PlayerSettingsAndroid.bindings.cs index dc0c0acbec..6685deca5b 100644 --- a/Editor/Mono/PlayerSettingsAndroid.bindings.cs +++ b/Editor/Mono/PlayerSettingsAndroid.bindings.cs @@ -67,6 +67,9 @@ public enum AndroidSdkVersions // Android 8.1, "Oreo", API level 27 AndroidApiLevel27 = 27, + + // Android 9.0, "Pie", API level 28 + AndroidApiLevel28 = 28, } // Preferred application install location diff --git a/Editor/Mono/PlayerSettingsSwitch.bindings.cs b/Editor/Mono/PlayerSettingsSwitch.bindings.cs index f435d72098..076266ecd8 100644 --- a/Editor/Mono/PlayerSettingsSwitch.bindings.cs +++ b/Editor/Mono/PlayerSettingsSwitch.bindings.cs @@ -49,7 +49,8 @@ public enum Languages Korean, } - public enum StartupUserAccount + public enum + StartupUserAccount { None = 0, Required = 1, @@ -367,6 +368,9 @@ extern public static string[] localCommunicationIds [NativeProperty("switchDataLossConfirmation", TargetType.Field)] extern public static bool isDataLossConfirmationEnabled { get; set; } + [NativeProperty("switchUserAccountLockEnabled", TargetType.Field)] + extern public static bool isUserAccountLockEnabled { get; set; } + [Obsolete("isDataLossConfirmation was renamed to isDataLossConfirmationEnabled")] [NativeProperty("switchDataLossConfirmation", TargetType.Field)] extern public static bool isDataLossConfirmation { get; set; } diff --git a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs index b99d96e3a3..a17eef3271 100644 --- a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs +++ b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs @@ -37,6 +37,12 @@ internal static class Constants internal class Styles { public static readonly GUIContent browse = EditorGUIUtility.TrTextContent("Browse..."); + public static readonly GUIStyle clearBindingButton = new GUIStyle(GUI.skin.button); + + static Styles() + { + clearBindingButton.margin.top = 0; + } } internal class GeneralProperties @@ -711,6 +717,9 @@ private void ShowShortcutConfiguration(int controlID, ShortcutEntry selectedShor { GUILayout.Label("Key:"); e = EditorGUILayout.KeyEventField(e); + + if (GUILayout.Button("Clear", Styles.clearBindingButton)) + e.keyCode = KeyCode.None; } using (new GUILayout.HorizontalScope()) @@ -732,7 +741,9 @@ private void ShowShortcutConfiguration(int controlID, ShortcutEntry selectedShor if (m_ValidKeyChange) { // TODO: Don't clobber secondary+ combinations - var newCombination = new List { new KeyCombination(e) }; + var newCombination = new List(); + if (e.keyCode != KeyCode.None) + newCombination.Add(new KeyCombination(e)); shortcutController.profileManager.ModifyShortcutEntry(selectedShortcut.identifier, newCombination); shortcutController.profileManager.PersistChanges(); } diff --git a/Editor/Mono/SceneHierarchy.cs b/Editor/Mono/SceneHierarchy.cs index 1f5e4ed5a8..3534c68484 100644 --- a/Editor/Mono/SceneHierarchy.cs +++ b/Editor/Mono/SceneHierarchy.cs @@ -493,8 +493,6 @@ public virtual void OnEnable() if (m_TreeViewKeyboardControlID == 0) m_TreeViewKeyboardControlID = EditorGUIUtility.GetPermanentControlID(); - - DoPingRequest(); } public virtual void OnDisable() diff --git a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs b/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs index c07d539564..c80cb9ee41 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs @@ -31,10 +31,13 @@ internal class LightingWindowLightmapPreviewTab SerializedProperty m_LightingDataAsset; SerializedProperty m_TextureCompression; - class Styles + static class Styles { public static readonly GUIStyle SelectedLightmapHighlight = "LightmapEditorSelectedHighlight"; public static readonly GUIContent LightingDataAsset = EditorGUIUtility.TrTextContent("Lighting Data Asset", "A different LightingData.asset can be assigned here. These assets are generated by baking a scene in the OnDemand mode."); + public static readonly GUIContent OpenPreview = EditorGUIUtility.TrTextContent("Open Preview"); + + public static readonly GUIStyle OpenPreviewStyle = EditorStyles.objectFieldThumb.name + "LightmapPreviewOverlay"; } public LightingWindowLightmapPreviewTab(LightmapType type) @@ -171,28 +174,27 @@ private void LightmapListGUI(LightmapData[] lightmaps, VisualisationGITexture[] private void LightmapField(Texture2D lightmap, int index, Hash128 hash) { Rect rect = GUILayoutUtility.GetRect(100, 100, EditorStyles.objectField); + Rect buttonRect = new Rect(rect.xMax - 70, rect.yMax - 14, 70, 14); if (EditorGUI.Toggle(rect, index == m_SelectedLightmapIndex, EditorStyles.objectFieldThumb)) { m_SelectedLightmapIndex = index; - if (rect.Contains(Event.current.mousePosition)) + if ((buttonRect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) || + (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 2)) + { + if (isRealtimeLightmap) + LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, true, true); + else + LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, false, true); + } + else if (rect.Contains(Event.current.mousePosition) && Event.current.clickCount == 1) { Object actualTargetObject = lightmap; Component com = actualTargetObject as Component; if (com) actualTargetObject = com.gameObject; - - if (Event.current.clickCount == 1) - EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, GUILayoutUtility.GetLastRect()); - - if (Event.current.clickCount == 2) - { - if (isRealtimeLightmap) - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, true, true); - else - LightmapPreviewWindow.CreateLightmapPreviewWindow(m_SelectedLightmapIndex, false, true); - } + EditorGUI.PingObjectOrShowPreviewOnClick(actualTargetObject, GUILayoutUtility.GetLastRect()); } } @@ -201,6 +203,8 @@ private void LightmapField(Texture2D lightmap, int index, Hash128 hash) rect = EditorStyles.objectFieldThumb.padding.Remove(rect); EditorGUI.DrawPreviewTexture(rect, lightmap); + Styles.OpenPreviewStyle.Draw(rect, Styles.OpenPreview, false, false, false, false); + if ((!isRealtimeLightmap && index == m_ActiveGameObjectLightmapIndex) || (isRealtimeLightmap && hash == m_ActiveGameObjectTextureHash)) { Styles.SelectedLightmapHighlight.Draw(rect, false, false, false, false); diff --git a/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs b/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs index 79645fd7f9..1bc8fb7a3a 100644 --- a/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs +++ b/Editor/Mono/SceneModeWindows/LightmapPreviewWindow.cs @@ -37,7 +37,9 @@ internal class LightmapPreviewWindow : EditorWindow Hash128 m_RealtimeTextureHash = new Hash128(); VisualisationGITexture m_CachedTexture; GameObject[] m_CachedTextureObjects; + int m_ActiveGameObjectLightmapIndex = -1; // the object the user selects in the scene + int m_ActiveGameObjectInstanceId = -1; // for instance based non-atlas textures such as baked emissive for Progressive Hash128 m_ActiveGameObjectTextureHash = new Hash128(); // the object the user selects in the scene private float m_ExposureSliderMax = 10f; @@ -93,19 +95,18 @@ static class Styles public static readonly GUIContent TextureNotAvailableRealtime = EditorGUIUtility.TrTextContent("The texture is not available at the moment."); public static readonly GUIContent TextureNotAvailableBaked = EditorGUIUtility.TrTextContent("The texture is not available at the moment.\nPlease try to rebake the current scene or turn on Auto, and make sure that this object is set to Lightmap Static if it's meant to be baked."); public static readonly GUIContent TextureNotAvailableBakedShadowmask = EditorGUIUtility.TrTextContent("The texture is not available at the moment.\nPlease make sure that Mixed Lights affect this GameObject and that it is set to Lightmap Static."); + public static readonly GUIContent TextureNotAvailableBakedAlbedoEmissive = EditorGUIUtility.TrTextContent("The texture is not an index based texture and is not available when using Progressive.\nPlease go to the instance you wish to debug, and select the lightmap on the Mesh Renderer."); public static readonly GUIContent TextureLoading = EditorGUIUtility.TrTextContent("Loading..."); public static readonly GUIContent ExposureIcon = EditorGUIUtility.TrIconContent("SceneViewLighting", "Controls the number of stops to over or under expose the lightmap."); } public int lightmapIndex { - get { return m_LightmapIndex; } set { m_LightmapIndex = value; } } public int instanceID { - get { return m_InstanceID; } set { m_InstanceID = value; } } @@ -115,17 +116,24 @@ public bool isRealtimeLightmap set { m_IsRealtimeLightmap = value; } } + // this seperates between lightsmaps that we opened from a specific index, or the ones that are connected to an object (where the index can change) private bool isIndexBased { - get { return m_LightmapIndex != -1; } + get { return m_InstanceID == -1; } } private string lightmapTitle { get { - return isIndexBased ? ((isRealtimeLightmap ? "Realtime Lightmap Index " : "Lightmap Index ") + lightmapIndex) : - (isRealtimeLightmap ? "Realtime Lightmap" : "Lightmap"); + if (isIndexBased) return ((isRealtimeLightmap ? "Realtime Lightmap Index " : "Lightmap Index ") + m_LightmapIndex); + + var obj = EditorUtility.InstanceIDToObject(m_InstanceID); + + if (obj) + return (isRealtimeLightmap ? "Realtime" : "") + " Lightmap for '" + obj.name + "'"; + + return (isRealtimeLightmap ? "Realtime" : "") + " Lightmap"; } } @@ -199,6 +207,7 @@ private void UpdateActiveGameObjectSelection() (terrain = Selection.activeGameObject.GetComponent()) == null)) { m_ActiveGameObjectLightmapIndex = -1; + m_ActiveGameObjectInstanceId = -1; m_ActiveGameObjectTextureHash = new Hash128(); return; } @@ -214,7 +223,10 @@ private void UpdateActiveGameObjectSelection() m_ActiveGameObjectTextureHash = new Hash128(); } else + { m_ActiveGameObjectLightmapIndex = renderer != null ? renderer.lightmapIndex : terrain.lightmapIndex; + m_ActiveGameObjectInstanceId = renderer != null ? renderer.GetInstanceID() : terrain.GetInstanceID(); + } } private void PreviewSettings() @@ -297,9 +309,11 @@ private void DrawPreview(Rect r) if (m_CachedTexture.textureAvailability == GITextureAvailability.GITextureNotAvailable || m_CachedTexture.textureAvailability == GITextureAvailability.GITextureUnknown) { - if (LightmapVisualizationUtility.IsBakedTextureType(textureType)) + if (!isRealtimeLightmap) { - if (textureType == GITextureType.BakedShadowMask) + if (!LightmapVisualizationUtility.IsAtlasTextureType(textureType) && isIndexBased) + GUI.Label(drawableArea, Styles.TextureNotAvailableBakedAlbedoEmissive, Styles.PreviewLabel); + else if (textureType == GITextureType.BakedShadowMask) GUI.Label(drawableArea, Styles.TextureNotAvailableBakedShadowmask, Styles.PreviewLabel); else GUI.Label(drawableArea, Styles.TextureNotAvailableBaked, Styles.PreviewLabel); @@ -324,8 +338,12 @@ private void DrawPreview(Rect r) case EventType.ValidateCommand: case EventType.ExecuteCommand: - if (Event.current.commandName == EventCommandNames.FrameSelected && (isRealtimeLightmap ? m_RealtimeTextureHash == m_ActiveGameObjectTextureHash : m_LightmapIndex == m_ActiveGameObjectLightmapIndex)) + if (Event.current.commandName == EventCommandNames.FrameSelected && IsSelectedObjectInLightmap(textureType)) { + // There are instance based baked textures where we don't get any STs and can't do the framing + if (!isRealtimeLightmap && !LightmapVisualizationUtility.IsAtlasTextureType(textureType)) + break; + Vector4 lightmapTilingOffset = LightmapVisualizationUtility.GetLightmapTilingOffset(lightmapType); Vector2 min = new Vector2(lightmapTilingOffset.z, lightmapTilingOffset.w); @@ -349,7 +367,7 @@ private void DrawPreview(Rect r) Rect rect = new Rect(min.x, min.y, max.x - min.x, max.y - min.y); rect.width = rect.height = Mathf.Max(rect.width, rect.height); rect.x -= (offsetX * min.x); - rect.y += (offsetY * (1 - max.y)); + rect.y += (offsetY * (1 - max.y)); m_ZoomablePreview.shownArea = rect; Event.current.Use(); @@ -377,7 +395,7 @@ private void DrawPreview(Rect r) texture.filterMode = FilterMode.Point; LightmapVisualizationUtility.DrawTextureWithUVOverlay(texture, - (m_ShowUVOverlay && (isRealtimeLightmap ? m_RealtimeTextureHash == m_ActiveGameObjectTextureHash : m_LightmapIndex == m_ActiveGameObjectLightmapIndex)) ? Selection.activeGameObject : null, + (m_ShowUVOverlay && IsSelectedObjectInLightmap(textureType)) ? Selection.activeGameObject : null, m_ShowUVOverlay ? m_CachedTextureObjects : new GameObject[] {}, drawableArea, textureRect, textureType, exposure); texture.filterMode = prevMode; } @@ -395,6 +413,17 @@ private void SelectPreviewTextureIndex(object textureOption) m_SelectedPreviewTextureOptionIndex = Array.IndexOf(options, textureOption); } + private bool IsSelectedObjectInLightmap(GITextureType textureType) + { + if (isRealtimeLightmap) + return (m_ActiveGameObjectTextureHash == m_RealtimeTextureHash); + + if (LightmapVisualizationUtility.IsAtlasTextureType(textureType)) + return (m_ActiveGameObjectLightmapIndex == m_LightmapIndex); + + return (m_ActiveGameObjectInstanceId == m_InstanceID); + } + private GITextureType GetSelectedTextureType() { GUIContent[] options = isRealtimeLightmap ? Styles.RealtimePreviewTextureOptions : Styles.BakedPreviewTextureOptions; @@ -437,7 +466,7 @@ private void UpdateCachedTexture(GITextureType textureType) { Hash128 systemHash; - if (!LightmapEditorSettings.GetInputSystemHash(instanceID, out systemHash)) + if (!LightmapEditorSettings.GetInputSystemHash(m_InstanceID, out systemHash)) return; m_RealtimeTextureHash = systemHash; @@ -446,7 +475,7 @@ private void UpdateCachedTexture(GITextureType textureType) { int lightmapIndex; - if (!LightmapEditorSettings.GetLightmapIndex(instanceID, out lightmapIndex)) + if (!LightmapEditorSettings.GetLightmapIndex(m_InstanceID, out lightmapIndex)) return; m_LightmapIndex = lightmapIndex; @@ -454,14 +483,14 @@ private void UpdateCachedTexture(GITextureType textureType) } Hash128 contentHash = isRealtimeLightmap ? LightmapVisualizationUtility.GetRealtimeGITextureHash(m_RealtimeTextureHash, textureType) : - LightmapVisualizationUtility.GetBakedGITextureHash(m_LightmapIndex, 0, textureType); + LightmapVisualizationUtility.GetBakedGITextureHash(m_LightmapIndex, m_InstanceID, textureType); // if we need to fetch a new texture if (m_CachedTexture.texture == null || m_CachedTexture.type != textureType || m_CachedTexture.contentHash != contentHash || m_CachedTexture.contentHash == new Hash128()) { m_CachedTexture = isRealtimeLightmap ? LightmapVisualizationUtility.GetRealtimeGITexture(m_RealtimeTextureHash, textureType) : - LightmapVisualizationUtility.GetBakedGITexture(m_LightmapIndex, 0, textureType); + LightmapVisualizationUtility.GetBakedGITexture(m_LightmapIndex, m_InstanceID, textureType); } if (!m_ShowUVOverlay) @@ -474,8 +503,10 @@ private void UpdateCachedTexture(GITextureType textureType) if (isRealtimeLightmap) m_CachedTextureObjects = LightmapVisualizationUtility.GetRealtimeGITextureRenderers(m_RealtimeTextureHash); - else + else if (LightmapVisualizationUtility.IsAtlasTextureType(textureType)) m_CachedTextureObjects = LightmapVisualizationUtility.GetBakedGITextureRenderers(m_LightmapIndex); + else // if it's an instance based baked lightmap, we only have 1 object in it + m_CachedTextureObjects = new GameObject[] {}; } private Rect ResizeRectToFit(Rect rect, Rect to) diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index 7adc6e7d02..2cf27b4719 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -412,6 +412,9 @@ public float cameraDistance static Shader s_ShowMipsShader; static Shader s_ShowTextureStreamingShader; static Shader s_AuraShader; + static Shader s_BuildFilterShader; + static Material s_FadeMaterial; + static Material s_ApplyFilterMaterial; static Texture2D s_MipColorsTexture; // Handle Dragging of stuff over scene view @@ -1317,31 +1320,7 @@ private void DoDrawCamera(Rect windowSpaceCameraRect, Rect groupSpaceCameraRect, if (UseSceneFiltering()) { if (evt.type == EventType.Repaint) - { - // First pass: Draw objects which do not meet the search filter with grayscale image effect. - Handles.EnableCameraFx(m_Camera, true); - - Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowRest); - - float fade = Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime)); - Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - Handles.DrawCameraFade(m_Camera, fade); - - // Second pass: Draw aura for objects which do meet search filter, but are occluded. - Handles.EnableCameraFx(m_Camera, false); - Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered); - if (!s_AuraShader) - s_AuraShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewAura.shader") as Shader; - m_Camera.SetReplacementShader(s_AuraShader, ""); - Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - - // Third pass: Draw objects which do meet filter normally - m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); - Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode, gridParam); - - if (fade < 1) - Repaint(); - } + RenderFilteredScene(groupSpaceCameraRect); if (evt.type == EventType.Repaint) RenderTexture.active = null; @@ -1368,6 +1347,73 @@ private void DoDrawCamera(Rect windowSpaceCameraRect, Rect groupSpaceCameraRect, } } + void RenderFilteredScene(Rect groupSpaceCameraRect) + { + var oldTargetTexture = m_Camera.targetTexture; + var oldDepthTextureMode = m_Camera.depthTextureMode; + var oldRenderingPath = m_Camera.renderingPath; + + // First pass: Draw the scene normally in destination render textsure + DoClearCamera(groupSpaceCameraRect); + Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); + + // Second pass: Blit the scene faded out in a different render texture + var fadedDesc = m_SceneTargetTexture.descriptor; + var fadedRT = RenderTexture.GetTemporary(fadedDesc); + fadedRT.name = "FadedRT"; + + float fade = Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime)); + if (!s_FadeMaterial) + s_FadeMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewGrayscaleEffectFade.mat") as Material; + s_FadeMaterial.SetFloat("_Fade", fade); + Graphics.Blit(m_SceneTargetTexture, fadedRT, s_FadeMaterial); + + // Third pass: Draw aura for objects which meet the search filter, but are occluded. + m_Camera.renderingPath = RenderingPath.Forward; + if (!s_AuraShader) + s_AuraShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewAura.shader") as Shader; + m_Camera.SetReplacementShader(s_AuraShader, ""); + m_Camera.SetTargetBuffers(fadedRT.colorBuffer, m_SceneTargetTexture.depthBuffer); + m_Camera.depthTextureMode = DepthTextureMode.None; + Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered); + Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); + + // Fourth pass: Draw objects which do meet filter in a mask + var maskDesc = m_SceneTargetTexture.descriptor; + maskDesc.colorFormat = RenderTextureFormat.R8; + maskDesc.depthBufferBits = 0; + var maskRT = RenderTexture.GetTemporary(maskDesc); + maskRT.name = "MaskRT"; + + RenderTexture.active = maskRT; + GL.Clear(false, true, Color.clear); + + if (!s_BuildFilterShader) + s_BuildFilterShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewBuildFilter.shader") as Shader; + m_Camera.SetReplacementShader(s_BuildFilterShader, ""); + m_Camera.SetTargetBuffers(maskRT.colorBuffer, m_SceneTargetTexture.depthBuffer); + m_Camera.depthTextureMode = DepthTextureMode.None; + Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); + + // Final pass: Blit the faded scene where the mask isn't set + if (!s_ApplyFilterMaterial) + s_ApplyFilterMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewApplyFilter.mat") as Material; + s_ApplyFilterMaterial.SetTexture("_MaskTex", maskRT); + Graphics.Blit(fadedRT, m_SceneTargetTexture, s_ApplyFilterMaterial); + + RenderTexture.ReleaseTemporary(maskRT); + RenderTexture.ReleaseTemporary(fadedRT); + + // Reset camera + m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); + m_Camera.renderingPath = oldRenderingPath; + m_Camera.targetTexture = oldTargetTexture; + m_Camera.depthTextureMode = oldDepthTextureMode; + + if (fade < 1) + Repaint(); + } + void SetupPBRValidation() { DrawCameraMode renderMode = m_CameraMode.drawMode; @@ -2222,9 +2268,7 @@ void SetupCamera() if (Event.current.type == EventType.Repaint) { - bool enableImageEffects = false; - if (!UseSceneFiltering()) - enableImageEffects = m_CameraMode.drawMode == DrawCameraMode.Textured && sceneViewState.showImageEffects; + bool enableImageEffects = m_CameraMode.drawMode == DrawCameraMode.Textured && sceneViewState.showImageEffects; UpdateImageEffects(enableImageEffects); } diff --git a/Editor/Mono/Scripting/Compilers/UWPReferences.cs b/Editor/Mono/Scripting/Compilers/UWPReferences.cs index da1105c3a5..d2c2861e13 100644 --- a/Editor/Mono/Scripting/Compilers/UWPReferences.cs +++ b/Editor/Mono/Scripting/Compilers/UWPReferences.cs @@ -31,20 +31,22 @@ internal class UWPSDK { public readonly Version Version; public readonly Version MinVSVersion; + public readonly IEnumerable PreviousSDKs; - public UWPSDK(Version version, Version minVSVersion) + public UWPSDK(Version version, Version minVSVersion, IEnumerable previousSDKs) { Version = version; MinVSVersion = minVSVersion; + PreviousSDKs = previousSDKs; } } - internal class PreviousSDKVersion + internal class PreviousUWPSDK { - public readonly string Version; + public readonly Version Version; public readonly bool DefaultFallback; - public PreviousSDKVersion(string version, bool defaultFallback) + public PreviousUWPSDK(Version version, bool defaultFallback) { Version = version; DefaultFallback = defaultFallback; @@ -71,13 +73,19 @@ public UWPExtension(string manifest, string windowsKitsFolder, string sdkVersion } } - public static string[] GetReferences(Version sdkVersion) + private static readonly Version kMinimumSupportedUWPVersion = new Version(10, 0, 10240, 0); + private static readonly PreviousUWPSDK kMinimumSupportedPreviousUWPSDK = new PreviousUWPSDK(kMinimumSupportedUWPVersion, true); + private static readonly UWPSDK kMinimumSupportedUWPSDK = new UWPSDK(kMinimumSupportedUWPVersion, new Version(14, 0), new[] { kMinimumSupportedPreviousUWPSDK }); + + public static UWPSDK MinimumSupportedUWPSDK { get { return kMinimumSupportedUWPSDK; } } + + public static string[] GetReferences(UWPSDK sdk) { var folder = GetWindowsKit10(); if (string.IsNullOrEmpty(folder)) return new string[0]; - var version = SdkVersionToString(sdkVersion); + var version = SdkVersionToString(sdk.Version); var references = new HashSet(StringComparer.InvariantCultureIgnoreCase); var windowsWinMd = CombinePaths(folder, "UnionMetadata", version, "Facade", "Windows.winmd"); @@ -102,13 +110,13 @@ public static string[] GetReferences(Version sdkVersion) return references.ToArray(); } - public static IEnumerable GetExtensionSDKs(Version sdkVersion) + public static IEnumerable GetExtensionSDKs(UWPSDK sdk) { var windowsKit10Directory = GetWindowsKit10(); if (string.IsNullOrEmpty(windowsKit10Directory)) return new UWPExtensionSDK[0]; - return GetExtensionSDKs(windowsKit10Directory, SdkVersionToString(sdkVersion)); + return GetExtensionSDKs(windowsKit10Directory, SdkVersionToString(sdk.Version)); } static string SdkVersionToString(Version version) @@ -125,17 +133,17 @@ static string SdkVersionToString(Version version) return sdkVersion; } - public static IEnumerable>>> GetInstalledSDKs() + public static IEnumerable GetInstalledSDKs() { var windowsKit10Directory = GetWindowsKit10(); if (string.IsNullOrEmpty(windowsKit10Directory)) - return Enumerable.Empty>>>(); + return Enumerable.Empty(); var platformsUAP = CombinePaths(windowsKit10Directory, "Platforms", "UAP"); if (!Directory.Exists(platformsUAP)) - return Enumerable.Empty>>>(); + return Enumerable.Empty(); - var allSDKs = new Dictionary>>(); + var allSDKs = new List(); var filesUnderPlatformsUAP = Directory.GetFiles(platformsUAP, "*", SearchOption.AllDirectories); var allPlatformXmlFiles = filesUnderPlatformsUAP.Where(f => string.Equals("Platform.xml", Path.GetFileName(f), StringComparison.OrdinalIgnoreCase)); @@ -158,46 +166,64 @@ public static IEnumerable e.Value).FirstOrDefault(); // Get supported previous versionss var previousVersionPath = Path.Combine(Path.GetDirectoryName(platformXmlFile), "PreviousPlatforms.xml"); - var previousVersions = new SortedList(); + var previousVersions = new List(); if (File.Exists(previousVersionPath)) { + XNamespace xn = "http://microsoft.com/schemas/Windows/SDK/PreviousPlatforms"; + XDocument previousPlatformsDocument = null; + try { - XNamespace xn = "http://microsoft.com/schemas/Windows/SDK/PreviousPlatforms"; - var previousPlatformsDocument = XDocument.Load(previousVersionPath); + previousPlatformsDocument = XDocument.Load(previousVersionPath); + } + catch + { + } - foreach (XElement previousPlatformElement in previousPlatformsDocument.Element(xn + "PreviousPlatforms").Elements(xn + "ApplicationPlatform")) + if (previousPlatformsDocument != null) + { + var previousPlatformsElement = previousPlatformsDocument.Element(xn + "PreviousPlatforms"); + if (previousPlatformsElement != null) { - var previousVersion = previousPlatformElement.Attribute("version").Value; - bool isDefault; - - if (!bool.TryParse(previousPlatformElement.Attribute("IsDefaultFallback").Value, out isDefault)) + foreach (XElement previousPlatformElement in previousPlatformsElement.Elements(xn + "ApplicationPlatform")) { - isDefault = false; + var versionAttribute = previousPlatformElement.Attribute("version"); + if (versionAttribute != null) + { + var previousVersionString = versionAttribute.Value; + bool isDefault = false; + + var isDefaultFallbackAttribute = previousPlatformElement.Attribute("IsDefaultFallback"); + if (isDefaultFallbackAttribute != null) + bool.TryParse(isDefaultFallbackAttribute.Value, out isDefault); + + var previousVersion = TryParseVersion(previousVersionString); + if (previousVersion != null && previousVersion >= kMinimumSupportedUWPVersion) + previousVersions.Add(new PreviousUWPSDK(previousVersion, isDefault)); + } } - - previousVersions.Add(previousVersion, new PreviousSDKVersion(previousVersion, isDefault)); } } - catch - { - // Ignore exception. We'll just use the default below. - } } if (previousVersions.Count == 0) { - // For previous versions, only support the current version if no PreviousVersions.xml was found. - previousVersions.Add(version.ToString(), new PreviousSDKVersion(version.ToString(), true)); + // For previous versions, only support the current version and our minimum supported version if no PreviousVersions.xml was found. + previousVersions.Add(new PreviousUWPSDK(version, true)); + + if (version > kMinimumSupportedUWPVersion) + previousVersions.Add(new PreviousUWPSDK(kMinimumSupportedUWPVersion, false)); } - previousVersions.Reverse(); - allSDKs.Add(new UWPSDK(version, TryParseVersion(minVSVersionString)), previousVersions); + allSDKs.Add(new UWPSDK(version, TryParseVersion(minVSVersionString), previousVersions)); } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs index 55e0c6d088..a8a63432fa 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs @@ -11,6 +11,14 @@ namespace UnityEditor.Scripting.ScriptCompilation { + internal class IllegalNamespaceParsing : Exception + { + public IllegalNamespaceParsing(string className, Exception cause) + : base($"Searching for classname: '{className}' caused error in CSharpNameParser", cause) + { + } + } + internal static class CSharpNamespaceParser { static readonly Regex k_ReDefineExpr = new Regex(@"r'\s+|([=!]=)\s*(true|false)|([_a-zA-Z][_a-zA-Z0-9]*)|([()!]|&&|\|\|)", RegexOptions.Compiled); @@ -20,6 +28,7 @@ internal static class CSharpNamespaceParser static readonly Regex k_VerbatimStrings = new Regex(@"@(""[^""]*"")+", RegexOptions.Compiled); static readonly Regex k_NewlineRegex = new Regex("\r\n?", RegexOptions.Compiled); static readonly Regex k_SingleQuote = new Regex(@"((? defines) var split = source.Split(new[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (var s in split) { - if (s.Contains("#define")) + var match = k_ConditionalCompilation.Match(s); + var directive = match.Groups[1].Value; + var arg = match.Groups[2].Value; + if (directive == "define") { - if (stack.Count == 0 || stack.Peek().Item1) defines.Add(s.Split(new[] { "#define" }, StringSplitOptions.None)[1].Trim()); + if (stack.Count == 0 || stack.Peek().Item1) defines.Add(arg.Trim()); } - else if (s.Contains("#undefine")) + else if (directive == "undefine") { - if (stack.Count == 0 || stack.Peek().Item1) defines.Add(s.Split(new[] { "#define" }, StringSplitOptions.None)[1].Trim()); + if (stack.Count == 0 || stack.Peek().Item1) defines.Add(arg.Trim()); } - else if (s.Contains("#if")) + else if (directive == "if") { - var evalResult = EvaluateDefine(s.Split(new[] { "#if" }, StringSplitOptions.None)[1].Trim(), defines); + var evalResult = EvaluateDefine(arg.Trim(), defines); var isEmitting = stack.Count == 0 || stack.Peek().Item1; stack.Push(new Tuple(isEmitting && evalResult, isEmitting && !evalResult)); } - else if (s.Contains("#elif")) + else if (directive == "elif") { + var evalResult = EvaluateDefine(arg, defines); var elseEmitting = stack.Peek().Item2; - var evalResult = EvaluateDefine(s.Split(new[] { "#elif" }, StringSplitOptions.None)[1], defines); - stack.Pop(); - stack.Push(new Tuple(elseEmitting && evalResult, elseEmitting && !evalResult)); + stack.Pop(); stack.Push(new Tuple(elseEmitting && evalResult, elseEmitting && !evalResult)); } - else if (s.Contains("#else")) + else if (directive == "else") { var elseEmitting = stack.Peek().Item2; - stack.Pop(); - stack.Push(new Tuple(elseEmitting, false)); + stack.Pop(); stack.Push(new Tuple(elseEmitting, false)); } - else if (s.Contains("#endif")) + else if (directive == "endif") { stack.Pop(); } diff --git a/Editor/Mono/UIElements/UXMLEditorFactories.cs b/Editor/Mono/UIElements/UXMLEditorFactories.cs index e08c7e366c..db9c6cd070 100644 --- a/Editor/Mono/UIElements/UXMLEditorFactories.cs +++ b/Editor/Mono/UIElements/UXMLEditorFactories.cs @@ -6,11 +6,12 @@ namespace UnityEditor.Experimental.UIElements { + [InitializeOnLoad] internal class UXMLEditorFactories { private static bool s_Registered; - internal static void RegisterAll() + static UXMLEditorFactories() { if (s_Registered) return; diff --git a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs b/Editor/Mono/UIElements/VisualTreeAssetEditor.cs index 230c2b81b2..dd9f1f6885 100644 --- a/Editor/Mono/UIElements/VisualTreeAssetEditor.cs +++ b/Editor/Mono/UIElements/VisualTreeAssetEditor.cs @@ -59,7 +59,6 @@ public void Render(VisualTreeAsset vta, Rect r, GUIStyle background) if (m_Panel == null) { - UXMLEditorFactories.RegisterAll(); m_Panel = UIElementsUtility.FindOrCreatePanel(m_LastTree, ContextType.Editor, new DataWatchService()); if (m_Panel.visualTree.styleSheets == null) { diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index ec051304c7..f7ab82ff33 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -504,7 +504,7 @@ private string ProjectHeader(MonoIsland island, { targetframeworkversion = "v4.7.1"; } - targetLanguageVersion = "7.2"; + targetLanguageVersion = "7.3"; } else if (_settings.VisualStudioVersion == 9) { diff --git a/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs b/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs index 9f52de4a7e..3eb316accf 100644 --- a/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs +++ b/Editor/Src/VR/Mono/GoogleVR/VRCustomOptionsGoogleVR.cs @@ -47,7 +47,7 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { return EditorGUIUtility.singleLineHeight + (EditorGUIUtility.standardVerticalSpacing * 2.0f); } @@ -87,9 +87,9 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { - return base.GetHeight() + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + return base.GetHeight(target) + EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; } } @@ -266,7 +266,7 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { float singleLineCount = 5.0f; float thumbnailCount = 2.0f; @@ -278,7 +278,7 @@ public override float GetHeight() verticalSpacingCount += 1.0f; } - return base.GetHeight() + (EditorGUIUtility.singleLineHeight * singleLineCount) + + return base.GetHeight(target) + (EditorGUIUtility.singleLineHeight * singleLineCount) + (EditorGUI.kObjectFieldThumbnailHeight * thumbnailCount) + (EditorGUIUtility.standardVerticalSpacing * verticalSpacingCount); } diff --git a/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs b/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs index 162bf65800..a76b51cb62 100644 --- a/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs +++ b/Editor/Src/VR/Mono/Oculus/VRCustomOptionsOculus.cs @@ -13,6 +13,7 @@ internal class VRCustomOptionsOculus : VRCustomOptions { static GUIContent s_SharedDepthBufferLabel = EditorGUIUtility.TextContent("Shared Depth Buffer|Enable depth buffer submission to allow for overlay depth occlusion, etc."); static GUIContent s_DashSupportLabel = EditorGUIUtility.TextContent("Dash Support|If enabled, pressing the home button brings up Dash, otherwise it brings up the older universal menu."); + static GUIContent s_SharedDepthAndroidInfo = EditorGUIUtility.TrTextContent("Shared Depth Buffer and Dash Support aren't available when targeting mobile."); SerializedProperty m_SharedDepthBuffer; SerializedProperty m_DashSupport; @@ -33,39 +34,51 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) { rect.y += EditorGUIUtility.standardVerticalSpacing; - EditorGUI.BeginDisabled(target == BuildTargetGroup.Android); - - rect.height = EditorGUIUtility.singleLineHeight; - GUIContent label = EditorGUI.BeginProperty(rect, s_SharedDepthBufferLabel, m_SharedDepthBuffer); - EditorGUI.BeginChangeCheck(); - bool boolValue = EditorGUI.Toggle(rect, label, m_SharedDepthBuffer.boolValue); - if (EditorGUI.EndChangeCheck()) + if (target != BuildTargetGroup.Android) { - m_SharedDepthBuffer.boolValue = boolValue; - } - EditorGUI.EndProperty(); - rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; + rect.height = EditorGUIUtility.singleLineHeight; + GUIContent label = EditorGUI.BeginProperty(rect, s_SharedDepthBufferLabel, m_SharedDepthBuffer); + EditorGUI.BeginChangeCheck(); + bool boolValue = EditorGUI.Toggle(rect, label, m_SharedDepthBuffer.boolValue); + if (EditorGUI.EndChangeCheck()) + { + m_SharedDepthBuffer.boolValue = boolValue; + } + EditorGUI.EndProperty(); + rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; - rect.height = EditorGUIUtility.singleLineHeight; - label = EditorGUI.BeginProperty(rect, s_DashSupportLabel, m_DashSupport); - EditorGUI.BeginChangeCheck(); - boolValue = EditorGUI.Toggle(rect, label, m_DashSupport.boolValue); - if (EditorGUI.EndChangeCheck()) + rect.height = EditorGUIUtility.singleLineHeight; + label = EditorGUI.BeginProperty(rect, s_DashSupportLabel, m_DashSupport); + EditorGUI.BeginChangeCheck(); + boolValue = EditorGUI.Toggle(rect, label, m_DashSupport.boolValue); + if (EditorGUI.EndChangeCheck()) + { + m_DashSupport.boolValue = boolValue; + } + EditorGUI.EndProperty(); + } + else { - m_DashSupport.boolValue = boolValue; + EditorGUI.BeginDisabled(true); + EditorGUI.LabelField(rect, s_SharedDepthAndroidInfo.text, EditorStyles.wordWrappedMiniLabel); + EditorGUI.EndDisabled(); } - EditorGUI.EndProperty(); - - EditorGUI.EndDisabled(); rect.y += rect.height + EditorGUIUtility.standardVerticalSpacing; return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { - return (EditorGUIUtility.singleLineHeight * 2.0f) + (EditorGUIUtility.standardVerticalSpacing * 3.0f); + if (target != BuildTargetGroup.Android) + { + return (EditorGUIUtility.singleLineHeight * 2.0f) + (EditorGUIUtility.standardVerticalSpacing * 3.0f); + } + else + { + return (EditorGUIUtility.singleLineHeight * 1.0f) + (EditorGUIUtility.standardVerticalSpacing * 2.0f); + } } } } diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs index 2cb70ecd12..eec3acf2ce 100644 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs @@ -160,6 +160,8 @@ internal void XRSectionGUI(BuildTargetGroup targetGroup, int sectionIndex) VuforiaGUI(targetGroup); + RemotingWSAHolographicGUI(targetGroup); + Stereo360CaptureGUI(targetGroup); ErrorOnARDeviceIncompatibility(targetGroup); @@ -170,6 +172,11 @@ internal void XRSectionGUI(BuildTargetGroup targetGroup, int sectionIndex) m_Settings.EndSettingsBox(); } + internal bool TargetGroupSupportsWSAHolographicRemoting(BuildTargetGroup targetGroup) + { + return targetGroup == BuildTargetGroup.WSA; + } + private void DevicesGUI(BuildTargetGroup targetGroup) { if (!TargetGroupSupportsVirtualReality(targetGroup)) @@ -474,7 +481,7 @@ private float GetVRDeviceElementHeight(BuildTargetGroup target, int index) VRCustomOptions customOptions; if (m_CustomOptions.TryGetValue(name, out customOptions)) { - customOptionsHeight = customOptions.IsExpanded ? customOptions.GetHeight() + EditorGUI.kControlVerticalSpacing : 0.0f; + customOptionsHeight = customOptions.IsExpanded ? customOptions.GetHeight(target) + EditorGUI.kControlVerticalSpacing : 0.0f; } return list.elementHeight + customOptionsHeight; @@ -612,5 +619,26 @@ internal void VuforiaGUI(BuildTargetGroup targetGroup) EditorGUILayout.HelpBox("Vuforia Augmented Reality is required when using the Vuforia Virtual Reality SDK.", MessageType.Info); } } + + internal void RemotingWSAHolographicGUI(BuildTargetGroup targetGroup) + { + if (!TargetGroupSupportsWSAHolographicRemoting(targetGroup)) + return; + var shouldEnableScope = VREditor.GetVREnabledOnTargetGroup(targetGroup) && GetVRDeviceElementIsInList(targetGroup, "WindowsMR"); + using (new EditorGUI.DisabledScope(!shouldEnableScope)) + { + var remotingEnabled = PlayerSettings.GetWsaHolographicRemotingEnabled(); + EditorGUI.BeginChangeCheck(); + remotingEnabled = EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("WSA Holographic Remoting Supported"), remotingEnabled); + if (EditorGUI.EndChangeCheck()) + { + PlayerSettings.SetWsaHolographicRemotingEnabled(remotingEnabled); + } + } + if (shouldEnableScope) + { + EditorGUILayout.HelpBox("WindowsMR is required when using WSA Holographic Remoting.", MessageType.Info); + } + } } } diff --git a/Editor/Src/VR/Mono/VRCustomOptions.cs b/Editor/Src/VR/Mono/VRCustomOptions.cs index 4f2987cfd7..e6b810c3bb 100644 --- a/Editor/Src/VR/Mono/VRCustomOptions.cs +++ b/Editor/Src/VR/Mono/VRCustomOptions.cs @@ -65,12 +65,12 @@ public virtual void Initialize(SerializedObject settings, string propertyName) } abstract public Rect Draw(BuildTargetGroup target, Rect rect); - abstract public float GetHeight(); + abstract public float GetHeight(BuildTargetGroup target); } internal class VRCustomOptionsNone : VRCustomOptions { public override Rect Draw(BuildTargetGroup target, Rect rect) { return rect; } - public override float GetHeight() { return 0.0f; } + public override float GetHeight(BuildTargetGroup target) { return 0.0f; } } } diff --git a/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs b/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs index 23cacc5175..0dec8b4b95 100644 --- a/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs +++ b/Editor/Src/VR/Mono/WindowsHolographic/VRCustomOptionsWindowsHolographic.cs @@ -61,7 +61,7 @@ public override Rect Draw(BuildTargetGroup target, Rect rect) return rect; } - public override float GetHeight() + public override float GetHeight(BuildTargetGroup target) { return EditorGUIUtility.singleLineHeight * 2.0f; } diff --git a/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs b/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs index 4ec47ccaa8..fd4083cfae 100644 --- a/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs +++ b/Modules/AssetPipelineEditor/Public/PluginImporter.bindings.cs @@ -213,6 +213,9 @@ public bool GetExcludeFromAnyPlatform(BuildTarget platform) [NativeMethod("SetCompatibleWithEditor")] extern internal void SetCompatibleWithEditorWithBuildTargetsInternal(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool enable); + [NativeMethod("IsCompatibleWithDefines")] + extern internal bool IsCompatibleWithDefines(string[] defines); + internal void SetCompatibleWithEditor(BuildTargetGroup buildTargetGroup, BuildTarget buildTarget, bool enable) { SetCompatibleWithEditorWithBuildTargetsInternal(buildTargetGroup, buildTarget, enable); diff --git a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs index 3ca57653be..0ad5078c77 100644 --- a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs @@ -10,12 +10,10 @@ namespace UnityEditor.Profiling.Memory.Experimental { - // Note: this snapshot is completely serializable by unity's serializer. // !!!!! NOTE: Keep in sync with Runtime\Profiler\MemorySnapshots.cpp - public class PackedMemorySnapshot : ISerializationCallbackReceiver + public class PackedMemorySnapshot : IDisposable { - private static readonly UInt64 kMinSupportedVersion = 7; - + static readonly UInt64 kMinSupportedVersion = 7; public static PackedMemorySnapshot Load(string path) { MemorySnapshotFileReader reader = new MemorySnapshotFileReader(path); @@ -42,7 +40,6 @@ public static void Save(PackedMemorySnapshot snapshot, string writePath) FileUtil.CopyFileIfExists(path, writePath, true); } - [SerializeField] MemorySnapshotFileReader m_Reader = null; public ConnectionEntries connections { get; internal set; } @@ -84,15 +81,6 @@ internal void BuildEntries() typeDescriptions = new TypeDescriptionEntries(m_Reader); } - public void OnBeforeSerialize() - { - } - - public void OnAfterDeserialize() - { - BuildEntries(); - } - internal MemorySnapshotFileReader GetReader() { return m_Reader; @@ -106,11 +94,11 @@ public UInt32 version } } - public UnityEngine.Profiling.Memory.Experimental.MetaData metadata + public MetaData metadata { get { - byte[] array = m_Reader.GetDataSingle(EntryType.Metadata_UserMetadata, ConversionFunctions.ToByteArray); + byte[] array = m_Reader.GetDataSingle(EntryType.Metadata_UserMetadata, ConversionFunctions.ToByteArray); // decoded as // content_data_length // content_data @@ -228,7 +216,7 @@ public DateTime recordDate } } - public UnityEngine.Profiling.Memory.Experimental.CaptureFlags captureFlags + public CaptureFlags captureFlags { get { @@ -243,6 +231,31 @@ public VirtualMachineInformation virtualMachineInformation return m_Reader.GetDataSingle(EntryType.Metadata_VirtualMachineInformation, ConversionFunctions.ToVirtualMachineInformation); } } + + ~PackedMemorySnapshot() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (m_Reader == null) + { + return; + } + + m_Reader.Dispose(); + m_Reader = null; + } + } } [Flags] diff --git a/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs b/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs index 5ff7053662..5a6c077a9e 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.IO; using UnityEngine; namespace UnityEditor.MemoryProfiler @@ -15,23 +16,33 @@ private static void SnapshotFinished(string path, bool result) { if (result) { - UnityEditor.Profiling.Memory.Experimental.PackedMemorySnapshot snapshot = UnityEditor.Profiling.Memory.Experimental.PackedMemorySnapshot.Load(path); + Profiling.Memory.Experimental.PackedMemorySnapshot snapshot = Profiling.Memory.Experimental.PackedMemorySnapshot.Load(path); - OnSnapshotReceived(new PackedMemorySnapshot(snapshot)); + var oldSnapshot = new PackedMemorySnapshot(snapshot); + snapshot.Dispose(); + File.Delete(path); + + OnSnapshotReceived(oldSnapshot); } else { + if (File.Exists(path)) + File.Delete(path); + OnSnapshotReceived(null); } } - public static void RequestNewSnapshot() + internal static string GetTemporarySnapshotPath() { string[] s = Application.dataPath.Split('/'); string projectName = s[s.Length - 2]; - string path = Application.temporaryCachePath + "/" + projectName + ".snap"; + return Path.Combine(Application.temporaryCachePath, projectName + ".snap"); + } - UnityEngine.Profiling.Memory.Experimental.MemoryProfiler.TakeSnapshot(path, SnapshotFinished, UnityEngine.Profiling.Memory.Experimental.CaptureFlags.NativeObjects | UnityEngine.Profiling.Memory.Experimental.CaptureFlags.ManagedObjects); + public static void RequestNewSnapshot() + { + UnityEngine.Profiling.Memory.Experimental.MemoryProfiler.TakeSnapshot(GetTemporarySnapshotPath(), SnapshotFinished, UnityEngine.Profiling.Memory.Experimental.CaptureFlags.NativeObjects | UnityEngine.Profiling.Memory.Experimental.CaptureFlags.ManagedObjects); } } diff --git a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs index 196892e6dd..ed6c0ee843 100644 --- a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs +++ b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -39,15 +40,15 @@ public IEnumerable GetDefinedShortcuts() { var entries = new List(); var names = new List(); - var shortcuts = new List(); - Menu.GetMenuItemShortcuts(names, shortcuts); + var defaultShortcuts = new List(); + Menu.GetMenuItemDefaultShortcuts(names, defaultShortcuts); entries.Capacity += names.Count; for (int index = 0; index < names.Count; ++index) { var keys = new List(); - if (!string.IsNullOrEmpty(shortcuts[index])) - keys.Add(new KeyCombination(Event.KeyboardEvent(shortcuts[index]))); + if (!string.IsNullOrEmpty(defaultShortcuts[index])) + keys.Add(new KeyCombination(Event.KeyboardEvent(defaultShortcuts[index]))); entries.Add(new MenuItemEntryDiscoveryInfo(names[index], keys)); } @@ -139,7 +140,8 @@ public MenuItemEntryDiscoveryInfo(string menuItemPath, List keys m_KeyCombinations = keys; m_MenuItemPath = menuItemPath; - m_ShortcutEntry = new ShortcutEntry(new Identifier(m_MenuItemPath), m_KeyCombinations, null, null, ShortcutType.Menu); + Action menuAction = (args) => { EditorApplication.ExecuteMenuItem(m_MenuItemPath); }; + m_ShortcutEntry = new ShortcutEntry(new Identifier(m_MenuItemPath), m_KeyCombinations, menuAction, null, ShortcutType.Menu); } public ShortcutEntry GetShortcutEntry() diff --git a/Modules/ShortcutManagerEditor/ShortcutController.cs b/Modules/ShortcutManagerEditor/ShortcutController.cs index f551108c50..34f3303ddc 100644 --- a/Modules/ShortcutManagerEditor/ShortcutController.cs +++ b/Modules/ShortcutManagerEditor/ShortcutController.cs @@ -20,6 +20,8 @@ static ShortcutIntegration() // Need to reinitialize after project load if we want menu items EditorApplication.projectWasLoaded += InitializeController; + + EditorApplication.focusChanged += OnFocusChanged; } static bool HasAnyEntriesHandler() @@ -33,6 +35,17 @@ static void EventHandler() instance.HandleKeyEvent(Event.current); } + static void OnInvokingAction(ShortcutEntry shortcutEntry, ShortcutArguments shortcutArguments) + { + // Separate shortcut actions into different undo groups + Undo.IncrementCurrentGroup(); + } + + static void OnFocusChanged(bool isFocused) + { + instance.trigger.ResetActiveClutches(); + } + static void InitializeController() { var shortcutProviders = new IDiscoveryShortcutProvider[] @@ -45,6 +58,7 @@ static void InitializeController() var discovery = new Discovery(shortcutProviders, identifierConflictHandler, invalidContextReporter); instance = new ShortcutController(discovery); instance.Initialize(instance.profileManager); + instance.trigger.invokingAction += OnInvokingAction; } } @@ -55,6 +69,7 @@ class ShortcutController public IShortcutProfileManager profileManager { get; } public IDirectory directory => m_Directory; + public Trigger trigger => m_Trigger; ContextManager m_ContextManager = new ContextManager(); diff --git a/Modules/ShortcutManagerEditor/ShortcutEntry.cs b/Modules/ShortcutManagerEditor/ShortcutEntry.cs index 298751209b..06f605f018 100644 --- a/Modules/ShortcutManagerEditor/ShortcutEntry.cs +++ b/Modules/ShortcutManagerEditor/ShortcutEntry.cs @@ -74,10 +74,10 @@ class ShortcutEntry public Type context => m_Context; public ShortcutType type => m_Type; - internal ShortcutEntry(Identifier id, List defaultCombination, Action action, Type context, ShortcutType type) + internal ShortcutEntry(Identifier id, IEnumerable defaultCombination, Action action, Type context, ShortcutType type) { m_Identifier = id; - m_DefaultCombinations = new List(defaultCombination); + m_DefaultCombinations = defaultCombination.ToList(); m_Context = context ?? ContextManager.globalContextType; m_Action = action; m_Type = type; diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index e6ccda2c44..28201c667a 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -17,7 +17,8 @@ class Trigger List m_KeyCombinationSequence = new List(); List m_Entries = new List(); Dictionary> m_ActiveClutches = new Dictionary>(); - HashSet m_KeysDown = new HashSet(); + + public event Action invokingAction; public Trigger(IDirectory directory, IConflictResolver conflictResolver) { @@ -32,7 +33,6 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) if (evt.type == EventType.KeyUp) { - m_KeysDown.Remove(evt.keyCode); Tuple clutchTuple; if (m_ActiveClutches.TryGetValue(evt.keyCode, out clutchTuple)) { @@ -44,17 +44,18 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) context = clutchContext, state = ShortcutState.End }; + invokingAction?.Invoke(clutchTuple.Item1, args); clutchTuple.Item1.action(args); } return; } - if (m_KeysDown.Contains(evt.keyCode)) + // Use the event and return if the key is currently used in an active clutch + if (m_ActiveClutches.ContainsKey(evt.keyCode)) { evt.Use(); return; } - m_KeysDown.Add(evt.keyCode); var keyCodeCombination = new KeyCombination(evt); m_KeyCombinationSequence.Add(keyCodeCombination); @@ -93,6 +94,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) { case ShortcutType.Action: args.state = ShortcutState.End; + invokingAction?.Invoke(shortcutEntry, args); shortcutEntry.action(args); evt.Use(); Reset(); @@ -103,6 +105,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) { m_ActiveClutches.Add(evt.keyCode, new Tuple(shortcutEntry, args.context)); args.state = ShortcutState.Begin; + invokingAction?.Invoke(shortcutEntry, args); shortcutEntry.action(args); evt.Use(); Reset(); @@ -110,7 +113,8 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) break; case ShortcutType.Menu: args.state = ShortcutState.End; - EditorApplication.ExecuteMenuItem(shortcutEntry.identifier.path); + invokingAction?.Invoke(shortcutEntry, args); + shortcutEntry.action(args); evt.Use(); Reset(); break; @@ -128,6 +132,22 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) } } + public void ResetActiveClutches() + { + foreach (var clutchTuple in m_ActiveClutches.Values) + { + var args = new ShortcutArguments + { + context = clutchTuple.Item2, + state = ShortcutState.End, + }; + invokingAction?.Invoke(clutchTuple.Item1, args); + clutchTuple.Item1.action(args); + } + + m_ActiveClutches.Clear(); + } + public bool HasAnyEntries() { return m_Entries.Any(); diff --git a/Modules/TextCore/Managed/AssemblyInfo.cs b/Modules/TextCore/Managed/AssemblyInfo.cs index 6e1c470b4e..8400fd720c 100644 --- a/Modules/TextCore/Managed/AssemblyInfo.cs +++ b/Modules/TextCore/Managed/AssemblyInfo.cs @@ -9,3 +9,5 @@ [assembly: InternalsVisibleTo("Unity.TextCore.Editor")] [assembly: InternalsVisibleTo("Unity.TextMeshPro")] [assembly: InternalsVisibleTo("Unity.TextMeshPro.Editor")] +[assembly: InternalsVisibleTo("Unity.FontEngine.Tests")] +[assembly: InternalsVisibleTo("Unity.FontEngine.Editor.Tests")] diff --git a/Modules/TextCore/Managed/FaceInfo.cs b/Modules/TextCore/Managed/FaceInfo.cs new file mode 100644 index 0000000000..fe1b8fadb9 --- /dev/null +++ b/Modules/TextCore/Managed/FaceInfo.cs @@ -0,0 +1,261 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using UnityEngine.TextCore.LowLevel; + + +namespace UnityEngine.TextCore +{ + /// + /// A structure that contains information about a given typeface and for a specific point size. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public struct FaceInfo + { + /// + /// The name of the font typeface also known as family name. + /// + public string familyName { get { return m_FamilyName; } set { m_FamilyName = value; } } + + /// + /// The style name of the typeface which defines both the visual style and weight of the typeface. + /// + public string styleName { get { return m_StyleName; } set { m_StyleName = value; } } + + /// + /// The point size used for sampling the typeface. This is also referenced as sampling point size. + /// + public int pointSize { get { return m_PointSize; } set { m_PointSize = value; } } + + /// + /// The relative scale of the typeface. + /// Default value is 1.0f. + /// + public float scale { get { return m_Scale; } set { m_Scale = value; } } + + // Key metrics for the typeface + + /// + /// The line height represents the distance between consecutive lines of text. + /// This is the distance from baseline to baseline. It is usually computed as line height = ascent - descent + line gap. + /// + public float lineHeight { get { return m_LineHeight; } set { m_LineHeight = value; } } + + /// + /// The Ascent line is typically located at the top of the tallest glyph in the typeface. This represents the distance between the baseline and the tallest ascender. This value is usually positive. + /// + public float ascentLine { get { return m_AscentLine; } set { m_AscentLine = value; } } + + /// + /// The Cap line is typically located at the top of capital letters. This value represents the distance between the baseline and the top of capital letters. + /// + public float capLine { get { return m_CapLine; } set { m_CapLine = value; } } + + /// + /// The Mean line is typically located at the top of lowercase letters. This value represents the distance between the baseline and the top of lowercase letters. + /// + public float meanLine { get { return m_MeanLine; } set { m_MeanLine = value; } } + + /// + /// The Baseline is an imaginary line upon which all glyphs appear to rest on. This value is typically zero. + /// + public float baseline { get { return m_Baseline; } set { m_Baseline = value; } } + + /// + /// The Descent line is typically located at the bottom of the glyph with the lowest descender in the typeface. This represents the distance between the baseline and the lowest descender. This value is usually negative. + /// + public float descentLine { get { return m_DescentLine; } set { m_DescentLine = value; } } + + /// + /// The position of characters using superscript. + /// + public float superscriptOffset { get { return m_SuperscriptOffset; } set { m_SuperscriptOffset = value; } } + + /// + /// The relative size / scale of superscript characters. + /// + public float superscriptSize { get { return m_SuperscriptSize; } set { m_SuperscriptSize = value; } } + + /// + /// The position of characters using subscript. + /// + public float subscriptOffset { get { return m_SubscriptOffset; } set { m_SubscriptOffset = value; } } + + /// + /// The relative size / scale of subscript characters. + /// + public float subscriptSize { get { return m_SubscriptSize; } set { m_SubscriptSize = value; } } + + /// + /// The position of the underline. + /// + public float underlineOffset { get { return m_UnderlineOffset; } set { m_UnderlineOffset = value; } } + + /// + /// The thickness of the underline. + /// + public float underlineThickness { get { return m_UnderlineThickness; } set { m_UnderlineThickness = value; } } + + /// + /// The position of the strikethrough. + /// + public float strikethroughOffset { get { return m_StrikethroughOffset; } set { m_StrikethroughOffset = value; } } + + /// + /// The thickness of the strikethrough. + /// + public float strikethroughThickness { get { return m_StrikethroughThickness; } set { m_StrikethroughThickness = value; } } + + /// + /// The width of the tab character. This width is typically the same as the space character. + /// + public float tabWidth { get { return m_TabWidth; } set { m_TabWidth = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("familyName")] + private string m_FamilyName; + + [SerializeField] + [NativeName("styleName")] + private string m_StyleName; + + [SerializeField] + [NativeName("pointSize")] + private int m_PointSize; + + [SerializeField] + [NativeName("scale")] + private float m_Scale; + + [SerializeField] + [NativeName("lineHeight")] + private float m_LineHeight; + + [SerializeField] + [NativeName("ascentLine")] + private float m_AscentLine; + + [SerializeField] + [NativeName("capLine")] + private float m_CapLine; + + [SerializeField] + [NativeName("meanLine")] + private float m_MeanLine; + + [SerializeField] + [NativeName("baseline")] + private float m_Baseline; + + [SerializeField] + [NativeName("descentLine")] + private float m_DescentLine; + + [SerializeField] + [NativeName("superscriptOffset")] + private float m_SuperscriptOffset; + + [SerializeField] + [NativeName("superscriptSize")] + private float m_SuperscriptSize; + + [SerializeField] + [NativeName("subscriptOffset")] + private float m_SubscriptOffset; + + [SerializeField] + [NativeName("subscriptSize")] + private float m_SubscriptSize; + + [SerializeField] + [NativeName("underlineOffset")] + private float m_UnderlineOffset; + + [SerializeField] + [NativeName("underlineThickness")] + private float m_UnderlineThickness; + + [SerializeField] + [NativeName("strikethroughOffset")] + private float m_StrikethroughOffset; + + [SerializeField] + [NativeName("strikethroughThickness")] + private float m_StrikethroughThickness; + + [SerializeField] + [NativeName("tabWidth")] + private float m_TabWidth; + + /// + /// Constructor used for testing + /// + internal FaceInfo(string familyName, string styleName, int pointSize, float scale, float lineHeight, float ascentLine, float capLine, float meanLine, float baseline, float descentLine, float superscriptOffset, float superscriptSize, float subscriptOffset, float subscriptSize, float underlineOffset, float underlineThickness, float strikethroughOffset, float strikethroughThickness, float tabWidth) + { + m_FamilyName = familyName; + m_StyleName = styleName; + + m_PointSize = pointSize; + m_Scale = scale; + + m_LineHeight = lineHeight; + m_AscentLine = ascentLine; + m_CapLine = capLine; + m_MeanLine = meanLine; + m_Baseline = baseline; + m_DescentLine = descentLine; + + m_SuperscriptOffset = superscriptOffset; + m_SuperscriptSize = superscriptSize; + m_SubscriptOffset = subscriptOffset; + m_SubscriptSize = subscriptSize; + + m_UnderlineOffset = underlineOffset; + m_UnderlineThickness = underlineThickness; + + m_StrikethroughOffset = strikethroughOffset; + m_StrikethroughThickness = strikethroughThickness; + + m_TabWidth = tabWidth; + } + + /// + /// Compares the information in this FaceInfo structure with the information in the given FaceInfo structure to determine whether they have the same values. + /// + /// The FaceInfo structure to compare this FaceInfo structure with. + /// Returns true if the FaceInfo structures have the same values. False if not. + public bool Compare(FaceInfo other) + { + return familyName == other.familyName && + styleName == other.styleName && + pointSize == other.pointSize && + FontEngineUtilities.Approximately(scale, other.scale) && + FontEngineUtilities.Approximately(lineHeight, other.lineHeight) && + FontEngineUtilities.Approximately(ascentLine, other.ascentLine) && + FontEngineUtilities.Approximately(capLine, other.capLine) && + FontEngineUtilities.Approximately(meanLine, other.meanLine) && + FontEngineUtilities.Approximately(baseline, other.baseline) && + FontEngineUtilities.Approximately(descentLine, other.descentLine) && + FontEngineUtilities.Approximately(superscriptOffset, other.superscriptOffset) && + FontEngineUtilities.Approximately(superscriptSize, other.superscriptSize) && + FontEngineUtilities.Approximately(subscriptOffset, other.subscriptOffset) && + FontEngineUtilities.Approximately(subscriptSize, other.subscriptSize) && + FontEngineUtilities.Approximately(underlineOffset, other.underlineOffset) && + FontEngineUtilities.Approximately(underlineThickness, other.underlineThickness) && + FontEngineUtilities.Approximately(strikethroughOffset, other.strikethroughOffset) && + FontEngineUtilities.Approximately(strikethroughThickness, other.strikethroughThickness) && + FontEngineUtilities.Approximately(tabWidth, other.tabWidth); + } + } +} diff --git a/Modules/TextCore/Managed/Glyph.cs b/Modules/TextCore/Managed/Glyph.cs index 0499ff254c..0aa3275e2d 100644 --- a/Modules/TextCore/Managed/Glyph.cs +++ b/Modules/TextCore/Managed/Glyph.cs @@ -6,211 +6,367 @@ using System.Runtime.InteropServices; using UnityEngine.Bindings; using UnityEngine.Scripting; +using UnityEngine.TextCore.LowLevel; namespace UnityEngine.TextCore { /// - /// A Glyph is the visual representation of a text element / character. + /// A rectangle that defines the position of a glyph within an atlas texture. /// [Serializable] - [NativeAsStruct] [UsedByNativeCode] [StructLayout(LayoutKind.Sequential)] - public class Glyph + public struct GlyphRect : IEquatable { /// - /// Constructor for a new glyph. + /// The x position of the glyph in the font atlas texture. /// - public Glyph() - { - this.index = 0; - this.x = 0; - this.y = 0; - this.width = 0; - this.height = 0; - this.bearingX = 0; - this.bearingY = 0; - this.advanceX = 0; - this.scale = 1; - this.atlasIndex = 0; - } + public int x { get { return m_X; } set { m_X = value; } } /// - /// Constructor for a new glyph + /// The y position of the glyph in the font atlas texture. /// - /// Glyph whose values are copied to the new glyph. - public Glyph(Glyph glyph) - { - this.index = glyph.index; - this.x = glyph.x; - this.y = glyph.y; - this.width = glyph.width; - this.height = glyph.height; - this.bearingX = glyph.bearingX; - this.bearingY = glyph.bearingY; - this.advanceX = glyph.advanceX; - this.scale = glyph.scale; - this.atlasIndex = glyph.atlasIndex; - } + public int y { get { return m_Y; } set { m_Y = value; } } /// - /// Constructor for a new glyph + /// The width of the glyph. /// - /// Index of the glyph. - /// The bearingX of the glyph. - /// The bearingY of the glyph. - /// The width of the glyph. - /// The height of the glyph. - /// The advanceX of the glyph. - /// The relative scale of the glyph. - public Glyph(uint index, int bearingX, int bearingY, int width, int height, int advanceX, float scale, int atlasIndex) - { - this.index = index; - this.x = 0; - this.y = 0; - this.width = width; - this.height = height; - this.bearingX = bearingX; - this.bearingY = bearingY; - this.advanceX = advanceX; - this.scale = scale; - this.atlasIndex = atlasIndex; - } + public int width { get { return m_Width; } set { m_Width = value; } } /// - /// The index of the glyph in the source font file. + /// The height of the glyph. /// - public uint index; + public int height { get { return m_Height; } set { m_Height = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("x")] + private int m_X; + + [SerializeField] + [NativeName("y")] + private int m_Y; + + [SerializeField] + [NativeName("width")] + private int m_Width; + + [SerializeField] + [NativeName("height")] + private int m_Height; + + static readonly GlyphRect s_ZeroGlyphRect = new GlyphRect(0, 0, 0, 0); /// - /// The point size at which this glyph was rastered. + /// A GlyphRect with all values set to zero. Shorthand for writing GlyphRect(0, 0, 0, 0). /// - //public int pointSize; + public static GlyphRect zero { get { return s_ZeroGlyphRect; } } /// - /// The x position of the glyph in the font atlas texture + /// Constructor for new GlyphRect. /// - public int x { get { return m_XMin; } set { m_XMin = value; } } - [SerializeField] - [NativeName("x")] - private int m_XMin; + /// The x position of the glyph in the atlas texture. + /// The y position of the glyph in the atlas texture. + /// The width of the glyph. + /// The height of the glyph. + public GlyphRect(int x, int y, int width, int height) + { + m_X = x; + m_Y = y; + m_Width = width; + m_Height = height; + } /// - /// The y position of the glyph in the font atlas texture. + /// Construct new GlyphRect from a Rect. /// - public int y { get { return m_YMin; } set { m_YMin = value; } } - [SerializeField] - [NativeName("y")] - private int m_YMin; + /// The Rect used to construct the new GlyphRect. + public GlyphRect(Rect rect) + { + m_X = (int)rect.x; + m_Y = (int)rect.y; + m_Width = (int)rect.width; + m_Height = (int)rect.height; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public bool Equals(GlyphRect other) + { + return base.Equals(other); + } + public static bool operator==(GlyphRect lhs, GlyphRect rhs) + { + return lhs.x == rhs.x && + lhs.y == rhs.y && + lhs.width == rhs.width && + lhs.height == rhs.height; + } - // ======================= - // Glyph Metrics - // ======================= + public static bool operator!=(GlyphRect lhs, GlyphRect rhs) + { + return !(lhs == rhs); + } + } + /// + /// A set of values that define the size, position and spacing of a glyph when performing text layout. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public struct GlyphMetrics : IEquatable + { /// /// The width of the glyph. /// - public int width { get { return m_Width; } set { m_Width = value; } } - [SerializeField] - [NativeName("width")] - private int m_Width; + public float width { get { return m_Width; } set { m_Width = value; } } /// /// The height of the glyph. /// - public int height { get { return m_Height; } set { m_Height = value; } } - [SerializeField] - [NativeName("height")] - private int m_Height; + public float height { get { return m_Height; } set { m_Height = value; } } /// - /// The horizontal distance from the current drawing position (origin) relative to the elements' left bounding box edge (bbox). + /// The horizontal distance from the current drawing position (origin) relative to the element's left bounding box edge (bbox). /// - public int bearingX; + public float horizontalBearingX { get { return m_HorizontalBearingX; } set { m_HorizontalBearingX = value; } } /// - /// The vertical distance from the current baseline relative to the elements' top bounding box edge (bbox). + /// The vertical distance from the current baseline relative to the element's top bounding box edge (bbox). /// - public int bearingY; + public float horizontalBearingY { get { return m_HorizontalBearingY; } set { m_HorizontalBearingY = value; } } /// /// The horizontal distance to increase (left to right) or decrease (right to left) the drawing position relative to the origin of the text element. - /// This determines the origin position of the next element. + /// This determines the origin position of the next text element. /// - public int advanceX; + public float horizontalAdvance { get { return m_HorizontalAdvance; } set { m_HorizontalAdvance = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("width")] + private float m_Width; + + [SerializeField] + [NativeName("height")] + private float m_Height; + + [SerializeField] + [NativeName("horizontalBearingX")] + private float m_HorizontalBearingX; + + [SerializeField] + [NativeName("horizontalBearingy")] + private float m_HorizontalBearingY; + + [SerializeField] + [NativeName("horizontalAdvance")] + private float m_HorizontalAdvance; /// - /// The relative scale of the text element. The default value is 1.0. + /// Constructor for new glyph metrics. /// - public float scale; + /// The width of the glyph. + /// The height of the glyph. + /// The horizontal bearingX. + /// The horizontal bearingY. + /// The horizontal advance. + public GlyphMetrics(float width, float height, float bearingX, float bearingY, float advance) + { + m_Width = width; + m_Height = height; + m_HorizontalBearingX = bearingX; + m_HorizontalBearingY = bearingY; + m_HorizontalAdvance = advance; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override bool Equals(object obj) + { + return base.Equals(obj); + } + + public bool Equals(GlyphMetrics other) + { + return base.Equals(other); + } + public static bool operator==(GlyphMetrics lhs, GlyphMetrics rhs) + { + return lhs.width == rhs.width && + lhs.height == rhs.height && + lhs.horizontalBearingX == rhs.horizontalBearingX && + lhs.horizontalBearingY == rhs.horizontalBearingY && + lhs.horizontalAdvance == rhs.horizontalAdvance; + } - // ======================= - // Font Atlas Information - // ======================= + public static bool operator!=(GlyphMetrics lhs, GlyphMetrics rhs) + { + return !(lhs == rhs); + } + } + /// + /// A Glyph is the visual representation of a text element or character. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public class Glyph + { /// - /// The index of the atlas texture that contains this glyph. + /// The index of the glyph in the source font file. /// - public int atlasIndex; + public uint index { get { return m_Index; } set { m_Index = value; } } /// - /// The x position of the glyph in the font atlas texture + /// The metrics that define the size, position and spacing of a glyph when performing text layout. /// - //public int x { get { return m_XMin; } set { m_XMin = value; } } - //[SerializeField] - //[NativeName("x")] - //private int m_XMin; + public GlyphMetrics metrics { get { return m_Metrics; } set { m_Metrics = value; } } /// - /// The y position of the glyph in the font atlas texture. + /// A rectangle that defines the position of a glyph within an atlas texture. /// - //public int y { get { return m_YMin; } set { m_YMin = value; } } - //[SerializeField] - //[NativeName("y")] - //private int m_YMin; + public GlyphRect glyphRect { get { return m_GlyphRect; } set { m_GlyphRect = value; } } /// - /// A Rect that contains the uv coordinates of the glyph in the atlas texture. These values correspond to the xMin, yMin, xMax, yMax positions. + /// The relative scale of the glyph. The default value is 1.0. /// - //public Vector4 uv; + public float scale { get { return m_Scale; } set { m_Scale = value; } } /// - /// The UV coordinate corresponding to the bottom left of the glyph in texture space. + /// The index of the atlas texture that contains this glyph. /// - //public Vector2 uv0 { get { return new Vector2(uv.xMin, uv.yMin); } } + public int atlasIndex { get { return m_AtlasIndex; } set { m_AtlasIndex = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("index")] + private uint m_Index; + + [SerializeField] + [NativeName("metrics")] + private GlyphMetrics m_Metrics; + + [SerializeField] + [NativeName("glyphRect")] + private GlyphRect m_GlyphRect; + + [SerializeField] + [NativeName("scale")] + private float m_Scale; + + [SerializeField] + [NativeName("atlasIndex")] + private int m_AtlasIndex; /// - /// The UV coordinate corresponding to the top left of the glyph in texture space. + /// Constructor for a new glyph. /// - //public Vector2 uv1 { get { return new Vector2(uv.xMin, uv.yMax); } } + public Glyph() + { + m_Index = 0; + m_Metrics = new GlyphMetrics(); + m_GlyphRect = new GlyphRect(); + m_Scale = 1; + m_AtlasIndex = 0; + } /// - /// The UV coordinate corresponding to the top right of the glyph in texture space. + /// Constructor for a new glyph /// - //public Vector2 uv2 { get { return new Vector2(uv.xMax, uv.yMax); } } + /// Glyph whose values are copied to the new glyph. + public Glyph(Glyph glyph) + { + m_Index = glyph.index; + m_Metrics = glyph.metrics; + m_GlyphRect = glyph.glyphRect; + m_Scale = glyph.scale; + m_AtlasIndex = glyph.atlasIndex; + } /// - /// The UV coordinate corresponding to the bottom right of the glyph in texture space. + /// Constructor for a new glyph /// - //public Vector2 uv3 { get { return new Vector2(uv.xMax, uv.yMin); } } + /// Glyph whose values are copied to the new glyph. + internal Glyph(GlyphMarshallingStruct glyphStruct) + { + m_Index = glyphStruct.index; + m_Metrics = glyphStruct.metrics; + m_GlyphRect = glyphStruct.glyphRect; + m_Scale = glyphStruct.scale; + m_AtlasIndex = glyphStruct.atlasIndex; + } /// - /// Set the uv coordinates of the glyph in the atlas texture. + /// Constructor for new glyph. + /// The scale will be set to a value of 1.0 and atlas index to 0. /// - /// The x position of the glyph in the atlas texture. - /// The y position of the glyph in the atlas texture. - /// The width of the atlas texture. - /// The height of the atlas texture. - //public void SetUV(int x, int y, int texWidth, int texHeight) - //{ - // uv.xMin = x / texWidth; - // uv.xMax = uv.xMin + m_Width / texWidth; - - // uv.xMin = y / texHeight; - // uv.yMax = uv.yMin + m_Height / texHeight; - //} + /// The index of the glyph in the font file. + /// The metrics of the glyph. + /// The GlyphRect defining the position of the glyph in the atlas texture. + public Glyph(uint index, GlyphMetrics metrics, GlyphRect glyphRect) + { + m_Index = index; + m_Metrics = metrics; + m_GlyphRect = glyphRect; + m_Scale = 1; + m_AtlasIndex = 0; + } + + /// + /// Constructor for new glyph. + /// + /// The index of the glyph in the font file. + /// The metrics of the glyph. + /// The GlyphRect defining the position of the glyph in the atlas texture. + /// The relative scale of the glyph. + /// The index of the atlas texture that contains the glyph. + public Glyph(uint index, GlyphMetrics metrics, GlyphRect glyphRect, float scale, int atlasIndex) + { + m_Index = index; + m_Metrics = metrics; + m_GlyphRect = glyphRect; + m_Scale = scale; + m_AtlasIndex = atlasIndex; + } + + /// + /// Compares two glyphs to determine if they have the same values. + /// + /// The glyph to compare with. + /// Returns true if the glyphs have the same values. False if not. + public bool Compare(Glyph other) + { + return index == other.index && + metrics == other.metrics && + glyphRect == other.glyphRect && + scale == other.scale && + atlasIndex == other.atlasIndex; + } } } diff --git a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs index b0b99f22f0..d886798a11 100644 --- a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs +++ b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs @@ -2,6 +2,7 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine.Scripting; using UnityEngine.Bindings; @@ -27,12 +28,11 @@ public enum GlyphLoadFlags //LOAD_LINEAR_DESIGN = 1 << 13, LOAD_NO_AUTOHINT = 1 << 15, /* Bits 16-19 are used by `LOAD_TARGET_' */ - LOAD_COLOR = 1 << 20, + //LOAD_COLOR = 1 << 20, LOAD_COMPUTE_METRICS = 1 << 21, LOAD_BITMAP_METRICS_ONLY = 1 << 22 } - /// /// Rasterizing modes used by the Font Engine to raster glyphs. /// @@ -71,21 +71,33 @@ public enum FontEngineError Invalid_File_Path = 0x1, Invalid_File_Format = 0x2, Invalid_File_Structure = 0x3, + Invalid_File = 0x4, // Glyph related errors. Invalid_Glyph_Index = 0x10, Invalid_Character_Code = 0x11, Invalid_Pixel_Size = 0x17, + // + Invalid_Library = 0x21, + + // Font face related errors. + Invalid_Face = 0x23, + + Invalid_Library_or_Face = 0x29, + + // Font atlas generation and glyph rendering related errors. + Atlas_Generation_Cancelled = 0x64, + Invalid_SharedTextureData = 0x65, + // Additional errors codes will be added as necessary to cover new FontEngine features and functionality. } - /// /// Rendering modes used by the Font Engine to render glyphs. /// [UsedByNativeCode] - public enum GlyphRenderModes + public enum GlyphRenderMode { SMOOTH_HINTED = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_BITMAP | GlyphRasterModes.RASTER_MODE_1X, SMOOTH = GlyphRasterModes.RASTER_MODE_NO_HINTING | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_BITMAP | GlyphRasterModes.RASTER_MODE_1X, @@ -98,17 +110,38 @@ public enum GlyphRenderModes SDF16 = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_MONO | GlyphRasterModes.RASTER_MODE_SDF | GlyphRasterModes.RASTER_MODE_16X, SDF32 = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_MONO | GlyphRasterModes.RASTER_MODE_SDF | GlyphRasterModes.RASTER_MODE_32X, - SDFAA = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_SDFAA | GlyphRasterModes.RASTER_MODE_1X, + SDFAA_HINTED = GlyphRasterModes.RASTER_MODE_HINTED | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_SDFAA | GlyphRasterModes.RASTER_MODE_1X, + SDFAA = GlyphRasterModes.RASTER_MODE_NO_HINTING | GlyphRasterModes.RASTER_MODE_8BIT | GlyphRasterModes.RASTER_MODE_SDFAA | GlyphRasterModes.RASTER_MODE_1X, //MSDF = RasterModes.RASTER_MODE_HINTED | RasterModes.RASTER_MODE_8BIT | RasterModes.RASTER_MODE_MSDF | RasterModes.RASTER_MODE_1X, //MSDFA = RasterModes.RASTER_MODE_HINTED | RasterModes.RASTER_MODE_8BIT | RasterModes.RASTER_MODE_MSDFA | RasterModes.RASTER_MODE_1X, } + /// + /// The modes available when packing glyphs into an atlas texture. + /// + [UsedByNativeCode] + public enum GlyphPackingMode + { + BestShortSideFit = 0x0, + BestLongSideFit = 0x1, + BestAreaFit = 0x2, + BottomLeftRule = 0x3, + ContactPointRule = 0x4, + } - [NativeHeader("Modules/TextCore/Native/FontEngine.h")] + [NativeHeader("Modules/TextCore/Native/FontEngine/FontEngine.h")] public sealed class FontEngine { private static readonly FontEngine s_Instance = new FontEngine(); + private static GlyphMarshallingStruct[] s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[16]; + private static GlyphMarshallingStruct[] s_GlyphMarshallingStruct_OUT = new GlyphMarshallingStruct[16]; + + private static GlyphRect[] s_FreeGlyphRects = new GlyphRect[16]; + private static GlyphRect[] s_UsedGlyphRects = new GlyphRect[16]; + + private static Dictionary s_GlyphLookupDictionary = new Dictionary(); + internal FontEngine() {} /// @@ -144,6 +177,38 @@ public static FontEngineError DestroyFontEngine() [NativeMethod(Name = "TextCore::FontEngine::DestroyFontEngine", IsFreeFunction = true)] static extern int DestroyFontEngine_Internal(); + /// + /// Force the cancellation of any atlas or glyph rendering process. + /// Used primarily by the Font Asset Creator. + /// + internal static void SendCancellationRequest() + { + SendCancellationRequest_Internal(); + } + + [NativeMethod(Name = "TextCore::FontEngine::SendCancellationRequest", IsFreeFunction = true)] + static extern void SendCancellationRequest_Internal(); + + /// + /// Determines if the font engine is currently in the process of rendering and adding glyphs into an atlas texture. + /// Used primarily by the Font Asset Creator. + /// + internal static extern bool isProcessingDone + { + [NativeMethod(Name = "TextCore::FontEngine::GetIsProcessingDone", IsFreeFunction = true)] + get; + } + + /// + /// Returns the generation progress on glyph packing and rendering. + /// Used primarily by the Font Asset Creator. + /// + internal static extern float generationProgress + { + [NativeMethod(Name = "TextCore::FontEngine::GetGenerationProgress", IsFreeFunction = true)] + get; + } + /// /// Load the source font file at the given file path. /// @@ -180,6 +245,9 @@ public static FontEngineError LoadFontFace(string filePath, int pointSize) /// Returns a value of zero if the font face was loaded successfully. public static FontEngineError LoadFontFace(byte[] sourceFontFile) { + if (sourceFontFile.Length == 0) + return FontEngineError.Invalid_File; + return (FontEngineError)LoadFontFace_FromSourceFontFile_Internal(sourceFontFile); } @@ -195,6 +263,9 @@ public static FontEngineError LoadFontFace(byte[] sourceFontFile) /// Returns a value of zero if the font face was loaded successfully. public static FontEngineError LoadFontFace(byte[] sourceFontFile, int pointSize) { + if (sourceFontFile.Length == 0) + return FontEngineError.Invalid_File; + return (FontEngineError)LoadFontFace_With_Size_FromSourceFontFile_Internal(sourceFontFile, pointSize); } @@ -202,6 +273,35 @@ public static FontEngineError LoadFontFace(byte[] sourceFontFile, int pointSize) static extern int LoadFontFace_With_Size_FromSourceFontFile_Internal(byte[] sourceFontFile, int pointSize); + /// + /// Load the font file from the Unity font's internal font data. Note the Unity font must be set to Dynamic with Include Font Data enabled. + /// + /// The font from which to load the data. + /// Returns a value of zero if the font face was loaded successfully. + public static FontEngineError LoadFontFace(Font font) + { + return (FontEngineError)LoadFontFace_FromFont_Internal(font); + } + + [NativeMethod(Name = "TextCore::FontEngine::LoadFontFace", IsFreeFunction = true)] + static extern int LoadFontFace_FromFont_Internal(Font font); + + + /// + /// Load the font file from the Unity font's internal font data. Note the Unity font must be set to Dynamic with Include Font Data enabled. + /// + /// The font from which to load the data. + /// The point size used to scale the font face. + /// Returns a value of zero if the font face was loaded successfully. + public static FontEngineError LoadFontFace(Font font, int pointSize) + { + return (FontEngineError)LoadFontFace_With_Size_FromFont_Internal(font, pointSize); + } + + [NativeMethod(Name = "TextCore::FontEngine::LoadFontFace", IsFreeFunction = true)] + static extern int LoadFontFace_With_Size_FromFont_Internal(Font font, int pointSize); + + /// /// Set the size of the currently loaded font face. /// @@ -212,17 +312,44 @@ public static FontEngineError SetFaceSize(int pointSize) return (FontEngineError)SetFaceSize_Internal(pointSize); } - [NativeMethod(Name = "TextCore::FontEngine::SetFaceSize", IsFreeFunction = true)] + [NativeMethod(Name = "TextCore::FontEngine::SetFaceSize", IsThreadSafe = true, IsFreeFunction = true)] static extern int SetFaceSize_Internal(int pointSize); + /// + /// Get information about the currently loaded and sized font face. + /// + /// Returns the FaceInfo of the currently loaded font face. + public static FaceInfo GetFaceInfo() + { + FaceInfo faceInfo = new FaceInfo(); + + GetFaceInfo_Internal(ref faceInfo); + + return faceInfo; + } + + [NativeMethod(Name = "TextCore::FontEngine::GetFaceInfo", IsThreadSafe = true, IsFreeFunction = true)] + static extern int GetFaceInfo_Internal(ref FaceInfo faceInfo); + + /// /// Get the index of the glyph for the character mapped at Unicode value. /// /// The Unicode value of the character for which to lookup the glyph index. /// Returns the index of the glyph used by the character using the Unicode value. Returns zero if no glyph exists for the given Unicode value. - [NativeMethod(Name = "TextCore::FontEngine::GetGlyphIndex", IsFreeFunction = true)] - public static extern int GetGlyphIndex(uint unicode); + [NativeMethod(Name = "TextCore::FontEngine::GetGlyphIndex", IsThreadSafe = true, IsFreeFunction = true)] + internal static extern uint GetGlyphIndex(uint unicode); + + + /// + /// Try to get the glyph index for the character at the given Unicode value. + /// + /// The unicode value of the character for which to lookup the glyph index. + /// The index of the glyph for the given unicode character or the .notdef glyph (index 0) if no glyph is available for the given Unicode value. + /// Returns true if the given unicode has a glyph index. + [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphIndex", IsThreadSafe = true, IsFreeFunction = true)] + public static extern bool TryGetGlyphIndex(uint unicode, out uint glyphIndex); /// @@ -236,7 +363,7 @@ internal static FontEngineError LoadGlyph(uint unicode, GlyphLoadFlags flags) return (FontEngineError)LoadGlyph_Internal(unicode, flags); } - [NativeMethod(Name = "TextCore::FontEngine::LoadGlyph", IsFreeFunction = true)] + [NativeMethod(Name = "TextCore::FontEngine::LoadGlyph", IsThreadSafe = true, IsFreeFunction = true)] static extern int LoadGlyph_Internal(uint unicode, GlyphLoadFlags loadFlags); @@ -249,13 +376,23 @@ internal static FontEngineError LoadGlyph(uint unicode, GlyphLoadFlags flags) /// Returns true if a glyph exists for the given unicode value. Otherwise returns false. public static bool TryGetGlyphWithUnicodeValue(uint unicode, GlyphLoadFlags flags, out Glyph glyph) { - glyph = new Glyph(); + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(); + + if (TryGetGlyphWithUnicodeValue_Internal(unicode, flags, ref glyphStruct)) + { + glyph = new Glyph(glyphStruct); + + return true; + } + + // Set glyph to null if no glyph exists for the given unicode value. + glyph = null; - return TryGetGlyphWithUnicodeValue_Internal(unicode, flags, glyph); + return false; } - [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithUnicodeValue", IsFreeFunction = true)] - static extern bool TryGetGlyphWithUnicodeValue_Internal(uint unicode, GlyphLoadFlags loadFlags, [Out] Glyph glyph); + [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithUnicodeValue", IsThreadSafe = true, IsFreeFunction = true)] + static extern bool TryGetGlyphWithUnicodeValue_Internal(uint unicode, GlyphLoadFlags loadFlags, ref GlyphMarshallingStruct glyphStruct); /// @@ -267,46 +404,485 @@ public static bool TryGetGlyphWithUnicodeValue(uint unicode, GlyphLoadFlags flag /// Returns true if a glyph exists at the given index. Otherwise returns false. public static bool TryGetGlyphWithIndexValue(uint glyphIndex, GlyphLoadFlags flags, out Glyph glyph) { - glyph = new Glyph(); + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(); + + if (TryGetGlyphWithIndexValue_Internal(glyphIndex, flags, ref glyphStruct)) + { + glyph = new Glyph(glyphStruct); + + return true; + } + + // Set glyph to null if no glyph exists for the given unicode value. + glyph = null; + + return false; + } - return TryGetGlyphWithIndexValue_Internal(glyphIndex, flags, glyph); + [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithIndexValue", IsThreadSafe = true, IsFreeFunction = true)] + static extern bool TryGetGlyphWithIndexValue_Internal(uint glyphIndex, GlyphLoadFlags loadFlags, ref GlyphMarshallingStruct glyphStruct); + + + /// + /// Try to pack the given glyph into the given texture width and height. + /// + /// The glyph to try to pack. + /// The padding between this glyph and other glyphs. + /// The packing algorithm used to pack the glyphs. + /// The glyph rendering mode. + /// The width of the target atlas texture. + /// The height of the target atlas texture. + /// List of GlyphRects representing the available space in the atlas. + /// List of GlyphRects representing the occupied space in the atlas. + /// + internal static bool TryPackGlyphInAtlas(Glyph glyph, int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, List freeGlyphRects, List usedGlyphRects) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyph); + + int freeGlyphRectCount = freeGlyphRects.Count; + int usedGlyphRectCount = usedGlyphRects.Count; + int totalGlyphRects = freeGlyphRectCount + usedGlyphRectCount; + + // Make sure marshalling arrays allocations are appropriate. + if (s_FreeGlyphRects.Length < totalGlyphRects || s_UsedGlyphRects.Length < totalGlyphRects) + { + int newSize = Mathf.NextPowerOfTwo(totalGlyphRects + 1); + s_FreeGlyphRects = new GlyphRect[newSize]; + s_UsedGlyphRects = new GlyphRect[newSize]; + } + + // Copy glyph rect data to marshalling arrays. + int glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + s_FreeGlyphRects[i] = freeGlyphRects[i]; + + if (i < usedGlyphRectCount) + s_UsedGlyphRects[i] = usedGlyphRects[i]; + } + + if (TryPackGlyphInAtlas_Internal(ref glyphStruct, padding, packingMode, renderMode, width, height, s_FreeGlyphRects, ref freeGlyphRectCount, s_UsedGlyphRects, ref usedGlyphRectCount)) + { + // Copy new glyph position to source glyph. + glyph.glyphRect = glyphStruct.glyphRect; + + freeGlyphRects.Clear(); + usedGlyphRects.Clear(); + + // Copy marshalled glyph rect data + glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + freeGlyphRects.Add(s_FreeGlyphRects[i]); + + if (i < usedGlyphRectCount) + usedGlyphRects.Add(s_UsedGlyphRects[i]); + } + + return true; + } + + return false; } - [NativeMethod(Name = "TextCore::FontEngine::TryGetGlyphWithIndexValue", IsFreeFunction = true)] - static extern bool TryGetGlyphWithIndexValue_Internal(uint glyphIndex, GlyphLoadFlags loadFlags, [Out] Glyph glyph); + [NativeMethod(Name = "TextCore::FontEngine::TryPackGlyph", IsThreadSafe = true, IsFreeFunction = true)] + extern static bool TryPackGlyphInAtlas_Internal(ref GlyphMarshallingStruct glyph, int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, + [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount); /// - /// Try rasterizing and adding the given glyph to the provided texture. + /// Pack glyphs in the given atlas size. + /// + /// Glyphs to pack in atlas. + /// Glyphs packed in atlas. + /// The padding between glyphs. + /// The packing algorithm used to pack the glyphs. + /// The glyph rendering mode. + /// The width of the target atlas texture. + /// The height of the target atlas texture. + /// List of GlyphRects representing the available space in the atlas. + /// List of GlyphRects representing the occupied space in the atlas. + /// + internal static bool TryPackGlyphsInAtlas(List glyphsToAdd, List glyphsAdded, int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, List freeGlyphRects, List usedGlyphRects) + { + // Determine potential total allocations required for glyphs and glyph rectangles. + int glyphsToAddCount = glyphsToAdd.Count; + int glyphsAddedCount = glyphsAdded.Count; + int freeGlyphRectCount = freeGlyphRects.Count; + int usedGlyphRectCount = usedGlyphRects.Count; + int totalCount = glyphsToAddCount + glyphsAddedCount + freeGlyphRectCount + usedGlyphRectCount; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < totalCount || s_GlyphMarshallingStruct_OUT.Length < totalCount || s_FreeGlyphRects.Length < totalCount || s_UsedGlyphRects.Length < totalCount) + { + int newSize = Mathf.NextPowerOfTwo(totalCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + s_GlyphMarshallingStruct_OUT = new GlyphMarshallingStruct[newSize]; + s_FreeGlyphRects = new GlyphRect[newSize]; + s_UsedGlyphRects = new GlyphRect[newSize]; + } + + s_GlyphLookupDictionary.Clear(); + + // Copy glyph data into appropriate marshaling array. + for (int i = 0; i < totalCount; i++) + { + if (i < glyphsToAddCount) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyphsToAdd[i]); + + s_GlyphMarshallingStruct_IN[i] = glyphStruct; + + // Add reference to glyph in lookup dictionary + if (s_GlyphLookupDictionary.ContainsKey(glyphStruct.index) == false) + s_GlyphLookupDictionary.Add(glyphStruct.index, glyphsToAdd[i]); + } + + if (i < glyphsAddedCount) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyphsAdded[i]); + + s_GlyphMarshallingStruct_OUT[i] = glyphStruct; + + // Add reference to glyph in lookup dictionary + if (s_GlyphLookupDictionary.ContainsKey(glyphStruct.index) == false) + s_GlyphLookupDictionary.Add(glyphStruct.index, glyphsAdded[i]); + } + + if (i < freeGlyphRectCount) + s_FreeGlyphRects[i] = freeGlyphRects[i]; + + if (i < usedGlyphRectCount) + s_UsedGlyphRects[i] = usedGlyphRects[i]; + } + + bool allGlyphsIncluded = TryPackGlyphsInAtlas_Internal(s_GlyphMarshallingStruct_IN, ref glyphsToAddCount, s_GlyphMarshallingStruct_OUT, ref glyphsAddedCount, + padding, packingMode, renderMode, width, height, + s_FreeGlyphRects, ref freeGlyphRectCount, s_UsedGlyphRects, ref usedGlyphRectCount); + + // Clear lists and / or re-allocate arrays. + glyphsToAdd.Clear(); + glyphsAdded.Clear(); + freeGlyphRects.Clear(); + usedGlyphRects.Clear(); + + // Copy marshaled glyph data back into the appropriate lists. + for (int i = 0; i < totalCount; i++) + { + if (i < glyphsToAddCount) + { + GlyphMarshallingStruct glyphStruct = s_GlyphMarshallingStruct_IN[i]; + Glyph glyph = s_GlyphLookupDictionary[glyphStruct.index]; + + // Note: In theory, only new glyphRect x and y need to be copied. + glyph.metrics = glyphStruct.metrics; + glyph.glyphRect = glyphStruct.glyphRect; + glyph.scale = glyphStruct.scale; + glyph.atlasIndex = glyphStruct.atlasIndex; + + glyphsToAdd.Add(glyph); + } + + if (i < glyphsAddedCount) + { + GlyphMarshallingStruct glyphStruct = s_GlyphMarshallingStruct_OUT[i]; + Glyph glyph = s_GlyphLookupDictionary[glyphStruct.index]; + + glyph.metrics = glyphStruct.metrics; + glyph.glyphRect = glyphStruct.glyphRect; + glyph.scale = glyphStruct.scale; + glyph.atlasIndex = glyphStruct.atlasIndex; + + glyphsAdded.Add(glyph); + } + + if (i < freeGlyphRectCount) + { + freeGlyphRects.Add(s_FreeGlyphRects[i]); + } + + if (i < usedGlyphRectCount) + { + usedGlyphRects.Add(s_UsedGlyphRects[i]); + } + } + + return allGlyphsIncluded; + } + + [NativeMethod(Name = "TextCore::FontEngine::TryPackGlyphs", IsThreadSafe = true, IsFreeFunction = true)] + extern static bool TryPackGlyphsInAtlas_Internal([Out] GlyphMarshallingStruct[] glyphsToAdd, ref int glyphsToAddCount, [Out] GlyphMarshallingStruct[] glyphsAdded, ref int glyphsAddedCount, + int padding, GlyphPackingMode packingMode, GlyphRenderMode renderMode, int width, int height, + [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount); + + + /// + /// Render and add glyph to the provided texture. /// /// The Glyph that should be added into the provided texture. /// The padding value around the glyph. /// The Rendering Mode for the Glyph. /// The Texture to which the glyph should be added. /// Returns a value of zero if the glyph was successfully added to the texture. - public static FontEngineError AddGlyphToTexture(Glyph glyph, int padding, GlyphRenderModes renderMode, Texture2D texture) + internal static FontEngineError RenderGlyphToTexture(Glyph glyph, int padding, GlyphRenderMode renderMode, Texture2D texture) { - return (FontEngineError)AddGlyphToTexture_Internal(glyph, padding, renderMode, texture); + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyph); + + return (FontEngineError)RenderGlyphToTexture_Internal(glyphStruct, padding, renderMode, texture); } - [NativeMethod(Name = "TextCore::FontEngine::AddGlyphToTexture", IsFreeFunction = true)] - extern static int AddGlyphToTexture_Internal(Glyph glyph, int padding, GlyphRenderModes renderMode, Texture2D texture); + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphToTexture", IsFreeFunction = true)] + extern static int RenderGlyphToTexture_Internal(GlyphMarshallingStruct glyphStruct, int padding, GlyphRenderMode renderMode, Texture2D texture); /// - /// Try rasterizing and adding the given list of glyphs to the provided texture. + /// Render and add the glyphs in the provided list to the texture. /// - /// The list of glyphs to be added into the provided texture. + /// The list of glyphs to be rendered and added to the provided texture. /// The padding value around the glyphs. - /// The rendering mode used rasterize the glyphs. + /// The rendering mode used to rasterize the glyphs. /// Returns a value of zero if the glyphs were successfully added to the texture. /// - public static FontEngineError AddGlyphsToTexture(Glyph[] glyphs, int padding, GlyphRenderModes renderMode, Texture2D texture) + internal static FontEngineError RenderGlyphsToTexture(List glyphs, int padding, GlyphRenderMode renderMode, Texture2D texture) { - return (FontEngineError)AddGlyphsToTextureFromArray_Internal(glyphs, padding, renderMode, texture); + int glyphCount = glyphs.Count; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < glyphCount) + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + } + + // Copy data to marshalling buffers + for (int i = 0; i < glyphCount; i++) + s_GlyphMarshallingStruct_IN[i] = new GlyphMarshallingStruct(glyphs[i]); + + // Call extern function to render and add glyphs to texture. + int error = RenderGlyphsToTexture_Internal(s_GlyphMarshallingStruct_IN, glyphCount, padding, renderMode, texture); + + return (FontEngineError)error; } - [NativeMethod(Name = "TextCore::FontEngine::AddGlyphsToTexture", IsFreeFunction = true)] - extern static int AddGlyphsToTextureFromArray_Internal(Glyph[] glyphs, int padding, GlyphRenderModes renderMode, Texture2D texture); + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphsToTexture", IsFreeFunction = true)] + extern static int RenderGlyphsToTexture_Internal(GlyphMarshallingStruct[] glyphs, int glyphCount, int padding, GlyphRenderMode renderMode, Texture2D texture); + + + internal static FontEngineError RenderGlyphsToTexture(List glyphs, int padding, GlyphRenderMode renderMode, byte[] texBuffer, int texWidth, int texHeight) + { + int glyphCount = glyphs.Count; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < glyphCount) + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + } + + // Copy data to marshalling buffers + for (int i = 0; i < glyphCount; i++) + s_GlyphMarshallingStruct_IN[i] = new GlyphMarshallingStruct(glyphs[i]); + + int error = RenderGlyphsToTextureBuffer_Internal(s_GlyphMarshallingStruct_IN, glyphCount, padding, renderMode, texBuffer, texWidth, texHeight); + + return (FontEngineError)error; + } + + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphsToTextureBuffer", IsThreadSafe = true, IsFreeFunction = true)] + extern static int RenderGlyphsToTextureBuffer_Internal(GlyphMarshallingStruct[] glyphs, int glyphCount, int padding, GlyphRenderMode renderMode, [Out] byte[] texBuffer, int texWidth, int texHeight); + + + /// + /// Internal function used to render and add glyphs to the cached shared texture data from outside the main thread. + /// It is necessary to use SetSharedTextureData(texture) prior to calling this function. + /// + /// The list of glyphs to be added into the provided texture. + /// The padding value around the glyphs. + /// The rendering mode used to rasterize the glyphs. + /// + internal static FontEngineError RenderGlyphsToSharedTexture(List glyphs, int padding, GlyphRenderMode renderMode) + { + int glyphCount = glyphs.Count; + + // Make sure marshaling arrays allocations are appropriate. + if (s_GlyphMarshallingStruct_IN.Length < glyphCount) + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[newSize]; + } + + // Copy data to marshalling buffers + for (int i = 0; i < glyphCount; i++) + s_GlyphMarshallingStruct_IN[i] = new GlyphMarshallingStruct(glyphs[i]); + + int error = RenderGlyphsToSharedTexture_Internal(s_GlyphMarshallingStruct_IN, glyphCount, padding, renderMode); + + return (FontEngineError)error; + } + + [NativeMethod(Name = "TextCore::FontEngine::RenderGlyphsToSharedTexture", IsThreadSafe = true, IsFreeFunction = true)] + extern static int RenderGlyphsToSharedTexture_Internal(GlyphMarshallingStruct[] glyphs, int glyphCount, int padding, GlyphRenderMode renderMode); + + + /// + /// Internal function used to get a reference to the shared texture data which is required for accessing the texture data outside of the main thread. + /// + [NativeMethod(Name = "TextCore::FontEngine::SetSharedTextureData", IsFreeFunction = true)] + internal extern static void SetSharedTexture(Texture2D texture); + + + /// + /// Internal function used to release the shared texture data. + /// + [NativeMethod(Name = "TextCore::FontEngine::ReleaseSharedTextureData", IsThreadSafe = true, IsFreeFunction = true)] + internal extern static void ReleaseSharedTexture(); + + + internal static bool TryAddGlyphToTexture(uint glyphIndex, int padding, GlyphPackingMode packingMode, List freeGlyphRects, List usedGlyphRects, GlyphRenderMode renderMode, Texture2D texture, out Glyph glyph) + { + // Determine potential total allocations required for glyphs and glyph rectangles. + int freeGlyphRectCount = freeGlyphRects.Count; + int usedGlyphRectCount = usedGlyphRects.Count; + int totalGlyphRects = freeGlyphRectCount + usedGlyphRectCount; + + // Make sure marshalling arrays allocations are appropriate. + if (s_FreeGlyphRects.Length < totalGlyphRects || s_UsedGlyphRects.Length < totalGlyphRects) + { + int newSize = Mathf.NextPowerOfTwo(totalGlyphRects + 1); + s_FreeGlyphRects = new GlyphRect[newSize]; + s_UsedGlyphRects = new GlyphRect[newSize]; + } + + // Copy glyph rect data to marshalling arrays. + int glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + s_FreeGlyphRects[i] = freeGlyphRects[i]; + + if (i < usedGlyphRectCount) + s_UsedGlyphRects[i] = usedGlyphRects[i]; + } + + GlyphMarshallingStruct glyphStruct; + + // Marshall data over to the native side. + if (TryAddGlyphToTexture_Internal(glyphIndex, padding, packingMode, s_FreeGlyphRects, ref freeGlyphRectCount, s_UsedGlyphRects, ref usedGlyphRectCount, renderMode, texture, out glyphStruct)) + { + // Copy marshalled data over to new glyph. + glyph = new Glyph(glyphStruct); + + freeGlyphRects.Clear(); + usedGlyphRects.Clear(); + + // Copy marshalled free and used GlyphRect data over. + glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < freeGlyphRectCount) + freeGlyphRects.Add(s_FreeGlyphRects[i]); + + if (i < usedGlyphRectCount) + usedGlyphRects.Add(s_UsedGlyphRects[i]); + } + + return true; + } + + glyph = null; + + return false; + } + + [NativeMethod(Name = "TextCore::FontEngine::TryAddGlyphToTexture", IsThreadSafe = true, IsFreeFunction = true)] + extern static bool TryAddGlyphToTexture_Internal(uint glyphIndex, int padding, + GlyphPackingMode packingMode, [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount, + GlyphRenderMode renderMode, Texture2D texture, out GlyphMarshallingStruct glyph); + + + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::GetGlyphPairAdjustmentTable", IsFreeFunction = true)] + internal extern static void GetGlyphPairAdjustmentTable(); + + // ================================================ + // Experimental / Testing / Benchmarking Functions + // ================================================ + + /// + /// Internal function used for testing rasterizing of shapes and glyphs. + /// + /// Texture containing the source shape to raster. + /// Padding value. + /// The rendering mode. + /// Texture containing the rastered shape. + [NativeMethod(Name = "TextCore::FontEngine::RenderToTexture", IsFreeFunction = true)] + internal extern static void RenderBufferToTexture(Texture2D srcTexture, int padding, GlyphRenderMode renderMode, Texture2D dstTexture); + + /* + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyph", IsFreeFunction = true)] + extern public static void ModifyGlyph([Out] Glyph glyph); + + /// + /// + /// + /// + public static void ModifyGlyphStruct(Glyph glyph) + { + GlyphMarshallingStruct glyphStruct = new GlyphMarshallingStruct(glyph); + + ModifyGlyph_Internal(ref glyphStruct); + + glyph.metrics = glyphStruct.metrics; + glyph.glyphRect = glyphStruct.glyphRect; + glyph.scale = glyphStruct.scale; + glyph.atlasIndex = glyphStruct.atlasIndex; + } + + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyph", IsThreadSafe = true, IsFreeFunction = true)] + extern static void ModifyGlyph_Internal(ref GlyphMarshallingStruct glyphs); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphMarshallingStruct", IsFreeFunction = true)] + extern public static void ModifyGlyphMarshallingStruct(GlyphMarshallingStruct[] glyph); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphMarshallingStruct", IsFreeFunction = true)] + extern public static void ModifyGlyphMarshallingStructArray(GlyphMarshallingStruct[] glyph); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphs", IsFreeFunction = true)] + extern public static void ModifyGlyphStructArray([Out] GlyphMarshallingStruct[] glyph); + + /// + /// + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ModifyGlyphs", IsFreeFunction = true)] + extern public static void ModifyGlyphArray([Out] Glyph[] glyph); + + [NativeMethod(Name = "TextCore::FontEngine::AccessFont", IsFreeFunction = true)] + extern public static void AccessFont(Font font); + */ + } + + internal struct FontEngineUtilities + { + internal static bool Approximately(float a, float b) + { + return Mathf.Abs(a - b) < 0.001f; + } } } diff --git a/Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs b/Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs new file mode 100644 index 0000000000..f293121789 --- /dev/null +++ b/Modules/TextCore/ScriptBindings/GlyphMarshallingStruct.cs @@ -0,0 +1,74 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using UnityEngine.Scripting; + + +namespace UnityEngine.TextCore.LowLevel +{ + /// + /// Structure used for marshalling glyphs between managed and native code. + /// + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphMarshallingStruct + { + /// + /// The index of the glyph in the source font file. + /// + public uint index; + + /// + /// Metrics defining the size, positioning and spacing of a glyph when doing text layout. + /// + public GlyphMetrics metrics; + + /// + /// A rectangle that defines the position of a glyph within an atlas texture. + /// + public GlyphRect glyphRect; + + /// + /// The relative scale of the text element. The default value is 1.0. + /// + public float scale; + + /// + /// The index of the atlas texture that contains this glyph. + /// + public int atlasIndex; + + /// + /// Constructor for a new glyph + /// + /// Glyph whose values are copied to the new glyph. + public GlyphMarshallingStruct(Glyph glyph) + { + this.index = glyph.index; + this.metrics = glyph.metrics; + this.glyphRect = glyph.glyphRect; + this.scale = glyph.scale; + this.atlasIndex = glyph.atlasIndex; + } + + /// + /// Constructor for new glyph + /// + /// The index of the glyph in the font file. + /// The metrics of the glyph. + /// A rectangle defining the position of the glyph in the atlas texture. + /// The relative scale of the glyph. + /// The index of the atlas texture that contains the glyph. + public GlyphMarshallingStruct(uint index, GlyphMetrics metrics, GlyphRect glyphRect, float scale, int atlasIndex) + { + this.index = index; + this.metrics = metrics; + this.glyphRect = glyphRect; + this.scale = scale; + this.atlasIndex = atlasIndex; + } + } +} diff --git a/Modules/TextRendering/TextRendering.bindings.cs b/Modules/TextRendering/TextRendering.bindings.cs index 63d1ff0d0b..d2d1875ef8 100644 --- a/Modules/TextRendering/TextRendering.bindings.cs +++ b/Modules/TextRendering/TextRendering.bindings.cs @@ -365,7 +365,14 @@ public static int GetMaxVertsForString(string str) } internal static extern Font GetDefault(); - public extern bool HasCharacter(char c); + + public bool HasCharacter(char c) + { + return HasCharacter((int)c); + } + + private extern bool HasCharacter(int c); + public static extern string[] GetOSInstalledFontNames(); private static extern void Internal_CreateFont([Writable] Font self, string name); diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs index 4cf48e9b5b..17081082fc 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs @@ -1244,7 +1244,18 @@ private static void OnPostprocessAllAssets(string[] importedAssets, string[] del public class PaletteAssetModificationProcessor : AssetModificationProcessor { + static void OnWillCreateAsset(string assetName) + { + SavePalettesIfRequired(); + } + static string[] OnWillSaveAssets(string[] paths) + { + SavePalettesIfRequired(); + return paths; + } + + static void SavePalettesIfRequired() { if (!GridPaintingState.savingPalette) { @@ -1257,7 +1268,6 @@ static string[] OnWillSaveAssets(string[] paths) } } } - return paths; } } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs index 952df16b08..6509d90f1d 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs @@ -104,6 +104,9 @@ internal void OnGUI() { if (GUILayout.Button(Styles.ok)) { + // case 1077362: Close window to prevent overlap with OS folder window when saving new palette asset + Close(); + var swizzle = Grid.CellSwizzle.XYZ; if (m_Layout == GridLayout.CellLayout.Hexagon) swizzle = Styles.hexagonSwizzleTypeValue[m_HexagonLayout]; @@ -114,6 +117,7 @@ internal void OnGUI() m_Owner.palette = go; m_Owner.Repaint(); } + GUIUtility.ExitGUI(); } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs index 4003031a24..72dfeac3c6 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs @@ -103,12 +103,20 @@ public virtual void OnGUI() } } - protected void UpdateMouseGridPosition() + protected void ResetPreviousMousePositionToCurrentPosition() { - if (Event.current.type == EventType.MouseDrag || Event.current.type == EventType.MouseMove || Event.current.type == EventType.DragUpdated) - { - m_MouseGridPositionChanged = false; + m_PreviousMouseGridPosition = m_MouseGridPosition; + } + protected void UpdateMouseGridPosition(bool forceUpdate = false) + { + if (Event.current.type == EventType.MouseDrag + || Event.current.type == EventType.MouseMove + // Case 1075857: Mouse Down when window is not in focus needs to update mouse grid position + || Event.current.type == EventType.MouseDown + || Event.current.type == EventType.DragUpdated + || forceUpdate) + { Vector2Int newGridPosition = ScreenToGrid(Event.current.mousePosition); if (newGridPosition != m_MouseGridPosition) { @@ -118,10 +126,14 @@ protected void UpdateMouseGridPosition() newGridPosition.x = m_MouseGridPosition.x + Math.Sign(delta.x) * k_MaxMouseCellDelta; if (Mathf.Abs(delta.y) > k_MaxMouseCellDelta) newGridPosition.y = m_MouseGridPosition.y + Math.Sign(delta.y) * k_MaxMouseCellDelta; - m_PreviousMouseGridPosition = m_MouseGridPosition; + ResetPreviousMousePositionToCurrentPosition(); m_MouseGridPosition = newGridPosition; MouseGridPositionChanged(); } + else if (!forceUpdate) + { + m_MouseGridPositionChanged = false; + } } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs index 4e5f28982b..a538cc4e38 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs @@ -18,6 +18,7 @@ internal class PaintableSceneViewGrid : PaintableGrid private Grid grid { get { return brushTarget != null ? brushTarget.GetComponentInParent() : (Selection.activeGameObject != null ? Selection.activeGameObject.GetComponentInParent() : null); } } private GridBrushBase gridBrush { get { return GridPaintingState.gridBrush; } } private SceneView activeSceneView = null; + private int sceneViewTransformHash; GameObject brushTarget { @@ -64,7 +65,12 @@ private Rect GetSceneViewPositionRect(SceneView sceneView) public void OnSceneGUI(SceneView sceneView) { - UpdateMouseGridPosition(); + HandleMouseEnterLeave(sceneView); + + // Case 1077400: SceneView camera transform changes may update the mouse grid position even though the mouse position has not changed + var currentSceneViewTransformHash = sceneView.camera.transform.localToWorldMatrix.GetHashCode(); + UpdateMouseGridPosition(currentSceneViewTransformHash == sceneViewTransformHash); + sceneViewTransformHash = currentSceneViewTransformHash; var dot = 1.0f; var gridView = GetGridView(); @@ -88,7 +94,6 @@ public void OnSceneGUI(SceneView sceneView) EditorGUIUtility.AddCursorRect(GetSceneViewPositionRect(sceneView), MouseCursor.CustomCursor); } } - HandleMouseEnterLeave(sceneView); } private void HandleMouseEnterLeave(SceneView sceneView) @@ -132,6 +137,7 @@ private void OnMouseEnter(SceneView sceneView) GridPaintingState.activeBrushEditor.OnMouseEnter(); GridPaintingState.activeGrid = this; activeSceneView = sceneView; + ResetPreviousMousePositionToCurrentPosition(); } private void OnMouseLeave(SceneView sceneView) diff --git a/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs b/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs index 998ba30d89..c1dc69eb80 100644 --- a/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs +++ b/Modules/VFX/Public/ScriptBindings/VFXEnums.bindings.cs @@ -63,7 +63,7 @@ internal enum VFXExpressionOperation // matrix operations TRSToMatrix, - InverseTRS, + InverseMatrix, ExtractPositionFromMatrix, ExtractAnglesFromMatrix, ExtractScaleFromMatrix, @@ -123,7 +123,10 @@ internal enum VFXExpressionOperation // Logical operations LogicalAnd, LogicalOr, - LogicalNot + LogicalNot, + + // This allows backward compatibility + InverseTRS = InverseMatrix, } internal enum VFXValueType diff --git a/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs b/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs index 2d107d7a9c..2401ade069 100644 --- a/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs +++ b/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs @@ -43,9 +43,29 @@ public VFXEventAttribute CreateVFXEventAttribute() return vfxEventAttribute; } - extern public void Play(VFXEventAttribute eventAttribute = null); - extern public void Stop(VFXEventAttribute eventAttribute = null); - extern public void SendEvent(string eventName, VFXEventAttribute eventAttribute = null); + extern public void Play(VFXEventAttribute eventAttribute); + + public void Play() + { + Play(null); + } + + extern public void Stop(VFXEventAttribute eventAttribute); + public void Stop() + { + Stop(null); + } + + extern public void SendEvent(int eventNameID, VFXEventAttribute eventAttribute); + public void SendEvent(string eventName) + { + SendEvent(Shader.PropertyToID(eventName), null); + } + + public void SendEvent(string eventName, VFXEventAttribute eventAttribute) + { + SendEvent(Shader.PropertyToID(eventName), null); + } extern public void Reinit(); extern public void AdvanceOneFrame(); diff --git a/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs b/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs index a5d4a5cf31..4773276ced 100644 --- a/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs +++ b/Modules/VFXEditor/Public/ScriptBindings/VFXMemorySerializer.bindings.cs @@ -19,8 +19,23 @@ internal static class VFXMemorySerializer { extern public static string StoreObjects(ScriptableObject[] objects); - [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_ExtractObjects")] - extern public static ScriptableObject[] ExtractObjects(string data, bool asACopy); + extern public static byte[] StoreObjectsToByteArray(ScriptableObject[] objects, CompressionLevel compressionLevel = CompressionLevel.None); + + [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_ExtractObjects_FromString")] + extern private static ScriptableObject[] ExtractObjects_FromString(string data, bool asACopy); + + [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_ExtractObjects_FromByteArray")] + extern private static ScriptableObject[] ExtractObjects_FromByteArray(byte[] data, bool asACopy); + + public static ScriptableObject[] ExtractObjects(string data, bool asACopy) + { + return ExtractObjects_FromString(data, asACopy); + } + + public static ScriptableObject[] ExtractObjects(byte[] data, bool asACopy) + { + return ExtractObjects_FromByteArray(data, asACopy); + } [FreeFunction(Name = "VFXMemorySerializerBindings::Internal_DuplicateObjects")] extern public static ScriptableObject[] DuplicateObjects(ScriptableObject[] objects); diff --git a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs index 8b16ca9b96..10b9a80910 100644 --- a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs +++ b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs @@ -35,6 +35,7 @@ internal struct VFXRendererSettings public bool receiveShadows; public ReflectionProbeUsage reflectionProbeUsage; public LightProbeUsage lightProbeUsage; + public int transparencyPriority; } [UsedByNativeCode] diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index baadafe1cf..9eb5fc83be 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1506,12 +1506,18 @@ Modules\TextCore\Managed\AssemblyInfo.cs + + Modules\TextCore\Managed\FaceInfo.cs + Modules\TextCore\Managed\Glyph.cs Modules\TextCore\ScriptBindings\FontEngine.bindings.cs + + Modules\TextCore\ScriptBindings\GlyphMarshallingStruct.cs + Modules\TextRendering\FontStyle.cs diff --git a/README.md b/README.md index c330049458..8700f0282d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b3 C# reference source code +## Unity 2018.3.0b5 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Camera.bindings.cs b/Runtime/Export/Camera.bindings.cs index c27dd8219c..9620d45454 100644 --- a/Runtime/Export/Camera.bindings.cs +++ b/Runtime/Export/Camera.bindings.cs @@ -232,6 +232,9 @@ public static Camera[] allCameras } public static int GetAllCameras(Camera[] cameras) { + if (cameras == null) + throw new NullReferenceException(); + if (cameras.Length < allCamerasCount) throw new ArgumentException("Passed in array to fill with cameras is to small to hold the number of cameras. Use Camera.allCamerasCount to get the needed size."); return GetAllCamerasImpl(cameras); diff --git a/Runtime/Export/GraphicsManagers.bindings.cs b/Runtime/Export/GraphicsManagers.bindings.cs index d5315d7c90..0e85526478 100644 --- a/Runtime/Export/GraphicsManagers.bindings.cs +++ b/Runtime/Export/GraphicsManagers.bindings.cs @@ -84,6 +84,8 @@ private QualitySettings() {} extern public static int antiAliasing { get; set; } extern public static int asyncUploadTimeSlice { get; set; } extern public static int asyncUploadBufferSize { get; set; } + extern public static bool asyncUploadPersistentBuffer { get; set; } + extern public static bool realtimeReflectionProbes { get; set; } extern public static bool billboardsFaceCameraPosition { get; set; } diff --git a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs index 591e257949..532b49ce9f 100644 --- a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs +++ b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs @@ -21,30 +21,30 @@ public partial class ParticleSystem : Component // Properties extern public bool isPlaying { - [NativeName("SyncJobs()->IsPlaying")] get; + [NativeName("SyncJobs(false)->IsPlaying")] get; } extern public bool isEmitting { - [NativeName("SyncJobs()->IsEmitting")] get; + [NativeName("SyncJobs(false)->IsEmitting")] get; } extern public bool isStopped { - [NativeName("SyncJobs()->IsStopped")] get; + [NativeName("SyncJobs(false)->IsStopped")] get; } extern public bool isPaused { - [NativeName("SyncJobs()->IsPaused")] get; + [NativeName("SyncJobs(false)->IsPaused")] get; } extern public int particleCount { - [NativeName("SyncJobs()->GetParticleCount")] get; + [NativeName("SyncJobs(false)->GetParticleCount")] get; } extern public float time { - [NativeName("SyncJobs()->GetSecPosition")] + [NativeName("SyncJobs(false)->GetSecPosition")] get; - [NativeName("SyncJobs()->SetSecPosition")] + [NativeName("SyncJobs(false)->SetSecPosition")] set; } @@ -52,7 +52,7 @@ extern public UInt32 randomSeed { [NativeName("GetRandomSeed")] get; - [NativeName("SyncJobs()->SetRandomSeed")] + [NativeName("SyncJobs(false)->SetRandomSeed")] set; } @@ -60,7 +60,7 @@ extern public bool useAutoRandomSeed { [NativeName("GetAutoRandomSeed")] get; - [NativeName("SyncJobs()->SetAutoRandomSeed")] + [NativeName("SyncJobs(false)->SetAutoRandomSeed")] set; } diff --git a/Runtime/Transform/ScriptBindings/Transform.bindings.cs b/Runtime/Transform/ScriptBindings/Transform.bindings.cs index 79877fee02..3e3e121490 100644 --- a/Runtime/Transform/ScriptBindings/Transform.bindings.cs +++ b/Runtime/Transform/ScriptBindings/Transform.bindings.cs @@ -382,7 +382,10 @@ public int hierarchyCapacity [FreeFunction("SetHierarchyCapacity", HasExplicitThis = true)] private extern void internal_setHierarchyCapacity(int value); - public int hierarchyCount { get; } + public int hierarchyCount { get { return internal_getHierarchyCount(); } } + + [FreeFunction("GetHierarchyCount", HasExplicitThis = true)] + private extern int internal_getHierarchyCount(); [NativeConditional("UNITY_EDITOR")] [FreeFunction("IsNonUniformScaleTransform", HasExplicitThis = true)] diff --git a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs index dfa7f7c180..8e66c9141b 100644 --- a/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/ParticleSystem/ParticleSystemBindings.gen.cs @@ -2971,6 +2971,8 @@ public partial struct TrailModule public bool generateLightingData { set { SetGenerateLightingData(m_ParticleSystem, value); } get { return GetGenerateLightingData(m_ParticleSystem); } } public int ribbonCount { get { return GetRibbonCount(m_ParticleSystem); } set { SetRibbonCount(m_ParticleSystem, value); } } public float shadowBias { set { SetShadowBias(m_ParticleSystem, value); } get { return GetShadowBias(m_ParticleSystem); } } + public bool splitSubEmitterRibbons { set { SetSplitSubEmitterRibbons(m_ParticleSystem, value); } get { return GetSplitSubEmitterRibbons(m_ParticleSystem); } } + public bool attachRibbonsToTransform { set { SetAttachRibbonsToTransform(m_ParticleSystem, value); } get { return GetAttachRibbonsToTransform(m_ParticleSystem); } } [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration @@ -3125,6 +3127,22 @@ public partial struct TrailModule [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern private static float GetShadowBias (ParticleSystem system) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static void SetSplitSubEmitterRibbons (ParticleSystem system, bool value) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static bool GetSplitSubEmitterRibbons (ParticleSystem system) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static void SetAttachRibbonsToTransform (ParticleSystem system, bool value) ; + + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern private static bool GetAttachRibbonsToTransform (ParticleSystem system) ; + } [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Sequential)] From 42361760bb0461e70c6b3a4e9b794e8abe7cf334 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Thu, 18 Oct 2018 07:28:58 +0000 Subject: [PATCH 04/10] Unity 2018.3.0b6 C# reference source code --- Editor/Mono/Animation/ZoomableArea.cs | 15 + Editor/Mono/Collab/Collab.cs | 11 +- Editor/Mono/ConsoleWindow.cs | 10 +- Editor/Mono/ContainerWindow.cs | 3 +- Editor/Mono/GameView/GameView.cs | 3 + Editor/Mono/Inspector/InspectorWindow.cs | 19 +- .../PlayerSettingsEditor.cs | 188 ++--- Editor/Mono/PlayerSettingsAndroid.bindings.cs | 8 - .../StageManager/StageNavigationManager.cs | 8 +- Editor/Mono/SceneView/SceneView.cs | 47 +- .../Mono/Scripting/Compilers/BooCompiler.cs | 17 +- .../Scripting/Compilers/CSharpLanguage.cs | 59 +- .../Compilers/MicrosoftCSharpCompiler.cs | 40 +- .../Scripting/Compilers/MonoCSharpCompiler.cs | 53 +- .../Compilers/MonoScriptCompilerBase.cs | 4 +- .../Scripting/Compilers/ScriptCompilerBase.cs | 138 +++- .../Compilers/UnityScriptCompiler.cs | 27 +- .../ScriptCompilation/EditorBuildRules.cs | 11 + .../ScriptCompilation/EditorCompilation.cs | 24 +- .../EditorCompilationInterface.cs | 10 +- .../ScriptCompilation/MonoLibraryHelpers.cs | 58 +- .../Providers/AssetSettingsProvider.cs | 6 + Editor/Mono/Settings/SettingsProvider.cs | 6 + Editor/Mono/Settings/SettingsWindow.cs | 16 +- Editor/Mono/Utils/DirectoryExtensions.cs | 2 +- .../SolutionSynchronizer.cs | 69 +- Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs | 102 ++- Modules/ShortcutManagerEditor/Trigger.cs | 1 + Modules/Terrain/Public/BrushTransform.cs | 80 ++ Modules/Terrain/Public/PaintContext.cs | 632 ++++++++++++++++ Modules/Terrain/Public/TerrainPaintUtility.cs | 688 +++--------------- Modules/TerrainEditor/Brush/Brush.cs | 2 +- Modules/TerrainEditor/Brush/BrushList.cs | 5 + .../PaintTools/PaintHeightTool.cs | 55 +- .../PaintTools/PaintTextureTool.cs | 22 +- .../TerrainEditor/PaintTools/SetHeightTool.cs | 56 +- .../PaintTools/SmoothHeightTool.cs | 39 +- Modules/TerrainEditor/PaintTools/StampTool.cs | 69 +- .../PaintTools/TerrainPaintTool.cs | 36 +- Modules/TerrainEditor/TerrainInspector.cs | 136 +++- .../Utilities/TerrainPaintUtilityEditor.cs | 193 +++-- Modules/UIElements/VisualElement.cs | 22 +- Projects/CSharp/UnityEngine.csproj | 6 + README.md | 2 +- .../AR/Tango/ScriptBindings/Tango.bindings.cs | 64 +- 45 files changed, 1892 insertions(+), 1170 deletions(-) create mode 100644 Modules/Terrain/Public/BrushTransform.cs create mode 100644 Modules/Terrain/Public/PaintContext.cs diff --git a/Editor/Mono/Animation/ZoomableArea.cs b/Editor/Mono/Animation/ZoomableArea.cs index 2bc23ff956..8ab4fd6020 100644 --- a/Editor/Mono/Animation/ZoomableArea.cs +++ b/Editor/Mono/Animation/ZoomableArea.cs @@ -992,5 +992,20 @@ public float PixelDeltaToTime(Rect rect) { return shownArea.width / rect.width; } + + public void UpdateZoomScale(float fMaxScaleValue, float fMinScaleValue) + { + // Update/reset the values of the scale to new zoom range, if the current values do not fall in the range of the new resolution + + if (m_Scale.y > fMaxScaleValue || m_Scale.y < fMinScaleValue) + { + m_Scale.y = m_Scale.y > fMaxScaleValue ? fMaxScaleValue : fMinScaleValue; + } + + if (m_Scale.x > fMaxScaleValue || m_Scale.x < fMinScaleValue) + { + m_Scale.x = m_Scale.x > fMaxScaleValue ? fMaxScaleValue : fMinScaleValue; + } + } } } // namespace diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs index 80ec1bd2c5..5a3a96c851 100644 --- a/Editor/Mono/Collab/Collab.cs +++ b/Editor/Mono/Collab/Collab.cs @@ -364,11 +364,16 @@ public bool SetConflictsResolvedTheirs(string[] paths) public PublishInfo GetChangesToPublish() { - Change[] changes = GetSelectedChangesInternal(); + Change[] changes = GetChangesToPublishInternal(); bool isFiltered = false; - if (Toolbar.isLastShowRequestPartial) + + if (SupportsAsyncChanges()) { - isFiltered = true; + changes = GetSelectedChangesInternal(); + if (Toolbar.isLastShowRequestPartial) + { + isFiltered = true; + } } return new PublishInfo() diff --git a/Editor/Mono/ConsoleWindow.cs b/Editor/Mono/ConsoleWindow.cs index 12d7ac5db0..4cb9501d5d 100644 --- a/Editor/Mono/ConsoleWindow.cs +++ b/Editor/Mono/ConsoleWindow.cs @@ -627,6 +627,7 @@ void OnGUI() EditorGUIUtility.SetIconSize(new Vector2(rowHeight, rowHeight)); GUIContent tempContent = new GUIContent(); int id = GUIUtility.GetControlID(0); + int rowDoubleClicked = -1; /////@TODO: Make Frame selected work with ListViewState using (new GettingLogEntriesScope(m_ListView)) @@ -712,11 +713,16 @@ void OnGUI() if (openSelectedItem) { - LogEntries.RowGotDoubleClicked(selectedRow); - Event.current.Use(); + rowDoubleClicked = selectedRow; + e.Use(); } } + // Prevent dead locking in EditorMonoConsole by delaying callbacks (which can log to the console) until after LogEntries.EndGettingEntries() has been + // called (this releases the mutex in EditorMonoConsole so logging again is allowed). Fix for case 1081060. + if (rowDoubleClicked != -1) + LogEntries.RowGotDoubleClicked(rowDoubleClicked); + EditorGUIUtility.SetIconSize(Vector2.zero); // Display active text (We want word wrapped text with a vertical scrollbar) diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index 638f8c1b8a..c1a379d446 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -82,7 +82,8 @@ internal void ShowPopupWithMode(ShowMode mode) m_RootView.SetWindowRecurse(this); Internal_SetTitle(m_Title); Save(); - Internal_BringLiveAfterCreation(false, false); + // only set focus iff mode is a popupMenu. + Internal_BringLiveAfterCreation(false, mode == ShowMode.PopupMenu); } static Color skinBackgroundColor diff --git a/Editor/Mono/GameView/GameView.cs b/Editor/Mono/GameView/GameView.cs index 628b539d89..8f0c17b335 100644 --- a/Editor/Mono/GameView/GameView.cs +++ b/Editor/Mono/GameView/GameView.cs @@ -385,6 +385,9 @@ private void UpdateZoomAreaAndParent() CopyDimensionsToParentView(); m_LastWindowPixelSize = position.size * EditorGUIUtility.pixelsPerPoint; EditorApplication.SetSceneRepaintDirty(); + + // update the scale according to new resolution + m_ZoomArea.UpdateZoomScale(maxScale, minScale); } void AllowCursorLockAndHide(bool enable) diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 1464161d4b..ba33875f25 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -511,7 +511,8 @@ protected virtual void OnGUI() if (tracker.activeEditors.Length > 0) { - DrawVCSShortInfo(); + Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors); + DrawVCSShortInfo(this, assetEditor); } } @@ -904,14 +905,13 @@ private void DetachPreview() GUIUtility.ExitGUI(); } - protected virtual void DrawVCSSticky(float offset) + private static void DrawVCSSticky(EditorWindow hostWindow, Editor assetEditor, float offset) { string message = ""; - Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors); bool hasRemovedSticky = EditorPrefs.GetBool("vcssticky"); if (!hasRemovedSticky && !Editor.IsAppropriateFileOpenForEdit(assetEditor.target, out message)) { - var rect = new Rect(10, position.height - 94, position.width - 20, 80); + var rect = new Rect(10, hostWindow.position.height - 94, hostWindow.position.width - 20, 80); rect.y -= offset; if (Event.current.type == EventType.Repaint) { @@ -932,14 +932,13 @@ protected virtual void DrawVCSSticky(float offset) } } - private void DrawVCSShortInfo() + internal static void DrawVCSShortInfo(EditorWindow hostWindow, Editor assetEditor) { if (Provider.enabled && EditorSettings.externalVersionControl != ExternalVersionControl.Disabled && EditorSettings.externalVersionControl != ExternalVersionControl.AutoDetect && EditorSettings.externalVersionControl != ExternalVersionControl.Generic) { - Editor assetEditor = InspectorWindowUtils.GetFirstNonImportInspectorEditor(tracker.activeEditors); string assetPath = AssetDatabase.GetAssetPath(assetEditor.target); Asset asset = Provider.GetAssetByPath(assetPath); if (asset == null || !(asset.path.StartsWith("Assets") || asset.path.StartsWith("ProjectSettings"))) @@ -1005,15 +1004,15 @@ private void DrawVCSShortInfo() // TODO: Retrieve default CheckoutMode from VC settings (depends on asset type; native vs. imported) Task task = Provider.Checkout(assetEditor.targets, CheckoutMode.Both); task.Wait(); - Repaint(); + hostWindow.Repaint(); } } - DrawVCSSticky(rect.height / 2); + DrawVCSSticky(hostWindow, assetEditor, rect.height / 2); } } } - protected string BuildTooltip(Asset asset, Asset metaAsset) + protected static string BuildTooltip(Asset asset, Asset metaAsset) { var sb = new StringBuilder(); if (asset != null) @@ -1029,7 +1028,7 @@ protected string BuildTooltip(Asset asset, Asset metaAsset) return sb.ToString(); } - protected void DrawVCSShortInfoAsset(Asset asset, string tooltip, Rect rect, Texture2D icon, string currentState) + protected static void DrawVCSShortInfoAsset(Asset asset, string tooltip, Rect rect, Texture2D icon, string currentState) { Rect overlayRect = new Rect(rect.x, rect.y, 28, 16); Rect iconRect = overlayRect; diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 6b8786ffff..370285f953 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -1137,6 +1137,14 @@ void OpenGLES31OptionsGUI(BuildTargetGroup targetGroup, BuildTarget targetPlatfo void GraphicsAPIsGUIOnePlatform(BuildTargetGroup targetGroup, BuildTarget targetPlatform, string platformTitle) { + // Facebook on windows must be always DX11 + // TODO: Remove this when Facebook platform support contract is over + if (targetGroup == BuildTargetGroup.Facebook && + (targetPlatform == BuildTarget.StandaloneWindows || targetPlatform == BuildTarget.StandaloneWindows64)) + { + return; + } + GraphicsDeviceType[] availableDevices = PlayerSettings.GetSupportedGraphicsAPIs(targetPlatform); // if no devices (e.g. no platform module), or we only have one possible choice, then no // point in having any UI @@ -1891,124 +1899,128 @@ private void OtherSectionConfigurationGUI(BuildTargetGroup targetGroup, ISetting // Configuration GUILayout.Label(SettingsContent.configurationTitle, EditorStyles.boldLabel); - // Scripting Runtime Version - var scriptingRuntimeVersions = new[] {ScriptingRuntimeVersion.Legacy, ScriptingRuntimeVersion.Latest}; - var scriptingRuntimeVersionNames = new[] {SettingsContent.scriptingRuntimeVersionLegacy, SettingsContent.scriptingRuntimeVersionLatest}; - var newScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; - - if (EditorApplication.isPlaying) - { - var current = PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; - BuildDisabledEnumPopup(current, SettingsContent.scriptingRuntimeVersion); - } - else - { - newScriptingRuntimeVersions = BuildEnumPopup(SettingsContent.scriptingRuntimeVersion, PlayerSettings.scriptingRuntimeVersion, scriptingRuntimeVersions, scriptingRuntimeVersionNames); - } - - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - { - EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionDeprecationWarning.text, MessageType.Warning); - } - - if (PlayerSettings.scriptingRuntimeVersion != EditorApplication.scriptingRuntimeVersion) + // scripting runtime settings in play mode are not supported + using (new EditorGUI.DisabledScope(EditorApplication.isPlaying)) { - var activeScriptingRuntime = EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; - BuildDisabledEnumPopup(activeScriptingRuntime, SettingsContent.scriptingRuntimeVersionActive); - - EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionActiveWarning.text, MessageType.Warning); - } + // Scripting Runtime Version + var scriptingRuntimeVersions = new[] {ScriptingRuntimeVersion.Legacy, ScriptingRuntimeVersion.Latest}; + var scriptingRuntimeVersionNames = new[] {SettingsContent.scriptingRuntimeVersionLegacy, SettingsContent.scriptingRuntimeVersionLatest}; + var newScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; - if (newScriptingRuntimeVersions != PlayerSettings.scriptingRuntimeVersion) - { - if (newScriptingRuntimeVersions == EditorApplication.scriptingRuntimeVersion) + if (EditorApplication.isPlaying) { - PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + var current = PlayerSettings.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; + BuildDisabledEnumPopup(current, SettingsContent.scriptingRuntimeVersion); } else { - var currentScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; - PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + newScriptingRuntimeVersions = BuildEnumPopup(SettingsContent.scriptingRuntimeVersion, PlayerSettings.scriptingRuntimeVersion, scriptingRuntimeVersions, scriptingRuntimeVersionNames); + } - if (!PlayerSettings.RelaunchProjectIfScriptRuntimeVersionHasChanged()) - { - PlayerSettings.scriptingRuntimeVersion = currentScriptingRuntimeVersions; - } + if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) + { + EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionDeprecationWarning.text, MessageType.Warning); } - } - // Scripting back-end - IScriptingImplementations scripting = ModuleManager.GetScriptingImplementations(targetGroup); - bool targetGroupSupportsIl2Cpp = false; - bool currentBackendIsIl2Cpp = false; + if (PlayerSettings.scriptingRuntimeVersion != EditorApplication.scriptingRuntimeVersion) + { + var activeScriptingRuntime = EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy ? SettingsContent.scriptingRuntimeVersionLegacy : SettingsContent.scriptingRuntimeVersionLatest; + BuildDisabledEnumPopup(activeScriptingRuntime, SettingsContent.scriptingRuntimeVersionActive); - if (scripting == null) - { - BuildDisabledEnumPopup(SettingsContent.scriptingDefault, SettingsContent.scriptingBackend); - } - else - { - var backends = scripting.Enabled(); + EditorGUILayout.HelpBox(SettingsContent.scriptingRuntimeVersionActiveWarning.text, MessageType.Warning); + } - foreach (var backend in backends) + if (newScriptingRuntimeVersions != PlayerSettings.scriptingRuntimeVersion) { - if (backend == ScriptingImplementation.IL2CPP) + if (newScriptingRuntimeVersions == EditorApplication.scriptingRuntimeVersion) { - targetGroupSupportsIl2Cpp = true; - break; + PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + } + else + { + var currentScriptingRuntimeVersions = PlayerSettings.scriptingRuntimeVersion; + PlayerSettings.scriptingRuntimeVersion = newScriptingRuntimeVersions; + + if (!PlayerSettings.RelaunchProjectIfScriptRuntimeVersionHasChanged()) + { + PlayerSettings.scriptingRuntimeVersion = currentScriptingRuntimeVersions; + } } } - ScriptingImplementation currBackend = PlayerSettings.GetScriptingBackend(targetGroup); - currentBackendIsIl2Cpp = currBackend == ScriptingImplementation.IL2CPP; - ScriptingImplementation newBackend; - var mono2xDeprecated = targetGroup == BuildTargetGroup.iOS; + // Scripting back-end + IScriptingImplementations scripting = ModuleManager.GetScriptingImplementations(targetGroup); + bool targetGroupSupportsIl2Cpp = false; + bool currentBackendIsIl2Cpp = false; - if (targetGroup == BuildTargetGroup.tvOS) - { - newBackend = ScriptingImplementation.IL2CPP; - PlayerSettingsEditor.BuildDisabledEnumPopup(SettingsContent.scriptingIL2CPP, SettingsContent.scriptingBackend); - } - else if (backends.Length == 1) + if (scripting == null) { - newBackend = backends[0]; - BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0], mono2xDeprecated), SettingsContent.scriptingBackend); + BuildDisabledEnumPopup(SettingsContent.scriptingDefault, SettingsContent.scriptingBackend); } else { - newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends, mono2xDeprecated)); - } + var backends = scripting.Enabled(); - if (targetGroup == BuildTargetGroup.iOS && newBackend == ScriptingImplementation.Mono2x) - { - EditorGUILayout.HelpBox(SettingsContent.monoNotSupportediOS11WarningGUIContent.text, MessageType.Warning); - } + foreach (var backend in backends) + { + if (backend == ScriptingImplementation.IL2CPP) + { + targetGroupSupportsIl2Cpp = true; + break; + } + } - if (newBackend != currBackend) - PlayerSettings.SetScriptingBackend(targetGroup, newBackend); - } + ScriptingImplementation currBackend = PlayerSettings.GetScriptingBackend(targetGroup); + currentBackendIsIl2Cpp = currBackend == ScriptingImplementation.IL2CPP; + ScriptingImplementation newBackend; + var mono2xDeprecated = targetGroup == BuildTargetGroup.iOS; + + if (targetGroup == BuildTargetGroup.tvOS) + { + newBackend = ScriptingImplementation.IL2CPP; + PlayerSettingsEditor.BuildDisabledEnumPopup(SettingsContent.scriptingIL2CPP, SettingsContent.scriptingBackend); + } + else if (backends.Length == 1) + { + newBackend = backends[0]; + BuildDisabledEnumPopup(GetNiceScriptingBackendName(backends[0], mono2xDeprecated), SettingsContent.scriptingBackend); + } + else + { + newBackend = BuildEnumPopup(SettingsContent.scriptingBackend, currBackend, backends, GetNiceScriptingBackendNames(backends, mono2xDeprecated)); + } - // Api Compatibility Level - var currentCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(targetGroup); - var availableCompatibilityLevels = GetAvailableApiCompatibilityLevels(targetGroup); + if (targetGroup == BuildTargetGroup.iOS && newBackend == ScriptingImplementation.Mono2x) + { + EditorGUILayout.HelpBox(SettingsContent.monoNotSupportediOS11WarningGUIContent.text, MessageType.Warning); + } + + if (newBackend != currBackend) + PlayerSettings.SetScriptingBackend(targetGroup, newBackend); + } - var newCompatibilityLevel = BuildEnumPopup(SettingsContent.apiCompatibilityLevel, currentCompatibilityLevel, availableCompatibilityLevels, GetNiceApiCompatibilityLevelNames(availableCompatibilityLevels)); + // Api Compatibility Level + var currentCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(targetGroup); + var availableCompatibilityLevels = GetAvailableApiCompatibilityLevels(targetGroup); - if (currentCompatibilityLevel != newCompatibilityLevel) - PlayerSettings.SetApiCompatibilityLevel(targetGroup, newCompatibilityLevel); + var newCompatibilityLevel = BuildEnumPopup(SettingsContent.apiCompatibilityLevel, currentCompatibilityLevel, availableCompatibilityLevels, GetNiceApiCompatibilityLevelNames(availableCompatibilityLevels)); - if (targetGroupSupportsIl2Cpp) - { - using (new EditorGUI.DisabledScope(!currentBackendIsIl2Cpp || !scripting.AllowIL2CPPCompilerConfigurationSelection())) + if (currentCompatibilityLevel != newCompatibilityLevel) + PlayerSettings.SetApiCompatibilityLevel(targetGroup, newCompatibilityLevel); + + if (targetGroupSupportsIl2Cpp) { - var currentConfiguration = PlayerSettings.GetIl2CppCompilerConfiguration(targetGroup); - var configurations = GetIl2CppCompilerConfigurations(); - var configurationNames = GetIl2CppCompilerConfigurationNames(); + using (new EditorGUI.DisabledScope(!currentBackendIsIl2Cpp || !scripting.AllowIL2CPPCompilerConfigurationSelection())) + { + var currentConfiguration = PlayerSettings.GetIl2CppCompilerConfiguration(targetGroup); + var configurations = GetIl2CppCompilerConfigurations(); + var configurationNames = GetIl2CppCompilerConfigurationNames(); - var newConfiguration = BuildEnumPopup(SettingsContent.il2cppCompilerConfiguration, currentConfiguration, configurations, configurationNames); + var newConfiguration = BuildEnumPopup(SettingsContent.il2cppCompilerConfiguration, currentConfiguration, configurations, configurationNames); - if (currentConfiguration != newConfiguration) - PlayerSettings.SetIl2CppCompilerConfiguration(targetGroup, newConfiguration); + if (currentConfiguration != newConfiguration) + PlayerSettings.SetIl2CppCompilerConfiguration(targetGroup, newConfiguration); + } } } diff --git a/Editor/Mono/PlayerSettingsAndroid.bindings.cs b/Editor/Mono/PlayerSettingsAndroid.bindings.cs index 6685deca5b..e904f27cff 100644 --- a/Editor/Mono/PlayerSettingsAndroid.bindings.cs +++ b/Editor/Mono/PlayerSettingsAndroid.bindings.cs @@ -399,14 +399,6 @@ public static extern bool startInFullscreen [NativeMethod("SetAndroidStartInFullscreen")] set; } - - public static extern int jvmMaxHeapSize - { - [NativeMethod("GetAndroidJvmMaxHeapSize")] - get; - [NativeMethod("SetAndroidJvmMaxHeapSize")] - set; - } } } } diff --git a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs index e23f0caa92..e13f91687a 100644 --- a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs +++ b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs @@ -265,10 +265,6 @@ internal void NavigateBack(Analytics.ChangeType stageChangeAnalytics) var previousStage = m_NavigationHistory.GetPrevious(); SwitchToStage(previousStage, false, true, stageChangeAnalytics); } - else - { - Debug.LogError("Cannot navigate back"); - } } internal void GoToMainStage(bool setPreviousSelection, Analytics.ChangeType stageChangeAnalytics) @@ -469,8 +465,8 @@ static bool OnOpenAsset(int instanceID, int line) if (assetPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase)) { - // The 'line' parameter is used for passing an instance if entered from the Hierarchy or SceneView, otherwise it is -1 - GameObject instanceRoot = line == -1 ? null : (GameObject)EditorUtility.InstanceIDToObject(line); + // The 'line' parameter can be used for passing an instanceID of a prefab instance + GameObject instanceRoot = line == -1 ? null : EditorUtility.InstanceIDToObject(line) as GameObject; PrefabStageUtility.OpenPrefab(assetPath, instanceRoot, Analytics.ChangeType.EnterViaAssetOpened); return true; diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index 2cf27b4719..9702700750 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -84,7 +84,7 @@ public static SceneView lastActiveSceneView public static SceneView currentDrawingSceneView { get { return s_CurrentDrawingSceneView; } } static readonly PrefColor kSceneViewBackground = new PrefColor("Scene/Background", 0.278431f, 0.278431f, 0.278431f, 0); - static readonly PrefColor kSceneViewPrefabBackground = new PrefColor("Scene/Background for Prefabs", 0.132f, 0.231f, 0.330f, 0); + internal static readonly PrefColor kSceneViewPrefabBackground = new PrefColor("Scene/Background for Prefabs", 0.132f, 0.231f, 0.330f, 0); static readonly PrefColor kSceneViewWire = new PrefColor("Scene/Wireframe", 0.0f, 0.0f, 0.0f, 0.5f); static readonly PrefColor kSceneViewWireOverlay = new PrefColor("Scene/Wireframe Overlay", 0.0f, 0.0f, 0.0f, 0.25f); static readonly PrefColor kSceneViewSelectedOutline = new PrefColor("Scene/Selected Outline", 255.0f / 255.0f, 102.0f / 255.0f, 0.0f / 255.0f, 0.0f / 255.0f); @@ -1349,66 +1349,61 @@ private void DoDrawCamera(Rect windowSpaceCameraRect, Rect groupSpaceCameraRect, void RenderFilteredScene(Rect groupSpaceCameraRect) { - var oldTargetTexture = m_Camera.targetTexture; - var oldDepthTextureMode = m_Camera.depthTextureMode; var oldRenderingPath = m_Camera.renderingPath; - // First pass: Draw the scene normally in destination render textsure + // First pass: Draw the scene normally in destination render texture, save color buffer for later DoClearCamera(groupSpaceCameraRect); Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - // Second pass: Blit the scene faded out in a different render texture - var fadedDesc = m_SceneTargetTexture.descriptor; - var fadedRT = RenderTexture.GetTemporary(fadedDesc); - fadedRT.name = "FadedRT"; + var colorDesc = m_SceneTargetTexture.descriptor; + colorDesc.depthBufferBits = 0; + var colorRT = RenderTexture.GetTemporary(colorDesc); + colorRT.name = "SavedColorRT"; + Graphics.Blit(m_SceneTargetTexture, colorRT); + // Second pass: Blit the scene faded out in the scene target texture float fade = Mathf.Clamp01((float)(EditorApplication.timeSinceStartup - m_StartSearchFilterTime)); if (!s_FadeMaterial) s_FadeMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewGrayscaleEffectFade.mat") as Material; s_FadeMaterial.SetFloat("_Fade", fade); - Graphics.Blit(m_SceneTargetTexture, fadedRT, s_FadeMaterial); + Graphics.Blit(colorRT, m_SceneTargetTexture, s_FadeMaterial); - // Third pass: Draw aura for objects which meet the search filter, but are occluded. + // Third pass: Draw aura for objects which meet the search filter, but are occluded. Save color buffer for later. m_Camera.renderingPath = RenderingPath.Forward; if (!s_AuraShader) s_AuraShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewAura.shader") as Shader; m_Camera.SetReplacementShader(s_AuraShader, ""); - m_Camera.SetTargetBuffers(fadedRT.colorBuffer, m_SceneTargetTexture.depthBuffer); - m_Camera.depthTextureMode = DepthTextureMode.None; Handles.SetCameraFilterMode(m_Camera, Handles.CameraFilterMode.ShowFiltered); Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); - // Fourth pass: Draw objects which do meet filter in a mask - var maskDesc = m_SceneTargetTexture.descriptor; - maskDesc.colorFormat = RenderTextureFormat.R8; - maskDesc.depthBufferBits = 0; - var maskRT = RenderTexture.GetTemporary(maskDesc); - maskRT.name = "MaskRT"; + var fadedDesc = m_SceneTargetTexture.descriptor; + colorDesc.depthBufferBits = 0; + var fadedRT = RenderTexture.GetTemporary(fadedDesc); + fadedRT.name = "FadedColorRT"; + Graphics.Blit(m_SceneTargetTexture, fadedRT); - RenderTexture.active = maskRT; + // Fourth pass: Draw objects which do meet filter in a mask + RenderTexture.active = m_SceneTargetTexture; GL.Clear(false, true, Color.clear); if (!s_BuildFilterShader) s_BuildFilterShader = EditorGUIUtility.LoadRequired("SceneView/SceneViewBuildFilter.shader") as Shader; m_Camera.SetReplacementShader(s_BuildFilterShader, ""); - m_Camera.SetTargetBuffers(maskRT.colorBuffer, m_SceneTargetTexture.depthBuffer); - m_Camera.depthTextureMode = DepthTextureMode.None; Handles.DrawCamera(groupSpaceCameraRect, m_Camera, m_CameraMode.drawMode); // Final pass: Blit the faded scene where the mask isn't set if (!s_ApplyFilterMaterial) s_ApplyFilterMaterial = EditorGUIUtility.LoadRequired("SceneView/SceneViewApplyFilter.mat") as Material; - s_ApplyFilterMaterial.SetTexture("_MaskTex", maskRT); - Graphics.Blit(fadedRT, m_SceneTargetTexture, s_ApplyFilterMaterial); + s_ApplyFilterMaterial.SetTexture("_MaskTex", m_SceneTargetTexture); + Graphics.Blit(fadedRT, colorRT, s_ApplyFilterMaterial); + Graphics.Blit(colorRT, m_SceneTargetTexture); - RenderTexture.ReleaseTemporary(maskRT); + RenderTexture.ReleaseTemporary(colorRT); RenderTexture.ReleaseTemporary(fadedRT); // Reset camera m_Camera.SetReplacementShader(m_ReplacementShader, m_ReplacementString); m_Camera.renderingPath = oldRenderingPath; - m_Camera.targetTexture = oldTargetTexture; - m_Camera.depthTextureMode = oldDepthTextureMode; if (fade < 1) Repaint(); diff --git a/Editor/Mono/Scripting/Compilers/BooCompiler.cs b/Editor/Mono/Scripting/Compilers/BooCompiler.cs index 91bc774c92..8cbb470b10 100644 --- a/Editor/Mono/Scripting/Compilers/BooCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/BooCompiler.cs @@ -23,19 +23,19 @@ override protected Program StartCompiler() { "-debug", "-target:library", - "-out:" + _island._output, + "-out:" + m_Island._output, "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) }; - foreach (string dll in _island._references) + foreach (string dll in m_Island._references) arguments.Add("-r:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) + foreach (string define in m_Island._defines.Distinct()) arguments.Add("-define:" + define); - foreach (string source in _island._files) + foreach (string source in m_Island._files) arguments.Add(PrepareFileName(source)); string compilerPath = Path.Combine(GetBooCompilerDirectory(), "booc.exe"); - return StartCompiler(_island._target, compilerPath, arguments, GetBooProfileDirectory()); + return StartCompiler(m_Island._target, compilerPath, arguments, GetBooProfileDirectory()); } protected override CompilerOutputParserBase CreateOutputParser() @@ -43,6 +43,11 @@ protected override CompilerOutputParserBase CreateOutputParser() return new BooCompilerOutputParser(); } + protected override string[] GetSystemReferenceDirectories() + { + return new[] { GetBooCompilerDirectory() }; + } + string GetBooCompilerDirectory() { if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) @@ -54,7 +59,7 @@ string GetBooCompilerDirectory() string GetBooProfileDirectory() { if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + return BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); return k_UnityScriptProfileDirectory; } diff --git a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs index 8d83e543ee..a3481ab119 100644 --- a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs @@ -56,45 +56,25 @@ public override bool CompilerRequiresAdditionalReferences() return true; } - public string GetNamespaceNewRuntime(string filePath, string definedSymbols) + static string[] GetSystemReferenceDirectories(ApiCompatibilityLevel apiCompatibilityLevel) { - var definedSymbolSplit = definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - string[] defines = null; - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); - try - { - var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(responseFilePath); - defines = new string[responseFileData.Defines.Length + definedSymbolSplit.Length]; - Array.Copy(definedSymbolSplit, defines, definedSymbolSplit.Length); - Array.Copy(responseFileData.Defines, 0, defines, definedSymbolSplit.Length, responseFileData.Defines.Length); - } - catch (Exception e) - { - Debug.LogException(e); - } - - var uniqueSymbols = new HashSet(defines ?? definedSymbolSplit); - return CSharpNamespaceParser.GetNamespace(ReadAndConverteNewLines(filePath).ReadToEnd(), Path.GetFileNameWithoutExtension(filePath), uniqueSymbols.ToArray()); + return MonoLibraryHelpers.GetSystemReferenceDirectories(apiCompatibilityLevel); } - public string GetNamespaceOldRuntime(string filePath, string definedSymbols) + public string GetNamespaceNewRuntime(string filePath, string definedSymbols, string[] defines) { var definedSymbolSplit = definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - string[] defines = null; - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); - try - { - var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(responseFilePath); - defines = new string[responseFileData.Defines.Length + definedSymbolSplit.Length]; - Array.Copy(definedSymbolSplit, defines, definedSymbolSplit.Length); - Array.Copy(responseFileData.Defines, 0, defines, definedSymbolSplit.Length, responseFileData.Defines.Length); - } - catch (Exception e) - { - Debug.LogException(e); - } + var uniqueSymbols = defines.Union(definedSymbolSplit).Distinct().ToArray(); + return CSharpNamespaceParser.GetNamespace( + ReadAndConverteNewLines(filePath).ReadToEnd(), + Path.GetFileNameWithoutExtension(filePath), + uniqueSymbols); + } - var uniqueSymbols = new HashSet(defines ?? definedSymbolSplit); + public string GetNamespaceOldRuntime(string filePath, string definedSymbols, string[] defines) + { + var definedSymbolSplit = definedSymbols.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var uniqueSymbols = defines.Union(definedSymbolSplit).Distinct().ToArray(); using (var parser = ParserFactory.CreateParser(ICSharpCode.NRefactory.SupportedLanguage.CSharp, ReadAndConverteNewLines(filePath))) { foreach (var symbol in uniqueSymbols) @@ -121,13 +101,22 @@ public string GetNamespaceOldRuntime(string filePath, string definedSymbols) public override string GetNamespace(string filePath, string definedSymbols) { + var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ResponseFilename); if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) { - return GetNamespaceNewRuntime(filePath, definedSymbols); + var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile( + responseFilePath, + Application.dataPath, + GetSystemReferenceDirectories(ApiCompatibilityLevel.NET_4_6)); + return GetNamespaceNewRuntime(filePath, definedSymbols, responseFileData.Defines); } else { - return GetNamespaceOldRuntime(filePath, definedSymbols); + var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile( + responseFilePath, + Application.dataPath, + GetSystemReferenceDirectories(ApiCompatibilityLevel.NET_2_0)); + return GetNamespaceOldRuntime(filePath, definedSymbols, responseFileData.Defines); } } diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs index fb95d0cfa4..5a19930cbc 100644 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using UnityEditor.Modules; +using UnityEditor.Scripting.ScriptCompilation; using UnityEditor.Utils; using UnityEngine; @@ -21,18 +22,18 @@ public MicrosoftCSharpCompiler(MonoIsland island, bool runUpdater) : base(island { } - private BuildTarget BuildTarget { get { return _island._target; } } + BuildTarget BuildTarget => m_Island._target; - private string[] GetClassLibraries() + public static string[] GetClassLibraries(BuildTarget buildTarget) { - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); + var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget); if (PlayerSettings.GetScriptingBackend(buildTargetGroup) != ScriptingImplementation.WinRTDotNET) { return new string[] {}; } - if (BuildTarget != BuildTarget.WSAPlayer) - throw new InvalidOperationException(string.Format("MicrosoftCSharpCompiler cannot build for .NET Scripting backend for BuildTarget.{0}.", BuildTarget)); + if (buildTarget != BuildTarget.WSAPlayer) + throw new InvalidOperationException($"MicrosoftCSharpCompiler cannot build for .NET Scripting backend for BuildTarget. {buildTarget}."); var resolver = new NuGetPackageResolver { ProjectLockFile = @"UWP\project.lock.json" }; return resolver.Resolve(); @@ -54,7 +55,7 @@ private void FillCompilerOptions(List arguments, out string argsPrefix) { var compilationExtension = platformSupportModule.CreateCompilationExtension(); - arguments.AddRange(GetClassLibraries().Select(r => "/reference:\"" + r + "\"")); + arguments.AddRange(GetClassLibraries(BuildTarget).Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetAdditionalAssemblyReferences().Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetWindowsMetadataReferences().Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetAdditionalDefines().Select(d => "/define:" + d)); @@ -69,14 +70,14 @@ private static void ThrowCompilerNotFoundException(string path) private Program StartCompilerImpl(List arguments, string argsPrefix) { - foreach (string dll in _island._references) + foreach (string dll in m_Island._references) arguments.Add("/reference:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) + foreach (string define in m_Island._defines.Distinct()) arguments.Add("/define:" + define); - var filePathMappings = new List(_island._files.Length); - foreach (var source in _island._files) + var filePathMappings = new List(m_Island._files.Length); + foreach (var source in m_Island._files) { var f = PrepareFileName(source); if (Application.platform == RuntimePlatform.WindowsEditor) @@ -117,7 +118,7 @@ private Program StartCompilerImpl(List arguments, string argsPrefix) if (!AddCustomResponseFileIfPresent(arguments, ReponseFilename) && PlayerSettings.GetScriptingBackend(buildTargetGroup) != ScriptingImplementation.WinRTDotNET) { if (AddCustomResponseFileIfPresent(arguments, "mcs.rsp")) - UnityEngine.Debug.LogWarning(string.Format("Using obsolete custom response file 'mcs.rsp'. Please use '{0}' instead.", ReponseFilename)); + UnityEngine.Debug.LogWarning($"Using obsolete custom response file 'mcs.rsp'. Please use '{ReponseFilename}' instead."); } var responseFile = CommandLineFormatter.GenerateResponseFile(arguments); @@ -168,7 +169,7 @@ static bool UseNetCoreCompiler() protected override Program StartCompiler() { - var outputPath = PrepareFileName(_island._output); + var outputPath = PrepareFileName(m_Island._output); // Always build with "/debug:pdbonly", "/optimize+", because even if the assembly is optimized // it seems you can still succesfully debug C# scripts in Visual Studio @@ -179,11 +180,11 @@ protected override Program StartCompiler() "/out:" + outputPath }; - if (_island._allowUnsafeCode) + if (m_Island._allowUnsafeCode) arguments.Add("/unsafe"); var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); - var disableOptimizations = _island._development_player || (_island._editor && EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true)); + var disableOptimizations = m_Island._development_player || (m_Island._editor && EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true)); if (!disableOptimizations) { if (PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) @@ -206,6 +207,17 @@ protected override Program StartCompiler() return StartCompilerImpl(arguments, argsPrefix); } + protected override string[] GetSystemReferenceDirectories() + { + var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); + if (BuildTarget == BuildTarget.WSAPlayer && PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) + { + return GetClassLibraries(BuildTarget).Select(library => Directory.GetParent(library).FullName).Distinct().ToArray(); + } + + return MonoLibraryHelpers.GetSystemReferenceDirectories(m_Island._api_compatibility_level); + } + protected override string[] GetStreamContainingCompilerMessages() { return GetStandardOutput(); diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs index 6572173376..f442a9f7b4 100644 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs @@ -14,13 +14,13 @@ namespace UnityEditor.Scripting.Compilers { class MonoCSharpCompiler : MonoScriptCompilerBase { - public static readonly string ReponseFilename = "mcs.rsp"; + public static readonly string ResponseFilename = "mcs.rsp"; public MonoCSharpCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) { } - override protected Program StartCompiler() + protected override Program StartCompiler() { var arguments = new List { @@ -28,23 +28,23 @@ override protected Program StartCompiler() "-target:library", "-nowarn:0169", "-langversion:" + ((EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) ? "6" : "4"), - "-out:" + PrepareFileName(_island._output), + "-out:" + PrepareFileName(m_Island._output), "-nostdlib", }; - if (_island._allowUnsafeCode) + if (m_Island._allowUnsafeCode) arguments.Add("-unsafe"); - if (!_island._development_player && !_island._editor) + if (!m_Island._development_player && !m_Island._editor) arguments.Add("-optimize"); - foreach (string dll in _island._references) + foreach (string dll in m_Island._references) arguments.Add("-r:" + PrepareFileName(dll)); - foreach (string define in _island._defines.Distinct()) + foreach (string define in m_Island._defines.Distinct()) arguments.Add("-define:" + define); - var pathMappings = new List(_island._files.Length); - foreach (string source in _island._files) + var pathMappings = new List(m_Island._files.Length); + foreach (string source in m_Island._files) { var preparedFileName = PrepareFileName(source); if (preparedFileName != source) @@ -53,35 +53,39 @@ override protected Program StartCompiler() arguments.Add(preparedFileName); } - if (!AddCustomResponseFileIfPresent(arguments, ReponseFilename)) + if (!AddCustomResponseFileIfPresent(arguments, ResponseFilename)) { - if (_island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0_Subset && AddCustomResponseFileIfPresent(arguments, "smcs.rsp")) - Debug.LogWarning(string.Format("Using obsolete custom response file 'smcs.rsp'. Please use '{0}' instead.", ReponseFilename)); - else if (_island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 && AddCustomResponseFileIfPresent(arguments, "gmcs.rsp")) - Debug.LogWarning(string.Format("Using obsolete custom response file 'gmcs.rsp'. Please use '{0}' instead.", ReponseFilename)); + if (m_Island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0_Subset + && AddCustomResponseFileIfPresent(arguments, "smcs.rsp")) + { + Debug.LogWarning("Using obsolete custom response file \'smcs.rsp\'. " + + $"Please use '{ResponseFilename}' instead."); + } + else if (m_Island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 + && AddCustomResponseFileIfPresent(arguments, "gmcs.rsp")) + { + Debug.LogWarning("Using obsolete custom response file \'gmcs.rsp\'. " + + $"Please use '{ResponseFilename}' instead."); + } } return StartCompiler( - _island._target, - GetCompilerPath(arguments), + m_Island._target, + GetCompilerPath(), arguments, - BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level), + BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level), false, MonoInstallationFinder.GetMonoInstallation(MonoInstallationFinder.MonoBleedingEdgeInstallation), pathMappings ); } - private string GetCompilerPath(List arguments) + static string GetCompilerPath() { string dir = MonoInstallationFinder.GetProfileDirectory("4.5", MonoInstallationFinder.MonoBleedingEdgeInstallation); var compilerPath = Path.Combine(dir, "mcs.exe"); if (File.Exists(compilerPath)) { - var systemAssemblyDirectory = MonoLibraryHelpers.GetSystemReferenceDirectory(_island._api_compatibility_level); - - if (!string.IsNullOrEmpty(systemAssemblyDirectory) && Directory.Exists(systemAssemblyDirectory)) - arguments.Add("-lib:" + PrepareFileName(systemAssemblyDirectory)); return compilerPath; } @@ -93,6 +97,11 @@ protected override CompilerOutputParserBase CreateOutputParser() return new MonoCSharpCompilerOutputParser(); } + protected override string[] GetSystemReferenceDirectories() + { + return MonoLibraryHelpers.GetSystemReferenceDirectories(m_Island._api_compatibility_level); + } + public static string[] Compile(string[] sources, string[] references, string[] defines, string outputFile, bool allowUnsafeCode) { var island = new MonoIsland(BuildTarget.StandaloneWindows, ApiCompatibilityLevel.NET_2_0_Subset, allowUnsafeCode, sources, references, defines, outputFile); diff --git a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs index 52122f5232..6d919acd25 100644 --- a/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/MonoScriptCompilerBase.cs @@ -16,14 +16,14 @@ protected MonoScriptCompilerBase(MonoIsland island, bool runUpdater) : base(isla protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments) { - return StartCompiler(target, compiler, arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level)); + return StartCompiler(target, compiler, arguments, BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level)); } protected ManagedProgram StartCompiler(BuildTarget target, string compiler, List arguments, string profileDirectory) { AddCustomResponseFileIfPresent(arguments, Path.GetFileNameWithoutExtension(compiler) + ".rsp"); - var monoInstallation = (PlayerSettingsEditor.IsLatestApiCompatibility(_island._api_compatibility_level)) + var monoInstallation = PlayerSettingsEditor.IsLatestApiCompatibility(m_Island._api_compatibility_level) ? MonoInstallationFinder.GetMonoBleedingEdgeInstallation() : MonoInstallationFinder.GetMonoInstallation(); return StartCompiler(target, compiler, arguments, profileDirectory, true, monoInstallation); diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index fd3072da16..d140999018 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using UnityEditor.Scripting.ScriptCompilation; using UnityEngine; using UnityEditor.Utils; @@ -22,9 +23,10 @@ public class Reference } public string[] Defines; - public Reference[] References; + public Reference[] FullPathReferences; public bool Unsafe; public string[] Errors; + public string[] OtherArguments; } public class CompilerOption @@ -38,9 +40,10 @@ public class CompilerOption private Program process; private string _responseFile = null; private bool _runAPIUpdater; + string m_ProjectDirectory; // ToDo: would be nice to move MonoIsland to MonoScriptCompilerBase - protected MonoIsland _island; + protected MonoIsland m_Island; protected abstract Program StartCompiler(); @@ -48,8 +51,9 @@ public class CompilerOption protected ScriptCompilerBase(MonoIsland island, bool runAPIUpdater) { - _island = island; + m_Island = island; _runAPIUpdater = runAPIUpdater; + m_ProjectDirectory = Directory.GetParent(Application.dataPath).FullName.ConvertSeparatorsToUnity(); } protected string[] GetErrorOutput() @@ -98,15 +102,17 @@ public void WaitForCompilationToFinish() protected string GetMonoProfileLibDirectory() { - var profile = BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + var profile = BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); - var monoInstall = (PlayerSettingsEditor.IsLatestApiCompatibility(_island._api_compatibility_level)) + var monoInstall = PlayerSettingsEditor.IsLatestApiCompatibility(m_Island._api_compatibility_level) ? MonoInstallationFinder.MonoBleedingEdgeInstallation : MonoInstallationFinder.MonoInstallation; return MonoInstallationFinder.GetProfileDirectory(profile, monoInstall); } + protected abstract string[] GetSystemReferenceDirectories(); + protected bool AddCustomResponseFileIfPresent(List arguments, string responseFileName) { var relativeCustomResponseFilePath = Path.Combine("Assets", responseFileName); @@ -114,19 +120,36 @@ protected bool AddCustomResponseFileIfPresent(List arguments, string res if (!File.Exists(relativeCustomResponseFilePath)) return false; - arguments.Add("@" + relativeCustomResponseFilePath); + var responseFileData = ParseResponseFileFromFile( + Path.Combine(m_ProjectDirectory, relativeCustomResponseFilePath), + Application.dataPath, + GetSystemReferenceDirectories()); + foreach (var error in responseFileData.Errors) + { + Debug.LogError($"{relativeCustomResponseFilePath} Parse Error : {error}"); + } + + arguments.AddRange(responseFileData.Defines.Distinct().Select(define => "/define:" + define)); + arguments.AddRange(responseFileData.FullPathReferences.Select(reference => + "/reference:" + PrepareFileName(reference.Assembly))); + + if (responseFileData.Unsafe) arguments.Add("/unsafe"); + arguments.AddRange(responseFileData.OtherArguments); return true; } - public static ResponseFileData ParseResponseFileFromFile(string responseFilePath) + public static ResponseFileData ParseResponseFileFromFile( + string responseFilePath, + string projectDirectory, + string[] systemReferenceDirectories) { if (!File.Exists(responseFilePath)) { var empty = new ResponseFileData { Defines = new string[0], - References = new ResponseFileData.Reference[0], + FullPathReferences = new ResponseFileData.Reference[0], Unsafe = false, Errors = new string[0] }; @@ -136,7 +159,11 @@ public static ResponseFileData ParseResponseFileFromFile(string responseFilePath var responseFileText = File.ReadAllText(responseFilePath); - return ParseResponseFileText(responseFileText); + return ParseResponseFileText( + responseFileText, + responseFilePath, + projectDirectory, + systemReferenceDirectories); } // From: @@ -204,7 +231,11 @@ static string[] ResponseFileTextToStrings(string responseFileText) return args.ToArray(); } - public static ResponseFileData ParseResponseFileText(string responseFileText) + static ResponseFileData ParseResponseFileText( + string responseFileText, + string responseFileName, + string projectDirectory, + string[] systemReferenceDirectories) { var compilerOptions = new List(); @@ -232,6 +263,7 @@ public static ResponseFileData ParseResponseFileText(string responseFileText) compilerOptions.Add(new CompilerOption { Arg = arg, Value = value }); } + var responseArguments = new List(); var defines = new List(); var references = new List(); bool unsafeDefined = false; @@ -276,24 +308,61 @@ public static ResponseFileData ParseResponseFileText(string responseFileText) break; } - foreach (string reference in refs) + var reference = refs[0]; + if (reference.Length == 0) { - if (reference.Length == 0) - continue; + continue; + } - int index = reference.IndexOf('='); - if (index > -1) - { - string alias = reference.Substring(0, index); - string assembly = reference.Substring(index + 1); + ResponseFileData.Reference responseReference; + + int index = reference.IndexOf('='); + if (index > -1) + { + string alias = reference.Substring(0, index); + string assembly = reference.Substring(index + 1); + + responseReference = new ResponseFileData.Reference { Alias = alias, Assembly = assembly }; + } + else + { + responseReference = new ResponseFileData.Reference { Alias = string.Empty, Assembly = reference }; + } - references.Add(new ResponseFileData.Reference { Alias = alias, Assembly = assembly }); + string fullPathReference = ""; + var referencePath = responseReference.Assembly; + if (Path.IsPathRooted(referencePath)) + { + fullPathReference = referencePath; + } + else + { + foreach (var directory in systemReferenceDirectories) + { + var systemReferencePath = Paths.Combine(directory, referencePath); + if (File.Exists(systemReferencePath)) + { + fullPathReference = systemReferencePath; + break; + } } - else + + var userPath = Paths.Combine(projectDirectory, referencePath); + if (File.Exists(userPath)) { - references.Add(new ResponseFileData.Reference { Alias = string.Empty, Assembly = reference }); + fullPathReference = userPath; } } + + if (fullPathReference == "") + { + errors.Add($"{responseFileName}: not parsed correctly: {responseReference.Assembly} could not be found as a system library.\n" + + "If this was meant as a user reference please provide the relative path from project root (parent of the Assets folder) in the response file."); + continue; + } + + responseReference.Assembly = fullPathReference.Replace('\\', '/'); + references.Add(responseReference); } break; @@ -309,15 +378,20 @@ public static ResponseFileData ParseResponseFileText(string responseFileText) unsafeDefined = false; } break; + default: + var valueWithColon = value.Length == 0 ? "" : ":" + value; + responseArguments.Add(arg + valueWithColon); + break; } } var responseFileData = new ResponseFileData { Defines = defines.ToArray(), - References = references.ToArray(), + FullPathReferences = references.ToArray(), Unsafe = unsafeDefined, - Errors = errors.ToArray() + Errors = errors.ToArray(), + OtherArguments = responseArguments.ToArray(), }; return responseFileData; @@ -336,7 +410,11 @@ public virtual CompilerMessage[] GetCompilerMessages() DumpStreamOutputToLog(); - return CreateOutputParser().Parse(GetStreamContainingCompilerMessages(), CompilationHadFailure(), Path.GetFileName(_island._output)).ToArray(); + return CreateOutputParser().Parse( + GetStreamContainingCompilerMessages(), + CompilationHadFailure(), + Path.GetFileName(m_Island._output) + ).ToArray(); } protected bool CompilationHadFailure() @@ -367,7 +445,11 @@ private void DumpStreamOutputToLog() string[] stdOutput = GetStandardOutput(); - Console.WriteLine("-----CompilerOutput:-stdout--exitcode: " + process.ExitCode + "--compilationhadfailure: " + hadCompilationFailure + "--outfile: " + _island._output); + Console.WriteLine( + "-----CompilerOutput:-stdout--exitcode: " + process.ExitCode + + "--compilationhadfailure: " + hadCompilationFailure + + "--outfile: " + m_Island._output + ); foreach (string line in stdOutput) Console.WriteLine(line); @@ -386,7 +468,11 @@ protected void RunAPIUpdaterIfRequired(string responseFile, IList pathMa var pathMappingsFilePath = Path.GetTempFileName(); File.WriteAllLines(pathMappingsFilePath, pathMappings.ToArray()); - APIUpdaterHelper.UpdateScripts(responseFile, _island.GetExtensionOfSourceFiles(), PrepareFileName(pathMappingsFilePath)); + APIUpdaterHelper.UpdateScripts( + responseFile, + m_Island.GetExtensionOfSourceFiles(), + PrepareFileName(pathMappingsFilePath) + ); } } diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs index 48b4ab118e..7b4c4c5809 100644 --- a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs @@ -25,7 +25,7 @@ protected override CompilerOutputParserBase CreateOutputParser() return new UnityScriptCompilerOutputParser(); } - override protected Program StartCompiler() + protected override Program StartCompiler() { var arguments = new List { @@ -37,30 +37,30 @@ override protected Program StartCompiler() "-nowarn:BCW0016", "-nowarn:BCW0003", "-method:Main", - "-out:" + _island._output, + "-out:" + m_Island._output, "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) }; if (StrictBuildTarget()) arguments.Add("-pragmas:strict,downcast"); - foreach (var define in _island._defines.Distinct()) + foreach (var define in m_Island._defines.Distinct()) arguments.Add("-define:" + define); - foreach (var dll in _island._references) + foreach (var dll in m_Island._references) arguments.Add("-r:" + PrepareFileName(dll)); - var compilingEditorScripts = Array.Exists(_island._references, UnityEditorPattern.IsMatch); + var compilingEditorScripts = Array.Exists(m_Island._references, UnityEditorPattern.IsMatch); if (compilingEditorScripts) arguments.Add("-i:UnityEditor"); - else if (!BuildPipeline.IsUnityScriptEvalSupported(_island._target)) - arguments.Add(string.Format("-disable-eval:eval is not supported on the current build target ({0}).", _island._target)); + else if (!BuildPipeline.IsUnityScriptEvalSupported(m_Island._target)) + arguments.Add($"-disable-eval:eval is not supported on the current build target ({m_Island._target})."); - foreach (string source in _island._files) + foreach (string source in m_Island._files) arguments.Add(PrepareFileName(source)); var compilerPath = Path.Combine(GetUnityScriptCompilerDirectory(), "us.exe"); - return StartCompiler(_island._target, compilerPath, arguments, GetUnityScriptProfileDirectory()); + return StartCompiler(m_Island._target, compilerPath, arguments, GetUnityScriptProfileDirectory()); } string GetUnityScriptCompilerDirectory() @@ -74,14 +74,19 @@ string GetUnityScriptCompilerDirectory() string GetUnityScriptProfileDirectory() { if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return BuildPipeline.CompatibilityProfileToClassLibFolder(_island._api_compatibility_level); + return BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); return k_UnityScriptProfileDirectory; } private bool StrictBuildTarget() { - return Array.IndexOf(_island._defines, "ENABLE_DUCK_TYPING") == -1; + return Array.IndexOf(m_Island._defines, "ENABLE_DUCK_TYPING") == -1; + } + + protected override string[] GetSystemReferenceDirectories() + { + return new[] { GetUnityScriptCompilerDirectory() }; } protected override string[] GetStreamContainingCompilerMessages() diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index f784520a09..1eccdccda8 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -769,6 +769,17 @@ static bool IsCompatibleWithPlatformAndDefines(TargetAssembly assembly, ScriptAs return assembly.IsCompatibleFunc == null || assembly.IsCompatibleFunc(settings, assembly.Defines); } + public static bool IsCompatibleWithPlatformAndDefines(TargetAssembly assembly, BuildTarget buildTarget, EditorScriptCompilationOptions options) + { + var settings = new ScriptAssemblySettings + { + BuildTarget = buildTarget, + CompilationOptions = options + }; + + return IsCompatibleWithPlatformAndDefines(assembly, settings); + } + internal static TargetAssembly[] CreatePredefinedTargetAssemblies() { var runtimeFirstPassAssemblies = new List(); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 6cab818501..5f5e896a54 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -240,6 +240,23 @@ public void DirtyScript(string path) dirtyScripts.Add(path); } + public void DirtyMovedScript(string oldPath, string newPath) + { + DirtyScript(newPath); + + var targetAssembly = EditorBuildRules.GetTargetAssembly(oldPath, projectDirectory, customTargetAssemblies); + + // The target assembly might not exist any more. + if (targetAssembly == null) + { + areAllScriptsDirty = true; + } + else + { + dirtyTargetAssemblies.Add(targetAssembly); + } + } + public void DirtyRemovedScript(string path) { allScripts.Remove(path); @@ -354,7 +371,7 @@ public PrecompiledAssembly[] GetAllPrecompiledAssemblies() return this.precompiledAssemblies; } - public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(out CustomScriptAssemblyAndReference[] assembliesWithMissingReference) + public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(EditorScriptCompilationOptions options, BuildTarget buildTarget, out CustomScriptAssemblyAndReference[] assembliesWithMissingReference) { if (customTargetAssemblies == null) { @@ -393,6 +410,11 @@ public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(out // of compiled assemblies. foreach (var reference in assembly.References) { + // Don't check references that are not compatible with the current build target, + // as those assemblies have not been compiled. + if (!EditorBuildRules.IsCompatibleWithPlatformAndDefines(reference, buildTarget, options)) + continue; + if (!customTargetAssemblyCompiledPaths.ContainsKey(reference)) { customTargetAssemblyCompiledPaths.Remove(assembly); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs index c30ab10805..e51ed2fc6c 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs @@ -155,6 +155,12 @@ public static void DirtyRemovedScript(string path) Instance.DirtyRemovedScript(path); } + [RequiredByNativeCode] + public static void DirtyMovedScript(string oldPath, string newPath) + { + Instance.DirtyMovedScript(oldPath, newPath); + } + [RequiredByNativeCode] public static void DirtyPrecompiledAssembly(string path) { @@ -210,11 +216,11 @@ public static void SetAllPackageAssemblies(EditorCompilation.PackageAssembly[] p } [RequiredByNativeCode] - public static EditorCompilation.TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies() + public static EditorCompilation.TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(EditorScriptCompilationOptions options, BuildTarget buildTarget) { EditorCompilation.CustomScriptAssemblyAndReference[] assembliesWithMissingReference = null; - var result = EmitExceptionAsError(() => Instance.GetAllCompiledAndResolvedCustomTargetAssemblies(out assembliesWithMissingReference), new EditorCompilation.TargetAssemblyInfo[0]); + var result = EmitExceptionAsError(() => Instance.GetAllCompiledAndResolvedCustomTargetAssemblies(options, buildTarget, out assembliesWithMissingReference), new EditorCompilation.TargetAssemblyInfo[0]); if (assembliesWithMissingReference.Length > 0) { diff --git a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs index f5578f113f..ecf78af84d 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs @@ -33,6 +33,16 @@ public static string[] GetSystemLibraryReferences(ApiCompatibilityLevel apiCompa return GetCachedSystemLibraryReferences(apiCompatibilityLevel); } + static string[] FindReferencesInDirectories(this string[] references, string[] directories) + { + return ( + from reference in references + from directory in directories + where File.Exists(Path.Combine(directory, reference)) + select Path.Combine(directory, reference) + ).ToArray(); + } + static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel) { // We cache the references because they are computed by getting files in directories on disk, @@ -43,7 +53,7 @@ static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompat } var references = new List(); - var monoAssemblyDirectory = GetSystemReferenceDirectory(apiCompatibilityLevel); + var monoAssemblyDirectories = GetSystemReferenceDirectories(apiCompatibilityLevel); if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) { @@ -51,19 +61,20 @@ static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompat } else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) { - references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - references.AddRange(GetNet46SystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); + references.AddRange(GetSystemReferences().FindReferencesInDirectories(monoAssemblyDirectories)); + references.AddRange(GetNet46SystemReferences().FindReferencesInDirectories(monoAssemblyDirectories)); // Look in the mono assembly directory for a facade folder and get a list of all the DLL's to be // used later by the language compilers. + var monoAssemblyDirectory = MonoInstallationFinder.GetProfileDirectory("4.7.1-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); references.AddRange(Directory.GetFiles(Path.Combine(monoAssemblyDirectory, "Facades"), "*.dll")); references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(MonoInstallationFinder.GetProfileDirectory("unityscript", MonoInstallationFinder.MonoBleedingEdgeInstallation), dll))); } else { - references.AddRange(GetSystemReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); - references.AddRange(GetBooAndUsReferences().Select(dll => Path.Combine(monoAssemblyDirectory, dll))); + references.AddRange(GetSystemReferences().FindReferencesInDirectories(monoAssemblyDirectories)); + references.AddRange(GetBooAndUsReferences().FindReferencesInDirectories(monoAssemblyDirectories)); } cachedReferences = new CachedReferences @@ -76,18 +87,40 @@ static string[] GetCachedSystemLibraryReferences(ApiCompatibilityLevel apiCompat return cachedReferences.References; } - public static string GetSystemReferenceDirectory(ApiCompatibilityLevel apiCompatibilityLevel) + static string GetSystemReference(ApiCompatibilityLevel apiCompatibilityLevel) { - if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) - return ""; - else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) return MonoInstallationFinder.GetProfileDirectory("4.7.1-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); - else if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0) + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_2_0) return MonoInstallationFinder.GetProfileDirectory("2.0-api", MonoInstallationFinder.MonoBleedingEdgeInstallation); return MonoInstallationFinder.GetProfileDirectory(BuildPipeline.CompatibilityProfileToClassLibFolder(apiCompatibilityLevel), MonoInstallationFinder.MonoBleedingEdgeInstallation); } + public static string[] GetSystemReferenceDirectories(ApiCompatibilityLevel apiCompatibilityLevel) + { + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_Standard_2_0) + { + var systemReferenceDirectories = new List(); + systemReferenceDirectories.Add(NetStandardFinder.GetReferenceDirectory()); + systemReferenceDirectories.Add(NetStandardFinder.GetNetStandardCompatShimsDirectory()); + systemReferenceDirectories.Add(NetStandardFinder.GetNetStandardExtensionsDirectory()); + systemReferenceDirectories.Add(NetStandardFinder.GetDotNetFrameworkCompatShimsDirectory()); + return systemReferenceDirectories.ToArray(); + } + + if (apiCompatibilityLevel == ApiCompatibilityLevel.NET_4_6) + { + var systemReferenceDirectories = new List(); + var frameworkDirectory = GetSystemReference(apiCompatibilityLevel); + systemReferenceDirectories.Add(frameworkDirectory); + systemReferenceDirectories.Add(Path.Combine(frameworkDirectory, "Facades")); + return systemReferenceDirectories.ToArray(); + } + + return new[] { GetSystemReference(apiCompatibilityLevel) }; + } + static string[] GetNetStandardClassLibraries() { var classLibraries = new List(); @@ -125,7 +158,10 @@ static string[] GetNet46SystemReferences() return new[] { "System.Numerics.dll", - "System.Numerics.Vectors.dll" + "System.Numerics.Vectors.dll", + "System.Net.Http.dll", + "Microsoft.CSharp.dll", + "System.Data.dll", }; } diff --git a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs index 7063a34d06..c1c276d9e1 100644 --- a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs +++ b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs @@ -102,5 +102,11 @@ public override void OnTitleBarGUI() } } } + + public override void OnFooterBarGUI() + { + if (m_SettingsEditor != null) + InspectorWindow.DrawVCSShortInfo(settingsWindow, m_SettingsEditor); + } } } diff --git a/Editor/Mono/Settings/SettingsProvider.cs b/Editor/Mono/Settings/SettingsProvider.cs index 622bdcdb43..c41f58ca89 100644 --- a/Editor/Mono/Settings/SettingsProvider.cs +++ b/Editor/Mono/Settings/SettingsProvider.cs @@ -69,6 +69,7 @@ public string label public Action guiHandler { get; set; } public Action titleBarGuiHandler { get; set; } + public Action footerBarGuiHandler { get; set; } public Action activateHandler { get; set; } public Action deactivateHandler { get; set; } public Func hasSearchInterestHandler { get; set; } @@ -119,6 +120,11 @@ public virtual void OnTitleBarGUI() titleBarGuiHandler?.Invoke(); } + public virtual void OnFooterBarGUI() + { + footerBarGuiHandler?.Invoke(); + } + public void PopulateSearchKeywordsFromGUIContentProperties() { GetSearchKeywordsFromGUIContentProperties(keywords); diff --git a/Editor/Mono/Settings/SettingsWindow.cs b/Editor/Mono/Settings/SettingsWindow.cs index e69757227e..cf6b61a8ba 100644 --- a/Editor/Mono/Settings/SettingsWindow.cs +++ b/Editor/Mono/Settings/SettingsWindow.cs @@ -275,19 +275,22 @@ private void DrawToolbar() private void DrawSettingsPanel() { + if (m_TreeView.currentProvider == null) + return; + + DrawTitleBar(); + using (var scrollViewScope = new EditorGUILayout.ScrollViewScope(m_PosRight, GUILayout.ExpandWidth(true))) { m_PosRight = scrollViewScope.scrollPosition; DrawControls(); } + + DrawFooterBar(); } private void DrawControls() { - if (m_TreeView.currentProvider == null) - return; - - DrawTitleBar(); using (new EditorGUI.LabelHighlightScope(m_SearchText, Styles.settingsPanel.GetColor("-unity-search-highlight-selection-color"), Styles.settingsPanel.GetColor("-unity-search-highlight-color"))) m_TreeView.currentProvider.OnGUI(m_SearchText); } @@ -303,6 +306,11 @@ private void DrawTitleBar() GUILayout.EndHorizontal(); } + private void DrawFooterBar() + { + m_TreeView.currentProvider.OnFooterBarGUI(); + } + private void DrawTreeView() { var splitterRect = m_Splitter.GetSplitterRect(m_Splitter.Children().First()); diff --git a/Editor/Mono/Utils/DirectoryExtensions.cs b/Editor/Mono/Utils/DirectoryExtensions.cs index 7079909df6..609bbae427 100644 --- a/Editor/Mono/Utils/DirectoryExtensions.cs +++ b/Editor/Mono/Utils/DirectoryExtensions.cs @@ -6,7 +6,7 @@ namespace UnityEditor.Utils { - internal static class DirectoryExtensions + static class DirectoryExtensions { public static void DeleteRecursive(this string directoryPath) { diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index f7ab82ff33..998704dfca 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -18,8 +18,8 @@ using UnityEditorInternal; using UnityEditor.Scripting.Compilers; -using Mono.Cecil; using UnityEditor.Compilation; +using UnityEditor.Modules; namespace UnityEditor.VisualStudioIntegration { @@ -233,25 +233,44 @@ internal void GenerateAndWriteSolutionAndProjects(ScriptEditorUtility.ScriptEdit var allAssetProjectParts = GenerateAllAssetProjectParts(); - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ReponseFilename); + var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ResponseFilename); - var responseFileData = ScriptCompilerBase.ParseResponseFileFromFile(Path.Combine(_projectDirectory, responseFilePath)); + var monoIslands = islands.ToList(); - if (responseFileData.Errors.Length > 0) - { - foreach (var error in responseFileData.Errors) - UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", responseFilePath, error); - } - SyncSolution(islands); - var allProjectIslands = RelevantIslandsForMode(islands, ModeForCurrentExternalEditor()).ToList(); + SyncSolution(monoIslands); + var allProjectIslands = RelevantIslandsForMode(monoIslands, ModeForCurrentExternalEditor()).ToList(); foreach (MonoIsland island in allProjectIslands) + { + var responseFileData = parseResponseFileData(island, responseFilePath); SyncProject(island, allAssetProjectParts, responseFileData, allProjectIslands); + } if (scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioCode) WriteVSCodeSettingsFiles(); } + ScriptCompilerBase.ResponseFileData parseResponseFileData(MonoIsland island, string responseFilePath) + { + var systemReferenceDirectories = CSharpLanguage.GetCSharpCompiler(island._target, true, "Assembly-CSharp") == CSharpCompiler.Microsoft + && PlayerSettings.GetScriptingBackend(BuildPipeline.GetBuildTargetGroup(island._target)) == ScriptingImplementation.WinRTDotNET + ? MicrosoftCSharpCompiler.GetClassLibraries(island._target) + : MonoLibraryHelpers.GetSystemReferenceDirectories(island._api_compatibility_level); + + ScriptCompilerBase.ResponseFileData responseFileData = ScriptCompilerBase.ParseResponseFileFromFile( + Path.Combine(_projectDirectory, responseFilePath), + _projectDirectory, + systemReferenceDirectories); + + if (responseFileData.Errors.Length > 0) + { + foreach (var error in responseFileData.Errors) + UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", responseFilePath, error); + } + + return responseFileData; + } + Dictionary GenerateAllAssetProjectParts() { Dictionary stringBuilders = new Dictionary(); @@ -401,8 +420,9 @@ string ProjectText(MonoIsland island, projectBuilder.Append(additionalAssetsForProject); var allAdditionalReferenceFilenames = new List(); + var islandRefs = references.Union(island._references); - foreach (string reference in references.Union(island._references).Union(responseFileData.References.Select(r => r.Assembly))) + foreach (string reference in islandRefs) { if (reference.EndsWith("/UnityEditor.dll") || reference.EndsWith("/UnityEngine.dll") || reference.EndsWith("\\UnityEditor.dll") || reference.EndsWith("\\UnityEngine.dll")) continue; @@ -439,13 +459,13 @@ string ProjectText(MonoIsland island, allAdditionalReferenceFilenames.Add(referenceName); } - //replace \ with / and \\ with / - var escapedFullPath = SecurityElement.Escape(fullReference); - escapedFullPath = escapedFullPath.Replace("\\", "/"); - escapedFullPath = escapedFullPath.Replace("\\\\", "/"); - projectBuilder.AppendFormat(" {1}", Path.GetFileNameWithoutExtension(escapedFullPath), WindowsNewline); - projectBuilder.AppendFormat(" {0}{1}", escapedFullPath, WindowsNewline); - projectBuilder.AppendFormat(" {0}", WindowsNewline); + AppendReference(fullReference, projectBuilder); + } + + var responseRefs = responseFileData.FullPathReferences.Select(r => r.Assembly); + foreach (var reference in responseRefs) + { + AppendReference(reference, projectBuilder); } if (0 < projectReferences.Count) @@ -472,6 +492,17 @@ string ProjectText(MonoIsland island, return projectBuilder.ToString(); } + static void AppendReference(string fullReference, StringBuilder projectBuilder) + { + //replace \ with / and \\ with / + var escapedFullPath = SecurityElement.Escape(fullReference); + escapedFullPath = escapedFullPath.Replace("\\", "/"); + escapedFullPath = escapedFullPath.Replace("\\\\", "/"); + projectBuilder.AppendFormat(" {1}", Path.GetFileNameWithoutExtension(escapedFullPath), WindowsNewline); + projectBuilder.AppendFormat(" {0}{1}", escapedFullPath, WindowsNewline); + projectBuilder.AppendFormat(" {0}", WindowsNewline); + } + public string ProjectFile(MonoIsland island) { ScriptingLanguage language = ScriptingLanguageFor(island); @@ -504,7 +535,7 @@ private string ProjectHeader(MonoIsland island, { targetframeworkversion = "v4.7.1"; } - targetLanguageVersion = "7.3"; + targetLanguageVersion = "latest"; } else if (_settings.VisualStudioVersion == 9) { diff --git a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs index eec3acf2ce..82b85d1157 100644 --- a/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs +++ b/Editor/Src/VR/Mono/PlayerSettingsEditorVR.cs @@ -22,19 +22,21 @@ static class Styles { public static readonly GUIContent singlepassAndroidWarning = EditorGUIUtility.TrTextContent("Single Pass stereo rendering requires OpenGL ES 3. Please make sure that it's the first one listed under Graphics APIs."); public static readonly GUIContent singlepassAndroidWarning2 = EditorGUIUtility.TrTextContent("Multi Pass will be used on Android devices that don't support Single Pass."); + public static readonly GUIContent singlepassAndroidWarning3 = EditorGUIUtility.TrTextContent("When using a Scriptable Render Pipeline, Single Pass Double Wide will be used on Android devices that don't support Single Pass Instancing or Multi-view."); public static readonly GUIContent singlePassInstancedWarning = EditorGUIUtility.TrTextContent("Single Pass Instanced is only supported on Windows. Multi Pass will be used on other platforms."); + public static readonly GUIContent multiPassNotSupportedWithSRP = EditorGUIUtility.TrTextContent("Multi Pass is only supported using the legacy render pipelies. Stereo Rendering Mode is set to the fallback mode of Single Pass."); public static readonly GUIContent[] kDefaultStereoRenderingPaths = { EditorGUIUtility.TrTextContent("Multi Pass"), EditorGUIUtility.TrTextContent("Single Pass"), - EditorGUIUtility.TrTextContent("Single Pass Instanced (Preview)") + EditorGUIUtility.TrTextContent("Single Pass Instanced") }; public static readonly GUIContent[] kMultiviewStereoRenderingPaths = { EditorGUIUtility.TrTextContent("Multi Pass"), - EditorGUIUtility.TrTextContent("Single Pass Multiview or Instanced (Preview)") + EditorGUIUtility.TrTextContent("Single Pass") }; public static readonly GUIContent xrSettingsTitle = EditorGUIUtility.TrTextContent("XR Settings"); @@ -60,6 +62,7 @@ static class Styles private bool m_InstallsRequired = false; private bool m_VuforiaInstalled = false; + private bool m_ShowMultiPassSRPInfoBox = false; internal int GUISectionIndex { get; set; } @@ -305,16 +308,44 @@ private static GUIContent[] GetStereoRenderingPaths(BuildTargetGroup targetGroup return DoesBuildTargetSupportStereoMultiviewRendering(targetGroup) ? Styles.kMultiviewStereoRenderingPaths : Styles.kDefaultStereoRenderingPaths; } + private bool IsStereoRenderingModeSupported(BuildTargetGroup targetGroup, StereoRenderingPath stereoRenderingPath) + { + switch (stereoRenderingPath) + { + case StereoRenderingPath.MultiPass: + return (UnityEngine.Rendering.GraphicsSettings.renderPipelineAsset == null); + + case StereoRenderingPath.SinglePass: + return DoesBuildTargetSupportSinglePassStereoRendering(targetGroup); + + case StereoRenderingPath.Instancing: + return DoesBuildTargetSupportStereoInstancingRendering(targetGroup); + } + ; + + return false; + } + + void OnStereoModeSelected(SerializedProperty stereoRenderingPath, object userData) + { + stereoRenderingPath.intValue = (int)userData; + m_ShowMultiPassSRPInfoBox = false; + + m_Settings.serializedObject.ApplyModifiedProperties(); + } + private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedProperty stereoRenderingPath) { if (!PlayerSettings.virtualRealitySupported) return; - bool supportsSinglePass = DoesBuildTargetSupportSinglePassStereoRendering(targetGroup); - bool supportsSinglePassInstanced = DoesBuildTargetSupportStereoInstancingRendering(targetGroup); + bool supportsMultiPass = IsStereoRenderingModeSupported(targetGroup, StereoRenderingPath.MultiPass); + bool supportsSinglePass = IsStereoRenderingModeSupported(targetGroup, StereoRenderingPath.SinglePass); + bool supportsSinglePassInstanced = IsStereoRenderingModeSupported(targetGroup, StereoRenderingPath.Instancing); // populate the dropdown with the valid options based on target platform. - int validStereoRenderingOptionsCount = 1 + (supportsSinglePass ? 1 : 0) + (supportsSinglePassInstanced ? 1 : 0); + int multiPassAndSinglePass = 2; + int validStereoRenderingOptionsCount = multiPassAndSinglePass + (supportsSinglePassInstanced ? 1 : 0); var validStereoRenderingPaths = new GUIContent[validStereoRenderingOptionsCount]; var validStereoRenderingValues = new int[validStereoRenderingOptionsCount]; @@ -324,11 +355,8 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.MultiPass]; validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.MultiPass; - if (supportsSinglePass) - { - validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.SinglePass]; - validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.SinglePass; - } + validStereoRenderingPaths[addedStereoRenderingOptionsCount] = stereoRenderingPaths[(int)StereoRenderingPath.SinglePass]; + validStereoRenderingValues[addedStereoRenderingOptionsCount++] = (int)StereoRenderingPath.SinglePass; if (supportsSinglePassInstanced) { @@ -337,20 +365,56 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert } // setup fallbacks + if (!supportsMultiPass && (stereoRenderingPath.intValue == (int)StereoRenderingPath.MultiPass)) + { + stereoRenderingPath.intValue = (int)StereoRenderingPath.SinglePass; + m_ShowMultiPassSRPInfoBox = true; + } + if (!supportsSinglePassInstanced && (stereoRenderingPath.intValue == (int)StereoRenderingPath.Instancing)) stereoRenderingPath.intValue = (int)StereoRenderingPath.SinglePass; if (!supportsSinglePass && (stereoRenderingPath.intValue == (int)StereoRenderingPath.SinglePass)) stereoRenderingPath.intValue = (int)StereoRenderingPath.MultiPass; - EditorGUILayout.IntPopup(stereoRenderingPath, validStereoRenderingPaths, validStereoRenderingValues, EditorGUIUtility.TrTextContent("Stereo Rendering Mode*")); + if (m_ShowMultiPassSRPInfoBox) + EditorGUILayout.HelpBox(Styles.multiPassNotSupportedWithSRP.text, MessageType.Info); + + var rect = EditorGUILayout.GetControlRect(); + EditorGUI.BeginProperty(rect, EditorGUIUtility.TrTextContent("Stereo Rendering Mode*"), stereoRenderingPath); + rect = EditorGUI.PrefixLabel(rect, EditorGUIUtility.TrTextContent("Stereo Rendering Mode*")); + + int index = Math.Max(0, Array.IndexOf(validStereoRenderingValues, stereoRenderingPath.intValue)); + if (EditorGUI.DropdownButton(rect, validStereoRenderingPaths[index], FocusType.Passive)) + { + var menu = new GenericMenu(); + for (int i = 0; i < validStereoRenderingValues.Length; i++) + { + int value = validStereoRenderingValues[i]; + bool selected = (value == stereoRenderingPath.intValue); + + if (!IsStereoRenderingModeSupported(targetGroup, (StereoRenderingPath)value)) + menu.AddDisabledItem(validStereoRenderingPaths[i], selected); + else + menu.AddItem(validStereoRenderingPaths[i], selected, (object userData) => { OnStereoModeSelected(stereoRenderingPath, userData); }, value); + } + menu.DropDown(rect); + } + EditorGUI.EndProperty(); if ((stereoRenderingPath.intValue == (int)StereoRenderingPath.SinglePass) && (targetGroup == BuildTargetGroup.Android)) { var apisAndroid = PlayerSettings.GetGraphicsAPIs(BuildTarget.Android); if ((apisAndroid.Length > 0) && (apisAndroid[0] == GraphicsDeviceType.OpenGLES3)) { - EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning2.text, MessageType.Info); + if (supportsMultiPass) + { + EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning2.text, MessageType.Info); + } + else + { + EditorGUILayout.HelpBox(Styles.singlepassAndroidWarning3.text, MessageType.Info); + } } else { @@ -361,6 +425,8 @@ private void SinglePassStereoGUI(BuildTargetGroup targetGroup, SerializedPropert { EditorGUILayout.HelpBox(Styles.singlePassInstancedWarning.text, MessageType.Warning); } + + m_Settings.serializedObject.ApplyModifiedProperties(); } private void Stereo360CaptureGUI(BuildTargetGroup targetGroup) @@ -577,18 +643,6 @@ internal void TangoGUI(BuildTargetGroup targetGroup) // Google Tango settings EditorGUILayout.PropertyField(m_AndroidEnableTango, EditorGUIUtility.TrTextContent("ARCore Supported")); - - if (PlayerSettings.Android.ARCoreEnabled) - { - EditorGUI.indentLevel++; - - if ((int)PlayerSettings.Android.minSdkVersion < 24) - { - GUIContent tangoAndroidWarning = EditorGUIUtility.TrTextContent("ARCore requires 'Minimum API Level' to be at least Android 7.0"); - EditorGUILayout.HelpBox(tangoAndroidWarning.text, MessageType.Warning); - } - EditorGUI.indentLevel--; - } } internal void VuforiaGUI(BuildTargetGroup targetGroup) diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index 28201c667a..87358087be 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -126,6 +126,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) if (HasConflicts(entries, m_KeyCombinationSequence)) { m_ConflictResolver.ResolveConflict(m_KeyCombinationSequence, entries); + evt.Use(); Reset(); } break; diff --git a/Modules/Terrain/Public/BrushTransform.cs b/Modules/Terrain/Public/BrushTransform.cs new file mode 100644 index 0000000000..229d3b07ea --- /dev/null +++ b/Modules/Terrain/Public/BrushTransform.cs @@ -0,0 +1,80 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using UnityEngine.Rendering; + +namespace UnityEngine.Experimental.TerrainAPI +{ + // represents a linear 2D transform between brush UV space and some other target XY space + // xy = u * brushU + v * brushV + brushOrigin + // uv = x * targetX + y * targetY + targetOrigin + public struct BrushTransform + { + public Vector2 brushOrigin { get; } // brush UV origin, in XY space + public Vector2 brushU { get; } // brush U vector, in XY space + public Vector2 brushV { get; } // brush V vector, in XY space + + public Vector2 targetOrigin { get; } // XY origin, in brush UV space + public Vector2 targetX { get; } // X vector, in brush UV space + public Vector2 targetY { get; } // Y vector, in brush UV space + + public BrushTransform(Vector2 brushOrigin, Vector2 brushU, Vector2 brushV) + { + // invert the rotation matrix [BrushU, BrushV] + // this gives us [X, Y] vectors in brush UV space + // note we run the true inverse, to support non-orthogonal brush axes + float det = brushU.x * brushV.y - brushU.y * brushV.x; + float invDet = Mathf.Approximately(det, 0.0f) ? 1.0f : 1.0f / det; // for non-invert-able matrices, we do 'something' + Vector2 targetX = new Vector2(brushV.y, -brushU.y) * invDet; + Vector2 targetY = new Vector2(-brushV.x, brushU.x) * invDet; + + // calculate XY origin in brush UV space + Vector2 targetOrigin = -brushOrigin.x * targetX - brushOrigin.y * targetY; + + this.brushOrigin = brushOrigin; + this.brushU = brushU; + this.brushV = brushV; + this.targetOrigin = targetOrigin; + this.targetX = targetX; + this.targetY = targetY; + } + + public Rect GetBrushXYBounds() // get the XY bounding rectangle around the Brush [0,1] UV space + { + // compute all four corners of the brush [0,1] UV space + Vector2 pU = brushOrigin + brushU; + Vector2 pV = brushOrigin + brushV; + Vector2 pUV = brushOrigin + brushU + brushV; + + // compute min and max XY coordinates + float minX = Mathf.Min(Mathf.Min(brushOrigin.x, pU.x), Mathf.Min(pV.x, pUV.x)); + float maxX = Mathf.Max(Mathf.Max(brushOrigin.x, pU.x), Mathf.Max(pV.x, pUV.x)); + float minY = Mathf.Min(Mathf.Min(brushOrigin.y, pU.y), Mathf.Min(pV.y, pUV.y)); + float maxY = Mathf.Max(Mathf.Max(brushOrigin.y, pU.y), Mathf.Max(pV.y, pUV.y)); + + // return the XY bounding rectangle + return Rect.MinMaxRect(minX, minY, maxX, maxY); + } + + public static BrushTransform FromRect(Rect brushRect) + { + Vector2 brushOrigin = brushRect.min; + Vector2 brushU = new Vector2(brushRect.width, 0.0f); + Vector2 brushV = new Vector2(0.0f, brushRect.height); + return new BrushTransform(brushOrigin, brushU, brushV); + } + + public Vector2 ToBrushUV(Vector2 targetXY) + { + return targetXY.x * targetX + targetXY.y * targetY + targetOrigin; + } + + public Vector2 FromBrushUV(Vector2 brushUV) + { + return brushUV.x * brushU + brushUV.y * brushV + brushOrigin; + } + } +} diff --git a/Modules/Terrain/Public/PaintContext.cs b/Modules/Terrain/Public/PaintContext.cs new file mode 100644 index 0000000000..f85775e442 --- /dev/null +++ b/Modules/Terrain/Public/PaintContext.cs @@ -0,0 +1,632 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using UnityEngine.Rendering; + +namespace UnityEngine.Experimental.TerrainAPI +{ + public class PaintContext + { + // initialized by constructor + public Terrain originTerrain { get; } // the terrain that defines the coordinate system and world space position of this PaintContext + public RectInt pixelRect { get; } // the rectangle, in target texture pixels on the originTerrain, that this paint context represents + public int targetTextureWidth { get; } // the size of the target texture, per terrain tile + public int targetTextureHeight { get; } // the size of the target texture, per terrain tile + public Vector2 pixelSize { get; } // size of a paint context pixel in object/terrain/world space + + // initialized by CreateRenderTargets() + public RenderTexture sourceRenderTexture { get { return m_SourceRenderTexture; } } // the original data + public RenderTexture destinationRenderTexture { get { return m_DestinationRenderTexture; } } // the modified data (you render to this) + public RenderTexture oldRenderTexture { get { return m_OldRenderTexture; } } // active render texture at the time CreateRenderTargets() is called, restored on Cleanup() + + public int terrainCount { get { return m_TerrainTiles.Count; } } + public Terrain GetTerrain(int terrainIndex) + { + return m_TerrainTiles[terrainIndex].terrain; + } + + public RectInt GetClippedPixelRectInTerrainPixels(int terrainIndex) + { + return m_TerrainTiles[terrainIndex].clippedLocal; + } + + public RectInt GetClippedPixelRectInRenderTexturePixels(int terrainIndex) + { + Rect vp = m_TerrainTiles[terrainIndex].validPaintRect; + return new RectInt( + Mathf.RoundToInt(vp.xMin), + Mathf.RoundToInt(vp.yMin), + Mathf.RoundToInt(vp.width), + Mathf.RoundToInt(vp.height)); + } + + // initialized by constructor + private List m_TerrainTiles; // all terrain tiles touched by this paint context + + // initialized by CreateRenderTargets() + private RenderTexture m_SourceRenderTexture; + private RenderTexture m_DestinationRenderTexture; + private RenderTexture m_OldRenderTexture; + + internal class TerrainTile + { + public TerrainTile() {} + public TerrainTile(Terrain newTerrain, RectInt newRegion) { rect = newRegion; terrain = newTerrain; } + + public Terrain terrain; // the terrain object + public RectInt rect; // coordinates of this terrain tile in paint context pixels (essentially originTerrain target texture pixels) + public RectInt clippedLocal; // pixelRect in local pixel coordinates (for target texture), clipped to the local tile + public Rect validPaintRect; // the area per tile where the source texture was able to read from (in paint context pixels) + public int mapIndex; // + public int channelIndex; // + + // offsets used for gather / scatter + public Vector2Int readOffset; // offsets used when reading from the terrain heightmap + public Vector2Int writeOffset; // offsets used when copying from PaintContext clipped heightmap back to the terrain heightmap + } + + [Flags] + internal enum ToolAction + { + None = 0, + PaintHeightmap = 1 << 0, + PaintTexture = 1 << 1, + } + + // TerrainPaintUtilityEditor hooks to this event to do automatic undo + internal static event Action onTerrainTileBeforePaint; + + public PaintContext(Terrain terrain, RectInt pixelRect, int targetTextureWidth, int targetTextureHeight) + { + this.originTerrain = terrain; + this.pixelRect = pixelRect; + this.targetTextureWidth = targetTextureWidth; + this.targetTextureHeight = targetTextureHeight; + TerrainData terrainData = terrain.terrainData; + this.pixelSize = new Vector2( + terrainData.size.x / (targetTextureWidth - 1.0f), + terrainData.size.z / (targetTextureHeight - 1.0f)); + + FindTerrainTiles(); + ClipTerrainTiles(); + } + + public static PaintContext CreateFromBounds(Terrain terrain, Rect boundsInTerrainSpace, int inputTextureWidth, int inputTextureHeight, int extraBorderPixels = 0) + { + return new PaintContext( + terrain, + TerrainPaintUtility.CalcPixelRectFromBounds(terrain, boundsInTerrainSpace, inputTextureWidth, inputTextureHeight, extraBorderPixels), + inputTextureWidth, inputTextureHeight); + } + + internal void FindTerrainTiles() + { + m_TerrainTiles = new List(); + + Terrain left = originTerrain.leftNeighbor; + Terrain right = originTerrain.rightNeighbor; + Terrain top = originTerrain.topNeighbor; + Terrain bottom = originTerrain.bottomNeighbor; + + bool wantLeft = (pixelRect.x < 0); + bool wantRight = (pixelRect.xMax > (targetTextureWidth - 1)); + bool wantTop = (pixelRect.yMax > (targetTextureHeight - 1)); + bool wantBottom = (pixelRect.y < 0); + + if (wantLeft && wantRight) + { + Debug.LogWarning("PaintContext pixelRect is too large! It should touch a maximum of 2 Terrains horizontally."); + wantRight = false; + } + + if (wantTop && wantBottom) + { + Debug.LogWarning("PaintContext pixelRect is too large! It should touch a maximum of 2 Terrains vertically."); + wantBottom = false; + } + + // add center tile + TerrainTile tile = new TerrainTile(originTerrain, new RectInt(0, 0, targetTextureWidth, targetTextureHeight)); + tile.readOffset = Vector2Int.zero; + tile.writeOffset = Vector2Int.zero; + m_TerrainTiles.Add(tile); + + // add horizontal and vertical neighbors + Terrain horiz = null; + Terrain vert = null; + Terrain cornerTerrain = null; + + int xBias = 0; + int yBias = 0; + int xReadBias = 0; + int yReadBias = 0; + int xWriteBias = 0; + int yWriteBias = 0; + + if (wantLeft) + { + xBias = -1; + xReadBias = -1; + xWriteBias = 1; + horiz = left; + } + else if (wantRight) + { + xBias = 1; + xReadBias = 1; + xWriteBias = -1; + horiz = right; + } + + if (wantTop) + { + yBias = 1; + yReadBias = 1; + yWriteBias = -1; + vert = top; + } + else if (wantBottom) + { + yBias = -1; + yReadBias = -1; + yWriteBias = 1; + vert = bottom; + } + + if (horiz) + { + tile = new TerrainTile(horiz, new RectInt(xBias * targetTextureWidth, 0, targetTextureWidth, targetTextureHeight)); + tile.readOffset = new Vector2Int(xReadBias, 0); + tile.writeOffset = new Vector2Int(xWriteBias, 0); + m_TerrainTiles.Add(tile); + + // add corner, if we have a link + if (wantTop && horiz.topNeighbor) + cornerTerrain = horiz.topNeighbor; + else if (wantBottom && horiz.bottomNeighbor) + cornerTerrain = horiz.bottomNeighbor; + } + + if (vert) + { + tile = new PaintContext.TerrainTile(vert, new RectInt(0, yBias * targetTextureHeight, targetTextureWidth, targetTextureHeight)); + tile.readOffset = new Vector2Int(0, yReadBias); + tile.writeOffset = new Vector2Int(0, yWriteBias); + m_TerrainTiles.Add(tile); + + // add corner, if we have a link + if (wantLeft && vert.leftNeighbor) + cornerTerrain = vert.leftNeighbor; + else if (wantRight && vert.rightNeighbor) + cornerTerrain = vert.rightNeighbor; + } + + if (cornerTerrain != null) + { + tile = new TerrainTile(cornerTerrain, new RectInt(xBias * targetTextureWidth, yBias * targetTextureHeight, targetTextureWidth, targetTextureHeight)); + tile.readOffset = new Vector2Int(xReadBias, yReadBias); + tile.writeOffset = new Vector2Int(xWriteBias, yWriteBias); + m_TerrainTiles.Add(tile); + } + } + + internal void ClipTerrainTiles() + { + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile tile = m_TerrainTiles[i]; + tile.clippedLocal = new RectInt(); + tile.clippedLocal.x = Mathf.Max(0, pixelRect.x - tile.rect.x); + tile.clippedLocal.y = Mathf.Max(0, pixelRect.y - tile.rect.y); + tile.clippedLocal.xMax = Mathf.Min(tile.rect.width, pixelRect.xMax - tile.rect.x); + tile.clippedLocal.yMax = Mathf.Min(tile.rect.height, pixelRect.yMax - tile.rect.y); + + tile.validPaintRect = new Rect( + tile.clippedLocal.x + tile.rect.x - pixelRect.x, + tile.clippedLocal.y + tile.rect.y - pixelRect.y, + tile.clippedLocal.width, + tile.clippedLocal.height); + } + } + + public void CreateRenderTargets(RenderTextureFormat colorFormat) + { + m_SourceRenderTexture = RenderTexture.GetTemporary(pixelRect.width, pixelRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); + m_DestinationRenderTexture = RenderTexture.GetTemporary(pixelRect.width, pixelRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); + m_SourceRenderTexture.wrapMode = TextureWrapMode.Clamp; + m_SourceRenderTexture.filterMode = FilterMode.Point; + m_OldRenderTexture = RenderTexture.active; + } + + public void Cleanup(bool restoreRenderTexture = true) + { + if (restoreRenderTexture) + { + RenderTexture.active = m_OldRenderTexture; + } + RenderTexture.ReleaseTemporary(m_SourceRenderTexture); + RenderTexture.ReleaseTemporary(m_DestinationRenderTexture); + m_SourceRenderTexture = null; + m_DestinationRenderTexture = null; + m_OldRenderTexture = null; + } + + public void GatherHeightmap() + { + Material blitMaterial = TerrainPaintUtility.GetBlitMaterial(); + + RenderTexture.active = sourceRenderTexture; + GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f)); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + Texture sourceTexture = terrainTile.terrain.terrainData.heightmapTexture; + if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext heightmap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, + (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, + (terrainTile.clippedLocal.width) / (float)targetTextureWidth, + (terrainTile.clippedLocal.height) / (float)targetTextureHeight); + + FilterMode oldFilterMode = sourceTexture.filterMode; + + sourceTexture.filterMode = FilterMode.Point; + + blitMaterial.SetTexture("_MainTex", sourceTexture); + blitMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + + sourceTexture.filterMode = oldFilterMode; + } + + RenderTexture.active = oldRenderTexture; + } + + public void ScatterHeightmap(string editorUndoName) + { + Material blitMaterial = TerrainPaintUtility.GetBlitMaterial(); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + RenderTexture heightmap = terrainTile.terrain.terrainData.heightmapTexture; + if ((heightmap.width != targetTextureWidth) || (heightmap.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext heightmap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + if (onTerrainTileBeforePaint != null) + onTerrainTileBeforePaint(terrainTile, ToolAction.PaintHeightmap, editorUndoName); + + RenderTexture.active = heightmap; + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.rect.x - pixelRect.x + terrainTile.writeOffset.x) / (float)pixelRect.width, + (terrainTile.clippedLocal.y + terrainTile.rect.y - pixelRect.y + terrainTile.writeOffset.y) / (float)pixelRect.height, + (terrainTile.clippedLocal.width) / (float)pixelRect.width, + (terrainTile.clippedLocal.height) / (float)pixelRect.height); + + Rect writeRect = new Rect( + terrainTile.clippedLocal.x, + terrainTile.clippedLocal.y, + terrainTile.clippedLocal.width, + terrainTile.clippedLocal.height); + + destinationRenderTexture.filterMode = FilterMode.Point; + + blitMaterial.SetTexture("_MainTex", destinationRenderTexture); + blitMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(heightmap.width, heightmap.height, readRect, writeRect); + + terrainTile.terrain.terrainData.UpdateDirtyRegion(terrainTile.clippedLocal.x, terrainTile.clippedLocal.y, terrainTile.clippedLocal.width, terrainTile.clippedLocal.height, !terrainTile.terrain.drawInstanced); + OnTerrainPainted(terrainTile, ToolAction.PaintHeightmap); + } + } + + public void GatherNormals() + { + RenderTexture rt = originTerrain.normalmapTexture; + + Material blitMaterial = TerrainPaintUtility.GetBlitMaterial(); + + RenderTexture.active = sourceRenderTexture; + GL.Clear(false, true, new Color(0.5f, 0.5f, 0.5f, 0.5f)); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + Texture sourceTexture = terrainTile.terrain.normalmapTexture; + if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext normalmap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, + (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, + (terrainTile.clippedLocal.width) / (float)targetTextureWidth, + (terrainTile.clippedLocal.height) / (float)targetTextureHeight); + + FilterMode oldFilterMode = sourceTexture.filterMode; + + sourceTexture.filterMode = FilterMode.Point; + + blitMaterial.SetTexture("_MainTex", sourceTexture); + blitMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + + sourceTexture.filterMode = oldFilterMode; + } + + RenderTexture.active = oldRenderTexture; + } + + public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = true) + { + if (inputLayer == null) + return; + + int terrainLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(originTerrain, inputLayer); + if (terrainLayerIndex == -1 && addLayerIfDoesntExist) + terrainLayerIndex = TerrainPaintUtility.AddTerrainLayer(originTerrain, inputLayer); + + RenderTexture.active = sourceRenderTexture; + GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f)); + + Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; + + Material copyTerrainLayerMaterial = TerrainPaintUtility.GetCopyTerrainLayerMaterial(); + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + Rect readRect = new Rect( + (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, + (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, + (terrainTile.clippedLocal.width) / (float)targetTextureWidth, + (terrainTile.clippedLocal.height) / (float)targetTextureHeight); + + int tileLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(terrainTile.terrain, inputLayer); + if (tileLayerIndex == -1) + { + if (!addLayerIfDoesntExist) + { + // setting these to zero will prevent them from being used later + terrainTile.clippedLocal.width = 0; + terrainTile.clippedLocal.height = 0; + terrainTile.validPaintRect.width = 0; + terrainTile.validPaintRect.height = 0; + continue; + } + tileLayerIndex = TerrainPaintUtility.AddTerrainLayer(terrainTile.terrain, inputLayer); + } + + terrainTile.mapIndex = tileLayerIndex >> 2; + terrainTile.channelIndex = tileLayerIndex & 0x3; + + Texture sourceTexture = TerrainPaintUtility.GetTerrainAlphaMapChecked(terrainTile.terrain, terrainTile.mapIndex); + if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + FilterMode oldFilterMode = sourceTexture.filterMode; + sourceTexture.filterMode = FilterMode.Point; + + copyTerrainLayerMaterial.SetVector("_LayerMask", layerMasks[terrainTile.channelIndex]); + copyTerrainLayerMaterial.SetTexture("_MainTex", sourceTexture); + copyTerrainLayerMaterial.SetPass(0); + + TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + + sourceTexture.filterMode = oldFilterMode; + } + + RenderTexture.active = oldRenderTexture; + } + + public void ScatterAlphamap(string editorUndoName) + { + Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; + + Material copyTerrainLayerMaterial = TerrainPaintUtility.GetCopyTerrainLayerMaterial(); + + for (int i = 0; i < m_TerrainTiles.Count; i++) + { + TerrainTile terrainTile = m_TerrainTiles[i]; + if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + continue; + + if (onTerrainTileBeforePaint != null) + onTerrainTileBeforePaint(terrainTile, ToolAction.PaintTexture, editorUndoName); + + var rtdesc = new RenderTextureDescriptor(destinationRenderTexture.width, destinationRenderTexture.height, RenderTextureFormat.ARGB32); + rtdesc.sRGB = false; + rtdesc.useMipMap = false; + rtdesc.autoGenerateMips = false; + RenderTexture destTarget = RenderTexture.GetTemporary(rtdesc); + RenderTexture.active = destTarget; + + var writeRect = new RectInt( + terrainTile.clippedLocal.x + terrainTile.rect.x - pixelRect.x + terrainTile.writeOffset.x, + terrainTile.clippedLocal.y + terrainTile.rect.y - pixelRect.y + terrainTile.writeOffset.y, + terrainTile.clippedLocal.width, + terrainTile.clippedLocal.height); + + var readRect = new Rect( + writeRect.x / (float)pixelRect.width, + writeRect.y / (float)pixelRect.height, + writeRect.width / (float)pixelRect.width, + writeRect.height / (float)pixelRect.height); + + destinationRenderTexture.filterMode = FilterMode.Point; + + for (int j = 0; j < terrainTile.terrain.terrainData.alphamapTextureCount; j++) + { + Texture2D sourceTex = terrainTile.terrain.terrainData.alphamapTextures[j]; + if ((sourceTex.width != targetTextureWidth) || (sourceTex.height != targetTextureHeight)) + { + Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + continue; + } + + int mapIndex = terrainTile.mapIndex; + int channelIndex = terrainTile.channelIndex; + + Rect combineRect = new Rect( + terrainTile.clippedLocal.x / (float)sourceTex.width, + terrainTile.clippedLocal.y / (float)sourceTex.height, + terrainTile.clippedLocal.width / (float)sourceTex.width, + terrainTile.clippedLocal.height / (float)sourceTex.height); + + copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture); + copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture); + copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", sourceTex); + copyTerrainLayerMaterial.SetVector("_LayerMask", j == mapIndex ? layerMasks[channelIndex] : Vector4.zero); + copyTerrainLayerMaterial.SetPass(1); + + GL.PushMatrix(); + GL.LoadOrtho(); + GL.LoadPixelMatrix(0, destTarget.width, 0, destTarget.height); + + GL.Begin(GL.QUADS); + GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f)); + + GL.MultiTexCoord2(0, readRect.x, readRect.y); + GL.MultiTexCoord2(1, combineRect.x, combineRect.y); + GL.Vertex3(writeRect.x, writeRect.y, 0.0f); + GL.MultiTexCoord2(0, readRect.x, readRect.yMax); + GL.MultiTexCoord2(1, combineRect.x, combineRect.yMax); + GL.Vertex3(writeRect.x, writeRect.yMax, 0.0f); + GL.MultiTexCoord2(0, readRect.xMax, readRect.yMax); + GL.MultiTexCoord2(1, combineRect.xMax, combineRect.yMax); + GL.Vertex3(writeRect.xMax, writeRect.yMax, 0.0f); + GL.MultiTexCoord2(0, readRect.xMax, readRect.y); + GL.MultiTexCoord2(1, combineRect.xMax, combineRect.y); + GL.Vertex3(writeRect.xMax, writeRect.y, 0.0f); + + GL.End(); + GL.PopMatrix(); + + if (TerrainPaintUtility.paintTextureUsesCopyTexture) + { + var rtdesc2 = new RenderTextureDescriptor(sourceTex.width, sourceTex.height, RenderTextureFormat.ARGB32); + rtdesc2.sRGB = false; + rtdesc2.useMipMap = true; + rtdesc2.autoGenerateMips = false; + var mips = RenderTexture.GetTemporary(rtdesc2); + if (!mips.IsCreated()) + mips.Create(); + + // Composes mip0 in a RT with full mipchain. + Graphics.CopyTexture(sourceTex, 0, 0, mips, 0, 0); + Graphics.CopyTexture(destTarget, 0, 0, writeRect.x, writeRect.y, writeRect.width, writeRect.height, mips, 0, 0, terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + mips.GenerateMips(); + + // Copy them into sourceTex. + Graphics.CopyTexture(mips, sourceTex); + + RenderTexture.ReleaseTemporary(mips); + } + else + { + GraphicsDeviceType deviceType = SystemInfo.graphicsDeviceType; + if (deviceType == GraphicsDeviceType.Metal || deviceType == GraphicsDeviceType.OpenGLCore) + sourceTex.ReadPixels(new Rect(writeRect.x, writeRect.y, writeRect.width, writeRect.height), terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + else + sourceTex.ReadPixels(new Rect(writeRect.x, destTarget.height - writeRect.y - writeRect.height, writeRect.width, writeRect.height), terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + sourceTex.Apply(); + } + } + + RenderTexture.active = null; + RenderTexture.ReleaseTemporary(destTarget); + + OnTerrainPainted(terrainTile, ToolAction.PaintTexture); + } + } + + // Collects modified terrain so that we can update some deferred operations at the mouse up event + private class PaintedTerrain + { + public Terrain terrain; + public ToolAction action; + }; + private static List s_PaintedTerrain = new List(); + + private static void OnTerrainPainted(PaintContext.TerrainTile tile, ToolAction action) + { + for (int i = 0; i < s_PaintedTerrain.Count; ++i) + { + if (tile.terrain == s_PaintedTerrain[i].terrain) + { + s_PaintedTerrain[i].action |= action; + return; + } + } + s_PaintedTerrain.Add(new PaintedTerrain { terrain = tile.terrain, action = action }); + } + + public static void ApplyDelayedActions() + { + for (int i = 0; i < s_PaintedTerrain.Count; ++i) + { + var pt = s_PaintedTerrain[i]; + if ((pt.action & ToolAction.PaintHeightmap) != 0) + { + pt.terrain.ApplyDelayedHeightmapModification(); + } + if ((pt.action & ToolAction.PaintTexture) != 0) + { + var terrainData = pt.terrain.terrainData; + if (terrainData == null) + continue; + terrainData.SetBaseMapDirty(); + if (TerrainPaintUtility.paintTextureUsesCopyTexture) + { + // pull the data from GPU to CPU + var rtdesc = new RenderTextureDescriptor(terrainData.alphamapResolution, terrainData.alphamapResolution, RenderTextureFormat.ARGB32); + rtdesc.sRGB = false; + rtdesc.useMipMap = false; + rtdesc.autoGenerateMips = false; + RenderTexture tmp = RenderTexture.GetTemporary(rtdesc); + for (int c = 0; c < terrainData.alphamapTextureCount; ++c) + { + Graphics.Blit(terrainData.alphamapTextures[c], tmp); + terrainData.alphamapTextures[c].ReadPixels(new Rect(0, 0, rtdesc.width, rtdesc.height), 0, 0, true); + } + RenderTexture.ReleaseTemporary(tmp); + } + } + } + + s_PaintedTerrain.Clear(); + } + } +} diff --git a/Modules/Terrain/Public/TerrainPaintUtility.cs b/Modules/Terrain/Public/TerrainPaintUtility.cs index 2089699697..a2d752a116 100644 --- a/Modules/Terrain/Public/TerrainPaintUtility.cs +++ b/Modules/Terrain/Public/TerrainPaintUtility.cs @@ -27,390 +27,96 @@ public static Material GetBuiltinPaintMaterial() return s_BuiltinPaintMaterial; } - public class TerrainTile + // returns a transform from terrain space to brush UV + public static BrushTransform CalculateBrushTransform( + Terrain terrain, Vector2 brushCenterTerrainUV, float brushSize, float brushRotationDegrees) { - public TerrainTile() { terrain = null; } - public TerrainTile(Terrain newTerrain, RectInt newRegion) { rect = newRegion; terrain = newTerrain; } - public Terrain terrain; - public RectInt rect; // pixel coordinates of this terrain tile in the paint context (a locally built space relative to the active 'center' tile) + float rotationRadians = brushRotationDegrees * Mathf.Deg2Rad; + float cos = Mathf.Cos(rotationRadians); + float sin = Mathf.Sin(rotationRadians); + Vector2 brushU = new Vector2(cos, -sin) * brushSize; + Vector2 brushV = new Vector2(sin, cos) * brushSize; - public int mapIndex; - public int channelIndex; + // calculate brush origin + Vector3 terrainSize = terrain.terrainData.size; + Vector2 brushCenterTerrainSpace = brushCenterTerrainUV * new Vector2(terrainSize.x, terrainSize.z); + Vector2 brushOrigin = brushCenterTerrainSpace - 0.5f * brushU - 0.5f * brushV; - // offsets used for gather / scatter - public Vector2Int readOffset; // offsets used when reading from the terrain heightmap - public Vector2Int writeOffset; // offsets used when copying from PaintContext clipped heightmap back to the terrain heightmap + BrushTransform xform = new BrushTransform(brushOrigin, brushU, brushV); + return xform; } - public class PaintContext + public static void BuildTransformPaintContextUVToPaintContextUV(PaintContext src, PaintContext dst, out Vector4 scaleOffset) { - public RectInt brushRect; // the rectangle represented by this paint context, in target texture pixels (for the active terrain tile) - public TerrainTile[] terrainTiles; // all terrain tiles touched by this paint context - public RectInt[] clippedTiles; // the intersection of brushRect with each of the terrain tiles above, clipped into local tile pixels - public Rect[] validPaintRects; // the area per tile where the source texture was able to read from - - public RenderTexture sourceRenderTexture; - public RenderTexture destinationRenderTexture; - - public RenderTexture oldRenderTexture; // active render texture before PaintContext was initialized - - - public void CalculateBrushRect(Terrain terrain, Rect bounds, int inputTextureWidth, int inputTextureHeight) - { - brushRect = CalcBrushRectInPixels(terrain, bounds, inputTextureWidth, inputTextureHeight); - } - - public void CreateTerrainTiles(Terrain terrain, int inputTextureWidth, int inputTextureHeight) - { - terrainTiles = FindTerrainTiles(terrain, inputTextureWidth, inputTextureHeight, brushRect); - clippedTiles = ClipTerrainTiles(terrainTiles, brushRect); - validPaintRects = new Rect[terrainTiles.Length]; - - for (int i = 0; i < terrainTiles.Length; ++i) - { - TerrainTile terrainTile = terrainTiles[i]; - validPaintRects[i] = new Rect( - clippedTiles[i].x + terrainTile.rect.x - brushRect.x, - clippedTiles[i].y + terrainTile.rect.y - brushRect.y, - clippedTiles[i].width, - clippedTiles[i].height); - } - } - - public void CreateRenderTargets(RenderTextureFormat colorFormat) - { - sourceRenderTexture = RenderTexture.GetTemporary(brushRect.width, brushRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); - destinationRenderTexture = RenderTexture.GetTemporary(brushRect.width, brushRect.height, 0, colorFormat, RenderTextureReadWrite.Linear); - sourceRenderTexture.wrapMode = TextureWrapMode.Clamp; - sourceRenderTexture.filterMode = FilterMode.Point; - oldRenderTexture = RenderTexture.active; - } - - public void Cleanup() - { - RenderTexture.active = oldRenderTexture; - RenderTexture.ReleaseTemporary(sourceRenderTexture); - RenderTexture.ReleaseTemporary(destinationRenderTexture); - sourceRenderTexture = null; - destinationRenderTexture = null; - oldRenderTexture = null; - } - - public void GatherHeightmap(Terrain terrain) - { - RenderTexture rt = terrain.terrainData.heightmapTexture; - int heightmapWidth = rt.width; - int heightmapHeight = rt.height; - - Material blitMaterial = GetBlitMaterial(); - - RenderTexture.active = sourceRenderTexture; - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.readOffset.x) / (float)heightmapWidth, - (clippedTiles[i].y + terrainTile.readOffset.y) / (float)heightmapHeight, - (clippedTiles[i].width) / (float)heightmapWidth, - (clippedTiles[i].height) / (float)heightmapHeight); - - Texture sourceTexture = terrainTile.terrain.terrainData.heightmapTexture; - FilterMode oldFilterMode = sourceTexture.filterMode; - - sourceTexture.filterMode = FilterMode.Point; - - blitMaterial.SetTexture("_MainTex", sourceTexture); - blitMaterial.SetPass(0); - - DrawQuad(brushRect.width, brushRect.height, readRect, validPaintRects[i]); - - sourceTexture.filterMode = oldFilterMode; - } - - RenderTexture.active = oldRenderTexture; - } - - public void ScatterHeightmap(string editorUndoName) - { - Material blitMaterial = GetBlitMaterial(); - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - if (onTerrainTileBeforePaint != null) - onTerrainTileBeforePaint(terrainTile, ToolAction.PaintHeightmap, editorUndoName); - - RenderTexture heightmap = terrainTile.terrain.terrainData.heightmapTexture; - RenderTexture.active = heightmap; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.rect.x - brushRect.x + terrainTile.writeOffset.x) / (float)brushRect.width, - (clippedTiles[i].y + terrainTile.rect.y - brushRect.y + terrainTile.writeOffset.y) / (float)brushRect.height, - (clippedTiles[i].width) / (float)brushRect.width, - (clippedTiles[i].height) / (float)brushRect.height); - - Rect writeRect = new Rect( - clippedTiles[i].x, - clippedTiles[i].y, - clippedTiles[i].width, - clippedTiles[i].height); - - destinationRenderTexture.filterMode = FilterMode.Point; - - blitMaterial.SetTexture("_MainTex", destinationRenderTexture); - blitMaterial.SetPass(0); - - DrawQuad(heightmap.width, heightmap.height, readRect, writeRect); - - terrainTile.terrain.terrainData.UpdateDirtyRegion(clippedTiles[i].x, clippedTiles[i].y, clippedTiles[i].width, clippedTiles[i].height, !terrainTile.terrain.drawInstanced); - OnTerrainPainted(terrainTile, ToolAction.PaintHeightmap); - } - } - - public void GatherNormals(Terrain terrain) - { - RenderTexture rt = terrain.normalmapTexture; - - RenderTextureFormat colorFormat = rt.format; - int heightmapWidth = rt.width; - int heightmapHeight = rt.height; - - Material blitMaterial = GetBlitMaterial(); - - RenderTexture.active = sourceRenderTexture; - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.readOffset.x) / (float)heightmapWidth, - (clippedTiles[i].y + terrainTile.readOffset.y) / (float)heightmapHeight, - (clippedTiles[i].width) / (float)heightmapWidth, - (clippedTiles[i].height) / (float)heightmapHeight); - - Texture sourceTexture = terrainTile.terrain.normalmapTexture; - FilterMode oldFilterMode = sourceTexture.filterMode; - - sourceTexture.filterMode = FilterMode.Point; - - blitMaterial.SetTexture("_MainTex", sourceTexture); - blitMaterial.SetPass(0); - - DrawQuad(brushRect.width, brushRect.height, readRect, validPaintRects[i]); - - sourceTexture.filterMode = oldFilterMode; - } - - RenderTexture.active = oldRenderTexture; - } - - public void GatherAlphamap(Terrain terrain, TerrainLayer inputLayer, bool addLayerIfDoesntExist = true) - { - if (inputLayer == null) - return; - - int terrainLayerIndex = FindTerrainLayerIndex(terrain, inputLayer); - if (terrainLayerIndex == -1 && addLayerIfDoesntExist) - terrainLayerIndex = AddTerrainLayer(terrain, inputLayer); - - Texture2D inputTexture = GetTerrainAlphaMapChecked(terrain, terrainLayerIndex >> 2); - - int inputTextureWidth = inputTexture.width; - int inputTextureHeight = inputTexture.height; - - RenderTexture.active = sourceRenderTexture; - - Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; - - Material copyTerrainLayerMaterial = GetCopyTerrainLayerMaterial(); - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - Rect readRect = new Rect( - (clippedTiles[i].x + terrainTile.readOffset.x) / (float)inputTextureWidth, - (clippedTiles[i].y + terrainTile.readOffset.y) / (float)inputTextureHeight, - (clippedTiles[i].width) / (float)inputTextureWidth, - (clippedTiles[i].height) / (float)inputTextureHeight); - - int tileLayerIndex = FindTerrainLayerIndex(terrainTile.terrain, inputLayer); - if (tileLayerIndex == -1) - { - if (!addLayerIfDoesntExist) - { - // setting these to zero will prevent them from being used later - clippedTiles[i].width = 0; - clippedTiles[i].height = 0; - validPaintRects[i].width = 0; - validPaintRects[i].height = 0; - continue; - } - tileLayerIndex = AddTerrainLayer(terrainTile.terrain, inputLayer); - } - - terrainTile.mapIndex = tileLayerIndex >> 2; - terrainTile.channelIndex = tileLayerIndex & 0x3; - - Texture sourceTexture = GetTerrainAlphaMapChecked(terrainTile.terrain, terrainTile.mapIndex); - - FilterMode oldFilterMode = sourceTexture.filterMode; - sourceTexture.filterMode = FilterMode.Point; - - copyTerrainLayerMaterial.SetVector("_LayerMask", layerMasks[terrainTile.channelIndex]); - copyTerrainLayerMaterial.SetTexture("_MainTex", sourceTexture); - copyTerrainLayerMaterial.SetPass(0); - - DrawQuad(brushRect.width, brushRect.height, readRect, validPaintRects[i]); - - sourceTexture.filterMode = oldFilterMode; - } - - RenderTexture.active = oldRenderTexture; - } - - public void ScatterAlphamap(string editorUndoName) - { - Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; - - Material copyTerrainLayerMaterial = GetCopyTerrainLayerMaterial(); - - for (int i = 0; i < terrainTiles.Length; i++) - { - if (clippedTiles[i].width == 0 || clippedTiles[i].height == 0) - continue; - - TerrainTile terrainTile = terrainTiles[i]; - - if (onTerrainTileBeforePaint != null) - onTerrainTileBeforePaint(terrainTile, ToolAction.PaintTexture, editorUndoName); - - var rtdesc = new RenderTextureDescriptor(destinationRenderTexture.width, destinationRenderTexture.height, RenderTextureFormat.ARGB32); - rtdesc.sRGB = false; - rtdesc.useMipMap = false; - rtdesc.autoGenerateMips = false; - RenderTexture destTarget = RenderTexture.GetTemporary(rtdesc); - RenderTexture.active = destTarget; - - var writeRect = new RectInt( - clippedTiles[i].x + terrainTile.rect.x - brushRect.x + terrainTile.writeOffset.x, - clippedTiles[i].y + terrainTile.rect.y - brushRect.y + terrainTile.writeOffset.y, - clippedTiles[i].width, - clippedTiles[i].height); - - var readRect = new Rect( - writeRect.x / (float)brushRect.width, - writeRect.y / (float)brushRect.height, - writeRect.width / (float)brushRect.width, - writeRect.height / (float)brushRect.height); - - destinationRenderTexture.filterMode = FilterMode.Point; - - for (int j = 0; j < terrainTile.terrain.terrainData.alphamapTextureCount; j++) - { - Texture2D sourceTex = terrainTile.terrain.terrainData.alphamapTextures[j]; - - int mapIndex = terrainTile.mapIndex; - int channelIndex = terrainTile.channelIndex; - - Rect combineRect = new Rect( - clippedTiles[i].x / (float)sourceTex.width, - clippedTiles[i].y / (float)sourceTex.height, - clippedTiles[i].width / (float)sourceTex.width, - clippedTiles[i].height / (float)sourceTex.height); - - copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture); - copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture); - copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", sourceTex); - copyTerrainLayerMaterial.SetVector("_LayerMask", j == mapIndex ? layerMasks[channelIndex] : Vector4.zero); - copyTerrainLayerMaterial.SetPass(1); - - GL.PushMatrix(); - GL.LoadOrtho(); - GL.LoadPixelMatrix(0, destTarget.width, 0, destTarget.height); - - GL.Begin(GL.QUADS); - GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f)); - - GL.MultiTexCoord2(0, readRect.x, readRect.y); - GL.MultiTexCoord2(1, combineRect.x, combineRect.y); - GL.Vertex3(writeRect.x, writeRect.y, 0.0f); - GL.MultiTexCoord2(0, readRect.x, readRect.yMax); - GL.MultiTexCoord2(1, combineRect.x, combineRect.yMax); - GL.Vertex3(writeRect.x, writeRect.yMax, 0.0f); - GL.MultiTexCoord2(0, readRect.xMax, readRect.yMax); - GL.MultiTexCoord2(1, combineRect.xMax, combineRect.yMax); - GL.Vertex3(writeRect.xMax, writeRect.yMax, 0.0f); - GL.MultiTexCoord2(0, readRect.xMax, readRect.y); - GL.MultiTexCoord2(1, combineRect.xMax, combineRect.y); - GL.Vertex3(writeRect.xMax, writeRect.y, 0.0f); - - GL.End(); - GL.PopMatrix(); - - if (paintTextureUsesCopyTexture) - { - var rtdesc2 = new RenderTextureDescriptor(sourceTex.width, sourceTex.height, RenderTextureFormat.ARGB32); - rtdesc2.sRGB = false; - rtdesc2.useMipMap = true; - rtdesc2.autoGenerateMips = false; - var mips = RenderTexture.GetTemporary(rtdesc2); - if (!mips.IsCreated()) - mips.Create(); - - // Composes mip0 in a RT with full mipchain. - Graphics.CopyTexture(sourceTex, 0, 0, mips, 0, 0); - Graphics.CopyTexture(destTarget, 0, 0, writeRect.x, writeRect.y, writeRect.width, writeRect.height, mips, 0, 0, clippedTiles[i].x, clippedTiles[i].y); - mips.GenerateMips(); - - // Copy them into sourceTex. - Graphics.CopyTexture(mips, sourceTex); - - RenderTexture.ReleaseTemporary(mips); - } - else - { - GraphicsDeviceType deviceType = SystemInfo.graphicsDeviceType; - if (deviceType == GraphicsDeviceType.Metal || deviceType == GraphicsDeviceType.OpenGLCore) - sourceTex.ReadPixels(new Rect(writeRect.x, writeRect.y, writeRect.width, writeRect.height), clippedTiles[i].x, clippedTiles[i].y); - else - sourceTex.ReadPixels(new Rect(writeRect.x, destTarget.height - writeRect.y - writeRect.height, writeRect.width, writeRect.height), clippedTiles[i].x, clippedTiles[i].y); - sourceTex.Apply(); - } - } - - RenderTexture.active = null; - RenderTexture.ReleaseTemporary(destTarget); - - OnTerrainPainted(terrainTile, ToolAction.PaintTexture); - } - } + // for example: + // src = alphaUV + // dst = normalUV + // dst.uv = src.u * scales.xy + src.v * scales.zw + offset + // terrainspace.xz = srcOrigin + src.uv * srcSize + // terrainspace.xz = dstOrigin + dst.uv * dstSize + // dstOrigin + dst.uv * dstSize = srcOrigin + src.uv * srcSize + // dst.uv * dstSize = src.uv * srcSize + srcOrigin - dstOrigin + // dst.uv = (src.uv * srcSize + srcOrigin - dstOrigin) / dstSize + // dst.uv = (src.uv * srcSize) / dstSize + (srcOrigin - dstOrigin) / dstSize + // scales.x = srcSize.x / dstSize.x + // scales.yz = 0.0f; + // scales.w = srcSize.y / dstSize.y + // offset.xy = (srcOrigin.xy - dstOrigin.xy) / dstSize.xy + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float srcOriginX = (src.pixelRect.xMin - 0.5f) * src.pixelSize.x; + float srcOriginZ = (src.pixelRect.yMin - 0.5f) * src.pixelSize.y; + float srcSizeX = (src.pixelRect.width) * src.pixelSize.x; + float srcSizeZ = (src.pixelRect.height) * src.pixelSize.y; + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float dstOriginX = (dst.pixelRect.xMin - 0.5f) * dst.pixelSize.x; + float dstOriginZ = (dst.pixelRect.yMin - 0.5f) * dst.pixelSize.y; + float dstSizeX = (dst.pixelRect.width) * dst.pixelSize.x; + float dstSizeZ = (dst.pixelRect.height) * dst.pixelSize.y; + + scaleOffset = new Vector4( + srcSizeX / dstSizeX, + srcSizeZ / dstSizeZ, + (srcOriginX - dstOriginX) / dstSizeX, + (srcOriginZ - dstOriginZ) / dstSizeZ + ); } - [Flags] - public enum ToolAction + // this function sets up material properties used by functions provided in TerrainTool.cginc + public static void SetupTerrainToolMaterialProperties( + PaintContext paintContext, + BrushTransform brushXform, // the brush transform to terrain space (of paintContext.originTerrain) + Material material) { - None = 0, - PaintHeightmap = 1 << 0, - PaintTexture = 1 << 1, + // BrushUV = f(terrainSpace.xz) = f(g(pc.uv)) + // f(ts.xy) = ts.x * brushXform.X + ts.y * brushXform.Y + brushXform.Origin + // g(pc.uv) = ts.xz = pcOrigin + pc.uv * pcSize + // f(g(pc.uv)) == (pcOrigin + pc.uv * pcSize).x * brushXform.X + (pcOrigin + pc.uv * pcSize).y * brushXform.Y + brushXform.Origin + // f(g(pc.uv)) == (pcOrigin.x + pc.u * pcSize.x) * brushXform.X + (pcOrigin.y + pc.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pc.uv)) == (pcOrigin.x * brushXform.X) + (pc.u * pcSize.x) * brushXform.X + (pcOrigin.y * brushXform.Y) + (pc.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pc.uv)) == pc.u * (pcSize.x * brushXform.X) + pc.v * (pcSize.y * brushXform.Y) + (brushXform.Origin + (pcOrigin.x * brushXform.X) + (pcOrigin.y * brushXform.Y)) + + // pcOrigin = (pc.pixelRect.xyMin - 0.5) * pc.pixelSize.xy + // pcSize = (pc.pixelRect.wh) * pc.pixelSize.xy + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float pcOriginX = (paintContext.pixelRect.xMin - 0.5f) * paintContext.pixelSize.x; + float pcOriginZ = (paintContext.pixelRect.yMin - 0.5f) * paintContext.pixelSize.y; + float pcSizeX = (paintContext.pixelRect.width) * paintContext.pixelSize.x; + float pcSizeZ = (paintContext.pixelRect.height) * paintContext.pixelSize.y; + + Vector2 scaleU = pcSizeX * brushXform.targetX; + Vector2 scaleV = pcSizeZ * brushXform.targetY; + Vector2 offset = brushXform.targetOrigin + pcOriginX * brushXform.targetX + pcOriginZ * brushXform.targetY; + material.SetVector("_PCUVToBrushUVScales", new Vector4(scaleU.x, scaleU.y, scaleV.x, scaleV.y)); + material.SetVector("_PCUVToBrushUVOffset", new Vector4(offset.x, offset.y, 0.0f, 0.0f)); } - private static bool paintTextureUsesCopyTexture + internal static bool paintTextureUsesCopyTexture { get { @@ -419,12 +125,10 @@ private static bool paintTextureUsesCopyTexture } } - static PaintContext InitializePaintContext(Terrain terrain, Rect bounds, int inputTextureWidth, int inputTextureHeight, RenderTextureFormat colorFormat) + static PaintContext InitializePaintContext(Terrain terrain, Texture target, RenderTextureFormat pcFormat, Rect boundsInTerrainSpace, int extraBorderPixels = 0) { - PaintContext ctx = new PaintContext(); - ctx.CalculateBrushRect(terrain, bounds, inputTextureWidth, inputTextureHeight); - ctx.CreateTerrainTiles(terrain, inputTextureWidth, inputTextureHeight); - ctx.CreateRenderTargets(colorFormat); + PaintContext ctx = PaintContext.CreateFromBounds(terrain, boundsInTerrainSpace, target.width, target.height, extraBorderPixels); + ctx.CreateRenderTargets(pcFormat); return ctx; } @@ -433,77 +137,11 @@ public static void ReleaseContextResources(PaintContext ctx) ctx.Cleanup(); } - public static Rect CalculateBrushRectInTerrainUnits(Terrain terrain, Vector2 uv, float brushSize) - { - Vector3 terrainSize = terrain.terrainData.size; - return new Rect(uv * new Vector2(terrainSize.x, terrainSize.z) - Vector2.one * brushSize * 0.5f, Vector2.one * brushSize); - } - - // Collects modified terrain so that we can update some deferred operations at the mouse up event - private class PaintedTerrain - { - public Terrain terrain; - public ToolAction action; - }; - private static List s_PaintedTerrain = new List(); - - private static void OnTerrainPainted(TerrainTile tile, ToolAction action) - { - for (int i = 0; i < s_PaintedTerrain.Count; ++i) - { - if (tile.terrain == s_PaintedTerrain[i].terrain) - { - s_PaintedTerrain[i].action |= action; - return; - } - } - s_PaintedTerrain.Add(new PaintedTerrain { terrain = tile.terrain, action = action }); - } - - public static void FlushAllPaints() - { - for (int i = 0; i < s_PaintedTerrain.Count; ++i) - { - var pt = s_PaintedTerrain[i]; - if ((pt.action & ToolAction.PaintHeightmap) != 0) - { - pt.terrain.ApplyDelayedHeightmapModification(); - } - if ((pt.action & ToolAction.PaintTexture) != 0) - { - var terrainData = pt.terrain.terrainData; - if (terrainData == null) - continue; - terrainData.SetBaseMapDirty(); - if (paintTextureUsesCopyTexture) - { - // pull the data from GPU to CPU - var rtdesc = new RenderTextureDescriptor(terrainData.alphamapResolution, terrainData.alphamapResolution, RenderTextureFormat.ARGB32); - rtdesc.sRGB = false; - rtdesc.useMipMap = false; - rtdesc.autoGenerateMips = false; - RenderTexture tmp = RenderTexture.GetTemporary(rtdesc); - for (int c = 0; c < terrainData.alphamapTextureCount; ++c) - { - Graphics.Blit(terrainData.alphamapTextures[c], tmp); - terrainData.alphamapTextures[c].ReadPixels(new Rect(0, 0, rtdesc.width, rtdesc.height), 0, 0, true); - } - RenderTexture.ReleaseTemporary(tmp); - } - } - } - - s_PaintedTerrain.Clear(); - } - - // TerrainPaintUtilityEditor hooks to this event to do automatic undo - internal static event Action onTerrainTileBeforePaint; - - public static PaintContext BeginPaintHeightmap(Terrain terrain, Rect bounds) // bounds in terrain space units + public static PaintContext BeginPaintHeightmap(Terrain terrain, Rect boundsInTerrainSpace, int extraBorderPixels = 0) { RenderTexture rt = terrain.terrainData.heightmapTexture; - PaintContext ctx = InitializePaintContext(terrain, bounds, rt.width, rt.height, rt.format); - ctx.GatherHeightmap(terrain); + PaintContext ctx = InitializePaintContext(terrain, rt, rt.format, boundsInTerrainSpace, extraBorderPixels); + ctx.GatherHeightmap(); return ctx; } @@ -513,15 +151,15 @@ public static void EndPaintHeightmap(PaintContext ctx, string editorUndoName) ctx.Cleanup(); } - public static PaintContext CollectNormals(Terrain terrain, Rect bounds) + public static PaintContext CollectNormals(Terrain terrain, Rect boundsInTerrainSpace, int extraBorderPixels = 0) { RenderTexture rt = terrain.normalmapTexture; - PaintContext ctx = InitializePaintContext(terrain, bounds, rt.width, rt.height, rt.format); - ctx.GatherNormals(terrain); + PaintContext ctx = InitializePaintContext(terrain, rt, rt.format, boundsInTerrainSpace, extraBorderPixels); + ctx.GatherNormals(); return ctx; } - public static PaintContext BeginPaintTexture(Terrain terrain, Rect bounds, TerrainLayer inputLayer) + public static PaintContext BeginPaintTexture(Terrain terrain, Rect boundsInTerrainSpace, TerrainLayer inputLayer, int extraBorderPixels = 0) { if (inputLayer == null) return null; @@ -532,8 +170,8 @@ public static PaintContext BeginPaintTexture(Terrain terrain, Rect bounds, Terra Texture2D inputTexture = GetTerrainAlphaMapChecked(terrain, terrainLayerIndex >> 2); - PaintContext ctx = InitializePaintContext(terrain, bounds, inputTexture.width, inputTexture.height, RenderTextureFormat.R8); - ctx.GatherAlphamap(terrain, inputLayer); + PaintContext ctx = InitializePaintContext(terrain, inputTexture, RenderTextureFormat.R8, boundsInTerrainSpace, extraBorderPixels); + ctx.GatherAlphamap(inputLayer); return ctx; } @@ -560,7 +198,7 @@ public static Material GetCopyTerrainLayerMaterial() return m_CopyTerrainLayerMaterial; } - static void DrawQuad(int width, int height, Rect source, Rect destination) + internal static void DrawQuad(int width, int height, Rect source, Rect destination) { GL.PushMatrix(); GL.LoadOrtho(); @@ -582,139 +220,15 @@ static void DrawQuad(int width, int height, Rect source, Rect destination) GL.PopMatrix(); } - public static RectInt CalcBrushRectInPixels(Terrain terrain, Rect brushRect, int textureWidth, int textureHeight) - { - int xMin = Mathf.FloorToInt(((float)textureWidth) * brushRect.xMin / terrain.terrainData.size.x); - int yMin = Mathf.FloorToInt(((float)textureHeight) * brushRect.yMin / terrain.terrainData.size.z); - int xMax = Mathf.CeilToInt(((float)textureWidth) * brushRect.xMax / terrain.terrainData.size.x); - int yMax = Mathf.CeilToInt(((float)textureHeight) * brushRect.yMax / terrain.terrainData.size.z); - return new RectInt(xMin, yMin, xMax - xMin, yMax - yMin); - } - - public static TerrainTile[] FindTerrainTiles(Terrain terrain, int width, int height, RectInt brushRect) + internal static RectInt CalcPixelRectFromBounds(Terrain terrain, Rect boundsInTerrainSpace, int textureWidth, int textureHeight, int extraBorderPixels) { - List terrainTiles = new List(); - - Terrain left = terrain.leftNeighbor; - Terrain right = terrain.rightNeighbor; - Terrain top = terrain.topNeighbor; - Terrain bottom = terrain.bottomNeighbor; - - bool wantLeft = (brushRect.x < 0); - bool wantRight = (brushRect.xMax > (width - 1)); - bool wantTop = (brushRect.yMax > (height - 1)); - bool wantBottom = (brushRect.y < 0); - - if (wantLeft && wantRight) - { - Debug.Log("FindTerrainTiles query rectangle too large!"); - wantRight = false; - } - - if (wantTop && wantBottom) - { - Debug.Log("FindTerrainTiles query rectangle too large!"); - wantBottom = false; - } - - // add center tile - TerrainTile tile = new TerrainTile(terrain, new RectInt(0, 0, width, height)); - tile.readOffset = Vector2Int.zero; - tile.writeOffset = Vector2Int.zero; - terrainTiles.Add(tile); - - // add horizontal and vertical neighbors - Terrain horiz = null; - Terrain vert = null; - Terrain cornerTerrain = null; - - int xBias = 0; - int yBias = 0; - int xReadBias = 0; - int yReadBias = 0; - int xWriteBias = 0; - int yWriteBias = 0; - - if (wantLeft) - { - xBias = -1; - xReadBias = -1; - xWriteBias = 1; - horiz = left; - } - else if (wantRight) - { - xBias = 1; - xReadBias = 1; - xWriteBias = -1; - horiz = right; - } - - if (wantTop) - { - yBias = 1; - yReadBias = 1; - yWriteBias = -1; - vert = top; - } - else if (wantBottom) - { - yBias = -1; - yReadBias = -1; - yWriteBias = 1; - vert = bottom; - } - - if (horiz) - { - tile = new TerrainTile(horiz, new RectInt(xBias * width, 0, width, height)); - tile.readOffset = new Vector2Int(xReadBias, 0); - tile.writeOffset = new Vector2Int(xWriteBias, 0); - terrainTiles.Add(tile); - - // add corner, if we have a link - if (wantTop && horiz.topNeighbor) - cornerTerrain = horiz.topNeighbor; - else if (wantBottom && horiz.bottomNeighbor) - cornerTerrain = horiz.bottomNeighbor; - } - - if (vert) - { - tile = new TerrainTile(vert, new RectInt(0, yBias * height, width, height)); - tile.readOffset = new Vector2Int(0, yReadBias); - tile.writeOffset = new Vector2Int(0, yWriteBias); - terrainTiles.Add(tile); - - // add corner, if we have a link - if (wantLeft && vert.leftNeighbor) - cornerTerrain = vert.leftNeighbor; - else if (wantRight && vert.rightNeighbor) - cornerTerrain = vert.rightNeighbor; - } - - if (cornerTerrain != null) - { - tile = new TerrainTile(cornerTerrain, new RectInt(xBias * width, yBias * height, width, height)); - tile.readOffset = new Vector2Int(xReadBias, yReadBias); - tile.writeOffset = new Vector2Int(xWriteBias, yWriteBias); - terrainTiles.Add(tile); - } - - return terrainTiles.ToArray(); - } - - public static RectInt[] ClipTerrainTiles(TerrainTile[] terrainTiles, RectInt brushRect) - { - RectInt[] clippedTiles = new RectInt[terrainTiles.Length]; - for (int i = 0; i < terrainTiles.Length; i++) - { - clippedTiles[i].x = Mathf.Max(0, brushRect.x - terrainTiles[i].rect.x); - clippedTiles[i].y = Mathf.Max(0, brushRect.y - terrainTiles[i].rect.y); - clippedTiles[i].xMax = Mathf.Min(terrainTiles[i].rect.width, brushRect.xMax - terrainTiles[i].rect.x); - clippedTiles[i].yMax = Mathf.Min(terrainTiles[i].rect.height, brushRect.yMax - terrainTiles[i].rect.y); - } - return clippedTiles; + float scaleX = (textureWidth - 1.0f) / terrain.terrainData.size.x; + float scaleY = (textureHeight - 1.0f) / terrain.terrainData.size.z; + int xMin = Mathf.FloorToInt(boundsInTerrainSpace.xMin * scaleX) - extraBorderPixels; + int yMin = Mathf.FloorToInt(boundsInTerrainSpace.yMin * scaleY) - extraBorderPixels; + int xMax = Mathf.CeilToInt(boundsInTerrainSpace.xMax * scaleX) + extraBorderPixels; + int yMax = Mathf.CeilToInt(boundsInTerrainSpace.yMax * scaleY) + extraBorderPixels; + return new RectInt(xMin, yMin, xMax - xMin + 1, yMax - yMin + 1); } // Alphamap utilities @@ -736,7 +250,7 @@ static public int FindTerrainLayerIndex(Terrain terrain, TerrainLayer inputLayer return -1; } - static int AddTerrainLayer(Terrain terrain, TerrainLayer inputLayer) + internal static int AddTerrainLayer(Terrain terrain, TerrainLayer inputLayer) { int newIndex = terrain.terrainData.terrainLayers.Length; var newarray = new TerrainLayer[newIndex + 1]; diff --git a/Modules/TerrainEditor/Brush/Brush.cs b/Modules/TerrainEditor/Brush/Brush.cs index 8453538495..a300ec29ac 100644 --- a/Modules/TerrainEditor/Brush/Brush.cs +++ b/Modules/TerrainEditor/Brush/Brush.cs @@ -99,7 +99,7 @@ internal static Texture2D GenerateBrushTexture(Texture2D mask, AnimationCurve fa s_CreateBrushMaterial = new Material(EditorGUIUtility.LoadRequired("Brushes/CreateBrush.shader") as Shader); int sampleCount = Mathf.Max(width, 1024); - Texture2D falloffTex = new Texture2D(sampleCount, 1, TextureFormat.R8, false); + Texture2D falloffTex = new Texture2D(sampleCount, 1, TextureFormat.R16, false); Color[] falloffPix = new Color[sampleCount]; for (int i = 0; i < sampleCount; i++) { diff --git a/Modules/TerrainEditor/Brush/BrushList.cs b/Modules/TerrainEditor/Brush/BrushList.cs index 7e199ba0ed..553ef2891d 100644 --- a/Modules/TerrainEditor/Brush/BrushList.cs +++ b/Modules/TerrainEditor/Brush/BrushList.cs @@ -97,6 +97,11 @@ public void UpdateSelection(int newSelectedBrush) m_BrushEditor = Editor.CreateEditor(GetActiveBrush()); } + public Brush GetCircleBrush() + { + return m_BrushList[0]; + } + public Brush GetActiveBrush() { if (m_SelectedBrush >= m_BrushList.Length) diff --git a/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs b/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs index eef201b7d3..3770163db0 100644 --- a/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs +++ b/Modules/TerrainEditor/PaintTools/PaintHeightTool.cs @@ -25,25 +25,56 @@ public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext editContext.ShowBrushesGUI(5); } - public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength * 0.01f, editContext.brushSize, editContext.brushStrength * 0.01f); + Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); + + brushStrength = Event.current.shift ? -brushStrength : brushStrength; + Vector4 brushParams = new Vector4(0.01f * brushStrength, 0.0f, 0.0f, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); + mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.RaiseLowerHeight); } - public override bool OnPaint(Terrain terrain, IOnPaint editContext) + public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - float brushStrength = Event.current.shift ? -editContext.brushStrength : editContext.brushStrength; + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); - // apply brush - Vector4 brushParams = new Vector4(brushStrength * 0.01f, 0.0f, 0.0f, 0.0f); - mat.SetTexture("_BrushTex", editContext.brushTexture); - mat.SetVector("_BrushParams", brushParams); - Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.RaiseLowerHeight); + Material material = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(); + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, material, 0); + + // draw result preview + { + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); + + // restore old render target + RenderTexture.active = paintContext.oldRenderTexture; + + material.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.DestinationRenderTexture, editContext.brushTexture, brushXform, material, 1); + } + TerrainPaintUtility.ReleaseContextResources(paintContext); + } + } + + public override bool OnPaint(Terrain terrain, IOnPaint editContext) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Raise or Lower Height"); return true; } diff --git a/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs b/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs index 827487c55e..0fae39fd1a 100644 --- a/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs +++ b/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs @@ -24,6 +24,7 @@ public class PaintTextureTool : TerrainPaintTool [SerializeField] float m_SplatAlpha = 1.0f; + public override string GetName() { return "Paint Texture"; @@ -36,17 +37,20 @@ public override string GetDesc() public override bool OnPaint(Terrain terrain, IOnPaint editContext) { - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushRect, m_SelectedTerrainLayer); + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintTexture(terrain, brushXform.GetBrushXYBounds(), m_SelectedTerrainLayer); if (paintContext == null) return false; Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); + // apply brush Vector4 brushParams = new Vector4(editContext.brushStrength, m_SplatAlpha, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.PaintTexture); TerrainPaintUtility.EndPaintTexture(paintContext, "Terrain Paint - Texture"); @@ -55,7 +59,17 @@ public override bool OnPaint(Terrain terrain, IOnPaint editContext) public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength, editContext.brushSize, 0.0f); + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; + + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(), 0); + TerrainPaintUtility.ReleaseContextResources(ctx); + } } private void DrawFoldoutEditor(Editor editor, int controlId, ref bool visible) diff --git a/Modules/TerrainEditor/PaintTools/SetHeightTool.cs b/Modules/TerrainEditor/PaintTools/SetHeightTool.cs index a2d3999f35..2d3087b176 100644 --- a/Modules/TerrainEditor/PaintTools/SetHeightTool.cs +++ b/Modules/TerrainEditor/PaintTools/SetHeightTool.cs @@ -29,7 +29,48 @@ public override string GetDesc() public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength * 0.01f, editContext.brushSize, 0); + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; + + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + + Material material = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, material, 0); + + // draw result preview + { + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); + + // restore old render target + RenderTexture.active = paintContext.oldRenderTexture; + + material.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.DestinationRenderTexture, editContext.brushTexture, brushXform, material, 1); + } + + TerrainPaintUtility.ReleaseContextResources(paintContext); + } + } + + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) + { + Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); + + Vector4 brushParams = new Vector4(brushStrength * 0.01f, 0.5f * m_Height, 0.0f, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); + mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.SetHeights); } public override bool OnPaint(Terrain terrain, IOnPaint editContext) @@ -40,17 +81,10 @@ public override bool OnPaint(Terrain terrain, IOnPaint editContext) editContext.RepaintAllInspectors(); return true; } - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); - - Vector4 brushParams = new Vector4(editContext.brushStrength * 0.01f, 0.5f * m_Height, 0.0f, 0.0f); - mat.SetTexture("_BrushTex", editContext.brushTexture); - mat.SetVector("_BrushParams", brushParams); - - Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.SetHeights); + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Set Height"); return true; } diff --git a/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs b/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs index d345368f35..ed607efb85 100644 --- a/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs +++ b/Modules/TerrainEditor/PaintTools/SmoothHeightTool.cs @@ -25,22 +25,41 @@ public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext editContext.ShowBrushesGUI(5); } - public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength, editContext.brushSize, 0.0f); - } + Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - public override bool OnPaint(Terrain terrain, IOnPaint editContext) - { - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); + brushStrength = Event.current.shift ? -brushStrength : brushStrength; - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - Vector4 brushParams = new Vector4(editContext.brushStrength, 0.0f, 0.0f, 0.0f); - mat.SetTexture("_BrushTex", editContext.brushTexture); + Vector4 brushParams = new Vector4(brushStrength, 0.0f, 0.0f, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); mat.SetVector("_BrushParams", brushParams); + + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); + Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.SmoothHeights); + } + + public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) + { + // We're only doing painting operations, early out if it's not a repaint + if (Event.current.type != EventType.Repaint) + return; + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(), 0); + TerrainPaintUtility.ReleaseContextResources(ctx); + } + } + + public override bool OnPaint(Terrain terrain, IOnPaint editContext) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Smooth Height"); return true; } diff --git a/Modules/TerrainEditor/PaintTools/StampTool.cs b/Modules/TerrainEditor/PaintTools/StampTool.cs index f4f4eafa62..d6d59e57da 100644 --- a/Modules/TerrainEditor/PaintTools/StampTool.cs +++ b/Modules/TerrainEditor/PaintTools/StampTool.cs @@ -21,45 +21,84 @@ public override string GetName() public override string GetDesc() { - return "Left click to stamp the brush onto the terrain.\n\nHold shift and left click to stamp negative."; + return "Left click to stamp the brush onto the terrain.\n\nHold shift and mousewheel to adjust height."; } - public override bool OnPaint(Terrain terrain, IOnPaint editContext) + private void ApplyBrushInternal(PaintContext paintContext, float brushStrength, Texture brushTexture, BrushTransform brushXform) { - if (Event.current.type == EventType.MouseDrag) - return true; - Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, editContext.uv, editContext.brushSize); - TerrainPaintUtility.PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); - - Vector4 brushParams = new Vector4(editContext.brushStrength * 0.01f, 0.0f, m_StampHeight, 0.0f); + Vector4 brushParams = new Vector4(0.01f * brushStrength, 0.0f, m_StampHeight, 0.0f); + mat.SetTexture("_BrushTex", brushTexture); + mat.SetVector("_BrushParams", brushParams); - if (Event.current.shift) - brushParams.x = -brushParams.x; + TerrainPaintUtility.SetupTerrainToolMaterialProperties(paintContext, brushXform, mat); - mat.SetTexture("_BrushTex", editContext.brushTexture); - mat.SetVector("_BrushParams", brushParams); Graphics.Blit(paintContext.sourceRenderTexture, paintContext.destinationRenderTexture, mat, (int)TerrainPaintUtility.BuiltinPaintMaterialPasses.StampHeight); + } + + public override bool OnPaint(Terrain terrain, IOnPaint editContext) + { + // ignore mouse drags + if (Event.current.type == EventType.MouseDrag) + return true; + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.uv, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds()); + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); TerrainPaintUtility.EndPaintHeightmap(paintContext, "Terrain Paint - Stamp"); return true; } public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, editContext.brushTexture, editContext.brushStrength * 0.01f, editContext.brushSize, m_StampHeight); + Event evt = Event.current; + if (evt.shift && (evt.type == EventType.ScrollWheel)) + { + m_StampHeight += Event.current.delta.y * -0.0000007f * editContext.raycastHit.distance; + evt.Use(); + } + + // We're only doing painting operations, early out if it's not a repaint + if (evt.type != EventType.Repaint) + return; + + if (editContext.hitValidTerrain) + { + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); + PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + + Material material = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, editContext.brushTexture, brushXform, material, 0); + + // draw result preview + { + ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); + + // restore old render target + RenderTexture.active = paintContext.oldRenderTexture; + + material.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); + + TerrainPaintUtilityEditor.DrawBrushPreview( + paintContext, TerrainPaintUtilityEditor.BrushPreview.DestinationRenderTexture, editContext.brushTexture, brushXform, material, 1); + } + + TerrainPaintUtility.ReleaseContextResources(paintContext); + } } public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext) { EditorGUI.BeginChangeCheck(); - m_StampHeight = EditorGUILayout.Slider(new GUIContent("Stamp Height", "You can set the Stamp Height property manually or you can shift-click on the terrain to sample the height at the mouse position (rather like the “eyedropper” tool in an image editor)."), m_StampHeight * terrain.terrainData.size.y, 0, terrain.terrainData.size.y) / terrain.terrainData.size.y; + m_StampHeight = EditorGUILayout.Slider(new GUIContent("Stamp Height", "You can set the Stamp Height manually or you can hold shift and mouse wheel on the terrain to adjust it."), m_StampHeight * terrain.terrainData.size.y, 0, terrain.terrainData.size.y) / terrain.terrainData.size.y; if (EditorGUI.EndChangeCheck()) Save(true); // show built-in brushes + editContext.ShowBrushesGUI(5); base.OnInspectorGUI(terrain, editContext); } } diff --git a/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs b/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs index 65eb147cdc..9f1de28910 100644 --- a/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs +++ b/Modules/TerrainEditor/PaintTools/TerrainPaintTool.cs @@ -15,7 +15,6 @@ public interface IOnPaint Texture brushTexture { get; } Vector2 uv { get; } float brushStrength { get; } - float brushRotation { get; } float brushSize { get; } void RepaintAllInspectors(); @@ -25,8 +24,9 @@ public interface IOnSceneGUI SceneView sceneView { get; } Texture brushTexture { get; } float brushStrength { get; } - float brushRotation { get; } float brushSize { get; } + bool hitValidTerrain { get; } + RaycastHit raycastHit { get; } } public interface IOnInspectorGUI @@ -40,6 +40,8 @@ internal interface ITerrainPaintTool string GetDesc(); void OnEnable(); void OnDisable(); + void OnEnterToolMode(); + void OnExitToolMode(); void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext); void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext); bool OnPaint(Terrain terrain, IOnPaint editContext); @@ -51,6 +53,8 @@ public abstract class TerrainPaintTool : ScriptableSingleton, ITerrainPain public abstract string GetDesc(); public virtual void OnEnable() {} public virtual void OnDisable() {} + public virtual void OnEnterToolMode() {} + public virtual void OnExitToolMode() {} public virtual void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) {} public virtual void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext) {} public virtual bool OnPaint(Terrain terrain, IOnPaint editContext) { return false; } @@ -62,27 +66,28 @@ internal class OnPaintContext : IOnPaint internal Vector2 m_UV = Vector2.zero; internal float m_BrushStrength = 0.0f; internal float m_BrushSize = 0; - internal float m_BrushRotation = 0.0f; + internal bool m_HitValidTerrain = false; + internal RaycastHit m_RaycastHit; - public OnPaintContext(Texture brushTexture, Vector2 uv, float brushStrength, float brushRotation, float brushSize) + public OnPaintContext(RaycastHit raycastHit, Texture brushTexture, Vector2 uv, float brushStrength, float brushSize) { - Set(brushTexture, uv, brushStrength, brushRotation, brushSize); + Set(false, raycastHit, brushTexture, uv, brushStrength, brushSize); } - public OnPaintContext Set(Texture brushTexture, Vector2 uv, float brushStrength, float brushRotation, float brushSize) + public OnPaintContext Set(bool hitValidTerrain, RaycastHit raycastHit, Texture brushTexture, Vector2 uv, float brushStrength, float brushSize) { m_BrushTexture = brushTexture; m_UV = uv; m_BrushStrength = brushStrength; m_BrushSize = brushSize; - m_BrushRotation = brushRotation; + m_HitValidTerrain = hitValidTerrain; + m_RaycastHit = raycastHit; return this; } public Texture brushTexture { get { return m_BrushTexture; } } public Vector2 uv { get { return m_UV; } } public float brushStrength { get { return m_BrushStrength; } } - public float brushRotation { get { return m_BrushRotation; } } public float brushSize { get { return m_BrushSize; } } public void RepaintAllInspectors() { InspectorWindow.RepaintAllInspectors(); } @@ -94,28 +99,31 @@ internal class OnSceneGUIContext : IOnSceneGUI internal Texture m_BrushTexture = null; internal float m_BrushStrength = 0.0f; internal float m_BrushSize = 0; - internal float m_BrushRotation = 0.0f; + internal bool m_HitValidTerrain = false; + internal RaycastHit m_RaycastHit; - public OnSceneGUIContext(SceneView sceneView, Texture brushTexture, float brushStrength, float brushRotation, float brushSize) + public OnSceneGUIContext(SceneView sceneView, RaycastHit raycastHit, Texture brushTexture, float brushStrength, float brushSize) { - Set(sceneView, brushTexture, brushStrength, brushSize, brushRotation); + Set(sceneView, false, raycastHit, brushTexture, brushStrength, brushSize); } - public OnSceneGUIContext Set(SceneView sceneView, Texture brushTexture, float brushStrength, float brushRotation, float brushSize) + public OnSceneGUIContext Set(SceneView sceneView, bool hitValidTerrain, RaycastHit raycastHit, Texture brushTexture, float brushStrength, float brushSize) { m_SceneView = sceneView; m_BrushTexture = brushTexture; m_BrushStrength = brushStrength; m_BrushSize = brushSize; - m_BrushRotation = brushRotation; + m_HitValidTerrain = hitValidTerrain; + m_RaycastHit = raycastHit; return this; } public SceneView sceneView { get { return m_SceneView; } } public Texture brushTexture { get { return m_BrushTexture; } } public float brushStrength { get { return m_BrushStrength; } } - public float brushRotation { get { return m_BrushRotation; } } public float brushSize { get { return m_BrushSize; } } + public bool hitValidTerrain { get { return m_HitValidTerrain; } } + public RaycastHit raycastHit { get { return m_RaycastHit; } } } internal class OnInspectorGUIContext : IOnInspectorGUI diff --git a/Modules/TerrainEditor/TerrainInspector.cs b/Modules/TerrainEditor/TerrainInspector.cs index fcc226c9cb..de381c2fe1 100644 --- a/Modules/TerrainEditor/TerrainInspector.cs +++ b/Modules/TerrainEditor/TerrainInspector.cs @@ -635,9 +635,9 @@ public bool active static internal ITerrainPaintTool[] m_Tools = null; static internal string[] m_ToolNames = null; - static OnPaintContext onPaintEditContext = new OnPaintContext(null, Vector2.zero, 0.0f, 0.0f, 0.0f); + static OnPaintContext onPaintEditContext = new OnPaintContext(new RaycastHit(), null, Vector2.zero, 0.0f, 0.0f); static OnInspectorGUIContext onInspectorGUIEditContext = new OnInspectorGUIContext(); - static OnSceneGUIContext onSceneGUIEditContext = new OnSceneGUIContext(null, null, 0.0f, 0.0f, 0.0f); + static OnSceneGUIContext onSceneGUIEditContext = new OnSceneGUIContext(null, new RaycastHit(), null, 0.0f, 0.0f); ITerrainPaintTool GetActiveTool() { @@ -813,6 +813,7 @@ void ResetPaintTools() void Initialize() { m_Terrain = target as Terrain; + CheckToolActivation(); } void LoadInspectorSettings() @@ -826,7 +827,7 @@ void LoadInspectorSettings() int selected = EditorPrefs.GetInt("TerrainSelectedBrush", 0); s_DetailPainter.selectedDetail = EditorPrefs.GetInt("TerrainSelectedDetail", 0); - m_ActivePaintToolIndex = EditorPrefs.GetInt("TerraiActivePaintToolIndex", 0); + m_ActivePaintToolIndex = EditorPrefs.GetInt("TerrainActivePaintToolIndex", 0); // TODO: this should be stored by name if (m_ActivePaintToolIndex > m_Tools.Length) m_ActivePaintToolIndex = 0; @@ -844,7 +845,7 @@ void SaveInspectorSettings() EditorPrefs.SetFloat("TerrainBrushSize", m_Size); EditorPrefs.SetFloat("TerrainBrushStrength", m_Strength); - EditorPrefs.SetInt("TerraiActivePaintToolIndex", m_ActivePaintToolIndex); + EditorPrefs.SetInt("TerrainActivePaintToolIndex", m_ActivePaintToolIndex); } public void OnEnable() @@ -874,6 +875,9 @@ public void OnEnable() LoadInspectorSettings(); + // now that tool selection has been loaded from inspector, activate the selected tool + CheckToolActivation(); + InitializeLightingFields(); m_TerrainToolContext = new TerrainToolContext(this); @@ -886,9 +890,11 @@ public void OnEnable() public void OnDisable() { ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_TerrainToolContext); - TerrainPaintUtility.FlushAllPaints(); + PaintContext.ApplyDelayedActions(); SceneView.onSceneGUIDelegate -= OnSceneGUICallback; + SetCurrentPaintToolInactive(); + SaveInspectorSettings(); m_ShowReflectionProbesGUI.valueChanged.RemoveListener(Repaint); @@ -922,6 +928,55 @@ TerrainTool selectedTool Tools.current = Tool.None; m_SelectedTool.value = (int)value; s_activeTerrainInspector = GetInstanceID(); + CheckToolActivation(); + } + } + + // this is a bunch of tracking to ensure we don't mess up the tool mode callbacks + private bool m_PaintToolActive = false; + private void SetCurrentPaintToolActive() + { + if (!m_PaintToolActive) + { + ITerrainPaintTool paintTool = GetActiveTool(); + if (paintTool != null) + { + paintTool.OnEnterToolMode(); + m_PaintToolActive = true; + } + } + } + + private void SetCurrentPaintToolInactive() + { + if (m_PaintToolActive) + { + ITerrainPaintTool paintTool = GetActiveTool(); + if (paintTool != null) + { + paintTool.OnExitToolMode(); + m_PaintToolActive = false; + } + } + } + + // Ideally we would be notified when the active tool changes, but I can see no way to do that + // So instead we will call this function everywhere, which checks for it changing and does the proper notification callbacks + private TerrainTool m_PreviousSelectedTool = TerrainTool.None; + private void CheckToolActivation() + { + TerrainTool currentTool = selectedTool; + if (currentTool != m_PreviousSelectedTool) + { + // inactivate previous tool, if necessary + if (m_PreviousSelectedTool == TerrainTool.Paint) + SetCurrentPaintToolInactive(); + + m_PreviousSelectedTool = currentTool; + + // activate new tool, if necessary + if (currentTool == TerrainTool.Paint) + SetCurrentPaintToolActive(); } } @@ -1390,9 +1445,14 @@ public void ShowPaint() if (m_Tools != null && m_Tools.Length > 1 && m_ToolNames != null) { EditorGUI.BeginChangeCheck(); - m_ActivePaintToolIndex = EditorGUILayout.Popup(m_ActivePaintToolIndex, m_ToolNames); - if (EditorGUI.EndChangeCheck()) + int newPaintToolIndex = EditorGUILayout.Popup(m_ActivePaintToolIndex, m_ToolNames); + if (EditorGUI.EndChangeCheck() && (newPaintToolIndex != m_ActivePaintToolIndex)) + { + SetCurrentPaintToolInactive(); + m_ActivePaintToolIndex = newPaintToolIndex; + SetCurrentPaintToolActive(); Repaint(); + } ITerrainPaintTool activeTool = GetActiveTool(); GUILayout.BeginVertical(EditorStyles.helpBox); @@ -1408,7 +1468,8 @@ public void ShowBrushes(int spacing) GUILayout.Space(spacing); bool repaint = brushList.ShowGUI(); - m_Size = EditorGUILayout.Slider(styles.brushSize, m_Size, 1.0f, Mathf.Min(m_Terrain.terrainData.size.x - 1.0f, m_Terrain.terrainData.size.z - 1.0f)); + float safetyFactorHack = 0.9375f; + m_Size = EditorGUILayout.Slider(styles.brushSize, m_Size, 0.1f, Mathf.Round(Mathf.Min(m_Terrain.terrainData.size.x, m_Terrain.terrainData.size.z) * safetyFactorHack)); m_Strength = PercentSlider(styles.opacity, m_Strength, kMinBrushStrength, 1); // former string formatting: "0.0%" brushList.ShowEditGUI(); @@ -1866,23 +1927,21 @@ private bool IsModificationToolActive() return true; } - bool IsBrushPreviewVisible() + bool IsBrushPreviewVisible(Terrain overTerrain) { if (!IsModificationToolActive()) return false; - Vector3 pos; - Vector2 uv; - return Raycast(out uv, out pos); + return (overTerrain != null); } - private bool RaycastAllTerrains(out Terrain hitTerrain, out Vector2 hitUV) + private bool RaycastAllTerrains(out Terrain hitTerrain, out RaycastHit raycastHit) { Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); float minDist = float.MaxValue; hitTerrain = null; - hitUV = Vector2.zero; + raycastHit = new RaycastHit(); foreach (Terrain terrain in Terrain.activeTerrains) { RaycastHit hit; @@ -1892,11 +1951,11 @@ private bool RaycastAllTerrains(out Terrain hitTerrain, out Vector2 hitUV) { minDist = hit.distance; hitTerrain = terrain; - hitUV = hit.textureCoord; + raycastHit = hit; } } } - return hitTerrain; + return (hitTerrain != null); } public void OnSceneGUICallback(SceneView sceneView) @@ -1905,47 +1964,52 @@ public void OnSceneGUICallback(SceneView sceneView) Event e = Event.current; - Terrain terrain = null; - Vector2 uv = Vector2.zero; + Terrain hitTerrain = null; + RaycastHit raycastHit = new RaycastHit(); if (selectedTool == TerrainTool.Paint || selectedTool == TerrainTool.PaintDetail || selectedTool == TerrainTool.PlaceTree) { - if (RaycastAllTerrains(out terrain, out uv)) + if (RaycastAllTerrains(out hitTerrain, out raycastHit)) { if (e.type == EventType.MouseDown || e.type == EventType.MouseUp) { if (e.button == 0 && !Event.current.alt) - Selection.activeObject = terrain; + Selection.activeObject = hitTerrain; } } } + Vector2 uv = raycastHit.textureCoord; - bool isTerrainValid = (terrain != null && terrain.terrainData != null); + bool hitValidTerrain = (hitTerrain != null && hitTerrain.terrainData != null); + if (!hitValidTerrain) + { + raycastHit = new RaycastHit(); + } if (selectedTool == TerrainTool.Paint) { - Terrain lastActiveTerrain = isTerrainValid ? terrain : s_LastActiveTerrain; + Terrain lastActiveTerrain = hitValidTerrain ? hitTerrain : s_LastActiveTerrain; if (lastActiveTerrain) { ITerrainPaintTool activeTool = GetActiveTool(); - activeTool.OnSceneGUI(lastActiveTerrain, onSceneGUIEditContext.Set(sceneView, brushList.GetActiveBrush().texture, m_Strength, 0.0f, m_Size)); + activeTool.OnSceneGUI(lastActiveTerrain, onSceneGUIEditContext.Set(sceneView, hitValidTerrain, raycastHit, brushList.GetActiveBrush().texture, m_Strength, m_Size)); } } else if (selectedTool == TerrainTool.PaintDetail || selectedTool == TerrainTool.PlaceTree) { - if (isTerrainValid) + if (hitValidTerrain) { float brushSize = selectedTool == TerrainTool.PlaceTree ? TreePainter.brushSize : m_Size; - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(terrain, brushList.GetActiveBrush().texture, m_Strength, brushSize, 0.0f); + TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(hitTerrain, brushList.GetCircleBrush().texture, brushSize); } } - if (!isTerrainValid) + if (!hitValidTerrain) return; - s_LastActiveTerrain = terrain; + s_LastActiveTerrain = hitTerrain; int id = GUIUtility.GetControlID(s_TerrainEditorHash, FocusType.Passive); switch (e.GetTypeForControl(id)) @@ -1957,7 +2021,7 @@ public void OnSceneGUICallback(SceneView sceneView) break; case EventType.MouseMove: - if (IsBrushPreviewVisible()) + if (IsBrushPreviewVisible(hitTerrain)) HandleUtility.Repaint(); break; @@ -2000,12 +2064,12 @@ public void OnSceneGUICallback(SceneView sceneView) TreePainter.BeginPlaceTrees(m_Terrain); } - TreePainter.PlaceTrees(terrain, uv.x, uv.y); + TreePainter.PlaceTrees(hitTerrain, uv.x, uv.y); } } else { - TreePainter.RemoveTrees(terrain, uv.x, uv.y, Event.current.control); + TreePainter.RemoveTrees(hitTerrain, uv.x, uv.y, Event.current.control); } } else if (selectedTool == TerrainTool.PaintDetail) @@ -2016,13 +2080,13 @@ public void OnSceneGUICallback(SceneView sceneView) } DetailPaintOperation paintOp = new DetailPaintOperation(); - paintOp.size = (int)Mathf.Max(1.0f, ((float)m_Size * ((float)terrain.terrainData.detailResolution / terrain.terrainData.size.x))); + paintOp.size = (int)Mathf.Max(1.0f, ((float)m_Size * ((float)hitTerrain.terrainData.detailResolution / hitTerrain.terrainData.size.x))); paintOp.targetStrength = m_DetailStrength * 16F; if (Event.current.shift || Event.current.control) paintOp.targetStrength *= -1; paintOp.opacity = m_DetailOpacity; paintOp.clearSelectedOnly = Event.current.control; - paintOp.terrainData = terrain.terrainData; + paintOp.terrainData = hitTerrain.terrainData; paintOp.brush = brushList.GetActiveBrush(); paintOp.tool = selectedTool; paintOp.randomizeDetails = true; @@ -2034,10 +2098,10 @@ public void OnSceneGUICallback(SceneView sceneView) else { ITerrainPaintTool activeTool = GetActiveTool(); - if (activeTool.OnPaint(terrain, onPaintEditContext.Set(brushList.GetActiveBrush().texture, uv, m_Strength, 0.0f, m_Size))) + if (activeTool.OnPaint(hitTerrain, onPaintEditContext.Set(hitValidTerrain, raycastHit, brushList.GetActiveBrush().texture, uv, m_Strength, m_Size))) { // height map modification modes - terrain.editorRenderFlags = TerrainRenderFlags.Heightmap; + hitTerrain.editorRenderFlags = TerrainRenderFlags.Heightmap; } } @@ -2067,8 +2131,8 @@ public void OnSceneGUICallback(SceneView sceneView) s_DetailPainter.EndPaintDetails(); } - terrain.editorRenderFlags = TerrainRenderFlags.All; - TerrainPaintUtility.FlushAllPaints(); + hitTerrain.editorRenderFlags = TerrainRenderFlags.All; + PaintContext.ApplyDelayedActions(); e.Use(); } diff --git a/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs b/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs index 39ccf3c7f7..22743c45f5 100644 --- a/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs +++ b/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs @@ -14,12 +14,6 @@ namespace UnityEditor.Experimental.TerrainAPI { public static class TerrainPaintUtilityEditor { - internal enum BrushPreviewMeshType - { - QuadOutline = 0, - QuadPatch - } - // This maintains the list of terrains we have touched in the current operation (and the current operation identifier, as an undo group) // We track this to have good cross-tile undo support: each modified tile should be added, at most, ONCE within a single operation private static int s_CurrentOperationUndoGroup = -1; @@ -27,7 +21,7 @@ internal enum BrushPreviewMeshType static TerrainPaintUtilityEditor() { - TerrainPaintUtility.onTerrainTileBeforePaint += (tile, action, editorUndoName) => + PaintContext.onTerrainTileBeforePaint += (tile, action, editorUndoName) => { // if we are in a new undo group (new operation) then start with an empty list if (Undo.GetCurrentGroup() != s_CurrentOperationUndoGroup) @@ -44,7 +38,7 @@ static TerrainPaintUtilityEditor() s_CurrentOperationUndoStack.Add(tile.terrain); var undoObjects = new List(); undoObjects.Add(tile.terrain.terrainData); - if (0 != (action & TerrainPaintUtility.ToolAction.PaintTexture)) + if (0 != (action & PaintContext.ToolAction.PaintTexture)) undoObjects.AddRange(tile.terrain.terrainData.alphamapTextures); Undo.RegisterCompleteObjectUndo(undoObjects.ToArray(), editorUndoName); } @@ -67,31 +61,15 @@ internal static void UpdateTerrainDataUndo(TerrainData terrainData, string undoN } } - public static void ShowDefaultPreviewBrush(Terrain terrain, Texture brushTexture, float brushStrength, float brushSize, float futurePreviewScale) + public static void ShowDefaultPreviewBrush(Terrain terrain, Texture brushTexture, float brushSize) { Ray mouseRay = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); RaycastHit hit; if (terrain.GetComponent().Raycast(mouseRay, out hit, Mathf.Infinity)) { - if (Event.current.shift) - brushStrength = -brushStrength; - - Rect brushRect = TerrainPaintUtility.CalculateBrushRectInTerrainUnits(terrain, hit.textureCoord, brushSize); - TerrainPaintUtility.PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushRect); - - ctx.sourceRenderTexture.filterMode = FilterMode.Bilinear; - brushTexture.filterMode = FilterMode.Bilinear; - - Vector2 topLeft = ctx.brushRect.min; - float xfrac = ((topLeft.x - (int)topLeft.x) / (float)ctx.sourceRenderTexture.width); - float yfrac = ((topLeft.y - (int)topLeft.y) / (float)ctx.sourceRenderTexture.height); - - Vector4 texScaleOffset = new Vector4(0.5f, 0.5f, 0.5f + xfrac + 0.5f / (float)ctx.sourceRenderTexture.width, 0.5f + yfrac + 0.5f / (float)ctx.sourceRenderTexture.height); - - DrawDefaultBrushPreviewMesh(terrain, hit, ctx.sourceRenderTexture, brushTexture, brushStrength * 0.01f, brushSize, defaultPreviewPatchMesh, false, texScaleOffset); - if ((futurePreviewScale > Mathf.Epsilon) && Event.current.control) - DrawDefaultBrushPreviewMesh(terrain, hit, ctx.sourceRenderTexture, brushTexture, futurePreviewScale, brushSize, defaultPreviewPatchMesh, true, texScaleOffset); - + BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, hit.textureCoord, brushSize, 0.0f); + PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); + DrawBrushPreview(ctx, TerrainPaintUtilityEditor.BrushPreview.SourceRenderTexture, brushTexture, brushXform, GetDefaultBrushPreviewMaterial(), 0); TerrainPaintUtility.ReleaseContextResources(ctx); } } @@ -103,83 +81,96 @@ public static Material GetDefaultBrushPreviewMaterial() return m_BrushPreviewMaterial; } - // drawing utilities - - internal static Mesh GenerateDefaultBrushPreviewMesh(int tesselationLevel) + public enum BrushPreview { - if (tesselationLevel < 1) - { - Debug.LogWarning("Invalid tessellation level passed to GenerateBrushPreviewMesh."); - return null; - } - - var verts = new List(); - var indices = new List(); - - Mesh m = new Mesh(); - - float incr = 2.0f / (float)tesselationLevel; - - Vector3 v = new Vector3(-1.0f, 0, -1.0f); - - for (int i = 0; i <= tesselationLevel; i++) - { - v.x = -1.0f; - for (int j = 0; j <= tesselationLevel; j++) - { - verts.Add(v); - v.x += incr; - - if (i != tesselationLevel && j != tesselationLevel) - { - int index = i * (tesselationLevel + 1) + j; - - indices.Add(index); - indices.Add(index + tesselationLevel + 1); - indices.Add(index + 1); - - indices.Add(index + 1); - indices.Add(index + tesselationLevel + 1); - indices.Add(index + tesselationLevel + 2); - } - } - v.z += incr; - } - - m.vertices = verts.ToArray(); - m.triangles = indices.ToArray(); - - return m; - } - - public static void DrawDefaultBrushPreviewMesh(Terrain terrain, RaycastHit hit, Texture heightmapTexture, Texture brushTexture, float brushStrength, float brushSize, Mesh mesh, bool showPreviewPostBrush, Vector4 texScaleOffset) + SourceRenderTexture, + DestinationRenderTexture + }; + + public static void DrawBrushPreview( + PaintContext heightmapPC, + BrushPreview previewTexture, + Texture brushTexture, // brush texture to apply + BrushTransform brushXform, // brush transform that defines the brush UV space + Material proceduralMaterial, // the material to render with (must support procedural quad-mesh generation) + int materialPassIndex) // the pass to use within the material { - Vector4 brushParams = new Vector4(brushStrength, 2.0f * terrain.terrainData.heightmapScale.y, 0.0f, 0.0f); - - Material mat = GetDefaultBrushPreviewMaterial(); - mat.SetTexture("_MainTex", heightmapTexture); - mat.SetTexture("_BrushTex", brushTexture); - mat.SetVector("_BrushParams", brushParams); - mat.SetVector("_TexScaleOffet", texScaleOffset); - mat.SetPass(showPreviewPostBrush ? 1 : 0); - - Matrix4x4 matrix = Matrix4x4.identity; - matrix.SetTRS(new Vector3(hit.point.x, terrain.GetPosition().y, hit.point.z), Quaternion.identity, new Vector3(brushSize / 2.0f, 1, brushSize / 2.0f)); - - Graphics.DrawMeshNow(mesh, matrix); + // we want to build a quad mesh, with one vertex for each pixel in the heightmap + // i.e. a 3x3 heightmap would create a mesh that looks like this: + // + // +-+-+ + // |\|\| + // +-+-+ + // |\|\| + // +-+-+ + // + int quadsX = heightmapPC.pixelRect.width - 1; + int quadsY = heightmapPC.pixelRect.height - 1; + int vertexCount = quadsX * quadsY * (2 * 3); // two triangles (2 * 3 vertices) per quad + + // this is used to tessellate the quad mesh (from within the vertex shader) + proceduralMaterial.SetVector("_QuadRez", new Vector4(quadsX, quadsY, vertexCount, 0.0f)); + + // paint context pixels to heightmap uv: uv = (pixels + 0.5) / width + Texture heightmapTexture = (previewTexture == BrushPreview.SourceRenderTexture) ? heightmapPC.sourceRenderTexture : heightmapPC.destinationRenderTexture; + float invWidth = 1.0f / heightmapTexture.width; + float invHeight = 1.0f / heightmapTexture.height; + proceduralMaterial.SetVector("_HeightmapUV_PCPixelsX", new Vector4(invWidth, 0.0f, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_HeightmapUV_PCPixelsY", new Vector4(0.0f, invHeight, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_HeightmapUV_Offset", new Vector4(0.5f * invWidth, 0.5f * invHeight, 0.0f, 0.0f)); + + // make sure we point filter the heightmap + FilterMode oldFilter = heightmapTexture.filterMode; + heightmapTexture.filterMode = FilterMode.Point; + proceduralMaterial.SetTexture("_Heightmap", heightmapTexture); + + // paint context pixels to object (terrain) position + // objectPos.x = scaleX * pcPixels.x + heightmapRect.xMin * scaleX + // objectPos.y = scaleY * H + // objectPos.z = scaleZ * pcPixels.y + heightmapRect.yMin * scaleZ + float scaleX = heightmapPC.pixelSize.x; + float scaleY = 2.0f * heightmapPC.originTerrain.terrainData.heightmapScale.y; + float scaleZ = heightmapPC.pixelSize.y; + proceduralMaterial.SetVector("_ObjectPos_PCPixelsX", new Vector4(scaleX, 0.0f, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_ObjectPos_HeightMapSample", new Vector4(0.0f, scaleY, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_ObjectPos_PCPixelsY", new Vector4(0.0f, 0.0f, scaleZ, 0.0f)); + proceduralMaterial.SetVector("_ObjectPos_Offset", new Vector4(heightmapPC.pixelRect.xMin * scaleX, 0.0f, heightmapPC.pixelRect.yMin * scaleZ, 1.0f)); + + // heightmap paint context pixels to brush UV + // derivation: + + // BrushUV = f(terrainSpace.xz) = f(g(pcPixels.xy)) + // f(ts.xy) = ts.x * brushXform.X + ts.y * brushXform.Y + brushXform.Origin + // g(pcPixels.xy) = ts.xz = pcOrigin + pcPixels.xy * pcSize + // f(g(pcPixels.uv)) == (pcOrigin + pcPixels.uv * pcSize).x * brushXform.X + (pcOrigin + pcPixels.uv * pcSize).y * brushXform.Y + brushXform.Origin + // f(g(pcPixels.uv)) == (pcOrigin.x + pcPixels.u * pcSize.x) * brushXform.X + (pcOrigin.y + pcPixels.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pcPixels.uv)) == (pcOrigin.x * brushXform.X) + (pcPixels.u * pcSize.x) * brushXform.X + (pcOrigin.y * brushXform.Y) + (pcPixels.v * pcSize.y) * brushXform.Y + brushXform.Origin + // f(g(pcPixels.uv)) == pcPixels.u * (pcSize.x * brushXform.X) + pcPixels.v * (pcSize.y * brushXform.Y) + (brushXform.Origin + (pcOrigin.x * brushXform.X) + (pcOrigin.y * brushXform.Y)) + + // paint context origin in terrain space + // (note this is the UV space origin and size, not the mesh origin & size) + float pcOriginX = heightmapPC.pixelRect.xMin * heightmapPC.pixelSize.x; + float pcOriginZ = heightmapPC.pixelRect.yMin * heightmapPC.pixelSize.y; + float pcSizeX = heightmapPC.pixelSize.x; + float pcSizeZ = heightmapPC.pixelSize.y; + + Vector2 scaleU = pcSizeX * brushXform.targetX; + Vector2 scaleV = pcSizeZ * brushXform.targetY; + Vector2 offset = brushXform.targetOrigin + pcOriginX * brushXform.targetX + pcOriginZ * brushXform.targetY; + proceduralMaterial.SetVector("_BrushUV_PCPixelsX", new Vector4(scaleU.x, scaleU.y, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_BrushUV_PCPixelsY", new Vector4(scaleV.x, scaleV.y, 0.0f, 0.0f)); + proceduralMaterial.SetVector("_BrushUV_Offset", new Vector4(offset.x, offset.y, 0.0f, 1.0f)); + proceduralMaterial.SetTexture("_BrushTex", brushTexture); + + Vector3 terrainPos = heightmapPC.originTerrain.GetPosition(); + proceduralMaterial.SetVector("_TerrainObjectToWorldOffset", terrainPos); + + proceduralMaterial.SetPass(materialPassIndex); + Graphics.DrawProcedural(MeshTopology.Triangles, vertexCount); + + heightmapTexture.filterMode = oldFilter; } - static Mesh m_DefaultPreviewPatchMesh = null; static Material m_BrushPreviewMaterial = null; - - public static Mesh defaultPreviewPatchMesh - { - get - { - if (m_DefaultPreviewPatchMesh == null) - m_DefaultPreviewPatchMesh = GenerateDefaultBrushPreviewMesh(100); - return m_DefaultPreviewPatchMesh; - } - } } } diff --git a/Modules/UIElements/VisualElement.cs b/Modules/UIElements/VisualElement.cs index 43ab959327..ccd739578f 100644 --- a/Modules/UIElements/VisualElement.cs +++ b/Modules/UIElements/VisualElement.cs @@ -620,9 +620,25 @@ internal void SetPanel(BaseVisualElementPanel p) elements.Add(this); GatherAllChildren(elements); - foreach (var e in elements) + EventDispatcher.Gate? pDispatcherGate = null; + if (p?.dispatcher != null) { - e.ChangePanel(p); + pDispatcherGate = new EventDispatcher.Gate(p.dispatcher); + } + + EventDispatcher.Gate? panelDispatcherGate = null; + if (panel?.dispatcher != null && panel.dispatcher != p?.dispatcher) + { + panelDispatcherGate = new EventDispatcher.Gate(panel.dispatcher); + } + + using (pDispatcherGate) + using (panelDispatcherGate) + { + foreach (var e in elements) + { + e.ChangePanel(p); + } } } finally @@ -655,7 +671,7 @@ void ChangePanel(BaseVisualElementPanel p) using (var e = AttachToPanelEvent.GetPooled(prevPanel, p)) { e.target = this; - elementPanel.SendEvent(e, DispatchMode.Immediate); + elementPanel.SendEvent(e, DispatchMode.Default); } } diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 9eb5fc83be..953308b49b 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1488,6 +1488,12 @@ Modules\Substance\SubstanceUtility.cs + + Modules\Terrain\Public\BrushTransform.cs + + + Modules\Terrain\Public\PaintContext.cs + Modules\Terrain\Public\Terrain.bindings.cs diff --git a/README.md b/README.md index 8700f0282d..9d239fc5b0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b5 C# reference source code +## Unity 2018.3.0b6 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs b/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs index d075d899e2..9a40d7718b 100644 --- a/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs +++ b/Runtime/AR/Tango/ScriptBindings/Tango.bindings.cs @@ -13,24 +13,6 @@ namespace UnityEngine.XR.Tango { - // This must correspond to Tango::CoordinateFrame in TangoTypes.h - internal enum CoordinateFrame - { - GlobalWGS84 = 0, - AreaDescription, - StartOfService, - PreviousDevicePose, - Device, - IMU, - Display, - CameraColor, - CameraDepth, - CameraFisheye, - UUID, - Invalid, - MaxCoordinateFrameType - } - internal enum PoseStatus { Initializing = 0, @@ -41,31 +23,16 @@ internal enum PoseStatus [UsedByNativeCode] [NativeHeader("ARScriptingClasses.h")] - [StructLayout(LayoutKind.Explicit, Size = 8)] - internal struct CoordinateFramePair - { - [FieldOffset(0)] public CoordinateFrame baseFrame; - [FieldOffset(4)] public CoordinateFrame targetFrame; - } - - [UsedByNativeCode] - [NativeHeader("ARScriptingClasses.h")] - [StructLayout(LayoutKind.Explicit, Size = 92)] internal struct PoseData { - [FieldOffset(0)] public uint version; - [FieldOffset(8)] public double timestamp; - [FieldOffset(16)] public double orientation_x; - [FieldOffset(24)] public double orientation_y; - [FieldOffset(32)] public double orientation_z; - [FieldOffset(40)] public double orientation_w; - [FieldOffset(48)] public double translation_x; - [FieldOffset(56)] public double translation_y; - [FieldOffset(64)] public double translation_z; - [FieldOffset(72)] public PoseStatus statusCode; - [FieldOffset(76)] public CoordinateFramePair frame; - [FieldOffset(84)] public uint confidence; - [FieldOffset(88)] public float accuracy; + public double orientation_x; + public double orientation_y; + public double orientation_z; + public double orientation_w; + public double translation_x; + public double translation_y; + public double translation_z; + public PoseStatus statusCode; public Quaternion rotation { @@ -78,24 +45,15 @@ public Vector3 position } } - [NativeHeader("Runtime/AR/Tango/TangoScriptApi.h")] [NativeConditional("PLATFORM_ANDROID")] internal static partial class TangoInputTracking { - extern private static bool Internal_TryGetPoseAtTime(double time, ScreenOrientation screenOrientation, - CoordinateFrame baseFrame, CoordinateFrame targetFrame, out PoseData pose); - - internal static bool TryGetPoseAtTime(out PoseData pose, CoordinateFrame baseFrame, CoordinateFrame targetFrame, - double time, ScreenOrientation screenOrientation) - { - return Internal_TryGetPoseAtTime(time, screenOrientation, baseFrame, targetFrame, out pose); - } + extern private static bool Internal_TryGetPoseAtTime(out PoseData pose); - internal static bool TryGetPoseAtTime(out PoseData pose, CoordinateFrame baseFrame, CoordinateFrame targetFrame, - double time = 0.0) + internal static bool TryGetPoseAtTime(out PoseData pose) { - return Internal_TryGetPoseAtTime(time, Screen.orientation, baseFrame, targetFrame, out pose); + return Internal_TryGetPoseAtTime(out pose); } } } From 95eee03f136b8bf8a9afd5d43fef5b919ba90c55 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 24 Oct 2018 09:18:44 +0000 Subject: [PATCH 05/10] Unity 2018.3.0b7 C# reference source code --- .../SpriteFrameModuleBaseView.cs | 12 +- .../Animation/AnimationWindow/CurveEditor.cs | 7 + Editor/Mono/EditorHandles/FreeMove.cs | 4 +- Editor/Mono/EditorHandles/PositionHandle.cs | 2 +- Editor/Mono/EditorHandles/VertexSnapping.cs | 73 ++---- Editor/Mono/GUI/CreateAssetUtility.cs | 17 +- Editor/Mono/GUI/Tools/BuiltinTools.cs | 2 +- .../AssetOrGameObjectTreeViewDragging.cs | 10 +- Editor/Mono/GameView/GameViewSizes.cs | 10 +- Editor/Mono/Inspector/Editor.cs | 29 +-- Editor/Mono/Inspector/GameObjectInspector.cs | 58 ++++- .../Mono/Inspector/PolygonCollider2DEditor.cs | 3 +- Editor/Mono/Inspector/PreviewRenderUtility.cs | 11 +- .../Mono/Inspector/ReflectionProbeEditor.cs | 2 +- .../Mono/Inspector/ShaderImporterInspector.cs | 5 + .../Inspector/ShaderIncludePathAttribute.cs | 1 + Editor/Mono/Inspector/ShaderInspector.cs | 16 ++ Editor/Mono/PlayerSettingsAndroid.bindings.cs | 8 + Editor/Mono/Prefabs/PrefabUtility.cs | 39 +-- .../PreferencesSettingsProviders.cs | 4 +- .../Mono/ProjectWindow/ProjectWindowUtil.cs | 3 +- Editor/Mono/SceneHierarchyStageHandling.cs | 13 +- Editor/Mono/SceneView/SceneView.cs | 5 + .../Mono/SceneView/SceneViewStageHandling.cs | 6 +- .../ScriptCompilation/EditorCompilation.cs | 20 +- .../EditorCompilationInterface.cs | 12 + Editor/Mono/Settings.cs | 9 +- Editor/Mono/Settings/SettingsService.cs | 23 +- Editor/Mono/Settings/SettingsWindow.cs | 2 +- Editor/Mono/ShaderUtil.bindings.cs | 2 + Editor/Mono/UIElements/Controls/CurveField.cs | 8 +- Editor/Mono/Undo/Undo.bindings.cs | 4 +- Editor/Mono/Utils/StateCache.cs | 132 +++++++--- .../ImportSettings/PluginImporterInspector.cs | 15 +- .../AnalyticsSettings.bindings.cs | 2 + .../ScriptBindings/GridLayout.bindings.cs | 5 + .../Editor/Managed/PackageManagerCommands.cs | 8 +- .../ProfilerWindow/ProfilerTimelineGUI.cs | 23 +- .../ShortcutManagerEditor/KeyCombination.cs | 232 ++++++++++++++++++ .../ShortcutAttribute.cs | 11 +- .../ShortcutAttributeDiscoveryProvider.cs | 2 +- .../ShortcutManagerEditor/ShortcutEntry.cs | 204 +-------------- .../ShortcutProfileManager.cs | 9 +- Modules/ShortcutManagerEditor/Trigger.cs | 2 +- .../Editor/Managed/SpriteMaskEditor.cs | 3 +- Modules/Terrain/Public/PaintContext.cs | 205 +++++++--------- Modules/Terrain/Public/TerrainPaintUtility.cs | 40 +-- .../PaintTools/PaintTextureTool.cs | 7 +- Modules/TerrainEditor/TerrainInspector.cs | 19 ++ .../Utilities/TerrainPaintUtilityEditor.cs | 2 +- Modules/TextCore/Managed/OpenTypeCommon.cs | 161 ++++++++++++ .../ScriptBindings/FontEngine.bindings.cs | 36 ++- .../ScriptBindings/Tilemap.bindings.cs | 36 +++ .../Editor/Managed/Grid/GridBrush.cs | 121 +++++---- .../Editor/Managed/Grid/GridBrushEditor.cs | 5 - Modules/UIElements/ListView.cs | 7 + Modules/UIElements/Panel.cs | 4 +- .../Public/UnityAnalytics.bindings.cs | 35 +++ .../ScriptBindings/VisualEffect.bindings.cs | 2 +- .../VisualEffectResource.bindings.cs | 1 - .../VisualEffectUtility.bindings.cs | 8 + Projects/CSharp/UnityEditor.csproj | 3 + Projects/CSharp/UnityEngine.csproj | 3 + README.md | 2 +- Runtime/Export/AssemblyInfo.cs | 2 +- Runtime/Export/Graphics.bindings.cs | 25 ++ Runtime/Export/Logger/DebugLogHandler.cs | 3 + Runtime/Export/PlayerLoop.bindings.cs | 4 +- .../RenderPipeline/CullingParameters.cs | 1 + .../ScriptBindings/ParticleSystem.bindings.cs | 8 +- .../ScriptBindings/Profiler.bindings.cs | 2 +- 71 files changed, 1156 insertions(+), 654 deletions(-) create mode 100644 Modules/ShortcutManagerEditor/KeyCombination.cs create mode 100644 Modules/TextCore/Managed/OpenTypeCommon.cs diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs index d4c6622975..5415fd398d 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs @@ -200,9 +200,9 @@ private void AddMainUI(VisualElement mainView) if (hasSelected) { var border = selectedSpriteBorder; - border.y = evt.newValue; + border.w = evt.newValue; selectedSpriteBorder = border; - m_BorderFieldT.SetValueWithoutNotify((long)selectedSpriteBorder.y); + m_BorderFieldT.SetValueWithoutNotify((long)selectedSpriteBorder.w); evt.StopPropagation(); } }); @@ -225,9 +225,9 @@ private void AddMainUI(VisualElement mainView) if (hasSelected) { var border = selectedSpriteBorder; - border.w = evt.newValue; + border.y = evt.newValue; selectedSpriteBorder = border; - m_BorderFieldB.SetValueWithoutNotify((long)selectedSpriteBorder.w); + m_BorderFieldB.SetValueWithoutNotify((long)selectedSpriteBorder.y); } }); @@ -335,9 +335,9 @@ protected void PopulateSpriteFrameInspectorField() m_PositionFieldH.SetValueWithoutNotify(Mathf.RoundToInt(spriteRect.height)); var spriteBorder = selectedSpriteBorder; m_BorderFieldL.SetValueWithoutNotify(Mathf.RoundToInt(spriteBorder.x)); - m_BorderFieldT.SetValueWithoutNotify(Mathf.RoundToInt(spriteBorder.y)); + m_BorderFieldT.SetValueWithoutNotify(Mathf.RoundToInt(spriteBorder.w)); m_BorderFieldR.SetValueWithoutNotify(Mathf.RoundToInt(spriteBorder.z)); - m_BorderFieldB.SetValueWithoutNotify(Mathf.RoundToInt(spriteBorder.w)); + m_BorderFieldB.SetValueWithoutNotify(Mathf.RoundToInt(spriteBorder.y)); m_PivotField.SetValueWithoutNotify(selectedSpriteAlignment); m_PivotUnitModeField.SetValueWithoutNotify(m_PivotUnitMode); Vector2 pivot = selectedSpritePivotInCurUnitMode; diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs index be328b707c..148c5711eb 100644 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs +++ b/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs @@ -51,6 +51,13 @@ public CurveWrapper() setAxisUiScalarsCallback = null; } + // Fix for case 1086532 - Audio source inspector leaks memory + ~CurveWrapper() + { + if (m_Renderer != null) + m_Renderer.FlushCache(); + } + internal enum SelectionMode { None = 0, diff --git a/Editor/Mono/EditorHandles/FreeMove.cs b/Editor/Mono/EditorHandles/FreeMove.cs index e360b44307..c173d409cd 100644 --- a/Editor/Mono/EditorHandles/FreeMove.cs +++ b/Editor/Mono/EditorHandles/FreeMove.cs @@ -22,7 +22,7 @@ public static Vector3 Do(int id, Vector3 position, Quaternion rotation, float si Vector3 worldPosition = Handles.matrix.MultiplyPoint(position); Matrix4x4 origMatrix = Handles.matrix; - VertexSnapping.HandleKeyAndMouseMove(id); + VertexSnapping.HandleMouseMove(id); Event evt = Event.current; switch (evt.GetTypeForControl(id)) @@ -162,7 +162,7 @@ public static Vector3 Do(int id, Vector3 position, Quaternion rotation, float si Vector3 worldPosition = Handles.matrix.MultiplyPoint(position); Matrix4x4 origMatrix = Handles.matrix; - VertexSnapping.HandleKeyAndMouseMove(id); + VertexSnapping.HandleMouseMove(id); Event evt = Event.current; switch (evt.GetTypeForControl(id)) diff --git a/Editor/Mono/EditorHandles/PositionHandle.cs b/Editor/Mono/EditorHandles/PositionHandle.cs index 973f78afa1..3867e4613c 100644 --- a/Editor/Mono/EditorHandles/PositionHandle.cs +++ b/Editor/Mono/EditorHandles/PositionHandle.cs @@ -322,7 +322,7 @@ static Vector3 DoPositionHandle_Internal(PositionHandleIds ids, Vector3 position } } - VertexSnapping.HandleKeyAndMouseMove(ids.xyz); + VertexSnapping.HandleMouseMove(ids.xyz); if (param.ShouldShow(PositionHandleParam.Handle.XYZ) && (isHot && ids.xyz == GUIUtility.hotControl || !isHot)) { color = ToActiveColorSpace(centerColor); diff --git a/Editor/Mono/EditorHandles/VertexSnapping.cs b/Editor/Mono/EditorHandles/VertexSnapping.cs index 69f94eafa6..5bc6bf1780 100644 --- a/Editor/Mono/EditorHandles/VertexSnapping.cs +++ b/Editor/Mono/EditorHandles/VertexSnapping.cs @@ -3,7 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using UnityEngine; -using UnityEditor; +using UnityEditor.ShortcutManagement; namespace UnityEditor { @@ -11,7 +11,27 @@ internal class VertexSnapping { private static Vector3 s_VertexSnappingOffset = Vector3.zero; - // This method handles KeyUp, KeyDown and MouseMove for doing vertex snapping. + [Shortcut("Scene View/Toggle Vertex Snapping", typeof(SceneView), "#v")] + private static void ToggleVertexSnappingViaShortcut() + { + int id = GUIUtility.hotControl; + if (Tools.vertexDragging) + DisableVertexSnapping(id); + else + EnableVertexSnapping(id); + } + + [ClutchShortcut("Scene View/Vertex Snapping", typeof(SceneView), "v")] + private static void ToggleVertexSnappingViaClutchShortcut(ShortcutArguments arguments) + { + int id = GUIUtility.hotControl; + if (arguments.state == ShortcutState.Begin) + EnableVertexSnapping(id); + else + DisableVertexSnapping(id); + } + + // This method handles MouseMove for doing vertex snapping. // To ensure correct behaviour the caller must do on it's own: // - On MouseDown and MouseUp (if event is ours to use): // HandleUtility.ignoreRaySnapObjects = null; @@ -29,52 +49,13 @@ internal class VertexSnapping // // This is not the most elegant code-reuse solution, // but still a step up from the copy-pasted code that was used before. - public static void HandleKeyAndMouseMove(int id) + public static void HandleMouseMove(int id) { - Event evt = Event.current; - switch (evt.GetTypeForControl(id)) + var evt = Event.current; + if (evt.GetTypeForControl(id) == EventType.MouseMove && Tools.vertexDragging) { - case EventType.MouseMove: - { - if (Tools.vertexDragging) - { - EnableVertexSnapping(id); - evt.Use(); - } - break; - } - case EventType.KeyDown: - { - // Vertex selection - if (!EditorGUIUtility.editingTextField && evt.keyCode == KeyCode.V) - { - // We are searching for a vertex in our selection - if (!Tools.vertexDragging && !evt.shift) - EnableVertexSnapping(id); - - evt.Use(); - } - break; - } - case EventType.KeyUp: - { - // Vertex selection - if (!EditorGUIUtility.editingTextField && evt.keyCode == KeyCode.V) - { - if (evt.shift) - Tools.vertexDragging = !Tools.vertexDragging; // toggle vertex dragging - else if (Tools.vertexDragging) - Tools.vertexDragging = false; // stop vertex dragging - - if (Tools.vertexDragging) - EnableVertexSnapping(id); - else - DisableVertexSnapping(id); - - evt.Use(); - } - break; - } + EnableVertexSnapping(id); + evt.Use(); } } diff --git a/Editor/Mono/GUI/CreateAssetUtility.cs b/Editor/Mono/GUI/CreateAssetUtility.cs index c33f28754c..d3b75392c6 100644 --- a/Editor/Mono/GUI/CreateAssetUtility.cs +++ b/Editor/Mono/GUI/CreateAssetUtility.cs @@ -4,6 +4,7 @@ using System.IO; using UnityEditor.ProjectWindowCallback; +using UnityEditor.Utils; using UnityEngine; @@ -44,7 +45,7 @@ public Texture2D icon public string folder { - get { return Path.GetDirectoryName(m_Path); } + get { return Path.GetDirectoryName(m_Path).ConvertSeparatorsToUnity(); } } public string extension @@ -77,19 +78,23 @@ static bool IsPathDataValid(string filePath) // Selection changes when calling BeginNewAsset if it succeeds public bool BeginNewAssetCreation(int instanceID, EndNameEditAction newAssetEndAction, string filePath, Texture2D icon, string newAssetResourceFile) { + //Sanitize input + string sanitizedFilePath = filePath != null ? filePath.ConvertSeparatorsToUnity() : filePath; + string sanitizedNewAssetResourceFile = newAssetResourceFile != null ? newAssetResourceFile.ConvertSeparatorsToUnity() : newAssetResourceFile; + string uniquePath; - if (!filePath.StartsWith("assets/", System.StringComparison.CurrentCultureIgnoreCase)) + if (!sanitizedFilePath.StartsWith("assets/", System.StringComparison.CurrentCultureIgnoreCase)) { - uniquePath = AssetDatabase.GetUniquePathNameAtSelectedPath(filePath); + uniquePath = AssetDatabase.GetUniquePathNameAtSelectedPath(sanitizedFilePath); } else { - uniquePath = AssetDatabase.GenerateUniqueAssetPath(filePath); + uniquePath = AssetDatabase.GenerateUniqueAssetPath(sanitizedFilePath); } if (!IsPathDataValid(uniquePath)) { - Debug.LogErrorFormat("Invalid generated unique path '{0}' (input path '{1}')", uniquePath, filePath); + Debug.LogErrorFormat("Invalid generated unique path '{0}' (input path '{1}')", uniquePath, sanitizedFilePath); Clear(); return false; } @@ -98,7 +103,7 @@ public bool BeginNewAssetCreation(int instanceID, EndNameEditAction newAssetEndA m_Path = uniquePath; m_Icon = icon; m_EndAction = newAssetEndAction; - m_ResourceFile = newAssetResourceFile; + m_ResourceFile = sanitizedNewAssetResourceFile; // Change selection to none or instanceID Selection.activeObject = EditorUtility.InstanceIDToObject(instanceID); diff --git a/Editor/Mono/GUI/Tools/BuiltinTools.cs b/Editor/Mono/GUI/Tools/BuiltinTools.cs index 77f9d67c7f..0f11f1031b 100644 --- a/Editor/Mono/GUI/Tools/BuiltinTools.cs +++ b/Editor/Mono/GUI/Tools/BuiltinTools.cs @@ -663,7 +663,7 @@ static Vector3 MoveHandlesGUI(Rect rect, Vector3 pivot, Quaternion rotation) corners[2] = rotation * new Vector2(rect.xMax, rect.yMax) + pivot; corners[3] = rotation * new Vector2(rect.x, rect.yMax) + pivot; - VertexSnapping.HandleKeyAndMouseMove(id); + VertexSnapping.HandleMouseMove(id); bool supportsRectSnapping = Selection.transforms.Length == 1 && UnityEditorInternal.InternalEditorUtility.SupportsRectLayout(Selection.activeTransform) && diff --git a/Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs b/Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs index f70b67fb06..d1c9375afd 100644 --- a/Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs +++ b/Editor/Mono/GUI/TreeView/AssetOrGameObjectTreeViewDragging.cs @@ -160,11 +160,6 @@ public override void StartDrag(TreeViewItem draggedItem, List draggedItemID public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewItem targetItem, bool perform, DropPosition dropPos) { - // Scene dragging logic - DragAndDropVisualMode dragSceneResult = DoDragScenes(parentItem as GameObjectTreeViewItem, targetItem as GameObjectTreeViewItem, perform, dropPos); - if (dragSceneResult != DragAndDropVisualMode.None) - return dragSceneResult; - // Allow client to handle drag if (m_CustomDragHandling != null) { @@ -173,6 +168,11 @@ public override DragAndDropVisualMode DoDrag(TreeViewItem parentItem, TreeViewIt return dragResult; } + // Scene dragging logic + DragAndDropVisualMode dragSceneResult = DoDragScenes(parentItem as GameObjectTreeViewItem, targetItem as GameObjectTreeViewItem, perform, dropPos); + if (dragSceneResult != DragAndDropVisualMode.None) + return dragSceneResult; + if (targetItem != null && !IsDropTargetUserModifiable(targetItem as GameObjectTreeViewItem, dropPos)) return DragAndDropVisualMode.Rejected; diff --git a/Editor/Mono/GameView/GameViewSizes.cs b/Editor/Mono/GameView/GameViewSizes.cs index 72b896eda3..c43dd0b614 100644 --- a/Editor/Mono/GameView/GameViewSizes.cs +++ b/Editor/Mono/GameView/GameViewSizes.cs @@ -197,8 +197,12 @@ private void InitBuiltinGroups() // iOS GameViewSize k_iPhone_750p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 750, 1334, "iPhone 1334x750 Portrait"); GameViewSize k_iPhone_750p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1334, 750, "iPhone 1334x750 Landscape"); - GameViewSize k_iPhone_X_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1125, 2436, "iPhoneX 2436x1125 Portrait"); - GameViewSize k_iPhone_X_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2436, 1125, "iPhoneX 2436x1125 Landscape"); + GameViewSize k_iPhone_X_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1125, 2436, "iPhone X/XS 2436x1125 Portrait"); + GameViewSize k_iPhone_X_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2436, 1125, "iPhone X/XS 2436x1125 Landscape"); + GameViewSize k_iPhone_828p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 828, 1792, "iPhone XR 1792x828 Portrait"); + GameViewSize k_iPhone_828p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 1792, 828, "iPhone XR 1792x828 Landscape"); + GameViewSize k_iPhone_1242p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1242, 2688, "iPhone XS Max 2688x1242 Portrait"); + GameViewSize k_iPhone_1242p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2688, 1242, "iPhone XS Max 2688x1242 Landscape"); GameViewSize k_iPad_1536p_Landscape = new GameViewSize(GameViewSizeType.FixedResolution, 2048, 1536, "iPad 2048x1536 Landscape"); GameViewSize k_iPad_1536p_Portrait = new GameViewSize(GameViewSizeType.FixedResolution, 1536, 2048, "iPad 2048x1536 Portrait"); @@ -232,6 +236,8 @@ private void InitBuiltinGroups() k_iPhone_750p_Portrait, k_iPhone_750p_Landscape, k_1080p_Portrait, k_1080p_Landscape, k_iPhone_X_Portrait, k_iPhone_X_Landscape, + k_iPhone_828p_Portrait, k_iPhone_828p_Landscape, + k_iPhone_1242p_Portrait, k_iPhone_1242p_Landscape, k_iPad_1536p_Landscape, k_iPad_1536p_Portrait, k_iPad_2048p_Landscape, k_iPad_2048p_Portrait, k_iPad_1668p_Landscape, k_iPad_1668p_Portrait, diff --git a/Editor/Mono/Inspector/Editor.cs b/Editor/Mono/Inspector/Editor.cs index c4f068ea2f..20bead8071 100644 --- a/Editor/Mono/Inspector/Editor.cs +++ b/Editor/Mono/Inspector/Editor.cs @@ -763,25 +763,19 @@ protected virtual bool ShouldHideOpenButton() internal virtual void OnHeaderIconGUI(Rect iconRect) { Texture2D icon = null; - if (!HasPreviewGUI()) + + // Fetch isLoadingAssetPreview to ensure that there is no situation where a preview needs a repaint because it hasn't finished loading yet. + bool isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(target.GetInstanceID()); + icon = AssetPreview.GetAssetPreview(target); + if (!icon) { - // Fetch isLoadingAssetPreview to ensure that there is no situation where a preview needs a repaint because it hasn't finished loading yet. - bool isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(target.GetInstanceID()); - icon = AssetPreview.GetAssetPreview(target); - if (!icon) - { - // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded. - if (isLoadingAssetPreview) - Repaint(); - icon = AssetPreview.GetMiniThumbnail(target); - } + // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded. + if (isLoadingAssetPreview) + Repaint(); + icon = AssetPreview.GetMiniThumbnail(target); } - if (HasPreviewGUI()) - // OnPreviewGUI must have all events; not just Repaint, or else the control IDs will mis-match. - OnPreviewGUI(iconRect, BaseStyles.inspectorBigInner); - else if (icon) - GUI.Label(iconRect, icon, BaseStyles.centerStyle); + GUI.Label(iconRect, icon, BaseStyles.centerStyle); } internal virtual void OnHeaderTitleGUI(Rect titleRect, string header) @@ -816,9 +810,10 @@ internal virtual void DrawHeaderHelpAndSettingsGUI(Rect r) // draw the header, and then start a new vertical block with the same style. private void DrawHeaderFromInsideHierarchy() { + var style = GUILayoutUtility.topLevel.style; EditorGUILayout.EndVertical(); OnHeaderGUI(); - EditorGUILayout.BeginVertical(GUILayoutUtility.topLevel.style); + EditorGUILayout.BeginVertical(style); } internal static Rect DrawHeaderGUI(Editor editor, string header) diff --git a/Editor/Mono/Inspector/GameObjectInspector.cs b/Editor/Mono/Inspector/GameObjectInspector.cs index ef7ccf6d4f..b984bc1af0 100644 --- a/Editor/Mono/Inspector/GameObjectInspector.cs +++ b/Editor/Mono/Inspector/GameObjectInspector.cs @@ -94,7 +94,6 @@ public Styles() } static Styles s_Styles; const float kIconSize = 24; - Vector2 previewDir; class PreviewData : IDisposable { @@ -130,7 +129,9 @@ public void Dispose() } Dictionary m_PreviewInstances = new Dictionary(); - + Dictionary m_PreviewCache; + Vector2 m_PreviewDir; + Rect m_PreviewRect; bool m_PlayModeObjects; bool m_IsAsset; bool m_ImmutableSelf; @@ -144,9 +145,9 @@ public void Dispose() public void OnEnable() { if (EditorSettings.defaultBehaviorMode == EditorBehaviorMode.Mode2D) - previewDir = new Vector2(0, 0); + m_PreviewDir = new Vector2(0, 0); else - previewDir = new Vector2(120, -20); + m_PreviewDir = new Vector2(120, -20); m_Name = serializedObject.FindProperty("m_Name"); m_IsActive = serializedObject.FindProperty("m_IsActive"); @@ -156,6 +157,8 @@ public void OnEnable() m_Icon = serializedObject.FindProperty("m_Icon"); CalculatePrefabStatus(); + + m_PreviewCache = new Dictionary(); } void CalculatePrefabStatus() @@ -203,7 +206,17 @@ void OnDisable() { foreach (var previewData in m_PreviewInstances.Values) previewData.Dispose(); - m_PreviewInstances.Clear(); + ClearPreviewCache(); + m_PreviewCache = null; + } + + void ClearPreviewCache() + { + foreach (var texture in m_PreviewCache.Values) + { + DestroyImmediate(texture); + } + m_PreviewCache.Clear(); } private static bool ShowMixedStaticEditorFlags(StaticEditorFlags mask) @@ -763,7 +776,7 @@ private void DoRenderPreview() float halfSize = Mathf.Max(bounds.extents.magnitude, 0.0001f); float distance = halfSize * 3.8f; - Quaternion rot = Quaternion.Euler(-previewDir.y, -previewDir.x, 0); + Quaternion rot = Quaternion.Euler(-m_PreviewDir.y, -m_PreviewDir.x, 0); Vector3 pos = bounds.center - rot * (Vector3.forward * distance); previewData.renderUtility.camera.transform.position = pos; @@ -805,17 +818,38 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) return; } - previewDir = PreviewGUI.Drag2D(previewDir, r); + var direction = PreviewGUI.Drag2D(m_PreviewDir, r); + if (direction != m_PreviewDir) + { + // None of the preview are valid since the camera position has changed. + ClearPreviewCache(); + m_PreviewDir = direction; + } if (Event.current.type != EventType.Repaint) return; - var previewUtility = GetPreviewData().renderUtility; - previewUtility.BeginPreview(r, background); - - DoRenderPreview(); + if (m_PreviewRect != r) + { + ClearPreviewCache(); + m_PreviewRect = r; + } - previewUtility.EndAndDrawPreview(r); + var previewUtility = GetPreviewData().renderUtility; + Texture previewTexture; + if (m_PreviewCache.TryGetValue(referenceTargetIndex, out previewTexture)) + { + PreviewRenderUtility.DrawPreview(r, previewTexture); + } + else + { + previewUtility.BeginPreview(r, background); + DoRenderPreview(); + previewUtility.EndAndDrawPreview(r); + var copy = new RenderTexture(previewUtility.renderTexture); + Graphics.CopyTexture(previewUtility.renderTexture, copy); + m_PreviewCache.Add(referenceTargetIndex, copy); + } } // Handle dragging in scene view diff --git a/Editor/Mono/Inspector/PolygonCollider2DEditor.cs b/Editor/Mono/Inspector/PolygonCollider2DEditor.cs index c716ebf9aa..66c0156e20 100644 --- a/Editor/Mono/Inspector/PolygonCollider2DEditor.cs +++ b/Editor/Mono/Inspector/PolygonCollider2DEditor.cs @@ -91,8 +91,9 @@ private void HandleDragAndDrop(Rect targetRect) DragAndDrop.AcceptDrag(); } - return; } + + return; } DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; diff --git a/Editor/Mono/Inspector/PreviewRenderUtility.cs b/Editor/Mono/Inspector/PreviewRenderUtility.cs index 0417154154..6d86f202c5 100644 --- a/Editor/Mono/Inspector/PreviewRenderUtility.cs +++ b/Editor/Mono/Inspector/PreviewRenderUtility.cs @@ -180,7 +180,7 @@ public Light[] lights { get { - return new[] {Light0, Light1}; + return new[] { Light0, Light1 }; } } @@ -341,8 +341,13 @@ private void FinishFrame() public void EndAndDrawPreview(Rect r) { - Texture t = EndPreview(); - GUI.DrawTexture(r, t, ScaleMode.StretchToFill, false); + var texture = EndPreview(); + DrawPreview(r, texture); + } + + internal static void DrawPreview(Rect r, Texture texture) + { + GUI.DrawTexture(r, texture, ScaleMode.StretchToFill, false); } public Texture2D EndStaticPreview() diff --git a/Editor/Mono/Inspector/ReflectionProbeEditor.cs b/Editor/Mono/Inspector/ReflectionProbeEditor.cs index 6d4dd4faee..4d59c4b409 100644 --- a/Editor/Mono/Inspector/ReflectionProbeEditor.cs +++ b/Editor/Mono/Inspector/ReflectionProbeEditor.cs @@ -429,7 +429,7 @@ public override void OnInspectorGUI() EditorGUI.BeginChangeCheck(); EditorGUI.showMixedValue = m_CustomBakedTexture.hasMultipleDifferentValues; - var newCubemap = EditorGUILayout.ObjectField(Styles.customCubemapText, m_CustomBakedTexture.objectReferenceValue, typeof(Cubemap), false); + var newCubemap = EditorGUILayout.ObjectField(Styles.customCubemapText, m_CustomBakedTexture.objectReferenceValue, typeof(Texture), false); EditorGUI.showMixedValue = false; if (EditorGUI.EndChangeCheck()) m_CustomBakedTexture.objectReferenceValue = newCubemap; diff --git a/Editor/Mono/Inspector/ShaderImporterInspector.cs b/Editor/Mono/Inspector/ShaderImporterInspector.cs index f44e2e258b..59b55ca211 100644 --- a/Editor/Mono/Inspector/ShaderImporterInspector.cs +++ b/Editor/Mono/Inspector/ShaderImporterInspector.cs @@ -214,7 +214,12 @@ internal static string[] GetShaderIncludePaths() if (s_ShaderIncludePaths == null) { List results = new List(); + // ShaderIncludePathAttribute has been obsoleted with warning but we keep it working for + // a transition period (2018.x) + // Therefore we need suppress the warning here to make the build succeed. +#pragma warning disable 618 var methods = AttributeHelper.GetMethodsWithAttribute(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.DeclaredOnly); +#pragma warning restore 618 foreach (var method in methods.methodsWithAttributes) { if (method.info.ReturnType == typeof(string[]) && method.info.GetParameters().Length == 0) diff --git a/Editor/Mono/Inspector/ShaderIncludePathAttribute.cs b/Editor/Mono/Inspector/ShaderIncludePathAttribute.cs index 965696df1c..d3887a1ef8 100644 --- a/Editor/Mono/Inspector/ShaderIncludePathAttribute.cs +++ b/Editor/Mono/Inspector/ShaderIncludePathAttribute.cs @@ -6,6 +6,7 @@ namespace UnityEditor { + [Obsolete("[ShaderIncludePath] attribute is being obsoleted. Your shader library should be under the Assets folder or in a package. To include shader headers directly from a package, use #include \"Packages//\"", false)] [AttributeUsage(AttributeTargets.Method)] public class ShaderIncludePathAttribute : Attribute { diff --git a/Editor/Mono/Inspector/ShaderInspector.cs b/Editor/Mono/Inspector/ShaderInspector.cs index 5f22865ed8..b36a6d047b 100644 --- a/Editor/Mono/Inspector/ShaderInspector.cs +++ b/Editor/Mono/Inspector/ShaderInspector.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Globalization; using Object = UnityEngine.Object; +using UnityEngine.Experimental.Rendering; namespace UnityEditor { @@ -103,6 +104,21 @@ public override void OnInspectorGUI() break; } EditorGUILayout.LabelField("Disable batching", disableBatchingString); + + // If any SRP is active, then display the SRP Batcher compatibility status + if (RenderPipelineManager.currentPipeline != null) + { + var mat = new Material(s); + mat.SetPass(0); // NOTE: Force the shader compilation to ensure GetSRPBatcherCompatibilityCode will be up to date + int subShader = ShaderUtil.GetShaderActiveSubshaderIndex(s); + int SRPErrCode = ShaderUtil.GetSRPBatcherCompatibilityCode(s, subShader); + string result = (0 == SRPErrCode) ? "compatible" : "not compatible"; + EditorGUILayout.LabelField("SRP Batcher", result); + if (SRPErrCode != 0) + { + EditorGUILayout.HelpBox(ShaderUtil.GetSRPBatcherCompatibilityIssueReason(s, subShader, SRPErrCode), MessageType.Info); + } + } ShowShaderProperties(s); } } diff --git a/Editor/Mono/PlayerSettingsAndroid.bindings.cs b/Editor/Mono/PlayerSettingsAndroid.bindings.cs index e904f27cff..5a49e97515 100644 --- a/Editor/Mono/PlayerSettingsAndroid.bindings.cs +++ b/Editor/Mono/PlayerSettingsAndroid.bindings.cs @@ -399,6 +399,14 @@ public static extern bool startInFullscreen [NativeMethod("SetAndroidStartInFullscreen")] set; } + + public static extern bool renderOutsideSafeArea + { + [NativeMethod("GetAndroidRenderOutsideSafeArea")] + get; + [NativeMethod("SetAndroidRenderOutsideSafeArea")] + set; + } } } } diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 695db44170..4c262b311d 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -308,20 +308,19 @@ public static void RevertPrefabInstance(GameObject instanceRoot, InteractionMode Undo.RegisterFullObjectHierarchyUndo(prefabInstanceRoot, actionName); } - if (isDisconnected) - { - RevertPrefabInstance_Internal(prefabInstanceRoot); - - if (action == InteractionMode.UserAction) - Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(prefabInstanceRoot), actionName); - } - RevertPrefabInstance_Internal(prefabInstanceRoot); if (action == InteractionMode.UserAction) { + if (isDisconnected) + { + Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(prefabInstanceRoot), actionName); + } + RegisterNewObjects(prefabInstanceRoot, hierarchy, actionName); } + + EditorUtility.ForceRebuildInspectors(); } public static void ApplyPrefabInstance(GameObject instanceRoot, InteractionMode action) @@ -796,24 +795,12 @@ public static void ApplyAddedGameObject(GameObject gameObject, string assetPath, if (action == InteractionMode.UserAction) { var createdAssetObject = GetCorrespondingObjectFromSourceInAsset(gameObject, prefabSourceGameObjectParent); - Undo.RegisterCreatedObjectUndo(createdAssetObject, actionName); - - //var instanceImmediateSourceObject = GetCorrespondingObjectFromSource(prefabInstanceGameObject); - //if (instanceImmediateSourceObject != createdAssetObject) - //{ - // // The asset containing this object is not actually changed and import/merge - // // logic would assure that it is create/deleted correctly based on the changes - // // in the source asset ("createdAssetObject" prefab asset) - // // However, during "redo" the import/merge will happed too late for the - // // following "register created object" operation on the instance object. - // // This would cause the instance to reference a non-existing corresponding - // // object which causes a disconnect. - // Undo.RegisterCreatedObjectUndo(instanceImmediateSourceObject, actionName); - //} - - //Undo.RegisterCreatedObjectUndo(instanceRoot, actionName); - - EditorUtility.ForceRebuildInspectors(); + if (createdAssetObject != null) + { + Undo.RegisterCreatedObjectUndo(createdAssetObject, actionName); + + EditorUtility.ForceRebuildInspectors(); + } } Analytics.SendApplyEvent( diff --git a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs index a17eef3271..50bfeaebfe 100644 --- a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs +++ b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs @@ -674,7 +674,7 @@ private void CheckForCollisions(Event e, ShortcutEntry selectedShortcut, PrefKey // Check shortcuts shortcutController.directory.FindShortcutEntries( - new List {new KeyCombination(e)}, + new List {KeyCombination.FromKeyboardInput(e)}, new[] { context }, collisions); @@ -743,7 +743,7 @@ private void ShowShortcutConfiguration(int controlID, ShortcutEntry selectedShor // TODO: Don't clobber secondary+ combinations var newCombination = new List(); if (e.keyCode != KeyCode.None) - newCombination.Add(new KeyCombination(e)); + newCombination.Add(KeyCombination.FromKeyboardInput(e)); shortcutController.profileManager.ModifyShortcutEntry(selectedShortcut.identifier, newCombination); shortcutController.profileManager.PersistChanges(); } diff --git a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs index 9277fffd56..510893410e 100644 --- a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs +++ b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs @@ -12,6 +12,7 @@ using UnityEditor.SceneManagement; using UnityEditorInternal; using UnityEditor.Experimental; +using UnityEditor.Utils; using UnityEngine; using UnityEngine.Internal; using Object = UnityEngine.Object; @@ -264,7 +265,7 @@ static void CreatePrefabVariant() string sourcePath = AssetDatabase.GetAssetPath(go); - string sourceDir = System.IO.Path.GetDirectoryName(sourcePath); + string sourceDir = Path.GetDirectoryName(sourcePath).ConvertSeparatorsToUnity(); string variantPath = string.Format("{0}/{1} Variant.prefab", sourceDir, go.name); StartNameEditingIfProjectWindowExists( diff --git a/Editor/Mono/SceneHierarchyStageHandling.cs b/Editor/Mono/SceneHierarchyStageHandling.cs index b0dffebe74..91c5ef2645 100644 --- a/Editor/Mono/SceneHierarchyStageHandling.cs +++ b/Editor/Mono/SceneHierarchyStageHandling.cs @@ -29,7 +29,7 @@ static Styles() SceneHierarchy m_SceneHierarchy; SceneHierarchyWindow m_SceneHierarchyWindow; - StateCache m_StateCache = new StateCache("Library/StateCache/Hierarchy/"); + StateCache m_StateCache = new StateCache("Library/StateCache/Hierarchy/"); GUIContent m_PrefabHeaderContent; bool m_LastPrefabStageModifiedState; @@ -142,6 +142,13 @@ static DragAndDropVisualMode PrefabModeDraggingHandler(GameObjectTreeViewItem pa if (parentItem != null && parentItem.parent == null && dropPos != TreeViewDragging.DropPosition.Upon) return DragAndDropVisualMode.Rejected; + // Disallow dragging scenes into the hierarchy when it is in Prefab Mode (we do not support multi-scenes for prefabs yet) + foreach (var dragged in DragAndDrop.objectReferences) + { + if (dragged is SceneAsset) + return DragAndDropVisualMode.Rejected; + } + // Check for cyclic nesting (only on perform since it is an expensive operation) if (perform) { @@ -180,7 +187,7 @@ void SaveHierarchyState(SceneHierarchyWindow hierarchyWindow, StageNavigationIte if (stage == null) return; string key = StageUtility.CreateWindowAndStageIdentifier(hierarchyWindow.windowGUID, stage); - var state = m_StateCache.GetState(key); + var state = m_StateCache.GetState(key); if (state == null) state = new SceneHierarchyState(); state.SaveStateFromHierarchy(hierarchyWindow, stage); @@ -190,7 +197,7 @@ void SaveHierarchyState(SceneHierarchyWindow hierarchyWindow, StageNavigationIte SceneHierarchyState GetStoredHierarchyState(SceneHierarchyWindow hierarchyWindow, StageNavigationItem stage) { string key = StageUtility.CreateWindowAndStageIdentifier(hierarchyWindow.windowGUID, stage); - return m_StateCache.GetState(key); + return m_StateCache.GetState(key); } void LoadHierarchyState(SceneHierarchyWindow hierarchy, StageNavigationItem stage) diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index 9702700750..c7c84b2df4 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -1439,8 +1439,13 @@ void DoClearCamera(Rect cameraRect) // for the skybox we always want to use the same FOV. float skyboxFOV = GetVerticalFOV(kPerspectiveFov); float realFOV = m_Camera.fieldOfView; + + var clearFlags = m_Camera.clearFlags; + if (GraphicsSettings.renderPipelineAsset != null) + m_Camera.clearFlags = CameraClearFlags.Color; m_Camera.fieldOfView = skyboxFOV; Handles.ClearCamera(cameraRect, m_Camera); + m_Camera.clearFlags = clearFlags; m_Camera.fieldOfView = realFOV; } diff --git a/Editor/Mono/SceneView/SceneViewStageHandling.cs b/Editor/Mono/SceneView/SceneViewStageHandling.cs index 4173497993..e73661f5a2 100644 --- a/Editor/Mono/SceneView/SceneViewStageHandling.cs +++ b/Editor/Mono/SceneView/SceneViewStageHandling.cs @@ -16,7 +16,7 @@ namespace UnityEditor class SceneViewStageHandling { SceneView m_SceneView; - StateCache m_StateCache = new StateCache("Library/StateCache/SceneView/"); + StateCache m_StateCache = new StateCache("Library/StateCache/SceneView/"); public BreadcrumbBar m_BreadcrumbBar = new BreadcrumbBar(); public bool m_BreadcrumbInitialized; @@ -188,7 +188,7 @@ void SaveCameraState(SceneView sceneView, StageNavigationItem stage) if (stage == null) return; string key = StageUtility.CreateWindowAndStageIdentifier(sceneView.windowGUID, stage); - var state = m_StateCache.GetState(key); + var state = m_StateCache.GetState(key); if (state == null) state = new SceneViewCameraState(); state.SaveStateFromSceneView(sceneView); @@ -198,7 +198,7 @@ void SaveCameraState(SceneView sceneView, StageNavigationItem stage) SceneViewCameraState GetStoredCameraState(SceneView sceneView, StageNavigationItem stage) { string key = StageUtility.CreateWindowAndStageIdentifier(sceneView.windowGUID, stage); - return m_StateCache.GetState(key); + return m_StateCache.GetState(key); } void LoadCameraState(SceneView sceneView, StageNavigationItem stage) diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 5f5e896a54..af0ba707ea 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -165,6 +165,7 @@ public override void PostprocessMessage(ref CompilerMessage message) HashSet dirtyTargetAssemblies = new HashSet(); HashSet dirtyPrecompiledAssemblies = new HashSet(); HashSet runScriptUpdaterAssemblies = new HashSet(); + bool recompileAllScriptsOnNextTick; PrecompiledAssembly[] precompiledAssemblies; CustomScriptAssembly[] customScriptAssemblies = new CustomScriptAssembly[0]; EditorBuildRules.TargetAssembly[] customTargetAssemblies; // TargetAssemblies for customScriptAssemblies. @@ -299,6 +300,16 @@ public void DirtyPrecompiledAssembly(string path) } } + public void RecompileAllScriptsOnNextTick() + { + recompileAllScriptsOnNextTick = true; + } + + public bool WillRecompileAllScriptsOnNextTick() + { + return recompileAllScriptsOnNextTick; + } + public void ClearDirtyScripts() { dirtyScripts.Clear(); @@ -1211,7 +1222,8 @@ public bool IsCompilationPending() // then compilation will trigger on next TickCompilationPipeline. return DoesProjectFolderHaveAnyDirtyScripts() || ArePrecompiledAssembliesDirty() || - runScriptUpdaterAssemblies.Count() > 0; + runScriptUpdaterAssemblies.Count() > 0 || + recompileAllScriptsOnNextTick; } public bool IsAnyAssemblyBuilderCompiling() @@ -1290,6 +1302,12 @@ public CompileStatus TickCompilationPipeline(EditorScriptCompilationOptions opti if (IsAnyAssemblyBuilderCompiling()) return CompileStatus.Compiling; + if (recompileAllScriptsOnNextTick) + { + DirtyAllScripts(); + recompileAllScriptsOnNextTick = false; + } + // If we are not currently compiling and there are dirty scripts, start compilation. if (!IsCompilationTaskCompiling() && IsCompilationPending()) { diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs index e51ed2fc6c..7ed7b46dfe 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs @@ -173,6 +173,18 @@ public static void ClearDirtyScripts() Instance.ClearDirtyScripts(); } + [RequiredByNativeCode] + public static void RecompileAllScriptsOnNextTick() + { + Instance.RecompileAllScriptsOnNextTick(); + } + + [RequiredByNativeCode] + public static bool WillRecompileAllScriptsOnNextTick() + { + return Instance.WillRecompileAllScriptsOnNextTick(); + } + [RequiredByNativeCode] public static void RunScriptUpdaterOnAssembly(string assemblyFilename) { diff --git a/Editor/Mono/Settings.cs b/Editor/Mono/Settings.cs index 3c1b5e3b5a..802ebf111e 100644 --- a/Editor/Mono/Settings.cs +++ b/Editor/Mono/Settings.cs @@ -235,25 +235,28 @@ public bool activated } } - internal static bool TryParseUniquePrefString(string prefString, out string name, out Event keyboardEvent) + internal static bool TryParseUniquePrefString(string prefString, out string name, out Event keyboardEvent, out string shortcut) { int i = prefString.IndexOf(";"); if (i < 0) { name = null; keyboardEvent = null; + shortcut = null; return false; } name = prefString.Substring(0, i); - keyboardEvent = Event.KeyboardEvent(prefString.Substring(i + 1)); + shortcut = prefString.Substring(i + 1); + keyboardEvent = Event.KeyboardEvent(shortcut); return true; } public void FromUniqueString(string s) { Load(); - if (!TryParseUniquePrefString(s, out m_name, out m_event)) + if (!TryParseUniquePrefString(s, out m_name, out m_event, out m_Shortcut)) Debug.LogError("Malformed string in Keyboard preferences"); + m_DefaultShortcut = m_Shortcut; } internal void ResetToDefault() diff --git a/Editor/Mono/Settings/SettingsService.cs b/Editor/Mono/Settings/SettingsService.cs index 8ca28cfcb2..2e50c92f30 100644 --- a/Editor/Mono/Settings/SettingsService.cs +++ b/Editor/Mono/Settings/SettingsService.cs @@ -19,8 +19,6 @@ public class SettingsService const string k_ProjectSettings = "Edit/Project Settings"; static SettingsService() { - EditorApplication.update -= CheckProjectSettings; - EditorApplication.update += CheckProjectSettings; } public static event Action settingsProviderChanged; @@ -30,7 +28,7 @@ public static SettingsProvider[] FetchSettingsProviders() return FetchSettingProviderFromAttribute() .Concat(FetchSettingProvidersFromAttribute()) - .Concat(FetchPreferenceItems()) + .Concat(FetchDeprecatedPreferenceItems()) .Where(provider => provider != null) .ToArray(); } @@ -40,23 +38,7 @@ public static void NotifySettingsProviderChanged() settingsProviderChanged?.Invoke(); } - private static void CheckProjectSettings() - { - EditorApplication.update -= CheckProjectSettings; - - var deprecatedMenuItems = Menu.ExtractSubmenus(k_ProjectSettings); - if (deprecatedMenuItems.Length > 0) - { - var sb = new StringBuilder(); - sb.Append("There are menu items registered under Edit/Project Settings: "); - sb.Append(string.Join(", ", deprecatedMenuItems.Select(item => item.Replace(k_ProjectSettings + "/", "")).ToArray())); - sb.Append("\n"); - sb.AppendLine("Consider using [SettingsProvider] attribute to register in the Unified Settings Window."); - Debug.LogWarning(sb); - } - } - - private static IEnumerable FetchPreferenceItems() + private static IEnumerable FetchDeprecatedPreferenceItems() { var methods = AttributeHelper.GetMethodsWithAttribute(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); return methods.methodsWithAttributes.Select(method => @@ -65,7 +47,6 @@ private static IEnumerable FetchPreferenceItems() if (callback != null) { var attributeName = (method.attribute as PreferenceItem).name; - Debug.LogWarning($"Trying to register preference item: \"{attributeName}\". [PreferenceItem] attribute is deprecated. Use [SettingsProvider] attribute instead."); return new SettingsProvider("Preferences/" + attributeName) { guiHandler = searchContext => callback(), scopes = SettingsScopes.User }; } diff --git a/Editor/Mono/Settings/SettingsWindow.cs b/Editor/Mono/Settings/SettingsWindow.cs index cf6b61a8ba..6bc3ce7cfa 100644 --- a/Editor/Mono/Settings/SettingsWindow.cs +++ b/Editor/Mono/Settings/SettingsWindow.cs @@ -339,7 +339,7 @@ internal static void OpenAllSettings() OpenAllSettings(null); } - [MenuItem("Edit/Settings", false, 259, false)] + [MenuItem("Edit/Project Settings...", false, 259, false)] internal static void OpenProjectSettings() { OpenProjectSettings(null); diff --git a/Editor/Mono/ShaderUtil.bindings.cs b/Editor/Mono/ShaderUtil.bindings.cs index cc93b82a05..500172a595 100644 --- a/Editor/Mono/ShaderUtil.bindings.cs +++ b/Editor/Mono/ShaderUtil.bindings.cs @@ -157,6 +157,8 @@ public static bool IsShaderPropertyNonModifiableTexureProperty(Shader s, int pro extern internal static int GetTextureBindingIndex(Shader s, int texturePropertyID); extern internal static int GetTextureSamplerBindingIndex(Shader s, int texturePropertyID); extern internal static int GetLOD(Shader s); + extern internal static int GetSRPBatcherCompatibilityCode(Shader s, int subShaderIdx); + extern internal static string GetSRPBatcherCompatibilityIssueReason(Shader s, int subShaderIdx, int err); extern internal static ulong GetVariantCount(Shader s, bool usedBySceneOnly); extern internal static int GetComputeShaderPlatformCount(ComputeShader s); diff --git a/Editor/Mono/UIElements/Controls/CurveField.cs b/Editor/Mono/UIElements/Controls/CurveField.cs index e6a2f58051..9bfd43d676 100644 --- a/Editor/Mono/UIElements/Controls/CurveField.cs +++ b/Editor/Mono/UIElements/Controls/CurveField.cs @@ -149,7 +149,11 @@ public override void SetValueWithoutNotify(AnimationCurve newValue) m_Value.postWrapMode = WrapMode.Once; } m_TextureDirty = true; - CurveEditorWindow.curve = m_Value; + if (CurveEditorWindow.visible && Object.ReferenceEquals(CurveEditorWindow.curve, m_Value)) + { + CurveEditorWindow.curve = m_Value; + CurveEditorWindow.instance.Repaint(); + } IncrementVersion(VersionChangeType.Repaint); @@ -178,10 +182,10 @@ void ShowCurveEditor() CurveEditorSettings settings = new CurveEditorSettings(); if (m_Value == null) m_Value = new AnimationCurve(); + CurveEditorWindow.instance.Show(OnCurveChanged, settings); CurveEditorWindow.curve = m_Value; CurveEditorWindow.color = curveColor; - CurveEditorWindow.instance.Show(OnCurveChanged, settings); } protected internal override void ExecuteDefaultAction(EventBase evt) diff --git a/Editor/Mono/Undo/Undo.bindings.cs b/Editor/Mono/Undo/Undo.bindings.cs index 094c9980e3..c9db0a16eb 100644 --- a/Editor/Mono/Undo/Undo.bindings.cs +++ b/Editor/Mono/Undo/Undo.bindings.cs @@ -78,9 +78,11 @@ public static void DestroyObjectImmediate(Object objectToUndo) DestroyObjectUndoable(objectToUndo, "Destroy Object"); } - [FreeFunction] + [NativeThrows] + [StaticAccessor("UndoBindings", StaticAccessorType.DoubleColon)] internal static extern void DestroyObjectUndoable([NotNull] Object objectToUndo, string name); + [NativeThrows] [StaticAccessor("UndoBindings", StaticAccessorType.DoubleColon)] public static extern Component AddComponent([NotNull] GameObject gameObject, Type type); diff --git a/Editor/Mono/Utils/StateCache.cs b/Editor/Mono/Utils/StateCache.cs index f509b1a376..e24a23ac21 100644 --- a/Editor/Mono/Utils/StateCache.cs +++ b/Editor/Mono/Utils/StateCache.cs @@ -2,74 +2,126 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; using System.Collections.Generic; using System.Text; +using UnityEditor.Utils; using UnityEngine; namespace UnityEditor { - class StateCache + class StateCache { - string m_CacheFolder = "Library/StateCache/"; - Dictionary m_Cache = new Dictionary(); + string m_CacheFolder; + Dictionary m_Cache = new Dictionary(); - public StateCache() + public StateCache(string cacheFolder) { - } + if (string.IsNullOrEmpty(cacheFolder)) + throw new ArgumentException("cacheFolder cannot be null or empty string", cacheFolder); - public StateCache(string cacheFolderPath) - { - if (ValidateCacheFolder(cacheFolderPath)) - m_CacheFolder = cacheFolderPath; + if (cacheFolder.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0) + { + throw new ArgumentException("Cache folder path has invalid path characters: '" + cacheFolder + "'"); + } + + cacheFolder = cacheFolder.ConvertSeparatorsToUnity(); + if (!cacheFolder.EndsWith("/")) + { + Debug.LogError("The cache folder path should end with a forward slash: '/'. Path: " + cacheFolder + ". Fixed up."); + cacheFolder += "/"; + } + if (cacheFolder.StartsWith("/")) + { + Debug.LogError("The cache folder path should not start with a forward slash: '/'. Path: " + cacheFolder + ". Fixed up."); // since on OSX a leading '/' means the root directory + cacheFolder = cacheFolder.TrimStart(new[] { '/' }); + } + + m_CacheFolder = cacheFolder; } - public void SetState(string key, T obj) + public string cacheFolderPath { get { return m_CacheFolder; } } + + public void SetState(string key, T obj) { + if (string.IsNullOrEmpty(key)) + throw new ArgumentException("key cannot be null or empty string", key); + + if (obj == null) + throw new ArgumentNullException("obj"); + string json = JsonUtility.ToJson(obj); - m_Cache[key] = json; - var filePath = GetFilePath(key); - string directory = System.IO.Path.GetDirectoryName(filePath); - System.IO.Directory.CreateDirectory(directory); - System.IO.File.WriteAllText(filePath, json, Encoding.UTF8); // Persist state + var filePath = GetFilePathForKey(key); + try + { + string directory = System.IO.Path.GetDirectoryName(filePath); + System.IO.Directory.CreateDirectory(directory); + System.IO.File.WriteAllText(filePath, json, Encoding.UTF8); // Persist state + } + catch (Exception e) + { + Debug.LogError(string.Format("Error saving file {0}. Error: {1}", filePath, e.ToString())); + } + + m_Cache[key] = obj; } - public T GetState(string key) + public T GetState(string key) { - string jsonString; - if (!m_Cache.TryGetValue(key, out jsonString)) + if (string.IsNullOrEmpty(key)) + throw new ArgumentException("key cannot be null or empty string", key); + + T obj; + if (m_Cache.TryGetValue(key, out obj)) + return obj; + + string filePath = GetFilePathForKey(key); + if (System.IO.File.Exists(filePath)) { - if (System.IO.File.Exists(GetFilePath(key))) - jsonString = System.IO.File.ReadAllText(GetFilePath(key)); // Fetch persisted state + string jsonString = null; + try + { + jsonString = System.IO.File.ReadAllText(filePath, Encoding.UTF8); + } + catch (Exception e) + { + Debug.LogError(string.Format("Error loading file {0}. Error: {1}", filePath, e.ToString())); + return default(T); + } + + try + { + obj = JsonUtility.FromJson(jsonString); + } + catch (ArgumentException exception) + { + Debug.LogError(string.Format("Invalid file content for {0}. Removing file. Error: {1}", filePath, exception.ToString())); + RemoveState(key); + return default(T); + } + + m_Cache[key] = obj; + return obj; } - return JsonUtility.FromJson(jsonString); + + return default(T); } public void RemoveState(string key) { + if (string.IsNullOrEmpty(key)) + throw new ArgumentException("key cannot be null or empty string", key); + m_Cache.Remove(key); - System.IO.File.Delete(GetFilePath(key)); - } - string GetFilePath(string fileName) - { - return m_CacheFolder + fileName + ".json"; + string filePath = GetFilePathForKey(key); + if (System.IO.File.Exists(filePath)) + System.IO.File.Delete(filePath); } - bool ValidateCacheFolder(string cacheFolder) + public string GetFilePathForKey(string key) { - if (string.IsNullOrEmpty(cacheFolder)) - { - Debug.LogError("Invalid cache folder: Is null or empty"); - return false; - } - - if (!m_CacheFolder.EndsWith("/")) - { - Debug.LogError("The cache folder path provided should end with a forward slash: '/'. Path provided: " + m_CacheFolder); - return false; - } - - return true; + return m_CacheFolder + key + ".json"; } } } diff --git a/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs b/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs index 66513fcc75..86d0062c02 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs @@ -307,6 +307,7 @@ protected override void ResetValues() } } + ResetCompatability(ref m_CompatibleWithAnyPlatform, (imp => imp.GetCompatibleWithAnyPlatform())); ResetCompatability(ref m_CompatibleWithEditor, (imp => imp.GetCompatibleWithEditor())); ResetCompatability(ref m_AutoReferenced, (imp => !imp.IsExplicitlyReferenced)); // If Any Platform is selected, initialize m_Compatible* variables using compatability function @@ -425,6 +426,13 @@ protected override void Awake() public override void OnEnable() { + m_DefineConstraints = new ReorderableList(m_DefineConstraintState, typeof(DefineConstraint), false, false, true, true); + m_DefineConstraints.drawElementCallback = DrawDefineConstraintListElement; + m_DefineConstraints.onRemoveCallback = RemoveDefineConstraintListElement; + + m_DefineConstraints.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + m_DefineConstraints.headerHeight = 3; + if (!IsEditingPlatformSettingsSupported()) return; @@ -464,13 +472,6 @@ public override void OnEnable() } m_ReferencesUnityEngineModule = importer.HasDiscouragedReferences(); - - m_DefineConstraints = new ReorderableList(m_DefineConstraintState, typeof(DefineConstraint), false, false, true, true); - m_DefineConstraints.drawElementCallback = DrawDefineConstraintListElement; - m_DefineConstraints.onRemoveCallback = RemoveDefineConstraintListElement; - - m_DefineConstraints.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - m_DefineConstraints.headerHeight = 3; } private void RemoveDefineConstraintListElement(ReorderableList list) diff --git a/Modules/CloudServicesSettingsEditor/Analytics/ScriptBindings/AnalyticsSettings.bindings.cs b/Modules/CloudServicesSettingsEditor/Analytics/ScriptBindings/AnalyticsSettings.bindings.cs index ebd2b86384..a35407687d 100644 --- a/Modules/CloudServicesSettingsEditor/Analytics/ScriptBindings/AnalyticsSettings.bindings.cs +++ b/Modules/CloudServicesSettingsEditor/Analytics/ScriptBindings/AnalyticsSettings.bindings.cs @@ -15,6 +15,8 @@ public static partial class AnalyticsSettings public static extern bool testMode { get; set; } + public static extern bool initializeOnStartup { get; set; } + internal static extern void SetEnabledServiceWindow(bool enabled); internal static extern bool enabledForPlatform { get; } diff --git a/Modules/Grid/ScriptBindings/GridLayout.bindings.cs b/Modules/Grid/ScriptBindings/GridLayout.bindings.cs index 7c6abdfbf8..663ef555de 100644 --- a/Modules/Grid/ScriptBindings/GridLayout.bindings.cs +++ b/Modules/Grid/ScriptBindings/GridLayout.bindings.cs @@ -2,6 +2,8 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; + using UnityEngine.Bindings; namespace UnityEngine @@ -81,5 +83,8 @@ public extern CellSwizzle cellSwizzle [FreeFunction("GridLayoutBindings::GetLayoutCellCenter", HasExplicitThis = true)] public extern Vector3 GetLayoutCellCenter(); + + [RequiredByNativeCode] + private void DoNothing() {} } } diff --git a/Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs b/Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs index 02809aa621..9eb8bfd098 100644 --- a/Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs +++ b/Modules/PackageManager/Editor/Managed/PackageManagerCommands.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using UnityEngine; +using UnityEditor; using UnityEditor.PackageManager.Requests; namespace UnityEditor.PackageManager @@ -12,10 +13,15 @@ static class PackageManagerCommands [MenuItem("Help/Reset Packages to defaults", priority = 1000)] public static void ResetProjectPackagesToEditorDefaults() { + if (EditorUtility.DisplayDialog(L10n.Tr("Unity Package Manager"), + L10n.Tr("Resetting packages to defaults will discard any changes you have made and/or remove packages set by the project template.\nThis action may result in compilation errors or a broken project. Are you sure?"), + L10n.Tr("No"), L10n.Tr("Yes"))) + return; + ResetToEditorDefaultsRequest request = Client.ResetToEditorDefaults(); if (request.Status == StatusCode.Failure) { - Debug.LogError("Resetting your project's packages to the editor's default configuration failed. Reason: " + request.Error.message); + Debug.LogError("Resetting packages to defaults failed. Reason: " + request.Error.message); } } } diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs index ee29b6a242..2bfc0cb031 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerTimelineGUI.cs @@ -684,19 +684,24 @@ void DoProfilerFrame(int frameIndex, Rect fullRect, bool ghost, int threadCount, var groupThreadCount = groupInfo.threads.Count; foreach (var threadInfo in groupInfo.threads) { - iter.SetRoot(frameIndex, threadInfo.threadIndex); r.y = y; r.height = expanded ? threadInfo.height * scaleForThreadHeight : Math.Max(groupInfo.height / groupThreadCount, k_ThreadMinHeightCollapsed); - DoNativeProfilerTimeline(r, frameIndex, threadInfo.threadIndex, offset, ghost, scaleForThreadHeight); - - // Save the y pos and height of the selected thread each time we draw, since it can change - bool containsSelected = m_SelectedEntry.IsValid() && (m_SelectedEntry.frameId == frameIndex) && (m_SelectedEntry.threadId == threadInfo.threadIndex); - if (containsSelected) + var tr = r; + tr.y -= fullRect.y; + if (tr.yMin < m_TimeArea.shownArea.yMax && tr.yMax > m_TimeArea.shownArea.yMin) { - m_SelectedThreadY = y; - m_SelectedThreadYRange = rangeY; - m_SelectedThread = threadInfo; + iter.SetRoot(frameIndex, threadInfo.threadIndex); + DoNativeProfilerTimeline(r, frameIndex, threadInfo.threadIndex, offset, ghost, scaleForThreadHeight); + + // Save the y pos and height of the selected thread each time we draw, since it can change + bool containsSelected = m_SelectedEntry.IsValid() && (m_SelectedEntry.frameId == frameIndex) && (m_SelectedEntry.threadId == threadInfo.threadIndex); + if (containsSelected) + { + m_SelectedThreadY = y; + m_SelectedThreadYRange = rangeY; + m_SelectedThread = threadInfo; + } } y += r.height; diff --git a/Modules/ShortcutManagerEditor/KeyCombination.cs b/Modules/ShortcutManagerEditor/KeyCombination.cs new file mode 100644 index 0000000000..a741cb5b22 --- /dev/null +++ b/Modules/ShortcutManagerEditor/KeyCombination.cs @@ -0,0 +1,232 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Linq; +using System.Text; +using System.Collections.Generic; + +using UnityEngine; + +namespace UnityEditor.ShortcutManagement +{ + [Serializable] + struct KeyCombination + { + [SerializeField] + KeyCode m_KeyCode; + [SerializeField] + ShortcutModifiers m_Modifiers; + + public KeyCode keyCode => m_KeyCode; + public ShortcutModifiers modifiers => m_Modifiers; + + public KeyCombination(KeyCode keyCode, ShortcutModifiers shortcutModifiers = ShortcutModifiers.None) + { + m_KeyCode = keyCode; + m_Modifiers = shortcutModifiers; + } + + internal static KeyCombination FromKeyboardInput(Event evt) + { + return new KeyCombination(evt.keyCode, ConvertEventModifiersToShortcutModifiers(evt.modifiers, false)); + } + + internal static KeyCombination ParseLegacyBindingString(string binding) + { + var keyEvent = Event.KeyboardEvent(binding); + return new KeyCombination(keyEvent.keyCode, ConvertEventModifiersToShortcutModifiers(keyEvent.modifiers, true)); + } + + private static ShortcutModifiers ConvertEventModifiersToShortcutModifiers(EventModifiers eventModifiers, bool coalesceCommandAndControl) + { + ShortcutModifiers modifiers = ShortcutModifiers.None; + if ((eventModifiers & EventModifiers.Alt) != 0) + modifiers |= ShortcutModifiers.Alt; + if ((eventModifiers & EventModifiers.Shift) != 0) + modifiers |= ShortcutModifiers.Shift; + + if (coalesceCommandAndControl) + { + if ((eventModifiers & (EventModifiers.Command | EventModifiers.Control)) != 0) + modifiers |= ShortcutModifiers.ControlOrCommand; + } + else if (Application.platform == RuntimePlatform.OSXEditor && (eventModifiers & EventModifiers.Command) != 0) + modifiers |= ShortcutModifiers.ControlOrCommand; + else if (Application.platform != RuntimePlatform.OSXEditor && (eventModifiers & EventModifiers.Control) != 0) + modifiers |= ShortcutModifiers.ControlOrCommand; + + return modifiers; + } + + public bool alt => (modifiers & ShortcutModifiers.Alt) == ShortcutModifiers.Alt; + public bool controlOrCommand => (modifiers & ShortcutModifiers.ControlOrCommand) == ShortcutModifiers.ControlOrCommand; + public bool shift => (modifiers & ShortcutModifiers.Shift) == ShortcutModifiers.Shift; + + public Event ToKeyboardEvent() + { + Event e = new Event(); + e.type = EventType.KeyDown; + e.alt = alt; + e.command = controlOrCommand && Application.platform == RuntimePlatform.OSXEditor; + e.control = controlOrCommand && Application.platform != RuntimePlatform.OSXEditor; + e.shift = shift; + e.keyCode = keyCode; + return e; + } + + public static string SequenceToString(IEnumerable keyCombinations) + { + if (!keyCombinations.Any()) + return ""; + + var builder = new StringBuilder(); + + builder.Append(keyCombinations.First()); + + foreach (var keyCombination in keyCombinations.Skip(1)) + { + builder.Append(", "); + builder.Append(keyCombination); + } + + return builder.ToString(); + } + + public override string ToString() + { + var builder = new StringBuilder(); + VisualizeModifiers(modifiers, builder); + VisualizeKeyCode(keyCode, builder); + return builder.ToString(); + } + + public string ToMenuShortcutString() + { + if (keyCode == KeyCode.None) + return string.Empty; + + var builder = new StringBuilder(); + if ((modifiers & ShortcutModifiers.Alt) != 0) + builder.Append("&"); + if ((modifiers & ShortcutModifiers.Shift) != 0) + builder.Append("#"); + if ((modifiers & ShortcutModifiers.ControlOrCommand) != 0) + builder.Append("%"); + if (modifiers == ShortcutModifiers.None) + builder.Append("_"); + + VisualizeKeyCode(keyCode, builder); + + return builder.ToString(); + } + + static void VisualizeModifiers(ShortcutModifiers modifiers, StringBuilder builder) + { + if (Application.platform == RuntimePlatform.OSXEditor) + { + if ((modifiers & ShortcutModifiers.Alt) != 0) + builder.Append("⌥"); + if ((modifiers & ShortcutModifiers.Shift) != 0) + builder.Append("⇧"); + if ((modifiers & ShortcutModifiers.ControlOrCommand) != 0) + builder.Append("⌘"); + } + else + { + if ((modifiers & ShortcutModifiers.ControlOrCommand) != 0) + builder.Append("Ctrl+"); + if ((modifiers & ShortcutModifiers.Alt) != 0) + builder.Append("Alt+"); + if ((modifiers & ShortcutModifiers.Shift) != 0) + builder.Append("Shift+"); + } + } + + static void VisualizeKeyCode(KeyCode keyCode, StringBuilder builder) + { + if (!TryFormatKeycode(keyCode, builder)) + builder.Append(keyCode.ToString()); + } + + static bool TryFormatKeycode(KeyCode code, StringBuilder builder) + { + if (Application.platform == RuntimePlatform.OSXEditor) + { + switch (code) + { + case KeyCode.Return: + builder.Append("↩"); + break; + case KeyCode.Backspace: + builder.Append("⌫"); + break; + case KeyCode.Delete: + builder.Append("⌦"); + break; + case KeyCode.Escape: + builder.Append("⎋"); + break; + case KeyCode.RightArrow: + builder.Append("→"); + break; + case KeyCode.LeftArrow: + builder.Append("←"); + break; + case KeyCode.UpArrow: + builder.Append("↑"); + break; + case KeyCode.DownArrow: + builder.Append("↓"); + break; + case KeyCode.PageUp: + builder.Append("⇞"); + break; + case KeyCode.PageDown: + builder.Append("⇟"); + break; + case KeyCode.Home: + builder.Append("↖"); + break; + case KeyCode.End: + builder.Append("↘"); + break; + case KeyCode.Tab: + builder.Append("⇥"); + break; + default: + return false; + } + } + else + { + switch (code) + { + case KeyCode.Delete: + builder.Append("DEL"); + break; + case KeyCode.Backspace: + builder.Append("BACKSPACE"); + break; + case KeyCode.LeftArrow: + builder.Append("LEFT"); + break; + case KeyCode.RightArrow: + builder.Append("RIGHT"); + break; + case KeyCode.UpArrow: + builder.Append("UP"); + break; + case KeyCode.DownArrow: + builder.Append("DOWN"); + break; + default: + return false; + } + } + + return true; + } + } +} diff --git a/Modules/ShortcutManagerEditor/ShortcutAttribute.cs b/Modules/ShortcutManagerEditor/ShortcutAttribute.cs index b4c6a72fb2..7f741de2e3 100644 --- a/Modules/ShortcutManagerEditor/ShortcutAttribute.cs +++ b/Modules/ShortcutManagerEditor/ShortcutAttribute.cs @@ -41,11 +41,14 @@ public ShortcutAttribute(string identifier, Type context = null, string defaultK public override ShortcutEntry CreateShortcutEntry(MethodInfo methodInfo) { - var keyEvent = Event.KeyboardEvent(defaultKeyCombination); - var defaultCombination = new List(); - var keyCombination = new KeyCombination(keyEvent); - defaultCombination.Add(keyCombination); var identifier = new Identifier(methodInfo, this); + + IEnumerable defaultCombination; + if (defaultKeyCombination == null) + defaultCombination = Enumerable.Empty(); + else + defaultCombination = new[] { KeyCombination.ParseLegacyBindingString(defaultKeyCombination) }; + var type = this is ClutchShortcutAttribute ? ShortcutType.Clutch : ShortcutType.Action; var methodParams = methodInfo.GetParameters(); Action action; diff --git a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs index ed6c0ee843..bd8c65d1ab 100644 --- a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs +++ b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs @@ -48,7 +48,7 @@ public IEnumerable GetDefinedShortcuts() { var keys = new List(); if (!string.IsNullOrEmpty(defaultShortcuts[index])) - keys.Add(new KeyCombination(Event.KeyboardEvent(defaultShortcuts[index]))); + keys.Add(KeyCombination.ParseLegacyBindingString(defaultShortcuts[index])); entries.Add(new MenuItemEntryDiscoveryInfo(names[index], keys)); } diff --git a/Modules/ShortcutManagerEditor/ShortcutEntry.cs b/Modules/ShortcutManagerEditor/ShortcutEntry.cs index 06f605f018..c68b8a5b8a 100644 --- a/Modules/ShortcutManagerEditor/ShortcutEntry.cs +++ b/Modules/ShortcutManagerEditor/ShortcutEntry.cs @@ -3,11 +3,9 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using System.Collections.Generic; using System.Linq; using System.Reflection; -using System.Text; -using UnityEngine; +using System.Collections.Generic; namespace UnityEditor.ShortcutManagement { @@ -185,204 +183,4 @@ enum ShortcutModifiers ControlOrCommand = 2, Shift = 4 } - - [Serializable] - struct KeyCombination - { - [SerializeField] - KeyCode m_KeyCode; - [SerializeField] - ShortcutModifiers m_Modifiers; - - public KeyCode keyCode => m_KeyCode; - public ShortcutModifiers modifiers => m_Modifiers; - - public KeyCombination(KeyCode keyCode, ShortcutModifiers shortcutModifiers = ShortcutModifiers.None) - { - m_KeyCode = keyCode; - m_Modifiers = shortcutModifiers; - } - - internal KeyCombination(Event evt) - { - m_KeyCode = evt.keyCode; - m_Modifiers = ShortcutModifiers.None; - - if (evt.alt) - m_Modifiers |= ShortcutModifiers.Alt; - if (evt.control || evt.command) - m_Modifiers |= ShortcutModifiers.ControlOrCommand; - if (evt.shift) - m_Modifiers |= ShortcutModifiers.Shift; - } - - public bool alt => (modifiers & ShortcutModifiers.Alt) == ShortcutModifiers.Alt; - public bool controlOrCommand => (modifiers & ShortcutModifiers.ControlOrCommand) == ShortcutModifiers.ControlOrCommand; - public bool shift => (modifiers & ShortcutModifiers.Shift) == ShortcutModifiers.Shift; - - public Event ToKeyboardEvent() - { - Event e = new Event(); - e.type = EventType.KeyDown; - e.alt = alt; - e.command = controlOrCommand && Application.platform == RuntimePlatform.OSXEditor; - e.control = controlOrCommand && Application.platform != RuntimePlatform.OSXEditor; - e.shift = shift; - e.keyCode = keyCode; - return e; - } - - public static string SequenceToString(IEnumerable keyCombinations) - { - if (!keyCombinations.Any()) - return ""; - - var builder = new StringBuilder(); - - builder.Append(keyCombinations.First()); - - foreach (var keyCombination in keyCombinations.Skip(1)) - { - builder.Append(", "); - builder.Append(keyCombination); - } - - return builder.ToString(); - } - - public override string ToString() - { - var builder = new StringBuilder(); - VisualizeModifiers(modifiers, builder); - VisualizeKeyCode(keyCode, builder); - return builder.ToString(); - } - - public string ToMenuShortcutString() - { - if (keyCode == KeyCode.None) - return string.Empty; - - var builder = new StringBuilder(); - if ((modifiers & ShortcutModifiers.Alt) != 0) - builder.Append("&"); - if ((modifiers & ShortcutModifiers.Shift) != 0) - builder.Append("#"); - if ((modifiers & ShortcutModifiers.ControlOrCommand) != 0) - builder.Append("%"); - if (modifiers == ShortcutModifiers.None) - builder.Append("_"); - - VisualizeKeyCode(keyCode, builder); - - return builder.ToString(); - } - - static void VisualizeModifiers(ShortcutModifiers modifiers, StringBuilder builder) - { - if (Application.platform == RuntimePlatform.OSXEditor) - { - if ((modifiers & ShortcutModifiers.Alt) != 0) - builder.Append("⌥"); - if ((modifiers & ShortcutModifiers.Shift) != 0) - builder.Append("⇧"); - if ((modifiers & ShortcutModifiers.ControlOrCommand) != 0) - builder.Append("⌘"); - } - else - { - if ((modifiers & ShortcutModifiers.ControlOrCommand) != 0) - builder.Append("Ctrl+"); - if ((modifiers & ShortcutModifiers.Alt) != 0) - builder.Append("Alt+"); - if ((modifiers & ShortcutModifiers.Shift) != 0) - builder.Append("Shift+"); - } - } - - static void VisualizeKeyCode(KeyCode keyCode, StringBuilder builder) - { - if (!TryFormatKeycode(keyCode, builder)) - builder.Append(keyCode.ToString()); - } - - static bool TryFormatKeycode(KeyCode code, StringBuilder builder) - { - if (Application.platform == RuntimePlatform.OSXEditor) - { - switch (code) - { - case KeyCode.Return: - builder.Append("↩"); - break; - case KeyCode.Backspace: - builder.Append("⌫"); - break; - case KeyCode.Delete: - builder.Append("⌦"); - break; - case KeyCode.Escape: - builder.Append("⎋"); - break; - case KeyCode.RightArrow: - builder.Append("→"); - break; - case KeyCode.LeftArrow: - builder.Append("←"); - break; - case KeyCode.UpArrow: - builder.Append("↑"); - break; - case KeyCode.DownArrow: - builder.Append("↓"); - break; - case KeyCode.PageUp: - builder.Append("⇞"); - break; - case KeyCode.PageDown: - builder.Append("⇟"); - break; - case KeyCode.Home: - builder.Append("↖"); - break; - case KeyCode.End: - builder.Append("↘"); - break; - case KeyCode.Tab: - builder.Append("⇥"); - break; - default: - return false; - } - } - else - { - switch (code) - { - case KeyCode.Delete: - builder.Append("DEL"); - break; - case KeyCode.Backspace: - builder.Append("BACKSPACE"); - break; - case KeyCode.LeftArrow: - builder.Append("LEFT"); - break; - case KeyCode.RightArrow: - builder.Append("RIGHT"); - break; - case KeyCode.UpArrow: - builder.Append("UP"); - break; - case KeyCode.DownArrow: - builder.Append("DOWN"); - break; - default: - return false; - } - } - - return true; - } - } } diff --git a/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs b/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs index 915b3180f3..c0262cec19 100644 --- a/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs +++ b/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs @@ -91,15 +91,14 @@ IEnumerable methodsWithFormerlyPrefKeyAs, List entrie var prefKeyAttr = (FormerlyPrefKeyAsAttribute)Attribute.GetCustomAttribute(method, typeof(FormerlyPrefKeyAsAttribute)); - var prefKeyDefaultValue = new KeyCombination(Event.KeyboardEvent(prefKeyAttr.defaultValue)); + var prefKeyDefaultValue = KeyCombination.ParseLegacyBindingString(prefKeyAttr.defaultValue); string name; + string binding; Event keyboardEvent; - var parsed = PrefKey.TryParseUniquePrefString( - EditorPrefs.GetString(prefKeyAttr.name, prefKeyAttr.defaultValue), out name, out keyboardEvent - ); + var parsed = PrefKey.TryParseUniquePrefString(EditorPrefs.GetString(prefKeyAttr.name, prefKeyAttr.defaultValue), out name, out keyboardEvent, out binding); if (!parsed) continue; - var prefKeyCurrentValue = new KeyCombination(keyboardEvent); + var prefKeyCurrentValue = KeyCombination.ParseLegacyBindingString(binding); // only migrate pref keys that the user actually overwrote if (!prefKeyCurrentValue.Equals(prefKeyDefaultValue)) entry.SetOverride(new List { prefKeyCurrentValue }); diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index 87358087be..df70a6d649 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -57,7 +57,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) return; } - var keyCodeCombination = new KeyCombination(evt); + var keyCodeCombination = KeyCombination.FromKeyboardInput(evt); m_KeyCombinationSequence.Add(keyCodeCombination); // Ignore event if sequence is empty diff --git a/Modules/SpriteMaskEditor/Editor/Managed/SpriteMaskEditor.cs b/Modules/SpriteMaskEditor/Editor/Managed/SpriteMaskEditor.cs index 4822728472..a696ab596e 100644 --- a/Modules/SpriteMaskEditor/Editor/Managed/SpriteMaskEditor.cs +++ b/Modules/SpriteMaskEditor/Editor/Managed/SpriteMaskEditor.cs @@ -36,7 +36,8 @@ private static class Contents [MenuItem("GameObject/2D Object/Sprite Mask")] static void CreateSpriteMaskGameObject() { - var go = ObjectFactory.CreateGameObject("", typeof(SpriteMask)); + var go = ObjectFactory.CreateGameObject(""); + go.AddComponent(); if (Selection.activeObject is Sprite) go.GetComponent().sprite = (Sprite)Selection.activeObject; else if (Selection.activeObject is Texture2D) diff --git a/Modules/Terrain/Public/PaintContext.cs b/Modules/Terrain/Public/PaintContext.cs index f85775e442..1ada108767 100644 --- a/Modules/Terrain/Public/PaintContext.cs +++ b/Modules/Terrain/Public/PaintContext.cs @@ -30,17 +30,12 @@ public Terrain GetTerrain(int terrainIndex) public RectInt GetClippedPixelRectInTerrainPixels(int terrainIndex) { - return m_TerrainTiles[terrainIndex].clippedLocal; + return m_TerrainTiles[terrainIndex].clippedLocalPixels; } public RectInt GetClippedPixelRectInRenderTexturePixels(int terrainIndex) { - Rect vp = m_TerrainTiles[terrainIndex].validPaintRect; - return new RectInt( - Mathf.RoundToInt(vp.xMin), - Mathf.RoundToInt(vp.yMin), - Mathf.RoundToInt(vp.width), - Mathf.RoundToInt(vp.height)); + return m_TerrainTiles[terrainIndex].clippedPCPixels; } // initialized by constructor @@ -54,18 +49,16 @@ public RectInt GetClippedPixelRectInRenderTexturePixels(int terrainIndex) internal class TerrainTile { public TerrainTile() {} - public TerrainTile(Terrain newTerrain, RectInt newRegion) { rect = newRegion; terrain = newTerrain; } - - public Terrain terrain; // the terrain object - public RectInt rect; // coordinates of this terrain tile in paint context pixels (essentially originTerrain target texture pixels) - public RectInt clippedLocal; // pixelRect in local pixel coordinates (for target texture), clipped to the local tile - public Rect validPaintRect; // the area per tile where the source texture was able to read from (in paint context pixels) - public int mapIndex; // - public int channelIndex; // - - // offsets used for gather / scatter - public Vector2Int readOffset; // offsets used when reading from the terrain heightmap - public Vector2Int writeOffset; // offsets used when copying from PaintContext clipped heightmap back to the terrain heightmap + public TerrainTile(Terrain newTerrain, int tileOriginPixelsX, int tileOriginPixelsY) { terrain = newTerrain; tileOriginPixels = new Vector2Int(tileOriginPixelsX, tileOriginPixelsY); } + + public Terrain terrain; // the terrain object for this tile + public Vector2Int tileOriginPixels; // coordinates of this terrain tile in originTerrain target texture pixels + + public RectInt clippedLocalPixels; // the tile pixels touched by this PaintContext (in local target texture pixels) + public RectInt clippedPCPixels; // the tile pixels touched by this PaintContext (in PaintContext/source/destRenderTexture pixels) + + public int mapIndex; // for splatmap operations, the splatmap index on this Terrain containing the desired TerrainLayer weight + public int channelIndex; // for splatmap operations, the channel on the splatmap containing the desired TerrainLayer weight } [Flags] @@ -129,9 +122,7 @@ internal void FindTerrainTiles() } // add center tile - TerrainTile tile = new TerrainTile(originTerrain, new RectInt(0, 0, targetTextureWidth, targetTextureHeight)); - tile.readOffset = Vector2Int.zero; - tile.writeOffset = Vector2Int.zero; + TerrainTile tile = new TerrainTile(originTerrain, 0, 0); m_TerrainTiles.Add(tile); // add horizontal and vertical neighbors @@ -139,48 +130,34 @@ internal void FindTerrainTiles() Terrain vert = null; Terrain cornerTerrain = null; - int xBias = 0; - int yBias = 0; - int xReadBias = 0; - int yReadBias = 0; - int xWriteBias = 0; - int yWriteBias = 0; + int horizTileDelta = 0; // how many tiles to move horizontally + int vertTileDelta = 0; // how many tiles to move vertically if (wantLeft) { - xBias = -1; - xReadBias = -1; - xWriteBias = 1; + horizTileDelta = -1; horiz = left; } else if (wantRight) { - xBias = 1; - xReadBias = 1; - xWriteBias = -1; + horizTileDelta = 1; horiz = right; } if (wantTop) { - yBias = 1; - yReadBias = 1; - yWriteBias = -1; + vertTileDelta = 1; vert = top; } else if (wantBottom) { - yBias = -1; - yReadBias = -1; - yWriteBias = 1; + vertTileDelta = -1; vert = bottom; } if (horiz) { - tile = new TerrainTile(horiz, new RectInt(xBias * targetTextureWidth, 0, targetTextureWidth, targetTextureHeight)); - tile.readOffset = new Vector2Int(xReadBias, 0); - tile.writeOffset = new Vector2Int(xWriteBias, 0); + tile = new TerrainTile(horiz, horizTileDelta * (targetTextureWidth - 1), 0); m_TerrainTiles.Add(tile); // add corner, if we have a link @@ -192,9 +169,7 @@ internal void FindTerrainTiles() if (vert) { - tile = new PaintContext.TerrainTile(vert, new RectInt(0, yBias * targetTextureHeight, targetTextureWidth, targetTextureHeight)); - tile.readOffset = new Vector2Int(0, yReadBias); - tile.writeOffset = new Vector2Int(0, yWriteBias); + tile = new PaintContext.TerrainTile(vert, 0, vertTileDelta * (targetTextureHeight - 1)); m_TerrainTiles.Add(tile); // add corner, if we have a link @@ -206,9 +181,7 @@ internal void FindTerrainTiles() if (cornerTerrain != null) { - tile = new TerrainTile(cornerTerrain, new RectInt(xBias * targetTextureWidth, yBias * targetTextureHeight, targetTextureWidth, targetTextureHeight)); - tile.readOffset = new Vector2Int(xReadBias, yReadBias); - tile.writeOffset = new Vector2Int(xWriteBias, yWriteBias); + tile = new TerrainTile(cornerTerrain, horizTileDelta * (targetTextureWidth - 1), vertTileDelta * (targetTextureHeight - 1)); m_TerrainTiles.Add(tile); } } @@ -218,17 +191,17 @@ internal void ClipTerrainTiles() for (int i = 0; i < m_TerrainTiles.Count; i++) { TerrainTile tile = m_TerrainTiles[i]; - tile.clippedLocal = new RectInt(); - tile.clippedLocal.x = Mathf.Max(0, pixelRect.x - tile.rect.x); - tile.clippedLocal.y = Mathf.Max(0, pixelRect.y - tile.rect.y); - tile.clippedLocal.xMax = Mathf.Min(tile.rect.width, pixelRect.xMax - tile.rect.x); - tile.clippedLocal.yMax = Mathf.Min(tile.rect.height, pixelRect.yMax - tile.rect.y); - - tile.validPaintRect = new Rect( - tile.clippedLocal.x + tile.rect.x - pixelRect.x, - tile.clippedLocal.y + tile.rect.y - pixelRect.y, - tile.clippedLocal.width, - tile.clippedLocal.height); + tile.clippedLocalPixels = new RectInt(); + tile.clippedLocalPixels.x = Mathf.Max(0, pixelRect.x - tile.tileOriginPixels.x); + tile.clippedLocalPixels.y = Mathf.Max(0, pixelRect.y - tile.tileOriginPixels.y); + tile.clippedLocalPixels.xMax = Mathf.Min(targetTextureWidth, pixelRect.xMax - tile.tileOriginPixels.x); + tile.clippedLocalPixels.yMax = Mathf.Min(targetTextureHeight, pixelRect.yMax - tile.tileOriginPixels.y); + + tile.clippedPCPixels = new RectInt( + tile.clippedLocalPixels.x + tile.tileOriginPixels.x - pixelRect.x, + tile.clippedLocalPixels.y + tile.tileOriginPixels.y - pixelRect.y, + tile.clippedLocalPixels.width, + tile.clippedLocalPixels.height); } } @@ -261,10 +234,13 @@ public void GatherHeightmap() RenderTexture.active = sourceRenderTexture; GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f)); + GL.PushMatrix(); + GL.LoadPixelMatrix(0, pixelRect.width, 0, pixelRect.height); + for (int i = 0; i < m_TerrainTiles.Count; i++) { TerrainTile terrainTile = m_TerrainTiles[i]; - if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0) continue; Texture sourceTexture = terrainTile.terrain.terrainData.heightmapTexture; @@ -274,12 +250,6 @@ public void GatherHeightmap() continue; } - Rect readRect = new Rect( - (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, - (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, - (terrainTile.clippedLocal.width) / (float)targetTextureWidth, - (terrainTile.clippedLocal.height) / (float)targetTextureHeight); - FilterMode oldFilterMode = sourceTexture.filterMode; sourceTexture.filterMode = FilterMode.Point; @@ -287,11 +257,13 @@ public void GatherHeightmap() blitMaterial.SetTexture("_MainTex", sourceTexture); blitMaterial.SetPass(0); - TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + TerrainPaintUtility.DrawQuad(terrainTile.clippedPCPixels, terrainTile.clippedLocalPixels, sourceTexture); sourceTexture.filterMode = oldFilterMode; } + GL.PopMatrix(); + RenderTexture.active = oldRenderTexture; } @@ -302,7 +274,7 @@ public void ScatterHeightmap(string editorUndoName) for (int i = 0; i < m_TerrainTiles.Count; i++) { TerrainTile terrainTile = m_TerrainTiles[i]; - if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0) continue; RenderTexture heightmap = terrainTile.terrain.terrainData.heightmapTexture; @@ -316,27 +288,19 @@ public void ScatterHeightmap(string editorUndoName) onTerrainTileBeforePaint(terrainTile, ToolAction.PaintHeightmap, editorUndoName); RenderTexture.active = heightmap; - - Rect readRect = new Rect( - (terrainTile.clippedLocal.x + terrainTile.rect.x - pixelRect.x + terrainTile.writeOffset.x) / (float)pixelRect.width, - (terrainTile.clippedLocal.y + terrainTile.rect.y - pixelRect.y + terrainTile.writeOffset.y) / (float)pixelRect.height, - (terrainTile.clippedLocal.width) / (float)pixelRect.width, - (terrainTile.clippedLocal.height) / (float)pixelRect.height); - - Rect writeRect = new Rect( - terrainTile.clippedLocal.x, - terrainTile.clippedLocal.y, - terrainTile.clippedLocal.width, - terrainTile.clippedLocal.height); + GL.PushMatrix(); + GL.LoadPixelMatrix(0, heightmap.width, 0, heightmap.height); destinationRenderTexture.filterMode = FilterMode.Point; blitMaterial.SetTexture("_MainTex", destinationRenderTexture); blitMaterial.SetPass(0); - TerrainPaintUtility.DrawQuad(heightmap.width, heightmap.height, readRect, writeRect); + TerrainPaintUtility.DrawQuad(terrainTile.clippedLocalPixels, terrainTile.clippedPCPixels, destinationRenderTexture); + + GL.PopMatrix(); - terrainTile.terrain.terrainData.UpdateDirtyRegion(terrainTile.clippedLocal.x, terrainTile.clippedLocal.y, terrainTile.clippedLocal.width, terrainTile.clippedLocal.height, !terrainTile.terrain.drawInstanced); + terrainTile.terrain.terrainData.UpdateDirtyRegion(terrainTile.clippedLocalPixels.x, terrainTile.clippedLocalPixels.y, terrainTile.clippedLocalPixels.width, terrainTile.clippedLocalPixels.height, !terrainTile.terrain.drawInstanced); OnTerrainPainted(terrainTile, ToolAction.PaintHeightmap); } } @@ -349,11 +313,13 @@ public void GatherNormals() RenderTexture.active = sourceRenderTexture; GL.Clear(false, true, new Color(0.5f, 0.5f, 0.5f, 0.5f)); + GL.PushMatrix(); + GL.LoadPixelMatrix(0, pixelRect.width, 0, pixelRect.height); for (int i = 0; i < m_TerrainTiles.Count; i++) { TerrainTile terrainTile = m_TerrainTiles[i]; - if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0) continue; Texture sourceTexture = terrainTile.terrain.normalmapTexture; @@ -363,12 +329,6 @@ public void GatherNormals() continue; } - Rect readRect = new Rect( - (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, - (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, - (terrainTile.clippedLocal.width) / (float)targetTextureWidth, - (terrainTile.clippedLocal.height) / (float)targetTextureHeight); - FilterMode oldFilterMode = sourceTexture.filterMode; sourceTexture.filterMode = FilterMode.Point; @@ -376,11 +336,13 @@ public void GatherNormals() blitMaterial.SetTexture("_MainTex", sourceTexture); blitMaterial.SetPass(0); - TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + TerrainPaintUtility.DrawQuad(terrainTile.clippedPCPixels, terrainTile.clippedLocalPixels, sourceTexture); sourceTexture.filterMode = oldFilterMode; } + GL.PopMatrix(); + RenderTexture.active = oldRenderTexture; } @@ -395,6 +357,8 @@ public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = RenderTexture.active = sourceRenderTexture; GL.Clear(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f)); + GL.PushMatrix(); + GL.LoadPixelMatrix(0, pixelRect.width, 0, pixelRect.height); Vector4[] layerMasks = { new Vector4(1, 0, 0, 0), new Vector4(0, 1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1) }; @@ -402,25 +366,19 @@ public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = for (int i = 0; i < m_TerrainTiles.Count; i++) { TerrainTile terrainTile = m_TerrainTiles[i]; - if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0) continue; - Rect readRect = new Rect( - (terrainTile.clippedLocal.x + terrainTile.readOffset.x) / (float)targetTextureWidth, - (terrainTile.clippedLocal.y + terrainTile.readOffset.y) / (float)targetTextureHeight, - (terrainTile.clippedLocal.width) / (float)targetTextureWidth, - (terrainTile.clippedLocal.height) / (float)targetTextureHeight); - int tileLayerIndex = TerrainPaintUtility.FindTerrainLayerIndex(terrainTile.terrain, inputLayer); if (tileLayerIndex == -1) { if (!addLayerIfDoesntExist) { // setting these to zero will prevent them from being used later - terrainTile.clippedLocal.width = 0; - terrainTile.clippedLocal.height = 0; - terrainTile.validPaintRect.width = 0; - terrainTile.validPaintRect.height = 0; + terrainTile.clippedLocalPixels.width = 0; + terrainTile.clippedLocalPixels.height = 0; + terrainTile.clippedPCPixels.width = 0; + terrainTile.clippedPCPixels.height = 0; continue; } tileLayerIndex = TerrainPaintUtility.AddTerrainLayer(terrainTile.terrain, inputLayer); @@ -432,7 +390,9 @@ public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = Texture sourceTexture = TerrainPaintUtility.GetTerrainAlphaMapChecked(terrainTile.terrain, terrainTile.mapIndex); if ((sourceTexture.width != targetTextureWidth) || (sourceTexture.height != targetTextureHeight)) { - Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored.", terrainTile.terrain); + Debug.LogWarning("PaintContext alphamap operations must use the same resolution for all Terrains - mismatched Terrains are ignored. (" + + sourceTexture.width + " x " + sourceTexture.height + ") != (" + targetTextureWidth + " x " + targetTextureHeight + ")", + terrainTile.terrain); continue; } @@ -443,11 +403,13 @@ public void GatherAlphamap(TerrainLayer inputLayer, bool addLayerIfDoesntExist = copyTerrainLayerMaterial.SetTexture("_MainTex", sourceTexture); copyTerrainLayerMaterial.SetPass(0); - TerrainPaintUtility.DrawQuad(pixelRect.width, pixelRect.height, readRect, terrainTile.validPaintRect); + TerrainPaintUtility.DrawQuad(terrainTile.clippedPCPixels, terrainTile.clippedLocalPixels, sourceTexture); sourceTexture.filterMode = oldFilterMode; } + GL.PopMatrix(); + RenderTexture.active = oldRenderTexture; } @@ -460,7 +422,7 @@ public void ScatterAlphamap(string editorUndoName) for (int i = 0; i < m_TerrainTiles.Count; i++) { TerrainTile terrainTile = m_TerrainTiles[i]; - if (terrainTile.clippedLocal.width == 0 || terrainTile.clippedLocal.height == 0) + if (terrainTile.clippedLocalPixels.width == 0 || terrainTile.clippedLocalPixels.height == 0) continue; if (onTerrainTileBeforePaint != null) @@ -473,13 +435,9 @@ public void ScatterAlphamap(string editorUndoName) RenderTexture destTarget = RenderTexture.GetTemporary(rtdesc); RenderTexture.active = destTarget; - var writeRect = new RectInt( - terrainTile.clippedLocal.x + terrainTile.rect.x - pixelRect.x + terrainTile.writeOffset.x, - terrainTile.clippedLocal.y + terrainTile.rect.y - pixelRect.y + terrainTile.writeOffset.y, - terrainTile.clippedLocal.width, - terrainTile.clippedLocal.height); + RectInt writeRect = terrainTile.clippedPCPixels; - var readRect = new Rect( + Rect readRect = new Rect( writeRect.x / (float)pixelRect.width, writeRect.y / (float)pixelRect.height, writeRect.width / (float)pixelRect.width, @@ -487,6 +445,10 @@ public void ScatterAlphamap(string editorUndoName) destinationRenderTexture.filterMode = FilterMode.Point; + int mapIndex = terrainTile.mapIndex; + int channelIndex = terrainTile.channelIndex; + Texture2D sourceTexTargetChannel = terrainTile.terrain.terrainData.alphamapTextures[mapIndex]; + for (int j = 0; j < terrainTile.terrain.terrainData.alphamapTextureCount; j++) { Texture2D sourceTex = terrainTile.terrain.terrainData.alphamapTextures[j]; @@ -496,23 +458,22 @@ public void ScatterAlphamap(string editorUndoName) continue; } - int mapIndex = terrainTile.mapIndex; - int channelIndex = terrainTile.channelIndex; - Rect combineRect = new Rect( - terrainTile.clippedLocal.x / (float)sourceTex.width, - terrainTile.clippedLocal.y / (float)sourceTex.height, - terrainTile.clippedLocal.width / (float)sourceTex.width, - terrainTile.clippedLocal.height / (float)sourceTex.height); + terrainTile.clippedLocalPixels.x / (float)sourceTex.width, + terrainTile.clippedLocalPixels.y / (float)sourceTex.height, + terrainTile.clippedLocalPixels.width / (float)sourceTex.width, + terrainTile.clippedLocalPixels.height / (float)sourceTex.height); copyTerrainLayerMaterial.SetTexture("_MainTex", destinationRenderTexture); copyTerrainLayerMaterial.SetTexture("_OldAlphaMapTexture", sourceRenderTexture); + copyTerrainLayerMaterial.SetTexture("_OriginalTargetAlphaMap", sourceTexTargetChannel); + copyTerrainLayerMaterial.SetTexture("_AlphaMapTexture", sourceTex); copyTerrainLayerMaterial.SetVector("_LayerMask", j == mapIndex ? layerMasks[channelIndex] : Vector4.zero); + copyTerrainLayerMaterial.SetVector("_OriginalTargetAlphaMask", layerMasks[channelIndex]); copyTerrainLayerMaterial.SetPass(1); GL.PushMatrix(); - GL.LoadOrtho(); GL.LoadPixelMatrix(0, destTarget.width, 0, destTarget.height); GL.Begin(GL.QUADS); @@ -546,7 +507,7 @@ public void ScatterAlphamap(string editorUndoName) // Composes mip0 in a RT with full mipchain. Graphics.CopyTexture(sourceTex, 0, 0, mips, 0, 0); - Graphics.CopyTexture(destTarget, 0, 0, writeRect.x, writeRect.y, writeRect.width, writeRect.height, mips, 0, 0, terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + Graphics.CopyTexture(destTarget, 0, 0, writeRect.x, writeRect.y, writeRect.width, writeRect.height, mips, 0, 0, terrainTile.clippedLocalPixels.x, terrainTile.clippedLocalPixels.y); mips.GenerateMips(); // Copy them into sourceTex. @@ -558,9 +519,9 @@ public void ScatterAlphamap(string editorUndoName) { GraphicsDeviceType deviceType = SystemInfo.graphicsDeviceType; if (deviceType == GraphicsDeviceType.Metal || deviceType == GraphicsDeviceType.OpenGLCore) - sourceTex.ReadPixels(new Rect(writeRect.x, writeRect.y, writeRect.width, writeRect.height), terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + sourceTex.ReadPixels(new Rect(writeRect.x, writeRect.y, writeRect.width, writeRect.height), terrainTile.clippedLocalPixels.x, terrainTile.clippedLocalPixels.y); else - sourceTex.ReadPixels(new Rect(writeRect.x, destTarget.height - writeRect.y - writeRect.height, writeRect.width, writeRect.height), terrainTile.clippedLocal.x, terrainTile.clippedLocal.y); + sourceTex.ReadPixels(new Rect(writeRect.x, destTarget.height - writeRect.y - writeRect.height, writeRect.width, writeRect.height), terrainTile.clippedLocalPixels.x, terrainTile.clippedLocalPixels.y); sourceTex.Apply(); } } diff --git a/Modules/Terrain/Public/TerrainPaintUtility.cs b/Modules/Terrain/Public/TerrainPaintUtility.cs index a2d752a116..fd5d6ba659 100644 --- a/Modules/Terrain/Public/TerrainPaintUtility.cs +++ b/Modules/Terrain/Public/TerrainPaintUtility.cs @@ -198,26 +198,28 @@ public static Material GetCopyTerrainLayerMaterial() return m_CopyTerrainLayerMaterial; } - internal static void DrawQuad(int width, int height, Rect source, Rect destination) + internal static void DrawQuad(RectInt destinationPixels, RectInt sourcePixels, Texture sourceTexture) { - GL.PushMatrix(); - GL.LoadOrtho(); - GL.LoadPixelMatrix(0, width, 0, height); - - GL.Begin(GL.QUADS); - GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f)); - - GL.TexCoord2(source.x, source.y); - GL.Vertex3(destination.x, destination.y, 0.0f); - GL.TexCoord2(source.x, source.yMax); - GL.Vertex3(destination.x, destination.yMax, 0.0f); - GL.TexCoord2(source.xMax, source.yMax); - GL.Vertex3(destination.xMax, destination.yMax, 0.0f); - GL.TexCoord2(source.xMax, source.y); - GL.Vertex3(destination.xMax, destination.y, 0.0f); - - GL.End(); - GL.PopMatrix(); + if ((destinationPixels.width > 0) && (destinationPixels.height > 0)) + { + Rect sourceUVs = new Rect( + (sourcePixels.x) / (float)sourceTexture.width, + (sourcePixels.y) / (float)sourceTexture.height, + (sourcePixels.width) / (float)sourceTexture.width, + (sourcePixels.height) / (float)sourceTexture.height); + + GL.Begin(GL.QUADS); + GL.Color(new Color(1.0f, 1.0f, 1.0f, 1.0f)); + GL.TexCoord2(sourceUVs.x, sourceUVs.y); + GL.Vertex3(destinationPixels.x, destinationPixels.y, 0.0f); + GL.TexCoord2(sourceUVs.x, sourceUVs.yMax); + GL.Vertex3(destinationPixels.x, destinationPixels.yMax, 0.0f); + GL.TexCoord2(sourceUVs.xMax, sourceUVs.yMax); + GL.Vertex3(destinationPixels.xMax, destinationPixels.yMax, 0.0f); + GL.TexCoord2(sourceUVs.xMax, sourceUVs.y); + GL.Vertex3(destinationPixels.xMax, destinationPixels.y, 0.0f); + GL.End(); + } } internal static RectInt CalcPixelRectFromBounds(Terrain terrain, Rect boundsInTerrainSpace, int textureWidth, int textureHeight, int extraBorderPixels) diff --git a/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs b/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs index 0fae39fd1a..15e7b57660 100644 --- a/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs +++ b/Modules/TerrainEditor/PaintTools/PaintTextureTool.cs @@ -22,9 +22,6 @@ public class PaintTextureTool : TerrainPaintTool [SerializeField] bool m_ShowLayerEditor = false; - [SerializeField] - float m_SplatAlpha = 1.0f; - public override string GetName() { return "Paint Texture"; @@ -45,7 +42,8 @@ public override bool OnPaint(Terrain terrain, IOnPaint editContext) Material mat = TerrainPaintUtility.GetBuiltinPaintMaterial(); // apply brush - Vector4 brushParams = new Vector4(editContext.brushStrength, m_SplatAlpha, 0.0f, 0.0f); + float targetAlpha = 1.0f; // always 1.0 now -- no subtractive painting (we assume this in the ScatterAlphaMap) + Vector4 brushParams = new Vector4(editContext.brushStrength, targetAlpha, 0.0f, 0.0f); mat.SetTexture("_BrushTex", editContext.brushTexture); mat.SetVector("_BrushParams", brushParams); @@ -103,7 +101,6 @@ public override void OnInspectorGUI(Terrain terrain, IOnInspectorGUI editContext GUILayout.Label("Settings", EditorStyles.boldLabel); EditorGUI.BeginChangeCheck(); - m_SplatAlpha = EditorGUILayout.Slider("Target Strength", m_SplatAlpha, 0.0F, 1.0F); EditorGUILayout.Space(); if (m_TemplateMaterialEditor != null && m_TemplateMaterialEditor.target != terrain.materialTemplate) diff --git a/Modules/TerrainEditor/TerrainInspector.cs b/Modules/TerrainEditor/TerrainInspector.cs index de381c2fe1..b0df34322f 100644 --- a/Modules/TerrainEditor/TerrainInspector.cs +++ b/Modules/TerrainEditor/TerrainInspector.cs @@ -508,6 +508,7 @@ class Styles "console.warnicon"); public GUIContent assign = EditorGUIUtility.TrTextContent("Assign"); + public GUIContent duplicateTab = EditorGUIUtility.TrTextContent("NOTE: Inspector tab is a duplicate. Paint functionality disabled."); // Textures public GUIContent terrainLayers = EditorGUIUtility.TrTextContent("Terrain Layers"); @@ -1465,6 +1466,8 @@ public void ShowPaint() public void ShowBrushes(int spacing) { + EditorGUI.BeginDisabledGroup(s_activeTerrainInspector != GetInstanceID() || s_activeTerrainInspectorInstance != this); + GUILayout.Space(spacing); bool repaint = brushList.ShowGUI(); @@ -1476,6 +1479,8 @@ public void ShowBrushes(int spacing) if (repaint) Repaint(); + + EditorGUI.EndDisabledGroup(); } void ResizeControlTexture(int newResolution) @@ -1755,6 +1760,12 @@ public override void OnInspectorGUI() return; } + if (s_activeTerrainInspector != GetInstanceID() || s_activeTerrainInspectorInstance != this) + { + GUILayout.BeginVertical(EditorStyles.helpBox); + GUILayout.Label(styles.duplicateTab, EditorStyles.boldLabel); + GUILayout.EndVertical(); + } if (Event.current.type == EventType.Layout) m_TerrainCollider = m_Terrain.gameObject.GetComponent(); @@ -1773,6 +1784,8 @@ public override void OnInspectorGUI() GUILayout.EndVertical(); } + EditorGUI.BeginDisabledGroup(s_activeTerrainInspector != GetInstanceID() || s_activeTerrainInspectorInstance != this); + // Show the master tool selector GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); // flexible space on either end centers the toolbar @@ -1811,6 +1824,8 @@ public override void OnInspectorGUI() GUILayout.EndVertical(); } + EditorGUI.EndDisabledGroup(); + switch ((TerrainTool)tool) { case TerrainTool.Paint: @@ -1967,6 +1982,10 @@ public void OnSceneGUICallback(SceneView sceneView) Terrain hitTerrain = null; RaycastHit raycastHit = new RaycastHit(); + // If this is not the active terrain inspector, we shouldn't be affecting the SceneGUI + if (s_activeTerrainInspector != GetInstanceID() || s_activeTerrainInspectorInstance != this) + return; + if (selectedTool == TerrainTool.Paint || selectedTool == TerrainTool.PaintDetail || selectedTool == TerrainTool.PlaceTree) diff --git a/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs b/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs index 22743c45f5..b054015c93 100644 --- a/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs +++ b/Modules/TerrainEditor/Utilities/TerrainPaintUtilityEditor.cs @@ -30,7 +30,7 @@ static TerrainPaintUtilityEditor() s_CurrentOperationUndoStack.Clear(); } - if (tile == null || string.IsNullOrEmpty(editorUndoName) || tile.rect.width == 0 || tile.rect.height == 0) + if (tile == null || string.IsNullOrEmpty(editorUndoName)) return; if (!s_CurrentOperationUndoStack.Contains(tile.terrain)) diff --git a/Modules/TextCore/Managed/OpenTypeCommon.cs b/Modules/TextCore/Managed/OpenTypeCommon.cs new file mode 100644 index 0000000000..c3ce401050 --- /dev/null +++ b/Modules/TextCore/Managed/OpenTypeCommon.cs @@ -0,0 +1,161 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using UnityEngine.Scripting; + + +namespace UnityEngine.TextCore.LowLevel +{ + /// + /// The values used to adjust the position of a glyph or set of glyphs. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphValueRecord + { + /// + /// The positional adjustment affecting the horizontal bearing X of the glyph. + /// + public float xPlacement { get { return m_XPlacement; } set { m_XPlacement = value; } } + + /// + /// The positional adjustment affecting the horizontal bearing Y of the glyph. + /// + public float yPlacement { get { return m_YPlacement; } set { m_YPlacement = value; } } + + /// + /// The positional adjustment affecting the horizontal advance of the glyph. + /// + public float xAdvance { get { return m_XAdvance; } set { m_XAdvance = value; } } + + /// + /// The positional adjustment affecting the vertical advance of the glyph. + /// + public float yAdvance { get { return m_YAdvance; } set { m_YAdvance = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("xPlacement")] + private float m_XPlacement; + + [SerializeField] + [NativeName("yPlacement")] + private float m_YPlacement; + + [SerializeField] + [NativeName("xAdvance")] + private float m_XAdvance; + + [SerializeField] + [NativeName("yAdvance")] + private float m_YAdvance; + + + /// + /// Constructor + /// + /// The positional adjustment affecting the horizontal bearing X of the glyph. + /// The positional adjustment affecting the horizontal bearing Y of the glyph. + /// The positional adjustment affecting the horizontal advance of the glyph. + /// The positional adjustment affecting the vertical advance of the glyph. + public GlyphValueRecord(float xPlacement, float yPlacement, float xAdvance, float yAdvance) + { + m_XPlacement = xPlacement; + m_YPlacement = yPlacement; + m_XAdvance = xAdvance; + m_YAdvance = yAdvance; + } + + public static GlyphValueRecord operator+(GlyphValueRecord a, GlyphValueRecord b) + { + GlyphValueRecord c; + c.m_XPlacement = a.xPlacement + b.xPlacement; + c.m_YPlacement = a.yPlacement + b.yPlacement; + c.m_XAdvance = a.xAdvance + b.xAdvance; + c.m_YAdvance = a.yAdvance + b.yAdvance; + + return c; + } + } + + /// + /// The positional adjustment values of a glyph. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphAdjustmentRecord + { + /// + /// The index of the glyph in the source font file. + /// + public uint glyphIndex { get { return m_GlyphIndex; } set { m_GlyphIndex = value; } } + + /// + /// The GlyphValueRecord contains the positional adjustments of the glyph. + /// + public GlyphValueRecord glyphValueRecord { get { return m_GlyphValueRecord; } set { m_GlyphValueRecord = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("glyphIndex")] + private uint m_GlyphIndex; + + [SerializeField] + [NativeName("glyphValueRecord")] + private GlyphValueRecord m_GlyphValueRecord; + + /// + /// Constructor + /// + /// The index of the glyph in the source font file. + /// The GlyphValueRecord contains the positional adjustments of the glyph. + public GlyphAdjustmentRecord(uint glyphIndex, GlyphValueRecord glyphValueRecord) + { + m_GlyphIndex = glyphIndex; + m_GlyphValueRecord = glyphValueRecord; + } + } + + /// + /// The positional adjustment values for a pair of glyphs. + /// + [Serializable] + [UsedByNativeCode] + [StructLayout(LayoutKind.Sequential)] + internal struct GlyphPairAdjustmentRecord + { + /// + /// Contains the positional adjustment values for the first glyph. + /// + public GlyphAdjustmentRecord firstAdjustmentRecord { get { return m_FirstAdjustmentRecord; } set { m_FirstAdjustmentRecord = value; } } + + /// + /// Contains the positional adjustment values for the second glyph. + /// + public GlyphAdjustmentRecord secondAdjustmentRecord { get { return m_SecondAdjustmentRecord; } set { m_SecondAdjustmentRecord = value; } } + + // ============================================= + // Private backing fields for public properties. + // ============================================= + + [SerializeField] + [NativeName("firstAdjustmentRecord")] + private GlyphAdjustmentRecord m_FirstAdjustmentRecord; + + [SerializeField] + [NativeName("secondAdjustmentRecord")] + private GlyphAdjustmentRecord m_SecondAdjustmentRecord; + } +} diff --git a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs index d886798a11..0505978ef4 100644 --- a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs +++ b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs @@ -72,6 +72,7 @@ public enum FontEngineError Invalid_File_Format = 0x2, Invalid_File_Structure = 0x3, Invalid_File = 0x4, + Invalid_Table = 0x8, // Glyph related errors. Invalid_Glyph_Index = 0x10, @@ -140,6 +141,8 @@ public sealed class FontEngine private static GlyphRect[] s_FreeGlyphRects = new GlyphRect[16]; private static GlyphRect[] s_UsedGlyphRects = new GlyphRect[16]; + private static GlyphPairAdjustmentRecord[] s_GlyphPairAdjustmentRecords; + private static Dictionary s_GlyphLookupDictionary = new Dictionary(); internal FontEngine() {} @@ -802,11 +805,42 @@ extern static bool TryAddGlyphToTexture_Internal(uint glyphIndex, int padding, GlyphRenderMode renderMode, Texture2D texture, out GlyphMarshallingStruct glyph); + /// + /// Internal function used to retrieve positional adjustments for pairs of glyphs. + /// + /// List of glyph indexes to check for potential positional adjustment records. + /// Array containing the positional adjustments for pairs of glyphs. + internal static GlyphPairAdjustmentRecord[] GetGlyphPairAdjustmentTable(uint[] glyphIndexes) + { + int maxGlyphPairAdjustmentRecords = glyphIndexes.Length * glyphIndexes.Length; + + if (s_GlyphPairAdjustmentRecords == null || s_GlyphPairAdjustmentRecords.Length < maxGlyphPairAdjustmentRecords) + { + s_GlyphPairAdjustmentRecords = new GlyphPairAdjustmentRecord[maxGlyphPairAdjustmentRecords]; + } + + int adjustmentRecordCount; + if (GetGlyphPairAdjustmentTable_Internal(glyphIndexes, s_GlyphPairAdjustmentRecords, out adjustmentRecordCount) != 0) + { + // TODO: Add debug warning messages. + return null; + } + + GlyphPairAdjustmentRecord[] pairAdjustmentRecords = new GlyphPairAdjustmentRecord[adjustmentRecordCount]; + + for (int i = 0; i < adjustmentRecordCount; i++) + { + pairAdjustmentRecords[i] = s_GlyphPairAdjustmentRecords[i]; + } + + return pairAdjustmentRecords; + } + /// /// /// [NativeMethod(Name = "TextCore::FontEngine::GetGlyphPairAdjustmentTable", IsFreeFunction = true)] - internal extern static void GetGlyphPairAdjustmentTable(); + extern static int GetGlyphPairAdjustmentTable_Internal(uint[] glyphIndexes, [Out] GlyphPairAdjustmentRecord[] glyphPairAdjustmentRecords, out int adjustmentRecordCount); // ================================================ // Experimental / Testing / Benchmarking Functions diff --git a/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs b/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs index 2fbe0c30a8..26d704374f 100644 --- a/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs +++ b/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs @@ -258,6 +258,42 @@ public void EditorPreviewBoxFill(Vector3Int position, Object tile, int startX, i [NativeMethod(Name = "ClearAllEditorPreviewTileAssets")] public extern void ClearAllEditorPreviewTiles(); + + [RequiredByNativeCode] + internal struct SyncTile + { + public Vector3Int m_Position; + public TileBase m_Tile; + public TileData m_TileData; + } + + internal static event Action tilemapTileChanged; + + internal static void SetSyncTileCallback(Action callback) + { + Tilemap.tilemapTileChanged += callback; + } + + internal static void RemoveSyncTileCallback(Action callback) + { + Tilemap.tilemapTileChanged -= callback; + } + + [RequiredByNativeCode] + private static bool HasSyncTileCallback() + { + return (Tilemap.tilemapTileChanged != null); + } + + [RequiredByNativeCode] + private void DoSyncTileCallback(SyncTile[] syncTiles) + { + if (Tilemap.tilemapTileChanged == null) + return; + + Tilemap.tilemapTileChanged(this, syncTiles); + } + } [RequireComponent(typeof(Tilemap))] diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs index 978133932c..43d0696099 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrush.cs @@ -5,6 +5,7 @@ using System; using UnityEngine.Tilemaps; using UnityEngine; +using System.Collections; namespace UnityEditor { @@ -22,6 +23,9 @@ public class GridBrush : GridBrushBase [HideInInspector] private Vector3Int m_Pivot; + private ArrayList m_Locations; + private ArrayList m_Tiles; + private static readonly Matrix4x4 s_Clockwise = new Matrix4x4(new Vector4(0f, 1f, 0f, 0f), new Vector4(-1f, 0f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f)); private static readonly Matrix4x4 s_CounterClockwise = new Matrix4x4(new Vector4(0f, -1f, 0f, 0f), new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f)); private static readonly Matrix4x4 s_180Rotate = new Matrix4x4(new Vector4(-1f, 0f, 0f, 0f), new Vector4(0f, -1f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, 0f, 0f, 1f)); @@ -31,6 +35,26 @@ public class GridBrush : GridBrushBase public BrushCell[] cells { get { return m_Cells; } } public int cellCount { get { return m_Cells != null ? m_Cells.Length : 0; } } + private ArrayList locations + { + get + { + if (m_Locations == null) + m_Locations = new ArrayList(); + return m_Locations; + } + } + + private ArrayList tiles + { + get + { + if (m_Tiles == null) + m_Tiles = new ArrayList(); + return m_Tiles; + } + } + public GridBrush() { Init(Vector3Int.one, Vector3Int.zero); @@ -57,14 +81,6 @@ public override void Paint(GridLayout gridLayout, GameObject brushTarget, Vector BoxFill(gridLayout, brushTarget, bounds); } - private void PaintCell(Vector3Int position, Tilemap tilemap, BrushCell cell) - { - if (cell.tile != null) - { - SetTilemapCell(tilemap, position, cell.tile, cell.matrix, cell.color); - } - } - public override void Erase(GridLayout gridLayout, GameObject brushTarget, Vector3Int position) { Vector3Int min = position - pivot; @@ -72,22 +88,37 @@ public override void Erase(GridLayout gridLayout, GameObject brushTarget, Vector BoxErase(gridLayout, brushTarget, bounds); } - private void EraseCell(Vector3Int position, Tilemap tilemap) - { - ClearTilemapCell(tilemap, position); - } - public override void BoxFill(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) { if (brushTarget == null) return; Tilemap map = brushTarget.GetComponent(); + if (map == null) + return; + + locations.Clear(); + tiles.Clear(); foreach (Vector3Int location in position.allPositionsWithin) { Vector3Int local = location - position.min; BrushCell cell = m_Cells[GetCellIndexWrapAround(local.x, local.y, local.z)]; - PaintCell(location, map, cell); + if (cell.tile == null) + continue; + + locations.Add(location); + tiles.Add(cell.tile); + } + map.SetTiles((Vector3Int[])locations.ToArray(typeof(Vector3Int)), (TileBase[])tiles.ToArray(typeof(TileBase))); + foreach (Vector3Int location in position.allPositionsWithin) + { + Vector3Int local = location - position.min; + BrushCell cell = m_Cells[GetCellIndexWrapAround(local.x, local.y, local.z)]; + if (cell.tile == null) + continue; + + map.SetTransformMatrix(location, cell.matrix); + map.SetColor(location, cell.color); } } @@ -97,9 +128,15 @@ public override void BoxErase(GridLayout gridLayout, GameObject brushTarget, Bou return; Tilemap map = brushTarget.GetComponent(); + if (map == null) + return; + + var emptyTiles = new TileBase[position.size.x * position.size.y * position.size.z]; + map.SetTilesBlock(position, emptyTiles); foreach (Vector3Int location in position.allPositionsWithin) { - EraseCell(location, map); + map.SetTransformMatrix(location, Matrix4x4.identity); + map.SetColor(location, Color.white); } } @@ -112,10 +149,10 @@ public override void FloodFill(GridLayout gridLayout, GameObject brushTarget, Ve return; Tilemap map = brushTarget.GetComponent(); - if (map != null) - { - map.FloodFill(position, cells[0].tile); - } + if (map == null) + return; + + map.FloodFill(position, cells[0].tile); } public override void Rotate(RotationDirection direction, Grid.CellLayout layout) @@ -251,12 +288,12 @@ public override void Pick(GridLayout gridLayout, GameObject brushTarget, BoundsI private void PickCell(Vector3Int position, Vector3Int brushPosition, Tilemap tilemap) { - if (tilemap != null) - { - SetTile(brushPosition, tilemap.GetTile(position)); - SetMatrix(brushPosition, tilemap.GetTransformMatrix(position)); - SetColor(brushPosition, tilemap.GetColor(position)); - } + if (tilemap == null) + return; + + SetTile(brushPosition, tilemap.GetTile(position)); + SetMatrix(brushPosition, tilemap.GetTransformMatrix(position)); + SetColor(brushPosition, tilemap.GetColor(position)); } public override void MoveStart(GridLayout gridLayout, GameObject brushTarget, BoundsInt position) @@ -265,14 +302,14 @@ public override void MoveStart(GridLayout gridLayout, GameObject brushTarget, Bo UpdateSizeAndPivot(new Vector3Int(position.size.x, position.size.y, 1), Vector3Int.zero); Tilemap tilemap = brushTarget.GetComponent(); - if (tilemap != null) + if (tilemap == null) + return; + + foreach (Vector3Int pos in position.allPositionsWithin) { - foreach (Vector3Int pos in position.allPositionsWithin) - { - Vector3Int brushPosition = new Vector3Int(pos.x - position.x, pos.y - position.y, 0); - PickCell(pos, brushPosition, tilemap); - tilemap.SetTile(pos, null); - } + Vector3Int brushPosition = new Vector3Int(pos.x - position.x, pos.y - position.y, 0); + PickCell(pos, brushPosition, tilemap); + tilemap.SetTile(pos, null); } } @@ -402,26 +439,6 @@ private void SizeUpdated() } } - private static void SetTilemapCell(Tilemap map, Vector3Int location, TileBase tile, Matrix4x4 transformMatrix, Color color) - { - if (map == null) - return; - - map.SetTile(location, tile); - map.SetTransformMatrix(location, transformMatrix); - map.SetColor(location, color); - } - - private static void ClearTilemapCell(Tilemap map, Vector3Int location) - { - if (map == null) - return; - - map.SetTile(location, null); - map.SetTransformMatrix(location, Matrix4x4.identity); - map.SetColor(location, Color.white); - } - public override int GetHashCode() { int hash = 0; diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs index 52f2e82669..18c19f5850 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs @@ -228,11 +228,6 @@ public override void RegisterUndo(GameObject brushTarget, GridBrushBase.Tool too { if (brushTarget != null) { - var tilemap = brushTarget.GetComponent(); - if (tilemap != null) - { - Undo.RecordObject(tilemap, tool.ToString()); - } Undo.RegisterFullObjectHierarchyUndo(brushTarget, tool.ToString()); } } diff --git a/Modules/UIElements/ListView.cs b/Modules/UIElements/ListView.cs index 64f5e45f30..d037bf99da 100644 --- a/Modules/UIElements/ListView.cs +++ b/Modules/UIElements/ListView.cs @@ -237,6 +237,13 @@ private void OnClick(MouseDownEvent evt) return; var clickedIndex = (int)(evt.localMousePosition.y / itemHeight); + + // ignore clicks on empty space + if (clickedIndex > itemsSource.Count - 1) + { + return; + } + switch (evt.clickCount) { case 1: diff --git a/Modules/UIElements/Panel.cs b/Modules/UIElements/Panel.cs index f08c931e8c..aca4cf735c 100644 --- a/Modules/UIElements/Panel.cs +++ b/Modules/UIElements/Panel.cs @@ -367,7 +367,7 @@ internal static long DefaultTimeSinceStartupMs() return (long)(Time.realtimeSinceStartup * 1000.0f); } - VisualElement PickAll(VisualElement root, Vector2 point, List picked = null) + internal static VisualElement PickAll(VisualElement root, Vector2 point, List picked = null) { Profiler.BeginSample("Panel.PickAll"); var result = PerformPick(root, point, picked); @@ -375,7 +375,7 @@ VisualElement PickAll(VisualElement root, Vector2 point, List pic return result; } - private VisualElement PerformPick(VisualElement root, Vector2 point, List picked = null) + private static VisualElement PerformPick(VisualElement root, Vector2 point, List picked = null) { // do not pick invisible if (root.visible == false) diff --git a/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs b/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs index 7ac9f080a8..93fee2fff8 100644 --- a/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs +++ b/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs @@ -13,6 +13,41 @@ namespace UnityEngine.Analytics [NativeHeader("Modules/UnityAnalytics/Public/Events/UserCustomEvent.h")] public static partial class Analytics { + public static bool initializeOnStartup + { + get + { + if (!IsInitialized()) + return false; + return initializeOnStartupInternal; + } + set + { + if (IsInitialized()) + initializeOnStartupInternal = value; + } + } + + public static AnalyticsResult ResumeInitialization() + { + if (!IsInitialized()) + return AnalyticsResult.NotInitialized; + return ResumeInitializationInternal(); + } + + [StaticAccessor("GetUnityAnalytics()", StaticAccessorType.Dot)] + [NativeMethod("ResumeInitialization")] + private static extern AnalyticsResult ResumeInitializationInternal(); + + [StaticAccessor("GetUnityAnalytics()", StaticAccessorType.Dot)] + private extern static bool initializeOnStartupInternal + { + [NativeMethod("GetInitializeOnStartup")] + get; + [NativeMethod("SetInitializeOnStartup")] + set; + } + [ThreadSafe] private static extern bool IsInitialized(); diff --git a/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs b/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs index 2401ade069..6581da1271 100644 --- a/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs +++ b/Modules/VFX/Public/ScriptBindings/VisualEffect.bindings.cs @@ -64,7 +64,7 @@ public void SendEvent(string eventName) public void SendEvent(string eventName, VFXEventAttribute eventAttribute) { - SendEvent(Shader.PropertyToID(eventName), null); + SendEvent(Shader.PropertyToID(eventName), eventAttribute); } extern public void Reinit(); diff --git a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs index 10b9a80910..8b16ca9b96 100644 --- a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs +++ b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectResource.bindings.cs @@ -35,7 +35,6 @@ internal struct VFXRendererSettings public bool receiveShadows; public ReflectionProbeUsage reflectionProbeUsage; public LightProbeUsage lightProbeUsage; - public int transparencyPriority; } [UsedByNativeCode] diff --git a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectUtility.bindings.cs b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectUtility.bindings.cs index 255aba86b2..e0b19a60c6 100644 --- a/Modules/VFXEditor/Public/ScriptBindings/VisualEffectUtility.bindings.cs +++ b/Modules/VFXEditor/Public/ScriptBindings/VisualEffectUtility.bindings.cs @@ -56,5 +56,13 @@ static public Gradient GetExpressionGradient(VisualEffect effect, uint expressio [FreeFunction(Name = "VisualEffectUtility::GetExpressionGradient", ThrowsException = true)] static extern private void GetExpressionGradient([NotNull] VisualEffect effect, uint expressionIndex, Gradient gradient); + + extern public static bool renderBounds + { + [FreeFunction(Name = "VisualEffectUtility::GetRenderBounds")] + get; + [FreeFunction(Name = "VisualEffectUtility::SetRenderBounds")] + set; + } } } diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index 03dd7982eb..4adac421dd 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -4461,6 +4461,9 @@ Modules\ShortcutManagerEditor\IShortcutPriorityContext.cs + + Modules\ShortcutManagerEditor\KeyCombination.cs + Modules\ShortcutManagerEditor\PriorityContextAttribute.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 953308b49b..bfcca14532 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1518,6 +1518,9 @@ Modules\TextCore\Managed\Glyph.cs + + Modules\TextCore\Managed\OpenTypeCommon.cs + Modules\TextCore\ScriptBindings\FontEngine.bindings.cs diff --git a/README.md b/README.md index 9d239fc5b0..777698aff2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b6 C# reference source code +## Unity 2018.3.0b7 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/AssemblyInfo.cs b/Runtime/Export/AssemblyInfo.cs index 8f7751eb50..b6102a5ea3 100644 --- a/Runtime/Export/AssemblyInfo.cs +++ b/Runtime/Export/AssemblyInfo.cs @@ -91,7 +91,7 @@ [assembly: InternalsVisibleTo("Unity.InternalAPIEngineBridgeDev.004")] [assembly: InternalsVisibleTo("Unity.InternalAPIEngineBridgeDev.005")] -[assembly: InternalsVisibleTo("Unity.Subsystem.Declaration")] +[assembly: InternalsVisibleTo("Unity.Subsystem.Registration")] // Note: Don't add InternalsVisibleTo for UnityEngine.UI, because it's editable by users and it shouldn't access internal UnityEngine methods diff --git a/Runtime/Export/Graphics.bindings.cs b/Runtime/Export/Graphics.bindings.cs index 76668a828b..906c6a225e 100644 --- a/Runtime/Export/Graphics.bindings.cs +++ b/Runtime/Export/Graphics.bindings.cs @@ -538,3 +538,28 @@ public extern UnityEngine.Rendering.SphericalHarmonicsL2[] bakedProbes public extern int cellCount {[NativeName("GetTetrahedraSize")] get; } } } + +namespace UnityEngine.Experimental.Rendering +{ + public enum WaitForPresentSyncPoint + { + BeginFrame = 0, + EndFrame = 1 + } + + public enum GraphicsJobsSyncPoint + { + EndOfFrame = 0, + AfterScriptUpdate = 1, + AfterScriptLateUpdate = 2, + WaitForPresent = 3 + }; + + public static partial class GraphicsDeviceSettings + { + [StaticAccessor("GetGfxDevice()", StaticAccessorType.Dot)] + extern public static WaitForPresentSyncPoint waitForPresentSyncPoint { get; set; } + [StaticAccessor("GetGfxDevice()", StaticAccessorType.Dot)] + extern public static GraphicsJobsSyncPoint graphicsJobsSyncPoint { get; set; } + } +} diff --git a/Runtime/Export/Logger/DebugLogHandler.cs b/Runtime/Export/Logger/DebugLogHandler.cs index c60c63622a..a43a3a5d15 100644 --- a/Runtime/Export/Logger/DebugLogHandler.cs +++ b/Runtime/Export/Logger/DebugLogHandler.cs @@ -15,6 +15,9 @@ public void LogFormat(LogType logType, Object context, string format, params obj public void LogException(Exception exception, Object context) { + if (exception == null) + throw new ArgumentNullException("exception"); + Internal_LogException(exception, context); } } diff --git a/Runtime/Export/PlayerLoop.bindings.cs b/Runtime/Export/PlayerLoop.bindings.cs index 19ae77c163..72314113da 100644 --- a/Runtime/Export/PlayerLoop.bindings.cs +++ b/Runtime/Export/PlayerLoop.bindings.cs @@ -176,7 +176,7 @@ public struct UpdateMasterServerInterface {} [RequiredByNativeCode] public struct UNetUpdate {} [RequiredByNativeCode] - public struct EndGraphicsJobsLate {} + public struct EndGraphicsJobsAfterScriptUpdate {} [RequiredByNativeCode] public struct ParticleSystemBeginUpdateAll {} [RequiredByNativeCode] @@ -208,6 +208,8 @@ public struct VFXUpdate {} [RequiredByNativeCode] public struct ParticleSystemEndUpdateAll {} [RequiredByNativeCode] + public struct EndGraphicsJobsAfterScriptLateUpdate {} + [RequiredByNativeCode] public struct UpdateSubstance {} [RequiredByNativeCode] public struct UpdateCustomRenderTextures {} diff --git a/Runtime/Export/RenderPipeline/CullingParameters.cs b/Runtime/Export/RenderPipeline/CullingParameters.cs index 95debed7c2..b2fe4d9e91 100644 --- a/Runtime/Export/RenderPipeline/CullingParameters.cs +++ b/Runtime/Export/RenderPipeline/CullingParameters.cs @@ -65,6 +65,7 @@ unsafe public struct CameraProperties CoreCameraValues coreCameraValues; uint cameraType; + private int projectionIsOblique; public Plane GetShadowCullingPlane(int index) { diff --git a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs index 532b49ce9f..f1fe7ae225 100644 --- a/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs +++ b/Runtime/ParticleSystem/ScriptBindings/ParticleSystem.bindings.cs @@ -14,6 +14,7 @@ namespace UnityEngine { [NativeHeader("ParticleSystemScriptingClasses.h")] [NativeHeader("Runtime/ParticleSystem/ParticleSystem.h")] + [NativeHeader("Runtime/ParticleSystem/ParticleSystemGeometryJob.h")] [NativeHeader("Runtime/ParticleSystem/ScriptBindings/ParticleSystemScriptBindings.h")] [RequireComponent(typeof(Transform))] public partial class ParticleSystem : Component @@ -283,6 +284,9 @@ public CustomDataModule customData [NativeName(Name = "SyncJobs()->EmitParticlesExternal")] extern public void Emit(ParticleSystem.EmitParams emitParams, int count); + [FreeFunction(Name = "ParticleSystemGeometryJob::ResetPreMappedBufferMemory")] + extern public static void ResetPreMappedBufferMemory(); + [FreeFunction(Name = "ParticleSystemEditor::SetupDefaultParticleSystemType", HasExplicitThis = true)] extern internal void SetupDefaultType(ParticleSystemSubEmitterType type); @@ -304,10 +308,10 @@ extern internal Matrix4x4 localToWorldMatrix extern internal bool CalculateEffectUISubEmitterData(ref int particleCount, ref float fastestParticle, ref float slowestParticle); [FreeFunction(Name = "ParticleSystemScriptBindings::CheckVertexStreamsMatchShader")] - extern static internal bool CheckVertexStreamsMatchShader(bool hasTangent, bool hasColor, int texCoordChannelCount, Material material, ref bool tangentError, ref bool colorError, ref bool uvError); + extern internal static bool CheckVertexStreamsMatchShader(bool hasTangent, bool hasColor, int texCoordChannelCount, Material material, ref bool tangentError, ref bool colorError, ref bool uvError); [FreeFunction(Name = "ParticleSystemScriptBindings::GetMaxTexCoordStreams")] - extern static internal int GetMaxTexCoordStreams(); + extern internal static int GetMaxTexCoordStreams(); } } diff --git a/Runtime/Profiler/ScriptBindings/Profiler.bindings.cs b/Runtime/Profiler/ScriptBindings/Profiler.bindings.cs index 8ff99cecec..9173dfda3e 100644 --- a/Runtime/Profiler/ScriptBindings/Profiler.bindings.cs +++ b/Runtime/Profiler/ScriptBindings/Profiler.bindings.cs @@ -162,7 +162,7 @@ public static void BeginSample(string name, Object targetObject) // End profiling a piece of code with a custom label. // TODO: make obsolete //OBSOLETE warning Profiler.EndSample method is deprecated. Please use faster CustomSampler.End method instead. - [NativeConditional("ENABLE_PROFILER")] + [Conditional("ENABLE_PROFILER")] [NativeMethod(Name = "ProfilerBindings::EndSample", IsFreeFunction = true, IsThreadSafe = true)] public extern static void EndSample(); From 31c7ca85bcc43ef4258c2a216b195ad1d6e59948 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 31 Oct 2018 10:43:25 +0000 Subject: [PATCH 06/10] Unity 2018.3.0b8 C# reference source code --- Editor/Mono/BuildPipeline.bindings.cs | 2 +- Editor/Mono/BuildPipeline/AssemblyStripper.cs | 27 ++++++++-- .../Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs | 41 +++++++++++----- .../Il2Cpp/Il2CppNativeCodeBuilder.cs | 12 +++++ Editor/Mono/Commands/GOCreationCommands.cs | 11 ++++- .../TextureImportPlatformSettings.cs | 10 ++-- Editor/Mono/Inspector/InspectorWindow.cs | 46 ++++++++++-------- .../PlayerSettingsEditor.cs | 18 ++++--- .../Inspector/StandardParticlesShaderGUI.cs | 11 ++++- .../LookDevView/CameraControllerStandard.cs | 2 +- Editor/Mono/MenuItem.cs | 10 +++- .../DefaultTextureImportSettingsExtension.cs | 8 +-- .../ParticleSystemModules/SubModuleUI.cs | 3 +- Editor/Mono/PlayerSettings.bindings.cs | 5 +- Editor/Mono/ProjectBrowser.cs | 5 +- Editor/Mono/SceneHierarchy.cs | 17 +++++-- Editor/Mono/SceneHierarchyStageHandling.cs | 2 + .../StageManager/PrefabStage/PrefabStage.cs | 39 ++++++++++----- .../PrefabStage/PrefabStageUtility.cs | 12 +++-- .../StageManager/StageNavigationManager.cs | 7 +++ Editor/Mono/SceneView/CameraFlyModeContext.cs | 22 +++++++-- Editor/Mono/SceneView/SceneViewMotion.cs | 2 +- Editor/Mono/ScriptEditorUtility.cs | 2 + .../Scripting/Compilers/ScriptCompilerBase.cs | 3 +- .../Providers/AssetSettingsProvider.cs | 40 ++++++++------- Editor/Mono/Settings/SettingsWindow.cs | 6 +-- .../UIElements/Controls/BasePopupField.cs | 5 +- .../lib/mono/2.0/Boo.Lang.Compiler.dll | Bin 934912 -> 934912 bytes .../lib/mono/2.0/Boo.Lang.Parser.dll | Bin 414208 -> 414208 bytes .../lib/mono/2.0/Boo.Lang.dll | Bin 126976 -> 126976 bytes .../lib/mono/2.0/Mono.Posix.dll | Bin 184320 -> 184320 bytes .../lib/mono/2.0/Mono.Security.dll | Bin 294912 -> 294912 bytes .../lib/mono/2.0/System.Core.dll | Bin 297984 -> 297984 bytes .../lib/mono/2.0/System.Xml.Linq.dll | Bin 106496 -> 106496 bytes .../lib/mono/2.0/System.Xml.dll | Bin 1270272 -> 1270272 bytes .../monodistribution/lib/mono/2.0/System.dll | Bin 1679360 -> 1679360 bytes .../lib/mono/2.0/UnityScript.dll | Bin 177664 -> 177664 bytes Modules/TerrainEditor/Brush/BrushEditor.cs | 2 +- .../Editor/Managed/Grid/GridBrushEditor.cs | 3 +- .../Managed/Grid/GridPaintPaletteWindow.cs | 3 ++ .../Editor/Managed/Grid/GridPaintingState.cs | 26 +++++----- .../Managed/Grid/GridPaletteAddPopup.cs | 25 +++++++++- .../Editor/Managed/Grid/GridPaletteUtility.cs | 2 - .../Editor/Managed/TilemapEditor.cs | 2 +- .../VideoMediaPlayback.bindings.cs | 1 + README.md | 2 +- .../Managed/ParticleSystemEnums.cs | 3 +- 47 files changed, 305 insertions(+), 132 deletions(-) diff --git a/Editor/Mono/BuildPipeline.bindings.cs b/Editor/Mono/BuildPipeline.bindings.cs index 64e3257ace..97178da1a3 100644 --- a/Editor/Mono/BuildPipeline.bindings.cs +++ b/Editor/Mono/BuildPipeline.bindings.cs @@ -517,7 +517,7 @@ internal static string GetPlaybackEngineDirectory(BuildTarget target, BuildOptio internal static extern string GetMonoBinDirectory(BuildTarget target); [FreeFunction] - internal static extern string GetMonoLibDirectory(BuildTarget target); + internal static extern string GetMonoRuntimeLibDirectory(BuildTarget target); [FreeFunction] internal static extern string CompatibilityProfileToClassLibFolder(ApiCompatibilityLevel compatibilityLevel); diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index 94da574fe4..c8a41c3c57 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -88,10 +88,12 @@ private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, if (EditorUserBuildSettings.development) args.Add("--editor-settings-flag=Development"); - // One final check to make sure we only run aggressive on latest runtime. - if ((managedStrippingLevel == ManagedStrippingLevel.Aggressive) && (PlayerSettingsEditor.IsLatestApiCompatibility(PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup)))) + args.Add($"--rule-set={GetRuleSetForStrippingLevel(managedStrippingLevel)}"); + + // One final check to make sure we only run high on latest runtime. + if ((managedStrippingLevel == ManagedStrippingLevel.High) && (PlayerSettingsEditor.IsLatestApiCompatibility(PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup)))) { - // Prepare the arguments to run the UnityLinker. When in aggressive mode, need to also + // Prepare the arguments to run the UnityLinker. When in high mode, need to also // supply the IL2CPP compiler platform and compiler architecture. When the scripting backend // is not IL2CPP, we have to map those strings and use a utility function to figure out proper strings. @@ -108,7 +110,7 @@ private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, { GetUnityLinkerPlatformStringsFromBuildTarget(platformProvider.target, out compilerPlatform, out compilerArchitecture); } - args.Add("--aggressive"); + args.Add($"--platform={compilerPlatform}"); if (platformProvider.target != BuildTarget.Android) args.Add($"--architecture={compilerArchitecture}"); @@ -125,6 +127,21 @@ private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, return RunAssemblyLinker(args, out output, out error, linkerPath, workingDirectory); } + private static string GetRuleSetForStrippingLevel(ManagedStrippingLevel managedStrippingLevel) + { + switch (managedStrippingLevel) + { + case ManagedStrippingLevel.Low: + return "Conservative"; + case ManagedStrippingLevel.Medium: + return "Aggressive"; + case ManagedStrippingLevel.High: + return "Experimental"; + } + + throw new ArgumentException($"Unhandled {nameof(ManagedStrippingLevel)} value of {managedStrippingLevel}"); + } + private static void GetUnityLinkerPlatformStringsFromBuildTarget(BuildTarget target, out string platform, out string architecture) { switch (target) @@ -167,7 +184,7 @@ private static void GetUnityLinkerPlatformStringsFromBuildTarget(BuildTarget tar architecture = "ARM64"; break; default: - throw new NotSupportedException($"Aggressive stripping is not supported for mono backend on {target}."); + throw new ArgumentException($"Mapping to UnityLinker platform not implemented for {nameof(BuildTarget)} `{target}`"); } } diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs index 9d079e57f6..cf0a9471c7 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs @@ -141,6 +141,28 @@ internal static string GetIl2CppFolder() EditorApplication.applicationContentsPath, "il2cpp")); } + + internal static string GetAdditionalArguments() + { + var arguments = new List(); + var additionalArgs = PlayerSettings.GetAdditionalIl2CppArgs(); + if (!string.IsNullOrEmpty(additionalArgs)) + arguments.Add(additionalArgs); + + additionalArgs = System.Environment.GetEnvironmentVariable("IL2CPP_ADDITIONAL_ARGS"); + if (!string.IsNullOrEmpty(additionalArgs)) + { + arguments.Add(additionalArgs); + } + + additionalArgs = Debug.GetDiagnosticSwitch("VMIl2CppAdditionalArgs") as string; + if (!string.IsNullOrEmpty(additionalArgs)) + { + arguments.Add(additionalArgs); + } + + return arguments.Aggregate(String.Empty, (current, arg) => current + arg + " "); + } } internal class IL2CPPBuilder @@ -177,6 +199,11 @@ public void Run() var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target); var managedStrippingLevel = PlayerSettings.GetManagedStrippingLevel(buildTargetGroup); + + // IL2CPP does not support a managed stripping level of disabled. If the player settings + // do try this (which should not be possible from the editor), use Low instead. + if (managedStrippingLevel == ManagedStrippingLevel.Disabled) + managedStrippingLevel = ManagedStrippingLevel.Low; AssemblyStripper.StripAssemblies(managedDir, m_PlatformProvider, m_RuntimeClassRegistry, managedStrippingLevel); // The IL2CPP editor integration here is responsible to give il2cpp.exe an empty directory to use. @@ -289,22 +316,10 @@ private void ConvertPlayerDlltoCpp(string inputDirectory, string outputDirectory arguments.Add(string.Format("--map-file-parser=\"{0}\"", GetMapFileParserPath())); - var additionalArgs = PlayerSettings.GetAdditionalIl2CppArgs(); + var additionalArgs = IL2CPPUtils.GetAdditionalArguments(); if (!string.IsNullOrEmpty(additionalArgs)) arguments.Add(additionalArgs); - additionalArgs = System.Environment.GetEnvironmentVariable("IL2CPP_ADDITIONAL_ARGS"); - if (!string.IsNullOrEmpty(additionalArgs)) - { - arguments.Add(additionalArgs); - } - - additionalArgs = Debug.GetDiagnosticSwitch("VMIl2CppAdditionalArgs") as string; - if (!string.IsNullOrEmpty(additionalArgs)) - { - arguments.Add(additionalArgs); - } - arguments.Add("--directory=\"" + Path.GetFullPath(inputDirectory) + "\""); arguments.Add(string.Format("--generatedcppdir=\"{0}\"", Path.GetFullPath(outputDirectory))); diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs index 7baea1079d..4d7b163112 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs @@ -84,6 +84,18 @@ public virtual bool LinkLibIl2CppStatically get { return true; } } + internal bool OverriddenCacheDirectory + { + get + { + var additionalArgs = IL2CPPUtils.GetAdditionalArguments(); + if (string.IsNullOrEmpty(additionalArgs)) + return false; + + return additionalArgs.Contains("--cachedirectory="); + } + } + /// /// Change the relative include paths into absolute paths that can be passed to the C++ compiler. /// By default this method returns its input with each path relative to the current directory. diff --git a/Editor/Mono/Commands/GOCreationCommands.cs b/Editor/Mono/Commands/GOCreationCommands.cs index 17755458d3..5af6908771 100644 --- a/Editor/Mono/Commands/GOCreationCommands.cs +++ b/Editor/Mono/Commands/GOCreationCommands.cs @@ -244,7 +244,14 @@ static void CreateParticleSystem(MenuCommand menuCommand) Place(go, parent); } - [MenuItem("GameObject/Effects/Trail", priority = 2)] + [MenuItem("GameObject/Effects/Particle System Force Field", priority = 2)] + static void CreateParticleSystemForceField(MenuCommand menuCommand) + { + var parent = menuCommand.context as GameObject; + Place(ObjectFactory.CreateGameObject("Particle System Force Field", typeof(ParticleSystemForceField)), parent); + } + + [MenuItem("GameObject/Effects/Trail", priority = 3)] static void CreateTrail(MenuCommand menuCommand) { var parent = menuCommand.context as GameObject; @@ -253,7 +260,7 @@ static void CreateTrail(MenuCommand menuCommand) Place(go, parent); } - [MenuItem("GameObject/Effects/Line", priority = 3)] + [MenuItem("GameObject/Effects/Line", priority = 4)] static void CreateLine(MenuCommand menuCommand) { var parent = menuCommand.context as GameObject; diff --git a/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs b/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs index b95726d653..611baa7c5a 100644 --- a/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs +++ b/Editor/Mono/ImportSettings/TextureImportPlatformSettings.cs @@ -336,11 +336,13 @@ public void Sync() if ((overridden || m_OverriddenIsDifferent) && m_PlatformSettings.format < 0) { + var showSettingsForPreset = m_Inspector.assetTarget == null; + m_PlatformSettings.format = TextureImporter.DefaultFormatFromTextureParameters( GetSettings(importers[0]), m_PlatformSettings, - importers[0].DoesSourceTextureHaveAlpha(), - importers[0].IsSourceTextureHDR(), + showSettingsForPreset || importers[0].DoesSourceTextureHaveAlpha(), + showSettingsForPreset || importers[0].IsSourceTextureHDR(), m_Target ); m_TextureFormatIsDifferent = false; @@ -352,8 +354,8 @@ public void Sync() TextureImporterFormat format = TextureImporter.DefaultFormatFromTextureParameters(settings, m_PlatformSettings, - imp.DoesSourceTextureHaveAlpha(), - imp.IsSourceTextureHDR(), + showSettingsForPreset || imp.DoesSourceTextureHaveAlpha(), + showSettingsForPreset || imp.IsSourceTextureHDR(), m_Target ); if (format != m_PlatformSettings.format) diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index ba33875f25..5eca5d41fb 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -55,7 +55,9 @@ internal class InspectorWindow : EditorWindow, IHasCustomMenu Editor m_LastInteractedEditor; bool m_IsOpenForEdit = false; + int m_LastInitialEditorInstanceID; Component[] m_ComponentsInPrefabSource; + HashSet m_RemovedComponents; [SerializeField] PreviewResizer m_PreviewResizer = new PreviewResizer(); @@ -211,7 +213,6 @@ void OnSelectionChange() if (m_Parent != null) // parent may be null in some situations (case 970700, 851988) m_Parent.ClearKeyboardControl(); ScriptAttributeUtility.ClearGlobalCache(); - ExtractPrefabComponents(); Repaint(); } @@ -332,25 +333,21 @@ protected virtual void CreateTracker() m_Tracker = sharedTrackerInUse ? new ActiveEditorTracker() : ActiveEditorTracker.sharedTracker; m_Tracker.inspectorMode = m_InspectorMode; m_Tracker.RebuildIfNecessary(); - - ExtractPrefabComponents(); } - bool PrefabComponentsOutdated(Editor[] editors) + void OnTrackerRebuilt() { - if (m_ComponentsInPrefabSource != null && m_ComponentsInPrefabSource.Length >= 1 && editors.Length >= 2) - { - Object transformFromSource = PrefabUtility.GetCorrespondingObjectFromSource(editors[1].target); - Object cachedTransformFromSource = m_ComponentsInPrefabSource[0]; - if (transformFromSource != cachedTransformFromSource) - return true; - } - return false; + ExtractPrefabComponents(); } void ExtractPrefabComponents() { + m_LastInitialEditorInstanceID = m_Tracker.activeEditors[0].GetInstanceID(); + m_ComponentsInPrefabSource = null; + if (m_RemovedComponents == null) + m_RemovedComponents = new HashSet(); + m_RemovedComponents.Clear(); if (m_Tracker.activeEditors.Length == 0) return; @@ -364,6 +361,11 @@ void ExtractPrefabComponents() return; m_ComponentsInPrefabSource = sourceGo.GetComponents(); + var removedComponentsList = PrefabUtility.GetRemovedComponents(PrefabUtility.GetOutermostPrefabInstanceRoot(go)); + for (int i = 0; i < removedComponentsList.Count; i++) + { + m_RemovedComponents.Add(removedComponentsList[i].assetComponent); + } } protected virtual void CreatePreviewables() @@ -905,13 +907,14 @@ private void DetachPreview() GUIUtility.ExitGUI(); } - private static void DrawVCSSticky(EditorWindow hostWindow, Editor assetEditor, float offset) + private static void DrawVCSSticky(Rect anchorRect, Editor assetEditor, float offset) { string message = ""; bool hasRemovedSticky = EditorPrefs.GetBool("vcssticky"); if (!hasRemovedSticky && !Editor.IsAppropriateFileOpenForEdit(assetEditor.target, out message)) { - var rect = new Rect(10, hostWindow.position.height - 94, hostWindow.position.width - 20, 80); + const int stickyRectHeight = 80; + var rect = new Rect(10, anchorRect.y - stickyRectHeight, anchorRect.width - 30, stickyRectHeight); rect.y -= offset; if (Event.current.type == EventType.Repaint) { @@ -1007,7 +1010,7 @@ internal static void DrawVCSShortInfo(EditorWindow hostWindow, Editor assetEdito hostWindow.Repaint(); } } - DrawVCSSticky(hostWindow, assetEditor, rect.height / 2); + DrawVCSSticky(rect, assetEditor, rect.height / 2); } } } @@ -1067,9 +1070,9 @@ private void DrawEditors(Editor[] editors) bool showImportedObjectBarNext = false; Rect importedObjectBarRect = new Rect(); + if (editors.Length > 0 && editors[0].GetInstanceID() != m_LastInitialEditorInstanceID) + OnTrackerRebuilt(); int prefabComponentIndex = -1; - if (PrefabComponentsOutdated(editors)) - ExtractPrefabComponents(); for (int editorIndex = 0; editorIndex < editors.Length; editorIndex++) { if (m_ComponentsInPrefabSource != null && editorIndex != 0) @@ -1141,6 +1144,13 @@ private static void DrawImportedObjectLabel(Rect importedObjectBarRect) void DisplayRemovedComponent(GameObject go, Component comp) { + if (comp == null) + return; + if ((comp.hideFlags & HideFlags.HideInInspector) != 0) + return; + if (!m_RemovedComponents.Contains(comp)) + return; + Rect rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar); EditorGUI.RemovedComponentTitlebar(rect, go, comp); } @@ -1654,8 +1664,6 @@ private static void FlushAllOptimizedGUIBlocksIfNeeded() { foreach (var editor in inspector.tracker.activeEditors) InspectorWindowUtils.FlushOptimizedGUIBlock(editor); - - inspector.ExtractPrefabComponents(); } } diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 370285f953..e977302fcc 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -173,8 +173,9 @@ class SettingsContent public static readonly GUIContent scriptingIL2CPP = EditorGUIUtility.TrTextContent("IL2CPP"); public static readonly GUIContent scriptingDefault = EditorGUIUtility.TrTextContent("Default"); public static readonly GUIContent strippingDisabled = EditorGUIUtility.TrTextContent("Disabled"); - public static readonly GUIContent strippingNormal = EditorGUIUtility.TrTextContent("Normal"); - public static readonly GUIContent strippingAggressive = EditorGUIUtility.TrTextContent("Aggressive (Experimental)"); + public static readonly GUIContent strippingLow = EditorGUIUtility.TrTextContent("Low"); + public static readonly GUIContent strippingMedium = EditorGUIUtility.TrTextContent("Medium"); + public static readonly GUIContent strippingHigh = EditorGUIUtility.TrTextContent("High"); public static readonly GUIContent apiCompatibilityLevel = EditorGUIUtility.TrTextContent("Api Compatibility Level*"); public static readonly GUIContent apiCompatibilityLevel_NET_2_0 = EditorGUIUtility.TrTextContent(".NET 2.0"); public static readonly GUIContent apiCompatibilityLevel_NET_2_0_Subset = EditorGUIUtility.TrTextContent(".NET 2.0 Subset"); @@ -2215,10 +2216,10 @@ private ApiCompatibilityLevel[] GetAvailableApiCompatibilityLevels(BuildTargetGr return only_2_0_profiles; } - static ManagedStrippingLevel[] mono_levels = new ManagedStrippingLevel[] { ManagedStrippingLevel.Disabled, ManagedStrippingLevel.Normal, ManagedStrippingLevel.Aggressive }; - static ManagedStrippingLevel[] il2cpp_levels = new ManagedStrippingLevel[] { ManagedStrippingLevel.Normal, ManagedStrippingLevel.Aggressive }; - static ManagedStrippingLevel[] mono_levels_old_runtime = new ManagedStrippingLevel[] { ManagedStrippingLevel.Disabled, ManagedStrippingLevel.Normal }; - static ManagedStrippingLevel[] il2cpp_levels_old_runtime = new ManagedStrippingLevel[] { ManagedStrippingLevel.Normal }; + static ManagedStrippingLevel[] mono_levels = new ManagedStrippingLevel[] { ManagedStrippingLevel.Disabled, ManagedStrippingLevel.Low, ManagedStrippingLevel.Medium, ManagedStrippingLevel.High }; + static ManagedStrippingLevel[] il2cpp_levels = new ManagedStrippingLevel[] { ManagedStrippingLevel.Low, ManagedStrippingLevel.Medium, ManagedStrippingLevel.High }; + static ManagedStrippingLevel[] mono_levels_old_runtime = new ManagedStrippingLevel[] { ManagedStrippingLevel.Disabled, ManagedStrippingLevel.Low }; + static ManagedStrippingLevel[] il2cpp_levels_old_runtime = new ManagedStrippingLevel[] { ManagedStrippingLevel.Low }; // stripping levels vary based on both scripting backend and runtime version private ManagedStrippingLevel[] GetAvailableManagedStrippingLevels(ScriptingImplementation backend) @@ -2387,8 +2388,9 @@ private static GUIContent[] GetNiceManagedStrippingLevelNames(ManagedStrippingLe m_NiceManagedStrippingLevelNames = new Dictionary { { ManagedStrippingLevel.Disabled, SettingsContent.strippingDisabled }, - { ManagedStrippingLevel.Normal, SettingsContent.strippingNormal }, - { ManagedStrippingLevel.Aggressive, SettingsContent.strippingAggressive } + { ManagedStrippingLevel.Low, SettingsContent.strippingLow }, + { ManagedStrippingLevel.Medium, SettingsContent.strippingMedium }, + { ManagedStrippingLevel.High, SettingsContent.strippingHigh }, }; } return GetGUIContentsForValues(m_NiceManagedStrippingLevelNames, managedStrippingLevels); diff --git a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs b/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs index 760f41840b..fda108a9ea 100644 --- a/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs +++ b/Editor/Mono/Inspector/StandardParticlesShaderGUI.cs @@ -79,10 +79,11 @@ private static class Styles public static GUIContent streamPositionText = EditorGUIUtility.TrTextContent("Position (POSITION.xyz)"); public static GUIContent streamNormalText = EditorGUIUtility.TrTextContent("Normal (NORMAL.xyz)"); public static GUIContent streamColorText = EditorGUIUtility.TrTextContent("Color (COLOR.xyzw)"); + public static GUIContent streamColorInstancedText = EditorGUIUtility.TrTextContent("Color (INSTANCED0.xyzw)"); public static GUIContent streamUVText = EditorGUIUtility.TrTextContent("UV (TEXCOORD0.xy)"); public static GUIContent streamUV2Text = EditorGUIUtility.TrTextContent("UV2 (TEXCOORD0.zw)"); public static GUIContent streamAnimBlendText = EditorGUIUtility.TrTextContent("AnimBlend (TEXCOORD1.x)"); - public static GUIContent streamAnimFrameText = EditorGUIUtility.TrTextContent("AnimFrame (INSTANCED0.x)"); + public static GUIContent streamAnimFrameText = EditorGUIUtility.TrTextContent("AnimFrame (INSTANCED1.x)"); public static GUIContent streamTangentText = EditorGUIUtility.TrTextContent("Tangent (TANGENT.xyzw)"); public static GUIContent streamApplyToAllSystemsText = EditorGUIUtility.TrTextContent("Apply to Systems", "Apply the vertex stream layout to all Particle Systems using this material"); @@ -477,14 +478,20 @@ void DoVertexStreamsArea(Material material) bool useLighting = (material.GetFloat("_LightingEnabled") > 0.0f); bool useFlipbookBlending = (material.GetFloat("_FlipbookMode") > 0.0f); bool useTangents = material.GetTexture("_BumpMap") && useLighting; + bool useGPUInstancing = ShaderUtil.HasProceduralInstancing(material.shader); + if (useGPUInstancing && m_RenderersUsingThisMaterial.Count > 0) + { + if (!m_RenderersUsingThisMaterial[0].enableGPUInstancing) + useGPUInstancing = false; + } GUILayout.Label(Styles.streamPositionText, EditorStyles.label); if (useLighting) GUILayout.Label(Styles.streamNormalText, EditorStyles.label); - GUILayout.Label(Styles.streamColorText, EditorStyles.label); + GUILayout.Label(useGPUInstancing ? Styles.streamColorInstancedText : Styles.streamColorText, EditorStyles.label); GUILayout.Label(Styles.streamUVText, EditorStyles.label); if (useTangents) diff --git a/Editor/Mono/LookDevView/CameraControllerStandard.cs b/Editor/Mono/LookDevView/CameraControllerStandard.cs index 70e0eb102c..24cba406e3 100644 --- a/Editor/Mono/LookDevView/CameraControllerStandard.cs +++ b/Editor/Mono/LookDevView/CameraControllerStandard.cs @@ -192,7 +192,7 @@ public override void Update(CameraState cameraState, Camera cam, EditorWindow wi } var id = GUIUtility.GetControlID(FocusType.Passive); - using (var inputSamplingScope = new CameraFlyModeContext.InputSamplingScope(m_CameraFlyModeContext, m_CurrentViewTool, id)) + using (var inputSamplingScope = new CameraFlyModeContext.InputSamplingScope(m_CameraFlyModeContext, m_CurrentViewTool, id, window)) { if (inputSamplingScope.inputVectorChanged) m_FlySpeed = 0; diff --git a/Editor/Mono/MenuItem.cs b/Editor/Mono/MenuItem.cs index 1951b37469..ea768c0311 100644 --- a/Editor/Mono/MenuItem.cs +++ b/Editor/Mono/MenuItem.cs @@ -3,7 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using UnityEngine; +using System.Linq; using UnityEngine.Scripting; namespace UnityEditor @@ -13,6 +13,8 @@ namespace UnityEditor [RequiredByNativeCode] public sealed class MenuItem : Attribute { + private static readonly string[] kMenuItemSeparators = {"/"}; + // Creates a menu item and invokes the static function following it, when the menu item is selected. public MenuItem(string itemName) : this(itemName, false) {} @@ -28,6 +30,7 @@ public MenuItem(string itemName, bool isValidateFunction, int priority) : this(i // Creates a menu item and invokes the static function following it, when the menu item is selected. internal MenuItem(string itemName, bool isValidateFunction, int priority, bool internalMenu) { + itemName = NormalizeMenuItemName(itemName); if (internalMenu) menuItem = "internal:" + itemName; else @@ -36,6 +39,11 @@ internal MenuItem(string itemName, bool isValidateFunction, int priority, bool i this.priority = priority; } + private static string NormalizeMenuItemName(string rawName) + { + return string.Join(kMenuItemSeparators[0], rawName.Split(kMenuItemSeparators, StringSplitOptions.None).Select(token => token.Trim()).ToArray()); + } + public string menuItem; public bool validate; public int priority; diff --git a/Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs b/Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs index 6ff8c147ac..bbaf24223f 100644 --- a/Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs +++ b/Editor/Mono/Modules/DefaultTextureImportSettingsExtension.cs @@ -86,9 +86,11 @@ public virtual void ShowImportSettings(Editor baseEditor, TextureImportPlatformS if (!platformSettings.isDefault && !platformSettings.overridden) { // If not overriden, show what the auto format is going to be - // don't care about alpha in normal maps - var sourceHasAlpha = imp.DoesSourceTextureHaveAlpha() && - textureTypeForThis != TextureImporterType.NormalMap; + // don't care about alpha in normal maps. If editor.assetTarget is null + // then we are dealing with texture preset and we show all options. + var showSettingsForPreset = editor.assetTarget == null; + var sourceHasAlpha = showSettingsForPreset || (imp.DoesSourceTextureHaveAlpha() && + textureTypeForThis != TextureImporterType.NormalMap); format = (int)TextureImporter.DefaultFormatFromTextureParameters(settings, platformSettings.platformTextureSettings, diff --git a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs index 806aa93529..37a7e9501c 100644 --- a/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs +++ b/Editor/Mono/ParticleSystemEditor/ParticleSystemModules/SubModuleUI.cs @@ -48,7 +48,8 @@ class Texts "Color", "Size", "Rotation", - "Lifetime" + "Lifetime", + "Duration" }; } private static Texts s_Texts; diff --git a/Editor/Mono/PlayerSettings.bindings.cs b/Editor/Mono/PlayerSettings.bindings.cs index fb1edb4611..446a1c94fd 100644 --- a/Editor/Mono/PlayerSettings.bindings.cs +++ b/Editor/Mono/PlayerSettings.bindings.cs @@ -181,8 +181,9 @@ public enum ApiCompatibilityLevel public enum ManagedStrippingLevel { Disabled = 0, - Normal = 1, - Aggressive = 2 + Low = 1, + Medium = 2, + High = 3 } // What to do on uncaught .NET exception (on iOS) diff --git a/Editor/Mono/ProjectBrowser.cs b/Editor/Mono/ProjectBrowser.cs index 6229ff1dda..cd2416174f 100644 --- a/Editor/Mono/ProjectBrowser.cs +++ b/Editor/Mono/ProjectBrowser.cs @@ -62,6 +62,7 @@ class Styles public GUIStyle topBarBg = "ProjectBrowserTopBarBg"; public GUIStyle selectedPathLabel = "Label"; public GUIStyle exposablePopup = GetStyle("ExposablePopupMenu"); + public GUIStyle exposablePopupItem = GetStyle("ExposablePopupItem"); public GUIStyle lockButton = "IN LockButton"; public GUIStyle separator = "ArrowNavigationRight"; @@ -537,8 +538,8 @@ void InitSearchMenu() List buttonData = new List(); - GUIStyle onStyle = "ExposablePopupItem"; - GUIStyle offStyle = "ExposablePopupItem"; + GUIStyle onStyle = s_Styles.exposablePopupItem; + GUIStyle offStyle = s_Styles.exposablePopupItem; bool hasFolderSelected = m_SearchFilter.folders.Length > 0; m_SearchAssetStore.text = m_ListArea.GetAssetStoreButtonText(); diff --git a/Editor/Mono/SceneHierarchy.cs b/Editor/Mono/SceneHierarchy.cs index 3534c68484..e2e7050162 100644 --- a/Editor/Mono/SceneHierarchy.cs +++ b/Editor/Mono/SceneHierarchy.cs @@ -951,10 +951,21 @@ void CreateGameObjectContextClick(GenericMenu menu, int contextClickedItemID) if (!string.IsNullOrEmpty(assetPath)) { - menu.AddItem(EditorGUIUtility.TrTextContent("Open Prefab Asset"), false, () => + if (PrefabUtility.IsPartOfModelPrefab(go)) { - PrefabStageUtility.OpenPrefab(assetPath, go, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceHierarchyContextMenu); - }); + menu.AddItem(EditorGUIUtility.TrTextContent("Open Model"), false, () => + { + GameObject asset = PrefabUtility.GetOriginalSourceOrVariantRoot(go); + AssetDatabase.OpenAsset(asset); + }); + } + else + { + menu.AddItem(EditorGUIUtility.TrTextContent("Open Prefab Asset"), false, () => + { + PrefabStageUtility.OpenPrefab(assetPath, go, StageNavigationManager.Analytics.ChangeType.EnterViaInstanceHierarchyContextMenu); + }); + } menu.AddItem(EditorGUIUtility.TrTextContent("Select Prefab Asset"), false, () => { diff --git a/Editor/Mono/SceneHierarchyStageHandling.cs b/Editor/Mono/SceneHierarchyStageHandling.cs index 91c5ef2645..d590a5f6bd 100644 --- a/Editor/Mono/SceneHierarchyStageHandling.cs +++ b/Editor/Mono/SceneHierarchyStageHandling.cs @@ -257,6 +257,8 @@ public void PrefabStageHeaderGUI(Rect rect) } var prefabStage = currentItem.prefabStage; + if (prefabStage == null) + return; // Cache header text if (m_PrefabHeaderContent == null || m_LastPrefabStageModifiedState == prefabStage.HasSceneBeenModified()) diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index 0b3f63498a..88b913d335 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -175,7 +175,13 @@ internal bool LoadStage(string prefabPath) internal void OpenStage(string prefabPath) { if (LoadStage(prefabPath)) - prefabStageOpened?.Invoke(this); + { + if (prefabStageOpened != null) + { + prefabStageOpened(this); + UpdateEnvironmentHideFlags(); + } + } } internal void CloseStage() @@ -214,7 +220,7 @@ void ReloadStage() Debug.Log("RELOADING Prefab at " + m_PrefabAssetPath); StageNavigationManager.instance.PrefabStageReloading(this); - LoadStage(m_PrefabAssetPath); + OpenStage(m_PrefabAssetPath); StageNavigationManager.instance.PrefabStageReloaded(this); if (SceneHierarchy.s_DebugPrefabStage) @@ -229,7 +235,7 @@ internal void Update() if (HasSceneBeenModified()) m_AnalyticsDidUserModify = true; - UpdateEnvironmentHideFlags(); + UpdateEnvironmentHideFlagsIfNeeded(); HandleAutoSave(); HandlePrefabChangedOnDisk(); DetectSceneDirtinessChange(); @@ -255,6 +261,13 @@ void DetectSceneDirtinessChange() m_LastSceneDirtyID = m_PreviewScene.dirtyID; } + void UpdateEnvironmentHideFlagsIfNeeded() + { + if (m_HideFlagUtility == null) + m_HideFlagUtility = new HideFlagUtility(m_PreviewScene, m_PrefabContentsRoot); + m_HideFlagUtility.UpdateEnvironmentHideFlagsIfNeeded(); + } + void UpdateEnvironmentHideFlags() { if (m_HideFlagUtility == null) @@ -640,11 +653,11 @@ Texture2D DeterminePrefabFileIconFromInstanceRootGameObject() return Icons.prefabIcon; } + internal const HideFlags kVisibleEnvironmentObjectHideFlags = HideFlags.DontSave | HideFlags.NotEditable; + internal const HideFlags kNotVisibleEnvironmentObjectHideFlags = HideFlags.DontSave | HideFlags.NotEditable | HideFlags.HideInHierarchy; + class HideFlagUtility { - const HideFlags kVisibleContextObjectHideFlags = HideFlags.DontSave | HideFlags.NotEditable; - const HideFlags kNotVisibleContextObjectHideFlags = HideFlags.DontSave | HideFlags.NotEditable | HideFlags.HideInHierarchy; - int m_LastSceneDirtyID = -1; List m_Roots = new List(); GameObject m_PrefabInstanceRoot; @@ -656,12 +669,16 @@ public HideFlagUtility(Scene scene, GameObject prefabInstanceRoot) m_PrefabInstanceRoot = prefabInstanceRoot; } - public void UpdateEnvironmentHideFlags() + public void UpdateEnvironmentHideFlagsIfNeeded() { if (m_LastSceneDirtyID == m_Scene.dirtyID) return; m_LastSceneDirtyID = m_Scene.dirtyID; + UpdateEnvironmentHideFlags(); + } + public void UpdateEnvironmentHideFlags() + { ValidatePreviewSceneConsistency(); // We use hideflags to hide all environment objects (and make them non-editable since the user cannot save them) @@ -674,20 +691,20 @@ public void UpdateEnvironmentHideFlags() if (go == rootOfPrefabInstance) continue; - SetHideFlagsRecursively(go.transform, kNotVisibleContextObjectHideFlags); + SetHideFlagsRecursively(go.transform, kNotVisibleEnvironmentObjectHideFlags); } if (rootOfPrefabInstance != m_PrefabInstanceRoot) { // Our prefab instance root might be a child of an environment object. Here we set those environment objects hidden (leaving the root prefab instance unchanged) - SetHideFlagsRecursivelyWithIgnore(rootOfPrefabInstance.transform, m_PrefabInstanceRoot.transform, kNotVisibleContextObjectHideFlags); + SetHideFlagsRecursivelyWithIgnore(rootOfPrefabInstance.transform, m_PrefabInstanceRoot.transform, kNotVisibleEnvironmentObjectHideFlags); // And finally we ensure the ancestors of the prefab root are visible Transform current = m_PrefabInstanceRoot.transform.parent; while (current != null) { - if (current.hideFlags != kVisibleContextObjectHideFlags) - current.gameObject.hideFlags = kVisibleContextObjectHideFlags; + if (current.hideFlags != kVisibleEnvironmentObjectHideFlags) + current.gameObject.hideFlags = kVisibleEnvironmentObjectHideFlags; current = current.parent; } } diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs index 165c6b0f7f..39397c380e 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs @@ -222,7 +222,7 @@ static bool HandleUIReparenting(GameObject instanceRoot, Scene scene) bool rootHasRectTransform = instanceRoot.transform is RectTransform; if (rootHasRectTransform) { - GameObject canvasGameObject = GetOrCreateCanvasGameObject(scene); + GameObject canvasGameObject = GetOrCreateCanvasGameObject(instanceRoot, scene); instanceRoot.transform.SetParent(canvasGameObject.transform, false); return true; } @@ -231,9 +231,9 @@ static bool HandleUIReparenting(GameObject instanceRoot, Scene scene) } // TODO: make hooks for extensions to handle setting up - static GameObject GetOrCreateCanvasGameObject(Scene scene) + static GameObject GetOrCreateCanvasGameObject(GameObject instanceRoot, Scene scene) { - Canvas canvas = GetCanvasInScene(scene); + Canvas canvas = GetCanvasInScene(instanceRoot, scene); if (canvas != null) return canvas.gameObject; @@ -248,10 +248,14 @@ static GameObject GetOrCreateCanvasGameObject(Scene scene) return root; } - static Canvas GetCanvasInScene(Scene scene) + static Canvas GetCanvasInScene(GameObject instanceRoot, Scene scene) { foreach (GameObject go in scene.GetRootGameObjects()) { + // Do not search for Canvas's under the prefab root since we want to + // have a Canvas for the prefab root + if (go == instanceRoot) + continue; var canvas = go.GetComponentInChildren(); if (canvas != null) return canvas; diff --git a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs index e13f91687a..b049b7c5a7 100644 --- a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs +++ b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs @@ -208,6 +208,13 @@ bool CleanupCurrentStageBeforeSwitchingStage() var prefabStage = currentItem.prefabStage; if (prefabStage != null) { + if (EditorApplication.isCompiling && prefabStage.HasSceneBeenModified()) + { + SceneView.ShowNotification("Compiling must finish before you can exit Prefab Mode"); + SceneView.RepaintAll(); + return false; + } + bool continueDestroyingScene = AskUserToSaveModifiedPrefabStageBeforeDestroyingStage(prefabStage); if (!continueDestroyingScene) return false; diff --git a/Editor/Mono/SceneView/CameraFlyModeContext.cs b/Editor/Mono/SceneView/CameraFlyModeContext.cs index 0fee343247..f9d912441d 100644 --- a/Editor/Mono/SceneView/CameraFlyModeContext.cs +++ b/Editor/Mono/SceneView/CameraFlyModeContext.cs @@ -28,12 +28,13 @@ public struct InputSamplingScope : IDisposable // controlID will get hotControl if using arrow keys while shortcut context is not active // passing a value of zero disables the arrow keys - public InputSamplingScope(CameraFlyModeContext context, ViewTool currentViewTool, int controlID, bool orthographic = false) + public InputSamplingScope(CameraFlyModeContext context, ViewTool currentViewTool, int controlID, EditorWindow window, bool orthographic = false) { m_ArrowKeysActive = false; m_Disposed = false; m_Context = context; m_Context.active = currentViewTool == ViewTool.FPS; + m_Context.m_Window = window; if (m_Context.active) { @@ -73,7 +74,7 @@ void ForceArrowKeysUp(bool orthographic) foreach (KeyCode key in s_ArrowKeysDown) { var action = s_ArrowKeyBindings[key]; - action(orthographic, new ShortcutArguments { state = ShortcutState.End }); + action(orthographic, new ShortcutArguments { state = ShortcutState.End, context = m_Context }); } s_ArrowKeysDown.Clear(); @@ -93,7 +94,7 @@ bool DoArrowKeys(int id, bool orthographic) case EventType.KeyDown: if (!s_ArrowKeyBindings.TryGetValue(evt.keyCode, out action)) return false; - action(orthographic, new ShortcutArguments { state = ShortcutState.Begin }); + action(orthographic, new ShortcutArguments { state = ShortcutState.Begin, context = m_Context }); GUIUtility.hotControl = id; s_ArrowKeysDown.Add(evt.keyCode); evt.Use(); @@ -101,7 +102,7 @@ bool DoArrowKeys(int id, bool orthographic) case EventType.KeyUp: if (!s_ArrowKeyBindings.TryGetValue(evt.keyCode, out action)) return false; - action(orthographic, new ShortcutArguments { state = ShortcutState.End }); + action(orthographic, new ShortcutArguments { state = ShortcutState.End, context = m_Context }); s_ArrowKeysDown.Remove(evt.keyCode); if (s_ArrowKeysDown.Count == 0) GUIUtility.hotControl = 0; @@ -115,6 +116,7 @@ bool DoArrowKeys(int id, bool orthographic) public bool active { get; set; } + EditorWindow m_Window; Vector3 m_PreviousVector; public static float deltaTime => s_Timer.Update(); @@ -128,6 +130,8 @@ bool DoArrowKeys(int id, bool orthographic) static void WalkForward(ShortcutArguments args) { s_CurrentInputVector.z = args.state == ShortcutState.Begin ? 1f : s_CurrentInputVector.z > 0f ? 0f : s_CurrentInputVector.z; + var context = (CameraFlyModeContext)args.context; + context.m_Window.Repaint(); } [ClutchShortcut("3D Viewport/Fly Mode Backward", typeof(CameraFlyModeContext), "s")] @@ -135,6 +139,8 @@ static void WalkForward(ShortcutArguments args) static void WalkBackward(ShortcutArguments args) { s_CurrentInputVector.z = args.state == ShortcutState.Begin ? -1f : s_CurrentInputVector.z < 0f ? 0f : s_CurrentInputVector.z; + var context = (CameraFlyModeContext)args.context; + context.m_Window.Repaint(); } [ClutchShortcut("3D Viewport/Fly Mode Left", typeof(CameraFlyModeContext), "a")] @@ -142,6 +148,8 @@ static void WalkBackward(ShortcutArguments args) static void WalkLeft(ShortcutArguments args) { s_CurrentInputVector.x = args.state == ShortcutState.Begin ? -1f : s_CurrentInputVector.x < 0f ? 0f : s_CurrentInputVector.x; + var context = (CameraFlyModeContext)args.context; + context.m_Window.Repaint(); } [ClutchShortcut("3D Viewport/Fly Mode Right", typeof(CameraFlyModeContext), "d")] @@ -149,6 +157,8 @@ static void WalkLeft(ShortcutArguments args) static void WalkRight(ShortcutArguments args) { s_CurrentInputVector.x = args.state == ShortcutState.Begin ? 1f : s_CurrentInputVector.x > 0f ? 0f : s_CurrentInputVector.x; + var context = (CameraFlyModeContext)args.context; + context.m_Window.Repaint(); } [ClutchShortcut("3D Viewport/Fly Mode Up", typeof(CameraFlyModeContext), "e")] @@ -156,6 +166,8 @@ static void WalkRight(ShortcutArguments args) static void WalkUp(ShortcutArguments args) { s_CurrentInputVector.y = args.state == ShortcutState.Begin ? 1f : s_CurrentInputVector.y > 0f ? 0f : s_CurrentInputVector.y; + var context = (CameraFlyModeContext)args.context; + context.m_Window.Repaint(); } [ClutchShortcut("3D Viewport/Fly Mode Down", typeof(CameraFlyModeContext), "q")] @@ -163,6 +175,8 @@ static void WalkUp(ShortcutArguments args) static void WalkDown(ShortcutArguments args) { s_CurrentInputVector.y = args.state == ShortcutState.Begin ? -1f : s_CurrentInputVector.y < 0f ? 0f : s_CurrentInputVector.y; + var context = (CameraFlyModeContext)args.context; + context.m_Window.Repaint(); } } } diff --git a/Editor/Mono/SceneView/SceneViewMotion.cs b/Editor/Mono/SceneView/SceneViewMotion.cs index a82ae636f9..d65fdc7609 100644 --- a/Editor/Mono/SceneView/SceneViewMotion.cs +++ b/Editor/Mono/SceneView/SceneViewMotion.cs @@ -44,7 +44,7 @@ public static void DoViewTool(SceneView view) view.FixNegativeSize(); } - using (var inputSamplingScope = new CameraFlyModeContext.InputSamplingScope(s_CameraFlyModeContext, Tools.s_LockedViewTool, id, view.orthographic)) + using (var inputSamplingScope = new CameraFlyModeContext.InputSamplingScope(s_CameraFlyModeContext, Tools.s_LockedViewTool, id, view, view.orthographic)) { if (inputSamplingScope.currentlyMoving) view.viewIsLockedToObject = false; diff --git a/Editor/Mono/ScriptEditorUtility.cs b/Editor/Mono/ScriptEditorUtility.cs index 04754f2159..d1597bb504 100644 --- a/Editor/Mono/ScriptEditorUtility.cs +++ b/Editor/Mono/ScriptEditorUtility.cs @@ -159,6 +159,8 @@ public static Dictionary GetFoundScriptEditorPaths(RuntimePlatfo static void AddIfDirectoryExists(string name, string path, Dictionary list) { + if (list.ContainsKey(path)) + return; if (Directory.Exists(path)) list.Add(path, name); else if (File.Exists(path)) list.Add(path, name); } diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index d140999018..55d02b8100 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -466,7 +466,8 @@ protected void RunAPIUpdaterIfRequired(string responseFile, IList pathMa return; var pathMappingsFilePath = Path.GetTempFileName(); - File.WriteAllLines(pathMappingsFilePath, pathMappings.ToArray()); + if (pathMappings != null) + File.WriteAllLines(pathMappingsFilePath, pathMappings.ToArray()); APIUpdaterHelper.UpdateScripts( responseFile, diff --git a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs index c1c276d9e1..b3161f57ad 100644 --- a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs +++ b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs @@ -70,16 +70,19 @@ public override void OnGUI(string searchContext) { if (m_SettingsEditor != null) { - using (new SettingsWindow.GUIScope()) - m_SettingsEditor.OnInspectorGUI(); - - // Emulate the Inspector by handling DnD at the native level. - var remainingRect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true)); - if ((Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && remainingRect.Contains(Event.current.mousePosition)) + using (new EditorGUI.DisabledScope(!m_SettingsEditor.IsEnabled())) { - DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(new[] { m_SettingsEditor.target }, Event.current.type == EventType.DragPerform); - if (Event.current.type == EventType.DragPerform) - DragAndDrop.AcceptDrag(); + using (new SettingsWindow.GUIScope()) + m_SettingsEditor.OnInspectorGUI(); + + // Emulate the Inspector by handling DnD at the native level. + var remainingRect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true)); + if ((Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && remainingRect.Contains(Event.current.mousePosition)) + { + DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(new[] { m_SettingsEditor.target }, Event.current.type == EventType.DragPerform); + if (Event.current.type == EventType.DragPerform) + DragAndDrop.AcceptDrag(); + } } } @@ -90,15 +93,18 @@ public override void OnTitleBarGUI() { if (m_SettingsEditor != null) { - var tagrObjects = new[] { m_SettingsEditor.serializedObject.targetObject }; - var rect = GUILayoutUtility.GetRect(Styles.settingsBtn.GetFloat(StyleKeyword.width), Styles.settingsBtn.GetFloat(StyleKeyword.height)); - rect.y = Styles.settingsBtn.GetFloat(StyleKeyword.marginTop); - EditorGUIUtility.DrawEditorHeaderItems(rect, tagrObjects); - var settingsRect = GUILayoutUtility.GetRect(Styles.settingsBtn.GetFloat(StyleKeyword.width), Styles.settingsBtn.GetFloat(StyleKeyword.height)); - settingsRect.y = rect.y; - if (GUI.Button(settingsRect, EditorGUI.GUIContents.titleSettingsIcon, Styles.settingsStyle)) + using (new EditorGUI.DisabledScope(!m_SettingsEditor.IsEnabled())) { - EditorUtility.DisplayObjectContextMenu(settingsRect, tagrObjects, 0); + var tagrObjects = new[] { m_SettingsEditor.serializedObject.targetObject }; + var rect = GUILayoutUtility.GetRect(Styles.settingsBtn.GetFloat(StyleKeyword.width), Styles.settingsBtn.GetFloat(StyleKeyword.height)); + rect.y = Styles.settingsBtn.GetFloat(StyleKeyword.marginTop); + EditorGUIUtility.DrawEditorHeaderItems(rect, tagrObjects); + var settingsRect = GUILayoutUtility.GetRect(Styles.settingsBtn.GetFloat(StyleKeyword.width), Styles.settingsBtn.GetFloat(StyleKeyword.height)); + settingsRect.y = rect.y; + if (GUI.Button(settingsRect, EditorGUI.GUIContents.titleSettingsIcon, Styles.settingsStyle)) + { + EditorUtility.DisplayObjectContextMenu(settingsRect, tagrObjects, 0); + } } } } diff --git a/Editor/Mono/Settings/SettingsWindow.cs b/Editor/Mono/Settings/SettingsWindow.cs index 6bc3ce7cfa..5b6d54ad2e 100644 --- a/Editor/Mono/Settings/SettingsWindow.cs +++ b/Editor/Mono/Settings/SettingsWindow.cs @@ -113,17 +113,15 @@ internal void OnEnable() internal void OnDisable() { - if (m_Splitter.childCount >= 1) + if (m_Splitter != null && m_Splitter.childCount >= 1) { var splitLeft = m_Splitter.Children().First(); float flexGrow = splitLeft.style.flex.value.grow; EditorPrefs.SetFloat(GetPrefKeyName(nameof(m_Splitter)), flexGrow); } - if (m_TreeView.currentProvider != null) - { + if (m_TreeView != null && m_TreeView.currentProvider != null) EditorPrefs.SetString(GetPrefKeyName(titleContent.text + "_current_provider"), m_TreeView.currentProvider.settingsPath); - } SettingsService.settingsProviderChanged -= OnSettingsProviderChanged; Undo.undoRedoPerformed -= OnUndoRedoPerformed; diff --git a/Editor/Mono/UIElements/Controls/BasePopupField.cs b/Editor/Mono/UIElements/Controls/BasePopupField.cs index b825eae0eb..e7368b68ba 100644 --- a/Editor/Mono/UIElements/Controls/BasePopupField.cs +++ b/Editor/Mono/UIElements/Controls/BasePopupField.cs @@ -81,10 +81,7 @@ private void ShowMenu() { var menu = new GenericMenu(); AddMenuItems(menu); - var menuPosition = new Vector2(0.0f, layout.height); - menuPosition = this.LocalToWorld(menuPosition); - var menuRect = new Rect(menuPosition, Vector2.zero); - menu.DropDown(menuRect); + menu.DropDown(worldBound); } } } diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.Compiler.dll index b6bf4938051d5f318d5133036beb98d48898730a..4ae78ee19bbb04e2e2dd126f1419d81680531929 100644 GIT binary patch delta 355 zcmZqZux#kCoY291@bSsU?$&O`)^4WOZsyi*mey|8)^4`eZuZu0j@E9@t=(LT(mdRe zMp~TA3=GVX;Rm{ba#`krCnCPtTM}z$k}HfmPB|>3VZy&VZBK8($D`&%-1g1 zT4ZHg!T$N(p2mNyvmUbCm2s23TJ%U)xoUmuU)HOGv?^OO&-J!6xbd@^!B!>`~g zNp%Nwv-)g=JZ5@SF^W1}{U?~lyiqG=yIAM@6@21zXB^J<+V1GUm&UlA&xY?4I{@GV Bet7@@ delta 355 zcmZqZux#kCoY29X>Fe6q-P+CA+RfD3&D`3}(%Q}1+RfJ5&EDG0(b~2cxRJdvwA*w{7LK13RKI|qS zGhV7PFo4X|RD;l-KpG?tqCw)BNHj>ieTFU<5OV`D4-oTipP|dwz*8SQ>&CCCXH5O~ z|J{0PR^<-MzjdF2BsNIYrY3eCzYr#Sd*WJaHE+ZA*CHXe&OhFGPrS9nh(_?LJ{QWLtVoi$6hSQW}gbEP^eV55l{wp0k;lJ2J!{kgjPiW delta 196 zcmV;#06YJHq#1yu8IXtrZB0dii-n5;g^L1(ivxv=1ci$QwTlLQNq@OBLj110Ye$KB zIdvsgRv04R*&C^*oSoJO1JUO#kUvUA>gPs~Y9?rTNbqmwTXflCjaaKGsJl0URy_|3Uw$%0`N@=KS&bOIc=uu2A70k;lJ2J!_fwp+CT diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/Boo.Lang.dll index 0b8451bdb269e0837e5aed8842ce2cf3a75b7f3c..b75f63c84ebcba513d79a8dac97f8b6507443db3 100644 GIT binary patch delta 177 zcmV;i08ama;0J)<2at#ZyyMA%i?xdZ1?7LzK|C2&PQgZsl5PGY|_6H>RXA7e6W2o(FtDS>EKbdqM~E$_FPKySH{THZPI!5(pMiW_!%pW9`faVmq@*bAd>Z$aJlxj15X4 zRx>+DbTKb(Mgg!AUSqBXr^UP=CEHDwGhSolGUoEOS4am5 zw2Q1{+%B?`>4SWIZH9wx#4UBV?YW^-LY_=*sdoRwq+ckW-E%uRar^sizY_wkIBk=Q z?Q1FEKfnIw%7ar)q}?)SK49MPraSObIAfx1$n#YOcPsmDHdn6*_}mk$EZ)w$xAH4v z(%Vz@|9wP{*t}kJ)We{dFZ=BE=+oDdC!OY$=$d{mx9QLA%AfAX%mqD9`oAy^Dz8{Q Y)kHaJP1Dnb(*w^kRc+@x#q^040Nm4h_W%F@ delta 295 zcmZozz}>KbdqM}ZkC$s>_ttL4<|Q(ZIeV;?*}MdTMV#3{Y-cE2nk!gjy4F(01|<-y znH?mzm>r~UF_?WAN`geTpIOQn!6*P$!V6NqnAe!A!D+k6a>i?nTp(eEbYm`W`*x9) zjN3(4GJTM*m-!XVJUjG|Yq!vg!{)JnXNB+gd6#Ms^r<>SFu~#Be#L_u|0wNLn(iT% zuF-h!F?aQ39{+G-`OHri_nY3AC)Hjvy4zT-!4}x-WvCv?m{7m0YJT=M#ZQlpT-S9> zHJddz(Ce(Y9@mz>-|H%JL}Qtk+r>9qx73@|8QpDp_4_ghv!Fm>p?K}3xXSHD8F;sY$w}M{=<}f?Vo-+;(iR2E9hZ&#PKFSw>S0X~}PR3rSbh#dK zrx@dDjq6bD1**STCljv_F|b6=wL n#&1coQ^Bec5mnNmNkzCU#-~?1hWwoqAeRw-1h%&hdIa(Xf~8il delta 185 zcmV;q07n0SfD(X!5|D@kQc6XEi-n5;g^L1(ivzWb1U-0vR2UM-aQK79N(j=<^t}GF5WuWLu8#*Y8YSCie50PfRw=Bu3G0T*DV`ZkE1LQnLB| z%{dvDQ}_KRyF3_#przj_jaPsn(DRli-n5;g^L1(ivzWb1l@yw`Sh25ip{e`mnak_^U~sH zQDR=Cq8m2#ahR33b}8dWDHQU_w>IEMvwx~UH@6Xr1Qr3e4u%Bs1>Uh+pa1{> delta 186 zcmV;r07d_Rm=b`P5|D@kPfA6Bi-n5;g^L1(ivzWb1l@yw#e~!BKs{bUy_#r`qk!@L zX~r}C!~QrL3_6+C?A}huBJ*`29RXN)e`Tr3PHU8UNR?H7qeh3C^-lL5rlRNPQLJCqab#?xWxHhz z_`DBIB(4!9iG0&*wruXgF?ZyjbXOLwjeLyBHup-iv#23g``b%ba1i@dm$%23)5fG# z5suTRPgl6Zu&&=NyOdyl9yewH$k9hx#@6(<7tjYJ=dDYm-eMl|5%_Sfzi_1kLXy@) XMlmFIHKnHkoB;xnFbcO0m;v$!<|<@l delta 221 zcmV<303!c@zy^T829SsYB1=Vqi?xdZO&JGk49OCJ0fU#{837jugAB9RXN)f4Gf+I)W-#N4QSM&3YlPG95V(#(e!#3&iCpFoy>`9LqnN zm}CV@%7hIWDbc~F2XxH;xY`#ENc+B93vEPbF>CYu5o+%Tf3QByO~?NSz5bUTf5m>yV+a2Ia<3pTf4bhySZDt zdA4@*mL3)o*rs`cf#K8Thg%`^txfGhM|gpl4~Y4JSOACxw+kH+nl!Cm;Eg8xDrRZ# z_SN&IPV)aEzWeO^G^PUfj(wrAc{loAUUOY(l04sAbnCr|9L#J%h7Wf&tJmy)7q-1# z#oLU@*s1slqxYJBTCaq!U45TZm@<)pxn!xU)|U-ai_h?^3;ODA#d4MD$G^)aE7tr7 zpEIfJ>YkbN53NpAnHQ1R@A`AEWT~LaHxcgoXLB#-u)B6j)n1X?F E06#2rGynhq delta 257 zcmZoT;@fbk&fxV2sA2rm%x0Wm)i3jnd;cA+Celcv@Gws5NZ{d}I& z$}b12t@pfmzVrJXi;1db?a{l6lH=fn9u1So_rg|L= z>u)peVJKbDdzfvL-P_hZi=8H3k@#ho6})u8w-+|wy5{|NNxFEio{Q;Z`a78}&lAs= z@XkNEJap#&w+cmBii{l1DbG`0ofDjL^iHwy5pU7l=gu>^8+OL0OczWLzO|h%M)(se E00uX9`2YX_ diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/System.dll index 95bdadbac46d0239f36fb0238a90a5cf72175f4e..5473fc57bf7dabd4e38ae8d0fe108cab6956a9e7 100644 GIT binary patch delta 941 zcmZ9KNla5w6o$`jf!bmVw@k&x8mL69xB%UNi7}N#sRU!g41z+e7L}nP)`&yJT&Bwy zqOanZm;mCmK>7@_Ai%%XQbG}-3PP2H1`!%eXb7PyLRS!~CR9UcD4{C})e@>BG>p*jA&NI-nbH7YAQ8a; z`<~kh5WZGodj@CmMHaRyqm<0CWJX|C0Z_&x2?(|eYwS2iwA!&(5hec|R|Ckwe!-uO z&4NA$zZGV4aAdSOblJ&SN)ipZxLu)_E0}e1koX`Ummz&O>-UlgERU2NOjJ@KK7mYf z#<)?=K)|^^8(=J1oG8LqRXSUVG?FqMK<^f-%kiSZBA4{%0}QhA4;^fr0*Q+bNi4;P zUI%t5g+(Vei18ITUlDPM#rLga9f>Rl32jI4DLl{vke!ae*&r=)n`k_WOBEs3TE08M zQ-w{IG%JE68v=C~fNi&=Y(3*)CV4U$0cTz(&n7;q!o3Q03cCvLmLZh7*s|MQcpuWs z(a!Tyrxd%d7U!x$G^GFydxhdUY%)Emk}j5UdASp3*IzZFw+@d5srl{a4j`Bpc6qQ- zIPJj(y>xdb@s2D@?Dw!cSh<700q0!+3)9Zu0B5-fXRe(;pk~I3fAevca>dMgT&c0x znapP_`TA!B6-+^ADuU7fSc(znTCq1)9R@+_lKlX>M$(I!>6t|^i)0qXESg!2NO}$L z0%sO}-%tID`)$J$xAcQg8{OBQH)&eGw1l3V{yF>crgCAt#b2{So!z;)`pS<@#qOlZ zF}L=%x2@LLmpgRO87GXi$GJ3F5!#E?;(i@yENm_dMSJp07XmffZr{eK#LDs;Aq7LF zhch#kbqPHkuAPHZ@8hQ@I=(IWzW+LY4EtQx)rp_VP4`|U&TL7Y|L~?OZk4F(i46q* E0dTAr@c;k- delta 970 zcmZ9Ke@IhN6vxlo)b-|^-l;h=7P(4YW=)DpOk*0PhSKm?T3T5nEuDxVCFV=JYFrcT z*Be$Q5gPUbLhF?YE$1I85@ZEIpp_A5gkb$+L3XdthtwYjKKGt;zURlig4-du9j#63 zqp7>j5==NuRG6qS@xsI#6CX@8m@LDD$3%;XFD5!n{4mjD;*UwdBZAhao9rn70c$wu z0f731C61%#o=E9!InM`EXPVxY9 zju?=I#w|*|+IK16Oj)^SEK5knY}BGMD0*hS5+pszMTfZs2Wz(|2;dU!`dmMxPdN} zW@k!arKnKl6KCTfI#m>$$Yilq%6sM86jctQD6{ySRGItfkgu)MODF15nV7?!!9mJp zfLQukwAunM1~pf(eX+{1c3Sxgfb4i&iLy05BTiOL++U4MCT$@=!vQLE9iU>d3&xAH zxvJ5i7tgA(*`~xa0fmWY1Y|VGf*kPo0px!q-4SS2F}w~1#S}jPu+a6ekHeTnu#a>8 zKUT>r+*60jw3ZS&Nb7bEI%hbr)4oP&vim=lW27(5$Q8=#!HX|A1mNF@yAU-4wLoe? z)PkukrxqgNF5|>(ZC@4kKBBEpYD@^S-qOsM>YH9|9`}uF$V{G&*)c@2ez%mhB#p+{ zP9@&-oV4}Xe+fTw273LBIb(TSKgQoaelC35D+uGwA0FzV>;IrhMY_-gQ$U QI_pr|>J^f{J#^OlFWk8rTL1t6 diff --git a/External/Mono/builds/monodistribution/lib/mono/2.0/UnityScript.dll b/External/Mono/builds/monodistribution/lib/mono/2.0/UnityScript.dll index 352000b8e295a5ffc5bdcbb406ada2c2498351dd..89459747d31b00c2c01bc8f38f96e937af8b291d 100644 GIT binary patch delta 276 zcmZp8!`1MHYeEO}mB%L=ySH{TYFe`hvM_OO-(k&oi&03QiGihB6G$*s>w!sw?MrMK zAK5W+GEMKOVVuL5KV7w!F^sWbdrd9l1bMzQa?A`aQF-#r41Q6SRF6>wpQ#_i_0OgC)VWMzaJws340UCnfjO~8SL zO{md^Q-O(5sL=t)+WvbZ(@aJI#Ts9J^F1$Im)yz?Zrby5;^aoA*zJs4nEo>Y09}<( A*Z=?k delta 276 zcmZp8!`1MHYeENegRg62_ttJkO=}iTK^CU%JFFRRF$x(lF|br?0tu#SeK4uFeTgmO zBReK0&gmUBjB^+ZrmNO6hB4-Euc>96AkQbv$jsmpbw-Yv!7nOLe!J9M#sWs(%={2F zW`?qSe<0bgefm5`Lkpl70|O&ajDdj(D0cN4qhzC~iHecA8H0+7k+CU|WzL{dl95@w zojHPuS5zIuR53QT07~cNCnx5BIF=9 diff --git a/Modules/TerrainEditor/Brush/BrushEditor.cs b/Modules/TerrainEditor/Brush/BrushEditor.cs index 66c772ad32..c392491b47 100644 --- a/Modules/TerrainEditor/Brush/BrushEditor.cs +++ b/Modules/TerrainEditor/Brush/BrushEditor.cs @@ -115,7 +115,7 @@ public sealed override Texture2D RenderStaticPreview(string assetPath, UnityEngi Brush brush = AssetDatabase.LoadMainAssetAtPath(assetPath) as Brush; if (brush == null) - return Brush.DefaultMask(); + return null; if (brush.m_Mask == null) brush.m_Mask = Brush.DefaultMask(); diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs index 18c19f5850..9ef23fa521 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs @@ -237,7 +237,8 @@ public override GameObject[] validTargets get { StageHandle currentStageHandle = StageUtility.GetCurrentStageHandle(); - return currentStageHandle.FindComponentsOfType().Where(x => x.gameObject.scene.isLoaded).Select(x => x.gameObject).ToArray(); + return currentStageHandle.FindComponentsOfType().Where(x => x.gameObject.scene.isLoaded + && x.gameObject.activeInHierarchy).Select(x => x.gameObject).ToArray(); } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs index 17081082fc..5bfa0dd37c 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs @@ -1177,6 +1177,9 @@ private void DisplayFocusMode(Object displayTarget, SceneView sceneView) private void EnableFocus() { + if (GridPaintingState.scenePaintTarget == null) + return; + switch (TilemapEditorUserSettings.focusMode) { case TilemapEditorUserSettings.FocusMode.Tilemap: diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs index 9010374679..e92278b33f 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintingState.cs @@ -59,6 +59,20 @@ private void HierarchyChanged() } } + private GameObject[] GetValidTargets() + { + if (m_FlushPaintTargetCache) + { + m_CachedPaintTargets = null; + if (activeBrushEditor != null) + m_CachedPaintTargets = activeBrushEditor.validTargets; + if (m_CachedPaintTargets == null || m_CachedPaintTargets.Length == 0) + scenePaintTarget = null; + m_FlushPaintTargetCache = false; + } + return m_CachedPaintTargets; + } + public static void AutoSelectPaintTarget() { if (activeBrushEditor != null) @@ -188,17 +202,7 @@ public static bool savingPalette public static GameObject[] validTargets { - get - { - if (instance.m_FlushPaintTargetCache) - { - instance.m_CachedPaintTargets = null; - if (activeBrushEditor != null) - instance.m_CachedPaintTargets = activeBrushEditor.validTargets; - instance.m_FlushPaintTargetCache = false; - } - return instance.m_CachedPaintTargets; - } + get { return instance.GetValidTargets(); } } public static void RegisterPainterInterest(Object painter) diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs index 6509d90f1d..118bd6e817 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteAddPopup.cs @@ -64,7 +64,30 @@ internal void OnGUI() GUILayout.BeginHorizontal(); GUILayout.Label(Styles.gridLabel, GUILayout.Width(90f)); - m_Layout = (Grid.CellLayout)EditorGUILayout.EnumPopup(m_Layout); + EditorGUI.BeginChangeCheck(); + var newLayout = (Grid.CellLayout)EditorGUILayout.EnumPopup(m_Layout); + if (EditorGUI.EndChangeCheck()) + { + // Set useful user settings for certain layouts + switch (newLayout) + { + case Grid.CellLayout.Rectangle: + case Grid.CellLayout.Hexagon: + { + m_CellSizing = GridPalette.CellSizing.Automatic; + m_CellSize = new Vector3(1, 1, 0); + break; + } + case Grid.CellLayout.Isometric: + case Grid.CellLayout.IsometricZAsY: + { + m_CellSizing = GridPalette.CellSizing.Manual; + m_CellSize = new Vector3(1, 0.5f, 1); + break; + } + } + m_Layout = newLayout; + } GUILayout.EndHorizontal(); if (m_Layout == GridLayout.CellLayout.Hexagon) diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteUtility.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteUtility.cs index 4ce117ade4..92137b9cb4 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteUtility.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaletteUtility.cs @@ -93,8 +93,6 @@ public static GameObject CreateNewLayer(GameObject paletteGO, string name, Grid. case Grid.CellLayout.Isometric: case Grid.CellLayout.IsometricZAsY: { - // Difficult to frame isometric sprites, set generic cell size which suits most cases - paletteGO.GetComponent().cellSize = new Vector3(1f, 0.5f, 1f); renderer.sortOrder = TilemapRenderer.SortOrder.TopRight; break; } diff --git a/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs b/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs index 292b2177bc..a420a5c23a 100644 --- a/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs +++ b/Modules/TilemapEditor/Editor/Managed/TilemapEditor.cs @@ -125,7 +125,7 @@ private static void CreateIsometricTilemap(GridLayout.CellLayout isometricLayout if (isometricLayout != grid.cellLayout) { grid.cellLayout = isometricLayout; - grid.cellSize = new Vector3(1.0f, 0.5f, 0.0f); + grid.cellSize = new Vector3(1.0f, 0.5f, 1.0f); } var tilemapRenderer = tilemapGO.GetComponent(); diff --git a/Modules/Video/Public/ScriptBindings/VideoMediaPlayback.bindings.cs b/Modules/Video/Public/ScriptBindings/VideoMediaPlayback.bindings.cs index 4383ed7d76..8a60473bfd 100644 --- a/Modules/Video/Public/ScriptBindings/VideoMediaPlayback.bindings.cs +++ b/Modules/Video/Public/ScriptBindings/VideoMediaPlayback.bindings.cs @@ -39,6 +39,7 @@ public void Dispose() public delegate void MessageCallback(string message); extern public VideoPlayback CreateVideoPlayback(string fileName, MessageCallback errorCallback, Callback readyCallback, Callback reachedEndCallback); extern public void ReleaseVideoPlayback(VideoPlayback playback); + extern public ulong videoPlaybackCount { get; } extern public void Update(); extern static internal void ProcessOSMainLoopMessagesForTesting(); diff --git a/README.md b/README.md index 777698aff2..32870e8a99 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b7 C# reference source code +## Unity 2018.3.0b8 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs b/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs index 432ca9b435..0f4ed7455d 100644 --- a/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs +++ b/Runtime/ParticleSystem/Managed/ParticleSystemEnums.cs @@ -309,11 +309,12 @@ public enum ParticleSystemSubEmitterType public enum ParticleSystemSubEmitterProperties { InheritNothing = 0, - InheritEverything = InheritColor | InheritSize | InheritRotation | InheritLifetime, + InheritEverything = InheritColor | InheritSize | InheritRotation | InheritLifetime | InheritDuration, InheritColor = 1 << 0, InheritSize = 1 << 1, InheritRotation = 1 << 2, InheritLifetime = 1 << 3, + InheritDuration = 1 << 4, } // The mode used for generating Particle Trails (Shuriken). From 2d9e6431c06e628577d972e063ba0998cfa338cb Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 7 Nov 2018 11:26:23 +0000 Subject: [PATCH 07/10] Unity 2018.3.0b9 C# reference source code --- Editor/Mono/AssemblyInfo/AssemblyInfo.cs | 1 + Editor/Mono/BuildPipeline/AssemblyStripper.cs | 2 +- .../Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs | 2 +- .../Il2Cpp/Il2CppNativeCodeBuilder.cs | 2 +- .../Il2Cpp/Il2CppNativeCodeBuilderUtils.cs | 7 +- .../PlayerSettingsEditor.cs | 1 + Editor/Mono/Inspector/SpriteRendererEditor.cs | 6 +- Editor/Mono/PlayerSettings.bindings.cs | 1 + Editor/Mono/Prefabs/PrefabUtility.bindings.cs | 14 +- Editor/Mono/Prefabs/PrefabUtility.cs | 26 +- .../StageManager/PrefabStage/PrefabStage.cs | 27 +- .../StageManager/StageNavigationManager.cs | 15 +- .../APIUpdater/APIUpdaterAssemblyHelper.cs | 30 +- .../Scripting/APIUpdater/APIUpdaterLogger.cs | 5 + .../Scripting/Compilers/CSharpLanguage.cs | 7 + .../Compilers/CompilerSpecificReponseFiles.cs | 28 + .../Compilers/MicrosoftCSharpCompiler.cs | 47 +- .../MicrosoftCSharpResponseFileProvider.cs | 13 + .../Scripting/Compilers/MonoCSharpCompiler.cs | 22 +- .../MonoCSharpResponseFileProvider.cs | 13 + .../Compilers/ResponseFileProvider.cs | 97 ++++ .../Scripting/Compilers/ScriptCompilerBase.cs | 16 +- .../Scripting/Compilers/SupportedLanguage.cs | 5 + .../CSharpNamespaceParser.cs | 26 +- .../ScriptCompilation/EditorBuildRules.cs | 1 + .../ScriptCompilation/EditorCompilation.cs | 2 +- .../ScriptCompilation/ScriptAssembly.cs | 15 +- .../Scripting/ScriptCompilation/WSAHelpers.cs | 3 + Editor/Mono/Scripting/ScriptCompilers.cs | 9 + .../SolutionSynchronizer.cs | 55 +- Modules/GraphViewEditor/Elements/StackNode.cs | 2 +- Modules/GraphViewEditor/Views/GraphView.cs | 103 +++- .../ShortcutManagerEditor/ContextManager.cs | 8 +- Modules/ShortcutManagerEditor/Directory.cs | 120 +++-- .../ShortcutManagerEditor/KeyCombination.cs | 21 +- .../ShortcutAttribute.cs | 30 +- .../ShortcutManagerEditor/ShortcutEntry.cs | 51 +- Modules/ShortcutManagerEditor/Trigger.cs | 31 +- Modules/TerrainEditor/Brush/Brush.cs | 3 + Modules/TerrainEditor/Brush/BrushList.cs | 8 +- Modules/TerrainEditor/TerrainInspector.cs | 490 +++++++++++------- .../Utilities/TerrainLayerUtility.cs | 25 +- Modules/Tilemap/Managed/Tilemap.cs | 68 +++ .../ScriptBindings/Tilemap.bindings.cs | 16 +- .../Managed/Grid/GridBrushEditorBase.cs | 23 + .../Editor/Managed/Grid/PaintableGrid.cs | 29 +- .../Managed/Grid/PaintableSceneViewGrid.cs | 12 + Modules/UIElements/Events/EventBase.cs | 2 +- .../VideoEditor/Editor/VideoPlayerEditor.cs | 20 +- Projects/CSharp/UnityEditor.csproj | 12 + Projects/CSharp/UnityEngine.csproj | 3 + README.md | 2 +- .../ScriptBindings/PhotoCapture.bindings.cs | 2 +- 53 files changed, 1126 insertions(+), 453 deletions(-) create mode 100644 Editor/Mono/Scripting/Compilers/CompilerSpecificReponseFiles.cs create mode 100644 Editor/Mono/Scripting/Compilers/MicrosoftCSharpResponseFileProvider.cs create mode 100644 Editor/Mono/Scripting/Compilers/MonoCSharpResponseFileProvider.cs create mode 100644 Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs create mode 100644 Modules/Tilemap/Managed/Tilemap.cs diff --git a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs index 7bc81d7272..851edf476f 100644 --- a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs +++ b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs @@ -93,5 +93,6 @@ [assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.004")] [assembly: InternalsVisibleTo("Unity.InternalAPIEditorBridgeDev.005")] [assembly: InternalsVisibleTo("Unity.XR.Remoting.Editor")] +[assembly: InternalsVisibleTo("Unity.GraphViewTestUtilities.Editor")] [assembly: AssemblyIsEditorAssembly] diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index c8a41c3c57..26b5b3a9fe 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -122,7 +122,7 @@ private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, additionalArgs = Debug.GetDiagnosticSwitch("VMUnityLinkerAdditionalArgs") as string; if (!string.IsNullOrEmpty(additionalArgs)) - args.Add(additionalArgs); + args.Add(additionalArgs.Trim('\'')); return RunAssemblyLinker(args, out output, out error, linkerPath, workingDirectory); } diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs index cf0a9471c7..7b8be5796e 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs @@ -158,7 +158,7 @@ internal static string GetAdditionalArguments() additionalArgs = Debug.GetDiagnosticSwitch("VMIl2CppAdditionalArgs") as string; if (!string.IsNullOrEmpty(additionalArgs)) { - arguments.Add(additionalArgs); + arguments.Add(additionalArgs.Trim('\'')); } return arguments.Aggregate(String.Empty, (current, arg) => current + arg + " "); diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs index 4d7b163112..a55e1433f5 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilder.cs @@ -84,7 +84,7 @@ public virtual bool LinkLibIl2CppStatically get { return true; } } - internal bool OverriddenCacheDirectory + internal virtual bool OverriddenCacheDirectory { get { diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs index b83ddfdb30..409beca263 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/Il2CppNativeCodeBuilderUtils.cs @@ -21,11 +21,14 @@ public static IEnumerable AddBuilderArguments(Il2CppNativeCodeBuilder bu arguments.Add("--libil2cpp-static"); arguments.Add(FormatArgument("platform", builder.CompilerPlatform)); arguments.Add(FormatArgument("architecture", builder.CompilerArchitecture)); - arguments.Add(FormatArgument("configuration", compilerConfiguration.ToString())); + + // In IL2CPP, Master config is called "ReleasePlus" + string configurationName = compilerConfiguration != Il2CppCompilerConfiguration.Master ? compilerConfiguration.ToString() : "ReleasePlus"; + arguments.Add(FormatArgument("configuration", configurationName)); arguments.Add(FormatArgument("outputpath", builder.ConvertOutputFileToFullPath(outputRelativePath))); - if (!string.IsNullOrEmpty(builder.CacheDirectory)) + if (!string.IsNullOrEmpty(builder.CacheDirectory) && !builder.OverriddenCacheDirectory) arguments.Add(FormatArgument("cachedirectory", CacheDirectoryPathFor(builder.CacheDirectory))); if (!string.IsNullOrEmpty(builder.CompilerFlags)) diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index e977302fcc..ab10d85a8e 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -2259,6 +2259,7 @@ private Il2CppCompilerConfiguration[] GetIl2CppCompilerConfigurations() { Il2CppCompilerConfiguration.Debug, Il2CppCompilerConfiguration.Release, + Il2CppCompilerConfiguration.Master, }; } diff --git a/Editor/Mono/Inspector/SpriteRendererEditor.cs b/Editor/Mono/Inspector/SpriteRendererEditor.cs index a070bb28c5..a6ce11c6af 100644 --- a/Editor/Mono/Inspector/SpriteRendererEditor.cs +++ b/Editor/Mono/Inspector/SpriteRendererEditor.cs @@ -142,11 +142,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(m_MaskInteraction, Contents.maskInteractionLabel); - if (EditorGUILayout.BeginFadeGroup(1.0f - m_ShowDrawMode.faded)) - { - EditorGUILayout.PropertyField(m_SpriteSortPoint, Contents.spriteSortPointLabel); - } - EditorGUILayout.EndFadeGroup(); + EditorGUILayout.PropertyField(m_SpriteSortPoint, Contents.spriteSortPointLabel); RenderRenderingLayer(); diff --git a/Editor/Mono/PlayerSettings.bindings.cs b/Editor/Mono/PlayerSettings.bindings.cs index 446a1c94fd..cd9eb89d33 100644 --- a/Editor/Mono/PlayerSettings.bindings.cs +++ b/Editor/Mono/PlayerSettings.bindings.cs @@ -35,6 +35,7 @@ public enum Il2CppCompilerConfiguration { Debug = 0, Release = 1, + Master = 2, } // Must be in sync with kAspectRatioSerializeNames and kAspectRatioValues diff --git a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs index 728dd0a803..af06d67d6a 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs @@ -175,7 +175,7 @@ private enum PrefabCreationFlags // 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) + private static GameObject SavePrefab(GameObject inputObject, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags creationFlags, out bool success) { if (inputObject == null) throw new ArgumentNullException("inputObject is null"); @@ -195,15 +195,21 @@ private static GameObject SavePrefab(GameObject inputObject, string path, Replac if (!VerifyNestingFromScript(new GameObject[] {inputObject}, prefabGUID, PrefabUtility.GetPrefabInstanceHandle(inputObject))) throw new ArgumentException("Cyclic nesting detected"); - return SavePrefab_Internal(inputObject, path, replaceOptions, creationFlags); + return SavePrefab_Internal(inputObject, path, replaceOptions, creationFlags, out success); + } + + private static GameObject SavePrefab(GameObject inputObject, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags creationFlags) + { + bool success; + return SavePrefab(inputObject, path, replaceOptions, creationFlags, out success); } #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)] + [StaticAccessor("PrefabUtilityBindings", StaticAccessorType.DoubleColon)] #pragma warning disable 0618 // Type or member is obsolete - extern private static GameObject SavePrefab_Internal([NotNull] GameObject root, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags createOptions); + extern private static GameObject SavePrefab_Internal([NotNull] GameObject root, string path, ReplacePrefabOptions replaceOptions, PrefabCreationFlags createOptions, out bool success); #pragma warning restore 0618 // Type or member is obsolete internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, Object targetPrefab) diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 4c262b311d..6765638a07 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -985,7 +985,8 @@ public static Object CreateEmptyPrefab(string path) } var empty = new GameObject("EmptyPrefab"); - var assetObject = SaveAsPrefabAsset(empty, path); + bool success; + var assetObject = SaveAsPrefabAsset(empty, path, out success); Object.DestroyImmediate(empty); return PrefabUtility.GetPrefabObject(assetObject); } @@ -1040,7 +1041,7 @@ private static bool IsPrefabInstanceRoot(GameObject gameObject) return instanceRoot != null && instanceRoot == gameObject; } - public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath) + public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath, out bool success) { SaveAsPrefabAssetArgumentCheck(instanceRoot); @@ -1049,11 +1050,23 @@ public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string asset creationFlags = PrefabCreationFlags.CreateVariant; #pragma warning disable CS0618 // Type or member is obsolete - return SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.Default, creationFlags); + return SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.Default, creationFlags, out success); #pragma warning restore CS0618 // Type or member is obsolete } + public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath) + { + bool success; + return SaveAsPrefabAsset(instanceRoot, assetPath, out success); + } + public static GameObject SaveAsPrefabAssetAndConnect(GameObject instanceRoot, string assetPath, InteractionMode action) + { + bool success; + return SaveAsPrefabAssetAndConnect(instanceRoot, assetPath, action, out success); + } + + public static GameObject SaveAsPrefabAssetAndConnect(GameObject instanceRoot, string assetPath, InteractionMode action, out bool success) { SaveAsPrefabAssetArgumentCheck(instanceRoot); @@ -1069,9 +1082,14 @@ public static GameObject SaveAsPrefabAssetAndConnect(GameObject instanceRoot, st creationFlags = PrefabCreationFlags.CreateVariant; #pragma warning disable CS0618 // Type or member is obsolete - var assetRoot = SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags); + var assetRoot = SavePrefab(instanceRoot, assetPath, ReplacePrefabOptions.ConnectToPrefab, creationFlags, out success); #pragma warning restore CS0618 // Type or member is obsolete + if (!success) + { + return null; + } + if (action == InteractionMode.UserAction) { Undo.RegisterCreatedObjectUndo(GetPrefabInstanceHandle(instanceRoot), actionName); diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index 88b913d335..abbe1ee12b 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -319,11 +319,11 @@ public void ClearDirtiness() m_InitialSceneDirtyID = m_PreviewScene.dirtyID; } - // Is internal so we can use it in Tests - internal void SavePrefab() + // Returns true if saved succesfully (internal so we can use it in Tests) + internal bool SavePrefab() { if (!initialized) - return; + return false; m_AnalyticsDidUserSave = true; m_AnalyticsDidUserModify = true; @@ -335,21 +335,35 @@ internal void SavePrefab() prefabSaving(m_PrefabContentsRoot); var startTime = EditorApplication.timeSinceStartup; - var prefabAssetRoot = PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath); + + bool savedSuccesfully; + PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath, out savedSuccesfully); m_LastSavingDuration = (float)(EditorApplication.timeSinceStartup - startTime); - if (prefabAssetRoot != null) + if (savedSuccesfully) { ClearDirtiness(); if (prefabSaved != null) prefabSaved(m_PrefabContentsRoot); } + else + { + string title = L10n.Tr("Saving Failed"); + string message = L10n.Tr("Saving failed. Check the Console window to get more insight into what needs to be fixed."); + if (autoSave) + message += L10n.Tr("\n\nAuto Save has been temporarily disabled."); + EditorUtility.DisplayDialog(title, message, L10n.Tr("OK")); + + m_TemporarilyDisableAutoSave = true; + } if (SceneHierarchy.s_DebugPrefabStage) Debug.Log("SAVE PREFAB ended"); showingSavingLabel = false; + + return savedSuccesfully; } internal bool SaveAsNewPrefab(string newPath, bool asCopy) @@ -464,8 +478,7 @@ internal bool SavePrefabWithVersionControlDialogAndRenameDialog() if (!CheckRenamedPrefabRootWhenSaving(showCancelButton)) return false; - SavePrefab(); - return true; + return SavePrefab(); } // Returns true if we should continue saving diff --git a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs index b049b7c5a7..4b395dbd42 100644 --- a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs +++ b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs @@ -406,12 +406,17 @@ internal PrefabStage OpenPrefabMode(string prefabAssetPath, GameObject instanceR { HandleSelectionWhenSwithingToNewPrefabMode(GetCurrentPrefabStage().prefabContentsRoot, previousFileID); } - } - SceneView.RepaintAll(); - var newPrefabStage = m_PrefabStages.Last(); - Assert.IsTrue(newPrefabStage.prefabAssetPath == prefabAssetPath); - return newPrefabStage; + var newPrefabStage = m_PrefabStages.Last(); + Assert.IsTrue(newPrefabStage.prefabAssetPath == prefabAssetPath); + SceneView.RepaintAll(); + return newPrefabStage; + } + else + { + // Failed to switch to new stage + return null; + } } static UInt64 GetFileIDForCorrespondingObjectFromSourceAtPath(GameObject gameObject, string prefabAssetPath) diff --git a/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs b/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs index ca15ccae26..1115f47abf 100644 --- a/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs +++ b/Editor/Mono/Scripting/APIUpdater/APIUpdaterAssemblyHelper.cs @@ -47,10 +47,13 @@ public static void Run(string commaSeparatedListOfAssemblies) string stdOut, stdErr; var assemblyFullPath = ResolveAssemblyPath(assemblyPath); - var exitCode = RunUpdatingProgram("AssemblyUpdater.exe", "-u -a " + assemblyFullPath + APIVersionArgument() + AssemblySearchPathArgument() + ConfigurationProviderAssembliesPathArgument(), out stdOut, out stdErr); + var exitCode = RunUpdatingProgram("AssemblyUpdater.exe", "-u -a " + assemblyFullPath + APIVersionArgument() + AssemblySearchPathArgument() + ConfigurationProviderAssembliesPathArgument() + NuGetArgument(), out stdOut, out stdErr); if (stdOut.Length > 0) APIUpdaterLogger.WriteToFile("Assembly update output ({0})\r\n{1}", assemblyFullPath, stdOut); + if (IsWarning(exitCode)) + APIUpdaterLogger.WriteWarningToConsole(stdOut); + if (IsError(exitCode)) APIUpdaterLogger.WriteErrorToConsole("Error {0} running AssemblyUpdater. Its output is: `{1}`", exitCode, stdErr); } @@ -58,6 +61,20 @@ public static void Run(string commaSeparatedListOfAssemblies) APIUpdaterLogger.WriteToFile("Update finished in {0}s", sw.Elapsed.TotalSeconds); } + private static string NuGetArgument() + { + var nugetPath = Paths.Combine(EditorApplication.applicationContentsPath, "Tools", "NuGet.exe"); + if (!File.Exists(nugetPath)) + return string.Empty; + + return " --nuget-path \"" + nugetPath + "\""; + } + + private static bool IsWarning(int exitCode) + { + return (exitCode & (1 << 6)) != 0; + } + private static bool IsError(int exitCode) { return (exitCode & (1 << 7)) != 0; @@ -80,7 +97,7 @@ public static bool DoesAssemblyRequireUpgrade(string assemblyFullPath) return false; string stdOut, stdErr; - var ret = RunUpdatingProgram("AssemblyUpdater.exe", TimeStampArgument() + APIVersionArgument() + "--check-update-required -a " + CommandLineFormatter.PrepareFileName(assemblyFullPath) + AssemblySearchPathArgument() + ConfigurationProviderAssembliesPathArgument(), out stdOut, out stdErr); + var ret = RunUpdatingProgram("AssemblyUpdater.exe", TimeStampArgument() + APIVersionArgument() + "--check-update-required -a " + CommandLineFormatter.PrepareFileName(assemblyFullPath) + AssemblySearchPathArgument() + ConfigurationProviderAssembliesPathArgument() + NuGetArgument(), out stdOut, out stdErr); { Console.WriteLine("{0}{1}", stdOut, stdErr); switch (ret) @@ -91,7 +108,14 @@ public static bool DoesAssemblyRequireUpgrade(string assemblyFullPath) case 2: return true; default: - Debug.LogError(stdOut + Environment.NewLine + stdErr); + if (IsWarning(ret)) + { + Debug.LogWarning(stdOut + Environment.NewLine + stdErr); + } + else + { + Debug.LogError(stdOut + Environment.NewLine + stdErr); + } return false; } } diff --git a/Editor/Mono/Scripting/APIUpdater/APIUpdaterLogger.cs b/Editor/Mono/Scripting/APIUpdater/APIUpdaterLogger.cs index 4143dcd762..c0a4764780 100644 --- a/Editor/Mono/Scripting/APIUpdater/APIUpdaterLogger.cs +++ b/Editor/Mono/Scripting/APIUpdater/APIUpdaterLogger.cs @@ -19,6 +19,11 @@ public static void WriteErrorToConsole(string msg, params object[] args) Debug.LogErrorFormat(msg, args); } + public static void WriteWarningToConsole(string msg, params object[] args) + { + Debug.LogWarningFormat(msg, args); + } + public static void WriteInfoToConsole(string line) { Debug.Log(line); diff --git a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs index a3481ab119..2b39572932 100644 --- a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs @@ -21,6 +21,13 @@ internal class CSharpLanguage : SupportedLanguage private static Regex _crOnlyRegex = new Regex("\r(?!\n)", RegexOptions.Compiled); private static Regex _lfOnlyRegex = new Regex("(? AllCompilerSpecific() + { + return new[] + { + MicrosoftCSharpCompiler, + MonoCSharpCompiler + }.Concat(MonoCSharpCompilerObsolete); + } + } +} diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs index 5a19930cbc..94728cf16f 100644 --- a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpCompiler.cs @@ -11,6 +11,7 @@ using UnityEditor.Scripting.ScriptCompilation; using UnityEditor.Utils; using UnityEngine; +using Debug = UnityEngine.Debug; namespace UnityEditor.Scripting.Compilers { @@ -24,10 +25,10 @@ public MicrosoftCSharpCompiler(MonoIsland island, bool runUpdater) : base(island BuildTarget BuildTarget => m_Island._target; - public static string[] GetClassLibraries(BuildTarget buildTarget) + public static string[] GetClassLibraries(BuildTarget buildTarget, bool buildingForEditor) { var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(buildTarget); - if (PlayerSettings.GetScriptingBackend(buildTargetGroup) != ScriptingImplementation.WinRTDotNET) + if (!IsBuildingForDotNetScriptingBackend(buildTargetGroup, buildingForEditor)) { return new string[] {}; } @@ -51,11 +52,11 @@ private void FillCompilerOptions(List arguments, out string argsPrefix) arguments.Add("/langversion:latest"); var platformSupportModule = ModuleManager.FindPlatformSupportModule(ModuleManager.GetTargetStringFromBuildTarget(BuildTarget)); - if (platformSupportModule != null) + if (platformSupportModule != null && !m_Island._editor) { var compilationExtension = platformSupportModule.CreateCompilationExtension(); - arguments.AddRange(GetClassLibraries(BuildTarget).Select(r => "/reference:\"" + r + "\"")); + arguments.AddRange(GetClassLibraries(BuildTarget, m_Island._editor).Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetAdditionalAssemblyReferences().Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetWindowsMetadataReferences().Select(r => "/reference:\"" + r + "\"")); arguments.AddRange(compilationExtension.GetAdditionalDefines().Select(d => "/define:" + d)); @@ -115,10 +116,26 @@ private Program StartCompilerImpl(List arguments, string argsPrefix) ThrowCompilerNotFoundException(csc); var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); - if (!AddCustomResponseFileIfPresent(arguments, ReponseFilename) && PlayerSettings.GetScriptingBackend(buildTargetGroup) != ScriptingImplementation.WinRTDotNET) + + var responseFiles = m_Island._responseFiles?.ToDictionary(Path.GetFileName) ?? new Dictionary(); + KeyValuePair obsoleteResponseFile = responseFiles + .SingleOrDefault(x => CompilerSpecificResponseFiles.MicrosoftCSharpCompilerObsolete.Contains(x.Key)); + + if (!string.IsNullOrEmpty(obsoleteResponseFile.Key)) + { + if (!IsBuildingForDotNetScriptingBackend(buildTargetGroup, m_Island._editor)) + { + Debug.LogWarning($"Using obsolete custom response file '{obsoleteResponseFile.Key}'. Please use '{CompilerSpecificResponseFiles.MicrosoftCSharpCompiler}' instead."); + } + else + { + responseFiles.Remove(obsoleteResponseFile.Key); + } + } + + foreach (var reposeFile in responseFiles) { - if (AddCustomResponseFileIfPresent(arguments, "mcs.rsp")) - UnityEngine.Debug.LogWarning($"Using obsolete custom response file 'mcs.rsp'. Please use '{ReponseFilename}' instead."); + AddResponseFileToArguments(arguments, reposeFile.Value); } var responseFile = CommandLineFormatter.GenerateResponseFile(arguments); @@ -187,7 +204,7 @@ protected override Program StartCompiler() var disableOptimizations = m_Island._development_player || (m_Island._editor && EditorPrefs.GetBool("AllowAttachedDebuggingOfEditor", true)); if (!disableOptimizations) { - if (PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) + if (IsBuildingForDotNetScriptingBackend(buildTargetGroup, m_Island._editor)) arguments.Add("/debug:pdbonly"); else arguments.Add("/debug:portable"); @@ -195,7 +212,7 @@ protected override Program StartCompiler() } else { - if (PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) + if (IsBuildingForDotNetScriptingBackend(buildTargetGroup, m_Island._editor)) arguments.Add("/debug:full"); else arguments.Add("/debug:portable"); @@ -207,12 +224,20 @@ protected override Program StartCompiler() return StartCompilerImpl(arguments, argsPrefix); } + private static bool IsBuildingForDotNetScriptingBackend(BuildTargetGroup buildTargetGroup, bool buildingForEditor) + { + if (buildingForEditor) + return false; + + return buildTargetGroup == BuildTargetGroup.WSA && PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET; + } + protected override string[] GetSystemReferenceDirectories() { var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(BuildTarget); - if (BuildTarget == BuildTarget.WSAPlayer && PlayerSettings.GetScriptingBackend(buildTargetGroup) == ScriptingImplementation.WinRTDotNET) + if (IsBuildingForDotNetScriptingBackend(buildTargetGroup, m_Island._editor)) { - return GetClassLibraries(BuildTarget).Select(library => Directory.GetParent(library).FullName).Distinct().ToArray(); + return GetClassLibraries(BuildTarget, m_Island._editor).Select(library => Directory.GetParent(library).FullName).Distinct().ToArray(); } return MonoLibraryHelpers.GetSystemReferenceDirectories(m_Island._api_compatibility_level); diff --git a/Editor/Mono/Scripting/Compilers/MicrosoftCSharpResponseFileProvider.cs b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpResponseFileProvider.cs new file mode 100644 index 0000000000..25bdaa9c4a --- /dev/null +++ b/Editor/Mono/Scripting/Compilers/MicrosoftCSharpResponseFileProvider.cs @@ -0,0 +1,13 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +namespace UnityEditor.Scripting.Compilers +{ + internal class MicrosoftCSharpResponseFileProvider : ResponseFileProvider + { + public override string ResponseFileName { get { return CompilerSpecificResponseFiles.MicrosoftCSharpCompiler; } } + public override string[] ObsoleteResponseFileNames { get { return CompilerSpecificResponseFiles.MicrosoftCSharpCompilerObsolete; } } + } +} diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs index f442a9f7b4..a43e08423f 100644 --- a/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs +++ b/Editor/Mono/Scripting/Compilers/MonoCSharpCompiler.cs @@ -53,22 +53,26 @@ protected override Program StartCompiler() arguments.Add(preparedFileName); } - if (!AddCustomResponseFileIfPresent(arguments, ResponseFilename)) + var responseFiles = m_Island._responseFiles?.ToDictionary(Path.GetFileName) ?? new Dictionary(); + KeyValuePair obsoleteResponseFile = responseFiles + .SingleOrDefault(x => CompilerSpecificResponseFiles.MonoCSharpCompilerObsolete.Contains(x.Key)); + if (!string.IsNullOrEmpty(obsoleteResponseFile.Key)) { - if (m_Island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0_Subset - && AddCustomResponseFileIfPresent(arguments, "smcs.rsp")) + if (m_Island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0_Subset) { - Debug.LogWarning("Using obsolete custom response file \'smcs.rsp\'. " + - $"Please use '{ResponseFilename}' instead."); + Debug.LogWarning($"Using obsolete custom response file '{obsoleteResponseFile.Key}'. Please use '{ResponseFilename}' instead."); } - else if (m_Island._api_compatibility_level == ApiCompatibilityLevel.NET_2_0 - && AddCustomResponseFileIfPresent(arguments, "gmcs.rsp")) + else { - Debug.LogWarning("Using obsolete custom response file \'gmcs.rsp\'. " + - $"Please use '{ResponseFilename}' instead."); + responseFiles.Remove(obsoleteResponseFile.Key); } } + foreach (var responseFile in responseFiles) + { + AddResponseFileToArguments(arguments, responseFile.Value); + } + return StartCompiler( m_Island._target, GetCompilerPath(), diff --git a/Editor/Mono/Scripting/Compilers/MonoCSharpResponseFileProvider.cs b/Editor/Mono/Scripting/Compilers/MonoCSharpResponseFileProvider.cs new file mode 100644 index 0000000000..9504f17764 --- /dev/null +++ b/Editor/Mono/Scripting/Compilers/MonoCSharpResponseFileProvider.cs @@ -0,0 +1,13 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +namespace UnityEditor.Scripting.Compilers +{ + internal class MonoCSharpResponseFileProvider : ResponseFileProvider + { + public override string ResponseFileName { get { return CompilerSpecificResponseFiles.MonoCSharpCompiler; } } + public override string[] ObsoleteResponseFileNames { get { return CompilerSpecificResponseFiles.MonoCSharpCompilerObsolete; } } + } +} diff --git a/Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs b/Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs new file mode 100644 index 0000000000..840c61bb75 --- /dev/null +++ b/Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs @@ -0,0 +1,97 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.IO; +using UnityEditor.Utils; +using UnityEngine; + +namespace UnityEditor.Scripting.Compilers +{ + internal abstract class ResponseFileProvider + { + private const string k_AssetsFolder = "Assets"; + public abstract string ResponseFileName { get; } + + public abstract string[] ObsoleteResponseFileNames { get; } + + public string ProjectPath + { + get; set; + } + + protected ResponseFileProvider() + { + var dataPath = Application.dataPath; + ProjectPath = Path.GetDirectoryName(dataPath); + } + + public List Get(string folderToLookForResponseFilesIn) + { + if (!string.IsNullOrEmpty(folderToLookForResponseFilesIn) && !Path.IsPathRooted(folderToLookForResponseFilesIn)) + { + folderToLookForResponseFilesIn = Path.Combine(ProjectPath, folderToLookForResponseFilesIn); + } + + var result = new List(); + + var folderResponseFile = GetCompilerSpecific(folderToLookForResponseFilesIn); + if (!string.IsNullOrEmpty(folderResponseFile)) + { + AddIfNotNull(result, folderResponseFile); + } + else + { + AddIfNotNull(result, GetDefaultResponseFiles()); + } + + return result; + } + + protected string GetCompilerSpecific(string path) + { + if (string.IsNullOrEmpty(path)) + { + return null; + } + + //We only look for the specific response file in the folder. + var responseFilePath = Path.Combine(path, ResponseFileName); + + if (File.Exists(responseFilePath)) + { + return responseFilePath; + } + return null; + } + + protected string GetDefaultResponseFiles() + { + var rootResponseFilePath = Paths.Combine(ProjectPath, k_AssetsFolder, ResponseFileName); + if (File.Exists(rootResponseFilePath)) + { + return rootResponseFilePath; + } + + foreach (var obsoleteResponseFileName in ObsoleteResponseFileNames) + { + var obsoleteResponseFilePath = Paths.Combine(ProjectPath, k_AssetsFolder, obsoleteResponseFileName); + if (File.Exists(obsoleteResponseFilePath)) + { + return obsoleteResponseFilePath; + } + } + return null; + } + + private static void AddIfNotNull(List list, T element) + { + if (element != null) + { + list.Add(element); + } + } + } +} diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index 55d02b8100..4dd2ba758e 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -119,24 +119,30 @@ protected bool AddCustomResponseFileIfPresent(List arguments, string res if (!File.Exists(relativeCustomResponseFilePath)) return false; + AddResponseFileToArguments(arguments, relativeCustomResponseFilePath); + return true; + } + protected void AddResponseFileToArguments(List arguments, string responseFileName) + { var responseFileData = ParseResponseFileFromFile( - Path.Combine(m_ProjectDirectory, relativeCustomResponseFilePath), + Path.Combine(m_ProjectDirectory, responseFileName), Application.dataPath, GetSystemReferenceDirectories()); foreach (var error in responseFileData.Errors) { - Debug.LogError($"{relativeCustomResponseFilePath} Parse Error : {error}"); + Debug.LogError($"{responseFileName} Parse Error : {error}"); } arguments.AddRange(responseFileData.Defines.Distinct().Select(define => "/define:" + define)); arguments.AddRange(responseFileData.FullPathReferences.Select(reference => "/reference:" + PrepareFileName(reference.Assembly))); + if (responseFileData.Unsafe) + { + arguments.Add("/unsafe"); + } - if (responseFileData.Unsafe) arguments.Add("/unsafe"); arguments.AddRange(responseFileData.OtherArguments); - - return true; } public static ResponseFileData ParseResponseFileFromFile( diff --git a/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs b/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs index c1ac360e69..12a3c04a72 100644 --- a/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs @@ -6,6 +6,11 @@ namespace UnityEditor.Scripting.Compilers { internal abstract class SupportedLanguage { + public virtual ResponseFileProvider CreateResponseFileProvider() + { + return null; + } + public abstract string GetExtensionICanCompile(); public abstract string GetLanguageName(); public abstract ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater); diff --git a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs index a8a63432fa..33221217f4 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs @@ -216,7 +216,7 @@ static bool IsNullOrWhiteSpace(string value) return value == null || value.All(char.IsWhiteSpace); } - static bool EvaluateDefine(string expr, ICollection defines) + public static bool EvaluateDefine(string expr, ICollection defines) { var res = new List(); var pos = 0; @@ -290,12 +290,24 @@ static bool EvaluateBool(string expression) static bool ApplyOp(char op, Stack values) { - if (op == '&') return values.Pop() && values.Pop(); - if (op == '|') return values.Pop() || values.Pop(); - if (op == '!') return !values.Pop(); - if (op == '=') return values.Pop() == values.Pop(); - - return false; + var val1 = values.Pop(); + switch (op) + { + case '&': + { + var val2 = values.Pop(); + return val1 && val2; + } + case '|': + { + var val2 = values.Pop(); + return val1 || val2; + } + case '!': return !val1; + case '=': return val1 == values.Pop(); + default: + throw new NotImplementedException($"{op}: unrecognized operator"); + } } /// Returns whether 'op2' has higher or same precedence as 'op1'. diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index 1eccdccda8..17bc5b7141 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -536,6 +536,7 @@ internal static ScriptAssembly[] ToScriptAssemblies(IDictionary a.FullPath)).ToArray(); } - public MonoIsland ToMonoIsland(EditorScriptCompilationOptions options, string buildOutputDirectory) + public MonoIsland ToMonoIsland(EditorScriptCompilationOptions options, string buildOutputDirectory, string projectPath = null) { bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; bool developmentBuild = (options & EditorScriptCompilationOptions.BuildingDevelopmentBuild) == EditorScriptCompilationOptions.BuildingDevelopmentBuild; @@ -81,6 +83,14 @@ public MonoIsland ToMonoIsland(EditorScriptCompilationOptions options, string bu var referencesArray = references.Concat(References).ToArray(); + var responseFileProvider = Language?.CreateResponseFileProvider(); + if (!string.IsNullOrEmpty(projectPath) && responseFileProvider != null) + { + responseFileProvider.ProjectPath = projectPath; + } + + List reposeFiles = responseFileProvider?.Get(OriginPath) ?? new List(); + var outputPath = AssetPath.Combine(buildOutputDirectory, Filename); return new MonoIsland(BuildTarget, @@ -91,7 +101,8 @@ public MonoIsland ToMonoIsland(EditorScriptCompilationOptions options, string bu Files, referencesArray, Defines, - outputPath); + outputPath, + reposeFiles.ToArray()); } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs index e2d0b0fce5..1a30f6358e 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs @@ -36,6 +36,9 @@ public static bool UseDotNetCore(ScriptAssembly scriptAssembly) public static bool BuildingForDotNet(BuildTarget buildTarget, bool buildingForEditor, string assemblyName) { + if (buildingForEditor) + return false; + if (buildTarget != BuildTarget.WSAPlayer) return false; diff --git a/Editor/Mono/Scripting/ScriptCompilers.cs b/Editor/Mono/Scripting/ScriptCompilers.cs index 37f02f9f16..f09670cf1c 100644 --- a/Editor/Mono/Scripting/ScriptCompilers.cs +++ b/Editor/Mono/Scripting/ScriptCompilers.cs @@ -28,6 +28,7 @@ internal struct MonoIsland public readonly string[] _files; public readonly string[] _references; public readonly string[] _defines; + public readonly string[] _responseFiles; public readonly string _output; public MonoIsland(BuildTarget target, ApiCompatibilityLevel api_compatibility_level, bool allowUnsafeCode, string[] files, string[] references, string[] defines, string output) @@ -41,6 +42,7 @@ public MonoIsland(BuildTarget target, ApiCompatibilityLevel api_compatibility_le _references = references; _defines = defines; _output = output; + _responseFiles = null; } public MonoIsland(BuildTarget target, bool editor, bool development_player, bool allowUnsafeCode, ApiCompatibilityLevel api_compatibility_level, string[] files, string[] references, string[] defines, string output) @@ -54,6 +56,13 @@ public MonoIsland(BuildTarget target, bool editor, bool development_player, bool _references = references; _defines = defines; _output = output; + _responseFiles = null; + } + + public MonoIsland(BuildTarget target, bool editor, bool development_player, bool allowUnsafeCode, ApiCompatibilityLevel api_compatibility_level, string[] files, string[] references, string[] defines, string output, string[] responseFiles) + : this(target, editor, development_player, allowUnsafeCode, api_compatibility_level, files, references, defines, output) + { + _responseFiles = responseFiles; } public string GetExtensionOfSourceFiles() diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index 998704dfca..266d8fad3d 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -228,47 +228,52 @@ internal void GenerateAndWriteSolutionAndProjects(ScriptEditorUtility.ScriptEdit { // Only synchronize islands that have associated source files and ones that we actually want in the project. // This also filters out DLLs coming from .asmdef files in packages. - IEnumerable islands = EditorCompilationInterface.GetAllMonoIslands(). - Where(i => 0 < i._files.Length && i._files.Any(f => ShouldFileBePartOfSolution(f))); + IEnumerable islands = EditorCompilationInterface.Instance.GetAllScriptAssemblies(EditorScriptCompilationOptions.BuildingForEditor | EditorCompilationInterface.GetAdditionalEditorScriptCompilationOptions()) + .Where(i => 0 < i.Files.Length && i.Files.Any(ShouldFileBePartOfSolution)) + .Select(x => x.ToMonoIsland(EditorScriptCompilationOptions.BuildingForEditor, string.Empty, _projectDirectory)).ToList(); var allAssetProjectParts = GenerateAllAssetProjectParts(); - var responseFilePath = Path.Combine("Assets", MonoCSharpCompiler.ResponseFilename); - var monoIslands = islands.ToList(); - SyncSolution(monoIslands); var allProjectIslands = RelevantIslandsForMode(monoIslands, ModeForCurrentExternalEditor()).ToList(); + foreach (MonoIsland island in allProjectIslands) { - var responseFileData = parseResponseFileData(island, responseFilePath); - SyncProject(island, allAssetProjectParts, responseFileData, allProjectIslands); + SyncProject(island, allAssetProjectParts, ParseResponseFileData(island), allProjectIslands); } if (scriptEditor == ScriptEditorUtility.ScriptEditor.VisualStudioCode) WriteVSCodeSettingsFiles(); } - ScriptCompilerBase.ResponseFileData parseResponseFileData(MonoIsland island, string responseFilePath) + IEnumerable ParseResponseFileData(MonoIsland island) { var systemReferenceDirectories = CSharpLanguage.GetCSharpCompiler(island._target, true, "Assembly-CSharp") == CSharpCompiler.Microsoft - && PlayerSettings.GetScriptingBackend(BuildPipeline.GetBuildTargetGroup(island._target)) == ScriptingImplementation.WinRTDotNET - ? MicrosoftCSharpCompiler.GetClassLibraries(island._target) + && PlayerSettings.GetScriptingBackend(BuildPipeline.GetBuildTargetGroup(island._target)) == ScriptingImplementation.WinRTDotNET && !island._editor + ? MicrosoftCSharpCompiler.GetClassLibraries(island._target, island._editor) : MonoLibraryHelpers.GetSystemReferenceDirectories(island._api_compatibility_level); - ScriptCompilerBase.ResponseFileData responseFileData = ScriptCompilerBase.ParseResponseFileFromFile( - Path.Combine(_projectDirectory, responseFilePath), + Dictionary responseFilesData = island._responseFiles.ToDictionary(x => x, x => ScriptCompilerBase.ParseResponseFileFromFile( + Path.Combine(_projectDirectory, x), _projectDirectory, - systemReferenceDirectories); + systemReferenceDirectories + )); - if (responseFileData.Errors.Length > 0) + Dictionary responseFilesWithErrors = responseFilesData.Where(x => x.Value.Errors.Any()) + .ToDictionary(x => x.Key, x => x.Value); + + if (responseFilesWithErrors.Any()) { - foreach (var error in responseFileData.Errors) - UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", responseFilePath, error); + foreach (var error in responseFilesWithErrors) + foreach (var valueError in error.Value.Errors) + { + UnityEngine.Debug.LogErrorFormat("{0} Parse Error : {1}", error.Key, valueError); + } } - return responseFileData; + return responseFilesData.Select(x => x.Value); } Dictionary GenerateAllAssetProjectParts() @@ -325,10 +330,10 @@ bool IsNonInternalizedPackagePath(string file) void SyncProject(MonoIsland island, Dictionary allAssetsProjectParts, - ScriptCompilerBase.ResponseFileData responseFileData, + IEnumerable responseFilesData, List allProjectIslands) { - SyncProjectFileIfNotChanged(ProjectFile(island), ProjectText(island, ModeForCurrentExternalEditor(), allAssetsProjectParts, responseFileData, allProjectIslands)); + SyncProjectFileIfNotChanged(ProjectFile(island), ProjectText(island, ModeForCurrentExternalEditor(), allAssetsProjectParts, responseFilesData, allProjectIslands)); } static void SyncProjectFileIfNotChanged(string path, string newContents) @@ -385,10 +390,10 @@ static bool IsAdditionalInternalAssemblyReference(bool isBuildingEditorProject, string ProjectText(MonoIsland island, Mode mode, Dictionary allAssetsProjectParts, - ScriptCompilerBase.ResponseFileData responseFileData, + IEnumerable responseFilesData, List allProjectIslands) { - var projectBuilder = new StringBuilder(ProjectHeader(island, responseFileData)); + var projectBuilder = new StringBuilder(ProjectHeader(island, responseFilesData)); var references = new List(); var projectReferences = new List(); Match match; @@ -462,7 +467,7 @@ string ProjectText(MonoIsland island, AppendReference(fullReference, projectBuilder); } - var responseRefs = responseFileData.FullPathReferences.Select(r => r.Assembly); + var responseRefs = responseFilesData.SelectMany(x => x.FullPathReferences.Select(r => r.Assembly)); foreach (var reference in responseRefs) { AppendReference(reference, projectBuilder); @@ -515,7 +520,7 @@ internal string SolutionFile() } private string ProjectHeader(MonoIsland island, - ScriptCompilerBase.ResponseFileData responseFileData) + IEnumerable responseFilesData) { string targetframeworkversion = "v3.5"; string targetLanguageVersion = "4"; @@ -548,14 +553,14 @@ private string ProjectHeader(MonoIsland island, toolsversion, productversion, ProjectGuid(island._output), _settings.EngineAssemblyPath, _settings.EditorAssemblyPath, - string.Join(";", new[] { "DEBUG", "TRACE"}.Concat(island._defines).Concat(responseFileData.Defines).Distinct().ToArray()), + string.Join(";", new[] { "DEBUG", "TRACE"}.Concat(island._defines).Concat(responseFilesData.SelectMany(x => x.Defines)).Distinct().ToArray()), MSBuildNamespaceUri, Path.GetFileNameWithoutExtension(island._output), EditorSettings.projectGenerationRootNamespace, targetframeworkversion, targetLanguageVersion, baseDirectory, - island._allowUnsafeCode | responseFileData.Unsafe + island._allowUnsafeCode | responseFilesData.Any(x => x.Unsafe) }; try diff --git a/Modules/GraphViewEditor/Elements/StackNode.cs b/Modules/GraphViewEditor/Elements/StackNode.cs index 2fc5dde794..89d0c5cfe0 100644 --- a/Modules/GraphViewEditor/Elements/StackNode.cs +++ b/Modules/GraphViewEditor/Elements/StackNode.cs @@ -99,7 +99,7 @@ public void InsertElement(int index, GraphElement element) if (graphView != null) { - graphView.RestorePersistedSelection(); + graphView.RestorePersitentSelectionForElement(element); } } diff --git a/Modules/GraphViewEditor/Views/GraphView.cs b/Modules/GraphViewEditor/Views/GraphView.cs index a22ce0220b..fcaf9e410a 100644 --- a/Modules/GraphViewEditor/Views/GraphView.cs +++ b/Modules/GraphViewEditor/Views/GraphView.cs @@ -14,25 +14,50 @@ namespace UnityEditor.Experimental.UIElements.GraphView internal interface IGraphViewSelection { int version { get; set; } - List selectedElements { get; set; } + + HashSet selectedElements { get; } } - internal class GraphViewUndoRedoSelection : ScriptableObject, IGraphViewSelection + internal class GraphViewUndoRedoSelection : ScriptableObject, IGraphViewSelection, ISerializationCallbackReceiver { [SerializeField] private int m_Version; + [SerializeField] - private List m_SelectedElements; + string[] m_SelectedElementsArray; + + [NonSerialized] + private HashSet m_SelectedElements = new HashSet(); public int version { get { return m_Version; } set { m_Version = value; } } - public List selectedElements + + public HashSet selectedElements => m_SelectedElements; + + public void OnBeforeSerialize() { - get { return m_SelectedElements; } - set { m_SelectedElements = value; } + if (m_SelectedElements.Count == 0) + return; + + m_SelectedElementsArray = new string[m_SelectedElements.Count]; + + m_SelectedElements.CopyTo(m_SelectedElementsArray); + } + + public void OnAfterDeserialize() + { + m_SelectedElements.Clear(); + + if (m_SelectedElementsArray == null || m_SelectedElementsArray.Length == 0) + return; + + foreach (string guid in m_SelectedElementsArray) + { + m_SelectedElements.Add(guid); + } } } @@ -84,22 +109,46 @@ internal class Layer : VisualElement {} public ViewTransformChanged viewTransformChanged { get; set; } [Serializable] - class PersistedSelection : IGraphViewSelection + class PersistedSelection : IGraphViewSelection, ISerializationCallbackReceiver { [SerializeField] private int m_Version; + [SerializeField] - private List m_SelectedElements; + string[] m_SelectedElementsArray; + + [NonSerialized] + private HashSet m_SelectedElements = new HashSet(); public int version { get { return m_Version; } set { m_Version = value; } } - public List selectedElements + + public HashSet selectedElements => m_SelectedElements; + + public void OnBeforeSerialize() { - get { return m_SelectedElements; } - set { m_SelectedElements = value; } + if (m_SelectedElements.Count == 0) + return; + + m_SelectedElementsArray = new string[m_SelectedElements.Count]; + + m_SelectedElements.CopyTo(m_SelectedElementsArray); + } + + public void OnAfterDeserialize() + { + if (m_SelectedElementsArray == null || m_SelectedElementsArray.Length == 0) + return; + + m_SelectedElements.Clear(); + + foreach (string guid in m_SelectedElementsArray) + { + m_SelectedElements.Add(guid); + } } } private const string k_SelectionUndoRedoLabel = "Change GraphView Selection"; @@ -270,12 +319,28 @@ private void RestoreSavedSelection(IGraphViewSelection graphViewSelection) selectionObjectToSync = m_PersistedSelection; selectionObjectToSync.selectedElements.Clear(); - selectionObjectToSync.selectedElements.AddRange(graphViewSelection.selectedElements); + + foreach (string guid in graphViewSelection.selectedElements) + { + selectionObjectToSync.selectedElements.Add(guid); + } } - internal void RestorePersistedSelection() + internal void RestorePersitentSelectionForElement(GraphElement element) { - RestoreSavedSelection(m_PersistedSelection); + if (m_PersistedSelection == null) + return; + + if (m_PersistedSelection.selectedElements.Count == selection.Count && m_PersistedSelection.version == m_SavedSelectionVersion) + return; + + if (string.IsNullOrEmpty(element.persistenceKey)) + return; + + if (m_PersistedSelection.selectedElements.Contains(element.persistenceKey)) + { + AddToSelectionNoUndoRecord(element); + } } private void UndoRedoPerformed() @@ -456,8 +521,6 @@ public override void OnPersistentDataReady() m_PersistedViewTransform = GetOrCreatePersistentData(m_PersistedViewTransform, key); m_PersistedSelection = GetOrCreatePersistentData(m_PersistedSelection, key); - if (m_PersistedSelection.selectedElements == null) - m_PersistedSelection.selectedElements = new List(); UpdateViewTransform(m_PersistedViewTransform.position, m_PersistedViewTransform.scale); RestoreSavedSelection(m_PersistedSelection); @@ -502,11 +565,6 @@ protected void ValidateTransform() // ISelection implementation public List selection { get; protected set; } - internal void AddToPersistedSelection(string guid) - { - m_PersistedSelection.selectedElements.Add(guid); - } - // functions to ISelection extensions public virtual void AddToSelection(ISelectable selectable) { @@ -701,7 +759,6 @@ protected internal override void ExecuteDefaultAction(EventBase evt) { Undo.undoRedoPerformed += UndoRedoPerformed; m_GraphViewUndoRedoSelection = ScriptableObject.CreateInstance(); - m_GraphViewUndoRedoSelection.selectedElements = new List(); m_GraphViewUndoRedoSelection.hideFlags = HideFlags.HideAndDontSave; } } @@ -1110,7 +1167,7 @@ public void AddElement(GraphElement graphElement) // Attempt to restore selection on the new element if it // was previously selected (same GUID). - RestorePersistedSelection(); + RestorePersitentSelectionForElement(graphElement); } public void RemoveElement(GraphElement graphElement) diff --git a/Modules/ShortcutManagerEditor/ContextManager.cs b/Modules/ShortcutManagerEditor/ContextManager.cs index c6709cd1f7..6febae5542 100644 --- a/Modules/ShortcutManagerEditor/ContextManager.cs +++ b/Modules/ShortcutManagerEditor/ContextManager.cs @@ -27,7 +27,7 @@ internal class GlobalContext {} public static readonly GlobalContext globalContext = new GlobalContext(); public static readonly Type globalContextType = typeof(GlobalContext); - WeakReference m_FocusedWindow; + WeakReference m_FocusedWindow = new WeakReference(null); List m_PriorityContexts = new List(); @@ -41,15 +41,15 @@ private EditorWindow focusedWindow { get { - if (m_FocusedWindow != null && m_FocusedWindow.IsAlive && m_FocusedWindow.Target != null) - return m_FocusedWindow.Target as EditorWindow; + if (m_FocusedWindow.Target != null && m_FocusedWindow.IsAlive) + return (EditorWindow)m_FocusedWindow.Target; return null; } } public void SetFocusedWindow(EditorWindow window) { - m_FocusedWindow = new WeakReference(window); + m_FocusedWindow.Target = window; } static bool IsPriorityContext(IShortcutToolContext context) diff --git a/Modules/ShortcutManagerEditor/Directory.cs b/Modules/ShortcutManagerEditor/Directory.cs index 05f04b2292..c26d1f63a4 100644 --- a/Modules/ShortcutManagerEditor/Directory.cs +++ b/Modules/ShortcutManagerEditor/Directory.cs @@ -12,6 +12,7 @@ namespace UnityEditor.ShortcutManagement { class Directory : IDirectory { + List[] m_IndexedShortcutEntries; List m_ShortcutEntries; public Directory(IEnumerable entries) @@ -21,66 +22,52 @@ public Directory(IEnumerable entries) public void Initialize(IEnumerable entries) { - m_ShortcutEntries = new List(entries); + m_ShortcutEntries = new List(entries.Count()); + m_IndexedShortcutEntries = new List[(int)KeyCode.Mouse0]; + foreach (ShortcutEntry entry in entries) + { + m_ShortcutEntries.Add(entry); + if (entry.combinations.Any()) + AddEntry(entry.combinations.First().keyCode, entry); + // TODO: Index unbound entries? + } } - public void FindShortcutEntries(List combinationSequence, Type[] context, List outputShortcuts) + void FindShortcutEntries(List combinationSequence, List outputShortcuts, Predicate filter) { outputShortcuts.Clear(); Assert.IsNotNull(combinationSequence); Assert.IsTrue(combinationSequence.Count > 0, "Sequence can not be empty"); + List entries = m_IndexedShortcutEntries[(int)combinationSequence[0].keyCode]; + if (entries == null) + return; + + m_CombinationSequence = combinationSequence; + m_Predicate = filter; + foreach (var entry in entries) + if (ShortcutStartsWithCombinationSequenceAndSatisfiesPredicate(entry)) + outputShortcuts.Add(entry); + } - foreach (var shortcutEntry in m_ShortcutEntries) - { - if (shortcutEntry.StartsWith(combinationSequence)) - { - if (context != null && Array.FindIndex(context, t => t == shortcutEntry.context || shortcutEntry.context != null && shortcutEntry.context.IsAssignableFrom(t)) < 0) - continue; - - outputShortcuts.Add(shortcutEntry); - } - } + public void FindShortcutEntries(List combinationSequence, Type[] context, List outputShortcuts) + { + m_ShortcutEntryContextList = context; + Predicate filter = null; + if (context != null) + filter = ShortcutEntryMatchesAnyContext; + FindShortcutEntries(combinationSequence, outputShortcuts, filter); } public void FindShortcutEntries(List combinationSequence, IContextManager contextManager, List outputShortcuts) { - outputShortcuts.Clear(); - - Assert.IsNotNull(combinationSequence); - Assert.IsTrue(combinationSequence.Count > 0, "Sequence can not be empty"); - - foreach (var shortcutEntry in m_ShortcutEntries) - { - if (shortcutEntry.StartsWith(combinationSequence)) - { - if (!contextManager.HasActiveContextOfType(shortcutEntry.context)) - continue; - if (shortcutEntry.type != ShortcutType.Menu && contextManager.playModeContextIsActive) - // Emulate old play mode shortcut behavior - // * Menu shortcuts are always active - // * Non-menu shortcuts only apply when the game view does not have focus - continue; - - outputShortcuts.Add(shortcutEntry); - } - } + m_ContextManager = contextManager; + FindShortcutEntries(combinationSequence, outputShortcuts, ShortcutEntrySatisfiesContextManager); } public void FindShortcutEntries(List combinationSequence, List outputShortcuts) { - outputShortcuts.Clear(); - - Assert.IsNotNull(combinationSequence); - Assert.IsTrue(combinationSequence.Count > 0, "Sequence can not be empty"); - - foreach (var shortcutEntry in m_ShortcutEntries) - { - if (shortcutEntry.StartsWith(combinationSequence)) - { - outputShortcuts.Add(shortcutEntry); - } - } + FindShortcutEntries(combinationSequence, outputShortcuts, null); } public ShortcutEntry FindShortcutEntry(Identifier identifier) @@ -94,5 +81,50 @@ public ShortcutEntry FindShortcutEntry(string shortcutId) id.path = shortcutId; return FindShortcutEntry(id); } + + void AddEntry(KeyCode keyCode, ShortcutEntry entry) + { + int keyCodeValue = (int)keyCode; + List entriesForKeyCode = m_IndexedShortcutEntries[keyCodeValue]; + if (entriesForKeyCode == null) + m_IndexedShortcutEntries[keyCodeValue] = entriesForKeyCode = new List(); + entriesForKeyCode.Add(entry); + } + + ////////////////////////////// + // Lambda elimination helpers + ////////////////////////////// + static Type m_ShortcutEntryContext; + static Type[] m_ShortcutEntryContextList; + static List m_CombinationSequence; + static Predicate m_Predicate; + static IContextManager m_ContextManager; + + static bool ShortcutStartsWithCombinationSequenceAndSatisfiesPredicate(ShortcutEntry entry) + { + return entry.StartsWith(m_CombinationSequence) && (m_Predicate == null || m_Predicate(entry)); + } + + static bool ShortcutEntryMatchesAnyContext(ShortcutEntry entry) + { + m_ShortcutEntryContext = entry.context; + return m_ShortcutEntryContextList == null || m_ShortcutEntryContextList.Any(ShortcutEntryMatchesContext); + } + + static bool ShortcutEntryMatchesContext(Type context) + { + return context == m_ShortcutEntryContext || + (m_ShortcutEntryContext != null && m_ShortcutEntryContext.IsAssignableFrom(context)); + } + + static bool ShortcutEntrySatisfiesContextManager(ShortcutEntry entry) + { + return m_ContextManager.HasActiveContextOfType(entry.context) && + // Emulate old play mode shortcut behavior + // * Menu shortcuts are always active + // * Non-menu shortcuts only apply when the game view does not have focus + (!m_ContextManager.playModeContextIsActive || + entry.type == ShortcutType.Menu); + } } } diff --git a/Modules/ShortcutManagerEditor/KeyCombination.cs b/Modules/ShortcutManagerEditor/KeyCombination.cs index a741cb5b22..7542ebefd4 100644 --- a/Modules/ShortcutManagerEditor/KeyCombination.cs +++ b/Modules/ShortcutManagerEditor/KeyCombination.cs @@ -12,7 +12,7 @@ namespace UnityEditor.ShortcutManagement { [Serializable] - struct KeyCombination + struct KeyCombination : IEquatable { [SerializeField] KeyCode m_KeyCode; @@ -228,5 +228,24 @@ static bool TryFormatKeycode(KeyCode code, StringBuilder builder) return true; } + + public bool Equals(KeyCombination other) + { + return m_KeyCode == other.m_KeyCode && m_Modifiers == other.m_Modifiers; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is KeyCombination && Equals((KeyCombination)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((int)m_KeyCode * 397) ^ (int)m_Modifiers; + } + } } } diff --git a/Modules/ShortcutManagerEditor/ShortcutAttribute.cs b/Modules/ShortcutManagerEditor/ShortcutAttribute.cs index 7f741de2e3..d0edad4adc 100644 --- a/Modules/ShortcutManagerEditor/ShortcutAttribute.cs +++ b/Modules/ShortcutManagerEditor/ShortcutAttribute.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection; using UnityEngine; +using UnityEngineInternal; namespace UnityEditor.ShortcutManagement { @@ -22,10 +23,7 @@ class ShortcutAttribute : ShortcutBaseAttribute internal string identifier { get; } internal Type context { get; } internal string defaultKeyCombination { get; } - - - static readonly object[] k_ReusableShortcutArgs = { null }; - static readonly object[] k_EmptyReusableShortcutArgs = {}; + Action m_NoArgumentsAction; public ShortcutAttribute(string identifier, Type context = null, string defaultKeyCombination = null) { @@ -39,6 +37,11 @@ public ShortcutAttribute(string identifier, Type context = null, string defaultK [RequiredSignature] static extern void ShortcutMethodNoArgs(); + void NoArgumentShortcutMethodProxy(ShortcutArguments arguments) + { + m_NoArgumentsAction(); + } + public override ShortcutEntry CreateShortcutEntry(MethodInfo methodInfo) { var identifier = new Identifier(methodInfo, this); @@ -52,20 +55,15 @@ public override ShortcutEntry CreateShortcutEntry(MethodInfo methodInfo) var type = this is ClutchShortcutAttribute ? ShortcutType.Clutch : ShortcutType.Action; var methodParams = methodInfo.GetParameters(); Action action; - if (methodParams.Length == 0) - { - action = shortcutArgs => - { - methodInfo.Invoke(null, k_EmptyReusableShortcutArgs); - }; - } + + // We instantiate this as the specific delegate type in advance, + // because passing ShortcutArguments in object[] via MethodInfo.Invoke() causes boxing/allocation + if (methodParams.Any()) + action = (Action)methodInfo.CreateDelegate(typeof(Action), null); else { - action = shortcutArgs => - { - k_ReusableShortcutArgs[0] = shortcutArgs; - methodInfo.Invoke(null, k_ReusableShortcutArgs); - }; + m_NoArgumentsAction = (Action)methodInfo.CreateDelegate(typeof(Action), null); + action = NoArgumentShortcutMethodProxy; } return new ShortcutEntry(identifier, defaultCombination, action, context, type); diff --git a/Modules/ShortcutManagerEditor/ShortcutEntry.cs b/Modules/ShortcutManagerEditor/ShortcutEntry.cs index c68b8a5b8a..bed4515b4a 100644 --- a/Modules/ShortcutManagerEditor/ShortcutEntry.cs +++ b/Modules/ShortcutManagerEditor/ShortcutEntry.cs @@ -64,7 +64,7 @@ class ShortcutEntry public Identifier identifier => m_Identifier; - public IEnumerable combinations => activeCombination; + public IList combinations => activeCombination; public bool overridden => m_OverridenCombinations != null; @@ -72,6 +72,8 @@ class ShortcutEntry public Type context => m_Context; public ShortcutType type => m_Type; + ShortcutModifiers m_ReservedModifier; + internal ShortcutEntry(Identifier id, IEnumerable defaultCombination, Action action, Type context, ShortcutType type) { m_Identifier = id; @@ -79,6 +81,10 @@ internal ShortcutEntry(Identifier id, IEnumerable defaultCombina m_Context = context ?? ContextManager.globalContextType; m_Action = action; m_Type = type; + + if (typeof(IShortcutToolContext).IsAssignableFrom(m_Context)) + foreach (var attribute in m_Context.GetCustomAttributes(typeof(ReserveModifiersAttribute), true)) + m_ReservedModifier |= (attribute as ReserveModifiersAttribute).modifier; } public override string ToString() @@ -101,43 +107,18 @@ public bool StartsWith(List prefix) if (activeCombination.Count < prefix.Count) return false; - if (prefix.Count != 0) + if (prefix.Count != 0 && typeof(IShortcutToolContext).IsAssignableFrom(m_Context)) { - var contextType = context; - if (typeof(IShortcutToolContext).IsAssignableFrom(contextType)) + var lastKeyCombination = prefix.Last(); + lastKeyCombination = new KeyCombination(lastKeyCombination.keyCode, lastKeyCombination.modifiers & ~m_ReservedModifier); + + for (int i = 0; i < prefix.Count - 1; i++) { - var attributes = contextType.GetCustomAttributes(typeof(ReserveModifiersAttribute), true); - - var lastKeyCombination = prefix.Last(); - var newModifier = lastKeyCombination.modifiers; - - foreach (var attribute in attributes) - { - var modifier = (attribute as ReserveModifiersAttribute).modifier; - if ((modifier & ShortcutModifiers.Shift) == ShortcutModifiers.Shift) - { - newModifier = newModifier & ~ShortcutModifiers.Shift; - } - if ((modifier & ShortcutModifiers.Alt) == ShortcutModifiers.Alt) - { - newModifier = newModifier & ~ShortcutModifiers.Alt; - } - if ((modifier & ShortcutModifiers.ControlOrCommand) == ShortcutModifiers.ControlOrCommand) - { - newModifier = newModifier & ~ShortcutModifiers.ControlOrCommand; - } - } - - lastKeyCombination = new KeyCombination(lastKeyCombination.keyCode, newModifier); - - for (int i = 0; i < prefix.Count - 1; i++) - { - if (!prefix[i].Equals(activeCombination[i])) - return false; - } - - return lastKeyCombination.Equals(activeCombination[prefix.Count - 1]); + if (!prefix[i].Equals(activeCombination[i])) + return false; } + + return lastKeyCombination.Equals(activeCombination[prefix.Count - 1]); } for (int i = 0; i < prefix.Count; i++) diff --git a/Modules/ShortcutManagerEditor/Trigger.cs b/Modules/ShortcutManagerEditor/Trigger.cs index df70a6d649..c0d66a63c5 100644 --- a/Modules/ShortcutManagerEditor/Trigger.cs +++ b/Modules/ShortcutManagerEditor/Trigger.cs @@ -13,10 +13,11 @@ class Trigger { IDirectory m_Directory; IConflictResolver m_ConflictResolver; + IContextManager m_CurrentContextManager; List m_KeyCombinationSequence = new List(); List m_Entries = new List(); - Dictionary> m_ActiveClutches = new Dictionary>(); + Dictionary> m_ActiveClutches = new Dictionary>(); public event Action invokingAction; @@ -33,10 +34,10 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) if (evt.type == EventType.KeyUp) { - Tuple clutchTuple; - if (m_ActiveClutches.TryGetValue(evt.keyCode, out clutchTuple)) + KeyValuePair clutchKeyValuePair; + if (m_ActiveClutches.TryGetValue(evt.keyCode, out clutchKeyValuePair)) { - var clutchContext = m_ActiveClutches[evt.keyCode].Item2; + var clutchContext = m_ActiveClutches[evt.keyCode].Value; m_ActiveClutches.Remove(evt.keyCode); var args = new ShortcutArguments @@ -44,8 +45,8 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) context = clutchContext, state = ShortcutState.End }; - invokingAction?.Invoke(clutchTuple.Item1, args); - clutchTuple.Item1.action(args); + invokingAction?.Invoke(clutchKeyValuePair.Key, args); + clutchKeyValuePair.Key.action(args); } return; } @@ -70,7 +71,8 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) // Deal ONLY with prioritycontext if (entries.Count() > 1 && contextManager.HasAnyPriorityContext()) { - entries = m_Entries.FindAll(a => contextManager.HasPriorityContextOfType(a.context)); + m_CurrentContextManager = contextManager; + entries = m_Entries.FindAll(CurrentContextManagerHasPriorityContextFor); if (!entries.Any()) entries = m_Entries; } @@ -103,7 +105,7 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) case ShortcutType.Clutch: if (!m_ActiveClutches.ContainsKey(evt.keyCode)) { - m_ActiveClutches.Add(evt.keyCode, new Tuple(shortcutEntry, args.context)); + m_ActiveClutches.Add(evt.keyCode, new KeyValuePair(shortcutEntry, args.context)); args.state = ShortcutState.Begin; invokingAction?.Invoke(shortcutEntry, args); shortcutEntry.action(args); @@ -135,15 +137,15 @@ public void HandleKeyEvent(Event evt, IContextManager contextManager) public void ResetActiveClutches() { - foreach (var clutchTuple in m_ActiveClutches.Values) + foreach (var clutchKeyValuePair in m_ActiveClutches.Values) { var args = new ShortcutArguments { - context = clutchTuple.Item2, + context = clutchKeyValuePair.Value, state = ShortcutState.End, }; - invokingAction?.Invoke(clutchTuple.Item1, args); - clutchTuple.Item1.action(args); + invokingAction?.Invoke(clutchKeyValuePair.Key, args); + clutchKeyValuePair.Key.action(args); } m_ActiveClutches.Clear(); @@ -171,5 +173,10 @@ void Reset() { m_KeyCombinationSequence.Clear(); } + + bool CurrentContextManagerHasPriorityContextFor(ShortcutEntry entry) + { + return m_CurrentContextManager.HasPriorityContextOfType(entry.context); + } } } diff --git a/Modules/TerrainEditor/Brush/Brush.cs b/Modules/TerrainEditor/Brush/Brush.cs index a300ec29ac..99c163ed9c 100644 --- a/Modules/TerrainEditor/Brush/Brush.cs +++ b/Modules/TerrainEditor/Brush/Brush.cs @@ -64,6 +64,9 @@ void UpdateThumbnail() { if (m_UpdateThumbnail || m_Thumbnail == null) { + if (m_Mask == null) + m_Mask = DefaultMask(); + m_Thumbnail = GenerateBrushTexture(m_Mask, m_Falloff, m_RadiusScale, 64, 64, true); m_UpdateThumbnail = false; } diff --git a/Modules/TerrainEditor/Brush/BrushList.cs b/Modules/TerrainEditor/Brush/BrushList.cs index 553ef2891d..27813df7d0 100644 --- a/Modules/TerrainEditor/Brush/BrushList.cs +++ b/Modules/TerrainEditor/Brush/BrushList.cs @@ -72,6 +72,7 @@ public void LoadBrushes() arr.AddRange( AssetDatabase.FindAssets($"t:{typeof(Brush).Name}") .Select(p => AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(p), typeof(Brush)) as Brush) + .Where(b => b != null && b.texture != null) ); m_BrushList = arr.ToArray(); @@ -154,7 +155,7 @@ public void ShowEditGUI() if (selectedIndex == -1) return; - Brush b = m_BrushList == null ? null : m_BrushList[m_SelectedBrush]; + Brush b = m_BrushList == null ? null : GetActiveBrush(); // if the brush has been deleted outside unity rebuild the brush list if (b == null) @@ -232,9 +233,8 @@ internal void CreateBrush() return; var brushName = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(ProjectWindowUtil.GetActiveFolderPath(), "NewBrush.brush")); - var newBrush = Brush.CreateInstance(null, AnimationCurve.Linear(0, 0, 1, 1), Brush.kMaxRadiusScale, false); + var newBrush = Brush.CreateInstance((Texture2D)selection, AnimationCurve.Linear(0, 0, 1, 1), Brush.kMaxRadiusScale, false); AssetDatabase.CreateAsset(newBrush, brushName); - newBrush.m_Mask = (Texture2D)selection; LoadBrushes(); }, null); } @@ -244,7 +244,7 @@ internal static GUIContent[] GUIContentFromBrush(Brush[] brushes) GUIContent[] retval = new GUIContent[brushes.Length]; for (int i = 0; i < brushes.Length; i++) - retval[i] = new GUIContent(brushes[i].thumbnail); + retval[i] = new GUIContent(brushes[i].thumbnail, brushes[i].name); return retval; } diff --git a/Modules/TerrainEditor/TerrainInspector.cs b/Modules/TerrainEditor/TerrainInspector.cs index b0df34322f..6949056bfb 100644 --- a/Modules/TerrainEditor/TerrainInspector.cs +++ b/Modules/TerrainEditor/TerrainInspector.cs @@ -483,7 +483,7 @@ class Styles public Texture settingsIcon = EditorGUIUtility.IconContent("SettingsIcon").image; // List of tools supported by the editor - public GUIContent[] toolIcons = + public readonly GUIContent[] toolIcons = { EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolSplat", "Paint Terrain"), EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolTrees", "Paint Trees"), @@ -491,7 +491,7 @@ class Styles EditorGUIUtility.TrIconContent("TerrainInspector.TerrainToolSettings", "Terrain Settings") }; - public GUIContent[] toolNames = + public readonly GUIContent[] toolNames = { EditorGUIUtility.TrTextContent("Paint Terrain", "Select a tool from the drop down list"), EditorGUIUtility.TrTextContent("Paint Trees", "Click to paint trees.\n\nHold shift and click to erase trees.\n\nHold Ctrl and click to erase only trees of the selected type."), @@ -499,83 +499,87 @@ class Styles EditorGUIUtility.TrTextContent("Terrain Settings") }; - public GUIContent brushSize = EditorGUIUtility.TrTextContent("Brush Size", "Size of the brush used to paint."); - public GUIContent opacity = EditorGUIUtility.TrTextContent("Opacity", "Strength of the applied effect."); - public GUIContent targetStrength = EditorGUIUtility.TrTextContent("Target Strength", "Maximum opacity you can reach by painting continuously."); - public GUIContent settings = EditorGUIUtility.TrTextContent("Settings"); - public GUIContent mismatchedTerrainData = EditorGUIUtility.TextContentWithIcon( + public readonly GUIContent brushSize = EditorGUIUtility.TrTextContent("Brush Size", "Size of the brush used to paint."); + public readonly GUIContent opacity = EditorGUIUtility.TrTextContent("Opacity", "Strength of the applied effect."); + public readonly GUIContent targetStrength = EditorGUIUtility.TrTextContent("Target Strength", "Maximum opacity you can reach by painting continuously."); + public readonly GUIContent settings = EditorGUIUtility.TrTextContent("Settings"); + public readonly GUIContent mismatchedTerrainData = EditorGUIUtility.TextContentWithIcon( "The TerrainData used by the TerrainCollider component is different from this terrain. Would you like to assign the same TerrainData to the TerrainCollider component?", "console.warnicon"); - public GUIContent assign = EditorGUIUtility.TrTextContent("Assign"); - public GUIContent duplicateTab = EditorGUIUtility.TrTextContent("NOTE: Inspector tab is a duplicate. Paint functionality disabled."); + public readonly GUIContent assign = EditorGUIUtility.TrTextContent("Assign"); + public readonly GUIContent duplicateTab = EditorGUIUtility.TrTextContent("NOTE: Inspector tab is a duplicate. Paint functionality disabled."); // Textures - public GUIContent terrainLayers = EditorGUIUtility.TrTextContent("Terrain Layers"); - public GUIContent editTerrainLayers = EditorGUIUtility.TrTextContent("Edit Terrain Layers..."); + public readonly GUIContent terrainLayers = EditorGUIUtility.TrTextContent("Terrain Layers"); + public readonly GUIContent editTerrainLayers = EditorGUIUtility.TrTextContent("Edit Terrain Layers..."); // Trees - public GUIContent trees = EditorGUIUtility.TrTextContent("Trees"); - public GUIContent noTrees = EditorGUIUtility.TrTextContent("No Trees defined", "Use edit button below to add new tree types."); - public GUIContent editTrees = EditorGUIUtility.TrTextContent("Edit Trees...", "Add/remove tree types."); - public GUIContent treeDensity = EditorGUIUtility.TrTextContent("Tree Density", "How dense trees are you painting"); - public GUIContent treeHeight = EditorGUIUtility.TrTextContent("Tree Height", "Height of the planted trees"); - public GUIContent treeHeightRandomLabel = EditorGUIUtility.TrTextContent("Random?", "Enable random variation in tree height (variation)"); - public GUIContent treeHeightRandomToggle = EditorGUIUtility.TrTextContent("", "Enable random variation in tree height (variation)"); - public GUIContent lockWidth = EditorGUIUtility.TrTextContent("Lock Width to Height", "Let the tree width be the same with height"); - public GUIContent treeWidth = EditorGUIUtility.TrTextContent("Tree Width", "Width of the planted trees"); - public GUIContent treeWidthRandomLabel = EditorGUIUtility.TrTextContent("Random?", "Enable random variation in tree width (variation)"); - public GUIContent treeWidthRandomToggle = EditorGUIUtility.TrTextContent("", "Enable random variation in tree width (variation)"); - public GUIContent treeColorVar = EditorGUIUtility.TrTextContent("Color Variation", "Amount of random shading applied to trees"); - public GUIContent treeRotation = EditorGUIUtility.TrTextContent("Random Tree Rotation", "Enable?"); - public GUIContent massPlaceTrees = EditorGUIUtility.TrTextContent("Mass Place Trees", "The Mass Place Trees button is a very useful way to create an overall covering of trees without painting over the whole landscape. Following a mass placement, you can still use painting to add or remove trees to create denser or sparser areas."); - public GUIContent treeLightmapStatic = EditorGUIUtility.TrTextContent("Tree Lightmap Static", "The state of the Lightmap Static flag for the tree prefab root GameObject. The flag can be changed on the prefab. When disabled, this tree will not be visible to the lightmapper. When enabled, any child GameObjects which also have the static flag enabled, will be present in lightmap calculations. Regardless of the Static flag, each tree instance receives its own light probe and no lightmap texels."); + public readonly GUIContent trees = EditorGUIUtility.TrTextContent("Trees"); + public readonly GUIContent noTrees = EditorGUIUtility.TrTextContent("No Trees defined", "Use edit button below to add new tree types."); + public readonly GUIContent editTrees = EditorGUIUtility.TrTextContent("Edit Trees...", "Add/remove tree types."); + public readonly GUIContent treeDensity = EditorGUIUtility.TrTextContent("Tree Density", "How dense trees are you painting"); + public readonly GUIContent treeHeight = EditorGUIUtility.TrTextContent("Tree Height", "Height of the planted trees"); + public readonly GUIContent treeHeightRandomLabel = EditorGUIUtility.TrTextContent("Random?", "Enable random variation in tree height (variation)"); + public readonly GUIContent treeHeightRandomToggle = EditorGUIUtility.TrTextContent("", "Enable random variation in tree height (variation)"); + public readonly GUIContent lockWidth = EditorGUIUtility.TrTextContent("Lock Width to Height", "Let the tree width be the same with height"); + public readonly GUIContent treeWidth = EditorGUIUtility.TrTextContent("Tree Width", "Width of the planted trees"); + public readonly GUIContent treeWidthRandomLabel = EditorGUIUtility.TrTextContent("Random?", "Enable random variation in tree width (variation)"); + public readonly GUIContent treeWidthRandomToggle = EditorGUIUtility.TrTextContent("", "Enable random variation in tree width (variation)"); + public readonly GUIContent treeColorVar = EditorGUIUtility.TrTextContent("Color Variation", "Amount of random shading applied to trees"); + public readonly GUIContent treeRotation = EditorGUIUtility.TrTextContent("Random Tree Rotation", "Enable?"); + public readonly GUIContent massPlaceTrees = EditorGUIUtility.TrTextContent("Mass Place Trees", "The Mass Place Trees button is a very useful way to create an overall covering of trees without painting over the whole landscape. Following a mass placement, you can still use painting to add or remove trees to create denser or sparser areas."); + public readonly GUIContent treeLightmapStatic = EditorGUIUtility.TrTextContent("Tree Lightmap Static", "The state of the Lightmap Static flag for the tree prefab root GameObject. The flag can be changed on the prefab. When disabled, this tree will not be visible to the lightmapper. When enabled, any child GameObjects which also have the static flag enabled, will be present in lightmap calculations. Regardless of the Static flag, each tree instance receives its own light probe and no lightmap texels."); // Details - public GUIContent details = EditorGUIUtility.TrTextContent("Details"); - public GUIContent editDetails = EditorGUIUtility.TrTextContent("Edit Details...", "Add/remove detail meshes"); - public GUIContent detailTargetStrength = EditorGUIUtility.TrTextContent("Target Strength", "Target amount"); + public readonly GUIContent details = EditorGUIUtility.TrTextContent("Details"); + public readonly GUIContent editDetails = EditorGUIUtility.TrTextContent("Edit Details...", "Add/remove detail meshes"); + public readonly GUIContent detailTargetStrength = EditorGUIUtility.TrTextContent("Target Strength", "Target amount"); // Heightmaps - public GUIContent height = EditorGUIUtility.TrTextContent("Height", "You can set the Height property manually or you can shift-click on the terrain to sample the height at the mouse position (rather like the \"eyedropper\" tool in an image editor)."); + public readonly GUIContent height = EditorGUIUtility.TrTextContent("Height", "You can set the Height property manually or you can shift-click on the terrain to sample the height at the mouse position (rather like the \"eyedropper\" tool in an image editor)."); - public GUIContent textures = EditorGUIUtility.TrTextContent("Texture Resolutions (Require resampling on change)"); - public GUIContent importRaw = EditorGUIUtility.TrTextContent("Import Raw...", "The Import Raw button allows you to set the terrain's heightmap from an image file in the RAW grayscale format. RAW format can be generated by third party terrain editing tools (such as Bryce) and can also be opened, edited and saved by Photoshop. This allows for sophisticated generation and editing of terrains outside Unity."); - public GUIContent exportRaw = EditorGUIUtility.TrTextContent("Export Raw...", "The Export Raw button allows you to save the terrain's heightmap to an image file in the RAW grayscale format. RAW format can be generated by third party terrain editing tools (such as Bryce) and can also be opened, edited and saved by Photoshop. This allows for sophisticated generation and editing of terrains outside Unity."); - public GUIContent flatten = EditorGUIUtility.TrTextContent("Flatten", "The Flatten button levels the whole terrain to the chosen height."); + public readonly GUIContent textures = EditorGUIUtility.TrTextContent("Texture Resolutions (On Terrain Data)"); + public readonly GUIContent requireResampling = EditorGUIUtility.TrTextContent("Require resampling on change"); + public readonly GUIContent importRaw = EditorGUIUtility.TrTextContent("Import Raw...", "The Import Raw button allows you to set the terrain's heightmap from an image file in the RAW grayscale format. RAW format can be generated by third party terrain editing tools (such as Bryce) and can also be opened, edited and saved by Photoshop. This allows for sophisticated generation and editing of terrains outside Unity."); + public readonly GUIContent exportRaw = EditorGUIUtility.TrTextContent("Export Raw...", "The Export Raw button allows you to save the terrain's heightmap to an image file in the RAW grayscale format. RAW format can be generated by third party terrain editing tools (such as Bryce) and can also be opened, edited and saved by Photoshop. This allows for sophisticated generation and editing of terrains outside Unity."); + public readonly GUIContent flatten = EditorGUIUtility.TrTextContent("Flatten", "The Flatten button levels the whole terrain to the chosen height."); - public GUIContent bakeLightProbesForTrees = EditorGUIUtility.TrTextContent("Bake Light Probes For Trees", "If the option is enabled, Unity will create internal light probes at the position of each tree (these probes are internal and will not affect other renderers in the scene) and apply them to tree renderers for lighting. Otherwise trees are still affected by LightProbeGroups. The option is only effective for trees that have LightProbe enabled on their prototype prefab."); - public GUIContent deringLightProbesForTrees = EditorGUIUtility.TrTextContent("Remove Light Probe Ringing", "When enabled, removes visible overshooting often observed as ringing on objects affected by intense lighting at the expense of reduced contrast."); - public GUIContent refresh = EditorGUIUtility.TrTextContent("Refresh", "When you save a tree asset from the modelling app, you will need to click the Refresh button (shown in the inspector when the tree painting tool is selected) in order to see the updated trees on your terrain."); + public readonly GUIContent bakeLightProbesForTrees = EditorGUIUtility.TrTextContent("Bake Light Probes For Trees", "If the option is enabled, Unity will create internal light probes at the position of each tree (these probes are internal and will not affect other renderers in the scene) and apply them to tree renderers for lighting. Otherwise trees are still affected by LightProbeGroups. The option is only effective for trees that have LightProbe enabled on their prototype prefab."); + public readonly GUIContent deringLightProbesForTrees = EditorGUIUtility.TrTextContent("Remove Light Probe Ringing", "When enabled, removes visible overshooting often observed as ringing on objects affected by intense lighting at the expense of reduced contrast."); + public readonly GUIContent refresh = EditorGUIUtility.TrTextContent("Refresh", "When you save a tree asset from the modelling app, you will need to click the Refresh button (shown in the inspector when the tree painting tool is selected) in order to see the updated trees on your terrain."); // Settings - public GUIContent groupingID = EditorGUIUtility.TrTextContent("Grouping ID", "Grouping ID for auto connection"); - public GUIContent allowAutoConnect = EditorGUIUtility.TrTextContent("Auto connect", "Allow the current terrain tile automatically connect to neighboring tiles sharing the same grouping ID."); - public GUIContent attemptReconnect = EditorGUIUtility.TrTextContent("Reconnect", "Will attempt to re-run auto connection"); - public GUIContent drawTerrain = EditorGUIUtility.TrTextContent("Draw", "Toggle the rendering of terrain"); - public GUIContent drawInstancedTerrain = EditorGUIUtility.TrTextContent("Draw Instanced" , "Toggle terrain instancing rendering"); - public GUIContent pixelError = EditorGUIUtility.TrTextContent("Pixel Error", "The accuracy of the mapping between the terrain maps (heightmap, textures, etc) and the generated terrain; higher values indicate lower accuracy but lower rendering overhead."); - public GUIContent baseMapDist = EditorGUIUtility.TrTextContent("Base Map Dist.", "The maximum distance at which terrain textures will be displayed at full resolution. Beyond this distance, a lower resolution composite image will be used for efficiency."); - public GUIContent castShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "Does the terrain cast shadows?"); - public GUIContent material = EditorGUIUtility.TrTextContent("Material", "The material used to render the terrain. This will affect how the color channels of a terrain texture are interpreted."); - public GUIContent reflectionProbes = EditorGUIUtility.TrTextContent("Reflection Probes", "How reflection probes are used on terrain. Only effective when using built-in standard material or a custom material which supports rendering with reflection."); - public GUIContent thickness = EditorGUIUtility.TrTextContent("Thickness", "How much the terrain collision volume should extend along the negative Y-axis. Objects are considered colliding with the terrain from the surface to a depth equal to the thickness. This helps prevent high-speed moving objects from penetrating into the terrain without using expensive continuous collision detection."); - public GUIContent preserveTreePrototypeLayers = EditorGUIUtility.TextContent("Preserve Tree Prototype Layers|Enable this option if you want your tree instances to take on the layer values of their prototype prefabs, rather than the terrain GameObject's layer."); - public GUIContent drawTrees = EditorGUIUtility.TrTextContent("Draw", "Should trees, grass and details be drawn?"); - public GUIContent detailObjectDistance = EditorGUIUtility.TrTextContent("Detail Distance", "The distance (from camera) beyond which details will be culled."); - public GUIContent collectDetailPatches = EditorGUIUtility.TrTextContent("Collect Detail Patches", "Should detail patches in the Terrain be removed from memory when not visible?"); - public GUIContent detailObjectDensity = EditorGUIUtility.TrTextContent("Detail Density", "The number of detail/grass objects in a given unit of area. The value can be set lower to reduce rendering overhead."); - public GUIContent treeDistance = EditorGUIUtility.TrTextContent("Tree Distance", "The distance (from camera) beyond which trees will be culled."); - public GUIContent treeBillboardDistance = EditorGUIUtility.TrTextContent("Billboard Start", "The distance (from camera) at which 3D tree objects will be replaced by billboard images."); - public GUIContent treeCrossFadeLength = EditorGUIUtility.TrTextContent("Fade Length", "Distance over which trees will transition between 3D objects and billboards."); - public GUIContent treeMaximumFullLODCount = EditorGUIUtility.TrTextContent("Max Mesh Trees", "The maximum number of visible trees that will be represented as solid 3D meshes. Beyond this limit, trees will be replaced with billboards."); - - public GUIContent wavingGrassStrength = EditorGUIUtility.TrTextContent("Speed", "The speed of the wind as it blows grass."); - public GUIContent wavingGrassSpeed = EditorGUIUtility.TrTextContent("Size", "The size of the 'ripples' on grassy areas as the wind blows over them."); - public GUIContent wavingGrassAmount = EditorGUIUtility.TrTextContent("Bending", "The degree to which grass objects are bent over by the wind."); - public GUIContent wavingGrassTint = EditorGUIUtility.TrTextContent("Grass Tint", "Overall color tint applied to grass objects."); - - public static readonly GUIContent detailResolutionWarning = EditorGUIUtility.TrTextContent("You may reduce CPU draw call overhead by setting the detail resolution per patch as high as possible, relative to detail resolution."); + public readonly GUIContent basicTerrain = EditorGUIUtility.TrTextContent("Basic Terrain"); + public readonly GUIContent groupingID = EditorGUIUtility.TrTextContent("Grouping ID", "Grouping ID for auto connection"); + public readonly GUIContent allowAutoConnect = EditorGUIUtility.TrTextContent("Auto connect", "Allow the current terrain tile automatically connect to neighboring tiles sharing the same grouping ID."); + public readonly GUIContent attemptReconnect = EditorGUIUtility.TrTextContent("Reconnect", "Will attempt to re-run auto connection"); + public readonly GUIContent drawTerrain = EditorGUIUtility.TrTextContent("Draw", "Toggle the rendering of terrain"); + public readonly GUIContent drawInstancedTerrain = EditorGUIUtility.TrTextContent("Draw Instanced" , "Toggle terrain instancing rendering"); + public readonly GUIContent pixelError = EditorGUIUtility.TrTextContent("Pixel Error", "The accuracy of the mapping between the terrain maps (heightmap, textures, etc) and the generated terrain; higher values indicate lower accuracy but lower rendering overhead."); + public readonly GUIContent baseMapDist = EditorGUIUtility.TrTextContent("Base Map Dist.", "The maximum distance at which terrain textures will be displayed at full resolution. Beyond this distance, a lower resolution composite image will be used for efficiency."); + public readonly GUIContent castShadows = EditorGUIUtility.TrTextContent("Cast Shadows", "Does the terrain cast shadows?"); + public readonly GUIContent material = EditorGUIUtility.TrTextContent("Material", "The material used to render the terrain. This will affect how the color channels of a terrain texture are interpreted."); + public readonly GUIContent reflectionProbes = EditorGUIUtility.TrTextContent("Reflection Probes", "How reflection probes are used on terrain. Only effective when using built-in standard material or a custom material which supports rendering with reflection."); + public readonly GUIContent preserveTreePrototypeLayers = EditorGUIUtility.TextContent("Preserve Tree Prototype Layers|Enable this option if you want your tree instances to take on the layer values of their prototype prefabs, rather than the terrain GameObject's layer."); + public readonly GUIContent treeAndDetails = EditorGUIUtility.TrTextContent("Tree & Detail Objects"); + public readonly GUIContent drawTrees = EditorGUIUtility.TrTextContent("Draw", "Should trees, grass and details be drawn?"); + public readonly GUIContent detailObjectDistance = EditorGUIUtility.TrTextContent("Detail Distance", "The distance (from camera) beyond which details will be culled."); + public readonly GUIContent collectDetailPatches = EditorGUIUtility.TrTextContent("Collect Detail Patches", "Should detail patches in the Terrain be removed from memory when not visible?"); + public readonly GUIContent detailObjectDensity = EditorGUIUtility.TrTextContent("Detail Density", "The number of detail/grass objects in a given unit of area. The value can be set lower to reduce rendering overhead."); + public readonly GUIContent treeDistance = EditorGUIUtility.TrTextContent("Tree Distance", "The distance (from camera) beyond which trees will be culled."); + public readonly GUIContent treeBillboardDistance = EditorGUIUtility.TrTextContent("Billboard Start", "The distance (from camera) at which 3D tree objects will be replaced by billboard images."); + public readonly GUIContent treeCrossFadeLength = EditorGUIUtility.TrTextContent("Fade Length", "Distance over which trees will transition between 3D objects and billboards."); + public readonly GUIContent treeMaximumFullLODCount = EditorGUIUtility.TrTextContent("Max Mesh Trees", "The maximum number of visible trees that will be represented as solid 3D meshes. Beyond this limit, trees will be replaced with billboards."); + public readonly GUIContent physics = EditorGUIUtility.TrTextContent("Physics (On Terrain Data)"); + public readonly GUIContent thickness = EditorGUIUtility.TrTextContent("Thickness", "How much the terrain collision volume should extend along the negative Y-axis. Objects are considered colliding with the terrain from the surface to a depth equal to the thickness. This helps prevent high-speed moving objects from penetrating into the terrain without using expensive continuous collision detection."); + public readonly GUIContent grassWindSettings = EditorGUIUtility.TrTextContent("Wind Settings for Grass (On Terrain Data)"); + public readonly GUIContent wavingGrassStrength = EditorGUIUtility.TrTextContent("Speed", "The speed of the wind as it blows grass."); + public readonly GUIContent wavingGrassSpeed = EditorGUIUtility.TrTextContent("Size", "The size of the 'ripples' on grassy areas as the wind blows over them."); + public readonly GUIContent wavingGrassAmount = EditorGUIUtility.TrTextContent("Bending", "The degree to which grass objects are bent over by the wind."); + public readonly GUIContent wavingGrassTint = EditorGUIUtility.TrTextContent("Grass Tint", "Overall color tint applied to grass objects."); + public readonly GUIContent meshResolution = EditorGUIUtility.TrTextContent("Mesh Resolution (On Terrain Data)"); + public readonly GUIContent detailResolutionWarning = EditorGUIUtility.TrTextContent("You may reduce CPU draw call overhead by setting the detail resolution per patch as high as possible, relative to detail resolution."); } static Styles styles; @@ -1251,7 +1255,7 @@ public void ShowDetailStats() { GUILayout.Space(3); - EditorGUILayout.HelpBox(Styles.detailResolutionWarning.text, MessageType.Warning); + EditorGUILayout.HelpBox(styles.detailResolutionWarning.text, MessageType.Warning); int maxMeshes = m_Terrain.terrainData.detailPatchCount * m_Terrain.terrainData.detailPatchCount; EditorGUILayout.LabelField("Detail patches currently allocated: " + maxMeshes); @@ -1298,144 +1302,230 @@ public void ShowDetails() m_DetailStrength = Mathf.Round(m_DetailStrength * 16.0f) / 16.0f; } + private bool m_ShowBasicTerrainSettings = true; + private bool m_ShowTreeAndDetailSettings = true; + private bool m_ShowPhysicsSettings = true; + private bool m_ShowGrassWindSettings = true; + + private void MarkDirty() + { + EditorApplication.SetSceneRepaintDirty(); + EditorUtility.SetDirty(m_Terrain); + + if (!EditorApplication.isPlaying) + SceneManagement.EditorSceneManager.MarkSceneDirty(m_Terrain.gameObject.scene); + } + + private void MarkTerrainDataDirty() + { + // In cases where terrain data is embedded in the scene (i.e. it's not an asset), + // we need to dirty the scene if terrainData has changed. + if (!EditorUtility.IsPersistent(m_Terrain.terrainData) && !EditorApplication.isPlaying) + SceneManagement.EditorSceneManager.MarkSceneDirty(m_Terrain.gameObject.scene); + } + public void ShowSettings() { TerrainData terrainData = m_Terrain.terrainData; - EditorGUI.BeginChangeCheck(); - - GUILayout.Label(L10n.Tr("Base Terrain"), EditorStyles.boldLabel); + m_ShowBasicTerrainSettings = EditorGUILayout.FoldoutTitlebar(m_ShowBasicTerrainSettings, styles.basicTerrain, true); + if (m_ShowBasicTerrainSettings) + { + ++EditorGUI.indentLevel; + EditorGUI.BeginChangeCheck(); - m_Terrain.groupingID = EditorGUILayout.IntField(styles.groupingID, m_Terrain.groupingID); + var groupingID = EditorGUILayout.IntField(styles.groupingID, m_Terrain.groupingID); - EditorGUILayout.BeginHorizontal(); - m_Terrain.allowAutoConnect = EditorGUILayout.Toggle(styles.allowAutoConnect, m_Terrain.allowAutoConnect); - if (GUILayout.Button(styles.attemptReconnect)) - Terrain.SetConnectivityDirty(); - EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + var allowAutoConnect = EditorGUILayout.Toggle(styles.allowAutoConnect, m_Terrain.allowAutoConnect); + if (GUILayout.Button(styles.attemptReconnect)) + Terrain.SetConnectivityDirty(); + EditorGUILayout.EndHorizontal(); - m_Terrain.drawHeightmap = EditorGUILayout.Toggle(styles.drawTerrain, m_Terrain.drawHeightmap); - m_Terrain.drawInstanced = EditorGUILayout.Toggle(styles.drawInstancedTerrain, m_Terrain.drawInstanced); - m_Terrain.heightmapPixelError = EditorGUILayout.Slider(styles.pixelError, m_Terrain.heightmapPixelError, 1, 200); // former string formatting: "" - m_Terrain.basemapDistance = EditorGUILayout.Slider(styles.baseMapDist, m_Terrain.basemapDistance, 0, 2000); // former string formatting: "" - m_Terrain.castShadows = EditorGUILayout.Toggle(styles.castShadows, m_Terrain.castShadows); + var drawHeightmap = EditorGUILayout.Toggle(styles.drawTerrain, m_Terrain.drawHeightmap); + var drawInstanced = EditorGUILayout.Toggle(styles.drawInstancedTerrain, m_Terrain.drawInstanced); + var heightmapPixelError = EditorGUILayout.Slider(styles.pixelError, m_Terrain.heightmapPixelError, 1, 200); // former string formatting: "" + var basemapDistance = EditorGUILayout.Slider(styles.baseMapDist, m_Terrain.basemapDistance, 0, 2000); // former string formatting: "" + var castShadows = EditorGUILayout.Toggle(styles.castShadows, m_Terrain.castShadows); - m_Terrain.materialType = (Terrain.MaterialType)EditorGUILayout.EnumPopup(styles.material, m_Terrain.materialType); + var materialType = (Terrain.MaterialType)EditorGUILayout.EnumPopup(styles.material, m_Terrain.materialType); + var materialTemplate = m_Terrain.materialTemplate; - // Make sure we don't reference any custom material if we are to use a built-in shader. - if (m_Terrain.materialType != Terrain.MaterialType.Custom) - m_Terrain.materialTemplate = null; + m_ShowBuiltinSpecularSettings.target = materialType == Terrain.MaterialType.BuiltInLegacySpecular; + m_ShowCustomMaterialSettings.target = materialType == Terrain.MaterialType.Custom; + m_ShowReflectionProbesGUI.target = materialType == Terrain.MaterialType.BuiltInStandard || materialType == Terrain.MaterialType.Custom; - m_ShowBuiltinSpecularSettings.target = m_Terrain.materialType == Terrain.MaterialType.BuiltInLegacySpecular; - m_ShowCustomMaterialSettings.target = m_Terrain.materialType == Terrain.MaterialType.Custom; - m_ShowReflectionProbesGUI.target = m_Terrain.materialType == Terrain.MaterialType.BuiltInStandard || m_Terrain.materialType == Terrain.MaterialType.Custom; + var legacySpecular = m_Terrain.legacySpecular; + var legacyShininess = m_Terrain.legacyShininess; + if (EditorGUILayout.BeginFadeGroup(m_ShowBuiltinSpecularSettings.faded)) + { + EditorGUI.indentLevel++; + legacySpecular = EditorGUILayout.ColorField("Specular Color", legacySpecular); + legacyShininess = EditorGUILayout.Slider("Shininess", legacyShininess, 0.03f, 1.0f); + EditorGUI.indentLevel--; + } + EditorGUILayout.EndFadeGroup(); - if (EditorGUILayout.BeginFadeGroup(m_ShowBuiltinSpecularSettings.faded)) - { - EditorGUI.indentLevel++; - m_Terrain.legacySpecular = EditorGUILayout.ColorField("Specular Color", m_Terrain.legacySpecular); - m_Terrain.legacyShininess = EditorGUILayout.Slider("Shininess", m_Terrain.legacyShininess, 0.03f, 1.0f); - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); + if (EditorGUILayout.BeginFadeGroup(m_ShowCustomMaterialSettings.faded)) + { + EditorGUI.indentLevel++; + materialTemplate = EditorGUILayout.ObjectField("Custom Material", materialTemplate, typeof(Material), false) as Material; - if (EditorGUILayout.BeginFadeGroup(m_ShowCustomMaterialSettings.faded)) - { - EditorGUI.indentLevel++; - m_Terrain.materialTemplate = EditorGUILayout.ObjectField("Custom Material", m_Terrain.materialTemplate, typeof(Material), false) as Material; + // Warn if shader needs tangent basis + if (materialTemplate != null) + { + Shader s = materialTemplate.shader; + if (ShaderUtil.HasTangentChannel(s)) + { + GUIContent c = EditorGUIUtility.TrTextContent("Can't use materials with shaders which need tangent geometry on terrain, use shaders in Nature/Terrain instead."); + EditorGUILayout.HelpBox(c.text, MessageType.Warning, false); + } + } + EditorGUI.indentLevel--; + } + EditorGUILayout.EndFadeGroup(); - // Warn if shader needs tangent basis - if (m_Terrain.materialTemplate != null) + var reflectionProbeUsage = m_Terrain.reflectionProbeUsage; + if (EditorGUILayout.BeginFadeGroup(m_ShowReflectionProbesGUI.faded)) { - Shader s = m_Terrain.materialTemplate.shader; - if (ShaderUtil.HasTangentChannel(s)) + reflectionProbeUsage = (ReflectionProbeUsage)EditorGUILayout.EnumPopup(styles.reflectionProbes, reflectionProbeUsage); + if (reflectionProbeUsage != ReflectionProbeUsage.Off) { - GUIContent c = EditorGUIUtility.TrTextContent("Can't use materials with shaders which need tangent geometry on terrain, use shaders in Nature/Terrain instead."); - EditorGUILayout.HelpBox(c.text, MessageType.Warning, false); + EditorGUI.indentLevel++; + RendererEditorBase.Probes.ShowClosestReflectionProbes(m_BlendInfoList); + EditorGUI.indentLevel--; } } - EditorGUI.indentLevel--; - } - EditorGUILayout.EndFadeGroup(); + EditorGUILayout.EndFadeGroup(); - if (EditorGUILayout.BeginFadeGroup(m_ShowReflectionProbesGUI.faded)) - { - m_Terrain.reflectionProbeUsage = (ReflectionProbeUsage)EditorGUILayout.EnumPopup(styles.reflectionProbes, m_Terrain.reflectionProbeUsage); - if (m_Terrain.reflectionProbeUsage != ReflectionProbeUsage.Off) + if (EditorGUI.EndChangeCheck()) { - EditorGUI.indentLevel++; + Undo.RecordObject(m_Terrain, "Terrain property change"); + + // Make sure we don't reference any custom material if we are to use a built-in shader. + if (materialType != Terrain.MaterialType.Custom) + materialTemplate = null; m_Terrain.GetClosestReflectionProbes(m_BlendInfoList); - RendererEditorBase.Probes.ShowClosestReflectionProbes(m_BlendInfoList); - EditorGUI.indentLevel--; + + m_Terrain.groupingID = groupingID; + m_Terrain.allowAutoConnect = allowAutoConnect; + m_Terrain.drawHeightmap = drawHeightmap; + m_Terrain.drawInstanced = drawInstanced; + m_Terrain.heightmapPixelError = heightmapPixelError; + m_Terrain.basemapDistance = basemapDistance; + m_Terrain.castShadows = castShadows; + m_Terrain.materialType = materialType; + m_Terrain.materialTemplate = materialTemplate; + m_Terrain.legacySpecular = legacySpecular; + m_Terrain.legacyShininess = legacyShininess; + m_Terrain.reflectionProbeUsage = reflectionProbeUsage; + + MarkDirty(); } + --EditorGUI.indentLevel; } - EditorGUILayout.EndFadeGroup(); - - terrainData.thickness = EditorGUILayout.FloatField(styles.thickness, terrainData.thickness); - - GUILayout.Label("Tree & Detail Objects", EditorStyles.boldLabel); - m_Terrain.drawTreesAndFoliage = EditorGUILayout.Toggle(styles.drawTrees, m_Terrain.drawTreesAndFoliage); - m_Terrain.bakeLightProbesForTrees = EditorGUILayout.Toggle(styles.bakeLightProbesForTrees, m_Terrain.bakeLightProbesForTrees); - using (new EditorGUI.DisabledScope(!m_Terrain.bakeLightProbesForTrees)) - m_Terrain.deringLightProbesForTrees = EditorGUILayout.Toggle(styles.deringLightProbesForTrees, m_Terrain.deringLightProbesForTrees); - m_Terrain.preserveTreePrototypeLayers = EditorGUILayout.Toggle(styles.preserveTreePrototypeLayers, m_Terrain.preserveTreePrototypeLayers); - m_Terrain.detailObjectDistance = EditorGUILayout.Slider(styles.detailObjectDistance, m_Terrain.detailObjectDistance, 0, 250); // former string formatting: "" - m_Terrain.collectDetailPatches = EditorGUILayout.Toggle(styles.collectDetailPatches, m_Terrain.collectDetailPatches); - m_Terrain.detailObjectDensity = EditorGUILayout.Slider(styles.detailObjectDensity, m_Terrain.detailObjectDensity, 0.0f, 1.0f); - m_Terrain.treeDistance = EditorGUILayout.Slider(styles.treeDistance, m_Terrain.treeDistance, 0, 2000); // former string formatting: "" - m_Terrain.treeBillboardDistance = EditorGUILayout.Slider(styles.treeBillboardDistance, m_Terrain.treeBillboardDistance, 5, 2000); // former string formatting: "" - m_Terrain.treeCrossFadeLength = EditorGUILayout.Slider(styles.treeCrossFadeLength, m_Terrain.treeCrossFadeLength, 0, 200); // former string formatting: "" - m_Terrain.treeMaximumFullLODCount = EditorGUILayout.IntSlider(styles.treeMaximumFullLODCount, m_Terrain.treeMaximumFullLODCount, 0, 10000); - - // Only do this check once per frame. - if (Event.current.type == EventType.Layout) + + m_ShowTreeAndDetailSettings = EditorGUILayout.FoldoutTitlebar(m_ShowTreeAndDetailSettings, styles.treeAndDetails, true); + if (m_ShowTreeAndDetailSettings) { - m_LODTreePrototypePresent = false; - for (int i = 0; i < terrainData.treePrototypes.Length; ++i) + ++EditorGUI.indentLevel; + EditorGUI.BeginChangeCheck(); + + var drawTreesAndFoliage = EditorGUILayout.Toggle(styles.drawTrees, m_Terrain.drawTreesAndFoliage); + var bakeLightProbesForTrees = EditorGUILayout.Toggle(styles.bakeLightProbesForTrees, m_Terrain.bakeLightProbesForTrees); + var deringLightProbesForTrees = m_Terrain.deringLightProbesForTrees; + using (new EditorGUI.DisabledScope(!bakeLightProbesForTrees)) + deringLightProbesForTrees = EditorGUILayout.Toggle(styles.deringLightProbesForTrees, deringLightProbesForTrees); + var preserveTreePrototypeLayers = EditorGUILayout.Toggle(styles.preserveTreePrototypeLayers, m_Terrain.preserveTreePrototypeLayers); + var detailObjectDistance = EditorGUILayout.Slider(styles.detailObjectDistance, m_Terrain.detailObjectDistance, 0, 250); // former string formatting: "" + var detailObjectDensity = EditorGUILayout.Slider(styles.detailObjectDensity, m_Terrain.detailObjectDensity, 0.0f, 1.0f); + var treeDistance = EditorGUILayout.Slider(styles.treeDistance, m_Terrain.treeDistance, 0, 5000); // former string formatting: "" + var treeBillboardDistance = EditorGUILayout.Slider(styles.treeBillboardDistance, m_Terrain.treeBillboardDistance, 5, 2000); // former string formatting: "" + var treeCrossFadeLength = EditorGUILayout.Slider(styles.treeCrossFadeLength, m_Terrain.treeCrossFadeLength, 0, 200); // former string formatting: "" + var treeMaximumFullLODCount = EditorGUILayout.IntSlider(styles.treeMaximumFullLODCount, m_Terrain.treeMaximumFullLODCount, 0, 10000); + + // Only do this check once per frame. + if (Event.current.type == EventType.Layout) { - if (TerrainEditorUtility.IsLODTreePrototype(terrainData.treePrototypes[i].prefab)) + m_LODTreePrototypePresent = false; + for (int i = 0; i < terrainData.treePrototypes.Length; ++i) { - m_LODTreePrototypePresent = true; - break; + if (TerrainEditorUtility.IsLODTreePrototype(terrainData.treePrototypes[i].prefab)) + { + m_LODTreePrototypePresent = true; + break; + } } } - } - if (m_LODTreePrototypePresent) - EditorGUILayout.HelpBox("Tree Distance, Billboard Start, Fade Length and Max Mesh Trees have no effect on SpeedTree trees. Please use the LOD Group component on the tree prefab to control LOD settings.", MessageType.Info); + if (m_LODTreePrototypePresent) + EditorGUILayout.HelpBox("Tree Distance, Billboard Start, Fade Length and Max Mesh Trees have no effect on SpeedTree trees. Please use the LOD Group component on the tree prefab to control LOD settings.", MessageType.Info); - if (EditorGUI.EndChangeCheck()) + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(m_Terrain, "Terrain property change"); + + m_Terrain.drawTreesAndFoliage = drawTreesAndFoliage; + m_Terrain.bakeLightProbesForTrees = bakeLightProbesForTrees; + m_Terrain.deringLightProbesForTrees = deringLightProbesForTrees; + m_Terrain.preserveTreePrototypeLayers = preserveTreePrototypeLayers; + m_Terrain.detailObjectDistance = detailObjectDistance; + m_Terrain.detailObjectDensity = detailObjectDensity; + m_Terrain.treeDistance = treeDistance; + m_Terrain.treeBillboardDistance = treeBillboardDistance; + m_Terrain.treeCrossFadeLength = treeCrossFadeLength; + m_Terrain.treeMaximumFullLODCount = treeMaximumFullLODCount; + + MarkDirty(); + } + --EditorGUI.indentLevel; + } + + m_ShowPhysicsSettings = EditorGUILayout.FoldoutTitlebar(m_ShowPhysicsSettings, styles.physics, true); + if (m_ShowPhysicsSettings) { - EditorApplication.SetSceneRepaintDirty(); - EditorUtility.SetDirty(m_Terrain); + ++EditorGUI.indentLevel; + EditorGUI.BeginChangeCheck(); + var thickness = EditorGUILayout.FloatField(styles.thickness, terrainData.thickness); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(terrainData, "TerrainData property change"); + terrainData.thickness = thickness; - if (!EditorApplication.isPlaying) - SceneManagement.EditorSceneManager.MarkSceneDirty(m_Terrain.gameObject.scene); + // In cases where terrain data is embedded in the scene (i.e. it's not an asset), + // we need to dirty the scene if terrainData has changed. + if (!EditorUtility.IsPersistent(terrainData) && !EditorApplication.isPlaying) + SceneManagement.EditorSceneManager.MarkSceneDirty(m_Terrain.gameObject.scene); + } + --EditorGUI.indentLevel; } - EditorGUI.BeginChangeCheck(); + m_ShowGrassWindSettings = EditorGUILayout.FoldoutTitlebar(m_ShowGrassWindSettings, styles.grassWindSettings, true); + if (m_ShowGrassWindSettings) + { + ++EditorGUI.indentLevel; + EditorGUI.BeginChangeCheck(); - GUILayout.Label("Wind Settings for Grass", EditorStyles.boldLabel); - float wavingGrassStrength = EditorGUILayout.Slider(styles.wavingGrassStrength, terrainData.wavingGrassStrength, 0, 1); // former string formatting: "%" - float wavingGrassSpeed = EditorGUILayout.Slider(styles.wavingGrassSpeed, terrainData.wavingGrassSpeed, 0, 1); // former string formatting: "%" - float wavingGrassAmount = EditorGUILayout.Slider(styles.wavingGrassAmount, terrainData.wavingGrassAmount, 0, 1); // former string formatting: "%" - Color wavingGrassTint = EditorGUILayout.ColorField(styles.wavingGrassTint, terrainData.wavingGrassTint); + var wavingGrassStrength = EditorGUILayout.Slider(styles.wavingGrassStrength, terrainData.wavingGrassStrength, 0, 1); // former string formatting: "%" + var wavingGrassSpeed = EditorGUILayout.Slider(styles.wavingGrassSpeed, terrainData.wavingGrassSpeed, 0, 1); // former string formatting: "%" + var wavingGrassAmount = EditorGUILayout.Slider(styles.wavingGrassAmount, terrainData.wavingGrassAmount, 0, 1); // former string formatting: "%" + var wavingGrassTint = EditorGUILayout.ColorField(styles.wavingGrassTint, terrainData.wavingGrassTint); - if (EditorGUI.EndChangeCheck()) - { - // Apply terrain settings only when something has changed. Otherwise we needlessly dirty the object and it will show up as modified. - terrainData.wavingGrassStrength = wavingGrassStrength; - terrainData.wavingGrassSpeed = wavingGrassSpeed; - terrainData.wavingGrassAmount = wavingGrassAmount; - terrainData.wavingGrassTint = wavingGrassTint; + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(terrainData, "TerrainData property change"); + + terrainData.wavingGrassStrength = wavingGrassStrength; + terrainData.wavingGrassSpeed = wavingGrassSpeed; + terrainData.wavingGrassAmount = wavingGrassAmount; + terrainData.wavingGrassTint = wavingGrassTint; - // In cases where terrain data is embedded in the scene (i.e. it's not an asset), - // we need to dirty the scene if terrainData has changed. - if (!EditorUtility.IsPersistent(terrainData) && !EditorApplication.isPlaying) - SceneManagement.EditorSceneManager.MarkSceneDirty(m_Terrain.gameObject.scene); + MarkTerrainDataDirty(); + } + --EditorGUI.indentLevel; } - ShowResolution(); + ShowResolution(terrainData); ShowTextures(); RenderLightingFields(); @@ -1498,7 +1588,7 @@ void ResizeControlTexture(int newResolution) Undo.RegisterCompleteObjectUndo(m_Terrain.terrainData, "Resize Heightmap"); - m_Terrain.terrainData.alphamapResolution = newResolution; + td.alphamapResolution = newResolution; for (int i = 0; i < oldAlphaMaps.Length; i++) { RenderTexture.active = oldAlphaMaps[i]; @@ -1539,18 +1629,33 @@ void ResizeHeightmap(int newResolution) Repaint(); } + private bool m_ShowTextures = true; public void ShowTextures() { - GUILayout.Label(styles.textures, EditorStyles.boldLabel); + m_ShowTextures = EditorGUILayout.FoldoutTitlebar(m_ShowTextures, styles.textures, true); + if (!m_ShowTextures) + return; + + ++EditorGUI.indentLevel; + + EditorGUILayout.HelpBox(styles.requireResampling.text, MessageType.Info); GUILayout.BeginVertical(); // base texture GUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); int baseTextureResolution = EditorGUILayout.DelayedIntField(EditorGUIUtility.TrTextContent("Base Texture Resolution", "Resolution of the composite texture used on the terrain when viewed from a distance greater than the Basemap Distance."), m_Terrain.terrainData.baseMapResolution); - baseTextureResolution = Mathf.Clamp(Mathf.ClosestPowerOfTwo(baseTextureResolution), 16, 2048); - if (m_Terrain.terrainData.baseMapResolution != baseTextureResolution) - m_Terrain.terrainData.baseMapResolution = baseTextureResolution; + if (EditorGUI.EndChangeCheck()) + { + baseTextureResolution = Mathf.Clamp(Mathf.ClosestPowerOfTwo(baseTextureResolution), 16, 2048); + if (m_Terrain.terrainData.baseMapResolution != baseTextureResolution) + { + Undo.RecordObject(m_Terrain.terrainData, "TerrainData property change"); + m_Terrain.terrainData.baseMapResolution = baseTextureResolution; + MarkTerrainDataDirty(); + } + } GUILayout.EndHorizontal(); // splatmap control texture @@ -1560,7 +1665,10 @@ public void ShowTextures() m_CurrentControlTextureResolution = EditorGUILayout.IntField(EditorGUIUtility.TrTextContent("Control Texture Resolution", "Resolution of the \"splatmap\" that controls the blending of the different terrain textures."), m_CurrentControlTextureResolution); m_CurrentControlTextureResolution = Mathf.Clamp(Mathf.ClosestPowerOfTwo(m_CurrentControlTextureResolution), 16, 2048); if (m_CurrentControlTextureResolution != m_Terrain.terrainData.alphamapResolution && GUILayout.Button("Resize", GUILayout.Width(128))) + { ResizeControlTexture(m_CurrentControlTextureResolution); + MarkTerrainDataDirty(); + } GUILayout.EndHorizontal(); @@ -1574,7 +1682,10 @@ public void ShowTextures() m_CurrentHeightmapResolution = Mathf.Clamp(m_CurrentHeightmapResolution, kMinimumResolution, kMaximumResolution); m_CurrentHeightmapResolution = m_Terrain.terrainData.GetAdjustedSize(m_CurrentHeightmapResolution); if (m_CurrentHeightmapResolution != m_Terrain.terrainData.heightmapResolution && GUILayout.Button("Resize", GUILayout.Width(128))) + { ResizeHeightmap(m_CurrentHeightmapResolution); + MarkTerrainDataDirty(); + } GUILayout.EndHorizontal(); @@ -1593,18 +1704,26 @@ public void ShowTextures() TerrainMenus.ExportHeightmapRaw(); } GUILayout.EndHorizontal(); + + --EditorGUI.indentLevel; } - public void ShowResolution() + private bool m_ShowResolution = true; + + public void ShowResolution(TerrainData terrainData) { - GUILayout.Label("Mesh Resolutions", EditorStyles.boldLabel); + m_ShowResolution = EditorGUILayout.FoldoutTitlebar(m_ShowResolution, styles.meshResolution, true); + if (!m_ShowResolution) + return; - float terrainWidth = m_Terrain.terrainData.size.x; - float terrainHeight = m_Terrain.terrainData.size.y; - float terrainLength = m_Terrain.terrainData.size.z; - int detailResolution = m_Terrain.terrainData.detailResolution; - int detailPatchCount = m_Terrain.terrainData.detailPatchCount; - int detailResolutionPerPatch = m_Terrain.terrainData.detailResolutionPerPatch; + ++EditorGUI.indentLevel; + + float terrainWidth = terrainData.size.x; + float terrainHeight = terrainData.size.y; + float terrainLength = terrainData.size.z; + int detailResolution = terrainData.detailResolution; + int detailPatchCount = terrainData.detailPatchCount; + int detailResolutionPerPatch = terrainData.detailResolutionPerPatch; EditorGUI.BeginChangeCheck(); @@ -1633,30 +1752,33 @@ public void ShowResolution() if (EditorGUI.EndChangeCheck()) { var undoObjects = new List(); - undoObjects.Add(m_Terrain.terrainData); - undoObjects.AddRange(m_Terrain.terrainData.alphamapTextures); + undoObjects.Add(terrainData); + undoObjects.AddRange(terrainData.alphamapTextures); Undo.RegisterCompleteObjectUndo(undoObjects.ToArray(), "Set Resolution"); - m_Terrain.terrainData.size = new Vector3(terrainWidth, terrainHeight, terrainLength); + terrainData.size = new Vector3(terrainWidth, terrainHeight, terrainLength); - bool resolutionChanged = m_Terrain.terrainData.detailResolution != detailResolution; + bool resolutionChanged = terrainData.detailResolution != detailResolution; if (resolutionChanged) { detailResolutionPerPatch = Mathf.Min(detailResolutionPerPatch, detailResolution); } - bool resolutionPerPatchChanged = m_Terrain.terrainData.detailResolutionPerPatch != detailResolutionPerPatch; + bool resolutionPerPatchChanged = terrainData.detailResolutionPerPatch != detailResolutionPerPatch; if (resolutionPerPatchChanged) { detailResolution = Mathf.Max(detailResolution, detailResolutionPerPatch); } if (resolutionChanged || resolutionPerPatchChanged) - ResizeDetailResolution(m_Terrain.terrainData, detailResolution, detailResolutionPerPatch); + ResizeDetailResolution(terrainData, detailResolution, detailResolutionPerPatch); + MarkTerrainDataDirty(); m_Terrain.Flush(); } + + --EditorGUI.indentLevel; } void ResizeDetailResolution(TerrainData terrainData, int resolution, int resolutionPerPatch) diff --git a/Modules/TerrainEditor/Utilities/TerrainLayerUtility.cs b/Modules/TerrainEditor/Utilities/TerrainLayerUtility.cs index 4dab60e20c..24dbda1c67 100644 --- a/Modules/TerrainEditor/Utilities/TerrainLayerUtility.cs +++ b/Modules/TerrainEditor/Utilities/TerrainLayerUtility.cs @@ -122,14 +122,17 @@ public static void TilingSettingsUI(SerializedProperty tileSize, SerializedPrope EditorGUILayout.PropertyField(tileOffset, s_Styles.tilingOffset); } - internal static int AddTerrainLayer(Terrain terrain, TerrainLayer inputLayer) + internal static void AddTerrainLayer(Terrain terrain, TerrainLayer inputLayer) { + if (inputLayer == null) + return; + var terrainData = terrain.terrainData; var layers = terrainData.terrainLayers; for (var idx = 0; idx < layers.Length; ++idx) { if (layers[idx] == inputLayer) - return idx; + return; } Undo.RegisterCompleteObjectUndo(terrainData, "Add terrain layer"); @@ -139,29 +142,31 @@ internal static int AddTerrainLayer(Terrain terrain, TerrainLayer inputLayer) Array.Copy(layers, 0, newarray, 0, newIndex); newarray[newIndex] = inputLayer; terrainData.terrainLayers = newarray; - EditorUtility.SetDirty(terrain); - return newIndex; } - internal static int ReplaceTerrainLayer(Terrain terrain, int index, TerrainLayer inputLayer) + internal static void ReplaceTerrainLayer(Terrain terrain, int index, TerrainLayer inputLayer) { + if (inputLayer == null) + { + RemoveTerrainLayer(terrain, index); + return; + } + var layers = terrain.terrainData.terrainLayers; // Make sure the selection is legit if (index < 0 || index > layers.Length) - return index; + return; // See if they're already using this layer for (var idx = 0; idx < layers.Length; ++idx) { if (layers[idx] == inputLayer) - return idx; + return; } - Undo.RegisterCompleteObjectUndo(terrain.terrainData, "Add terrain layer"); + Undo.RegisterCompleteObjectUndo(terrain.terrainData, "Replace terrain layer"); layers[index] = inputLayer; - EditorUtility.SetDirty(terrain); terrain.terrainData.terrainLayers = layers; - return index; } internal static void RemoveTerrainLayer(Terrain terrain, int index) diff --git a/Modules/Tilemap/Managed/Tilemap.cs b/Modules/Tilemap/Managed/Tilemap.cs new file mode 100644 index 0000000000..6a7a8dfa68 --- /dev/null +++ b/Modules/Tilemap/Managed/Tilemap.cs @@ -0,0 +1,68 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace UnityEngine.Tilemaps +{ + public partial class Tilemap + { + internal static event Action tilemapTileChanged; + + private Dictionary m_SyncTileBuffer; + private Dictionary syncTileBuffer + { + get + { + if (m_SyncTileBuffer == null) + m_SyncTileBuffer = new Dictionary(); + return m_SyncTileBuffer; + } + } + + private bool m_BufferSyncTile; + internal bool bufferSyncTile + { + get { return m_BufferSyncTile; } + set + { + if (value == false && m_BufferSyncTile != value && HasSyncTileCallback() && syncTileBuffer.Count > 0) + SendTilemapTileChangedCallback(syncTileBuffer.Values.ToArray()); + syncTileBuffer.Clear(); + m_BufferSyncTile = value; + } + } + + private void HandleSyncTileCallback(SyncTile[] syncTiles) + { + if (bufferSyncTile) + { + foreach (var syncTile in syncTiles) + { + syncTileBuffer[syncTile.m_Position] = syncTile; + } + return; + } + SendTilemapTileChangedCallback(syncTiles); + } + + private void SendTilemapTileChangedCallback(SyncTile[] syncTiles) + { + Tilemap.tilemapTileChanged(this, syncTiles); + } + + internal static void SetSyncTileCallback(Action callback) + { + Tilemap.tilemapTileChanged += callback; + } + + internal static void RemoveSyncTileCallback(Action callback) + { + Tilemap.tilemapTileChanged -= callback; + } + + } +} diff --git a/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs b/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs index 26d704374f..57e57ea122 100644 --- a/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs +++ b/Modules/Tilemap/ScriptBindings/Tilemap.bindings.cs @@ -267,20 +267,8 @@ internal struct SyncTile public TileData m_TileData; } - internal static event Action tilemapTileChanged; - - internal static void SetSyncTileCallback(Action callback) - { - Tilemap.tilemapTileChanged += callback; - } - - internal static void RemoveSyncTileCallback(Action callback) - { - Tilemap.tilemapTileChanged -= callback; - } - [RequiredByNativeCode] - private static bool HasSyncTileCallback() + internal static bool HasSyncTileCallback() { return (Tilemap.tilemapTileChanged != null); } @@ -291,7 +279,7 @@ private void DoSyncTileCallback(SyncTile[] syncTiles) if (Tilemap.tilemapTileChanged == null) return; - Tilemap.tilemapTileChanged(this, syncTiles); + HandleSyncTileCallback(syncTiles); } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs index 72ceacb7d1..0884a9b13d 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditorBase.cs @@ -4,6 +4,7 @@ using UnityEditorInternal; using UnityEngine; +using UnityEngine.Tilemaps; namespace UnityEditor { @@ -35,6 +36,28 @@ public virtual void OnToolDeactivated(GridBrushBase.Tool tool) {} public virtual void RegisterUndo(GameObject brushTarget, GridBrushBase.Tool tool) {} public virtual GameObject[] validTargets { get { return null; } } + internal void OnEditStart(GridLayout gridLayout, GameObject brushTarget) + { + SetBufferSyncTile(brushTarget, true); + } + + internal void OnEditEnd(GridLayout gridLayout, GameObject brushTarget) + { + SetBufferSyncTile(brushTarget, false); + } + + private void SetBufferSyncTile(GameObject brushTarget, bool active) + { + if (brushTarget == null || !Tilemap.HasSyncTileCallback()) + return; + + var tilemaps = brushTarget.GetComponentsInChildren(); + foreach (var tilemap in tilemaps) + { + tilemap.bufferSyncTile = active; + } + } + internal static void OnPaintSceneGUIInternal(GridLayout gridLayout, GameObject brushTarget, BoundsInt position, GridBrushBase.Tool tool, bool executing) { if (Event.current.type != EventType.Repaint) diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs index 72dfeac3c6..684f118bdb 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableGrid.cs @@ -42,6 +42,9 @@ protected virtual void OnBrushPickDragged(BoundsInt position) {} protected virtual void OnBrushPickCancelled() {} + protected virtual void OnEditStart() {} + protected virtual void OnEditEnd() {} + internal static PaintableGrid s_LastActivePaintableGrid; private Vector2Int m_PreviousMouseGridPosition; @@ -61,7 +64,22 @@ protected virtual void OnBrushPickCancelled() {} 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; } } + protected bool executing + { + get { return m_IsExecuting; } + set + { + var isExecuting = value && isHotControl; + if (isExecuting != m_IsExecuting) + { + if (isExecuting) + OnEditStart(); + else + OnEditEnd(); + } + m_IsExecuting = isExecuting; + } + } protected bool isHotControl { get { return GUIUtility.hotControl == m_PermanentControlID; } } protected bool mouseGridPositionChanged { get { return m_MouseGridPositionChanged; } } @@ -341,6 +359,8 @@ private void HandleBrushPaintAndErase() { case EventType.MouseDown: RegisterUndo(); + GUIUtility.hotControl = m_PermanentControlID; + executing = true; if (IsErasingEvent(evt)) { if (EditMode.editMode != EditMode.SceneViewEditMode.GridEraser) @@ -353,13 +373,11 @@ private void HandleBrushPaintAndErase() EditMode.ChangeEditMode(EditMode.SceneViewEditMode.GridPainting, GridPaintingState.instance); Paint(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); } - Event.current.Use(); - GUIUtility.hotControl = m_PermanentControlID; GUI.changed = true; - executing = true; break; case EventType.MouseDrag: + executing = true; if (isHotControl && mouseGridPositionChanged) { List points = GridEditorUtility.GetPointsOnLine(m_PreviousMouseGridPosition, mouseGridPosition).ToList(); @@ -376,7 +394,6 @@ private void HandleBrushPaintAndErase() Event.current.Use(); GUI.changed = true; } - executing = true; break; case EventType.MouseUp: executing = false; @@ -422,9 +439,9 @@ private void HandleFloodFill() } if (evt.type == EventType.MouseUp && evt.button == 0 && isHotControl) { - executing = false; RegisterUndo(); FloodFill(new Vector3Int(mouseGridPosition.x, mouseGridPosition.y, zPosition)); + executing = false; GUI.changed = true; Event.current.Use(); GUIUtility.hotControl = 0; diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs index a538cc4e38..709fefa3b6 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/PaintableSceneViewGrid.cs @@ -230,6 +230,18 @@ protected override void MoveEnd(BoundsInt position) gridBrush.MoveEnd(grid, brushTarget, position); } + protected override void OnEditStart() + { + if (GridPaintingState.activeBrushEditor != null && grid != null) + GridPaintingState.activeBrushEditor.OnEditStart(grid, brushTarget); + } + + protected override void OnEditEnd() + { + if (GridPaintingState.activeBrushEditor != null && grid != null) + GridPaintingState.activeBrushEditor.OnEditEnd(grid, brushTarget); + } + protected override void ClearGridSelection() { GridSelection.Clear(); diff --git a/Modules/UIElements/Events/EventBase.cs b/Modules/UIElements/Events/EventBase.cs index 3eeed766e9..9e2a3f5c47 100644 --- a/Modules/UIElements/Events/EventBase.cs +++ b/Modules/UIElements/Events/EventBase.cs @@ -240,7 +240,7 @@ protected set protected virtual void Init() { - timestamp = DateTime.Now.Ticks; + timestamp = (long)(Time.realtimeSinceStartup * 1000.0f); flags = EventFlags.None; diff --git a/Modules/VideoEditor/Editor/VideoPlayerEditor.cs b/Modules/VideoEditor/Editor/VideoPlayerEditor.cs index b1a31cab40..28d89d82d7 100644 --- a/Modules/VideoEditor/Editor/VideoPlayerEditor.cs +++ b/Modules/VideoEditor/Editor/VideoPlayerEditor.cs @@ -98,6 +98,8 @@ class Styles "Audio controls not editable when using muliple selection."; public readonly string enableDecodingTooltip = "Enable decoding for this track. Only effective when not playing. When playing from a URL, track details are shown only while playing back."; + + public static readonly int ObjectFieldControlID = "VideoPlayerAudioSourceObjectFieldHash".GetHashCode(); } internal class AudioTrackInfo @@ -600,9 +602,21 @@ private void HandleAudio() EditorGUI.indentLevel++; if (audioOutputMode == VideoAudioOutputMode.AudioSource) { - EditorGUILayout.PropertyField( - m_TargetAudioSources.GetArrayElementAtIndex(trackIdx), - s_Styles.audioSourceContent); + var property = m_TargetAudioSources.GetArrayElementAtIndex(trackIdx); + Rect rect = EditorGUILayout.GetControlRect(); + int id = GUIUtility.GetControlID(Styles.ObjectFieldControlID, FocusType.Keyboard, rect); + var label = EditorGUI.BeginProperty(rect, s_Styles.audioSourceContent, property); + rect = EditorGUI.PrefixLabel(rect, id, label); + EditorGUI.BeginChangeCheck(); + + var result = EditorGUI.DoObjectField(rect, rect, id, property.objectReferenceValue, typeof(AudioSource), null, null, true, EditorStyles.objectField); + if (EditorGUI.EndChangeCheck()) + { + if (!EditorUtility.IsPersistent(result)) + property.objectReferenceValue = result; + else + Debug.LogWarning("Invalid AudioSource for VideoPlayer. Use an instance of an AudioSource in the scene."); + } } else if (audioOutputMode == VideoAudioOutputMode.Direct) { diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index 4adac421dd..2a0a6ac75d 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -3087,6 +3087,9 @@ Editor\Mono\Scripting\Compilers\CompilerOutputParserBase.cs + + Editor\Mono\Scripting\Compilers\CompilerSpecificReponseFiles.cs + Editor\Mono\Scripting\Compilers\Il2CppOutputParser.cs @@ -3096,18 +3099,27 @@ Editor\Mono\Scripting\Compilers\MicrosoftCSharpCompilerOutputParser.cs + + Editor\Mono\Scripting\Compilers\MicrosoftCSharpResponseFileProvider.cs + Editor\Mono\Scripting\Compilers\MonoCSharpCompiler.cs Editor\Mono\Scripting\Compilers\MonoCSharpCompilerOutputParser.cs + + Editor\Mono\Scripting\Compilers\MonoCSharpResponseFileProvider.cs + Editor\Mono\Scripting\Compilers\MonoScriptCompilerBase.cs Editor\Mono\Scripting\Compilers\NuGetPackageResolver.cs + + Editor\Mono\Scripting\Compilers\ResponseFileProvider.cs + Editor\Mono\Scripting\Compilers\ScriptCompilerBase.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index bfcca14532..9c7516da88 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -1551,6 +1551,9 @@ Modules\Tilemap\Managed\TileBase.cs + + Modules\Tilemap\Managed\Tilemap.cs + Modules\Tilemap\ScriptBindings\Tilemap.bindings.cs diff --git a/README.md b/README.md index 32870e8a99..71397c489f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b8 C# reference source code +## Unity 2018.3.0b9 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/VR/HoloLens/ScriptBindings/PhotoCapture.bindings.cs b/Runtime/VR/HoloLens/ScriptBindings/PhotoCapture.bindings.cs index 5b6b4e2b01..738356ebf7 100644 --- a/Runtime/VR/HoloLens/ScriptBindings/PhotoCapture.bindings.cs +++ b/Runtime/VR/HoloLens/ScriptBindings/PhotoCapture.bindings.cs @@ -294,7 +294,7 @@ public void Dispose() public sealed class PhotoCaptureFrame : IDisposable { #pragma warning disable 169 - private IntPtr m_NativePtr; + internal IntPtr m_NativePtr; public int dataLength { get; private set; } From b59a19d33f58bc6cf69aa2f295afc8d16f81bbc2 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 14 Nov 2018 13:35:56 +0000 Subject: [PATCH 08/10] Unity 2018.3.0b10 C# reference source code --- .../2D/SpriteAtlas/SpriteAtlasInspector.cs | 2 +- .../SpriteFrameModuleBase.cs | 1 + .../SpriteFrameModuleBaseView.cs | 16 +- .../Animation/AnimationWindow/AnimEditor.cs | 74 +++----- .../AnimationWindow/AnimationWindow.cs | 8 + .../Animation/AnimationWindow/CurveEditor.cs | 27 ++- .../AnimationWindow/CurveEditorSettings.cs | 1 + Editor/Mono/AssetStore/AssetStoreWindow.cs | 3 +- Editor/Mono/CustomInspectorStubs.cs | 24 +-- .../AssemblyDefinitionImporterInspector.cs | 14 +- .../Mono/Inspector/AudioManagerInspector.cs | 7 +- .../Mono/Inspector/EditorSettingsInspector.cs | 5 +- .../Inspector/GraphicsSettingsInspector.cs | 28 +-- Editor/Mono/Inspector/InspectorWindow.cs | 16 +- Editor/Mono/Inspector/MonoScriptInspector.cs | 2 +- .../Inspector/Physics2DSettingsInspector.cs | 8 +- .../Mono/Inspector/PhysicsManagerInspector.cs | 16 +- .../PlayerSettingsEditor.cs | 13 +- .../Mono/Inspector/QualitySettingsEditor.cs | 9 +- .../ScriptExecutionOrderInspector.cs | 9 +- Editor/Mono/Inspector/TagManagerInspector.cs | 8 +- Editor/Mono/Inspector/TimeManagerInspector.cs | 11 +- .../Modules/DefaultCompilationExtension.cs | 3 +- Editor/Mono/Modules/PlatformSupportModule.cs | 3 +- Editor/Mono/Prefabs/PrefabUtility.cs | 39 +++-- .../CacheServerPreferences.cs | 6 +- .../DiagnosticsSwitchPreferences.cs | 3 +- .../PreferencesSettingsProviders.cs | 62 ++++--- .../Mono/Scripting/Compilers/BooLanguage.cs | 3 +- .../Scripting/Compilers/CSharpLanguage.cs | 27 ++- .../Scripting/Compilers/SupportedLanguage.cs | 10 +- .../Compilers/UnityScriptLanguage.cs | 4 +- .../ScriptCompilation/CompilationTask.cs | 2 +- .../ScriptCompilation/EditorBuildRules.cs | 9 +- .../ScriptCompilation/EditorCompilation.cs | 10 +- .../ScriptCompilation/MonoLibraryHelpers.cs | 4 +- .../Scripting/ScriptCompilation/WSAHelpers.cs | 4 +- Editor/Mono/Scripting/ScriptCompilers.cs | 5 +- Editor/Mono/Settings.cs | 12 +- .../Providers/AssetSettingsProvider.cs | 96 +++++++---- Editor/Mono/Settings/SettingsProvider.cs | 108 +++++++----- .../Settings/SettingsProviderAttribute.cs | 5 +- Editor/Mono/Settings/SettingsService.cs | 30 +++- Editor/Mono/Settings/SettingsWindow.cs | 48 ++---- Editor/Mono/Sprites/SpritePackerWindow.cs | 2 +- Editor/Mono/SyncRiderProject.cs | 20 +-- .../Mono/VersionControl/UI/VCWindowPending.cs | 2 +- .../SolutionSynchronizer.cs | 12 +- Modules/IMGUI/Event.cs | 14 +- Modules/PresetsEditor/PresetManagerEditor.cs | 8 +- .../MemoryProfiler/MemorySnapshot.cs | 150 +++++++++++++++- .../MemorySnapshotFileWriter.bindings.cs | 5 +- .../ProfilerWindow/MemorySnapshot.cs | 2 +- Modules/ShortcutManagerEditor/Directory.cs | 73 ++++---- .../ShortcutManagerEditor/KeyCombination.cs | 160 +++++++++++++++++- .../ShortcutAttribute.cs | 9 +- .../ShortcutAttributeDiscoveryProvider.cs | 7 +- .../ShortcutProfileManager.cs | 19 ++- .../Editor/Managed/Grid/GridBrushEditor.cs | 6 +- .../Managed/Grid/GridPaintPaletteWindow.cs | 8 +- README.md | 2 +- Runtime/Export/Director/FrameData.cs | 26 ++- .../Scripting/GarbageCollector.bindings.cs | 2 +- Runtime/Export/SystemInfo.bindings.cs | 8 + .../MemoryProfiling.bindings.cs | 4 +- .../Editor/ModuleMetadataBindings.gen.cs | 4 + 66 files changed, 865 insertions(+), 473 deletions(-) diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs index 90218d3f3e..1a156d99e8 100644 --- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs +++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasInspector.cs @@ -313,7 +313,7 @@ public override void OnInspectorGUI() { if (GUILayout.Button(s_Styles.disabledPackLabel, EditorStyles.helpBox)) { - SettingsWindow.OpenProjectSettings("Project/Editor"); + SettingsService.OpenProjectSettings("Project/Editor"); } } diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs index 361b67d876..ce7303068c 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs @@ -327,6 +327,7 @@ private void UndoCallback() protected static Rect ClampSpriteRect(Rect rect, float maxX, float maxY) { // Clamp rect to width height + rect = FlipNegativeRect(rect); Rect newRect = new Rect(); newRect.xMin = Mathf.Clamp(rect.xMin, 0, maxX - 1); diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs index 5415fd398d..88032fbc9d 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBaseView.cs @@ -108,6 +108,14 @@ private void RemoveMainUI(VisualElement mainView) mainView.UnregisterCallback(SelectionChange); } + private void UpdatePositionField(Rect rect) + { + m_PositionFieldX.SetValueWithoutNotify((long)selectedSpriteRect.x); + m_PositionFieldY.SetValueWithoutNotify((long)selectedSpriteRect.y); + m_PositionFieldW.SetValueWithoutNotify((long)selectedSpriteRect.width); + m_PositionFieldH.SetValueWithoutNotify((long)selectedSpriteRect.height); + } + private void AddMainUI(VisualElement mainView) { var visualTree = EditorGUIUtility.Load("UXML/SpriteEditor/SpriteFrameModuleInspector.uxml") as VisualTreeAsset; @@ -141,7 +149,7 @@ private void AddMainUI(VisualElement mainView) var rect = selectedSpriteRect; rect.x = evt.newValue; selectedSpriteRect = rect; - m_PositionFieldX.SetValueWithoutNotify((long)selectedSpriteRect.x); + UpdatePositionField(selectedSpriteRect); } }); @@ -153,7 +161,7 @@ private void AddMainUI(VisualElement mainView) var rect = selectedSpriteRect; rect.y = evt.newValue; selectedSpriteRect = rect; - m_PositionFieldY.SetValueWithoutNotify((long)selectedSpriteRect.y); + UpdatePositionField(selectedSpriteRect); } }); @@ -165,7 +173,7 @@ private void AddMainUI(VisualElement mainView) var rect = selectedSpriteRect; rect.width = evt.newValue; selectedSpriteRect = rect; - m_PositionFieldW.SetValueWithoutNotify((long)selectedSpriteRect.width); + UpdatePositionField(selectedSpriteRect); } }); @@ -177,7 +185,7 @@ private void AddMainUI(VisualElement mainView) var rect = selectedSpriteRect; rect.height = evt.newValue; selectedSpriteRect = rect; - m_PositionFieldH.SetValueWithoutNotify((long)selectedSpriteRect.height); + UpdatePositionField(selectedSpriteRect); } }); diff --git a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs index b996775768..45819ae070 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs @@ -22,25 +22,6 @@ internal enum WrapModeFixed PingPong = (int)WrapMode.PingPong } - class AnimationShortcutContex : IShortcutToolContext - { - AnimEditor m_AnimEditor; - public AnimationShortcutContex(AnimEditor animEditor) - { - m_AnimEditor = animEditor; - } - - public bool active - { - get { return !animEditor.stateDisabled && !animEditor.state.animatorIsOptimized; } - } - - public AnimEditor animEditor - { - get { return m_AnimEditor; } - } - } - internal class AnimEditor : ScriptableObject { // Active Animation windows @@ -102,8 +83,6 @@ static private Color inRangeColor } } - AnimationShortcutContex m_AnimationShortcutContex; - internal const int kSliderThickness = 15; internal const int kLayoutRowHeight = EditorGUI.kWindowToolbarHeight + 1; internal const int kIntFieldWidth = 35; @@ -356,9 +335,6 @@ public void OnEnable() m_CurveEditor.curvesUpdated += SaveChangedCurvesFromCurveEditor; m_CurveEditor.OnEnable(); - - m_AnimationShortcutContex = new AnimationShortcutContex(this); - ShortcutIntegration.instance.contextManager.RegisterToolContext(m_AnimationShortcutContex); } public void OnDisable() @@ -375,7 +351,6 @@ public void OnDisable() m_DopeSheet.OnDisable(); m_State.OnDisable(); - ShortcutIntegration.instance.contextManager.DeregisterToolContext(m_AnimationShortcutContex); } public void OnDestroy() @@ -729,10 +704,13 @@ private void LinkOptionsOnGUI() static void ExecuteShortcut(ShortcutArguments args, Action exp) { - var animEditorContext = (AnimationShortcutContex)args.context; - var animEditor = animEditorContext.animEditor; + var animationWindow = (AnimationWindow)args.context; + var animEditor = animationWindow.animEditor; + + if (EditorWindow.focusedWindow != animationWindow) + return; - if (EditorWindow.focusedWindow != animEditor.m_OwnerWindow) + if (animEditor.stateDisabled || animEditor.state.animatorIsOptimized) return; exp(animEditor); @@ -746,14 +724,14 @@ static void ExecuteShortcut(ShortcutArguments args, Action { animEditor.SwitchBetweenCurvesAndDopesheet(); }); } [FormerlyPrefKeyAs("Animation/Play Animation", " ")] - [Shortcut("Animation/Play Animation", typeof(AnimationShortcutContex), " ")] + [Shortcut("Animation/Play Animation", typeof(AnimationWindow), " ")] static void TogglePlayAnimation(ShortcutArguments args) { ExecuteShortcut(args, controlInterface => @@ -766,76 +744,75 @@ static void TogglePlayAnimation(ShortcutArguments args) } [FormerlyPrefKeyAs("Animation/Next Frame", ".")] - [Shortcut("Animation/Next Frame", typeof(AnimationShortcutContex), ".")] + [Shortcut("Animation/Next Frame", typeof(AnimationWindow), ".")] static void NextFrame(ShortcutArguments args) { ExecuteShortcut(args, controlInterface => controlInterface.GoToNextFrame()); } [FormerlyPrefKeyAs("Animation/Previous Frame", ",")] - [Shortcut("Animation/Previous Frame", typeof(AnimationShortcutContex), ",")] + [Shortcut("Animation/Previous Frame", typeof(AnimationWindow), ",")] static void PreviousFrame(ShortcutArguments args) { ExecuteShortcut(args, controlInterface => controlInterface.GoToPreviousFrame()); } [FormerlyPrefKeyAs("Animation/Previous Keyframe", "&,")] - [Shortcut("Animation/Previous Keyframe", typeof(AnimationShortcutContex), "&,")] + [Shortcut("Animation/Previous Keyframe", typeof(AnimationWindow), "&,")] static void PreviousKeyFrame(ShortcutArguments args) { ExecuteShortcut(args, controlInterface => controlInterface.GoToPreviousKeyframe()); } [FormerlyPrefKeyAs("Animation/Next Keyframe", "&.")] - [Shortcut("Animation/Next Keyframe", typeof(AnimationShortcutContex), "&.")] + [Shortcut("Animation/Next Keyframe", typeof(AnimationWindow), "&.")] static void NextKeyFrame(ShortcutArguments args) { ExecuteShortcut(args, controlInterface => controlInterface.GoToNextKeyframe()); } [FormerlyPrefKeyAs("Animation/First Keyframe", "#,")] - [Shortcut("Animation/First Keyframe", typeof(AnimationShortcutContex), "#,")] + [Shortcut("Animation/First Keyframe", typeof(AnimationWindow), "#,")] static void FirstKeyFrame(ShortcutArguments args) { ExecuteShortcut(args, controlInterface => controlInterface.GoToFirstKeyframe()); } [FormerlyPrefKeyAs("Animation/Last Keyframe", "#.")] - [Shortcut("Animation/Last Keyframe", typeof(AnimationShortcutContex), "#.")] + [Shortcut("Animation/Last Keyframe", typeof(AnimationWindow), "#.")] static void LastKeyFrame(ShortcutArguments args) { ExecuteShortcut(args, controlInterface => controlInterface.GoToLastKeyframe()); } [FormerlyPrefKeyAs("Animation/Key Selected", "k")] - [Shortcut("Animation/Key Selected", typeof(AnimationShortcutContex), "k")] + [Shortcut("Animation/Key Selected", null, "k")] static void KeySelected(ShortcutArguments args) { - var animEditorContext = (AnimationShortcutContex)args.context; - var animEditor = animEditorContext.animEditor; - - if (!animEditor.m_State.previewing) + AnimationWindow animationWindow = AnimationWindow.GetAllAnimationWindows().Find(aw => (aw.state.previewing || aw == EditorWindow.focusedWindow)); + if (animationWindow == null) return; + var animEditor = animationWindow.animEditor; + animEditor.SaveCurveEditorKeySelection(); AnimationWindowUtility.AddSelectedKeyframes(animEditor.m_State, animEditor.controlInterface.time); - if (!animEditor.m_OwnerWindow.hasFocus) - animEditor.controlInterface.ClearCandidates(); + animEditor.controlInterface.ClearCandidates(); animEditor.UpdateSelectedKeysToCurveEditor(); animEditor.Repaint(); } [FormerlyPrefKeyAs("Animation/Key Modified", "#k")] - [Shortcut("Animation/Key Modified", typeof(AnimationShortcutContex), "#k")] + [Shortcut("Animation/Key Modified", null, "#k")] static void KeyModified(ShortcutArguments args) { - var animEditorContext = (AnimationShortcutContex)args.context; - var animEditor = animEditorContext.animEditor; - - if (!animEditor.m_State.previewing) + AnimationWindow animationWindow = AnimationWindow.GetAllAnimationWindows().Find(aw => (aw.state.previewing || aw == EditorWindow.focusedWindow)); + if (animationWindow == null) return; + var animEditor = animationWindow.animEditor; + animEditor.SaveCurveEditorKeySelection(); animEditor.controlInterface.ProcessCandidates(); animEditor.UpdateSelectedKeysToCurveEditor(); @@ -1226,6 +1203,7 @@ private void InitializeCurveEditor() settings.allowDeleteLastKeyInCurve = true; settings.rectangleToolFlags = CurveEditorSettings.RectangleToolFlags.FullRectangleTool; settings.undoRedoSelection = true; + settings.flushCurveCache = false; // Curve Wrappers are cached in AnimationWindowState. m_CurveEditor.shownArea = new Rect(1, 1, 1, 1); m_CurveEditor.settings = settings; diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs index 3c0725eb9f..a4325c07c7 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs @@ -31,6 +31,14 @@ internal class AnimationWindow : EditorWindow, IHasCustomMenu private GUIContent m_DefaultTitleContent; private GUIContent m_RecordTitleContent; + internal AnimEditor animEditor + { + get + { + return m_AnimEditor; + } + } + internal AnimationWindowState state { get diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs index 148c5711eb..69801785a6 100644 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs +++ b/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs @@ -51,13 +51,6 @@ public CurveWrapper() setAxisUiScalarsCallback = null; } - // Fix for case 1086532 - Audio source inspector leaks memory - ~CurveWrapper() - { - if (m_Renderer != null) - m_Renderer.FlushCache(); - } - internal enum SelectionMode { None = 0, @@ -231,6 +224,8 @@ public CurveWrapper[] animationCurves } set { + FlushCurvesCache(); + m_AnimationCurves = value; curveIDToIndexMap.Clear(); @@ -259,6 +254,22 @@ public bool GetTopMostCurveID(out int curveID) return false; } + void FlushCurvesCache() + { + if (!settings.flushCurveCache) + return; + + if (m_AnimationCurves == null) + return; + + for (int i = 0; i < m_AnimationCurves.Length; ++i) + { + CurveWrapper curveWrapper = m_AnimationCurves[i]; + if (curveWrapper.renderer != null) + curveWrapper.renderer.FlushCache(); + } + } + private List m_DrawOrder = new List(); // contains curveIds (last element topmost) void SyncDrawOrder() { @@ -605,6 +616,8 @@ public void OnDisable() if (m_PointRenderer != null) m_PointRenderer.FlushCache(); + + FlushCurvesCache(); } public void OnDestroy() diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs index 46bb57a439..af5e63bd11 100644 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs +++ b/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs @@ -53,6 +53,7 @@ public bool hasUnboundedRanges public bool allowDraggingCurvesAndRegions = true; public bool allowDeleteLastKeyInCurve = false; public bool undoRedoSelection = false; + public bool flushCurveCache = true; public string xAxisLabel = L10n.Tr("time"); public string yAxisLabel = L10n.Tr("value"); public Vector2 curveRegionDomain = new Vector2(0, 1); // X axis range in which to draw the shaded curve region between 2 curves. diff --git a/Editor/Mono/AssetStore/AssetStoreWindow.cs b/Editor/Mono/AssetStore/AssetStoreWindow.cs index 1deca88670..54fb59bc86 100644 --- a/Editor/Mono/AssetStore/AssetStoreWindow.cs +++ b/Editor/Mono/AssetStore/AssetStoreWindow.cs @@ -30,7 +30,8 @@ public static void OpenURL(string url) } // Use this for initialization - [MenuItem("Window/General/Asset Store %9", false, 301)] + // Index at 1499 because "Package Manager" is 1500, pairing tools for user to get external content + [MenuItem("Window/Asset Store %9", false, 1499)] public static AssetStoreWindow Init() { AssetStoreWindow window = EditorWindow.GetWindow(typeof(SceneView)); diff --git a/Editor/Mono/CustomInspectorStubs.cs b/Editor/Mono/CustomInspectorStubs.cs index 17df87122a..824cd94150 100644 --- a/Editor/Mono/CustomInspectorStubs.cs +++ b/Editor/Mono/CustomInspectorStubs.cs @@ -2,7 +2,6 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using System.Linq; using UnityEngine; using UnityEditorInternal; using UnityEngine.Bindings; @@ -50,8 +49,9 @@ private VFXManager() [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/VFX", "ProjectSettings/VFXManager.asset"); - SettingsProvider.GetSearchKeywordsFromSerializedObject(provider.CreateEditor().serializedObject, provider.keywords); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/VFX", "ProjectSettings/VFXManager.asset", + SettingsProvider.GetSearchKeywordsFromPath("ProjectSettings/VFXManager.asset")); return provider; } } @@ -65,13 +65,9 @@ private InputManager() {} [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Input", "ProjectSettings/InputManager.asset") - { - icon = EditorGUIUtility.FindTexture("UnityEngine/EventSystems/StandaloneInputModule Icon") - }; - - SettingsProvider.GetSearchKeywordsFromSerializedObject(provider.CreateEditor().serializedObject, provider.keywords); - + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Input", "ProjectSettings/InputManager.asset", + SettingsProvider.GetSearchKeywordsFromPath("ProjectSettings/InputManager.asset")); return provider; } } @@ -94,13 +90,5 @@ private UnityConnectSettings() {} internal sealed class ClusterInputSettings { private ClusterInputSettings() {} - - [SettingsProvider] - internal static SettingsProvider CreateProjectSettingsProvider() - { - var provider = new AssetSettingsProvider("Project/Cluster Input", "ProjectSettings/ClusterInputManager.asset"); - SettingsProvider.GetSearchKeywordsFromSerializedObject(provider.CreateEditor().serializedObject, provider.keywords); - return provider; - } } } diff --git a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs b/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs index bfc80f31fa..6d1484942e 100644 --- a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs +++ b/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs @@ -450,31 +450,39 @@ void LoadAssemblyDefinitionFiles() UpdateCombinedCompatibility(); - m_ReferencesList = new ReorderableList(m_State.references, typeof(AssemblyDefinitionReference), false, false, true, true); + m_ReferencesList = new ReorderableList(m_State.references, typeof(AssemblyDefinitionReference), true, false, true, true); m_ReferencesList.drawElementCallback = DrawReferenceListElement; m_ReferencesList.onAddCallback = AddReferenceListElement; m_ReferencesList.onRemoveCallback = RemoveReferenceListElement; + m_ReferencesList.onReorderCallback = ReorderableListChanged; m_ReferencesList.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; m_ReferencesList.headerHeight = 3; - m_DefineConstraints = new ReorderableList(m_State.defineConstraints, typeof(DefineConstraint), false, false, true, true); + m_DefineConstraints = new ReorderableList(m_State.defineConstraints, typeof(DefineConstraint), true, false, true, true); m_DefineConstraints.drawElementCallback = DrawDefineConstraintListElement; m_DefineConstraints.onAddCallback = AddDefineConstraintListElement; m_DefineConstraints.onRemoveCallback = RemoveDefineConstraintListElement; + m_DefineConstraints.onReorderCallback = ReorderableListChanged; m_DefineConstraints.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; m_DefineConstraints.headerHeight = 3; - m_PrecompiledReferencesList = new ReorderableList(m_State.precompiledReferences, typeof(PrecompiledReference), false, false, true, true); + m_PrecompiledReferencesList = new ReorderableList(m_State.precompiledReferences, typeof(PrecompiledReference), true, false, true, true); m_PrecompiledReferencesList.drawElementCallback = DrawPrecompiledReferenceListElement; m_PrecompiledReferencesList.onAddCallback = AddPrecompiledReferenceListElement; m_PrecompiledReferencesList.onRemoveCallback = RemovePrecompiledReferenceListElement; + m_PrecompiledReferencesList.onReorderCallback = ReorderableListChanged; m_PrecompiledReferencesList.elementHeight = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; m_PrecompiledReferencesList.headerHeight = 3; } + void ReorderableListChanged(ReorderableList list) + { + m_State.modified = true; + } + private void DrawDefineConstraintListElement(Rect rect, int index, bool isactive, bool isfocused) { var list = m_DefineConstraints.list; diff --git a/Editor/Mono/Inspector/AudioManagerInspector.cs b/Editor/Mono/Inspector/AudioManagerInspector.cs index 854a21e5c8..1e8868d7f3 100644 --- a/Editor/Mono/Inspector/AudioManagerInspector.cs +++ b/Editor/Mono/Inspector/AudioManagerInspector.cs @@ -3,7 +3,6 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using UnityEngine; -using UnityEditor; using UnityEditorInternal; using System.Collections.Generic; @@ -133,9 +132,9 @@ public override void OnInspectorGUI() [SettingsProvider] static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Audio", "ProjectSettings/AudioManager.asset"); - provider.icon = EditorGUIUtility.IconContent("Audio Mixer").image as Texture2D; - provider.PopulateSearchKeywordsFromGUIContentProperties(); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Audio", "ProjectSettings/AudioManager.asset", + SettingsProvider.GetSearchKeywordsFromGUIContentProperties()); return provider; } } diff --git a/Editor/Mono/Inspector/EditorSettingsInspector.cs b/Editor/Mono/Inspector/EditorSettingsInspector.cs index 3c2c932edf..e255eca6c1 100644 --- a/Editor/Mono/Inspector/EditorSettingsInspector.cs +++ b/Editor/Mono/Inspector/EditorSettingsInspector.cs @@ -774,8 +774,9 @@ private void SetLineEndingsForNewScripts(object data) [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Editor", "ProjectSettings/EditorSettings.asset"); - provider.PopulateSearchKeywordsFromGUIContentProperties(); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Editor", "ProjectSettings/EditorSettings.asset", + SettingsProvider.GetSearchKeywordsFromGUIContentProperties()); return provider; } } diff --git a/Editor/Mono/Inspector/GraphicsSettingsInspector.cs b/Editor/Mono/Inspector/GraphicsSettingsInspector.cs index e7e3db3d58..dd166d7297 100644 --- a/Editor/Mono/Inspector/GraphicsSettingsInspector.cs +++ b/Editor/Mono/Inspector/GraphicsSettingsInspector.cs @@ -2,6 +2,8 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System.Collections.Generic; +using System.Linq; using UnityEditorInternal; using UnityEngine; using UnityEngine.Events; @@ -10,7 +12,6 @@ using AlwaysIncludedShadersEditor = UnityEditor.GraphicsSettingsWindow.AlwaysIncludedShadersEditor; using ShaderStrippingEditor = UnityEditor.GraphicsSettingsWindow.ShaderStrippingEditor; using ShaderPreloadEditor = UnityEditor.GraphicsSettingsWindow.ShaderPreloadEditor; - using UnityEngine.Experimental.Rendering; using UnityEngine.Rendering; @@ -180,20 +181,19 @@ public void SetSectionOpenListener(UnityAction action) [SettingsProvider] static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Graphics", "ProjectSettings/GraphicsSettings.asset"); - provider.PopulateSearchKeywordsFromGUIContentProperties(); - provider.PopulateSearchKeywordsFromGUIContentProperties(); - provider.PopulateSearchKeywordsFromGUIContentProperties(); - provider.PopulateSearchKeywordsFromGUIContentProperties(); - provider.PopulateSearchKeywordsFromGUIContentProperties(); - - var graphicSettings = provider.CreateEditor() as GraphicsSettingsInspector; - SettingsProvider.GetSearchKeywordsFromSerializedObject(graphicSettings.serializedObject, provider.keywords); - SettingsProvider.GetSearchKeywordsFromSerializedObject(graphicSettings.alwaysIncludedShadersEditor.serializedObject, provider.keywords); - - provider.onEditorCreated = editor => + var provider = AssetSettingsProvider.CreateProviderFromAssetPath("Project/Graphics", "ProjectSettings/GraphicsSettings.asset"); + var graphicsEditor = Editor.CreateEditor(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/GraphicsSettings.asset")) as GraphicsSettingsInspector; + provider.keywords = SettingsProvider.GetSearchKeywordsFromGUIContentProperties() + .Concat(SettingsProvider.GetSearchKeywordsFromGUIContentProperties()) + .Concat(SettingsProvider.GetSearchKeywordsFromGUIContentProperties()) + .Concat(SettingsProvider.GetSearchKeywordsFromGUIContentProperties()) + .Concat(SettingsProvider.GetSearchKeywordsFromGUIContentProperties()) + .Concat(SettingsProvider.GetSearchKeywordsFromSerializedObject(graphicsEditor.serializedObject)) + .Concat(SettingsProvider.GetSearchKeywordsFromSerializedObject(graphicsEditor.alwaysIncludedShadersEditor.serializedObject)); + + provider.activateHandler = (searchContext, rootElement) => { - (editor as GraphicsSettingsInspector).SetSectionOpenListener(provider.settingsWindow.Repaint); + (provider.settingsEditor as GraphicsSettingsInspector)?.SetSectionOpenListener(provider.Repaint); }; provider.icon = EditorGUIUtility.FindTexture("UnityEngine/UI/GraphicRaycaster Icon"); diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 5eca5d41fb..b35b399eb7 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -102,6 +102,12 @@ internal static class Styles public static GUIStyle stickyNotePerforce = "VCS_StickyNoteP4"; public static GUIStyle stickyNoteLabel = "VCS_StickyNoteLabel"; public static readonly GUIContent VCS_NotConnectedMessage = EditorGUIUtility.TrTextContent("VCS Plugin {0} is enabled but not connected"); + public static readonly string objectDisabledModuleWarningFormat = L10n.Tr( + "The built-in package '{0}', which implements this component type, has been disabled in Package Manager. This object will be removed in play mode and from any builds you make." + ); + public static readonly string objectDisabledModuleWithDependencyWarningFormat = L10n.Tr( + "The built-in package '{0}', which is required by the package '{1}', which implements this component type, has been disabled in Package Manager. This object will be removed in play mode and from any builds you make." + ); } internal InspectorWindow() @@ -1250,7 +1256,15 @@ private void DrawEditor(Editor[] editors, int editorIndex, bool rebuildOptimized Rect contentRect = new Rect(); bool excludedClass = ModuleMetadata.GetModuleIncludeSettingForObject(target) == ModuleIncludeSetting.ForceExclude; if (excludedClass) - EditorGUILayout.HelpBox("The built-in package '" + ModuleMetadata.GetExcludingModuleForObject(target) + "', which is required this component type has been disabled in Package Manager. This object will be removed in play mode and from any builds you make.", MessageType.Warning); + { + var objectModule = ModuleMetadata.GetModuleForObject(target); + var excludingModule = ModuleMetadata.GetExcludingModuleForObject(target); + if (objectModule == excludingModule) + EditorGUILayout.HelpBox(string.Format(Styles.objectDisabledModuleWarningFormat, objectModule), MessageType.Warning); + else + EditorGUILayout.HelpBox(string.Format(Styles.objectDisabledModuleWithDependencyWarningFormat, excludingModule, objectModule), MessageType.Warning); + } + using (new EditorGUI.DisabledScope(!editor.IsEnabled() || excludedClass)) { diff --git a/Editor/Mono/Inspector/MonoScriptInspector.cs b/Editor/Mono/Inspector/MonoScriptInspector.cs index 03a5c26411..c5f575f2a5 100644 --- a/Editor/Mono/Inspector/MonoScriptInspector.cs +++ b/Editor/Mono/Inspector/MonoScriptInspector.cs @@ -37,7 +37,7 @@ internal override void OnHeaderControlsGUI() { if (GUILayout.Button("Execution Order...", EditorStyles.miniButton))//GUILayout.Width(150))) { - SettingsWindow.OpenProjectSettings("Project/Script Execution Order"); + SettingsService.OpenProjectSettings("Project/Script Execution Order"); GUIUtility.ExitGUI(); } } diff --git a/Editor/Mono/Inspector/Physics2DSettingsInspector.cs b/Editor/Mono/Inspector/Physics2DSettingsInspector.cs index ebd01c39a9..231009a98c 100644 --- a/Editor/Mono/Inspector/Physics2DSettingsInspector.cs +++ b/Editor/Mono/Inspector/Physics2DSettingsInspector.cs @@ -88,11 +88,9 @@ public override void OnInspectorGUI() [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Physics 2D", "ProjectSettings/Physics2DSettings.asset") - { - icon = EditorGUIUtility.IconContent("Profiler.Physics2D").image as Texture2D - }; - SettingsProvider.GetSearchKeywordsFromSerializedObject(provider.CreateEditor().serializedObject, provider.keywords); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Physics 2D", "ProjectSettings/Physics2DSettings.asset", + SettingsProvider.GetSearchKeywordsFromPath("ProjectSettings/Physics2DSettings.asset")); return provider; } diff --git a/Editor/Mono/Inspector/PhysicsManagerInspector.cs b/Editor/Mono/Inspector/PhysicsManagerInspector.cs index a2062b770d..838e4a0a43 100644 --- a/Editor/Mono/Inspector/PhysicsManagerInspector.cs +++ b/Editor/Mono/Inspector/PhysicsManagerInspector.cs @@ -3,7 +3,6 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using UnityEngine; -using UnityEditor; using UnityEditorInternal; namespace UnityEditor @@ -39,16 +38,17 @@ public static void DoGUI(string title, ref bool show, GetValueFunc getValue, Set GUILayout.EndHorizontal(); if (show) { - var scrollPos = GUI.GetTopScrollView() != null ? GUI.GetTopScrollView().scrollPosition : Vector2.zero; + var scrollState = GUI.GetTopScrollView(); + var scrollStatePosOffset = scrollState?.position.y ?? 0; + var scrollPos = scrollState?.scrollPosition ?? Vector2.zero; var topLabelRect = GUILayoutUtility.GetRect(checkboxSize + labelSize, labelSize); - var scrollArea = GUIClip.topmostRect; var topLeft = new Vector2(topLabelRect.x, topLabelRect.y); var y = 0; for (int i = 0; i < kMaxLayers; i++) { if (LayerMask.LayerToName(i) != "") { - var translate = new Vector3(labelSize + indent + checkboxSize * (numLayers - y) + topLeft.x - scrollPos.x, topLeft.y - scrollPos.y, 0); + var translate = new Vector3(labelSize + indent + checkboxSize * (numLayers - y) + topLeft.x - scrollPos.x + scrollStatePosOffset, topLeft.y - scrollPos.y + scrollStatePosOffset, 0); GUI.matrix = Matrix4x4.TRS(translate, Quaternion.Euler(0, 0, 90), Vector3.one); GUI.Label(new Rect(scrollPos.x, scrollPos.y, labelSize, checkboxSize), LayerMask.LayerToName(i), "RightLabel"); y++; @@ -157,11 +157,9 @@ public override void OnInspectorGUI() [SettingsProvider] static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Physics", "ProjectSettings/DynamicsManager.asset") - { - icon = EditorGUIUtility.IconContent("Profiler.Physics").image as Texture2D - }; - SettingsProvider.GetSearchKeywordsFromSerializedObject(provider.CreateEditor().serializedObject, provider.keywords); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Physics", "ProjectSettings/DynamicsManager.asset", + SettingsProvider.GetSearchKeywordsFromPath("ProjectSettings/DynamicsManager.asset")); return provider; } } diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index ab10d85a8e..3d1c8d271b 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -7,7 +7,6 @@ using UnityEditor.Build; using UnityEditor.SceneManagement; using UnityEditor.PlatformSupport; -using UnityEditor.Rendering; using UnityEditorInternal; using System; using System.Collections.Generic; @@ -2589,14 +2588,12 @@ protected override bool ShouldHideOpenButton() [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Player", "ProjectSettings/ProjectSettings.asset") + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Player", "ProjectSettings/ProjectSettings.asset", + SettingsProvider.GetSearchKeywordsFromGUIContentProperties()); + provider.activateHandler = (searchContext, rootElement) => { - icon = EditorGUIUtility.LoadIconRequired("BuildSettings.Editor") - }; - provider.PopulateSearchKeywordsFromGUIContentProperties(); - provider.onEditorCreated = editor => - { - (editor as PlayerSettingsEditor).SetSectionOpenListener(provider.settingsWindow.Repaint); + (provider.settingsEditor as PlayerSettingsEditor)?.SetSectionOpenListener(provider.Repaint); }; return provider; } diff --git a/Editor/Mono/Inspector/QualitySettingsEditor.cs b/Editor/Mono/Inspector/QualitySettingsEditor.cs index 495fd0a4a9..2ac84f13d0 100644 --- a/Editor/Mono/Inspector/QualitySettingsEditor.cs +++ b/Editor/Mono/Inspector/QualitySettingsEditor.cs @@ -608,12 +608,9 @@ public override void OnInspectorGUI() [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Quality", "ProjectSettings/QualitySettings.asset") - { - icon = EditorGUIUtility.LoadIconRequired("Profiler.Rendering") - }; - provider.PopulateSearchKeywordsFromGUIContentProperties(); - SettingsProvider.GetSearchKeywordsFromSerializedObject(provider.CreateEditor().serializedObject, provider.keywords); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Quality", "ProjectSettings/QualitySettings.asset", + SettingsProvider.GetSearchKeywordsFromGUIContentProperties().Concat(SettingsProvider.GetSearchKeywordsFromPath("ProjectSettings/QualitySettings.asset"))); return provider; } } diff --git a/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs b/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs index 75b6afcfbc..8a9692060e 100644 --- a/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs +++ b/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs @@ -815,11 +815,10 @@ public static int DragReorder(Rect position, int elementHeight, List [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Script Execution Order", Resources.FindObjectsOfTypeAll(typeof(MonoManager)).First()) - { - icon = EditorGUIUtility.FindTexture("cs Script") - }; - provider.PopulateSearchKeywordsFromGUIContentProperties(); + var provider = new AssetSettingsProvider( + "Project/Script Execution Order", + () => Editor.CreateEditor(Resources.FindObjectsOfTypeAll(typeof(MonoManager)).First()), + SettingsProvider.GetSearchKeywordsFromGUIContentProperties()); return provider; } } diff --git a/Editor/Mono/Inspector/TagManagerInspector.cs b/Editor/Mono/Inspector/TagManagerInspector.cs index b4548b6da4..94079449b6 100644 --- a/Editor/Mono/Inspector/TagManagerInspector.cs +++ b/Editor/Mono/Inspector/TagManagerInspector.cs @@ -348,11 +348,9 @@ public override void OnInspectorGUI() [SettingsProvider] static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Tags and Layers", "ProjectSettings/TagManager.asset") - { - icon = EditorGUIUtility.LoadIconRequired("CustomSorting") - }; - provider.PopulateSearchKeywordsFromGUIContentProperties(); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Tags and Layers", "ProjectSettings/TagManager.asset", + SettingsProvider.GetSearchKeywordsFromGUIContentProperties()); return provider; } } diff --git a/Editor/Mono/Inspector/TimeManagerInspector.cs b/Editor/Mono/Inspector/TimeManagerInspector.cs index c97f548150..4d7aa39df1 100644 --- a/Editor/Mono/Inspector/TimeManagerInspector.cs +++ b/Editor/Mono/Inspector/TimeManagerInspector.cs @@ -3,9 +3,6 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using UnityEngine; -using UnityEditor; -using UnityEditorInternal; -using System.Collections; namespace UnityEditor { @@ -48,11 +45,9 @@ public override void OnInspectorGUI() [SettingsProvider] internal static SettingsProvider CreateProjectSettingsProvider() { - var provider = new AssetSettingsProvider("Project/Time", "ProjectSettings/TimeManager.asset") - { - icon = EditorGUIUtility.FindTexture("UnityEngine/Timeline/TimelineAsset Icon") - }; - provider.PopulateSearchKeywordsFromGUIContentProperties(); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Time", "ProjectSettings/TimeManager.asset", + SettingsProvider.GetSearchKeywordsFromGUIContentProperties()); return provider; } } diff --git a/Editor/Mono/Modules/DefaultCompilationExtension.cs b/Editor/Mono/Modules/DefaultCompilationExtension.cs index 66928fe768..b4ac96d048 100644 --- a/Editor/Mono/Modules/DefaultCompilationExtension.cs +++ b/Editor/Mono/Modules/DefaultCompilationExtension.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Mono.Cecil; +using UnityEditor.Scripting.ScriptCompilation; using UnityEngine; namespace UnityEditor.Modules @@ -12,7 +13,7 @@ namespace UnityEditor.Modules internal class DefaultCompilationExtension : ICompilationExtension { - public virtual CSharpCompiler GetCsCompiler(bool buildingForEditor, string assemblyName) + public virtual CSharpCompiler GetCsCompiler(bool buildingForEditor, ScriptAssembly scriptAssemly) { if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Latest) return CSharpCompiler.Microsoft; diff --git a/Editor/Mono/Modules/PlatformSupportModule.cs b/Editor/Mono/Modules/PlatformSupportModule.cs index d546ff8566..b4c35bd64f 100644 --- a/Editor/Mono/Modules/PlatformSupportModule.cs +++ b/Editor/Mono/Modules/PlatformSupportModule.cs @@ -7,6 +7,7 @@ using UnityEditor.DeploymentTargets; using UnityEngine; using Mono.Cecil; +using UnityEditor.Scripting.ScriptCompilation; namespace UnityEditor.Modules { @@ -399,7 +400,7 @@ internal enum CSharpCompiler internal interface ICompilationExtension { - CSharpCompiler GetCsCompiler(bool buildingForEditor, string assemblyName); + CSharpCompiler GetCsCompiler(bool buildingForEditor, ScriptAssembly scriptAssembly); string[] GetCompilerExtraAssemblyPaths(bool isEditor, string assemblyPathName); IAssemblyResolver GetAssemblyResolver(bool buildingForEditor, string assemblyPath, string[] searchDirectories); diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 6765638a07..1f023bb79b 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -402,7 +402,7 @@ public static void ApplyPropertyOverride(SerializedProperty instanceProperty, st ); } - // This method is called both from ApplyPropertyOverride (one time) and ApplyObjectOverride (many times). + // This method is called both from ApplyPropertyOverride and ApplyObjectOverride. // In the former case, optionalSingleInstanceProperty is passed along as is the only property that should be processed. // In the latter, all properties in the prefabInstanceObject are iterated. // An alternative approach was considered where the method takes an array of SerializedProperties, @@ -418,8 +418,6 @@ public static void ApplyPropertyOverride(SerializedProperty instanceProperty, st // again require storing information about that for each property in some kind of list, which we want to avoid. static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProperty optionalSingleInstanceProperty, string assetPath, InteractionMode action) { - bool singleProperty = optionalSingleInstanceProperty != null; - Object prefabSourceObject = GetCorrespondingObjectFromSourceAtPath(prefabInstanceObject, assetPath); if (prefabSourceObject == null) return; @@ -430,18 +428,38 @@ static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProper List serializedObjects = new List(); bool isObjectOnRootInAsset = IsObjectOnRootInAsset(prefabInstanceObject, assetPath); - if (singleProperty) + + SerializedProperty property; + if (optionalSingleInstanceProperty != null) { - if (optionalSingleInstanceProperty.prefabOverride) - ApplySingleProperty(optionalSingleInstanceProperty, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, true, serializedObjects, action); + property = optionalSingleInstanceProperty.Copy(); } else { SerializedObject so = new SerializedObject(prefabInstanceObject); - SerializedProperty property = so.GetIterator(); + property = so.GetIterator(); + } + + if (!property.hasVisibleChildren) + { + if (property.prefabOverride) + ApplySingleProperty(property, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, true, serializedObjects, action); + } + else + { while (property.Next(property.hasChildren)) { - if (property.prefabOverride) + // If we apply a property that has child properties that are object references if they + // reference non-asset objects, those references will get lost, since ApplySingleProperty + // only patches up references in the provided property; not its children. + // This could be fixed by letting ApplySingleProperty patch up all its child properties as well, + // but then calling ApplySingleProperty n times would result in time complexity n*log(n). + // Instead we only call ApplySingleProperty for leaf properties - the ones that actually contain + // the data. Here, that means properties with hasVisibleChildren=false. + // Note that an object reference property has hasVisibleChildren=false but has hasChildren=true. + // Applying all leaf properties applies exactly all data there is to apply only once and ensures + // that when an object reference is applied, it's via its own property and not a parent property. + if (property.prefabOverride && !property.hasVisibleChildren) ApplySingleProperty(property, prefabSourceSerializedObject, assetPath, isObjectOnRootInAsset, false, serializedObjects, action); } } @@ -486,9 +504,9 @@ static void ApplySingleProperty( } prefabSourceSerializedObject.CopyFromSerializedProperty(instanceProperty); - SerializedProperty sourceProperty = prefabSourceSerializedObject.FindProperty(instanceProperty.propertyPath); // Abort if property has reference to object in scene. + SerializedProperty sourceProperty = prefabSourceSerializedObject.FindProperty(instanceProperty.propertyPath); if (sourceProperty.propertyType == SerializedPropertyType.ObjectReference) { MapObjectReferencePropertyToSourceIfApplicable(sourceProperty, assetPath); @@ -574,9 +592,6 @@ public static void ApplyObjectOverride(Object instanceComponentOrGameObject, str ); } - // TODO Review. This method is redundant since there was already a method for it, - // but it fits in with a consistent naming scheme where methods come in pairs of - // Apply[x] and Revert[X]. Maybe obsolete the old one? public static void RevertObjectOverride(Object instanceComponentOrGameObject, InteractionMode action) { CheckInstanceIsNotPersistent(instanceComponentOrGameObject); diff --git a/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs b/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs index 4d0d4ce0ff..65e0d379f2 100644 --- a/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs +++ b/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs @@ -4,7 +4,6 @@ using Microsoft.Win32; using UnityEngine; -using UnityEditor; using UnityEditor.Collaboration; using UnityEditorInternal; using System.Collections.Generic; @@ -119,14 +118,13 @@ private static string GetCommandLineRemoteAddressOverride() [SettingsProvider] internal static SettingsProvider CreateSettingsProvider() { - return new SettingsProvider("Preferences/Cache Server") + return new SettingsProvider("Preferences/Cache Server", SettingsScope.User) { guiHandler = searchContext => { using (new SettingsWindow.GUIScope()) OnGUI(searchContext); - }, - scopes = SettingsScopes.User + } }; } diff --git a/Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs b/Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs index ba5565d21f..0bc3f046e5 100644 --- a/Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs +++ b/Editor/Mono/PreferencesWindow/DiagnosticsSwitchPreferences.cs @@ -129,14 +129,13 @@ private static bool DisplaySwitch(DiagnosticSwitch diagnosticSwitch) [SettingsProvider] internal static SettingsProvider CreateDiagnosticProvider() { - return new SettingsProvider("Preferences/Diagnostics") + return new SettingsProvider("Preferences/Diagnostics", SettingsScope.User) { guiHandler = searchContext => { using (new SettingsWindow.GUIScope()) OnGUI(searchContext); }, - scopes = SettingsScopes.User, hasSearchInterestHandler = searchContext => { var switches = new List(); diff --git a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs index 50bfeaebfe..f9a21083bd 100644 --- a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs +++ b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs @@ -187,10 +187,9 @@ public override string ToString() } } - public PreferencesProvider(string path) - : base(path) + public PreferencesProvider(string path, IEnumerable keywords = null) + : base(path, SettingsScope.User, keywords) { - scopes = SettingsScopes.User; prefWinExtensions = ModuleManager.GetPreferenceWindowExtensions(); ReadPreferences(); } @@ -198,45 +197,40 @@ public PreferencesProvider(string path) [SettingsProvider] internal static SettingsProvider CreateGeneralProvider() { - var settings = new PreferencesProvider("Preferences/_General") { label = "General" }; - settings.PopulateSearchKeywordsFromGUIContentProperties(); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.ShowGeneral); }; + var settings = new PreferencesProvider("Preferences/_General", GetSearchKeywordsFromGUIContentProperties()) { label = "General" }; + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowGeneral); }; return settings; } [SettingsProvider] internal static SettingsProvider CreateExternalToolsProvider() { - var settings = new PreferencesProvider("Preferences/External Tools"); - settings.PopulateSearchKeywordsFromGUIContentProperties(); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.ShowExternalApplications); }; + var settings = new PreferencesProvider("Preferences/External Tools", GetSearchKeywordsFromGUIContentProperties()); + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowExternalApplications); }; return settings; } [SettingsProvider] internal static SettingsProvider CreateColorsProvider() { - var settings = new PreferencesProvider("Preferences/Colors"); - settings.PopulateSearchKeywordsFromGUIContentProperties(); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.ShowColors); }; + var settings = new PreferencesProvider("Preferences/Colors", GetSearchKeywordsFromGUIContentProperties()); + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowColors); }; return settings; } [SettingsProvider] internal static SettingsProvider CreateGICacheProvider() { - var settings = new PreferencesProvider("Preferences/GI Cache"); - settings.PopulateSearchKeywordsFromGUIContentProperties(); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.ShowGICache); }; + var settings = new PreferencesProvider("Preferences/GI Cache", GetSearchKeywordsFromGUIContentProperties()); + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowGICache); }; return settings; } [SettingsProvider] internal static SettingsProvider Create2DProvider() { - var settings = new PreferencesProvider("Preferences/2D"); - settings.PopulateSearchKeywordsFromGUIContentProperties(); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.Show2D); }; + var settings = new PreferencesProvider("Preferences/2D", GetSearchKeywordsFromGUIContentProperties()); + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.Show2D); }; return settings; } @@ -244,7 +238,7 @@ internal static SettingsProvider Create2DProvider() internal static SettingsProvider CreateKeysProvider() { var settings = new PreferencesProvider("Preferences/Keys"); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.ShowShortcuts); }; + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowShortcuts); }; return settings; } @@ -276,7 +270,7 @@ internal static SettingsProvider CreateLanguagesProvider() if (editorLanguages.Length > 1) { var settings = new PreferencesProvider("Preferences/Languages"); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.ShowLanguage); }; + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowLanguage); }; return settings; } @@ -290,14 +284,14 @@ internal static SettingsProvider CreateUnityServicesProvider() if (Unsupported.IsDeveloperMode() || UnityConnect.preferencesEnabled) { var settings = new PreferencesProvider("Preferences/Unity Services"); - settings.guiHandler = searchContext => { settings.OnGUI(searchContext, settings.ShowUnityConnectPrefs); }; + settings.guiHandler = searchContext => { OnGUI(searchContext, settings.ShowUnityConnectPrefs); }; return settings; } return null; } // Group Preference sections with the same name - private void OnGUI(string searchContext, Action drawAction) + private static void OnGUI(string searchContext, Action drawAction) { using (new SettingsWindow.GUIScope()) drawAction(searchContext); @@ -528,7 +522,7 @@ private static void RevertShortcuts() private static void RevertPrefKeys() { - foreach (KeyValuePair kvp in Settings.Prefs()) + foreach (KeyValuePair kvp in PrefSettings.Prefs()) { kvp.Value.ResetToDefault(); EditorPrefs.SetString(kvp.Value.Name, kvp.Value.ToUniqueString()); @@ -589,7 +583,7 @@ private object ShowShortcutsAndKeys(int controlID) ) ); m_SortedKeyEntries.AddRange( - Settings.Prefs().Select(pk => new KeyValuePair(pk.Key, pk.Value)) + PrefSettings.Prefs().Select(pk => new KeyValuePair(pk.Key, pk.Value)) ); m_SortedKeyEntries.Sort((k1, k2) => k1.Key.CompareTo(k2.Key)); foreach (var keyEntry in m_SortedKeyEntries) @@ -614,7 +608,10 @@ private object ShowShortcutsAndKeys(int controlID) } if (changeCheckScope.changed) + { GUIUtility.keyboardControl = controlID; + m_InvalidKeyMessage = ""; + } } } @@ -650,7 +647,7 @@ private void ProcessArrowKeyInShortcutConfiguration() Event.current.Use(); break; case KeyCode.DownArrow: - if (m_SelectedShortcut < ShortcutIntegration.instance.profileManager.GetAllShortcuts().Count() + Settings.Prefs().Count()) + if (m_SelectedShortcut < ShortcutIntegration.instance.profileManager.GetAllShortcuts().Count() + PrefSettings.Prefs().Count()) { m_SelectedShortcut++; m_ValidKeyChange = true; @@ -666,6 +663,7 @@ private void CheckForCollisions(Event e, ShortcutEntry selectedShortcut, PrefKey ShortcutController shortcutController = ShortcutIntegration.instance; var collisions = new List(); m_ValidKeyChange = true; + m_InvalidKeyMessage = ""; Type context = selectedShortcut?.context; string identifier = selectedShortcut != null ? selectedShortcut.identifier.path @@ -678,20 +676,19 @@ private void CheckForCollisions(Event e, ShortcutEntry selectedShortcut, PrefKey new[] { context }, collisions); - if (collisions.Any()) + if (collisions.Any() && !Equals(identifier, collisions[0].identifier.path)) { m_ValidKeyChange = false; m_InvalidKeyMessage = string.Format(k_KeyCollisionFormat, BuildDescription(e), identifier, collisions[0].identifier); return; } - // Check prefkeys string selectedToolName = identifier.Split('/')[0]; // Setting the same key to the same action is ok. // Setting the same key to a different action from a different tool is ok too. - KeyValuePair collision = Settings.Prefs().FirstOrDefault(kvp => + KeyValuePair collision = PrefSettings.Prefs().FirstOrDefault(kvp => kvp.Value.KeyboardEvent.Equals(e) && kvp.Key.Split('/')[0] == selectedToolName && kvp.Key != identifier ); @@ -794,7 +791,7 @@ private void ShowPrefKeyConfiguration(int controlID, PrefKey selectedKey) if (m_ValidKeyChange) { selectedKey.KeyboardEvent = e; - Settings.Set(selectedKey.Name, selectedKey); + PrefSettings.Set(selectedKey.Name, selectedKey); } } else if (GUIUtility.keyboardControl == controlID && Event.current.type == EventType.KeyDown) @@ -849,6 +846,7 @@ private void ShowShortcuts(string searchContext) if (GUILayout.Button(ColorsProperties.userDefaults, GUILayout.Width(120))) { m_ValidKeyChange = true; + m_InvalidKeyMessage = ""; RevertShortcuts(); RevertPrefKeys(); } @@ -856,7 +854,7 @@ private void ShowShortcuts(string searchContext) private void RevertColors() { - foreach (KeyValuePair kvp in Settings.Prefs()) + foreach (KeyValuePair kvp in PrefSettings.Prefs()) { kvp.Value.ResetToDefault(); EditorPrefs.SetString(kvp.Value.Name, kvp.Value.ToUniqueString()); @@ -867,7 +865,7 @@ private void ShowColors(string searchContext) { if (s_CachedColors == null) { - s_CachedColors = OrderPrefs(Settings.Prefs()); + s_CachedColors = OrderPrefs(PrefSettings.Prefs()); } var changedColor = false; @@ -887,7 +885,7 @@ private void ShowColors(string searchContext) } } if (ccolor != null) - Settings.Set(ccolor.Name, ccolor); + PrefSettings.Set(ccolor.Name, ccolor); } GUILayout.Space(5f); diff --git a/Editor/Mono/Scripting/Compilers/BooLanguage.cs b/Editor/Mono/Scripting/Compilers/BooLanguage.cs index 36f8f30817..863cc01f62 100644 --- a/Editor/Mono/Scripting/Compilers/BooLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/BooLanguage.cs @@ -5,6 +5,7 @@ using Boo.Lang.Parser; using System.Linq; +using UnityEditor.Scripting.ScriptCompilation; namespace UnityEditor.Scripting.Compilers { @@ -20,7 +21,7 @@ public override string GetLanguageName() return "Boo"; } - public override ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) + public override ScriptCompilerBase CreateCompiler(ScriptAssembly scriptAssembly, MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) { return new BooCompiler(island, runUpdater); } diff --git a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs index 2b39572932..ae8f4c9041 100644 --- a/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/CSharpLanguage.cs @@ -39,16 +39,16 @@ public override string GetLanguageName() } public static CSharpCompiler GetCSharpCompiler(BuildTarget targetPlatform, bool buildingForEditor, - string assemblyName) + ScriptAssembly scriptAssembly) { var target = ModuleManager.GetTargetStringFromBuildTarget(targetPlatform); var extension = ModuleManager.GetCompilationExtension(target); - return extension.GetCsCompiler(buildingForEditor, assemblyName); + return extension.GetCsCompiler(buildingForEditor, scriptAssembly); } - public override ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) + public override ScriptCompilerBase CreateCompiler(ScriptAssembly scriptAssembly, MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) { - switch (GetCSharpCompiler(targetPlatform, buildingForEditor, island._output)) + switch (GetCSharpCompiler(targetPlatform, buildingForEditor, scriptAssembly)) { case CSharpCompiler.Microsoft: return new MicrosoftCSharpCompiler(island, runUpdater); @@ -63,6 +63,25 @@ public override bool CompilerRequiresAdditionalReferences() return true; } + public override string[] GetCompilerDefines(BuildTarget targetPlatform, bool buildingForEditor, + ScriptAssembly scriptAssembly) + { + var compiler = GetCSharpCompiler(targetPlatform, buildingForEditor, scriptAssembly); + + if (compiler == CSharpCompiler.Microsoft) + { + var defines = new string[] + { + "CSHARP_7_OR_LATER", // Incremental Compiler adds this. + "CSHARP_7_3_OR_NEWER", + }; + + return defines; + } + + return new string[0]; + } + static string[] GetSystemReferenceDirectories(ApiCompatibilityLevel apiCompatibilityLevel) { return MonoLibraryHelpers.GetSystemReferenceDirectories(apiCompatibilityLevel); diff --git a/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs b/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs index 12a3c04a72..f8db47f384 100644 --- a/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/SupportedLanguage.cs @@ -2,6 +2,8 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using UnityEditor.Scripting.ScriptCompilation; + namespace UnityEditor.Scripting.Compilers { internal abstract class SupportedLanguage @@ -13,7 +15,7 @@ public virtual ResponseFileProvider CreateResponseFileProvider() public abstract string GetExtensionICanCompile(); public abstract string GetLanguageName(); - public abstract ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater); + public abstract ScriptCompilerBase CreateCompiler(ScriptAssembly scriptAssembly, MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater); public virtual string GetNamespace(string fileName, string definedSymbols) { return string.Empty; @@ -23,5 +25,11 @@ public virtual bool CompilerRequiresAdditionalReferences() { return false; } + + public virtual string[] GetCompilerDefines(BuildTarget targetPlatform, bool buildingForEditor, + ScriptAssembly scriptAssembly) + { + return new string[0]; + } } } diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs b/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs index 7bcf8c2c41..45b654fca9 100644 --- a/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs +++ b/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs @@ -2,6 +2,8 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using UnityEditor.Scripting.ScriptCompilation; + namespace UnityEditor.Scripting.Compilers { internal class UnityScriptLanguage : SupportedLanguage @@ -16,7 +18,7 @@ public override string GetLanguageName() return "UnityScript"; } - public override ScriptCompilerBase CreateCompiler(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) + public override ScriptCompilerBase CreateCompiler(ScriptAssembly scriptAssembly, MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) { return new UnityScriptCompiler(island, runUpdater); } diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs index 955e99130b..6c606ac42e 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs @@ -232,7 +232,7 @@ void QueuePendingAssemblies() { pendingAssemblies.Remove(assembly); var island = assembly.ToMonoIsland(options, buildOutputDirectory); - var compiler = ScriptCompilers.CreateCompilerInstance(island, buildingForEditor, island._target, assembly.RunUpdater); + var compiler = ScriptCompilers.CreateCompilerInstance(assembly, island, buildingForEditor, island._target, assembly.RunUpdater); compilerTasks.Add(assembly, compiler); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index 17bc5b7141..bb3b375f17 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -58,6 +58,7 @@ internal class TargetAssembly public TargetAssembly() { References = new List(); + Defines = new string[0]; } public TargetAssembly(string name, @@ -550,8 +551,12 @@ internal static ScriptAssembly[] ToScriptAssemblies(IDictionary(); diff --git a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs index ecf78af84d..7566bf835c 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/MonoLibraryHelpers.cs @@ -21,9 +21,9 @@ class CachedReferences static CachedReferences cachedReferences; public static string[] GetSystemLibraryReferences(ApiCompatibilityLevel apiCompatibilityLevel, BuildTarget buildTarget, SupportedLanguage supportedLanguage, - bool buildingForEditor, string assemblyName) + bool buildingForEditor, ScriptAssembly scriptAssembly) { - if (WSAHelpers.BuildingForDotNet(buildTarget, buildingForEditor, assemblyName)) + if (WSAHelpers.BuildingForDotNet(buildTarget, buildingForEditor, scriptAssembly)) return new string[0]; // The language may not be compatible with these additional references diff --git a/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs index 1a30f6358e..f8aaab4bdc 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/WSAHelpers.cs @@ -34,7 +34,7 @@ public static bool UseDotNetCore(ScriptAssembly scriptAssembly) return useDotNetCore; } - public static bool BuildingForDotNet(BuildTarget buildTarget, bool buildingForEditor, string assemblyName) + public static bool BuildingForDotNet(BuildTarget buildTarget, bool buildingForEditor, ScriptAssembly scriptAssembly) { if (buildingForEditor) return false; @@ -42,7 +42,7 @@ public static bool BuildingForDotNet(BuildTarget buildTarget, bool buildingForEd if (buildTarget != BuildTarget.WSAPlayer) return false; - if (CSharpLanguage.GetCSharpCompiler(buildTarget, buildingForEditor, assemblyName) != CSharpCompiler.Microsoft) + if (CSharpLanguage.GetCSharpCompiler(buildTarget, buildingForEditor, scriptAssembly) != CSharpCompiler.Microsoft) return false; if (PlayerSettings.GetScriptingBackend(BuildPipeline.GetBuildTargetGroup(buildTarget)) != ScriptingImplementation.WinRTDotNET) diff --git a/Editor/Mono/Scripting/ScriptCompilers.cs b/Editor/Mono/Scripting/ScriptCompilers.cs index f09670cf1c..903a06fcf0 100644 --- a/Editor/Mono/Scripting/ScriptCompilers.cs +++ b/Editor/Mono/Scripting/ScriptCompilers.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Runtime.InteropServices; using UnityEditor.Scripting.Compilers; +using UnityEditor.Scripting.ScriptCompilation; namespace UnityEditor.Scripting { @@ -139,14 +140,14 @@ internal static SupportedLanguage GetLanguageFromExtension(string extension) throw new ApplicationException(string.Format("Script file extension '{0}' is not supported", extension)); } - internal static ScriptCompilerBase CreateCompilerInstance(MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) + internal static ScriptCompilerBase CreateCompilerInstance(ScriptAssembly scriptAssembly, MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) { if (island._files.Length == 0) throw new ArgumentException("Cannot compile MonoIsland with no files"); foreach (var lang in SupportedLanguages) { if (lang.GetExtensionICanCompile() == island.GetExtensionOfSourceFiles()) - return lang.CreateCompiler(island, buildingForEditor, targetPlatform, runUpdater); + return lang.CreateCompiler(scriptAssembly, island, buildingForEditor, targetPlatform, runUpdater); } throw new ApplicationException(string.Format("Unable to find a suitable compiler for sources with extension '{0}' (Output assembly: {1})", island.GetExtensionOfSourceFiles(), island._output)); diff --git a/Editor/Mono/Settings.cs b/Editor/Mono/Settings.cs index 802ebf111e..a3902beec1 100644 --- a/Editor/Mono/Settings.cs +++ b/Editor/Mono/Settings.cs @@ -41,7 +41,7 @@ public PrefColor(string name, float defaultRed, float defaultGreen, float defaul this.m_Color = this.m_DefaultColor = new Color(defaultRed, defaultGreen, defaultBlue, defaultAlpha); this.m_SeparateColors = false; this.m_OptionalDarkColor = this.m_OptionalDarkDefaultColor = Color.clear; - Settings.Add(this); + PrefSettings.Add(this); m_Loaded = false; } @@ -51,7 +51,7 @@ public PrefColor(string name, float defaultRed, float defaultGreen, float defaul this.m_Color = this.m_DefaultColor = new Color(defaultRed, defaultGreen, defaultBlue, defaultAlpha); this.m_SeparateColors = true; this.m_OptionalDarkColor = this.m_OptionalDarkDefaultColor = new Color(defaultRed2, defaultGreen2, defaultBlue2, defaultAlpha2); - Settings.Add(this); + PrefSettings.Add(this); m_Loaded = false; } @@ -62,7 +62,7 @@ public void Load() m_Loaded = true; - PrefColor pk = Settings.Get(m_Name, this); + PrefColor pk = PrefSettings.Get(m_Name, this); this.m_Name = pk.m_Name; this.m_Color = pk.m_Color; this.m_SeparateColors = pk.m_SeparateColors; @@ -187,7 +187,7 @@ private PrefKey(string name, string shortcut) this.m_name = name; this.m_Shortcut = shortcut; this.m_DefaultShortcut = shortcut; - Settings.Add(this); + PrefSettings.Add(this); m_Loaded = false; } @@ -199,7 +199,7 @@ public void Load() m_Loaded = true; this.m_event = Event.KeyboardEvent(m_Shortcut); - PrefKey pk = Settings.Get(m_name, this); + PrefKey pk = PrefSettings.Get(m_name, this); this.m_name = pk.Name; this.m_event = pk.KeyboardEvent; } @@ -267,7 +267,7 @@ internal void ResetToDefault() } - internal class Settings + internal class PrefSettings { static List m_AddedPrefs = new List(); static SortedList m_Prefs = new SortedList(); diff --git a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs index b3161f57ad..b54b4340cb 100644 --- a/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs +++ b/Editor/Mono/Settings/Providers/AssetSettingsProvider.cs @@ -6,13 +6,12 @@ using UnityEditor.Experimental; using UnityEngine; using UnityEngine.Experimental.UIElements; -using UnityEngine.Internal; using UnityEditor.StyleSheets; using UnityEditorInternal; +using System.Collections.Generic; namespace UnityEditor { - [ExcludeFromDocs] public class AssetSettingsProvider : SettingsProvider { static class Styles @@ -21,65 +20,84 @@ static class Styles public static StyleBlock settingsBtn => EditorResources.GetStyle("settings-icon-btn"); } - protected Editor m_SettingsEditor; - public Func settingsFetcher { get; set; } - public Action onEditorCreated { get; set; } + Func m_EditorCreator; - public AssetSettingsProvider(string preferencePath, string assetPath) - : this(preferencePath, () => AssetDatabase.LoadAssetAtPath(assetPath)) {} + public Editor settingsEditor { get; private set; } - public AssetSettingsProvider(string preferencePath, UnityEngine.Object settings) - : this(preferencePath, () => settings) {} + public AssetSettingsProvider(string settingsWindowPath, Func editorCreator, IEnumerable keywords = null) + : base(settingsWindowPath, SettingsScope.Project, keywords) + { + m_EditorCreator = editorCreator; + } - public AssetSettingsProvider(string preferencePath, Func settingsGetter) - : base(preferencePath, SettingsScopes.Project) + public AssetSettingsProvider(string settingsWindowPath, Func settingsGetter) + : this(settingsWindowPath, () => CreateEditorFromSettingsObject(settingsGetter())) { - settingsFetcher = settingsGetter; } - public Editor CreateEditor() + public static AssetSettingsProvider CreateProviderFromAssetPath(string settingsWindowPath, string assetPath, IEnumerable keywords = null) { - var settings = settingsFetcher?.Invoke(); - if (settings != null) + return new AssetSettingsProvider(settingsWindowPath, () => { - var editor = Editor.CreateEditor(settings); - onEditorCreated?.Invoke(editor); - return editor; - } + var settingsObj = AssetDatabase.LoadAllAssetsAtPath(assetPath); + if (settingsObj != null) + { + return Editor.CreateEditor(settingsObj); + } + return null; + }, keywords); + } - return null; + public static AssetSettingsProvider CreateProviderFromObject(string settingsWindowPath, UnityEngine.Object settingsObj, IEnumerable keywords = null) + { + return new AssetSettingsProvider(settingsWindowPath, () => CreateEditorFromSettingsObject(settingsObj), keywords); + } + + public static AssetSettingsProvider CreateProviderFromResourcePath(string settingsWindowPath, string resourcePath, IEnumerable keywords = null) + { + return new AssetSettingsProvider(settingsWindowPath, () => + { + var resourceObj = Resources.Load(resourcePath); + if (resourceObj != null) + { + return Editor.CreateEditor(resourceObj); + } + return null; + }, keywords); } public override void OnActivate(string searchContext, VisualElement rootElement) { - m_SettingsEditor = CreateEditor(); + settingsEditor = m_EditorCreator?.Invoke(); + base.OnActivate(searchContext, rootElement); } public override void OnDeactivate() { - if (m_SettingsEditor != null) + if (settingsEditor != null) { - var info = m_SettingsEditor.GetType().GetMethod("OnDisable"); - info?.Invoke(m_SettingsEditor, null); + var info = settingsEditor.GetType().GetMethod("OnDisable"); + info?.Invoke(settingsEditor, null); } - m_SettingsEditor = null; + settingsEditor = null; + base.OnDeactivate(); } public override void OnGUI(string searchContext) { - if (m_SettingsEditor != null) + if (settingsEditor != null) { - using (new EditorGUI.DisabledScope(!m_SettingsEditor.IsEnabled())) + using (new EditorGUI.DisabledScope(!settingsEditor.IsEnabled())) { using (new SettingsWindow.GUIScope()) - m_SettingsEditor.OnInspectorGUI(); + settingsEditor.OnInspectorGUI(); // Emulate the Inspector by handling DnD at the native level. var remainingRect = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none, GUILayout.ExpandHeight(true)); if ((Event.current.type == EventType.DragUpdated || Event.current.type == EventType.DragPerform) && remainingRect.Contains(Event.current.mousePosition)) { - DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(new[] { m_SettingsEditor.target }, Event.current.type == EventType.DragPerform); + DragAndDrop.visualMode = InternalEditorUtility.InspectorWindowDrag(new[] { settingsEditor.target }, Event.current.type == EventType.DragPerform); if (Event.current.type == EventType.DragPerform) DragAndDrop.AcceptDrag(); } @@ -91,11 +109,11 @@ public override void OnGUI(string searchContext) public override void OnTitleBarGUI() { - if (m_SettingsEditor != null) + if (settingsEditor != null) { - using (new EditorGUI.DisabledScope(!m_SettingsEditor.IsEnabled())) + using (new EditorGUI.DisabledScope(!settingsEditor.IsEnabled())) { - var tagrObjects = new[] { m_SettingsEditor.serializedObject.targetObject }; + var tagrObjects = new[] { settingsEditor.serializedObject.targetObject }; var rect = GUILayoutUtility.GetRect(Styles.settingsBtn.GetFloat(StyleKeyword.width), Styles.settingsBtn.GetFloat(StyleKeyword.height)); rect.y = Styles.settingsBtn.GetFloat(StyleKeyword.marginTop); EditorGUIUtility.DrawEditorHeaderItems(rect, tagrObjects); @@ -106,13 +124,23 @@ public override void OnTitleBarGUI() EditorUtility.DisplayObjectContextMenu(settingsRect, tagrObjects, 0); } } + base.OnTitleBarGUI(); } } public override void OnFooterBarGUI() { - if (m_SettingsEditor != null) - InspectorWindow.DrawVCSShortInfo(settingsWindow, m_SettingsEditor); + if (settingsEditor != null) + InspectorWindow.DrawVCSShortInfo(settingsWindow, settingsEditor); + } + + private static Editor CreateEditorFromSettingsObject(UnityEngine.Object settingsObj) + { + if (settingsObj != null) + { + return Editor.CreateEditor(settingsObj); + } + return null; } } } diff --git a/Editor/Mono/Settings/SettingsProvider.cs b/Editor/Mono/Settings/SettingsProvider.cs index c41f58ca89..148674f326 100644 --- a/Editor/Mono/Settings/SettingsProvider.cs +++ b/Editor/Mono/Settings/SettingsProvider.cs @@ -13,59 +13,59 @@ namespace UnityEditor { - [ExcludeFromDocs, Flags] - public enum SettingsScopes : uint + public enum SettingsScope { - None = 0, - - Any = 0xFFFFFFFF, - - User = 1U << 1, - Project = 1U << 2, - - BuiltIn = 1U << 10, - Package = 1U << 11, - - // User defined - Custom1 = 1U << 21, - Custom2 = 1U << 22, - Custom3 = 1U << 23, - Custom4 = 1U << 24, - Custom5 = 1U << 25, - Custom6 = 1U << 26, - Custom7 = 1U << 27, - Custom8 = 1U << 28, - Custom9 = 1U << 29, - - Reserved = 1U << 30, - Reserved1 = 1U << 31 + User, + Project } [ExcludeFromDocs] + public enum SettingsScopes + { + User, + Project + } + public class SettingsProvider { private string m_Label; + private string m_Name; + private HashSet m_Keywords; internal SettingsWindow settingsWindow { get; set; } + internal string[] pathTokens { get; } + internal Texture2D icon { get; set; } - public string name { get; set; } public string label { get { if (String.IsNullOrEmpty(m_Label)) - return name; + return m_Name; return m_Label; } - set { m_Label = value; } + set { m_Label = L10n.Tr(value); } + } + + public string settingsPath { get; } + public SettingsScope scope { get; private set; } + + [ExcludeFromDocs] + public SettingsScopes scopes + { + get { return (SettingsScopes)scope; } + set { scope = (SettingsScope)value; } } - public string settingsPath { get; set; } - public string[] pathTokens { get; } - public Texture2D icon { get; set; } - public HashSet keywords { get; set; } - public SettingsScopes scopes { get; set; } + public IEnumerable keywords + { + get { return m_Keywords; } + set + { + m_Keywords = new HashSet(value); + } + } public Action guiHandler { get; set; } public Action titleBarGuiHandler { get; set; } @@ -74,13 +74,13 @@ public string label public Action deactivateHandler { get; set; } public Func hasSearchInterestHandler { get; set; } - public SettingsProvider(string path, SettingsScopes scopes = SettingsScopes.Any) + public SettingsProvider(string path, SettingsScope scopes = SettingsScope.Project, IEnumerable keywords = null) { settingsPath = path; - name = Path.GetFileName(settingsPath); + m_Name = L10n.Tr(Path.GetFileName(settingsPath)); pathTokens = settingsPath.Split('/'); - this.scopes = scopes; - keywords = new HashSet(); + this.scope = scopes; + m_Keywords = keywords == null ? new HashSet() : new HashSet(keywords); } public virtual void OnActivate(string searchContext, VisualElement rootElement) @@ -125,36 +125,50 @@ public virtual void OnFooterBarGUI() footerBarGuiHandler?.Invoke(); } + public void Repaint() + { + settingsWindow.Repaint(); + } + public void PopulateSearchKeywordsFromGUIContentProperties() { - GetSearchKeywordsFromGUIContentProperties(keywords); + keywords = GetSearchKeywordsFromGUIContentProperties(); } #region Helper - public static void GetSearchKeywordsFromGUIContentProperties(ICollection searchKeywords) + public static IEnumerable GetSearchKeywordsFromGUIContentProperties() { - var keywords = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public) + return typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public) .Where(field => typeof(GUIContent).IsAssignableFrom(field.FieldType)) .Select(field => ((GUIContent)field.GetValue(null)).text) .Concat(typeof(T).GetProperties(BindingFlags.Static | BindingFlags.Public) .Where(prop => typeof(GUIContent).IsAssignableFrom(prop.PropertyType)) .Select(prop => ((GUIContent)prop.GetValue(null, null)).text)) .Where(content => content != null) - .Select(content => content.ToLowerInvariant()); + .Select(content => content.ToLowerInvariant()) + .Distinct(); + } - foreach (var keyword in keywords) + public static IEnumerable GetSearchKeywordsFromSerializedObject(SerializedObject serializedObject) + { + var keywords = new HashSet(); + var property = serializedObject.GetIterator(); + while (property.NextVisible(true)) { - searchKeywords.Add(keyword); + keywords.Add(property.displayName); } + return keywords; } - public static void GetSearchKeywordsFromSerializedObject(SerializedObject serializedObject, ICollection searchKeywords) + public static IEnumerable GetSearchKeywordsFromPath(string path) { - var property = serializedObject.GetIterator(); - while (property.NextVisible(true)) + var obj = AssetDatabase.LoadAssetAtPath(path); + if (obj != null) { - searchKeywords.Add(property.displayName); + return GetSearchKeywordsFromSerializedObject(new SerializedObject(obj)); } + + return new string[] {}; } #endregion diff --git a/Editor/Mono/Settings/SettingsProviderAttribute.cs b/Editor/Mono/Settings/SettingsProviderAttribute.cs index ab6be90eeb..4d3339e944 100644 --- a/Editor/Mono/Settings/SettingsProviderAttribute.cs +++ b/Editor/Mono/Settings/SettingsProviderAttribute.cs @@ -3,11 +3,10 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using UnityEngine.Internal; namespace UnityEditor { - [AttributeUsage(AttributeTargets.Method), ExcludeFromDocs] + [AttributeUsage(AttributeTargets.Method)] public sealed class SettingsProviderAttribute : Attribute { [RequiredSignature] @@ -17,7 +16,7 @@ private static SettingsProvider signature() } } - [AttributeUsage(AttributeTargets.Method), ExcludeFromDocs] + [AttributeUsage(AttributeTargets.Method)] public sealed class SettingsProviderGroupAttribute : Attribute { [RequiredSignature] diff --git a/Editor/Mono/Settings/SettingsService.cs b/Editor/Mono/Settings/SettingsService.cs index 2e50c92f30..706a0374f5 100644 --- a/Editor/Mono/Settings/SettingsService.cs +++ b/Editor/Mono/Settings/SettingsService.cs @@ -8,22 +8,34 @@ using System.Reflection; using System.Text; using UnityEngine; -using UnityEngine.Internal; namespace UnityEditor { - [ExcludeFromDocs] [InitializeOnLoad] - public class SettingsService + public static class SettingsService { + public static EditorWindow OpenProjectSettings(string settingsPath = null) + { + return SettingsWindow.Show(SettingsScope.Project, settingsPath); + } + + public static EditorWindow OpenUserPreferences(string settingsPath = null) + { + return SettingsWindow.Show(SettingsScope.User, settingsPath); + } + + public static void NotifySettingsProviderChanged() + { + settingsProviderChanged?.Invoke(); + } + const string k_ProjectSettings = "Edit/Project Settings"; static SettingsService() { } - public static event Action settingsProviderChanged; - - public static SettingsProvider[] FetchSettingsProviders() + internal static event Action settingsProviderChanged; + internal static SettingsProvider[] FetchSettingsProviders() { return FetchSettingProviderFromAttribute() @@ -33,9 +45,9 @@ public static SettingsProvider[] FetchSettingsProviders() .ToArray(); } - public static void NotifySettingsProviderChanged() + internal static EditorWindow OpenUserPreferenceWindow() { - settingsProviderChanged?.Invoke(); + return SettingsWindow.Show(SettingsScope.User); } private static IEnumerable FetchDeprecatedPreferenceItems() @@ -47,7 +59,7 @@ private static IEnumerable FetchDeprecatedPreferenceItems() if (callback != null) { var attributeName = (method.attribute as PreferenceItem).name; - return new SettingsProvider("Preferences/" + attributeName) { guiHandler = searchContext => callback(), scopes = SettingsScopes.User }; + return new SettingsProvider("Preferences/" + attributeName, SettingsScope.User) { guiHandler = searchContext => callback() }; } return null; diff --git a/Editor/Mono/Settings/SettingsWindow.cs b/Editor/Mono/Settings/SettingsWindow.cs index 5b6d54ad2e..85ae8e4302 100644 --- a/Editor/Mono/Settings/SettingsWindow.cs +++ b/Editor/Mono/Settings/SettingsWindow.cs @@ -20,7 +20,7 @@ internal class SettingsWindow : EditorWindow, IHasCustomMenu [SerializeField] private Vector2 m_PosLeft; [SerializeField] private Vector2 m_PosRight; - [SerializeField] private SettingsScopes m_Scopes; + [SerializeField] private SettingsScope m_Scope; [SerializeField] public float m_SplitterFlex = 0.2f; private SettingsProvider[] m_Providers; @@ -50,7 +50,7 @@ private static class Styles public SettingsWindow() { m_SearchFieldGiveFocus = true; - m_Scopes = SettingsScopes.None; + m_Scope = SettingsScope.Project; } internal SettingsProvider[] GetProviders() @@ -168,7 +168,7 @@ private void RestoreSelection() private void Init() { - m_Providers = SettingsService.FetchSettingsProviders().Where(p => (p.scopes & m_Scopes) != 0).ToArray(); + m_Providers = SettingsService.FetchSettingsProviders().Where(p => p.scope == m_Scope).ToArray(); WarnAgainstDuplicates(); @@ -331,53 +331,27 @@ private void HandleSearchFiltering() m_TreeView.searchString = m_SearchText; } - [MenuItem("Edit/All Settings &F8", false, 260, true)] - internal static void OpenAllSettings() - { - OpenAllSettings(null); - } - [MenuItem("Edit/Project Settings...", false, 259, false)] internal static void OpenProjectSettings() { - OpenProjectSettings(null); - } - - internal static SettingsWindow OpenAllSettings(string settingsPath) - { - return Show(SettingsScopes.Any, settingsPath); - } - - internal static SettingsWindow OpenProjectSettings(string settingsPath) - { - return Show(SettingsScopes.Project, settingsPath); + Show(SettingsScope.Project); } internal static SettingsWindow OpenUserPreferences() { - return OpenUserPreferences(null); - } - - internal static SettingsWindow OpenUserPreferences(string settingsPath) - { - return Show(SettingsScopes.User, settingsPath); + return Show(SettingsScope.User); } - private static SettingsWindow Create(SettingsScopes scopes) + private static SettingsWindow Create(SettingsScope scope) { var settingsWindow = CreateInstance(); - settingsWindow.m_Scopes = scopes; - if ((scopes & SettingsScopes.Project) != 0) - settingsWindow.titleContent.text = "Settings"; - else if ((scopes & SettingsScopes.User) != 0) - settingsWindow.titleContent.text = "Preferences"; - else - settingsWindow.titleContent.text = scopes.ToString(); + settingsWindow.m_Scope = scope; + settingsWindow.titleContent.text = scope == SettingsScope.Project ? "Project Settings" : "Preferences"; settingsWindow.Init(); return settingsWindow; } - internal static SettingsWindow Show(SettingsScopes scopes, string settingsPath = null) + internal static SettingsWindow Show(SettingsScope scopes, string settingsPath = null) { var settingsWindow = FindWindowByScope(scopes) ?? Create(scopes); settingsWindow.Show(); @@ -390,10 +364,10 @@ internal static SettingsWindow Show(SettingsScopes scopes, string settingsPath = return settingsWindow; } - internal static SettingsWindow FindWindowByScope(SettingsScopes scopes) + internal static SettingsWindow FindWindowByScope(SettingsScope scopes) { var settingsWindows = Resources.FindObjectsOfTypeAll(typeof(SettingsWindow)).Cast(); - return settingsWindows.FirstOrDefault(settingsWindow => (settingsWindow.m_Scopes & scopes) != 0); + return settingsWindows.FirstOrDefault(settingsWindow => settingsWindow.m_Scope == scopes); } internal class GUIScope : GUI.Scope diff --git a/Editor/Mono/Sprites/SpritePackerWindow.cs b/Editor/Mono/Sprites/SpritePackerWindow.cs index 240e2a5555..f5e504bc98 100644 --- a/Editor/Mono/Sprites/SpritePackerWindow.cs +++ b/Editor/Mono/Sprites/SpritePackerWindow.cs @@ -135,7 +135,7 @@ private bool ValidateIsPackingEnabled() EditorGUILayout.BeginVertical(); GUILayout.Label(PackerWindowStyle.packingDisabledLabel); if (GUILayout.Button(PackerWindowStyle.openProjectSettingButton)) - SettingsWindow.OpenProjectSettings("Project/Editor"); + SettingsService.OpenProjectSettings("Project/Editor"); EditorGUILayout.EndVertical(); return false; } diff --git a/Editor/Mono/SyncRiderProject.cs b/Editor/Mono/SyncRiderProject.cs index c59187447d..d65f4f125d 100644 --- a/Editor/Mono/SyncRiderProject.cs +++ b/Editor/Mono/SyncRiderProject.cs @@ -59,16 +59,16 @@ static RiderInfo[] CollectAllRiderPathsLinux() var lines = File.ReadAllLines(shortcut.FullName); foreach (var line in lines) { - if (line.StartsWith("Exec=\"")) - { - var path = line.Split('"').Where((item, index) => index == 1).SingleOrDefault(); - if (!string.IsNullOrEmpty(path)) - { - var buildTxtPath = Path.Combine(path, pathToBuildTxt); - var buildNumber = GetBuildNumber(buildTxtPath); - paths.Add(new RiderInfo(buildNumber, path, false)); - } - } + if (!line.StartsWith("Exec=\"")) + continue; + var path = line.Split('"').Where((item, index) => index == 1).SingleOrDefault(); + if (string.IsNullOrEmpty(path)) + continue; + var buildTxtPath = Path.Combine(path, pathToBuildTxt); + var buildNumber = GetBuildNumber(buildTxtPath); + if (paths.Any(a => a.Path == path)) // avoid adding similar build as from toolbox + continue; + paths.Add(new RiderInfo(buildNumber, path, false)); } } diff --git a/Editor/Mono/VersionControl/UI/VCWindowPending.cs b/Editor/Mono/VersionControl/UI/VCWindowPending.cs index 72a1f0fe6e..94e036f198 100644 --- a/Editor/Mono/VersionControl/UI/VCWindowPending.cs +++ b/Editor/Mono/VersionControl/UI/VCWindowPending.cs @@ -432,7 +432,7 @@ void OnGUI() bool showSettingsButton = Mathf.FloorToInt(position.width - s_ToolbarButtonsWidth - s_SettingsButtonWidth) > 0; if (showSettingsButton && GUILayout.Button("Settings", EditorStyles.toolbarButton)) { - SettingsWindow.OpenProjectSettings("Project/Editor"); + SettingsService.OpenProjectSettings("Project/Editor"); EditorWindow.FocusWindowIfItsOpen(); GUIUtility.ExitGUI(); } diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index 266d8fad3d..e51406be63 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -250,7 +250,14 @@ internal void GenerateAndWriteSolutionAndProjects(ScriptEditorUtility.ScriptEdit IEnumerable ParseResponseFileData(MonoIsland island) { - var systemReferenceDirectories = CSharpLanguage.GetCSharpCompiler(island._target, true, "Assembly-CSharp") == CSharpCompiler.Microsoft + var scriptAssembly = new ScriptAssembly + { + Filename = "Assembly-CSharp.dll", + Language = ScriptCompilers.CSharpSupportedLanguage, + Flags = Scripting.ScriptCompilation.AssemblyFlags.None + }; + + var systemReferenceDirectories = CSharpLanguage.GetCSharpCompiler(island._target, true, scriptAssembly) == CSharpCompiler.Microsoft && PlayerSettings.GetScriptingBackend(BuildPipeline.GetBuildTargetGroup(island._target)) == ScriptingImplementation.WinRTDotNET && !island._editor ? MicrosoftCSharpCompiler.GetClassLibraries(island._target, island._editor) : MonoLibraryHelpers.GetSystemReferenceDirectories(island._api_compatibility_level); @@ -531,8 +538,7 @@ private string ProjectHeader(MonoIsland island, if (PlayerSettingsEditor.IsLatestApiCompatibility(island._api_compatibility_level)) { - if (ScriptEditorUtility.GetScriptEditorFromPreferences() == ScriptEditorUtility.ScriptEditor.Rider - || ScriptEditorUtility.GetScriptEditorFromPreferences() == ScriptEditorUtility.ScriptEditor.VisualStudioCode) + if (ScriptEditorUtility.GetScriptEditorFromPreferences() == ScriptEditorUtility.ScriptEditor.VisualStudioCode) { targetframeworkversion = "v4.5"; } diff --git a/Modules/IMGUI/Event.cs b/Modules/IMGUI/Event.cs index d1cf68d4a2..81666b6b21 100644 --- a/Modules/IMGUI/Event.cs +++ b/Modules/IMGUI/Event.cs @@ -180,20 +180,14 @@ public static Event KeyboardEvent(string key) evt.modifiers |= EventModifiers.Alt; startIdx++; break; case '^': // Ctrl + evt.modifiers |= EventModifiers.Control; startIdx++; + break; case '%': - if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX) - // ios? - evt.modifiers |= EventModifiers.Command; - else - evt.modifiers |= EventModifiers.Control; - startIdx++; + evt.modifiers |= EventModifiers.Command; startIdx++; break; case '#': evt.modifiers |= EventModifiers.Shift; startIdx++; break; - case '_': - startIdx++; - break; default: found = false; break; @@ -268,7 +262,7 @@ public static Event KeyboardEvent(string key) { evt.character = subStr.ToLower()[0]; evt.keyCode = (KeyCode)evt.character; - if (evt.modifiers != EventModifiers.None && evt.modifiers != EventModifiers.Shift) + if (evt.modifiers != 0) evt.character = (char)0; } break; diff --git a/Modules/PresetsEditor/PresetManagerEditor.cs b/Modules/PresetsEditor/PresetManagerEditor.cs index 31d983ae32..d6685d524c 100644 --- a/Modules/PresetsEditor/PresetManagerEditor.cs +++ b/Modules/PresetsEditor/PresetManagerEditor.cs @@ -209,11 +209,9 @@ public override void OnInspectorGUI() [SettingsProvider] static SettingsProvider CreatePresetManagerProvider() { - var provider = new AssetSettingsProvider("Project/Preset Manager", "ProjectSettings/PresetManager.asset") - { - icon = EditorGUIUtility.FindTexture("UnityEditor/Presets/Preset Icon") - }; - provider.PopulateSearchKeywordsFromGUIContentProperties(); + var provider = AssetSettingsProvider.CreateProviderFromAssetPath( + "Project/Preset Manager", "ProjectSettings/PresetManager.asset", + SettingsProvider.GetSearchKeywordsFromGUIContentProperties()); return provider; } } diff --git a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs index 0ad5078c77..f399d17450 100644 --- a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshot.cs @@ -7,18 +7,21 @@ using UnityEngine.Profiling.Memory.Experimental; using UnityEditorInternal.Profiling.Memory.Experimental; using UnityEditorInternal.Profiling.Memory.Experimental.FileFormat; +using ExperimentalMemoryProfiler = UnityEngine.Profiling.Memory.Experimental.MemoryProfiler; namespace UnityEditor.Profiling.Memory.Experimental { // !!!!! NOTE: Keep in sync with Runtime\Profiler\MemorySnapshots.cpp public class PackedMemorySnapshot : IDisposable { - static readonly UInt64 kMinSupportedVersion = 7; + static readonly UInt32 kMinSupportedVersion = 7; + static readonly UInt32 kCurrentVersion = 8; + public static PackedMemorySnapshot Load(string path) { MemorySnapshotFileReader reader = new MemorySnapshotFileReader(path); - UInt64 ver = reader.GetDataSingle(EntryType.Metadata_Version, ConversionFunctions.ToUInt32); + UInt32 ver = reader.GetDataSingle(EntryType.Metadata_Version, ConversionFunctions.ToUInt32); if (ver < kMinSupportedVersion) { @@ -28,6 +31,145 @@ public static PackedMemorySnapshot Load(string path) return new PackedMemorySnapshot(reader); } + public static bool Convert(UnityEditor.MemoryProfiler.PackedMemorySnapshot snapshot, string writePath) + { + MemorySnapshotFileWriter writer = null; + + try + { + writer = new MemorySnapshotFileWriter(writePath); + } + catch (Exception e) + { + Debug.LogError("Failed to create snapshot file: " + e.Message); + return false; + } + + //snapshot version will always be the current one for convertion operations + writer.WriteEntry(EntryType.Metadata_Version, kCurrentVersion); + + //timestamp with conversion date + writer.WriteEntry(EntryType.Metadata_RecordDate, (ulong)DateTime.Now.Ticks); + + //prepare metadata + string platform = "Unknown"; + string content = "Converted Snapshot"; + int stringDataLength = (platform.Length + content.Length) * sizeof(char); + byte[] metaDataBytes = new byte[stringDataLength + (sizeof(int) * 3)]; // add space for serializing the lengths of the strings + + int offset = 0; + offset = ExperimentalMemoryProfiler.WriteIntToByteArray(metaDataBytes, offset, content.Length); + offset = ExperimentalMemoryProfiler.WriteStringToByteArray(metaDataBytes, offset, content); + + offset = ExperimentalMemoryProfiler.WriteIntToByteArray(metaDataBytes, offset, platform.Length); + offset = ExperimentalMemoryProfiler.WriteStringToByteArray(metaDataBytes, offset, platform); + + offset = ExperimentalMemoryProfiler.WriteIntToByteArray(metaDataBytes, offset, 0); + + // Write metadata + writer.WriteEntryArray(EntryType.Metadata_UserMetadata, metaDataBytes); + + writer.WriteEntry(EntryType.Metadata_CaptureFlags, (UInt32)CaptureFlags.ManagedObjects); //capture just managed + + // Write managed heap sections + for (int i = 0; i < snapshot.managedHeapSections.Length; ++i) + { + var heapSection = snapshot.managedHeapSections[i]; + writer.WriteEntry(EntryType.ManagedHeapSections_StartAddress, heapSection.startAddress); + writer.WriteEntryArray(EntryType.ManagedHeapSections_Bytes, heapSection.m_Bytes); + } + + // Write managed types + int fieldDescriptionCount = 0; + for (int i = 0; i < snapshot.typeDescriptions.Length; ++i) + { + var type = snapshot.typeDescriptions[i]; + writer.WriteEntry(EntryType.TypeDescriptions_Flags, (UInt32)type.m_Flags); + writer.WriteEntry(EntryType.TypeDescriptions_BaseOrElementTypeIndex, type.baseOrElementTypeIndex); + writer.WriteEntry(EntryType.TypeDescriptions_TypeIndex, type.typeIndex); + + if (!type.isArray) + { + var typeFields = type.fields; + int[] fieldIndices = new int[typeFields.Length]; + + for (int j = 0; j < typeFields.Length; ++j) + { + var field = typeFields[j]; + fieldIndices[j] = fieldDescriptionCount; + ++fieldDescriptionCount; + + writer.WriteEntry(EntryType.FieldDescriptions_Offset, field.offset); + writer.WriteEntry(EntryType.FieldDescriptions_TypeIndex, field.typeIndex); + writer.WriteEntry(EntryType.FieldDescriptions_Name, field.name); + writer.WriteEntry(EntryType.FieldDescriptions_IsStatic, field.isStatic); + } + + writer.WriteEntryArray(EntryType.TypeDescriptions_FieldIndices, fieldIndices); + writer.WriteEntryArray(EntryType.TypeDescriptions_StaticFieldBytes, type.staticFieldBytes); + } + else + { + writer.WriteEntryArray(EntryType.TypeDescriptions_FieldIndices, new int[0]); + writer.WriteEntryArray(EntryType.TypeDescriptions_StaticFieldBytes, new byte[0]); + } + + writer.WriteEntry(EntryType.TypeDescriptions_Name, type.name); + writer.WriteEntry(EntryType.TypeDescriptions_Assembly, type.assembly); + writer.WriteEntry(EntryType.TypeDescriptions_TypeInfoAddress, type.typeInfoAddress); + writer.WriteEntry(EntryType.TypeDescriptions_Size, type.size); + } + + //write managed gc handles + for (int i = 0; i < snapshot.gcHandles.Length; ++i) + { + var handle = snapshot.gcHandles[i]; + writer.WriteEntry(EntryType.GCHandles_Target, handle.target); + } + + //write managed connections + for (int i = 0; i < snapshot.connections.Length; ++i) + { + var connection = snapshot.connections[i]; + writer.WriteEntry(EntryType.Connections_From, connection.from); + writer.WriteEntry(EntryType.Connections_To, connection.to); + } + + //write native types + for (int i = 0; i < snapshot.nativeTypes.Length; ++i) + { + var nativeType = snapshot.nativeTypes[i]; + writer.WriteEntry(EntryType.NativeTypes_NativeBaseTypeArrayIndex, nativeType.nativeBaseTypeArrayIndex); + writer.WriteEntry(EntryType.NativeTypes_Name, nativeType.name); + } + + //write stub root reference for all native objects to point to, as the old format did not capture these + writer.WriteEntry(EntryType.NativeRootReferences_AreaName, "Invalid Root"); + writer.WriteEntry(EntryType.NativeRootReferences_AccumulatedSize, (ulong)0); + writer.WriteEntry(EntryType.NativeRootReferences_Id, (long)0); + writer.WriteEntry(EntryType.NativeRootReferences_ObjectName, "Invalid Root Object"); + + //write native objects + for (int i = 0; i < snapshot.nativeObjects.Length; ++i) + { + var nativeObject = snapshot.nativeObjects[i]; + writer.WriteEntry(EntryType.NativeObjects_Name, nativeObject.name); + writer.WriteEntry(EntryType.NativeObjects_InstanceId, nativeObject.instanceId); + writer.WriteEntry(EntryType.NativeObjects_Size, (ulong)nativeObject.size); + writer.WriteEntry(EntryType.NativeObjects_NativeTypeArrayIndex, nativeObject.nativeTypeArrayIndex); + writer.WriteEntry(EntryType.NativeObjects_HideFlags, (UInt32)nativeObject.hideFlags); + writer.WriteEntry(EntryType.NativeObjects_Flags, (UInt32)nativeObject.m_Flags); + writer.WriteEntry(EntryType.NativeObjects_NativeObjectAddress, (ulong)nativeObject.nativeObjectAddress); + writer.WriteEntry(EntryType.NativeObjects_RootReferenceId, (long)0); + } + + //write virtual machine information + writer.WriteEntry(EntryType.Metadata_VirtualMachineInformation, snapshot.virtualMachineInformation); + writer.Close(); + + return true; + } + public static void Save(PackedMemorySnapshot snapshot, string writePath) { string path = snapshot.GetReader().GetFilePath(); @@ -211,8 +353,8 @@ public DateTime recordDate { get { - double seconds = (double)m_Reader.GetDataSingle(EntryType.Metadata_RecordDate, ConversionFunctions.ToUInt64); - return new DateTime(1970, 1, 1).AddSeconds(seconds); + long ticks = m_Reader.GetDataSingle(EntryType.Metadata_RecordDate, ConversionFunctions.ToInt64); + return new DateTime(ticks); } } diff --git a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshotFileWriter.bindings.cs b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshotFileWriter.bindings.cs index 1da6f5568d..e54036dbfa 100644 --- a/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshotFileWriter.bindings.cs +++ b/Modules/ProfilerEditor/MemoryProfiler/MemorySnapshotFileWriter.bindings.cs @@ -5,6 +5,7 @@ using System; using UnityEngine.Bindings; using System.Runtime.InteropServices; +using Unity.Collections.LowLevel.Unsafe; namespace UnityEditorInternal.Profiling.Memory.Experimental { @@ -59,7 +60,7 @@ public void WriteEntry(FileFormat.EntryType entryType, T data) where T : stru try { IntPtr rawDataPtr = handle.AddrOfPinnedObject(); - int dataSize = Marshal.SizeOf(data); + int dataSize = UnsafeUtility.SizeOf(); Internal_WriteEntryData(rawDataPtr, dataSize, (int)entryType); } finally @@ -74,7 +75,7 @@ public void WriteEntryArray(FileFormat.EntryType entryType, T[] data) where T try { IntPtr rawDataPtr = handle.AddrOfPinnedObject(); - int dataSize = Marshal.SizeOf(typeof(T)); + int dataSize = UnsafeUtility.SizeOf(); int numElements = data.Length; Internal_WriteEntryDataArray(rawDataPtr, dataSize, numElements, (int)entryType); } diff --git a/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs b/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs index 5a6c077a9e..7032cd4862 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/MemorySnapshot.cs @@ -75,7 +75,7 @@ public class PackedMemorySnapshot [SerializeField] internal VirtualMachineInformation m_VirtualMachineInformation = default(VirtualMachineInformation); - internal PackedMemorySnapshot(Profiling.Memory.Experimental.PackedMemorySnapshot snapshot) + public PackedMemorySnapshot(Profiling.Memory.Experimental.PackedMemorySnapshot snapshot) { int cacheCapacity = 128; string[] cacheString = new string[cacheCapacity]; diff --git a/Modules/ShortcutManagerEditor/Directory.cs b/Modules/ShortcutManagerEditor/Directory.cs index c26d1f63a4..ce7dd6cfe4 100644 --- a/Modules/ShortcutManagerEditor/Directory.cs +++ b/Modules/ShortcutManagerEditor/Directory.cs @@ -33,41 +33,39 @@ public void Initialize(IEnumerable entries) } } - void FindShortcutEntries(List combinationSequence, List outputShortcuts, Predicate filter) + private List GetShortcutEntriesForPrimaryKey(List combinationSequence) { - outputShortcuts.Clear(); + if (combinationSequence == null || combinationSequence.Count < 1) + return null; + return m_IndexedShortcutEntries[(int)combinationSequence[0].keyCode]; + } - Assert.IsNotNull(combinationSequence); - Assert.IsTrue(combinationSequence.Count > 0, "Sequence can not be empty"); - List entries = m_IndexedShortcutEntries[(int)combinationSequence[0].keyCode]; + // These two overloads have some duplication to avoid creating predicates etc. + public void FindShortcutEntries(List combinationSequence, Type[] context, List outputShortcuts) + { + outputShortcuts.Clear(); + List entries = GetShortcutEntriesForPrimaryKey(combinationSequence); if (entries == null) return; - - m_CombinationSequence = combinationSequence; - m_Predicate = filter; foreach (var entry in entries) - if (ShortcutStartsWithCombinationSequenceAndSatisfiesPredicate(entry)) + if (entry.StartsWith(combinationSequence) && ShortcutEntryMatchesAnyContext(entry.context, context)) outputShortcuts.Add(entry); } - public void FindShortcutEntries(List combinationSequence, Type[] context, List outputShortcuts) - { - m_ShortcutEntryContextList = context; - Predicate filter = null; - if (context != null) - filter = ShortcutEntryMatchesAnyContext; - FindShortcutEntries(combinationSequence, outputShortcuts, filter); - } - public void FindShortcutEntries(List combinationSequence, IContextManager contextManager, List outputShortcuts) { - m_ContextManager = contextManager; - FindShortcutEntries(combinationSequence, outputShortcuts, ShortcutEntrySatisfiesContextManager); + outputShortcuts.Clear(); + List entries = GetShortcutEntriesForPrimaryKey(combinationSequence); + if (entries == null) + return; + foreach (var entry in entries) + if (entry.StartsWith(combinationSequence) && ShortcutEntrySatisfiesContextManager(contextManager, entry)) + outputShortcuts.Add(entry); } public void FindShortcutEntries(List combinationSequence, List outputShortcuts) { - FindShortcutEntries(combinationSequence, outputShortcuts, null); + FindShortcutEntries(combinationSequence, (Type[])null, outputShortcuts); } public ShortcutEntry FindShortcutEntry(Identifier identifier) @@ -94,36 +92,29 @@ void AddEntry(KeyCode keyCode, ShortcutEntry entry) ////////////////////////////// // Lambda elimination helpers ////////////////////////////// - static Type m_ShortcutEntryContext; - static Type[] m_ShortcutEntryContextList; - static List m_CombinationSequence; - static Predicate m_Predicate; - static IContextManager m_ContextManager; - - static bool ShortcutStartsWithCombinationSequenceAndSatisfiesPredicate(ShortcutEntry entry) - { - return entry.StartsWith(m_CombinationSequence) && (m_Predicate == null || m_Predicate(entry)); - } - - static bool ShortcutEntryMatchesAnyContext(ShortcutEntry entry) + static bool ShortcutEntryMatchesAnyContext(Type shortcutEntryContext, Type[] contextList) { - m_ShortcutEntryContext = entry.context; - return m_ShortcutEntryContextList == null || m_ShortcutEntryContextList.Any(ShortcutEntryMatchesContext); + if (contextList == null) + return true; + foreach (var type in contextList) + if (ShortcutEntryMatchesContext(shortcutEntryContext, type)) + return true; + return false; } - static bool ShortcutEntryMatchesContext(Type context) + static bool ShortcutEntryMatchesContext(Type shortcutEntryContext, Type context) { - return context == m_ShortcutEntryContext || - (m_ShortcutEntryContext != null && m_ShortcutEntryContext.IsAssignableFrom(context)); + return context == shortcutEntryContext || + (shortcutEntryContext != null && shortcutEntryContext.IsAssignableFrom(context)); } - static bool ShortcutEntrySatisfiesContextManager(ShortcutEntry entry) + static bool ShortcutEntrySatisfiesContextManager(IContextManager contextManager, ShortcutEntry entry) { - return m_ContextManager.HasActiveContextOfType(entry.context) && + return contextManager.HasActiveContextOfType(entry.context) && // Emulate old play mode shortcut behavior // * Menu shortcuts are always active // * Non-menu shortcuts only apply when the game view does not have focus - (!m_ContextManager.playModeContextIsActive || + (!contextManager.playModeContextIsActive || entry.type == ShortcutType.Menu); } } diff --git a/Modules/ShortcutManagerEditor/KeyCombination.cs b/Modules/ShortcutManagerEditor/KeyCombination.cs index 7542ebefd4..e714867d42 100644 --- a/Modules/ShortcutManagerEditor/KeyCombination.cs +++ b/Modules/ShortcutManagerEditor/KeyCombination.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Text; using System.Collections.Generic; - using UnityEngine; namespace UnityEditor.ShortcutManagement @@ -22,6 +21,46 @@ struct KeyCombination : IEquatable public KeyCode keyCode => m_KeyCode; public ShortcutModifiers modifiers => m_Modifiers; + static Dictionary s_KeyCodeToMenuItemKeyCodeString = new Dictionary() + { + { KeyCode.LeftArrow, "LEFT" }, + { KeyCode.UpArrow, "UP" }, + { KeyCode.RightArrow, "RIGHT" }, + { KeyCode.DownArrow, "DOWN" }, + + { KeyCode.PageDown, "PGDN" }, + { KeyCode.PageUp, "PGUP" }, + { KeyCode.Home, "HOME" }, + { KeyCode.Insert, "INS" }, + { KeyCode.Delete, "DEL" }, + { KeyCode.End, "END" }, + + { KeyCode.F1, "F1" }, + { KeyCode.F2, "F2" }, + { KeyCode.F3, "F3" }, + { KeyCode.F4, "F4" }, + { KeyCode.F5, "F5" }, + { KeyCode.F6, "F6" }, + { KeyCode.F7, "F7" }, + { KeyCode.F8, "F8" }, + { KeyCode.F9, "F9" }, + { KeyCode.F10, "F10" }, + { KeyCode.F11, "F11" }, + { KeyCode.F12, "F12" } + }; + + static Dictionary s_MenuItemKeyCodeStringToKeyCode; + + static KeyCombination() + { + // Populate s_MenuItemKeyCodeStringToKeyCode by reversing s_KeyCodeToMenuItemKeyCodeString + s_MenuItemKeyCodeStringToKeyCode = new Dictionary(s_KeyCodeToMenuItemKeyCodeString.Count); + foreach (var entry in s_KeyCodeToMenuItemKeyCodeString) + { + s_MenuItemKeyCodeStringToKeyCode.Add(entry.Value, entry.Key); + } + } + public KeyCombination(KeyCode keyCode, ShortcutModifiers shortcutModifiers = ShortcutModifiers.None) { m_KeyCode = keyCode; @@ -30,16 +69,20 @@ public KeyCombination(KeyCode keyCode, ShortcutModifiers shortcutModifiers = Sho internal static KeyCombination FromKeyboardInput(Event evt) { - return new KeyCombination(evt.keyCode, ConvertEventModifiersToShortcutModifiers(evt.modifiers, false)); + return FromKeyboardInput(evt.keyCode, evt.modifiers); } - internal static KeyCombination ParseLegacyBindingString(string binding) + internal static KeyCombination FromKeyboardInput(KeyCode keyCode, EventModifiers modifiers) { - var keyEvent = Event.KeyboardEvent(binding); - return new KeyCombination(keyEvent.keyCode, ConvertEventModifiersToShortcutModifiers(keyEvent.modifiers, true)); + return new KeyCombination(keyCode, ConvertEventModifiersToShortcutModifiers(modifiers, false)); } - private static ShortcutModifiers ConvertEventModifiersToShortcutModifiers(EventModifiers eventModifiers, bool coalesceCommandAndControl) + internal static KeyCombination FromPrefKeyKeyboardEvent(Event evt) + { + return new KeyCombination(evt.keyCode, ConvertEventModifiersToShortcutModifiers(evt.modifiers, true)); + } + + static ShortcutModifiers ConvertEventModifiersToShortcutModifiers(EventModifiers eventModifiers, bool coalesceCommandAndControl) { ShortcutModifiers modifiers = ShortcutModifiers.None; if ((eventModifiers & EventModifiers.Alt) != 0) @@ -117,11 +160,114 @@ public string ToMenuShortcutString() if (modifiers == ShortcutModifiers.None) builder.Append("_"); - VisualizeKeyCode(keyCode, builder); + KeyCodeToMenuItemKeyCodeString(keyCode, builder); return builder.ToString(); } + static void KeyCodeToMenuItemKeyCodeString(KeyCode keyCode, StringBuilder builder) + { + string keyCodeString; + if (s_KeyCodeToMenuItemKeyCodeString.TryGetValue(keyCode, out keyCodeString)) + { + builder.Append(keyCodeString); + return; + } + + var character = (char)keyCode; + if (character >= ' ' && character <= '@' || + character >= '[' && character <= '~') + builder.Append(character.ToString()); + } + + internal static bool TryParseMenuItemBindingString(string menuItemBindingString, out KeyCombination keyCombination) + { + if (string.IsNullOrEmpty(menuItemBindingString)) + { + keyCombination = default(KeyCombination); + return false; + } + + var modifiers = ShortcutModifiers.None; + var startIndex = 0; + var found = false; + do + { + found = true; + if (startIndex >= menuItemBindingString.Length) + { + found = false; + break; + } + + switch (menuItemBindingString[startIndex]) + { + case '&': + modifiers |= ShortcutModifiers.Alt; + startIndex++; + break; + + case '%': + modifiers |= ShortcutModifiers.ControlOrCommand; + startIndex++; + break; + + case '#': + modifiers |= ShortcutModifiers.Shift; + startIndex++; + break; + + case '_': + startIndex++; + break; + + default: + found = false; + break; + } + } + while (found); + + var keyCodeString = menuItemBindingString.Substring(startIndex, menuItemBindingString.Length - startIndex); + KeyCode keyCode; + ShortcutModifiers additionalModifiers; + if (!TryParseMenuItemKeyCodeString(keyCodeString, out keyCode, out additionalModifiers)) + { + keyCombination = default(KeyCombination); + return false; + } + + modifiers |= additionalModifiers; + keyCombination = new KeyCombination(keyCode, modifiers); + return true; + } + + static bool TryParseMenuItemKeyCodeString(string keyCodeString, out KeyCode keyCode, out ShortcutModifiers additionalModifiers) + { + keyCode = default(KeyCode); + additionalModifiers = ShortcutModifiers.None; + + if (string.IsNullOrEmpty(keyCodeString)) + return false; + + if (s_MenuItemKeyCodeStringToKeyCode.TryGetValue(keyCodeString, out keyCode)) + return true; + + if (keyCodeString.Length != 1) + return false; + + var character = keyCodeString[0]; + if (character >= 'A' && character <= 'Z') + { + keyCode = KeyCode.A + (character - 'A'); + additionalModifiers = ShortcutModifiers.Shift; + return true; + } + + keyCode = (KeyCode)character; + return Enum.IsDefined(typeof(KeyCode), keyCode); + } + static void VisualizeModifiers(ShortcutModifiers modifiers, StringBuilder builder) { if (Application.platform == RuntimePlatform.OSXEditor) diff --git a/Modules/ShortcutManagerEditor/ShortcutAttribute.cs b/Modules/ShortcutManagerEditor/ShortcutAttribute.cs index d0edad4adc..f6324a5668 100644 --- a/Modules/ShortcutManagerEditor/ShortcutAttribute.cs +++ b/Modules/ShortcutManagerEditor/ShortcutAttribute.cs @@ -47,10 +47,13 @@ public override ShortcutEntry CreateShortcutEntry(MethodInfo methodInfo) var identifier = new Identifier(methodInfo, this); IEnumerable defaultCombination; - if (defaultKeyCombination == null) - defaultCombination = Enumerable.Empty(); + + KeyCombination keyCombination; + if (KeyCombination.TryParseMenuItemBindingString(defaultKeyCombination, out keyCombination)) + defaultCombination = new[] { keyCombination }; else - defaultCombination = new[] { KeyCombination.ParseLegacyBindingString(defaultKeyCombination) }; + defaultCombination = Enumerable.Empty(); + var type = this is ClutchShortcutAttribute ? ShortcutType.Clutch : ShortcutType.Action; var methodParams = methodInfo.GetParameters(); diff --git a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs index bd8c65d1ab..c0c5cf3dbc 100644 --- a/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs +++ b/Modules/ShortcutManagerEditor/ShortcutAttributeDiscoveryProvider.cs @@ -44,11 +44,12 @@ public IEnumerable GetDefinedShortcuts() Menu.GetMenuItemDefaultShortcuts(names, defaultShortcuts); entries.Capacity += names.Count; - for (int index = 0; index < names.Count; ++index) + for (var index = 0; index < names.Count; ++index) { var keys = new List(); - if (!string.IsNullOrEmpty(defaultShortcuts[index])) - keys.Add(KeyCombination.ParseLegacyBindingString(defaultShortcuts[index])); + KeyCombination keyCombination; + if (KeyCombination.TryParseMenuItemBindingString(defaultShortcuts[index], out keyCombination)) + keys.Add(keyCombination); entries.Add(new MenuItemEntryDiscoveryInfo(names[index], keys)); } diff --git a/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs b/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs index c0262cec19..b939649ef0 100644 --- a/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs +++ b/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs @@ -91,17 +91,22 @@ IEnumerable methodsWithFormerlyPrefKeyAs, List entrie var prefKeyAttr = (FormerlyPrefKeyAsAttribute)Attribute.GetCustomAttribute(method, typeof(FormerlyPrefKeyAsAttribute)); - var prefKeyDefaultValue = KeyCombination.ParseLegacyBindingString(prefKeyAttr.defaultValue); + var prefKeyDefaultValue = $"{prefKeyAttr.name};{prefKeyAttr.defaultValue}"; string name; - string binding; Event keyboardEvent; - var parsed = PrefKey.TryParseUniquePrefString(EditorPrefs.GetString(prefKeyAttr.name, prefKeyAttr.defaultValue), out name, out keyboardEvent, out binding); - if (!parsed) + string shortcut; + if (!PrefKey.TryParseUniquePrefString(prefKeyDefaultValue, out name, out keyboardEvent, out shortcut)) continue; - var prefKeyCurrentValue = KeyCombination.ParseLegacyBindingString(binding); + var prefKeyDefaultKeyCombination = KeyCombination.FromPrefKeyKeyboardEvent(keyboardEvent); + + // Parse current pref key value (falling back on default pref key value) + if (!PrefKey.TryParseUniquePrefString(EditorPrefs.GetString(prefKeyAttr.name, prefKeyDefaultValue), out name, out keyboardEvent, out shortcut)) + continue; + var prefKeyCurrentKeyCombination = KeyCombination.FromPrefKeyKeyboardEvent(keyboardEvent); + // only migrate pref keys that the user actually overwrote - if (!prefKeyCurrentValue.Equals(prefKeyDefaultValue)) - entry.SetOverride(new List { prefKeyCurrentValue }); + if (!prefKeyCurrentKeyCombination.Equals(prefKeyDefaultKeyCombination)) + entry.SetOverride(new List { prefKeyCurrentKeyCombination }); } } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs index 9ef23fa521..d463b255e2 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridBrushEditor.cs @@ -4,7 +4,6 @@ using System.Linq; using UnityEngine; -using UnityEngine.SceneManagement; using UnityEngine.Tilemaps; using UnityEditor.SceneManagement; @@ -322,13 +321,12 @@ public virtual void FloodFillPreview(GridLayout gridLayout, GameObject brushTarg [SettingsProvider] internal static SettingsProvider CreateSettingsProvider() { - var settingsProvider = new SettingsProvider("Preferences/2D/Grid Brush") { + var settingsProvider = new SettingsProvider("Preferences/2D/Grid Brush", SettingsScope.User, SettingsProvider.GetSearchKeywordsFromGUIContentProperties()) { guiHandler = searchContext => { PreferencesGUI(); - }, scopes = SettingsScopes.User + } }; - settingsProvider.PopulateSearchKeywordsFromGUIContentProperties(); return settingsProvider; } diff --git a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs index 5bfa0dd37c..6d3fc2912a 100644 --- a/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs +++ b/Modules/TilemapEditor/Editor/Managed/Grid/GridPaintPaletteWindow.cs @@ -310,15 +310,13 @@ static void DecreaseBrushZ() [SettingsProvider] internal static SettingsProvider CreateSettingsProvider() { - var settingsProvider = new SettingsProvider("Preferences/2D/Tile Palette") + var settingsProvider = new SettingsProvider("Preferences/2D/Tile Palette", SettingsScope.User, SettingsProvider.GetSearchKeywordsFromGUIContentProperties()) { guiHandler = searchContext => { PreferencesGUI(); - }, - scopes = SettingsScopes.User + } }; - settingsProvider.PopulateSearchKeywordsFromGUIContentProperties(); return settingsProvider; } @@ -1011,7 +1009,7 @@ private void SelectTarget(int i, object o) // Do nothing here for "No" break; case 2: - var settingsWindow = SettingsWindow.Show(SettingsScopes.User); + var settingsWindow = SettingsWindow.Show(SettingsScope.User); settingsWindow.FilterProviders(TilePaletteProperties.targetEditModeLookup); break; } diff --git a/README.md b/README.md index 71397c489f..f2127cdca7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b9 C# reference source code +## Unity 2018.3.0b10 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Director/FrameData.cs b/Runtime/Export/Director/FrameData.cs index 5522247f5c..531e74c896 100644 --- a/Runtime/Export/Director/FrameData.cs +++ b/Runtime/Export/Director/FrameData.cs @@ -18,7 +18,9 @@ internal enum Flags Evaluate = 1, SeekOccured = 2, Loop = 4, - Hold = 8 + Hold = 8, + EffectivePlayStateDelayed = 16, + EffectivePlayStatePlaying = 32 } public enum EvaluationType @@ -37,6 +39,8 @@ public enum EvaluationType internal Flags m_Flags; internal PlayableOutput m_Output; + private bool HasFlags(Flags flag) { return (m_Flags & flag) == flag; } + public ulong frameId { get { return m_FrameID; } } public float deltaTime { get { return (float)m_DeltaTime; } } public float weight { get { return m_Weight; } } @@ -44,10 +48,22 @@ public enum EvaluationType public double effectiveParentDelay { get { return m_EffectiveParentDelay; } } public float effectiveParentSpeed { get { return m_EffectiveParentSpeed; } } public float effectiveSpeed { get { return m_EffectiveSpeed; } } - public EvaluationType evaluationType { get { return ((m_Flags & Flags.Evaluate) != 0) ? EvaluationType.Evaluate : EvaluationType.Playback; } } - public bool seekOccurred { get { return (m_Flags & Flags.SeekOccured) != 0; } } - public bool timeLooped { get { return (m_Flags & Flags.Loop) != 0; } } - public bool timeHeld { get { return (m_Flags & Flags.Hold) != 0; } } + public EvaluationType evaluationType { get { return HasFlags(Flags.Evaluate) ? EvaluationType.Evaluate : EvaluationType.Playback; } } + public bool seekOccurred { get { return HasFlags(Flags.SeekOccured); } } + public bool timeLooped { get { return HasFlags(Flags.Loop); } } + public bool timeHeld { get { return HasFlags(Flags.Hold); } } public PlayableOutput output { get { return m_Output; } } + + public PlayState effectivePlayState + { + get + { + if (HasFlags(Flags.EffectivePlayStateDelayed)) + return PlayState.Delayed; + if (HasFlags(Flags.EffectivePlayStatePlaying)) + return PlayState.Playing; + return PlayState.Paused; + } + } } } diff --git a/Runtime/Export/Scripting/GarbageCollector.bindings.cs b/Runtime/Export/Scripting/GarbageCollector.bindings.cs index 3ed1d0271e..1f4783fb0b 100644 --- a/Runtime/Export/Scripting/GarbageCollector.bindings.cs +++ b/Runtime/Export/Scripting/GarbageCollector.bindings.cs @@ -17,7 +17,7 @@ public enum Mode Enabled = 1, } - public static Action GCModeChanged; + public static event Action GCModeChanged; public static Mode GCMode { diff --git a/Runtime/Export/SystemInfo.bindings.cs b/Runtime/Export/SystemInfo.bindings.cs index 23fa6dc4ed..f073385d04 100644 --- a/Runtime/Export/SystemInfo.bindings.cs +++ b/Runtime/Export/SystemInfo.bindings.cs @@ -219,6 +219,11 @@ public static bool hasHiddenSurfaceRemovalOnGPU get { return HasHiddenSurfaceRemovalOnGPU(); } } + public static bool hasDynamicUniformArrayIndexingInFragmentShaders + { + get { return HasDynamicUniformArrayIndexingInFragmentShaders(); } + } + // Are built-in shadows supported? (RO) public static bool supportsShadows { @@ -535,6 +540,9 @@ public static int graphicsPixelFillrate [FreeFunction("ScriptingGraphicsCaps::HasHiddenSurfaceRemovalOnGPU")] static extern bool HasHiddenSurfaceRemovalOnGPU(); + [FreeFunction("ScriptingGraphicsCaps::HasDynamicUniformArrayIndexingInFragmentShaders")] + static extern bool HasDynamicUniformArrayIndexingInFragmentShaders(); + [FreeFunction("ScriptingGraphicsCaps::SupportsShadows")] static extern bool SupportsShadows(); diff --git a/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs b/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs index 38177b0d47..b37920679e 100644 --- a/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs +++ b/Runtime/Profiler/ScriptBindings/MemoryProfiling.bindings.cs @@ -127,7 +127,7 @@ static byte[] PrepareMetadata() return metaDataBytes; } - private static int WriteIntToByteArray(byte[] array, int offset, int value) + internal static int WriteIntToByteArray(byte[] array, int offset, int value) { unsafe { @@ -141,7 +141,7 @@ private static int WriteIntToByteArray(byte[] array, int offset, int value) return offset; } - private static int WriteStringToByteArray(byte[] array, int offset, string value) + internal static int WriteStringToByteArray(byte[] array, int offset, string value) { if (value.Length != 0) { diff --git a/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs b/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs index 51484d3ada..b680af3e81 100644 --- a/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs +++ b/artifacts/generated/bindings_old/common/Editor/ModuleMetadataBindings.gen.cs @@ -54,6 +54,10 @@ public static UnityType[] GetModuleTypes(string moduleName) [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static ModuleIncludeSetting GetModuleIncludeSettingForObject (Object o) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration + [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] + extern internal static string GetModuleForObject (Object o) ; + [UnityEngine.Scripting.GeneratedByOldBindingsGeneratorAttribute] // Temporarily necessary for bindings migration [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)0x1000)] extern internal static string GetExcludingModuleForObject (Object o) ; From 4fa30e9632f486cbaf9b34c130ca6af3d49d73c9 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 21 Nov 2018 13:58:06 +0000 Subject: [PATCH 09/10] Unity 2018.3.0b11 C# reference source code --- .../AnimationWindow/AnimationWindowUtility.cs | 21 ++- Editor/Mono/BuildPipeline/AssemblyStripper.cs | 1 + .../DesktopStandaloneBuildWindowExtension.cs | 4 + Editor/Mono/EditorHandles/Disc.cs | 10 +- Editor/Mono/EditorHandles/RotationHandle.cs | 8 +- Editor/Mono/GUI/PopupWindow.cs | 7 + Editor/Mono/GUI/PopupWindowWithoutFocus.cs | 12 ++ Editor/Mono/GameView/GameView.cs | 29 ++-- Editor/Mono/InternalEditorUtility.cs | 2 - .../PrefabOverridesTreeView.cs | 91 +++++------ .../PrefabOverrides/PrefabOverridesWindow.cs | 80 ++++++---- .../Mono/ProjectWindow/ProjectWindowUtil.cs | 6 - .../StageManager/PrefabStage/PrefabStage.cs | 33 ++-- .../PrefabStage/PrefabStageUtility.cs | 63 ++++---- .../Mono/Scripting/Compilers/BooCompiler.cs | 67 -------- .../Compilers/BooCompilerOutputParser.cs | 34 ----- .../Mono/Scripting/Compilers/BooLanguage.cs | 40 ----- .../Compilers/ResponseFileProvider.cs | 10 +- .../Scripting/Compilers/ScriptCompilerBase.cs | 96 ++++++------ .../Compilers/UnityScriptCompiler.cs | 97 ------------ .../UnityScriptCompilerOutputParser.cs | 34 ----- .../Compilers/UnityScriptLanguage.cs | 26 ---- .../Scripting/ScriptCompilation/AssetPath.cs | 5 + .../ScriptCompilation/CompilationTask.cs | 10 +- .../ScriptCompilation/EditorBuildRules.cs | 14 +- .../ScriptCompilation/EditorCompilation.cs | 63 ++++++-- Editor/Mono/Scripting/ScriptCompilers.cs | 2 - Editor/Mono/Settings.cs | 2 +- .../SolutionSynchronizer.cs | 6 +- .../ImportSettings/ScriptedImporterEditor.cs | 15 +- .../ScriptBindings/Physics2D.bindings.cs | 143 ++---------------- .../RestService/ProjectStateRestHandler.cs | 2 +- Modules/TerrainEditor/TerrainInspector.cs | 15 +- .../ScriptBindings/FontEngine.bindings.cs | 102 ++++++++++++- .../Public/UnityAnalytics.bindings.cs | 7 + .../UnityAnalytics/Public/UnityAnalytics.cs | 10 ++ Projects/CSharp/UnityEditor.csproj | 18 --- README.md | 2 +- Runtime/Dynamics/Managed/Dynamics.cs | 44 +++++- .../ScriptBindings/Dynamics.bindings.cs | 1 + Runtime/Export/Application.bindings.cs | 2 +- .../SerializableManagedRefTests.Resources.cs | 8 +- 42 files changed, 545 insertions(+), 697 deletions(-) delete mode 100644 Editor/Mono/Scripting/Compilers/BooCompiler.cs delete mode 100644 Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/BooLanguage.cs delete mode 100644 Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs delete mode 100644 Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs delete mode 100644 Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs index 6bc2b4052a..49977f06b9 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs @@ -1036,12 +1036,21 @@ public static int GetPropertyNodeID(int setId, string path, System.Type type, st // What is the first animation player component (Animator or Animation) when recursing parent tree toward root public static Component GetClosestAnimationPlayerComponentInParents(Transform tr) { - Animator animator = GetClosestAnimatorInParents(tr); - if (animator != null) - return animator; - Animation animation = GetClosestAnimationInParents(tr); - if (animation != null) - return animation; + while (true) + { + var animator = tr.GetComponent(); + if (animator != null) + return animator; + + var animation = tr.GetComponent(); + if (animation != null) + return animation; + + if (tr == tr.root) + break; + + tr = tr.parent; + } return null; } diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index 26b5b3a9fe..baccbda1ec 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -81,6 +81,7 @@ private static bool StripAssembliesTo(string[] assemblies, string[] searchDirs, args.Add($"--dotnetruntime={GetRuntimeArgumentValueForLinker(buildTargetGroup)}"); args.Add($"--dotnetprofile={GetProfileArgumentValueForLinker(buildTargetGroup)}"); args.Add("--use-editor-options"); + args.Add($"--include-directory={CommandLineFormatter.PrepareFileName(workingDirectory)}"); if (EditorUserBuildSettings.allowDebugging) args.Add("--editor-settings-flag=AllowDebugging"); diff --git a/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs b/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs index 4cba449433..1badf4191c 100644 --- a/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs +++ b/Editor/Mono/BuildPipeline/DesktopStandaloneBuildWindowExtension.cs @@ -138,6 +138,8 @@ private static BuildTarget DefaultArchitectureForTarget(BuildTarget target) } } + protected virtual void ShowArchitectureSpecificOptions() {} + public override void ShowPlatformBuildOptions() { BuildTarget selectedTarget = GetBestStandaloneTarget(EditorUserBuildSettings.selectedStandaloneTarget); @@ -181,6 +183,8 @@ public override void ShowPlatformBuildOptions() GUIUtility.ExitGUI(); } + ShowArchitectureSpecificOptions(); + EditorUserBuildSettings.enableHeadlessMode = EditorGUILayout.Toggle(m_HeadlessMode, EditorUserBuildSettings.enableHeadlessMode); ShowIl2CppErrorIfNeeded(); diff --git a/Editor/Mono/EditorHandles/Disc.cs b/Editor/Mono/EditorHandles/Disc.cs index 82982da2b8..3a598040d7 100644 --- a/Editor/Mono/EditorHandles/Disc.cs +++ b/Editor/Mono/EditorHandles/Disc.cs @@ -27,7 +27,9 @@ public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vecto public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vector3 axis, float size, bool cutoffPlane, float snap, bool enableRayDrag, bool showHotArc, Color fillColor) { - if (Mathf.Abs(Vector3.Dot(Camera.current.transform.forward, axis)) > .999f) + var cam = Handles.inverseMatrix.MultiplyVector(Camera.current.transform.forward); + + if (Mathf.Abs(Vector3.Dot(cam, axis)) > .999f) cutoffPlane = false; Event evt = Event.current; @@ -38,7 +40,7 @@ public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vecto float d; if (cutoffPlane) { - Vector3 from = Vector3.Cross(axis, Camera.current.transform.forward).normalized; + Vector3 from = Vector3.Cross(axis, cam).normalized; d = HandleUtility.DistanceToArc(position, axis, from, 180, size) * k_GrabZoneScale; } else @@ -57,7 +59,7 @@ public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vecto Tools.LockHandlePosition(); if (cutoffPlane) { - Vector3 from = Vector3.Cross(axis, Camera.current.transform.forward).normalized; + Vector3 from = Vector3.Cross(axis, cam).normalized; s_StartPosition = HandleUtility.ClosestPointToArc(position, axis, from, 180, size); } else @@ -167,7 +169,7 @@ public static Quaternion Do(int id, Quaternion rotation, Vector3 position, Vecto Handles.DrawWireDisc(position, axis, size); else if (GUIUtility.hotControl != id && cutoffPlane) { - Vector3 from = Vector3.Cross(axis, Camera.current.transform.forward).normalized; + Vector3 from = Vector3.Cross(axis, cam).normalized; Handles.DrawWireArc(position, axis, from, 180, size); } diff --git a/Editor/Mono/EditorHandles/RotationHandle.cs b/Editor/Mono/EditorHandles/RotationHandle.cs index 6af976af0c..c39afcaea8 100644 --- a/Editor/Mono/EditorHandles/RotationHandle.cs +++ b/Editor/Mono/EditorHandles/RotationHandle.cs @@ -130,7 +130,7 @@ public static Quaternion DoRotationHandle(Quaternion rotation, Vector3 position) internal static Quaternion DoRotationHandle(RotationHandleIds ids, Quaternion rotation, Vector3 position, RotationHandleParam param) { var evt = Event.current; - var camTr = Camera.current.transform; + var camForward = Handles.inverseMatrix.MultiplyVector(Camera.current.transform.forward); var size = HandleUtility.GetHandleSize(position); var temp = color; @@ -167,13 +167,13 @@ internal static Quaternion DoRotationHandle(RotationHandleIds ids, Quaternion ro if (radiusOfAxesHandles > 0 && evt.type == EventType.Repaint) { Handles.color = new Color(0, 0, 0, 0.2f); - Handles.DrawWireDisc(position, camTr.forward, radiusOfAxesHandles); + Handles.DrawWireDisc(position, camForward, radiusOfAxesHandles); } if (isHot && evt.type == EventType.Repaint) { color = ToActiveColorSpace(s_DisabledHandleColor); - Handles.DrawWireDisc(position, camTr.forward, size * param.axisSize[0]); + Handles.DrawWireDisc(position, camForward, size * param.axisSize[0]); } if (!isStatic @@ -181,7 +181,7 @@ internal static Quaternion DoRotationHandle(RotationHandleIds ids, Quaternion ro && (isHot && ids.cameraAxis == GUIUtility.hotControl || !isHot)) { color = ToActiveColorSpace(centerColor); - rotation = UnityEditorInternal.Disc.Do(ids.cameraAxis, rotation, position, Camera.current.transform.forward, size * param.cameraAxisSize, false, 0, param.enableRayDrag, true, k_RotationPieColor); + rotation = UnityEditorInternal.Disc.Do(ids.cameraAxis, rotation, position, camForward, size * param.cameraAxisSize, false, 0, param.enableRayDrag, true, k_RotationPieColor); } color = temp; diff --git a/Editor/Mono/GUI/PopupWindow.cs b/Editor/Mono/GUI/PopupWindow.cs index 6bf252c585..f24858ac39 100644 --- a/Editor/Mono/GUI/PopupWindow.cs +++ b/Editor/Mono/GUI/PopupWindow.cs @@ -123,8 +123,15 @@ protected virtual void OnDisable() AssemblyReloadEvents.beforeAssemblyReload -= CloseWindow; s_LastClosedTime = EditorApplication.timeSinceStartup; + CloseContent(); + } + + // Change to private protected once available in C#. + internal void CloseContent() + { if (m_WindowContent != null) m_WindowContent.OnClose(); + m_WindowContent = null; } } } diff --git a/Editor/Mono/GUI/PopupWindowWithoutFocus.cs b/Editor/Mono/GUI/PopupWindowWithoutFocus.cs index 49f5ec594f..0641e89087 100644 --- a/Editor/Mono/GUI/PopupWindowWithoutFocus.cs +++ b/Editor/Mono/GUI/PopupWindowWithoutFocus.cs @@ -21,6 +21,14 @@ class PopupWindowWithoutFocus : PopupWindow internal new static void Show(Rect activatorRect, PopupWindowContent windowContent, PopupLocation[] locationPriorityOrder) { + if (windowContent == null) + throw new System.ArgumentNullException(nameof(windowContent)); + + if (s_PopupWindowWithoutFocus != null) + { + s_PopupWindowWithoutFocus.CloseContent(); + } + if (ShouldShowWindow(activatorRect)) { if (s_PopupWindowWithoutFocus == null) @@ -28,6 +36,10 @@ class PopupWindowWithoutFocus : PopupWindow s_PopupWindowWithoutFocus.Init(activatorRect, windowContent, locationPriorityOrder, ShowMode.PopupMenu, false); } + else + { + windowContent.OnClose(); + } } public static bool IsVisible() diff --git a/Editor/Mono/GameView/GameView.cs b/Editor/Mono/GameView/GameView.cs index 8f0c17b335..2327cf4983 100644 --- a/Editor/Mono/GameView/GameView.cs +++ b/Editor/Mono/GameView/GameView.cs @@ -297,11 +297,6 @@ Rect targetInParent // Area of the render target in parent view space float gameMouseScale { get { return EditorGUIUtility.pixelsPerPoint / m_ZoomArea.scale.y; } } - Vector2 WindowToGameMousePosition(Vector2 windowMousePosition) - { - return (windowMousePosition + gameMouseOffset) * gameMouseScale; - } - void InitializeZoomArea() { m_ZoomArea = new ZoomableArea(true, false); @@ -382,7 +377,6 @@ private void UpdateZoomAreaAndParent() EnforceZoomAreaConstraints(); } - CopyDimensionsToParentView(); m_LastWindowPixelSize = position.size * EditorGUIUtility.pixelsPerPoint; EditorApplication.SetSceneRepaintDirty(); @@ -417,12 +411,6 @@ private void OnLostFocus() InternalEditorUtility.OnGameViewFocus(false); } - internal void CopyDimensionsToParentView() - { - if (m_Parent) - SetParentGameViewDimensions(targetInParent, clippedTargetInParent, targetSize); - } - // Call when number of available aspects can have changed (after deserialization or gui change) private void EnsureSelectedSizeAreValid() { @@ -796,9 +784,6 @@ private void OnGUI() DoToolbarGUI(); - // Setup game view dimensions, so that player loop can use it for input - CopyDimensionsToParentView(); - // This isn't ideal. Custom Cursors set by editor extensions for other windows can leak into the game view. // To fix this we should probably stop using the global custom cursor (intended for runtime) for custom editor cursors. // This has been noted for Cursors tech debt. @@ -830,15 +815,23 @@ private void OnGUI() if (playing) EditorGUIUtility.keyboardControl = 0; - var editorMousePosition = Event.current.mousePosition; - var gameMousePosition = WindowToGameMousePosition(editorMousePosition); - GUI.color = Color.white; // Get rid of play mode tint var originalEventType = Event.current.type; m_ZoomArea.BeginViewGUI(); + // Setup game view dimensions, so that player loop can use it for input + var gameViewTarget = GUIClip.UnclipToWindow(m_ZoomArea.drawRect); + if (m_Parent) + { + var zoomedTarget = new Rect(targetInView.position + gameViewTarget.position, targetInView.size); + SetParentGameViewDimensions(zoomedTarget, gameViewTarget, targetSize); + } + + var editorMousePosition = Event.current.mousePosition; + var gameMousePosition = (editorMousePosition + gameMouseOffset) * gameMouseScale; + if (type == EventType.Repaint) { GUI.Box(m_ZoomArea.drawRect, GUIContent.none, Styles.gameViewBackgroundStyle); diff --git a/Editor/Mono/InternalEditorUtility.cs b/Editor/Mono/InternalEditorUtility.cs index 93b1b3bd92..1027867728 100644 --- a/Editor/Mono/InternalEditorUtility.cs +++ b/Editor/Mono/InternalEditorUtility.cs @@ -28,11 +28,9 @@ public static Texture2D FindIconForFile(string fileName) // Most .asset files use their scriptable object defined icon instead of a default one. case "asset": return AssetDatabase.GetCachedIcon(fileName) as Texture2D ?? EditorGUIUtility.FindTexture("GameManager Icon"); - case "boo": return EditorGUIUtility.FindTexture("boo Script Icon"); case "cginc": return EditorGUIUtility.FindTexture("CGProgram Icon"); case "cs": return EditorGUIUtility.FindTexture("cs Script Icon"); case "guiskin": return EditorGUIUtility.FindTexture(typeof(GUISkin)); - case "js": return EditorGUIUtility.FindTexture("Js Script Icon"); case "dll": return EditorGUIUtility.FindTexture("Assembly Icon"); case "asmdef": return EditorGUIUtility.FindTexture(typeof(AssemblyDefinitionAsset)); case "mat": return EditorGUIUtility.FindTexture(typeof(Material)); diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs index 8c582ab7ad..58fb342d02 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs @@ -20,7 +20,7 @@ class PrefabOverridesTreeView : TreeView string m_PrefabAssetPath { get; set; } GameObject m_PrefabInstanceRoot { get; set; } GameObject m_PrefabAssetRoot { get; set; } - int m_ShowPreviewForID = -1; + int m_LastShownPreviewWindowRowID = -1; enum ToggleValue { FALSE, TRUE, MIXED }; enum ItemType { PREFAB_OBJECT, ADDED_OBJECT, REMOVED_OBJECT }; @@ -397,69 +397,54 @@ protected override void RowGUI(RowGUIArgs args) } } - DoPreviewPopup(item, args.rowRect); + if (args.selected && state.selectedIDs.Count == 1 && item.id != m_LastShownPreviewWindowRowID) + { + DoPreviewPopup(item, args.rowRect); + } + // Ensure preview is shown when clicking on an already selected item (the preview might have been closed) + if (Event.current.type == EventType.MouseDown && args.rowRect.Contains(Event.current.mousePosition)) + { + DoPreviewPopup(item, args.rowRect); + } } void DoPreviewPopup(PrefabOverridesTreeViewItem item, Rect rowRect) { - if (item != null) + if (item == null || item.obj == null) + return; + + if (PopupWindowWithoutFocus.IsVisible()) { - // Ensure preview is shown when clicking on an already selected item (the preview might have been closed) - if (Event.current.type == EventType.MouseDown && rowRect.Contains(Event.current.mousePosition) && !PopupWindowWithoutFocus.IsVisible()) - m_ShowPreviewForID = item.id; + if (item.id == m_LastShownPreviewWindowRowID) + return; + } - // Show preview - if (item.id == m_ShowPreviewForID && Event.current.type != EventType.Layout) - { - m_ShowPreviewForID = -1; - if (item.obj != null) - { - Rect buttonRect = rowRect; - buttonRect.width = EditorGUIUtility.currentViewWidth; - Object rowObject = item.obj; + Rect buttonRect = rowRect; + buttonRect.width = EditorGUIUtility.currentViewWidth; + Object rowObject = item.obj; - Object instance, source; - if (item.type == ItemType.REMOVED_OBJECT) - { - instance = null; - source = rowObject; - } - else if (item.type == ItemType.ADDED_OBJECT) - { - instance = rowObject; - source = null; - } - else - { - instance = rowObject; - source = PrefabUtility.GetCorrespondingObjectFromSource(rowObject); - } - - PopupWindowWithoutFocus.Show( - buttonRect, - new ComparisonViewPopup(source, instance, item.singleModification, this), - new[] { PopupLocation.Right, PopupLocation.Left, PopupLocation.Below }); - } - } + Object instance, source; + if (item.type == ItemType.REMOVED_OBJECT) + { + instance = null; + source = rowObject; } - } - - protected override void SelectionChanged(IList selectedIds) - { - base.SelectionChanged(selectedIds); - if (selectedIds.Count == 1) + else if (item.type == ItemType.ADDED_OBJECT) { - // Not guaranteed to be a PrefabOverridesTreeViewItem. - // If there are no overrides, the one item in the tree is not. - var selectedItem = FindItem(selectedIds[0], rootItem) as PrefabOverridesTreeViewItem; - if (selectedItem != null && selectedItem.obj != null) - { - m_ShowPreviewForID = selectedIds[0]; - return; - } + instance = rowObject; + source = null; + } + else + { + instance = rowObject; + source = PrefabUtility.GetCorrespondingObjectFromSource(rowObject); } - PopupWindowWithoutFocus.Hide(); + m_LastShownPreviewWindowRowID = item.id; + PopupWindowWithoutFocus.Show( + buttonRect, + new ComparisonViewPopup(source, instance, item.singleModification, this), + new[] { PopupLocation.Right, PopupLocation.Left, PopupLocation.Below }); } public GameObject selectedGameObject diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs index 1d23d08821..968efeb789 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs @@ -47,6 +47,20 @@ static class Styles public static GUIContent instanceLabel = EditorGUIUtility.TrTextContent("Overrides to"); public static GUIContent contextLabel = EditorGUIUtility.TrTextContent("in"); + public static GUIContent infoMultiple = EditorGUIUtility.TrTextContent("Multiple Prefabs selected. Cannot show overrides."); + public static GUIContent infoMultipleNoApply = EditorGUIUtility.TrTextContent("Multiple Prefabs selected. Cannot show overrides.\nApplying is not possible for one or more Prefabs. Select individual Prefabs for details."); + + // Messages related to the overrides list. + public static GUIContent infoModel = EditorGUIUtility.TrTextContent("Click on individual items to review and revert.\nApplying to a Model Prefab is not possible."); + public static GUIContent infoDefault = EditorGUIUtility.TrTextContent("Click on individual items to review, revert and apply."); + public static GUIContent infoNoApply = EditorGUIUtility.TrTextContent("Click on individual items to review and revert."); + public static GUIContent warningDisconnected = EditorGUIUtility.TrTextContent("Disconnected. Cannot show overrides."); + + // Messages related to reasons for inability to apply. + public static GUIContent warningInvalidAsset = EditorGUIUtility.TrTextContent("The Prefab file contains an invalid script. Applying is not possible. Enter Prefab Mode and remove or recover the script."); + public static GUIContent warningInvalidInstance = EditorGUIUtility.TrTextContent("The Prefab instance contains an invalid script. Applying is not possible. Remove or recover the script."); + public static GUIContent warningImmutable = EditorGUIUtility.TrTextContent("The Prefab file is immutable. Applying is not possible."); + public static GUIStyle boldRightAligned; static Styles() @@ -112,6 +126,15 @@ bool DisplayingTreeView() return m_AnyOverrides && !HasMultiSelection(); } + bool IsShowingApplyWarning() + { + return + !HasMultiSelection() && + (m_AnyOverrides || m_Disconnected) && + !m_ModelPrefab && + (m_InvalidComponentOnInstance || m_InvalidComponentOnAsset || m_Immutable); + } + public override Vector2 GetWindowSize() { var height = k_HeaderHeight; @@ -125,8 +148,10 @@ public override Vector2 GetWindowSize() if (DisplayingTreeView()) height += k_TreeViewPadding.top + m_TreeView.totalHeight + k_TreeViewPadding.bottom; - if (IsShowingActionButton()) - height += k_ApplyButtonHeight + k_HelpBoxHeight; + height += k_ApplyButtonHeight + k_HelpBoxHeight; + + if (IsShowingApplyWarning()) + height += k_HelpBoxHeight; // A second help box in this case. } // Width should be no smaller than minimum width, but we could potentially improve @@ -177,44 +202,41 @@ public override void OnGUI(Rect rect) if (HasMultiSelection()) { if (m_InvalidComponentOnAsset || m_InvalidComponentOnInstance || m_ModelPrefab || m_Immutable) - EditorGUILayout.HelpBox( - "Multiple Prefabs selected. Cannot show overrides.\nApplying is not possible for one or more Prefabs. Select individual Prefabs for details.", - MessageType.Info); + EditorGUILayout.HelpBox(Styles.infoMultipleNoApply.text, MessageType.Info); else - EditorGUILayout.HelpBox( - "Multiple Prefabs selected. Cannot show overrides.", - MessageType.Info); + EditorGUILayout.HelpBox(Styles.infoMultiple.text, MessageType.Info); } else { if (m_Disconnected) { - EditorGUILayout.HelpBox("Disconnected. Cannot show overrides.", MessageType.Warning); + EditorGUILayout.HelpBox(Styles.warningDisconnected.text, MessageType.Warning); } else if (m_AnyOverrides) { Rect treeViewRect = GUILayoutUtility.GetRect(100, 1000, 0, 1000); m_TreeView.OnGUI(treeViewRect); + // Display info message telling user they can click on individual items for more detailed actions. + if (m_ModelPrefab) + EditorGUILayout.HelpBox(Styles.infoModel.text, MessageType.Info); + else if (m_Immutable || m_InvalidComponentOnInstance) + EditorGUILayout.HelpBox(Styles.infoNoApply.text, MessageType.Info); + else + EditorGUILayout.HelpBox(Styles.infoDefault.text, MessageType.Info); + } + + if (IsShowingApplyWarning()) + { + // Display warnings about edge cases that make it impossible to apply. + // Model Prefabs are not an edge case and not needed to warn about so it's + // not included here but rather combined into the info message above. if (m_InvalidComponentOnAsset) - EditorGUILayout.HelpBox( - "Click on individual items to review and revert.\nThe Prefab file contains an invalid script. Applying is not possible. Enter Prefab Mode and remove the script.", - MessageType.Info); + EditorGUILayout.HelpBox(Styles.warningInvalidAsset.text, MessageType.Warning); else if (m_InvalidComponentOnInstance) - EditorGUILayout.HelpBox( - "Click on individual items to review and revert.\nThe Prefab instance contains an invalid script. Applying is not possible. Remove the script.", - MessageType.Info); - else if (m_ModelPrefab) - EditorGUILayout.HelpBox( - "Click on individual items to review and revert.\nApplying to a model Prefab is not possible.", - MessageType.Info); - else if (m_Immutable) - EditorGUILayout.HelpBox( - "Click on individual items to review and revert.\nThe Prefab file is immutable. Applying is not possible.", - MessageType.Info); + EditorGUILayout.HelpBox(Styles.warningInvalidInstance.text, MessageType.Warning); else - EditorGUILayout.HelpBox("Click on individual items to review, revert and apply.", - MessageType.Info); + EditorGUILayout.HelpBox(Styles.warningImmutable.text, MessageType.Warning); } } @@ -263,10 +285,10 @@ bool ApplyAll() // If more than one instance of the same Prefab Asset, show dialog to user. if (multipleOfSame && !EditorUtility.DisplayDialog( - "Multiple instances of same Prefab Asset", - "Multiple instances of the same Prefab Asset were detected. Potentially conflicting overrides will be applied sequentially and will overwrite each other.", - "OK", - "Cancel")) + L10n.Tr("Multiple instances of same Prefab Asset"), + L10n.Tr("Multiple instances of the same Prefab Asset were detected. Potentially conflicting overrides will be applied sequentially and will overwrite each other."), + L10n.Tr("OK"), + L10n.Tr("Cancel"))) return false; // Make sure assets are checked out in version control. diff --git a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs index 510893410e..7fbb500d5c 100644 --- a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs +++ b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs @@ -288,15 +288,9 @@ static void CreateScriptAsset(string templatePath, string destName) Texture2D icon = null; switch (Path.GetExtension(destName)) { - case ".js": - icon = EditorGUIUtility.IconContent("js Script Icon").image as Texture2D; - break; case ".cs": icon = EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D; break; - case ".boo": - icon = EditorGUIUtility.IconContent("boo Script Icon").image as Texture2D; - break; case ".shader": icon = EditorGUIUtility.IconContent().image as Texture2D; break; diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index abbe1ee12b..77604461f3 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -145,15 +145,7 @@ internal bool LoadStage(string prefabPath) if (m_PrefabContentsRoot != null) { - // Create the environment scene and move the prefab root to this scene to ensure the correct rendersettings (skybox etc) are used in Prefab Mode. - string environmentEditingScenePath = PrefabStageUtility.GetEnvironmentScenePathForPrefab(m_PrefabContentsRoot); - Scene environmentScene = PrefabStageUtility.CreatePreviewScene(environmentEditingScenePath); - environmentScene.name = m_PrefabContentsRoot.name; - SceneManager.MoveGameObjectToScene(m_PrefabContentsRoot, environmentScene); - if (!PrefabStageUtility.HandleAutoReparenting(m_PrefabContentsRoot, environmentScene)) - { - m_PrefabContentsRoot.transform.SetAsFirstSibling(); - } + Scene environmentScene = PrefabStageUtility.MovePrefabRootToEnvironmentScene(m_PrefabContentsRoot); // Close the temporary prefab loading scene and set the environment scene as the scene of the stage EditorSceneManager.ClosePreviewScene(m_PreviewScene); @@ -179,6 +171,11 @@ internal void OpenStage(string prefabPath) if (prefabStageOpened != null) { prefabStageOpened(this); + + // Update environment scene objects after the 'prefabStageOpened' user callback so we can + // ensure: correct hideflags and that our prefab root is not under a prefab instance (which would mark it as an added object). + // Note: The user can have reparented and created new GameObjects in the environment scene during this callback. + EnsureParentOfPrefabRootIsUnpacked(); UpdateEnvironmentHideFlags(); } } @@ -275,6 +272,19 @@ void UpdateEnvironmentHideFlags() m_HideFlagUtility.UpdateEnvironmentHideFlags(); } + void EnsureParentOfPrefabRootIsUnpacked() + { + var parent = m_PrefabContentsRoot.transform.parent; + if (parent != null) + { + if (PrefabUtility.IsPartOfPrefabInstance(parent)) + { + var outerMostPrefabInstance = PrefabUtility.GetOutermostPrefabInstanceRoot(parent); + PrefabUtility.UnpackPrefabInstance(outerMostPrefabInstance, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); + } + } + } + bool isTextFieldCaretShowing { get { return EditorGUI.IsEditingTextField() && !EditorGUIUtility.textFieldHasSelection; } @@ -346,6 +356,11 @@ internal bool SavePrefab() if (prefabSaved != null) prefabSaved(m_PrefabContentsRoot); + + // After saving the Prefab any Prefab instances in the environment scene + // that are dependent on the saved Prefab will have lost their hideflags + // so here we set them again. + UpdateEnvironmentHideFlags(); } else { diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs index 39397c380e..13e746dafd 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs @@ -102,12 +102,12 @@ internal static GameObject LoadPrefabIntoPreviewScene(string prefabAssetPath, Sc return prefabInstanceRoot; } - internal static string GetEnvironmentScenePathForPrefab(GameObject prefabInstanceRoot) + static string GetEnvironmentScenePathForPrefab(bool isUIPrefab) { string environmentEditingScenePath = ""; // If prefab root has RectTransform, try to use UI environment. - if (prefabInstanceRoot.GetComponent() != null) + if (isUIPrefab) { if (EditorSettings.prefabUIEnvironment != null) environmentEditingScenePath = AssetDatabase.GetAssetPath(EditorSettings.prefabUIEnvironment); @@ -125,7 +125,7 @@ internal static string GetEnvironmentScenePathForPrefab(GameObject prefabInstanc return environmentEditingScenePath; } - internal static Scene CreatePreviewScene(string environmentEditingScenePath) + static Scene LoadOrCreatePreviewScene(string environmentEditingScenePath) { Scene previewScene; if (!string.IsNullOrEmpty(environmentEditingScenePath)) @@ -135,7 +135,6 @@ internal static Scene CreatePreviewScene(string environmentEditingScenePath) var visitor = new TransformVisitor(); foreach (var root in roots) { - visitor.VisitAndAllowEarlyOut(root.transform, UnpackPrefabInstance, null); visitor.VisitAll(root.transform, AppendEnvironmentName, null); } } @@ -147,16 +146,6 @@ internal static Scene CreatePreviewScene(string environmentEditingScenePath) return previewScene; } - static bool UnpackPrefabInstance(Transform transform, object userData) - { - if (PrefabUtility.IsPartOfNonAssetPrefabInstance(transform)) - { - PrefabUtility.UnpackPrefabInstance(transform.gameObject, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction); - return false; - } - return true; - } - static void AppendEnvironmentName(Transform transform, object userData) { transform.gameObject.name += " (Environment)"; @@ -201,36 +190,44 @@ internal static void DestroyPreviewScene(Scene previewScene) } } - internal static bool HandleAutoReparenting(GameObject instanceRoot, Scene scene) + internal static Scene MovePrefabRootToEnvironmentScene(GameObject prefabInstanceRoot) { - if (instanceRoot == null) - return false; + bool isUIPrefab = PrefabStageUtility.IsUI(prefabInstanceRoot); - if (HandleUIReparenting(instanceRoot, scene)) - return true; + // Create the environment scene and move the prefab root to this scene to ensure + // the correct rendersettings (skybox etc) are used in Prefab Mode. + string environmentEditingScenePath = GetEnvironmentScenePathForPrefab(isUIPrefab); + Scene environmentScene = LoadOrCreatePreviewScene(environmentEditingScenePath); + environmentScene.name = prefabInstanceRoot.name; + SceneManager.MoveGameObjectToScene(prefabInstanceRoot, environmentScene); - return false; + if (isUIPrefab) + HandleUIReparentingIfNeeded(prefabInstanceRoot, environmentScene); + else + prefabInstanceRoot.transform.SetAsFirstSibling(); + + return environmentScene; } - static bool HandleUIReparenting(GameObject instanceRoot, Scene scene) + static bool IsUI(GameObject root) { - // We need a Canvas in order to render UI so below we ensure the prefab instance is under a Canvas + // We require a RectTransform and a CanvasRenderer to be considered a UI prefab. + // E.g 3D TextMeshPro uses RectTransform but a MeshRenderer so should not be considered a UI prefab + // This function needs to be peformant since it is called every time a prefab is opened in a prefab stage. + return root.GetComponent() != null && root.GetComponentInChildren(true) != null; + } + + static void HandleUIReparentingIfNeeded(GameObject instanceRoot, Scene scene) + { + // We need a Canvas in order to render UI so ensure the prefab instance is under a Canvas Canvas canvas = instanceRoot.GetComponent(); if (canvas != null) - return true; + return; - bool rootHasRectTransform = instanceRoot.transform is RectTransform; - if (rootHasRectTransform) - { - GameObject canvasGameObject = GetOrCreateCanvasGameObject(instanceRoot, scene); - instanceRoot.transform.SetParent(canvasGameObject.transform, false); - return true; - } - - return false; + GameObject canvasGameObject = GetOrCreateCanvasGameObject(instanceRoot, scene); + instanceRoot.transform.SetParent(canvasGameObject.transform, false); } - // TODO: make hooks for extensions to handle setting up static GameObject GetOrCreateCanvasGameObject(GameObject instanceRoot, Scene scene) { Canvas canvas = GetCanvasInScene(instanceRoot, scene); diff --git a/Editor/Mono/Scripting/Compilers/BooCompiler.cs b/Editor/Mono/Scripting/Compilers/BooCompiler.cs deleted file mode 100644 index 8cbb470b10..0000000000 --- a/Editor/Mono/Scripting/Compilers/BooCompiler.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.IO; -using System.Linq; -using System.Collections.Generic; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.Compilers -{ - class BooCompiler : MonoScriptCompilerBase - { - const string k_UnityScriptProfileDirectory = "unityscript"; - - public BooCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) - { - } - - override protected Program StartCompiler() - { - var arguments = new List - { - "-debug", - "-target:library", - "-out:" + m_Island._output, - "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) - }; - - foreach (string dll in m_Island._references) - arguments.Add("-r:" + PrepareFileName(dll)); - foreach (string define in m_Island._defines.Distinct()) - arguments.Add("-define:" + define); - foreach (string source in m_Island._files) - arguments.Add(PrepareFileName(source)); - - string compilerPath = Path.Combine(GetBooCompilerDirectory(), "booc.exe"); - return StartCompiler(m_Island._target, compilerPath, arguments, GetBooProfileDirectory()); - } - - protected override CompilerOutputParserBase CreateOutputParser() - { - return new BooCompilerOutputParser(); - } - - protected override string[] GetSystemReferenceDirectories() - { - return new[] { GetBooCompilerDirectory() }; - } - - string GetBooCompilerDirectory() - { - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return GetMonoProfileLibDirectory(); - - return Path.Combine(MonoInstallationFinder.GetProfilesDirectory(MonoInstallationFinder.MonoBleedingEdgeInstallation), k_UnityScriptProfileDirectory); - } - - string GetBooProfileDirectory() - { - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); - - return k_UnityScriptProfileDirectory; - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs b/Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs deleted file mode 100644 index fef008d186..0000000000 --- a/Editor/Mono/Scripting/Compilers/BooCompilerOutputParser.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - class BooCompilerOutputParser : CompilerOutputParserBase - { - private static Regex sCompilerOutput = new Regex(@"\s*(?.*)\((?\d+),(?\d+)\):\s*[BU]C(?W|E)(?[^:]*):\s*(?.*)", RegexOptions.ExplicitCapture); - private static Regex sMissingMember = new Regex(@"[^']*'(?[^']+)'[^']+'(?[^']+)'", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - private static Regex sUnknownTypeOrNamespace = new Regex(@"[^']*'(?[^']+)'.*", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - - protected override string GetErrorIdentifier() - { - return "E"; - } - - protected override Regex GetOutputRegex() - { - return sCompilerOutput; - } - - protected override NormalizedCompilerStatus NormalizedStatusFor(Match match) - { - var status = TryNormalizeCompilerStatus(match, "0019", sMissingMember, NormalizeMemberNotFoundError); - if (status.code != NormalizedCompilerStatusCode.NotNormalized) - return status; - - return TryNormalizeCompilerStatus(match, "0018", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/BooLanguage.cs b/Editor/Mono/Scripting/Compilers/BooLanguage.cs deleted file mode 100644 index 863cc01f62..0000000000 --- a/Editor/Mono/Scripting/Compilers/BooLanguage.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using Boo.Lang.Parser; - -using System.Linq; -using UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditor.Scripting.Compilers -{ - internal class BooLanguage : SupportedLanguage - { - public override string GetExtensionICanCompile() - { - return "boo"; - } - - public override string GetLanguageName() - { - return "Boo"; - } - - public override ScriptCompilerBase CreateCompiler(ScriptAssembly scriptAssembly, MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) - { - return new BooCompiler(island, runUpdater); - } - - public override string GetNamespace(string fileName, string definedSymbols) - { - try - { - return BooParser.ParseFile(fileName).Modules.First().Namespace.Name; - } - catch {} - - return base.GetNamespace(fileName, definedSymbols); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs b/Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs index 840c61bb75..9d9d800ab0 100644 --- a/Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs +++ b/Editor/Mono/Scripting/Compilers/ResponseFileProvider.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.IO; -using UnityEditor.Utils; +using UnityEditor.Scripting.ScriptCompilation; using UnityEngine; namespace UnityEditor.Scripting.Compilers @@ -32,7 +32,7 @@ public List Get(string folderToLookForResponseFilesIn) { if (!string.IsNullOrEmpty(folderToLookForResponseFilesIn) && !Path.IsPathRooted(folderToLookForResponseFilesIn)) { - folderToLookForResponseFilesIn = Path.Combine(ProjectPath, folderToLookForResponseFilesIn); + folderToLookForResponseFilesIn = AssetPath.Combine(ProjectPath, folderToLookForResponseFilesIn); } var result = new List(); @@ -58,7 +58,7 @@ protected string GetCompilerSpecific(string path) } //We only look for the specific response file in the folder. - var responseFilePath = Path.Combine(path, ResponseFileName); + var responseFilePath = AssetPath.Combine(path, ResponseFileName); if (File.Exists(responseFilePath)) { @@ -69,7 +69,7 @@ protected string GetCompilerSpecific(string path) protected string GetDefaultResponseFiles() { - var rootResponseFilePath = Paths.Combine(ProjectPath, k_AssetsFolder, ResponseFileName); + var rootResponseFilePath = AssetPath.Combine(ProjectPath, k_AssetsFolder, ResponseFileName); if (File.Exists(rootResponseFilePath)) { return rootResponseFilePath; @@ -77,7 +77,7 @@ protected string GetDefaultResponseFiles() foreach (var obsoleteResponseFileName in ObsoleteResponseFileNames) { - var obsoleteResponseFilePath = Paths.Combine(ProjectPath, k_AssetsFolder, obsoleteResponseFileName); + var obsoleteResponseFilePath = AssetPath.Combine(ProjectPath, k_AssetsFolder, obsoleteResponseFileName); if (File.Exists(obsoleteResponseFilePath)) { return obsoleteResponseFilePath; diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index 4dd2ba758e..88378004d8 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -16,14 +16,8 @@ internal abstract class ScriptCompilerBase : IDisposable { public class ResponseFileData { - public class Reference - { - public String Alias; - public String Assembly; - } - public string[] Defines; - public Reference[] FullPathReferences; + public string[] FullPathReferences; public bool Unsafe; public string[] Errors; public string[] OtherArguments; @@ -38,9 +32,7 @@ public class CompilerOption static readonly char[] CompilerOptionArgumentSeperators = { ';', ',' }; private Program process; - private string _responseFile = null; private bool _runAPIUpdater; - string m_ProjectDirectory; // ToDo: would be nice to move MonoIsland to MonoScriptCompilerBase protected MonoIsland m_Island; @@ -53,7 +45,6 @@ protected ScriptCompilerBase(MonoIsland island, bool runAPIUpdater) { m_Island = island; _runAPIUpdater = runAPIUpdater; - m_ProjectDirectory = Directory.GetParent(Application.dataPath).FullName.ConvertSeparatorsToUnity(); } protected string[] GetErrorOutput() @@ -80,11 +71,6 @@ public virtual void Dispose() process.Dispose(); process = null; } - if (_responseFile != null) - { - File.Delete(_responseFile); - _responseFile = null; - } } public virtual bool Poll() @@ -126,7 +112,7 @@ protected bool AddCustomResponseFileIfPresent(List arguments, string res protected void AddResponseFileToArguments(List arguments, string responseFileName) { var responseFileData = ParseResponseFileFromFile( - Path.Combine(m_ProjectDirectory, responseFileName), + responseFileName, Application.dataPath, GetSystemReferenceDirectories()); foreach (var error in responseFileData.Errors) @@ -136,7 +122,7 @@ protected void AddResponseFileToArguments(List arguments, string respons arguments.AddRange(responseFileData.Defines.Distinct().Select(define => "/define:" + define)); arguments.AddRange(responseFileData.FullPathReferences.Select(reference => - "/reference:" + PrepareFileName(reference.Assembly))); + "/reference:" + PrepareFileName(reference))); if (responseFileData.Unsafe) { arguments.Add("/unsafe"); @@ -150,28 +136,49 @@ public static ResponseFileData ParseResponseFileFromFile( string projectDirectory, string[] systemReferenceDirectories) { - if (!File.Exists(responseFilePath)) + var relativeResponseFilePath = GetRelativePath(responseFilePath, projectDirectory); + var responseFile = AssetDatabase.LoadAssetAtPath(relativeResponseFilePath); + + if (!responseFile && File.Exists(responseFilePath)) + { + var responseFileText = File.ReadAllText(responseFilePath); + return ParseResponseFileText( + responseFileText, + responseFilePath, + projectDirectory, + systemReferenceDirectories); + } + + if (!responseFile) { var empty = new ResponseFileData { Defines = new string[0], - FullPathReferences = new ResponseFileData.Reference[0], + FullPathReferences = new string[0], Unsafe = false, - Errors = new string[0] + Errors = new string[0], + OtherArguments = new string[0], }; return empty; } - var responseFileText = File.ReadAllText(responseFilePath); - return ParseResponseFileText( - responseFileText, - responseFilePath, + responseFile.text, + responseFile.name, projectDirectory, systemReferenceDirectories); } + static string GetRelativePath(string responseFilePath, string projectDirectory) + { + if (Path.IsPathRooted(responseFilePath) && responseFilePath.Contains(projectDirectory)) + { + responseFilePath = responseFilePath.Substring(Directory.GetParent(Application.dataPath).FullName.Length + 1); + } + return responseFilePath; + } + // From: // https://github.com/mono/mono/blob/c106cdc775792ceedda6da58de7471f9f5c0b86c/mcs/mcs/settings.cs // @@ -238,14 +245,14 @@ static string[] ResponseFileTextToStrings(string responseFileText) } static ResponseFileData ParseResponseFileText( - string responseFileText, - string responseFileName, + string fileContent, + string fileName, string projectDirectory, string[] systemReferenceDirectories) { var compilerOptions = new List(); - var responseFileStrings = ResponseFileTextToStrings(responseFileText); + var responseFileStrings = ResponseFileTextToStrings(fileContent); foreach (var line in responseFileStrings) { @@ -271,7 +278,7 @@ static ResponseFileData ParseResponseFileText( var responseArguments = new List(); var defines = new List(); - var references = new List(); + var references = new List(); bool unsafeDefined = false; var errors = new List(); @@ -320,32 +327,22 @@ static ResponseFileData ParseResponseFileText( continue; } - ResponseFileData.Reference responseReference; + var responseReference = reference; int index = reference.IndexOf('='); if (index > -1) { - string alias = reference.Substring(0, index); - string assembly = reference.Substring(index + 1); + var assembly = reference.Substring(index + 1); - responseReference = new ResponseFileData.Reference { Alias = alias, Assembly = assembly }; - } - else - { - responseReference = new ResponseFileData.Reference { Alias = string.Empty, Assembly = reference }; + responseReference = assembly; } - string fullPathReference = ""; - var referencePath = responseReference.Assembly; - if (Path.IsPathRooted(referencePath)) - { - fullPathReference = referencePath; - } - else + var fullPathReference = responseReference; + if (!Path.IsPathRooted(responseReference)) { foreach (var directory in systemReferenceDirectories) { - var systemReferencePath = Paths.Combine(directory, referencePath); + var systemReferencePath = Paths.Combine(directory, responseReference); if (File.Exists(systemReferencePath)) { fullPathReference = systemReferencePath; @@ -353,7 +350,7 @@ static ResponseFileData ParseResponseFileText( } } - var userPath = Paths.Combine(projectDirectory, referencePath); + var userPath = Paths.Combine(projectDirectory, responseReference); if (File.Exists(userPath)) { fullPathReference = userPath; @@ -362,12 +359,12 @@ static ResponseFileData ParseResponseFileText( if (fullPathReference == "") { - errors.Add($"{responseFileName}: not parsed correctly: {responseReference.Assembly} could not be found as a system library.\n" + + errors.Add($"{fileName}: not parsed correctly: {responseReference} could not be found as a system library.\n" + "If this was meant as a user reference please provide the relative path from project root (parent of the Assets folder) in the response file."); continue; } - responseReference.Assembly = fullPathReference.Replace('\\', '/'); + responseReference = fullPathReference.Replace('\\', '/'); references.Add(responseReference); } break; @@ -414,6 +411,11 @@ public virtual CompilerMessage[] GetCompilerMessages() if (!Poll()) Debug.LogWarning("Compile process is not finished yet. This should not happen."); + if (process == null) + { + return new CompilerMessage[0]; + } + DumpStreamOutputToLog(); return CreateOutputParser().Parse( diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs b/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs deleted file mode 100644 index 7b4c4c5809..0000000000 --- a/Editor/Mono/Scripting/Compilers/UnityScriptCompiler.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.IO; -using System.Linq; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using UnityEditor.Utils; - -namespace UnityEditor.Scripting.Compilers -{ - class UnityScriptCompiler : MonoScriptCompilerBase - { - private static readonly Regex UnityEditorPattern = new Regex(@"UnityEditor\.dll$", RegexOptions.ExplicitCapture); - const string k_UnityScriptProfileDirectory = "unityscript"; - - public UnityScriptCompiler(MonoIsland island, bool runUpdater) : base(island, runUpdater) - { - } - - protected override CompilerOutputParserBase CreateOutputParser() - { - return new UnityScriptCompilerOutputParser(); - } - - protected override Program StartCompiler() - { - var arguments = new List - { - "-debug", - "-target:library", - "-i:UnityEngine", - "-i:System.Collections", - "-base:UnityEngine.MonoBehaviour", - "-nowarn:BCW0016", - "-nowarn:BCW0003", - "-method:Main", - "-out:" + m_Island._output, - "-x-type-inference-rule-attribute:" + typeof(UnityEngineInternal.TypeInferenceRuleAttribute) - }; - - if (StrictBuildTarget()) - arguments.Add("-pragmas:strict,downcast"); - - foreach (var define in m_Island._defines.Distinct()) - arguments.Add("-define:" + define); - - foreach (var dll in m_Island._references) - arguments.Add("-r:" + PrepareFileName(dll)); - - var compilingEditorScripts = Array.Exists(m_Island._references, UnityEditorPattern.IsMatch); - if (compilingEditorScripts) - arguments.Add("-i:UnityEditor"); - else if (!BuildPipeline.IsUnityScriptEvalSupported(m_Island._target)) - arguments.Add($"-disable-eval:eval is not supported on the current build target ({m_Island._target})."); - - foreach (string source in m_Island._files) - arguments.Add(PrepareFileName(source)); - - var compilerPath = Path.Combine(GetUnityScriptCompilerDirectory(), "us.exe"); - return StartCompiler(m_Island._target, compilerPath, arguments, GetUnityScriptProfileDirectory()); - } - - string GetUnityScriptCompilerDirectory() - { - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return GetMonoProfileLibDirectory(); - - return Path.Combine(MonoInstallationFinder.GetProfilesDirectory(MonoInstallationFinder.MonoBleedingEdgeInstallation), k_UnityScriptProfileDirectory); - } - - string GetUnityScriptProfileDirectory() - { - if (EditorApplication.scriptingRuntimeVersion == ScriptingRuntimeVersion.Legacy) - return BuildPipeline.CompatibilityProfileToClassLibFolder(m_Island._api_compatibility_level); - - return k_UnityScriptProfileDirectory; - } - - private bool StrictBuildTarget() - { - return Array.IndexOf(m_Island._defines, "ENABLE_DUCK_TYPING") == -1; - } - - protected override string[] GetSystemReferenceDirectories() - { - return new[] { GetUnityScriptCompilerDirectory() }; - } - - protected override string[] GetStreamContainingCompilerMessages() - { - return GetStandardOutput(); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs b/Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs deleted file mode 100644 index 9ea0c0ad66..0000000000 --- a/Editor/Mono/Scripting/Compilers/UnityScriptCompilerOutputParser.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System.Text.RegularExpressions; - -namespace UnityEditor.Scripting.Compilers -{ - class UnityScriptCompilerOutputParser : CompilerOutputParserBase - { - private static Regex sCompilerOutput = new Regex(@"\s*(?.*)\((?\d+),(?\d+)\):\s*[BU]C(?W|E)(?[^:]*):\s*(?.*)", RegexOptions.ExplicitCapture); - - private static Regex sUnknownTypeOrNamespace = new Regex(@"[^']*'(?[^']+)'.*", RegexOptions.ExplicitCapture | RegexOptions.Compiled); - - protected override string GetErrorIdentifier() - { - return "E"; - } - - protected override Regex GetOutputRegex() - { - return sCompilerOutput; - } - - protected override NormalizedCompilerStatus NormalizedStatusFor(Match match) - { - var status = TryNormalizeCompilerStatus(match, "0018", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - if (status.code != NormalizedCompilerStatusCode.NotNormalized) - return status; - - return TryNormalizeCompilerStatus(match, "0005", sUnknownTypeOrNamespace, NormalizeSimpleUnknownTypeOfNamespaceError); - } - } -} diff --git a/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs b/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs deleted file mode 100644 index 45b654fca9..0000000000 --- a/Editor/Mono/Scripting/Compilers/UnityScriptLanguage.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using UnityEditor.Scripting.ScriptCompilation; - -namespace UnityEditor.Scripting.Compilers -{ - internal class UnityScriptLanguage : SupportedLanguage - { - public override string GetExtensionICanCompile() - { - return "js"; - } - - public override string GetLanguageName() - { - return "UnityScript"; - } - - public override ScriptCompilerBase CreateCompiler(ScriptAssembly scriptAssembly, MonoIsland island, bool buildingForEditor, BuildTarget targetPlatform, bool runUpdater) - { - return new UnityScriptCompiler(island, runUpdater); - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs b/Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs index 640607b4da..65dc3bc233 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/AssetPath.cs @@ -18,6 +18,11 @@ public static string GetFullPath(string path) return ReplaceSeparators(SystemPath.GetFullPath(path.NormalizePath())); } + public static string Combine(params string[] paths) + { + return ReplaceSeparators(Paths.Combine(paths)); + } + public static string Combine(string path1, string path2) { return ReplaceSeparators(SystemPath.Combine(path1, path2)); diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs index 6c606ac42e..7e90f5e7b3 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs @@ -129,15 +129,7 @@ public bool Poll() if (stopOnFirstError && CompileErrors) { - // Set empty compiler messages for all pending assemblies. - // Makes handling of messages easier in the editor. - if (pendingAssemblies.Count > 0) - { - foreach (var pendingAssembly in pendingAssemblies) - processedAssemblies.Add(pendingAssembly, new CompilerMessage[0]); - - pendingAssemblies.Clear(); - } + pendingAssemblies.Clear(); return compilerTasks.Count == 0; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index bb3b375f17..9a917a91ad 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -394,7 +394,19 @@ public static ScriptAssembly[] GenerateChangedScriptAssemblies(GenerateChangedSc HashSet assemblySourceFiles; var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(dirtySourceFile); - var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); + SupportedLanguage scriptLanguage = null; + + try + { + scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); + } + catch (Exception e) + { + // UnityScript/Boo support has been disabled but not removed, + // so we log the exception and skip the source file. + UnityEngine.Debug.Log(e); + continue; + } if (!dirtyTargetAssemblies.TryGetValue(targetAssembly, out assemblySourceFiles)) { diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index cba36dd5fd..40c0f7ce57 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -484,40 +484,83 @@ string[] CustomTargetAssembliesToFilePaths(IEnumerable visited) + public struct CheckCyclicAssemblyReferencesFunctions { - if (visited.Contains(visitAssembly)) - throw new Compilation.AssemblyDefinitionException("Assembly with cyclic references detected", CustomTargetAssembliesToFilePaths(visited)); + public Func ToFilePathFunc; + public Func, string[]> ToFilePathsFunc; + } + static void CheckCyclicAssemblyReferencesDFS(EditorBuildRules.TargetAssembly visitAssembly, + HashSet visited, + HashSet recursion, + CheckCyclicAssemblyReferencesFunctions functions) + { visited.Add(visitAssembly); + recursion.Add(visitAssembly); foreach (var reference in visitAssembly.References) { if (reference.Filename == visitAssembly.Filename) - throw new Compilation.AssemblyDefinitionException("Assembly contains a references to itself", CustomTargetAssembliesToFilePaths(visitAssembly)); + { + throw new Compilation.AssemblyDefinitionException("Assembly contains a references to itself", + functions.ToFilePathFunc(visitAssembly)); + } - CheckCyclicAssemblyReferencesDFS(reference, visited); + if (recursion.Contains(reference)) + { + throw new Compilation.AssemblyDefinitionException("Assembly with cyclic references detected", + functions.ToFilePathsFunc(recursion)); + } + + if (!visited.Contains(reference)) + { + CheckCyclicAssemblyReferencesDFS(reference, + visited, + recursion, + functions); + } } - visited.Remove(visitAssembly); + recursion.Remove(visitAssembly); } - void CheckCyclicAssemblyReferences() + public static void CheckCyclicAssemblyReferences(EditorBuildRules.TargetAssembly[] customTargetAssemblies, + CheckCyclicAssemblyReferencesFunctions functions) { if (customTargetAssemblies == null || customTargetAssemblies.Length < 1) return; var visited = new HashSet(); + foreach (var assembly in customTargetAssemblies) + { + if (!visited.Contains(assembly)) + { + var recursion = new HashSet(); + + CheckCyclicAssemblyReferencesDFS(assembly, + visited, + recursion, + functions); + } + } + } + + void CheckCyclicAssemblyReferences() + { try { - foreach (var assembly in customTargetAssemblies) - CheckCyclicAssemblyReferencesDFS(assembly, visited); + CheckCyclicAssemblyReferencesFunctions functions; + + functions.ToFilePathFunc = CustomTargetAssemblyToFilePath; + functions.ToFilePathsFunc = CustomTargetAssembliesToFilePaths; + + CheckCyclicAssemblyReferences(customTargetAssemblies, functions); } catch (Exception e) { diff --git a/Editor/Mono/Scripting/ScriptCompilers.cs b/Editor/Mono/Scripting/ScriptCompilers.cs index 903a06fcf0..d47baaac90 100644 --- a/Editor/Mono/Scripting/ScriptCompilers.cs +++ b/Editor/Mono/Scripting/ScriptCompilers.cs @@ -82,8 +82,6 @@ static ScriptCompilers() var types = new List(); types.Add(typeof(CSharpLanguage)); - types.Add(typeof(BooLanguage)); - types.Add(typeof(UnityScriptLanguage)); foreach (var t in types) { diff --git a/Editor/Mono/Settings.cs b/Editor/Mono/Settings.cs index a3902beec1..cb3e269e15 100644 --- a/Editor/Mono/Settings.cs +++ b/Editor/Mono/Settings.cs @@ -181,7 +181,7 @@ internal class PrefKey : IPrefType public PrefKey() { m_Loaded = true; } - [Obsolete("Use the new ShortcutManager attrbiute [Shortcut]")] + [Obsolete("Use the new ShortcutManager attribute [Shortcut]")] private PrefKey(string name, string shortcut) { this.m_name = name; diff --git a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs index e51406be63..7a05677bf5 100644 --- a/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs +++ b/Editor/Mono/VisualStudioIntegration/SolutionSynchronizer.cs @@ -50,8 +50,6 @@ enum Mode static internal readonly Dictionary BuiltinSupportedExtensions = new Dictionary { {"cs", ScriptingLanguage.CSharp}, - {"js", ScriptingLanguage.UnityScript}, - {"boo", ScriptingLanguage.Boo}, {"uxml", ScriptingLanguage.None}, {"uss", ScriptingLanguage.None}, {"shader", ScriptingLanguage.None}, @@ -263,7 +261,7 @@ internal void GenerateAndWriteSolutionAndProjects(ScriptEditorUtility.ScriptEdit : MonoLibraryHelpers.GetSystemReferenceDirectories(island._api_compatibility_level); Dictionary responseFilesData = island._responseFiles.ToDictionary(x => x, x => ScriptCompilerBase.ParseResponseFileFromFile( - Path.Combine(_projectDirectory, x), + x, _projectDirectory, systemReferenceDirectories )); @@ -474,7 +472,7 @@ string ProjectText(MonoIsland island, AppendReference(fullReference, projectBuilder); } - var responseRefs = responseFilesData.SelectMany(x => x.FullPathReferences.Select(r => r.Assembly)); + var responseRefs = responseFilesData.SelectMany(x => x.FullPathReferences); foreach (var reference in responseRefs) { AppendReference(reference, projectBuilder); diff --git a/Modules/AssetPipelineEditor/ImportSettings/ScriptedImporterEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/ScriptedImporterEditor.cs index 3a31034a2d..9e3c1d1a58 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/ScriptedImporterEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/ScriptedImporterEditor.cs @@ -16,7 +16,20 @@ internal override string targetTitle public override void OnInspectorGUI() { - DrawDefaultInspector(); + // Copy-paste of DrawDefaultInspector code because we are drawing the same way + // but need to NOT call serializedObject.ApplyModifiedProperties + // because it would break the Apply/Revert buttons. + + SerializedProperty property = serializedObject.GetIterator(); + bool expanded = true; + while (property.NextVisible(expanded)) + { + using (new EditorGUI.DisabledScope("m_Script" == property.propertyPath)) + { + EditorGUILayout.PropertyField(property, true); + } + expanded = false; + } ApplyRevertGUI(); } diff --git a/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs b/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs index 542ffac964..b4db1c4b67 100644 --- a/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs +++ b/Modules/Physics2D/ScriptBindings/Physics2D.bindings.cs @@ -509,6 +509,9 @@ public partial class Physics2D [StaticAccessor("GetPhysics2DSettings()")] extern public static bool callbacksOnDisable { get; set; } + [StaticAccessor("GetPhysics2DSettings()")] + extern public static bool reuseCollisionCallbacks { get; set; } + [StaticAccessor("GetPhysics2DSettings()")] extern public static bool autoSyncTransforms { get; set; } @@ -2298,98 +2301,6 @@ static internal ContactFilter2D CreateLegacyFilter(int layerMask, float minDepth } } - [UsedByNativeCode] - [StructLayout(LayoutKind.Sequential)] - internal unsafe partial struct CachedContactPoints2D - { - public ContactPoint2D this[int i] - { - get - { - // No need to limit the index here as it is limited by the contact count when accessed. - // Adding a constant here will just introduce something else that will need updating - // should the contact point cache change in the future. - fixed(ContactPoint2D * contact = &m_Contact0) - { - return *(contact + i); - } - } - } - - // It would've been nice to have some fixed array here but it's not possible. - // Using a fixed primitive type array isn't possible either as the size cannot be specified as an explicit constant. - ContactPoint2D m_Contact0; - ContactPoint2D m_Contact1; - ContactPoint2D m_Contact2; - ContactPoint2D m_Contact3; - ContactPoint2D m_Contact4; - ContactPoint2D m_Contact5; - ContactPoint2D m_Contact6; - ContactPoint2D m_Contact7; - ContactPoint2D m_Contact8; - ContactPoint2D m_Contact9; - - ContactPoint2D m_Contact10; - ContactPoint2D m_Contact11; - ContactPoint2D m_Contact12; - ContactPoint2D m_Contact13; - ContactPoint2D m_Contact14; - ContactPoint2D m_Contact15; - ContactPoint2D m_Contact16; - ContactPoint2D m_Contact17; - ContactPoint2D m_Contact18; - ContactPoint2D m_Contact19; - - ContactPoint2D m_Contact20; - ContactPoint2D m_Contact21; - ContactPoint2D m_Contact22; - ContactPoint2D m_Contact23; - ContactPoint2D m_Contact24; - ContactPoint2D m_Contact25; - ContactPoint2D m_Contact26; - ContactPoint2D m_Contact27; - ContactPoint2D m_Contact28; - ContactPoint2D m_Contact29; - - ContactPoint2D m_Contact30; - ContactPoint2D m_Contact31; - ContactPoint2D m_Contact32; - ContactPoint2D m_Contact33; - ContactPoint2D m_Contact34; - ContactPoint2D m_Contact35; - ContactPoint2D m_Contact36; - ContactPoint2D m_Contact37; - ContactPoint2D m_Contact38; - ContactPoint2D m_Contact39; - - ContactPoint2D m_Contact40; - ContactPoint2D m_Contact41; - ContactPoint2D m_Contact42; - ContactPoint2D m_Contact43; - ContactPoint2D m_Contact44; - ContactPoint2D m_Contact45; - ContactPoint2D m_Contact46; - ContactPoint2D m_Contact47; - ContactPoint2D m_Contact48; - ContactPoint2D m_Contact49; - - ContactPoint2D m_Contact50; - ContactPoint2D m_Contact51; - ContactPoint2D m_Contact52; - ContactPoint2D m_Contact53; - ContactPoint2D m_Contact54; - ContactPoint2D m_Contact55; - ContactPoint2D m_Contact56; - ContactPoint2D m_Contact57; - ContactPoint2D m_Contact58; - ContactPoint2D m_Contact59; - - ContactPoint2D m_Contact60; - ContactPoint2D m_Contact61; - ContactPoint2D m_Contact62; - ContactPoint2D m_Contact63; - } - // Describes a collision. [UsedByNativeCode] [StructLayout(LayoutKind.Sequential)] @@ -2402,8 +2313,11 @@ public partial class Collision2D internal Vector2 m_RelativeVelocity; internal int m_Enabled; internal int m_ContactCount; - internal CachedContactPoints2D m_CachedContactPoints; - internal ContactPoint2D[] m_LegacyContactArray; + internal ContactPoint2D[] m_RecycledContacts; + internal ContactPoint2D[] m_LegacyContacts; + + // Return the appropriate contacts array. + private ContactPoint2D[] GetContacts_Internal() { return m_LegacyContacts == null ? m_RecycledContacts : m_LegacyContacts; } // The first collider involved in the collision. public Collider2D collider { get { return Object.FindObjectFromInstanceID(m_Collider) as Collider2D; } } @@ -2434,21 +2348,13 @@ public ContactPoint2D[] contacts { get { - if (m_LegacyContactArray == null) + if (m_LegacyContacts == null) { - m_LegacyContactArray = new ContactPoint2D[m_ContactCount]; - if (m_ContactCount > 0) - { - { - for (var i = 0; i < m_ContactCount; ++i) - { - m_LegacyContactArray[i] = m_CachedContactPoints[i]; - } - } - } + m_LegacyContacts = new ContactPoint2D[m_ContactCount]; + Array.Copy(m_RecycledContacts, m_LegacyContacts, m_ContactCount); } - return m_LegacyContactArray; + return m_LegacyContacts; } } @@ -2461,34 +2367,17 @@ public ContactPoint2D GetContact(int index) if (index < 0 || index >= m_ContactCount) throw new ArgumentOutOfRangeException(String.Format("Cannot get contact at index {0}. There are {1} contact(s).", index, m_ContactCount)); - return m_CachedContactPoints[index]; + return GetContacts_Internal()[index]; } // Get contacts for this collision. public int GetContacts(ContactPoint2D[] contacts) { if (contacts == null) - throw new ArgumentNullException("Cannot get contacts into a NULL array."); - - var contactCount = Mathf.Min(contacts.Length, m_ContactCount); - if (contactCount == 0) - return 0; - - // If we have an existing contact array then use that and copy it. - if (m_LegacyContactArray != null) - { - Array.Copy(m_LegacyContactArray, contacts, contactCount); - return contactCount; - } + throw new NullReferenceException("Cannot get contacts as the provided array is NULL."); - // Copy the cached contact points instead. - if (m_ContactCount > 0) - { - for (var i = 0; i < contactCount; ++i) - { - contacts[i] = m_CachedContactPoints[i]; - } - } + var contactCount = Mathf.Min(m_ContactCount, contacts.Length); + Array.Copy(GetContacts_Internal(), contacts, contactCount); return contactCount; } }; diff --git a/Modules/RestService/ProjectStateRestHandler.cs b/Modules/RestService/ProjectStateRestHandler.cs index a0ba4abeb0..d6af8567c9 100644 --- a/Modules/RestService/ProjectStateRestHandler.cs +++ b/Modules/RestService/ProjectStateRestHandler.cs @@ -112,7 +112,7 @@ private static JSONValue JsonForIsland(Island island) var result = new JSONValue(); result["name"] = island.Name; - result["language"] = island.Name.Contains("Boo") ? "Boo" : island.Name.Contains("UnityScript") ? "UnityScript" : "C#"; + result["language"] = "C#"; result["files"] = ToJSON(island.MonoIsland._files); result["defines"] = ToJSON(island.MonoIsland._defines); result["references"] = ToJSON(island.MonoIsland._references); diff --git a/Modules/TerrainEditor/TerrainInspector.cs b/Modules/TerrainEditor/TerrainInspector.cs index 6949056bfb..e0d13a2229 100644 --- a/Modules/TerrainEditor/TerrainInspector.cs +++ b/Modules/TerrainEditor/TerrainInspector.cs @@ -2142,8 +2142,19 @@ public void OnSceneGUICallback(SceneView sceneView) { if (hitValidTerrain) { - float brushSize = selectedTool == TerrainTool.PlaceTree ? TreePainter.brushSize : m_Size; - TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(hitTerrain, brushList.GetCircleBrush().texture, brushSize); + float brushSize; + Texture2D brushTexture; + if (selectedTool == TerrainTool.PaintDetail) + { + brushSize = m_Size; + brushTexture = brushList.GetActiveBrush().texture; + } + else + { + brushSize = TreePainter.brushSize; + brushTexture = brushList.GetCircleBrush().texture; + } + TerrainPaintUtilityEditor.ShowDefaultPreviewBrush(hitTerrain, brushTexture, brushSize); } } diff --git a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs index 0505978ef4..4616b2734b 100644 --- a/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs +++ b/Modules/TextCore/ScriptBindings/FontEngine.bindings.cs @@ -135,6 +135,8 @@ public sealed class FontEngine { private static readonly FontEngine s_Instance = new FontEngine(); + private static uint[] s_GlyphIndexesToMarshall; + private static GlyphMarshallingStruct[] s_GlyphMarshallingStruct_IN = new GlyphMarshallingStruct[16]; private static GlyphMarshallingStruct[] s_GlyphMarshallingStruct_OUT = new GlyphMarshallingStruct[16]; @@ -742,7 +744,9 @@ internal static FontEngineError RenderGlyphsToSharedTexture(List glyphs, [NativeMethod(Name = "TextCore::FontEngine::ReleaseSharedTextureData", IsThreadSafe = true, IsFreeFunction = true)] internal extern static void ReleaseSharedTexture(); - + /// + /// Internal function used to add glyph to atlas texture. + /// internal static bool TryAddGlyphToTexture(uint glyphIndex, int padding, GlyphPackingMode packingMode, List freeGlyphRects, List usedGlyphRects, GlyphRenderMode renderMode, Texture2D texture, out Glyph glyph) { // Determine potential total allocations required for glyphs and glyph rectangles. @@ -799,11 +803,100 @@ internal static bool TryAddGlyphToTexture(uint glyphIndex, int padding, GlyphPac return false; } + // [NativeMethod(Name = "TextCore::FontEngine::TryAddGlyphToTexture", IsThreadSafe = true, IsFreeFunction = true)] extern static bool TryAddGlyphToTexture_Internal(uint glyphIndex, int padding, GlyphPackingMode packingMode, [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount, GlyphRenderMode renderMode, Texture2D texture, out GlyphMarshallingStruct glyph); + /// + /// Internal function used to add multiple glyphs to atlas texture. + /// + internal static bool TryAddGlyphsToTexture(List glyphIndexes, int padding, GlyphPackingMode packingMode, List freeGlyphRects, List usedGlyphRects, GlyphRenderMode renderMode, Texture2D texture, out Glyph[] glyphs) + { + glyphs = null; + + if (glyphIndexes == null || glyphIndexes.Count == 0) + return false; + + int glyphCount = glyphIndexes.Count; + + // Make sure marshalling glyph index array allocations are appropriate. + if (s_GlyphIndexesToMarshall == null || s_GlyphIndexesToMarshall.Length < glyphCount) + { + if (s_GlyphIndexesToMarshall == null) + s_GlyphIndexesToMarshall = new uint[glyphCount]; + else + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphIndexesToMarshall = new uint[newSize]; + } + } + + // Determine potential total allocations required for glyphs and glyph rectangles. + int freeGlyphRectCount = freeGlyphRects.Count; + int usedGlyphRectCount = usedGlyphRects.Count; + int totalGlyphRects = freeGlyphRectCount + usedGlyphRectCount + glyphCount; + + // Make sure marshalling array(s) allocations are appropriate. + if (s_FreeGlyphRects.Length < totalGlyphRects || s_UsedGlyphRects.Length < totalGlyphRects) + { + int newSize = Mathf.NextPowerOfTwo(totalGlyphRects + 1); + s_FreeGlyphRects = new GlyphRect[newSize]; + s_UsedGlyphRects = new GlyphRect[newSize]; + } + + // Make sure marshaling array allocations are appropriate. + if (s_GlyphMarshallingStruct_OUT.Length < glyphCount) + { + int newSize = Mathf.NextPowerOfTwo(glyphCount + 1); + s_GlyphMarshallingStruct_OUT = new GlyphMarshallingStruct[newSize]; + } + + // Copy glyph indexes and glyph rect data to marshalling arrays. + int glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount, glyphCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < glyphCount) + s_GlyphIndexesToMarshall[i] = glyphIndexes[i]; + + if (i < freeGlyphRectCount) + s_FreeGlyphRects[i] = freeGlyphRects[i]; + + if (i < usedGlyphRectCount) + s_UsedGlyphRects[i] = usedGlyphRects[i]; + } + + // Marshall data over to the native side. + bool allGlyphsAdded = TryAddGlyphsToTexture_Internal(s_GlyphIndexesToMarshall, padding, packingMode, s_FreeGlyphRects, ref freeGlyphRectCount, s_UsedGlyphRects, ref usedGlyphRectCount, renderMode, texture, s_GlyphMarshallingStruct_OUT, ref glyphCount); + + // Allocate array of glyphs + glyphs = new Glyph[glyphCount]; + + freeGlyphRects.Clear(); + usedGlyphRects.Clear(); + + // Copy marshalled free and used GlyphRect data over. + glyphRectCount = Mathf.Max(freeGlyphRectCount, usedGlyphRectCount, glyphCount); + for (int i = 0; i < glyphRectCount; i++) + { + if (i < glyphCount) + glyphs[i] = new Glyph(s_GlyphMarshallingStruct_OUT[i]); + + if (i < freeGlyphRectCount) + freeGlyphRects.Add(s_FreeGlyphRects[i]); + + if (i < usedGlyphRectCount) + usedGlyphRects.Add(s_UsedGlyphRects[i]); + } + + return allGlyphsAdded; + } + + [NativeMethod(Name = "TextCore::FontEngine::TryAddGlyphsToTexture", IsThreadSafe = true, IsFreeFunction = true)] + extern static bool TryAddGlyphsToTexture_Internal(uint[] glyphIndex, int padding, + GlyphPackingMode packingMode, [Out] GlyphRect[] freeGlyphRects, ref int freeGlyphRectCount, [Out] GlyphRect[] usedGlyphRects, ref int usedGlyphRectCount, + GlyphRenderMode renderMode, Texture2D texture, [Out] GlyphMarshallingStruct[] glyphs, ref int glyphCount); /// /// Internal function used to retrieve positional adjustments for pairs of glyphs. @@ -846,6 +939,13 @@ internal static GlyphPairAdjustmentRecord[] GetGlyphPairAdjustmentTable(uint[] g // Experimental / Testing / Benchmarking Functions // ================================================ + /// + /// Internal function used to reset an atlas texture to black + /// + /// + [NativeMethod(Name = "TextCore::FontEngine::ResetAtlasTexture", IsFreeFunction = true)] + internal extern static void ResetAtlasTexture(Texture2D texture); + /// /// Internal function used for testing rasterizing of shapes and glyphs. /// diff --git a/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs b/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs index 93fee2fff8..7b4473bacc 100644 --- a/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs +++ b/Modules/UnityAnalytics/Public/UnityAnalytics.bindings.cs @@ -60,6 +60,13 @@ private extern static bool enabledInternal set; } + [StaticAccessor("GetUnityAnalytics()", StaticAccessorType.Dot)] + private extern static bool playerOptedOutInternal + { + [NativeMethod("GetPlayerOptedOut")] + get; + } + [StaticAccessor("GetUnityAnalytics()", StaticAccessorType.Dot)] private extern static bool limitUserTrackingInternal { diff --git a/Modules/UnityAnalytics/Public/UnityAnalytics.cs b/Modules/UnityAnalytics/Public/UnityAnalytics.cs index d5d312266c..2219bcb02e 100644 --- a/Modules/UnityAnalytics/Public/UnityAnalytics.cs +++ b/Modules/UnityAnalytics/Public/UnityAnalytics.cs @@ -32,6 +32,16 @@ public enum AnalyticsResult public static partial class Analytics { + public static bool playerOptedOut + { + get + { + if (!IsInitialized()) + return false; + return playerOptedOutInternal; + } + } + public static bool limitUserTracking { get diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index 2a0a6ac75d..b48407a248 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -3066,15 +3066,6 @@ Editor\Mono\Scripting\Compilers\APIUpdaterHelper.cs - - Editor\Mono\Scripting\Compilers\BooCompiler.cs - - - Editor\Mono\Scripting\Compilers\BooCompilerOutputParser.cs - - - Editor\Mono\Scripting\Compilers\BooLanguage.cs - Editor\Mono\Scripting\Compilers\CSharpCompilerOutputParserBase.cs @@ -3129,15 +3120,6 @@ Editor\Mono\Scripting\Compilers\UWPReferences.cs - - Editor\Mono\Scripting\Compilers\UnityScriptCompiler.cs - - - Editor\Mono\Scripting\Compilers\UnityScriptCompilerOutputParser.cs - - - Editor\Mono\Scripting\Compilers\UnityScriptLanguage.cs - Editor\Mono\Scripting\NativeClassExtensionUtilities.cs diff --git a/README.md b/README.md index f2127cdca7..13c5a01b11 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b10 C# reference source code +## Unity 2018.3.0b11 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Dynamics/Managed/Dynamics.cs b/Runtime/Dynamics/Managed/Dynamics.cs index b159652f65..26b09d3191 100644 --- a/Runtime/Dynamics/Managed/Dynamics.cs +++ b/Runtime/Dynamics/Managed/Dynamics.cs @@ -332,8 +332,12 @@ public class Collision internal Vector3 m_RelativeVelocity; internal Rigidbody m_Rigidbody; internal Collider m_Collider; + internal int m_ContactCount; + internal ContactPoint[] m_RecycledContacts; + internal ContactPoint[] m_LegacyContacts; - internal ContactPoint[] m_Contacts; + // Return the appropriate contacts array. + private ContactPoint[] GetContacts_Internal() { return m_LegacyContacts == null ? m_RecycledContacts : m_LegacyContacts; } // The relative linear velocity of the two colliding objects (RO). public Vector3 relativeVelocity { get { return m_RelativeVelocity; } } @@ -350,8 +354,44 @@ public class Collision // The [[GameObject]] whose collider we are colliding with. (RO). public GameObject gameObject { get { return m_Rigidbody != null ? m_Rigidbody.gameObject : m_Collider.gameObject; } } + // The number of contacts available. + public int contactCount { get { return m_ContactCount; } } + // The contact points generated by the physics engine. - public ContactPoint[] contacts { get { return m_Contacts; } } + // NOTE: This produces garbage and should be avoided. + public ContactPoint[] contacts + { + get + { + if (m_LegacyContacts == null) + { + m_LegacyContacts = new ContactPoint[m_ContactCount]; + Array.Copy(m_RecycledContacts, m_LegacyContacts, m_ContactCount); + } + + return m_LegacyContacts; + } + } + + // Get contact at specific index. + public ContactPoint GetContact(int index) + { + if (index < 0 || index >= m_ContactCount) + throw new ArgumentOutOfRangeException(String.Format("Cannot get contact at index {0}. There are {1} contact(s).", index, m_ContactCount)); + + return GetContacts_Internal()[index]; + } + + // Get contacts for this collision. + public int GetContacts(ContactPoint[] contacts) + { + if (contacts == null) + throw new NullReferenceException("Cannot get contacts as the provided array is NULL."); + + var contactCount = Mathf.Min(m_ContactCount, contacts.Length); + Array.Copy(GetContacts_Internal(), contacts, contactCount); + return contactCount; + } //*undocumented* public virtual IEnumerator GetEnumerator() diff --git a/Runtime/Dynamics/ScriptBindings/Dynamics.bindings.cs b/Runtime/Dynamics/ScriptBindings/Dynamics.bindings.cs index 5d6ff7b9d4..7bc8c2ad9e 100644 --- a/Runtime/Dynamics/ScriptBindings/Dynamics.bindings.cs +++ b/Runtime/Dynamics/ScriptBindings/Dynamics.bindings.cs @@ -1455,6 +1455,7 @@ public static void Simulate(float step) extern public static bool autoSimulation { get; set; } extern public static void SyncTransforms(); extern public static bool autoSyncTransforms { get; set; } + extern public static bool reuseCollisionCallbacks { get; set; } [NativeName("ComputePenetration")] [StaticAccessor("GetPhysicsManager().GetPhysicsQuery()")] diff --git a/Runtime/Export/Application.bindings.cs b/Runtime/Export/Application.bindings.cs index 97e70bc4f9..b8daaeec24 100644 --- a/Runtime/Export/Application.bindings.cs +++ b/Runtime/Export/Application.bindings.cs @@ -213,7 +213,7 @@ extern public static string dataPath // Contains the path to the StreamingAssets folder (RO). extern public static string streamingAssetsPath { - [FreeFunction("GetStreamingAssetsPath")] + [FreeFunction("GetStreamingAssetsPath", IsThreadSafe = true)] get; } diff --git a/Runtime/Scripting/ManagedReference/SerializableManagedRefTests.Resources.cs b/Runtime/Scripting/ManagedReference/SerializableManagedRefTests.Resources.cs index 84ed81481a..f976176394 100644 --- a/Runtime/Scripting/ManagedReference/SerializableManagedRefTests.Resources.cs +++ b/Runtime/Scripting/ManagedReference/SerializableManagedRefTests.Resources.cs @@ -7,14 +7,18 @@ namespace EmbeddedScriptedObjectsTests { + public sealed class ExtensionOfNativeClass : Attribute {} + // Mimic exactly data layout of UnityEnging.Object! [StructLayout(LayoutKind.Sequential)] public class Object { - public IntPtr m_CachedPtr; - public int m_InstanceID; + public IntPtr m_CachedPtr; + public int m_InstanceID; + public string m_UnityRuntimeErrorString; } + [ExtensionOfNativeClass] public class DummyClass : Object { public int Attribute1 = 1; From 57f723ec72ca50427e5d17cad0ec123be2372f67 Mon Sep 17 00:00:00 2001 From: Unity Technologies Date: Wed, 28 Nov 2018 12:03:56 +0000 Subject: [PATCH 10/10] Unity 2018.3.0b12 C# reference source code --- .../SpriteFrameModuleBase.cs | 1 + .../SpriteEditorModule/SpriteOutlineModule.cs | 1 + .../SpritePhysicsShapeModule.cs | 1 + Editor/Mono/AssetModificationProcessor.cs | 4 +- Editor/Mono/ConsoleWindow.cs | 104 +++--- Editor/Mono/GI/Lightmapping.bindings.cs | 9 + Editor/Mono/GUI/PopupWindow.cs | 2 + .../PlayerConnection/AttachToPlayerGUI.cs | 322 ++++++++++++++++++ Editor/Mono/PerformanceTools/FrameDebugger.cs | 19 +- Editor/Mono/Prefabs/PrefabUtility.bindings.cs | 3 + Editor/Mono/Prefabs/PrefabUtility.cs | 157 ++++++++- .../PreferencesSettingsProviders.cs | 9 +- .../StageManager/PrefabStage/PrefabStage.cs | 60 ++-- .../PrefabStage/PrefabStageUtility.cs | 192 ++++++++--- .../StageManager/StageNavigationManager.cs | 13 +- .../StageManager/StageUtility.cs | 7 + .../Implementations/ExposedReferenceDrawer.cs | 3 - .../CSharpNamespaceParser.cs | 1 + Editor/Mono/SyncProject.cs | 29 +- .../VisualStudioIntegration/UnityVSSupport.cs | 13 +- .../ProfilerWindow/AttachProfilerUI.cs | 286 ---------------- .../ProfilerWindow/ProfilerWindow.cs | 24 +- .../ShortcutProfileManager.cs | 1 + Modules/TerrainEditor/Brush/Brush.cs | 2 +- .../Utilities/TerrainLayerInspector.cs | 2 +- Projects/CSharp/UnityEditor.csproj | 6 +- Projects/CSharp/UnityEngine.csproj | 3 + README.md | 2 +- .../PlayerConnection/ConnectionApi.cs | 16 + .../Scripting/AlwaysLinkAssemblyAttribute.cs | 13 + Runtime/Export/UnitySynchronizationContext.cs | 24 +- 31 files changed, 863 insertions(+), 466 deletions(-) create mode 100644 Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs delete mode 100644 Modules/ProfilerEditor/ProfilerWindow/AttachProfilerUI.cs create mode 100644 Runtime/Export/Scripting/AlwaysLinkAssemblyAttribute.cs diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs index ce7303068c..1223b9b2b4 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteFrameModule/SpriteFrameModuleBase.cs @@ -57,6 +57,7 @@ public override void OnModuleActivate() textureActualWidth = width; textureActualHeight = height; m_RectsCache = ScriptableObject.CreateInstance(); + m_RectsCache.hideFlags = HideFlags.HideAndDontSave; m_RectsCache.spriteRects = m_SpriteDataProvider.GetSpriteRects().ToList(); spriteEditor.spriteRects = m_RectsCache.spriteRects; if (spriteEditor.selectedSpriteRect != null) diff --git a/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs index 19ba825414..0db86e6b10 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpriteOutlineModule.cs @@ -327,6 +327,7 @@ private void ClearSelection() protected virtual void LoadOutline() { m_Outline = ScriptableObject.CreateInstance(); + m_Outline.hideFlags = HideFlags.HideAndDontSave; var spriteDataProvider = spriteEditorWindow.GetDataProvider(); var outlineDataProvider = spriteEditorWindow.GetDataProvider(); foreach (var rect in spriteDataProvider.GetSpriteRects()) diff --git a/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs b/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs index f0d796c4fe..3929527ca7 100644 --- a/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs +++ b/Editor/Mono/2D/SpriteEditorModule/SpritePhysicsShapeModule.cs @@ -58,6 +58,7 @@ public override bool ApplyRevert(bool apply) protected override void LoadOutline() { m_Outline = ScriptableObject.CreateInstance(); + m_Outline.hideFlags = HideFlags.HideAndDontSave; var spriteDataProvider = spriteEditorWindow.GetDataProvider(); var outlineDataProvider = spriteEditorWindow.GetDataProvider(); foreach (var rect in spriteDataProvider.GetSpriteRects()) diff --git a/Editor/Mono/AssetModificationProcessor.cs b/Editor/Mono/AssetModificationProcessor.cs index a2a8f8f548..37fad46f85 100644 --- a/Editor/Mono/AssetModificationProcessor.cs +++ b/Editor/Mono/AssetModificationProcessor.cs @@ -122,7 +122,7 @@ static void FileModeChanged(string[] assets, UnityEditor.VersionControl.FileMode } // Postprocess on all assets once an automatic import has completed - static void OnWillSaveAssets(string[] assets, out string[] assetsThatShouldBeSaved, out string[] assetsThatShouldBeReverted, int explicitlySaveAsset) + static void OnWillSaveAssets(string[] assets, out string[] assetsThatShouldBeSaved, out string[] assetsThatShouldBeReverted, bool explicitlySaveAsset) { assetsThatShouldBeReverted = new string[0]; assetsThatShouldBeSaved = assets; @@ -131,7 +131,7 @@ static void OnWillSaveAssets(string[] assets, out string[] assetsThatShouldBeSav // If we are only saving a single scene or prefab and the user explicitly said we should, skip the dialog. We don't need // to verify this twice. - if (explicitlySaveAsset != 0 && assets.Length == 1 && (assets[0].EndsWith(".unity") || assets[0].EndsWith(".prefab"))) + if (explicitlySaveAsset && assets.Length == 1 && (assets[0].EndsWith(".unity") || assets[0].EndsWith(".prefab"))) showSaveDialog = false; if (showSaveDialog) diff --git a/Editor/Mono/ConsoleWindow.cs b/Editor/Mono/ConsoleWindow.cs index 4cb9501d5d..65fe3c93a5 100644 --- a/Editor/Mono/ConsoleWindow.cs +++ b/Editor/Mono/ConsoleWindow.cs @@ -9,6 +9,9 @@ using System.Linq; using System.Text; using UnityEngine.Scripting; +using UnityEngine.Experimental.Networking.PlayerConnection; +using UnityEditor.Experimental.Networking.PlayerConnection; +using ConnectionGUILayout = UnityEditor.Experimental.Networking.PlayerConnection.EditorGUILayout; namespace UnityEditor { @@ -132,86 +135,53 @@ private static void UpdateLogStyleFixedHeights() int ms_LVHeight = 0; - class ConsoleAttachProfilerUI : AttachProfilerUI + class ConsoleAttachToPlayerState : GeneralConnectionState { - List additionalMenuItems = null; - - enum MenuItemIndex + static class Content { - PlayerLogging, - FullLog + public static GUIContent PlayerLogging = EditorGUIUtility.TrTextContent("Player Logging"); + public static GUIContent FullLog = EditorGUIUtility.TrTextContent("Full Log (Developer Mode Only)"); } - protected void SelectClick(object userData, string[] options, int selected) + public ConsoleAttachToPlayerState(EditorWindow parentWindow, Action connectedCallback = null) : base(parentWindow, connectedCallback) { - if (selected == (int)MenuItemIndex.PlayerLogging) - { - var connected = PlayerConnectionLogReceiver.instance.State != PlayerConnectionLogReceiver.ConnectionState.Disconnected; - PlayerConnectionLogReceiver.instance.State = connected ? PlayerConnectionLogReceiver.ConnectionState.Disconnected : PlayerConnectionLogReceiver.ConnectionState.CleanLog; - return; - } - - if (selected == (int)MenuItemIndex.FullLog) - { - var cleanLog = PlayerConnectionLogReceiver.instance.State == PlayerConnectionLogReceiver.ConnectionState.CleanLog; - PlayerConnectionLogReceiver.instance.State = cleanLog ? PlayerConnectionLogReceiver.ConnectionState.FullLog : PlayerConnectionLogReceiver.ConnectionState.CleanLog; - return; - } - - if (selected < additionalMenuItems.Count) - return; - - SelectProfilerClick(userData, options, selected - additionalMenuItems.Count); } - protected override void OnGUIMenu(Rect connectRect, List profilers) + bool IsConnected() { - if (additionalMenuItems == null) - { - additionalMenuItems = new List {"Player Logging"}; - if (Unsupported.IsDeveloperMode()) - additionalMenuItems.Add("Full Log (Developer Mode Only)"); - additionalMenuItems.Add(""); - } + return PlayerConnectionLogReceiver.instance.State != PlayerConnectionLogReceiver.ConnectionState.Disconnected; + } - var names = additionalMenuItems.Concat(profilers.Select(p => p.Name)).ToArray(); + void PlayerLoggingOptionSelected() + { + PlayerConnectionLogReceiver.instance.State = IsConnected() ? PlayerConnectionLogReceiver.ConnectionState.Disconnected : PlayerConnectionLogReceiver.ConnectionState.CleanLog; + } - // "Player Logging" field is always enabled. - var enabled = new List {true}; - var selected = new List(); + bool IsLoggingFullLog() + { + return PlayerConnectionLogReceiver.instance.State == PlayerConnectionLogReceiver.ConnectionState.FullLog; + } - var connected = PlayerConnectionLogReceiver.instance.State != PlayerConnectionLogReceiver.ConnectionState.Disconnected; - if (connected) - { - selected.Add((int)MenuItemIndex.PlayerLogging); - if (Unsupported.IsDeveloperMode()) - { - if (PlayerConnectionLogReceiver.instance.State == PlayerConnectionLogReceiver.ConnectionState.FullLog) - selected.Add((int)MenuItemIndex.FullLog); + void FullLogOptionSelected() + { + PlayerConnectionLogReceiver.instance.State = IsLoggingFullLog() ? PlayerConnectionLogReceiver.ConnectionState.CleanLog : PlayerConnectionLogReceiver.ConnectionState.FullLog; + } - // Enable "Show Full Log" - enabled.Add(true); - } - enabled.Add(true); - enabled.AddRange(profilers.Select(p => p.Enabled)); - } - else + public override void AddItemsToMenu(GenericMenu menu, Rect position) + { + // option to turn logging and the connection on or of + menu.AddItem(Content.PlayerLogging, IsConnected(), PlayerLoggingOptionSelected); + if (IsConnected()) { - // everything but first menu item is disabled. - enabled.AddRange(new bool[names.Length - 1]); + // All other options but the first are only available if logging is enabled + menu.AddItem(Content.FullLog, IsLoggingFullLog(), FullLogOptionSelected); + menu.AddSeparator(""); + base.AddItemsToMenu(menu, position); } - - int index = profilers.FindIndex(p => p.IsSelected()); - if (index != -1) - selected.Add(index + additionalMenuItems.Count); - - var seperators = new bool[enabled.Count]; - seperators[additionalMenuItems.Count - 1] = true; - EditorUtility.DisplayCustomMenuWithSeparators(connectRect, names, enabled.ToArray(), seperators, selected.ToArray(), SelectClick, profilers); } } - ConsoleAttachProfilerUI m_AttachProfilerUI = new ConsoleAttachProfilerUI(); + IConnectionState m_ConsoleAttachToPlayerState; [Flags] internal enum Mode @@ -322,6 +292,9 @@ public ConsoleWindow() void OnEnable() { + if (m_ConsoleAttachToPlayerState == null) + m_ConsoleAttachToPlayerState = new ConsoleAttachToPlayerState(this); + MakeSureConsoleAlwaysOnlyOne(); titleContent = GetLocalizedTitleContent(); @@ -347,6 +320,9 @@ void MakeSureConsoleAlwaysOnlyOne() void OnDisable() { + m_ConsoleAttachToPlayerState?.Dispose(); + m_ConsoleAttachToPlayerState = null; + if (ms_ConsoleWindow == this) ms_ConsoleWindow = null; } @@ -593,7 +569,7 @@ void OnGUI() SetFlag(ConsoleFlags.ClearOnPlay, GUILayout.Toggle(HasFlag(ConsoleFlags.ClearOnPlay), Constants.ClearOnPlayLabel, Constants.MiniButton)); SetFlag(ConsoleFlags.ErrorPause, GUILayout.Toggle(HasFlag(ConsoleFlags.ErrorPause), Constants.ErrorPauseLabel, Constants.MiniButton)); - m_AttachProfilerUI.OnGUILayout(this); + ConnectionGUILayout.AttachToPlayerDropdown(m_ConsoleAttachToPlayerState, EditorStyles.toolbarDropDown); EditorGUILayout.Space(); diff --git a/Editor/Mono/GI/Lightmapping.bindings.cs b/Editor/Mono/GI/Lightmapping.bindings.cs index 338e97ac25..1e1cbda86e 100644 --- a/Editor/Mono/GI/Lightmapping.bindings.cs +++ b/Editor/Mono/GI/Lightmapping.bindings.cs @@ -157,6 +157,7 @@ public enum GIWorkflowMode public delegate void OnStartedFunction(); public delegate void OnCompletedFunction(); + internal delegate void OnWroteLightingDataAsset(); // How is GI data created: iteratively or on demand by Enlighten [StaticAccessor("GetLightmapSettings()")] @@ -304,6 +305,14 @@ private static void Internal_CallStartedFunctions() started(); } + internal static event OnWroteLightingDataAsset wroteLightingDataAsset; + + internal static void Internal_CallOnWroteLightingDataAsset() + { + if (wroteLightingDataAsset != null) + wroteLightingDataAsset(); + } + public static OnCompletedFunction completed; private static void Internal_CallCompletedFunctions() diff --git a/Editor/Mono/GUI/PopupWindow.cs b/Editor/Mono/GUI/PopupWindow.cs index f24858ac39..e270597914 100644 --- a/Editor/Mono/GUI/PopupWindow.cs +++ b/Editor/Mono/GUI/PopupWindow.cs @@ -98,6 +98,8 @@ internal void OnGUI() private void FitWindowToContent() { + if (m_WindowContent == null) + return; Vector2 wantedSize = m_WindowContent.GetWindowSize(); if (m_LastWantedSize != wantedSize) { diff --git a/Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs b/Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs new file mode 100644 index 0000000000..fddc7584ed --- /dev/null +++ b/Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs @@ -0,0 +1,322 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEditor.Hardware; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Experimental.Networking.PlayerConnection; + +namespace UnityEditor.Experimental.Networking.PlayerConnection +{ + internal interface IConnectionStateInternal : IConnectionState + { + EditorWindow parentWindow { get; } + GUIContent notificationMessage { get; } + void AddItemsToMenu(GenericMenu menu, Rect position); + } + + public static partial class EditorGUIUtility + { + public static IConnectionState GetAttachToPlayerState(EditorWindow parentWindow, Action connectedCallback = null) + { + return new GeneralConnectionState(parentWindow, connectedCallback); + } + } + static class Styles + { + public static readonly GUIStyle defaultDropdown = "MiniPullDown"; + public static readonly GUIContent dropdownButton = UnityEditor.EditorGUIUtility.TrTextContent("", "Choose the target player to connect to."); + } + + public static partial class EditorGUI + { + public static void AttachToPlayerDropdown(Rect rect, IConnectionState state, GUIStyle style = null) + { + var internalState = state as IConnectionStateInternal; + if (internalState?.parentWindow) + { + if (internalState.notificationMessage != null) + internalState.parentWindow.ShowNotification(internalState.notificationMessage); + else + internalState.parentWindow.RemoveNotification(); + } + + Styles.dropdownButton.text = state.connectionName; + + if (style == null) + style = Styles.defaultDropdown; + + if (!UnityEditor.EditorGUI.DropdownButton(rect, Styles.dropdownButton, FocusType.Passive, style)) + return; + GenericMenu menu = new GenericMenu(); + + internalState?.AddItemsToMenu(menu, rect); + menu.DropDown(rect); + } + } + public static partial class EditorGUILayout + { + public static void AttachToPlayerDropdown(IConnectionState state, GUIStyle style = null) + { + if (style == null) + style = Styles.defaultDropdown; + Styles.dropdownButton.text = state.connectionName; + + var size = style.CalcSize(Styles.dropdownButton); + Rect connectRect = GUILayoutUtility.GetRect(size.x, size.y); + EditorGUI.AttachToPlayerDropdown(connectRect, state, style); + } + } + + internal class GeneralConnectionState : IConnectionStateInternal + { + static class Content + { + public static readonly GUIContent EnterIPText = UnityEditor.EditorGUIUtility.TrTextContent(""); + public static readonly GUIContent AutoconnectedPlayer = UnityEditor.EditorGUIUtility.TrTextContent("(Autoconnected Player)"); + public static readonly GUIContent ConnectingToPlayerMessage = UnityEditor.EditorGUIUtility.TrTextContent("Connecting to player...(this can take a while)"); + + public static readonly string LocalHostProhibited = L10n.Tr(" (Localhost prohibited)"); + public static readonly string VersionMismatch = L10n.Tr(" (Version mismatch)"); + } + static GUIContent s_NotificationMessage; + + public GUIContent notificationMessage => s_NotificationMessage; + + // keep this constant in sync with PLAYER_DIRECT_IP_CONNECT_GUID in GeneralConnection.h + const int PLAYER_DIRECT_IP_CONNECT_GUID = 0xFEED; + // keep this constant in sync with PLAYER_DIRECT_URL_CONNECT_GUID in GeneralConnection.h + const int PLAYER_DIRECT_URL_CONNECT_GUID = 0xFEEE; + + public EditorWindow parentWindow { get; private set; } + + public ConnectionTarget connectedToTarget => ProfilerDriver.IsConnectionEditor() ? ConnectionTarget.Editor : ConnectionTarget.Player; + + public string connectionName => ProfilerDriver.GetConnectionIdentifier(ProfilerDriver.connectedProfiler); + + private event Action connected; + + static List s_AllGeneralAttachToPlayerStates = new List(); + + public GeneralConnectionState(EditorWindow parentWindow, Action connectedCallback = null) + { + this.parentWindow = parentWindow; + if (parentWindow != null) + connected += (player) => this.parentWindow.Repaint(); + + if (connectedCallback != null) + connected += connectedCallback; + + s_AllGeneralAttachToPlayerStates.Add(new WeakReference(this)); + } + + static void SuccesfullyConnectedToPlayer(string player) + { + for (int i = s_AllGeneralAttachToPlayerStates.Count - 1; i >= 0; i--) + { + if (s_AllGeneralAttachToPlayerStates[i] == null || !s_AllGeneralAttachToPlayerStates[i].IsAlive) + { + s_AllGeneralAttachToPlayerStates.RemoveAt(i); + } + (s_AllGeneralAttachToPlayerStates[i].Target as GeneralConnectionState).connected?.Invoke(player); + } + } + + public virtual void AddItemsToMenu(GenericMenu menu, Rect position) + { + bool hasAnyConnectionOpen = false; + AddAvailablePlayerConnections(menu, ref hasAnyConnectionOpen); + AddAvailableDeviceConnections(menu, ref hasAnyConnectionOpen); + AddLastConnectedIP(menu, ref hasAnyConnectionOpen); + + // Case 810030: Check if player is connected using AutoConnect Profiler feature via 'connect string in PlayerConnectionConfigFile + // In that case ProfilerDriver.GetAvailableProfilers() won't return the connected player + // But we still want to show that it's connected, because the data is incoming + if (!ProfilerDriver.IsConnectionEditor() && !hasAnyConnectionOpen) + { + menu.AddDisabledItem(Content.AutoconnectedPlayer, true); + } + + AddConnectionViaEnterIPWindow(menu, GUIUtility.GUIToScreenRect(position)); + } + + internal static void DirectIPConnect(string ip) + { + // Profiler.DirectIPConnect is a blocking call, so a notification message and the console are used to show progress + ConsoleWindow.ShowConsoleWindow(true); + s_NotificationMessage = Content.ConnectingToPlayerMessage; + ProfilerDriver.DirectIPConnect(ip); + s_NotificationMessage = null; + SuccesfullyConnectedToPlayer(ip); + } + + internal static void DirectURLConnect(string url) + { + // Profiler.DirectURLConnect is a blocking call, so a notification message and the console are used to show progress + ConsoleWindow.ShowConsoleWindow(true); + s_NotificationMessage = Content.ConnectingToPlayerMessage; + ProfilerDriver.DirectURLConnect(url); + s_NotificationMessage = null; + SuccesfullyConnectedToPlayer(url); + } + + void AddLastConnectedIP(GenericMenu menuOptions, ref bool hasOpenConnection) + { + string lastIP = AttachToPlayerPlayerIPWindow.GetLastIPString(); + if (string.IsNullOrEmpty(lastIP)) + return; + + bool isConnected = ProfilerDriver.connectedProfiler == PLAYER_DIRECT_IP_CONNECT_GUID; + hasOpenConnection |= isConnected; + menuOptions.AddItem(new GUIContent(lastIP), isConnected, () => DirectIPConnect(lastIP)); + } + + void AddAvailablePlayerConnections(GenericMenu menuOptions, ref bool hasOpenConnection) + { + int[] connectionGuids = ProfilerDriver.GetAvailableProfilers(); + for (int index = 0; index < connectionGuids.Length; index++) + { + int guid = connectionGuids[index]; + string name = ProfilerDriver.GetConnectionIdentifier(guid); + bool isProhibited = ProfilerDriver.IsIdentifierOnLocalhost(guid) && (name.Contains("MetroPlayerX") || name.Contains("UWPPlayerX")); + bool enabled = !isProhibited && ProfilerDriver.IsIdentifierConnectable(guid); + + bool isConnected = ProfilerDriver.connectedProfiler == guid; + hasOpenConnection |= isConnected; + if (!enabled) + { + if (isProhibited) + name += Content.LocalHostProhibited; + else + name += Content.VersionMismatch; + } + if (enabled) + menuOptions.AddItem(new GUIContent(name), isConnected, () => + { + ProfilerDriver.connectedProfiler = guid; + SuccesfullyConnectedToPlayer(connectionName); + }); + else + menuOptions.AddDisabledItem(new GUIContent(name), isConnected); + } + } + + void AddAvailableDeviceConnections(GenericMenu menuOptions, ref bool hasOpenConnection) + { + foreach (var device in DevDeviceList.GetDevices()) + { + bool supportsPlayerConnection = (device.features & DevDeviceFeatures.PlayerConnection) != 0; + if (!device.isConnected || !supportsPlayerConnection) + continue; + + var url = "device://" + device.id; + bool isConnected = ProfilerDriver.connectedProfiler == PLAYER_DIRECT_URL_CONNECT_GUID && ProfilerDriver.directConnectionUrl == url; + hasOpenConnection |= isConnected; + menuOptions.AddItem(new GUIContent(device.name), isConnected, () => DirectURLConnect(url)); + } + } + + void AddConnectionViaEnterIPWindow(GenericMenu menuOptions, Rect buttonScreenRect) + { + menuOptions.AddItem(Content.EnterIPText, false, () => AttachToPlayerPlayerIPWindow.Show(buttonScreenRect)); + } + + private bool disposed = false; // To detect redundant calls + + ~GeneralConnectionState() + { + if (!disposed) + // Referring to the interface here, because the user only knows about the public IConnectionState interfaces and nothing about the internal GeneralConnectionState (except for the fact that it's about to show up in this error's callstack) + Debug.LogError("IConnectionState was not Disposed! Please make sure to call Dispose in OnDisable of the EditorWindow in which it was used."); + } + + public void Dispose() + { + if (!disposed) + { + if (s_AllGeneralAttachToPlayerStates != null) + { + for (int i = s_AllGeneralAttachToPlayerStates.Count - 1; i >= 0; i--) + { + if (!s_AllGeneralAttachToPlayerStates[i].IsAlive || s_AllGeneralAttachToPlayerStates[i].Target == this) + { + s_AllGeneralAttachToPlayerStates.RemoveAt(i); + } + } + } + parentWindow = null; + disposed = true; + } + } + } + + internal class AttachToPlayerPlayerIPWindow : EditorWindow + { + static class Content + { + public static readonly GUIContent ConnectButtonContent = UnityEditor.EditorGUIUtility.TrTextContent("Connect"); + public static readonly string EnterPlayerIPWindowName = L10n.Tr("Enter Player IP"); + } + private const string k_TextFieldControlId = "IPWindow"; + private const string k_LastIPEditorPrefKey = "ProfilerLastIP"; + + private string m_IPString; + private bool m_DidFocus = false; + + + public static void Show(Rect buttonScreenRect) + { + Rect rect = new Rect(buttonScreenRect.x, buttonScreenRect.yMax, 300, 50); + AttachToPlayerPlayerIPWindow w = EditorWindow.GetWindowWithRect(rect, true, Content.EnterPlayerIPWindowName); + w.position = rect; + w.m_Parent.window.m_DontSaveToLayout = true; + } + + void OnEnable() + { + m_IPString = GetLastIPString(); + } + + public static string GetLastIPString() + { + return EditorPrefs.GetString(k_LastIPEditorPrefKey, ""); + } + + void OnGUI() + { + Event evt = Event.current; + bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); + GUI.SetNextControlName(k_TextFieldControlId); + + UnityEditor.EditorGUILayout.BeginVertical(); + { + GUILayout.Space(5); + m_IPString = UnityEditor.EditorGUILayout.TextField(m_IPString); + + + if (!m_DidFocus) + { + m_DidFocus = true; + UnityEditor.EditorGUI.FocusTextInControl(k_TextFieldControlId); + } + + GUI.enabled = m_IPString.Length != 0; + if (GUILayout.Button(Content.ConnectButtonContent) || hitEnter) + { + Close(); + // Save ip + EditorPrefs.SetString(k_LastIPEditorPrefKey, m_IPString); + GeneralConnectionState.DirectIPConnect(m_IPString); + GUIUtility.ExitGUI(); + } + } + UnityEditor.EditorGUILayout.EndVertical(); + } + } +} diff --git a/Editor/Mono/PerformanceTools/FrameDebugger.cs b/Editor/Mono/PerformanceTools/FrameDebugger.cs index 2cca28353c..9ee0d15f0f 100644 --- a/Editor/Mono/PerformanceTools/FrameDebugger.cs +++ b/Editor/Mono/PerformanceTools/FrameDebugger.cs @@ -13,6 +13,9 @@ using System.Runtime.InteropServices; using UnityEditor; using UnityEditor.IMGUI.Controls; +using UnityEngine.Experimental.Networking.PlayerConnection; +using ConnectionUtility = UnityEditor.Experimental.Networking.PlayerConnection.EditorGUIUtility; +using ConnectionGUILayout = UnityEditor.Experimental.Networking.PlayerConnection.EditorGUILayout; namespace UnityEditorInternal { @@ -340,7 +343,7 @@ private struct EventDataStrings static List s_FrameDebuggers = new List(); - private AttachProfilerUI m_AttachProfilerUI = new AttachProfilerUI(); + private IConnectionState m_AttachToPlayerState; [MenuItem("Window/Analysis/Frame Debugger", false, 10)] public static FrameDebuggerWindow ShowFrameDebuggerWindow() @@ -414,6 +417,9 @@ void OnPlayModeStateChanged(PlayModeStateChange state) internal void OnEnable() { + if (m_AttachToPlayerState == null) + m_AttachToPlayerState = ConnectionUtility.GetAttachToPlayerState(this); + autoRepaintOnSceneChange = true; s_FrameDebuggers.Add(this); EditorApplication.pauseStateChanged += OnPauseStateChanged; @@ -433,6 +439,9 @@ internal void OnDisable() m_PreviewUtility = null; } + m_AttachToPlayerState?.Dispose(); + m_AttachToPlayerState = null; + s_FrameDebuggers.Remove(this); EditorApplication.pauseStateChanged -= OnPauseStateChanged; EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; @@ -456,7 +465,7 @@ private void ClickEnableFrameDebugger() { bool isEnabled = FrameDebuggerUtility.IsLocalEnabled() || FrameDebuggerUtility.IsRemoteEnabled(); - bool enablingLocally = !isEnabled && m_AttachProfilerUI.IsEditor(); + bool enablingLocally = !isEnabled && m_AttachToPlayerState.connectedToTarget == ConnectionTarget.Editor; if (enablingLocally && !FrameDebuggerUtility.locallySupported) return; @@ -598,7 +607,7 @@ private bool DrawToolbar(FrameDebuggerEvent[] descs) { bool repaint = false; - bool isSupported = !m_AttachProfilerUI.IsEditor() || FrameDebuggerUtility.locallySupported; + bool isSupported = m_AttachToPlayerState.connectedToTarget != ConnectionTarget.Editor || FrameDebuggerUtility.locallySupported; GUILayout.BeginHorizontal(EditorStyles.toolbar); // enable toggle @@ -613,7 +622,7 @@ private bool DrawToolbar(FrameDebuggerEvent[] descs) repaint = true; } - m_AttachProfilerUI.OnGUILayout(this); + ConnectionGUILayout.AttachToPlayerDropdown(m_AttachToPlayerState, EditorStyles.toolbarDropDown); bool isAnyEnabled = FrameDebuggerUtility.IsLocalEnabled() || FrameDebuggerUtility.IsRemoteEnabled(); if (isAnyEnabled && ProfilerDriver.connectedProfiler != FrameDebuggerUtility.GetRemotePlayerGUID()) @@ -1338,7 +1347,7 @@ internal void OnGUI() int oldLimit = FrameDebuggerUtility.limit; bool repaint = DrawToolbar(descs); - if (!FrameDebuggerUtility.IsLocalEnabled() && !FrameDebuggerUtility.IsRemoteEnabled() && m_AttachProfilerUI.IsEditor()) + if (!FrameDebuggerUtility.IsLocalEnabled() && !FrameDebuggerUtility.IsRemoteEnabled() && m_AttachToPlayerState.connectedToTarget == ConnectionTarget.Editor) { GUI.enabled = true; diff --git a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs index af06d67d6a..9470bc1c97 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.bindings.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.bindings.cs @@ -346,6 +346,9 @@ internal static void AddGameObjectsToPrefabAndConnect(GameObject[] gameObjects, [FreeFunction] extern internal static GameObject GetOriginalSourceOrVariantRoot([NotNull] Object instanceOrAsset); + [FreeFunction] + extern internal static GameObject GetOriginalSourceRootWhereGameObjectIsAdded([NotNull] GameObject gameObject); + [NativeMethod("PrefabUtilityBindings::ApplyPrefabAddedComponent", IsFreeFunction = true, ThrowsException = true)] extern private static void ApplyAddedComponent([NotNull] Component addedComponent, [NotNull] Object applyTargetPrefabObject); diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index 1f023bb79b..6ac985b14c 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -14,6 +14,7 @@ using Object = UnityEngine.Object; using RequiredByNativeCodeAttribute = UnityEngine.Scripting.RequiredByNativeCodeAttribute; using UnityEditor.VersionControl; +using UnityEditorInternal; namespace UnityEditor { @@ -368,18 +369,10 @@ private static void MapObjectReferencePropertyToSourceIfApplicable(SerializedPro { return; } - while (true) + referencedObject = GetCorrespondingObjectFromSourceAtPath(referencedObject, assetPath); + if (referencedObject != null) { - referencedObject = PrefabUtility.GetCorrespondingObjectFromSource(referencedObject); - if (referencedObject == null) - { - break; - } - if (AssetDatabase.GetAssetPath(referencedObject) == assetPath) - { - property.objectReferenceValue = referencedObject; - break; - } + property.objectReferenceValue = referencedObject; } } @@ -429,13 +422,31 @@ static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProper bool isObjectOnRootInAsset = IsObjectOnRootInAsset(prefabInstanceObject, assetPath); - SerializedProperty property; + SerializedProperty property = null; + SerializedProperty endProperty = null; if (optionalSingleInstanceProperty != null) { - property = optionalSingleInstanceProperty.Copy(); + bool cancel; + property = GetArrayPropertyIfGivenPropertyIsPartOfArrayElementInInstanceWhichDoesNotExistInAsset( + optionalSingleInstanceProperty, + prefabSourceSerializedObject, + action, + out cancel); + + if (cancel) + return; + + if (property == null) + { + // We didn't find any mismatching array so just use the property the user supplied. + property = optionalSingleInstanceProperty.Copy(); + } + endProperty = property.GetEndProperty(); } else { + // Note: Mismatching array sizes are not a problem when applying entire component, + // since array sizes will always be applied before array content. SerializedObject so = new SerializedObject(prefabInstanceObject); property = so.GetIterator(); } @@ -447,7 +458,7 @@ static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProper } else { - while (property.Next(property.hasChildren)) + while (property.Next(property.hasVisibleChildren) && (endProperty == null || !SerializedProperty.EqualContents(property, endProperty))) { // If we apply a property that has child properties that are object references if they // reference non-asset objects, those references will get lost, since ApplySingleProperty @@ -473,6 +484,75 @@ static void ApplyPropertyOverrides(Object prefabInstanceObject, SerializedProper } } + // Returns null if property is not part of array where whole array needs to be appled. + static SerializedProperty GetArrayPropertyIfGivenPropertyIsPartOfArrayElementInInstanceWhichDoesNotExistInAsset( + SerializedProperty optionalSingleInstanceProperty, + SerializedObject prefabSourceSerializedObject, + InteractionMode action, + out bool cancel) + { + cancel = false; + + // Check if the property is part of an array with mismatching size, + // and in that case make the property be that entire array. + string propertyPath = optionalSingleInstanceProperty.propertyPath; + int fullPropertyPathLength = optionalSingleInstanceProperty.propertyPath.Length; + int startSearchIndex = 0; + const string arrayElementIndexPrefix = ".Array.data["; + // We need to handle nested arrays, hence the while loop. + while (startSearchIndex < fullPropertyPathLength) + { + int arrayPropertySplitIndex = propertyPath.IndexOf(arrayElementIndexPrefix, startSearchIndex); + + // Break if no array was found in property path. + if (arrayPropertySplitIndex < 0) + return null; + + // Find property path for array. + string arrayPropertyPath = propertyPath.Substring(0, arrayPropertySplitIndex); + + // Find array element index start and length up front since we need it either way. + int arrayElementIndexStart = arrayPropertySplitIndex + arrayElementIndexPrefix.Length; + int arrayElementIndexLength = propertyPath.IndexOf(']', arrayElementIndexStart) - arrayElementIndexStart; + + // Check if found array has different length on instance than on Asset. + SerializedProperty arrayPropertyOnInstance = optionalSingleInstanceProperty.serializedObject.FindProperty(arrayPropertyPath); + SerializedProperty arrayPropertyOnAsset = prefabSourceSerializedObject.FindProperty(arrayPropertyPath); + if (arrayPropertyOnInstance.arraySize > arrayPropertyOnAsset.arraySize) + { + // Array size mismatches. Check if the property the user is attempting to apply + // resides in an element which exceeds the array in the Prefab Asset. + string arrayElementIndexString = propertyPath.Substring(arrayElementIndexStart, arrayElementIndexLength); + int indexInArray; + if (!int.TryParse(arrayElementIndexString, out indexInArray)) + { + // This should not be able to happen, but fallback by using array. + Debug.LogError("Misformed arrayElementIndexString " + arrayElementIndexString); + return arrayPropertyOnInstance; + } + + if (indexInArray >= arrayPropertyOnAsset.arraySize) + { + if (action == InteractionMode.UserAction && !EditorUtility.DisplayDialog( + "Mismatching array size", + string.Format("The property is part of an array element which does not exist in the source Prefab because the corresponding array there is shorter. Do you want to apply the entire array '{0}'?", arrayPropertyOnInstance.displayName), + "Apply Array", + "Cancel")) + { + cancel = true; + return null; + } + + return arrayPropertyOnInstance; + } + } + + // Array does not mismatch, so look if there are other arrays (deeper in property path) that do. + startSearchIndex = arrayPropertySplitIndex + arrayElementIndexPrefix.Length + arrayElementIndexLength + 1; + } + return null; + } + // Since method is called for each overridden property in a component. // That may be thousands of times if a component has lots of array data. // We provide as much information as possible to the method as parameters @@ -656,7 +736,21 @@ public static void RevertAddedComponent(Component component, InteractionMode act throw new ArgumentNullException(nameof(component), "Can't revert added component. Component is null."); if (action == InteractionMode.UserAction) + { + string dependentComponents = string.Join( + ", ", + GetDependentComponents(component).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray()); + if (!string.IsNullOrEmpty(dependentComponents)) + { + string error = String.Format( + L10n.Tr("Can't revert added component {0} because {1} depends on it"), + ObjectNames.GetInspectorTitle(component), + dependentComponents); + EditorUtility.DisplayDialog(L10n.Tr("Can't revert added component"), error, L10n.Tr("OK")); + return; + } Undo.DestroyObjectImmediate(component); + } else Object.DestroyImmediate(component); } @@ -1663,6 +1757,41 @@ internal static List GetApplyTargets(Object instanceOrAssetObject, bool return applyTargets; } + static List GetDependentComponents(Component component) + { + List dependencies = new List(); + var componentType = component.GetType(); + + // Iterate all components on *this* GameObject. + // We don't care about other components on the Prefab instance. + var allComponents = component.gameObject.GetComponents(); + for (int i = 0; i < allComponents.Length; i++) + { + var comp = allComponents[i]; + + // Ignore components that are not added. + if (GetCorrespondingObjectFromSource(comp) != null) + continue; + + // Ignore component itself the user is reverting. + if (comp == component) + continue; + + var requiredComps = comp.GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true); + foreach (RequireComponent reqComp in requiredComps) + { + if (reqComp.m_Type0 == componentType || reqComp.m_Type1 == componentType || reqComp.m_Type2 == componentType) + { + // We might get the same component type requirement from multiple sources. + // Make sure we don't add the same component more than once. + if (!dependencies.Contains(comp)) + dependencies.Add(comp); + } + } + } + return dependencies; + } + internal static class Analytics { public enum ApplyScope diff --git a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs index f9a21083bd..6bfd782186 100644 --- a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs +++ b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs @@ -527,6 +527,13 @@ private static void RevertPrefKeys() kvp.Value.ResetToDefault(); EditorPrefs.SetString(kvp.Value.Name, kvp.Value.ToUniqueString()); } + + // Delete PrefKeys from EditorPrefs based on key given in FormerlyPrefKeyAs attributes + foreach (var methodInfo in EditorAssemblies.GetAllMethodsWithAttribute()) + { + var attribute = (FormerlyPrefKeyAsAttribute)Attribute.GetCustomAttribute(methodInfo, typeof(FormerlyPrefKeyAsAttribute)); + EditorPrefs.DeleteKey(attribute.name); + } } private SortedDictionary>> OrderPrefs(IEnumerable> input) @@ -847,8 +854,8 @@ private void ShowShortcuts(string searchContext) { m_ValidKeyChange = true; m_InvalidKeyMessage = ""; - RevertShortcuts(); RevertPrefKeys(); + RevertShortcuts(); } } diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs index 77604461f3..eb54a144f6 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStage.cs @@ -136,21 +136,15 @@ internal bool LoadStage(string prefabPath) m_PrefabAssetPath = prefabPath; - // Tempoary scene used while loading the prefab - m_PreviewScene = EditorSceneManager.NewPreviewScene(); + // Ensure m_PreviewScene is set before calling LoadPrefabIntoPreviewScene() so the user can request the current + // the PrefabStage in their OnEnable and other callbacks (if they use ExecuteInEditMode or ExecuteAlways) + bool isUIPrefab = PrefabStageUtility.IsUIPrefab(m_PrefabAssetPath); + m_PreviewScene = PrefabStageUtility.GetEnvironmentSceneOrEmptyScene(isUIPrefab); - // The user can have OnEnable and other callbacks called during LoadPrefabIntoPreviewScene (if they use ExecuteInEditMode or ExecuteAlways) - // where they might request the current the prefabstage, so we ensure m_PreviewScene have been setup so they can check this stage's scene. m_PrefabContentsRoot = PrefabStageUtility.LoadPrefabIntoPreviewScene(prefabAssetPath, m_PreviewScene); - if (m_PrefabContentsRoot != null) { - Scene environmentScene = PrefabStageUtility.MovePrefabRootToEnvironmentScene(m_PrefabContentsRoot); - - // Close the temporary prefab loading scene and set the environment scene as the scene of the stage - EditorSceneManager.ClosePreviewScene(m_PreviewScene); - m_PreviewScene = environmentScene; - + PrefabStageUtility.HandleReparentingIfNeeded(m_PrefabContentsRoot, isUIPrefab); m_PrefabFileIcon = DeterminePrefabFileIconFromInstanceRootGameObject(); m_InitialSceneDirtyID = m_PreviewScene.dirtyID; UpdateEnvironmentHideFlags(); @@ -164,7 +158,8 @@ internal bool LoadStage(string prefabPath) return initialized; } - internal void OpenStage(string prefabPath) + // Returns true if opened successfully + internal bool OpenStage(string prefabPath) { if (LoadStage(prefabPath)) { @@ -178,7 +173,9 @@ internal void OpenStage(string prefabPath) EnsureParentOfPrefabRootIsUnpacked(); UpdateEnvironmentHideFlags(); } + return true; } + return false; } internal void CloseStage() @@ -217,8 +214,8 @@ void ReloadStage() Debug.Log("RELOADING Prefab at " + m_PrefabAssetPath); StageNavigationManager.instance.PrefabStageReloading(this); - OpenStage(m_PrefabAssetPath); - StageNavigationManager.instance.PrefabStageReloaded(this); + if (OpenStage(m_PrefabAssetPath)) + StageNavigationManager.instance.PrefabStageReloaded(this); if (SceneHierarchy.s_DebugPrefabStage) Debug.Log("RELOADING done"); @@ -329,6 +326,21 @@ public void ClearDirtiness() m_InitialSceneDirtyID = m_PreviewScene.dirtyID; } + bool PromptIfMissingBasePrefabForVariant() + { + if (PrefabUtility.IsPrefabAssetMissing(m_PrefabContentsRoot)) + { + string title = L10n.Tr("Saving Variant Failed"); + string message = L10n.Tr("Can't save the Prefab Variant when its base Prefab is missing. You have to unpack the root GameObject or recover the missing base Prefab in order to save the Prefab Variant"); + if (autoSave) + message += L10n.Tr("\n\nAuto Save has been temporarily disabled."); + EditorUtility.DisplayDialog(title, message, L10n.Tr("OK")); + m_TemporarilyDisableAutoSave = true; + return true; + } + return false; + } + // Returns true if saved succesfully (internal so we can use it in Tests) internal bool SavePrefab() { @@ -346,6 +358,14 @@ internal bool SavePrefab() var startTime = EditorApplication.timeSinceStartup; + if (PromptIfMissingBasePrefabForVariant()) + return false; + + // The user can have deleted required folders + var folder = Path.GetDirectoryName(m_PrefabAssetPath); + if (!Directory.Exists(folder)) + Directory.CreateDirectory(folder); + bool savedSuccesfully; PrefabUtility.SaveAsPrefabAsset(m_PrefabContentsRoot, m_PrefabAssetPath, out savedSuccesfully); m_LastSavingDuration = (float)(EditorApplication.timeSinceStartup - startTime); @@ -371,6 +391,7 @@ internal bool SavePrefab() EditorUtility.DisplayDialog(title, message, L10n.Tr("OK")); m_TemporarilyDisableAutoSave = true; + m_IgnoreNextAssetImportedEventForCurrentPrefab = false; } if (SceneHierarchy.s_DebugPrefabStage) @@ -643,21 +664,20 @@ internal void OnAssetsChangedOnHDD(string[] importedAssets, string[] deletedAsse } } - // Prefab was modified on HDD + // Detect if our Prefab was modified on HDD outside Prefab Mode (in that case we should ask the user if he wants to reload it) for (int i = 0; i < importedAssets.Length; ++i) { if (importedAssets[i] == m_PrefabAssetPath) { if (!m_IgnoreNextAssetImportedEventForCurrentPrefab) m_PrefabWasChangedOnDisk = true; + + // Reset the ignore flag when we finally have imported the saved prefab (We set this flag when saving the Prefab from Prefab Mode) + // Note we can get multiple OnAssetsChangedOnHDD events before the Prefab imported event if e.g folders of the Prefab path needs to be reimported first. + m_IgnoreNextAssetImportedEventForCurrentPrefab = false; break; } } - - if (importedAssets.Length > 0) - { - m_IgnoreNextAssetImportedEventForCurrentPrefab = false; - } } void DestroyPrefabInstance() diff --git a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs index 13e746dafd..acd5d4777b 100644 --- a/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs +++ b/Editor/Mono/SceneManagement/StageManager/PrefabStage/PrefabStageUtility.cs @@ -5,16 +5,37 @@ using System; using System.IO; using UnityEditor.SceneManagement; +using UnityEditor.ShortcutManagement; using UnityEngine; using UnityEngine.Assertions; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.Scripting; +using System.Linq; +using System.Collections.Generic; namespace UnityEditor.Experimental.SceneManagement { public class PrefabStageUtility { + [Shortcut("Stage/Enter Prefab Mode", null, "p")] + static void EnterPrefabModeShortcut() + { + var activeGameObject = Selection.activeGameObject; + if (activeGameObject == null) + return; + + if (PrefabUtility.IsPartOfAnyPrefab(activeGameObject)) + { + var prefabPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(activeGameObject); + if (!string.IsNullOrEmpty(prefabPath) && prefabPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase)) + { + var instanceObject = !EditorUtility.IsPersistent(activeGameObject) ? activeGameObject : null; + OpenPrefab(prefabPath, instanceObject); + } + } + } + internal static PrefabStage OpenPrefab(string prefabAssetPath) { return OpenPrefab(prefabAssetPath, null); @@ -30,6 +51,9 @@ internal static PrefabStage OpenPrefab(string prefabAssetPath, GameObject instan if (string.IsNullOrEmpty(prefabAssetPath)) throw new ArgumentNullException(prefabAssetPath); + if (!prefabAssetPath.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase)) + throw new ArgumentException("Incorrect file extension: " + prefabAssetPath + ". Must be '.prefab'", prefabAssetPath); + if (AssetDatabase.LoadMainAssetAtPath(prefabAssetPath) == null) throw new ArgumentException("Prefab not found at path " + prefabAssetPath, prefabAssetPath); @@ -69,37 +93,133 @@ internal static bool IsGameObjectThePrefabRootInAnyPrefabStage(GameObject gameOb return false; } - internal static GameObject LoadPrefabIntoPreviewScene(string prefabAssetPath, Scene previewScene) + static bool IsDynamicallyCreatedDuringLoad(GameObject gameObject) { - Assert.AreEqual(0, previewScene.GetRootGameObjects().Length); + return Unsupported.GetFileIDHint(gameObject) == 0; + } - PrefabUtility.LoadPrefabContentsIntoPreviewScene(prefabAssetPath, previewScene); - var roots = previewScene.GetRootGameObjects(); - if (roots.Length == 0) - { - Debug.LogError("No Prefab instance root loaded.."); - return null; - } + static UInt64 GetPrefabOrVariantFileID(GameObject gameObject) + { + var handle = PrefabUtility.GetPrefabInstanceHandle(gameObject); + if (handle != null) + return Unsupported.GetFileIDHint(handle); - GameObject prefabInstanceRoot = null; - if (roots.Length == 1) - prefabInstanceRoot = roots[0]; - else + return Unsupported.GetFileIDHint(gameObject); + } + + static GameObject FindFirstGameObjectThatMatchesFileID(Transform searchRoot, UInt64 fileID) + { + GameObject result = null; + var transformVisitor = new TransformVisitor(); + transformVisitor.VisitAndAllowEarlyOut(searchRoot, + (transform, userdata) => + { + UInt64 id = GetPrefabOrVariantFileID(transform.gameObject); + if (id == fileID) + { + result = transform.gameObject; + return false; // stop searching + } + return true; // continue searching + } + , null); + + return result; + } + + static GameObject RepairBrokenPrefabIfNeeded(string prefabAssetPath, GameObject[] environmentRoots, GameObject[] rootsAfterLoadingPrefab) + { + var rootsLoadedFromFile = rootsAfterLoadingPrefab.Except(environmentRoots).ToList(); + + // Filter out the subset of roots that were loaded from the Prefab file (there can be dynamically created environment objects, + // created from Awake and OnEnable calls from user land, if they use ExecuteAlways or ExecuteInEditMode. + rootsLoadedFromFile.RemoveAll(x => IsDynamicallyCreatedDuringLoad(x)); + + if (rootsLoadedFromFile.Count >= 2) { - prefabInstanceRoot = ObjectFactory.CreateGameObject("Replacement Root"); - var rootTransform = prefabInstanceRoot.GetComponent(); + Debug.LogError(string.Format("Prefab Mode: Multiple roots detected. Combined under new generated root. Prefab '{0}'", prefabAssetPath)); + var root = ObjectFactory.CreateGameObject("Replacement Root"); + var rootTransform = root.GetComponent(); + var previewScene = rootsLoadedFromFile[0].scene; + SceneManager.MoveGameObjectToScene(root.gameObject, previewScene); - for (int i = 0; i < roots.Length; ++i) + foreach (var go in rootsLoadedFromFile) { - roots[i].GetComponent().parent = rootTransform; + go.GetComponent().parent = rootTransform; } + return root; + } + + return null; + } + + static GameObject FindPrefabRoot(string prefabAssetPath, GameObject[] environmentRoots, GameObject[] rootsAfterLoadingPrefab) + { + var assetRoot = AssetDatabase.LoadAssetAtPath(prefabAssetPath); + if (assetRoot == null) + { + Debug.LogError(string.Format("Opening Prefab Mode failed: The Prefab at '{0}' is broken.", prefabAssetPath)); + return null; } - // We need to ensure root instance name is matching filename when loading a prefab as a scene since the prefab file might contain an old root name. - // The same name-matching is also ensured when importing a prefab: the library prefab asset root gets the same name as the filename of the prefab. + var repairedRoot = RepairBrokenPrefabIfNeeded(prefabAssetPath, environmentRoots, rootsAfterLoadingPrefab); + if (repairedRoot != null) + return repairedRoot; + + // Normal use case: Find the prefab root or variant root among the roots of the scene (or as a child) + UInt64 prefabAssetRootFileID = GetPrefabOrVariantFileID(assetRoot); + + foreach (var root in rootsAfterLoadingPrefab) + { + var prefabRoot = FindFirstGameObjectThatMatchesFileID(root.transform, prefabAssetRootFileID); + if (prefabRoot != null) + return prefabRoot; + } + + Debug.LogError(string.Format("Opening Prefab Mode failed: Could not detect a Prefab root after loading '{0}'.", prefabAssetPath)); + return null; + } + + internal static GameObject LoadPrefabIntoPreviewScene(string prefabAssetPath, Scene previewScene) + { var prefabName = Path.GetFileNameWithoutExtension(prefabAssetPath); - prefabInstanceRoot.name = prefabName; - return prefabInstanceRoot; + previewScene.name = prefabName; + + // Get start roots from scene (before loading in the the Prefab) + var environmentRoots = previewScene.GetRootGameObjects(); + + // Load Prefab into scene + try + { + PrefabUtility.LoadPrefabContentsIntoPreviewScene(prefabAssetPath, previewScene); + } + catch (Exception e) + { + Debug.LogError(string.Format("Loading Prefab failed: {0}", e.Message)); + return null; + } + + var rootsAfterLoadingPrefab = previewScene.GetRootGameObjects(); + var root = FindPrefabRoot(prefabAssetPath, environmentRoots, rootsAfterLoadingPrefab); + if (root != null) + { + // We need to ensure root instance name is matching filename when loading a prefab as a scene since the prefab file might contain an old root name. + // The same name-matching is also ensured when importing a prefab: the library prefab asset root gets the same name as the filename of the prefab. + root.name = prefabName; + } + return root; + } + + internal static void HandleReparentingIfNeeded(GameObject prefabInstanceRoot, bool isUIPrefab) + { + // Skip reparenting if the root is already reparented + if (prefabInstanceRoot.transform.parent != null) + return; + + if (isUIPrefab) + HandleUIReparentingIfNeeded(prefabInstanceRoot); + else + prefabInstanceRoot.transform.SetAsFirstSibling(); } static string GetEnvironmentScenePathForPrefab(bool isUIPrefab) @@ -190,47 +310,40 @@ internal static void DestroyPreviewScene(Scene previewScene) } } - internal static Scene MovePrefabRootToEnvironmentScene(GameObject prefabInstanceRoot) + internal static Scene GetEnvironmentSceneOrEmptyScene(bool isUIPrefab) { - bool isUIPrefab = PrefabStageUtility.IsUI(prefabInstanceRoot); - // Create the environment scene and move the prefab root to this scene to ensure // the correct rendersettings (skybox etc) are used in Prefab Mode. string environmentEditingScenePath = GetEnvironmentScenePathForPrefab(isUIPrefab); Scene environmentScene = LoadOrCreatePreviewScene(environmentEditingScenePath); - environmentScene.name = prefabInstanceRoot.name; - SceneManager.MoveGameObjectToScene(prefabInstanceRoot, environmentScene); - - if (isUIPrefab) - HandleUIReparentingIfNeeded(prefabInstanceRoot, environmentScene); - else - prefabInstanceRoot.transform.SetAsFirstSibling(); - return environmentScene; } - static bool IsUI(GameObject root) + internal static bool IsUIPrefab(string prefabAssetPath) { // We require a RectTransform and a CanvasRenderer to be considered a UI prefab. // E.g 3D TextMeshPro uses RectTransform but a MeshRenderer so should not be considered a UI prefab // This function needs to be peformant since it is called every time a prefab is opened in a prefab stage. + var root = AssetDatabase.LoadAssetAtPath(prefabAssetPath); + if (root == null) + return false; return root.GetComponent() != null && root.GetComponentInChildren(true) != null; } - static void HandleUIReparentingIfNeeded(GameObject instanceRoot, Scene scene) + static void HandleUIReparentingIfNeeded(GameObject instanceRoot) { // We need a Canvas in order to render UI so ensure the prefab instance is under a Canvas Canvas canvas = instanceRoot.GetComponent(); if (canvas != null) return; - GameObject canvasGameObject = GetOrCreateCanvasGameObject(instanceRoot, scene); + GameObject canvasGameObject = GetOrCreateCanvasGameObject(instanceRoot); instanceRoot.transform.SetParent(canvasGameObject.transform, false); } - static GameObject GetOrCreateCanvasGameObject(GameObject instanceRoot, Scene scene) + static GameObject GetOrCreateCanvasGameObject(GameObject instanceRoot) { - Canvas canvas = GetCanvasInScene(instanceRoot, scene); + Canvas canvas = GetCanvasInScene(instanceRoot); if (canvas != null) return canvas.gameObject; @@ -241,12 +354,13 @@ static GameObject GetOrCreateCanvasGameObject(GameObject instanceRoot, Scene sce root.layer = LayerMask.NameToLayer(kUILayerName); canvas = root.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; - SceneManager.MoveGameObjectToScene(root, scene); + SceneManager.MoveGameObjectToScene(root, instanceRoot.scene); return root; } - static Canvas GetCanvasInScene(GameObject instanceRoot, Scene scene) + static Canvas GetCanvasInScene(GameObject instanceRoot) { + Scene scene = instanceRoot.scene; foreach (GameObject go in scene.GetRootGameObjects()) { // Do not search for Canvas's under the prefab root since we want to diff --git a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs index 4b395dbd42..0d8f811a4d 100644 --- a/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs +++ b/Editor/Mono/SceneManagement/StageManager/StageNavigationManager.cs @@ -323,8 +323,8 @@ internal bool SwitchToStage(StageNavigationItem newStage, bool setAsFirstItemAft PrefabStage prefabStage = new PrefabStage(); m_PrefabStages.Add(prefabStage); - prefabStage.OpenStage(newStage.prefabAssetPath); - if (prefabStage.prefabContentsRoot == null) + var success = prefabStage.OpenStage(newStage.prefabAssetPath); + if (!success) { m_PrefabStages.RemoveAt(m_PrefabStages.Count - 1); return false; @@ -448,6 +448,15 @@ static void HandleSelectionWhenSwithingToNewPrefabMode(GameObject prefabContents newSelection = prefabContentsRoot; Selection.activeGameObject = newSelection; + + // For Prefab Mode we restore the last expanded tree view state for the opened Prefab. For usability + // if a child GameObject on the Prefab Instance is selected when entering the Prefab Asset Mode we select the corresponding + // child GameObject in the Asset. Here we ensure that selction is revealed and framed in the Scene hierarchy. + if (newSelection != prefabContentsRoot) + { + foreach (SceneHierarchyWindow shw in SceneHierarchyWindow.GetAllSceneHierarchyWindows()) + shw.FrameObject(newSelection.GetInstanceID(), false); + } } static bool IsPartOfPrefabStage(GameObject gameObject, PrefabStage prefabStage) diff --git a/Editor/Mono/SceneManagement/StageManager/StageUtility.cs b/Editor/Mono/SceneManagement/StageManager/StageUtility.cs index 424ca7605e..25945cfe8a 100644 --- a/Editor/Mono/SceneManagement/StageManager/StageUtility.cs +++ b/Editor/Mono/SceneManagement/StageManager/StageUtility.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System.Collections.Generic; +using UnityEditor.ShortcutManagement; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.Scripting; @@ -12,6 +13,12 @@ namespace UnityEditor.SceneManagement { public static partial class StageUtility { + [Shortcut("Stage/Go Back", null, "o")] + static void GoBackShortcut() + { + StageUtility.GoBackToPreviousStage(); + } + public static bool IsGameObjectRenderedByCamera(GameObject gameObject, Camera camera) { return IsGameObjectRenderedByCameraInternal(gameObject, camera); diff --git a/Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs b/Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs index e80e59e4ae..f0f15fdd38 100644 --- a/Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs +++ b/Editor/Mono/ScriptAttributeGUI/Implementations/ExposedReferenceDrawer.cs @@ -97,7 +97,6 @@ public override void OnGUI(Rect position, var valuePosition = DrawLabel(showContextMenu, currentOverrideState, label, position, exposedPropertyTable, exposedNameStr, exposedName, defaultValue); - EditorGUI.BeginChangeCheck(); if (propertyMode == ExposedPropertyMode.DefaultValue || propertyMode == ExposedPropertyMode.NamedGUID) { OnRenderProperty(valuePosition, propertyName, currentReferenceValue, defaultValue, exposedName, propertyMode, exposedPropertyTable); @@ -114,8 +113,6 @@ public override void OnGUI(Rect position, OnRenderProperty(valuePosition, new PropertyName(exposedNameStr), currentReferenceValue, defaultValue, exposedName, propertyMode, exposedPropertyTable); } - EditorGUI.EndDisabledGroup(); - GUI.color = previousColor; EditorGUIUtility.SetBoldDefaultFont(wasBoldDefaultFont); diff --git a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs index 33221217f4..b29c286f46 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs @@ -315,6 +315,7 @@ static bool HasPrecedence(char op1, char op2) { if (op2 == '(' || op2 == ')') return false; if (op1 == '!' && op2 == '&') return false; + if (op1 == '!' && op2 == '|') return false; if (op1 == '&' && op2 == '|') return false; if (op1 == '=') return false; diff --git a/Editor/Mono/SyncProject.cs b/Editor/Mono/SyncProject.cs index 5062977b66..1bef270055 100644 --- a/Editor/Mono/SyncProject.cs +++ b/Editor/Mono/SyncProject.cs @@ -24,6 +24,7 @@ internal enum VisualStudioVersion VisualStudio2013 = 12, VisualStudio2015 = 14, VisualStudio2017 = 15, + VisualStudio2019 = 16, } internal class VisualStudioPath @@ -275,23 +276,27 @@ private static IDictionary GetInstalled } } - var requiredWorkloads = new[] {"Microsoft.VisualStudio.Workload.ManagedGame"}; - var raw = VisualStudioUtil.FindVisualStudioDevEnvPaths((int)VisualStudioVersion.VisualStudio2017, requiredWorkloads); - - var visualStudioPaths = VisualStudioUtil.ParseRawDevEnvPaths(raw) - .Where(vs => !requiredWorkloads.Except(vs.Workloads).Any()) // All required workloads must be present - .Select(vs => new VisualStudioPath(vs.DevEnvPath, vs.Edition)) - .ToArray(); - - if (visualStudioPaths.Length != 0) - { - versions[VisualStudioVersion.VisualStudio2017] = visualStudioPaths; - } + GetInstalledVisualStudios(VisualStudioVersion.VisualStudio2017, versions); + GetInstalledVisualStudios(VisualStudioVersion.VisualStudio2019, versions); } return versions; } + private static void GetInstalledVisualStudios(VisualStudioVersion vsVersion, Dictionary versions) + { + var requiredWorkloads = new[] { "Microsoft.VisualStudio.Workload.ManagedGame" }; + var raw = VisualStudioUtil.FindVisualStudioDevEnvPaths((int)vsVersion, requiredWorkloads); + + var visualStudioPaths = VisualStudioUtil.ParseRawDevEnvPaths(raw) + .Where(vs => !requiredWorkloads.Except(vs.Workloads).Any()) // All required workloads must be present + .Select(vs => new VisualStudioPath(vs.DevEnvPath, vs.Edition)) + .ToArray(); + + if (visualStudioPaths.Length != 0) + versions[vsVersion] = visualStudioPaths; + } + static string GetRegistryValue(string path, string key) { try diff --git a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs b/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs index 40749c3564..39702b5cc2 100644 --- a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs +++ b/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs @@ -224,6 +224,9 @@ private static bool TryGetVisualStudioVersion(string externalEditor, out VisualS case 15: vsVersion = VisualStudioVersion.VisualStudio2017; return true; + case 16: + vsVersion = VisualStudioVersion.VisualStudio2019; + return true; } vsVersion = VisualStudioVersion.Invalid; @@ -263,8 +266,13 @@ static string GetAssemblyLocation(System.Reflection.Assembly a) [RequiredByNativeCode] static public bool IsUnityVSEnabled() { + if (!m_ShouldUnityVSBeActive) + { + return false; + } + if (!s_IsUnityVSEnabled.HasValue) - s_IsUnityVSEnabled = m_ShouldUnityVSBeActive && AppDomain.CurrentDomain.GetAssemblies().Any(a => GetAssemblyLocation(a) == s_UnityVSBridgeToLoad); + s_IsUnityVSEnabled = AppDomain.CurrentDomain.GetAssemblies().Any(a => GetAssemblyLocation(a) == s_UnityVSBridgeToLoad); return s_IsUnityVSEnabled.Value; } @@ -282,6 +290,9 @@ private static string GetVstuBridgeAssembly(VisualStudioVersion version) case VisualStudioVersion.VisualStudio2017: vsVersion = "15.0"; break; + case VisualStudioVersion.VisualStudio2019: + vsVersion = "16.0"; + break; // VS 2015 and under are still installed in the registry // using their project names case VisualStudioVersion.VisualStudio2015: diff --git a/Modules/ProfilerEditor/ProfilerWindow/AttachProfilerUI.cs b/Modules/ProfilerEditor/ProfilerWindow/AttachProfilerUI.cs deleted file mode 100644 index ef4ce412c6..0000000000 --- a/Modules/ProfilerEditor/ProfilerWindow/AttachProfilerUI.cs +++ /dev/null @@ -1,286 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using UnityEditor; -using UnityEditor.Hardware; -using UnityEditorInternal; -using UnityEngine; - - -namespace UnityEditor -{ - internal struct ProfilerChoise - { - public string Name; - public bool Enabled; - public Func IsSelected; - public Action ConnectTo; - } - - internal class AttachProfilerUI - { - private static string kEnterIPText = ""; - private static GUIContent ms_NotificationMessage; - - // keep this constant in sync with PLAYER_DIRECT_IP_CONNECT_GUID in GeneralConnection.h - const int PLAYER_DIRECT_IP_CONNECT_GUID = 0xFEED; - // keep this constant in sync with PLAYER_DIRECT_URL_CONNECT_GUID in GeneralConnection.h - const int PLAYER_DIRECT_URL_CONNECT_GUID = 0xFEEE; - - public delegate void ProfilerTargetSelectionChangedDelegate(); - public ProfilerTargetSelectionChangedDelegate OnProfilerTargetChanged - { - private get; - set; - } - - protected void SelectProfilerClick(object userData, string[] options, int selected) - { - var profilers = (List)userData; - if (selected < profilers.Count()) - { - profilers[selected].ConnectTo(); - if (OnProfilerTargetChanged != null) - { - OnProfilerTargetChanged.Invoke(); - } - } - } - - public bool IsEditor() - { - return ProfilerDriver.IsConnectionEditor(); - } - - public string GetConnectedProfiler() - { - return ProfilerDriver.GetConnectionIdentifier(ProfilerDriver.connectedProfiler); - } - - public static void DirectIPConnect(string ip) - { - // Profiler.DirectIPConnect is a blocking call, so a notification message and the console are used to show progress - ConsoleWindow.ShowConsoleWindow(true); - ms_NotificationMessage = EditorGUIUtility.TrTextContent("Connecting to player...(this can take a while)"); - ProfilerDriver.DirectIPConnect(ip); - ms_NotificationMessage = null; - } - - public static void DirectURLConnect(string url) - { - // Profiler.DirectURLConnect is a blocking call, so a notification message and the console are used to show progress - ConsoleWindow.ShowConsoleWindow(true); - ms_NotificationMessage = EditorGUIUtility.TrTextContent("Connecting to player...(this can take a while)"); - ProfilerDriver.DirectURLConnect(url); - ms_NotificationMessage = null; - } - - public void OnGUILayout(EditorWindow window) - { - OnGUI(); - - if (ms_NotificationMessage != null) - window.ShowNotification(ms_NotificationMessage); - else - window.RemoveNotification(); - } - - static void AddLastIPProfiler(List profilers) - { - string lastIP = ProfilerIPWindow.GetLastIPString(); - if (string.IsNullOrEmpty(lastIP)) - return; - - profilers.Add(new ProfilerChoise() - { - Name = lastIP, - Enabled = true, - IsSelected = () => { return ProfilerDriver.connectedProfiler == PLAYER_DIRECT_IP_CONNECT_GUID; }, - ConnectTo = () => { - DirectIPConnect(lastIP); - } - }); - } - - static void AddPlayerProfilers(List profilers) - { - int[] connectionGuids = ProfilerDriver.GetAvailableProfilers(); - for (int index = 0; index < connectionGuids.Length; index++) - { - int guid = connectionGuids[index]; - string name = ProfilerDriver.GetConnectionIdentifier(guid); - bool isProhibited = ProfilerDriver.IsIdentifierOnLocalhost(guid) && (name.Contains("MetroPlayerX") || name.Contains("UWPPlayerX")); - bool enabled = !isProhibited && ProfilerDriver.IsIdentifierConnectable(guid); - - if (!enabled) - { - if (isProhibited) - name += " (Localhost prohibited)"; - else - name += " (Version mismatch)"; - } - - profilers.Add(new ProfilerChoise() - { - Name = name, - Enabled = enabled, - IsSelected = () => { return ProfilerDriver.connectedProfiler == guid; }, - ConnectTo = () => { ProfilerDriver.connectedProfiler = guid; } - }); - } - } - - static void AddDeviceProfilers(List profilers) - { - foreach (var device in DevDeviceList.GetDevices()) - { - bool supportsPlayerConnection = (device.features & DevDeviceFeatures.PlayerConnection) != 0; - if (!device.isConnected || !supportsPlayerConnection) - continue; - - var url = "device://" + device.id; - profilers.Add(new ProfilerChoise() - { - Name = device.name, - Enabled = true, - IsSelected = () => - { - return (ProfilerDriver.connectedProfiler == PLAYER_DIRECT_URL_CONNECT_GUID) - && (ProfilerDriver.directConnectionUrl == url); - }, - ConnectTo = () => { DirectURLConnect(url); } - }); - } - } - - void AddEnterIPProfiler(List profilers, Rect buttonScreenRect) - { - profilers.Add(new ProfilerChoise() - { - Name = kEnterIPText, - Enabled = true, - IsSelected = () => { return false; }, - ConnectTo = () => { ProfilerIPWindow.Show(buttonScreenRect); } - }); - } - - public void OnGUI() - { - var m_CurrentProfiler = EditorGUIUtility.TextContent(GetConnectedProfiler() + "|Specifies the target player for receiving profiler and log data."); - var size = EditorStyles.toolbarDropDown.CalcSize(m_CurrentProfiler); - Rect connectRect = GUILayoutUtility.GetRect(size.x, size.y); - - if (!EditorGUI.DropdownButton(connectRect, m_CurrentProfiler, FocusType.Passive, EditorStyles.toolbarDropDown)) - return; - - var profilers = new List(); - profilers.Clear(); - AddPlayerProfilers(profilers); - AddDeviceProfilers(profilers); - AddLastIPProfiler(profilers); - - // Case 810030: Check if player is connected using AutoConnect Profiler feature via 'connect string in PlayerConnectionConfigFile - // In that case ProfilerDriver.GetAvailableProfilers() won't return the connected player - // But we still want to show that it's connected, because the data is incoming - if (!ProfilerDriver.IsConnectionEditor()) - { - bool anyEnabled = profilers.Any(p => p.IsSelected()); - if (!anyEnabled) - { - profilers.Add(new ProfilerChoise() - { - Name = "(Autoconnected Player)", - Enabled = false, - IsSelected = () => - { - return true; - }, - ConnectTo = () => {} - }); - } - } - - AddEnterIPProfiler(profilers, GUIUtility.GUIToScreenRect(connectRect)); - - OnGUIMenu(connectRect, profilers); - } - - protected virtual void OnGUIMenu(Rect connectRect, List profilers) - { - string[] names = profilers.Select(p => p.Name).ToArray(); - bool[] enabled = profilers.Select(p => p.Enabled).ToArray(); - int[] selected; - int index = profilers.FindIndex(p => p.IsSelected()); - if (index == -1) - selected = new int[0]; - else - selected = new int[] { index }; - - EditorUtility.DisplayCustomMenu(connectRect, names, enabled, selected, SelectProfilerClick, profilers); - } - } - - internal class ProfilerIPWindow : EditorWindow - { - private const string kTextFieldId = "IPWindow"; - private const string kLastIP = "ProfilerLastIP"; - internal string m_IPString; - internal bool didFocus = false; - - public static void Show(Rect buttonScreenRect) - { - Rect rect = new Rect(buttonScreenRect.x, buttonScreenRect.yMax, 300, 50); - ProfilerIPWindow w = EditorWindow.GetWindowWithRect(rect, true, "Enter Player IP"); - w.position = rect; - w.m_Parent.window.m_DontSaveToLayout = true; - } - - void OnEnable() - { - m_IPString = GetLastIPString(); - } - - public static string GetLastIPString() - { - return EditorPrefs.GetString(kLastIP, ""); - } - - void OnGUI() - { - Event evt = Event.current; - bool hitEnter = evt.type == EventType.KeyDown && (evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.KeypadEnter); - GUI.SetNextControlName(kTextFieldId); - - /*Rect contentRect = */ EditorGUILayout.BeginVertical(); - { - GUILayout.Space(5); - m_IPString = EditorGUILayout.TextField(m_IPString); - - - if (!didFocus) - { - didFocus = true; - EditorGUI.FocusTextInControl(kTextFieldId); - } - - GUI.enabled = m_IPString.Length != 0; - if (GUILayout.Button("Connect") || hitEnter) - { - Close(); - // Save ip - EditorPrefs.SetString(kLastIP, m_IPString); - AttachProfilerUI.DirectIPConnect(m_IPString); - GUIUtility.ExitGUI(); - } - } - EditorGUILayout.EndVertical(); - - //position.height = contentRect.height; - } - } -} diff --git a/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs b/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs index 127ff30dbb..9ee077fe9a 100644 --- a/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs +++ b/Modules/ProfilerEditor/ProfilerWindow/ProfilerWindow.cs @@ -14,6 +14,9 @@ using UnityEngine; using UnityEngine.Profiling; using UnityEngine.Scripting; +using UnityEngine.Experimental.Networking.PlayerConnection; +using ConnectionUtility = UnityEditor.Experimental.Networking.PlayerConnection.EditorGUIUtility; +using ConnectionGUILayout = UnityEditor.Experimental.Networking.PlayerConnection.EditorGUILayout; namespace UnityEditor @@ -46,8 +49,10 @@ internal static class Styles public static readonly GUIContent loadProfilingData = EditorGUIUtility.TrTextContent("Load", "Load binary profiling information from a file. Shift click to append to the existing data"); public static readonly string[] loadProfilingDataFileFilters = new string[] { L10n.Tr("Profiler files"), "data,raw", L10n.Tr("All files"), "*" }; - public static readonly GUIContent optionsButtonContent = EditorGUIUtility.TrIconContent("_Popup", "Options"); + public static readonly GUIContent takeSample = EditorGUIUtility.TrTextContent("Take Sample {0}", "Warning: this may freeze the Editor and the connected Player for a moment!"); + public static readonly GUIContent memoryUsageInEditorDisclaimer = EditorGUIUtility.TrTextContent("Memory usage in the Editor is not the same as it would be in a Player."); + public static readonly GUIContent optionsButtonContent = EditorGUIUtility.TrIconContent("_Popup", "Options"); public static readonly GUIContent[] reasons = GetLocalizedReasons(); public static readonly GUIContent accessibilityModeLabel = EditorGUIUtility.TrTextContent("Color Blind Mode"); @@ -102,7 +107,7 @@ static Styles() [SerializeField] private bool m_Recording; - private AttachProfilerUI m_AttachProfilerUI = new AttachProfilerUI(); + private IConnectionState m_AttachProfilerState; private Vector2 m_GraphPos = Vector2.zero; private Vector2[] m_PaneScroll = new Vector2[Profiler.areaCount]; @@ -336,7 +341,6 @@ void OnEnable() InitializeIfNeeded(); titleContent = GetLocalizedTitleContent(); - m_AttachProfilerUI.OnProfilerTargetChanged = ClearFramesCallback; m_ProfilerWindows.Add(this); EditorApplication.playModeStateChanged += OnPlaymodeStateChanged; UserAccessiblitySettings.colorBlindConditionChanged += Initialize; @@ -352,6 +356,8 @@ void InitializeIfNeeded() void Initialize() { + m_AttachProfilerState = ConnectionUtility.GetAttachToPlayerState(this, (player) => ClearFramesCallback()); + int historySize = ProfilerDriver.maxHistoryLength - 1; m_Charts = new ProfilerChart[Profiler.areaCount]; @@ -501,6 +507,8 @@ void CheckForPlatformModuleChange() void OnDisable() { + m_AttachProfilerState.Dispose(); + m_AttachProfilerState = null; m_ProfilerWindows.Remove(this); m_UISystemProfiler.CurrentAreaChanged(null); EditorApplication.playModeStateChanged -= OnPlaymodeStateChanged; @@ -1048,13 +1056,13 @@ private void DrawMemoryToolbar() if (m_ShowDetailedMemoryPane == ProfilerMemoryView.Detailed) { - if (GUILayout.Button("Take Sample: " + m_AttachProfilerUI.GetConnectedProfiler(), EditorStyles.toolbarButton)) + if (GUILayout.Button(GUIContent.Temp(string.Format(Styles.takeSample.text, m_AttachProfilerState.connectionName), Styles.takeSample.tooltip), EditorStyles.toolbarButton)) RefreshMemoryData(); m_GatherObjectReferences = GUILayout.Toggle(m_GatherObjectReferences, Styles.gatherObjectReferences, EditorStyles.toolbarButton); - if (m_AttachProfilerUI.IsEditor()) - GUILayout.Label("Memory usage in editor is not as it would be in a player", EditorStyles.toolbarButton); + if (m_AttachProfilerState.connectedToTarget == ConnectionTarget.Editor) + GUILayout.Label(Styles.memoryUsageInEditorDisclaimer, EditorStyles.toolbarButton); } GUILayout.FlexibleSpace(); @@ -1305,7 +1313,7 @@ private void DrawMainToolbar() SessionState.SetBool(kProfilerEnabledSessionKey, profilerEnabled); } - EditorGUI.BeginDisabledGroup(!m_AttachProfilerUI.IsEditor()); + EditorGUI.BeginDisabledGroup(m_AttachProfilerState.connectedToTarget != ConnectionTarget.Editor); // Deep profiling SetProfileDeepScripts(GUILayout.Toggle(ProfilerDriver.deepProfiling, Styles.deepProfile, EditorStyles.toolbarButton)); @@ -1316,7 +1324,7 @@ private void DrawMainToolbar() EditorGUI.EndDisabledGroup(); // Engine attach - m_AttachProfilerUI.OnGUILayout(this); + ConnectionGUILayout.AttachToPlayerDropdown(m_AttachProfilerState, EditorStyles.toolbarDropDown); // Allocation callstacks AllocationCallstacksToolbarItem(); diff --git a/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs b/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs index b939649ef0..9e91c51399 100644 --- a/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs +++ b/Modules/ShortcutManagerEditor/ShortcutProfileManager.cs @@ -62,6 +62,7 @@ public void ResetToDefault() entry.ResetToDefault(); } m_ActiveProfile.SaveToDisk(); + shortcutsModified?.Invoke(this); } public void ApplyActiveProfile() diff --git a/Modules/TerrainEditor/Brush/Brush.cs b/Modules/TerrainEditor/Brush/Brush.cs index 99c163ed9c..a9e9190bb1 100644 --- a/Modules/TerrainEditor/Brush/Brush.cs +++ b/Modules/TerrainEditor/Brush/Brush.cs @@ -14,7 +14,7 @@ internal class Brush : ScriptableObject public static void CreateNewDefaultBrush() { Brush b = CreateInstance(DefaultMask(), AnimationCurve.Linear(0, 0, 1, 1), 1.0f, false); - ProjectWindowUtil.CreateAsset(b, "Untitled.brush"); + ProjectWindowUtil.CreateAsset(b, "New Brush.brush"); } // Don't instantiate directly, use Brush.CreateInstance() diff --git a/Modules/TerrainEditor/Utilities/TerrainLayerInspector.cs b/Modules/TerrainEditor/Utilities/TerrainLayerInspector.cs index 7c4a536d78..bce38d5b02 100644 --- a/Modules/TerrainEditor/Utilities/TerrainLayerInspector.cs +++ b/Modules/TerrainEditor/Utilities/TerrainLayerInspector.cs @@ -21,7 +21,7 @@ internal class TerrainLayerInspector : Editor public static void CreateNewDefaultTerrainLayer() { TerrainLayer terrainLayer = new TerrainLayer(); - ProjectWindowUtil.CreateAsset(terrainLayer, "Untitled.terrainlayer"); + ProjectWindowUtil.CreateAsset(terrainLayer, "New Terrain Layer.terrainlayer"); } private class Styles diff --git a/Projects/CSharp/UnityEditor.csproj b/Projects/CSharp/UnityEditor.csproj index b48407a248..30561089ab 100644 --- a/Projects/CSharp/UnityEditor.csproj +++ b/Projects/CSharp/UnityEditor.csproj @@ -2676,6 +2676,9 @@ Editor\Mono\Modules\PlatformSupportModule.cs + + Editor\Mono\Networking\PlayerConnection\AttachToPlayerGUI.cs + Editor\Mono\Networking\PlayerConnection\EditorConnection.cs @@ -4293,9 +4296,6 @@ Modules\ProfilerEditor\MemoryProfiler\MemorySnapshotFileWriter.bindings.cs - - Modules\ProfilerEditor\ProfilerWindow\AttachProfilerUI.cs - Modules\ProfilerEditor\ProfilerWindow\AudioProfilerView.cs diff --git a/Projects/CSharp/UnityEngine.csproj b/Projects/CSharp/UnityEngine.csproj index 9c7516da88..768d604806 100644 --- a/Projects/CSharp/UnityEngine.csproj +++ b/Projects/CSharp/UnityEngine.csproj @@ -789,6 +789,9 @@ Runtime\Export\Scripting\APIUpdating\UpdatedFromAttribute.cs + + Runtime\Export\Scripting\AlwaysLinkAssemblyAttribute.cs + Runtime\Export\Scripting\ExtensionOfNativeClassAttribute.cs diff --git a/README.md b/README.md index 13c5a01b11..6ed7fbe2b3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Unity 2018.3.0b11 C# reference source code +## Unity 2018.3.0b12 C# reference source code The C# part of the Unity engine and editor source code. May be used for reference purposes only. diff --git a/Runtime/Export/Networking/PlayerConnection/ConnectionApi.cs b/Runtime/Export/Networking/PlayerConnection/ConnectionApi.cs index 692fb70064..87a33e8998 100644 --- a/Runtime/Export/Networking/PlayerConnection/ConnectionApi.cs +++ b/Runtime/Export/Networking/PlayerConnection/ConnectionApi.cs @@ -5,6 +5,22 @@ using System; using UnityEngine.Events; +namespace UnityEngine.Experimental.Networking.PlayerConnection +{ + public enum ConnectionTarget + { + None, // Only to be used from player side. The editor is always connected to itself, unless connected to a player. + Player, + Editor, + } + + public interface IConnectionState : IDisposable + { + ConnectionTarget connectedToTarget { get; } + string connectionName { get; } + } +} + namespace UnityEngine.Networking.PlayerConnection { [Serializable] diff --git a/Runtime/Export/Scripting/AlwaysLinkAssemblyAttribute.cs b/Runtime/Export/Scripting/AlwaysLinkAssemblyAttribute.cs new file mode 100644 index 0000000000..89864192d2 --- /dev/null +++ b/Runtime/Export/Scripting/AlwaysLinkAssemblyAttribute.cs @@ -0,0 +1,13 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; + +namespace UnityEngine.Scripting +{ + [AttributeUsage(AttributeTargets.Assembly)] + public class AlwaysLinkAssemblyAttribute : Attribute + { + } +} diff --git a/Runtime/Export/UnitySynchronizationContext.cs b/Runtime/Export/UnitySynchronizationContext.cs index deb67e0aec..f239a23404 100644 --- a/Runtime/Export/UnitySynchronizationContext.cs +++ b/Runtime/Export/UnitySynchronizationContext.cs @@ -12,8 +12,20 @@ namespace UnityEngine internal sealed class UnitySynchronizationContext : SynchronizationContext { private const int kAwqInitialCapacity = 20; - private readonly Queue m_AsyncWorkQueue = new Queue(kAwqInitialCapacity); - private readonly int m_MainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId; + private readonly Queue m_AsyncWorkQueue; + private readonly int m_MainThreadID; + + private UnitySynchronizationContext(int mainThreadID) + { + m_AsyncWorkQueue = new Queue(kAwqInitialCapacity); + m_MainThreadID = mainThreadID; + } + + private UnitySynchronizationContext(Queue queue, int mainThreadID) + { + m_AsyncWorkQueue = queue; + m_MainThreadID = mainThreadID; + } // Send will process the call synchronously. If the call is processed on the main thread, we'll invoke it // directly here. If the call is processed on another thread it will be queued up like POST to be executed @@ -46,6 +58,12 @@ public override void Post(SendOrPostCallback callback, object state) } } + // CreateCopy returns a new UnitySynchronizationContext object, but the queue is still shared with the original + public override SynchronizationContext CreateCopy() + { + return new UnitySynchronizationContext(m_AsyncWorkQueue, m_MainThreadID); + } + // Exec will execute tasks off the task list private void Exec() { @@ -66,7 +84,7 @@ private void Exec() private static void InitializeSynchronizationContext() { if (SynchronizationContext.Current == null) - SynchronizationContext.SetSynchronizationContext(new UnitySynchronizationContext()); + SynchronizationContext.SetSynchronizationContext(new UnitySynchronizationContext(System.Threading.Thread.CurrentThread.ManagedThreadId)); } // All requests must be processed on the main thread where the full Unity API is available