diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs index 5bea4058b3..738cf9fe1f 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyDataSource.cs @@ -54,7 +54,7 @@ public override void FetchData() private TreeViewItem AddGameObjectToHierarchy(GameObject gameObject, GameObject rootGameObject, AnimationClip animationClip, TreeViewItem parent) { string path = AnimationUtility.CalculateTransformPath(gameObject.transform, rootGameObject.transform); - TreeViewItem node = new AddCurvesPopupGameObjectNode(gameObject, parent, gameObject.name); + AddCurvesPopupGameObjectNode node = new AddCurvesPopupGameObjectNode(gameObject, parent, gameObject.name); List childNodes = new List(); if (m_RootItem == null) @@ -111,6 +111,20 @@ private TreeViewItem AddGameObjectToHierarchy(GameObject gameObject, GameObject } } + var animator = rootGameObject.GetComponent(); + if (animator != null) + { + //If the Animator has a human avatar, we need to check if the avatar's hierarchy matches that of the current GameObject. If they do not match, disable the node. + if (animator.avatarRoot != null && animator.isHuman) + { + if (animator.avatarRoot.Find(path) == null) + { + node.propertyPathMismatchWithHumanAvatar = true; + } + } + } + + if (showEntireHierarchy) { // Iterate over all child GOs @@ -220,6 +234,7 @@ public void UpdateData() internal class AddCurvesPopupGameObjectNode : TreeViewItem { + internal bool propertyPathMismatchWithHumanAvatar = false; public AddCurvesPopupGameObjectNode(GameObject gameObject, TreeViewItem parent, string displayName) : base(gameObject.GetInstanceID(), parent != null ? parent.depth + 1 : -1, parent, displayName) { diff --git a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs index 939b21cf85..017908c032 100644 --- a/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs +++ b/Editor/Mono/Animation/AnimationWindow/AddCurvesPopupHierarchyGUI.cs @@ -6,6 +6,7 @@ using UnityEditor.IMGUI.Controls; using UnityEngine; using System.Collections.Generic; +using UnityEditor.ShortcutManagement; namespace UnityEditorInternal { @@ -18,17 +19,38 @@ internal class AddCurvesPopupHierarchyGUI : TreeViewGUI private GUIContent addPropertiesContent = EditorGUIUtility.TrTextContent("Add Properties"); private const float plusButtonWidth = 17; + static Texture2D warningIcon = (Texture2D)EditorGUIUtility.LoadRequired("Icons/ShortcutManager/alertDialog.png"); + public static GUIStyle warningIconStyle; + public AddCurvesPopupHierarchyGUI(TreeViewController treeView, EditorWindow owner) : base(treeView, true) { this.owner = owner; + warningIconStyle = new GUIStyle(); + warningIconStyle.margin = new RectOffset(15, 15, 15, 15); } 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); + bool propertyPathMismatchWithHumanAvatar = false; + AddCurvesPopupGameObjectNode addCurvesPopupNode = node as AddCurvesPopupGameObjectNode; + if (addCurvesPopupNode != null) + { + propertyPathMismatchWithHumanAvatar = addCurvesPopupNode.propertyPathMismatchWithHumanAvatar; + } + + using (new EditorGUI.DisabledScope(propertyPathMismatchWithHumanAvatar)) + { + base.OnRowGUI(rowRect, node, row, selected, focused); + DoAddCurveButton(rowRect, node); + HandleContextMenu(rowRect, node); + } + + if (propertyPathMismatchWithHumanAvatar) + { + Rect iconRect = new Rect(rowRect.width - plusButtonWidth, rowRect.yMin, plusButtonWidth, plusButtonStyle.fixedHeight); + GUI.Label(iconRect, new GUIContent(warningIcon, "The Avatar definition does not match the property path. Please author using a hierarchy the Avatar was built with."), warningIconStyle); + } } private void DoAddCurveButton(Rect rowRect, TreeViewItem node) diff --git a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs index e5e27f7ca1..3a66eeb2fa 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs @@ -115,7 +115,7 @@ public FrameRateMenuEntry(GUIContent content, float value) public GUIContent content; public float value; - }; + } internal static FrameRateMenuEntry[] kAvailableFrameRates = new FrameRateMenuEntry[] { diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs b/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs index cf52ac9a3e..697f03d428 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationRecording.cs @@ -31,7 +31,6 @@ static bool HasAnyRecordableModifications(GameObject root, UndoPropertyModificat static private UndoPropertyModification[] FilterModifications(IAnimationRecordingState state, ref UndoPropertyModification[] modifications) { - AnimationClip clip = state.activeAnimationClip; GameObject rootGameObject = state.activeRootGameObject; List discardedModifications = new List(); @@ -163,7 +162,6 @@ static private void DiscardRotationModification(RotationModification rotationMod static private UndoPropertyModification[] FilterRotationModifications(IAnimationRecordingState state, ref Dictionary rotationModifications) { - AnimationClip clip = state.activeAnimationClip; GameObject rootGameObject = state.activeRootGameObject; List itemsToRemove = new List(); @@ -213,9 +211,6 @@ static private void AddRotationPropertyModification(IAnimationRecordingState sta static private void ProcessRotationModifications(IAnimationRecordingState state, ref Dictionary rotationModifications) { - AnimationClip clip = state.activeAnimationClip; - GameObject root = state.activeRootGameObject; - foreach (KeyValuePair item in rotationModifications) { RotationModification m = item.Value; @@ -387,9 +382,6 @@ static private void ProcessVector3Modification(IAnimationRecordingState state, E static public void ProcessVector3Modifications(IAnimationRecordingState state, ref Dictionary vector3Modifications) { - AnimationClip clip = state.activeAnimationClip; - GameObject root = state.activeRootGameObject; - foreach (KeyValuePair item in vector3Modifications) { Vector3Modification m = item.Value; @@ -411,7 +403,6 @@ static public void ProcessVector3Modifications(IAnimationRecordingState state, r static public void ProcessModifications(IAnimationRecordingState state, UndoPropertyModification[] modifications) { - AnimationClip clip = state.activeAnimationClip; GameObject root = state.activeRootGameObject; // Record modified properties @@ -500,7 +491,6 @@ static bool ValueFromPropertyModification(PropertyModification modification, Edi static void AddKey(IAnimationRecordingState state, EditorCurveBinding binding, Type type, object previousValue, object currentValue) { - GameObject root = state.activeRootGameObject; AnimationClip clip = state.activeAnimationClip; if ((clip.hideFlags & HideFlags.NotEditable) != 0) @@ -573,7 +563,6 @@ internal class RootMotionModification static private void ProcessRootMotionModifications(IAnimationRecordingState state, ref Dictionary rootMotionModifications) { - AnimationClip clip = state.activeAnimationClip; GameObject root = state.activeRootGameObject; Animator animator = root.GetComponent(); diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs index 50bdf86e29..3eaa5e954c 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowControl.cs @@ -58,7 +58,7 @@ enum RecordingStateMode { ManualKey, AutoKey - }; + } class RecordingState : IAnimationRecordingState { @@ -105,7 +105,7 @@ enum ResampleFlags FlushUndos = 1 << 2, Default = RefreshViews | FlushUndos - }; + } private static bool HasFlag(ResampleFlags flags, ResampleFlags flag) { diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs index 5f7c34ba1a..0884c194bb 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowEventInspector.cs @@ -379,10 +379,7 @@ private static int EnumPopup(string label, Type enumType, int selected) private static bool IsSupportedMethodName(string name) { - if (name == "Main" || name == "Start" || name == "Awake" || name == "Update") - return false; - - return true; + return name != "Main" && name != "Start" && name != "Awake" && name != "Update"; } private static string FormatEventArguments(IEnumerable paramTypes, AnimationEvent evt) diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs index 51e1600845..820a11e84c 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyDataSource.cs @@ -67,10 +67,7 @@ public override bool IsRenamingItemAllowed(TreeViewItem item) if (item is AnimationWindowHierarchyAddButtonNode || item is AnimationWindowHierarchyMasterNode || item is AnimationWindowHierarchyClipNode) return false; - if ((item as AnimationWindowHierarchyNode).path.Length == 0) - return false; - - return true; + return (item as AnimationWindowHierarchyNode).path.Length != 0; } public List CreateTreeFromCurves() diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs index 9371b950c0..8ff30aa81b 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs @@ -822,14 +822,6 @@ override public bool BeginRename(TreeViewItem item, float delay) { m_RenamedNode = item as AnimationWindowHierarchyNode; - GameObject rootGameObject = null; - if (m_RenamedNode.curves.Length > 0) - { - AnimationWindowSelectionItem selectionBinding = m_RenamedNode.curves[0].selectionBinding; - if (selectionBinding != null) - rootGameObject = selectionBinding.rootGameObject; - } - return GetRenameOverlay().BeginRename(m_RenamedNode.path, item.id, delay); } diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs index 76fc50980b..f3b0ef7f87 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowManipulator.cs @@ -124,7 +124,7 @@ public enum Alignment Center, Left, Right - }; + } public Alignment alignment; public Color headColor; diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs index f99df8e428..86b5fc8961 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs @@ -23,14 +23,14 @@ public enum RefreshType None = 0, CurvesOnly = 1, Everything = 2 - }; + } public enum SnapMode { Disabled = 0, SnapToFrame = 1, SnapToClipFrame = 2 - }; + } [SerializeField] public AnimationWindowHierarchyState hierarchyState; // Persistent state of treeview on the left side of window [SerializeField] public AnimEditor animEditor; // Reference to owner of this state. Used to trigger repaints. @@ -1204,7 +1204,7 @@ public void PasteKeys() clipboardCurves.Add(keyframe.curve); // If we have equal number of target and source curves, then match by index. If not, then try to match with AnimationWindowUtility.BestMatchForPaste. - bool matchCurveByIndex = clipboardCurves.Count() == activeCurves.Count(); + bool matchCurveByIndex = clipboardCurves.Count == activeCurves.Count; int targetIndex = 0; foreach (AnimationWindowKeyframe keyframe in s_KeyframeClipboard) @@ -1737,7 +1737,7 @@ public Vector2 timeRange public string FormatFrame(int frame, int frameDigits) { - return (frame / (int)frameRate).ToString() + ":" + (frame % frameRate).ToString().PadLeft(frameDigits, '0'); + return (frame / (int)frameRate) + ":" + (frame % frameRate).ToString().PadLeft(frameDigits, '0'); } //@TODO: Remove. Replace with animationkeytime diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs index 64a1704e92..e3caef7f2c 100644 --- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs +++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs @@ -13,7 +13,6 @@ using Object = UnityEngine.Object; using TangentMode = UnityEditor.AnimationUtility.TangentMode; -using CurveModifiedType = UnityEditor.AnimationUtility.CurveModifiedType; namespace UnityEditorInternal { @@ -849,7 +848,7 @@ public static float GetNextKeyframeTime(AnimationWindowCurve[] curves, float cur public static float GetPreviousKeyframeTime(AnimationWindowCurve[] curves, float currentTime, float frameRate) { - float candidate = float.MinValue; + AnimationKeyTime candidateKeyTime = AnimationKeyTime.Time(float.MinValue, frameRate); AnimationKeyTime time = AnimationKeyTime.Time(currentTime, frameRate); AnimationKeyTime previousTime = AnimationKeyTime.Frame(time.frame - 1, frameRate); @@ -859,14 +858,19 @@ public static float GetPreviousKeyframeTime(AnimationWindowCurve[] curves, float { foreach (AnimationWindowKeyframe keyframe in curve.m_Keyframes) { - if (keyframe.time > candidate && keyframe.time <= previousTime.time) + AnimationKeyTime keyTime = AnimationKeyTime.Time(keyframe.time, frameRate); + if (keyTime.frame >= candidateKeyTime.frame && keyTime.frame <= previousTime.frame) { - candidate = keyframe.time; - found = true; + if (keyTime.time >= candidateKeyTime.time) + { + candidateKeyTime = keyTime; + found = true; + } } } } - return found ? candidate : time.time; + + return found ? candidateKeyTime.time : time.time; } // Add animator, controller and clip to gameobject if they are missing to make this gameobject animatable @@ -1045,7 +1049,7 @@ internal static AnimationClip AllocateAndSetupClip(bool useAnimator) public static int GetPropertyNodeID(int setId, string path, System.Type type, string propertyName) { - return (setId.ToString() + path + type.Name + propertyName).GetHashCode(); + return (setId + path + type.Name + propertyName).GetHashCode(); } // What is the first animation player component (Animator or Animation) when recursing parent tree toward root diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs index f93cca8339..bcfa786fa6 100644 --- a/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs +++ b/Editor/Mono/Animation/AnimationWindow/CurveEditor.cs @@ -3861,7 +3861,7 @@ private void SetAxisUiScalars(Vector2 newScalars, List curvesInSam } } - internal enum PickMode { None, Click, Marquee }; + internal enum PickMode { None, Click, Marquee } public void GridGUI() { diff --git a/Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs b/Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs index 0934007f51..2fe260e392 100644 --- a/Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs +++ b/Editor/Mono/Animation/AnimationWindow/Deprecated/AnimationEventTimeline.cs @@ -353,7 +353,7 @@ public void EventLineGUI(Rect rect, AnimationWindowState state) public void DrawInstantTooltip(Rect position) { - if (m_InstantTooltipText != null && m_InstantTooltipText != "") + if (!string.IsNullOrEmpty(m_InstantTooltipText)) { // Draw body of tooltip GUIStyle style = (GUIStyle)"AnimationEventTooltip"; diff --git a/Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs b/Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs index a6e2691b3f..a4cb8204e0 100644 --- a/Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs +++ b/Editor/Mono/Animation/AnimationWindow/Deprecated/EditorGUIExt.cs @@ -47,8 +47,7 @@ static bool DoRepeatButton(Rect position, GUIContent content, GUIStyle style, Fo } return false; case EventType.Repaint: - style.Draw(position, content, id); - // Handles.Repaint (); + style.Draw(position, content, id, false, position.Contains(Event.current.mousePosition)); return id == GUIUtility.hotControl && position.Contains(Event.current.mousePosition); } return false; @@ -133,17 +132,13 @@ public static void MinMaxScroller(Rect position, int id, ref float value, ref fl MinMaxSlider(sliderRect, ref value, ref size, newVisualStart, newVisualEnd, newVisualStart, newVisualEnd, slider, thumb, horiz); - bool wasMouseUpEvent = false; - if (Event.current.type == EventType.MouseUp) - wasMouseUpEvent = true; - if (ScrollerRepeatButton(id, minRect, leftButton)) value -= scrollStepSize * (visualStart < visualEnd ? 1f : -1f); if (ScrollerRepeatButton(id, maxRect, rightButton)) value += scrollStepSize * (visualStart < visualEnd ? 1f : -1f); - if (wasMouseUpEvent && Event.current.type == EventType.Used) // repeat buttons ate mouse up event - release scrolling + if (Event.current.type == EventType.MouseUp && Event.current.type == EventType.Used) // repeat buttons ate mouse up event - release scrolling scrollControlID = 0; if (startLimit < endLimit) diff --git a/Editor/Mono/Animation/StateMachine.cs b/Editor/Mono/Animation/StateMachine.cs index 7fadf37c91..6fbe2217fd 100644 --- a/Editor/Mono/Animation/StateMachine.cs +++ b/Editor/Mono/Animation/StateMachine.cs @@ -55,7 +55,7 @@ public void DoUndo(Object target, string undoOperation) } public bool m_PushUndo; - }; + } } diff --git a/Editor/Mono/Animation/TimeArea.cs b/Editor/Mono/Animation/TimeArea.cs index cec8607005..cb163f861a 100644 --- a/Editor/Mono/Animation/TimeArea.cs +++ b/Editor/Mono/Animation/TimeArea.cs @@ -44,7 +44,7 @@ public enum TimeFormat None, // Unformatted time TimeFrame, // Time:Frame Frame // Integer frame - }; + } class Styles2 { @@ -501,7 +501,7 @@ public string FormatTime(float time, float frameRate, TimeFormat timeFormat) sign = "-"; frame = -frame; } - return sign + (frame / (int)frameRate).ToString() + ":" + + return sign + (frame / (int)frameRate) + ":" + (frame % frameRate).ToString().PadLeft(frameDigits, '0'); } else diff --git a/Editor/Mono/Animation/TransitionPreview.cs b/Editor/Mono/Animation/TransitionPreview.cs index b9287ecdb1..da4a2629d2 100644 --- a/Editor/Mono/Animation/TransitionPreview.cs +++ b/Editor/Mono/Animation/TransitionPreview.cs @@ -112,7 +112,7 @@ public void Set(AnimatorStateTransition transition, AnimatorState srcState, Anim Init(); } } - }; + } private void CopyStateForPreview(AnimatorState src, ref AnimatorState dst) @@ -557,11 +557,7 @@ private void ControllerDirty() private void DisableIKOnFeetIfNeeded() { - bool disable = false; - if (m_SrcMotion == null || m_DstMotion == null) - { - disable = true; - } + bool disable = m_SrcMotion == null || m_DstMotion == null; if (m_LayerIndex > 0) { diff --git a/Editor/Mono/Animation/ZoomableArea.cs b/Editor/Mono/Animation/ZoomableArea.cs index 3c1858328a..d653c63abc 100644 --- a/Editor/Mono/Animation/ZoomableArea.cs +++ b/Editor/Mono/Animation/ZoomableArea.cs @@ -258,12 +258,12 @@ public Styles(bool minimalGUI) if (minimalGUI) { visualSliderWidth = 0; - sliderWidth = 12; + sliderWidth = 13; } else { - visualSliderWidth = 12; - sliderWidth = 12; + visualSliderWidth = 13; + sliderWidth = 13; } } diff --git a/Editor/Mono/Annotation/AnnotationWindow.cs b/Editor/Mono/Annotation/AnnotationWindow.cs index 8514315499..1ab66a2a7f 100644 --- a/Editor/Mono/Annotation/AnnotationWindow.cs +++ b/Editor/Mono/Annotation/AnnotationWindow.cs @@ -50,7 +50,7 @@ private enum EnabledState None = 0, All = 1, Mixed = 2 - }; + } const float kWindowWidth = 270; const float scrollBarWidth = 14; @@ -78,7 +78,6 @@ private enum EnabledState readonly string textGizmoVisible = L10n.Tr("Show/Hide Gizmo"); GUIContent iconToggleContent = EditorGUIUtility.TrTextContent("", "Show/Hide Icon"); GUIContent iconSelectContent = EditorGUIUtility.TrTextContent("", "Select Icon"); - GUIContent icon3dGizmoContent = EditorGUIUtility.TrTextContent("3D Icons"); GUIContent showOutlineContent = EditorGUIUtility.TrTextContent("Selection Outline"); GUIContent showWireframeContent = EditorGUIUtility.TrTextContent("Selection Wire"); @@ -257,8 +256,8 @@ private void SyncToState() if (s_Debug) debuginfo += " same as below: icon " + a[i].iconEnabled + " gizmo " + a[i].gizmoEnabled + "\n"; - bool ge = (a[i].gizmoEnabled == 1) ? true : false; - bool ie = (a[i].iconEnabled == 1) ? true : false; + bool ge = (a[i].gizmoEnabled == 1); + bool ie = (a[i].iconEnabled == 1); AInfo anno = new AInfo(ge, ie, a[i].flags, a[i].classID, a[i].scriptClass); if (anno.m_ScriptClass == "") @@ -601,21 +600,24 @@ void DrawListElement(Rect rect, bool even, AInfo ainfo) GUI.DrawTexture(div, EditorGUIUtility.whiteTexture, ScaleMode.StretchToFill); GUI.color = Color.white; - Rect arrowRect = iconRect; - arrowRect.x += 18; - arrowRect.y += 0; - arrowRect.width = 9; - - if (GUI.Button(arrowRect, iconSelectContent, m_Styles.iconDropDown)) + if (!ainfo.IsDisabled()) { - Object script = EditorGUIUtility.GetScript(ainfo.m_ScriptClass); - if (script != null) + Rect arrowRect = iconRect; + arrowRect.x += 18; + arrowRect.y += 0; + arrowRect.width = 9; + + if (GUI.Button(arrowRect, iconSelectContent, m_Styles.iconDropDown)) { - m_LastScriptThatHasShownTheIconSelector = ainfo.m_ScriptClass; - if (IconSelector.ShowAtPosition(script, arrowRect, true)) + Object script = EditorGUIUtility.GetScript(ainfo.m_ScriptClass); + if (script != null) { - IconSelector.SetMonoScriptIconChangedCallback(MonoScriptIconChanged); - GUIUtility.ExitGUI(); + m_LastScriptThatHasShownTheIconSelector = ainfo.m_ScriptClass; + if (IconSelector.ShowAtPosition(script, arrowRect, true)) + { + IconSelector.SetMonoScriptIconChangedCallback(MonoScriptIconChanged); + GUIUtility.ExitGUI(); + } } } } @@ -688,7 +690,7 @@ void SetGizmoState(AInfo ainfo, bool addToMostRecentChanged = true) internal class AInfo : System.IComparable, System.IEquatable { // Similar values as in Annotation (in AnnotationManager.h) - public enum Flags { kHasIcon = 1, kHasGizmo = 2 }; + public enum Flags { kHasIcon = 1, kHasGizmo = 2, kIsDisabled = 4 } public AInfo(bool gizmoEnabled, bool iconEnabled, int flags, int classID, string scriptClass) { @@ -720,6 +722,11 @@ public bool HasIcon() return (m_Flags & (int)Flags.kHasIcon) > 0; } + public bool IsDisabled() + { + return (m_Flags & (int)Flags.kIsDisabled) > 0; + } + public int CompareTo(object obj) { AInfo other = obj as AInfo; diff --git a/Editor/Mono/Annotation/SceneViewCameraWindow.cs b/Editor/Mono/Annotation/SceneViewCameraWindow.cs index 72f1f9dab4..0af109f061 100644 --- a/Editor/Mono/Annotation/SceneViewCameraWindow.cs +++ b/Editor/Mono/Annotation/SceneViewCameraWindow.cs @@ -2,11 +2,13 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License +using System; +using System.Linq; using UnityEngine; namespace UnityEditor { - class SceneViewCameraWindow : PopupWindowContent + public class SceneViewCameraWindow : PopupWindowContent { static class Styles { @@ -22,7 +24,7 @@ public static void Init() settingsArea = new GUIStyle() { - padding = new RectOffset(4, 4, 4, 4), + border = new RectOffset(4, 4, 4, 4), }; } } @@ -31,8 +33,7 @@ public static void Init() GUIContent m_CameraSpeedSliderContent; GUIContent m_AccelerationEnabled; - GUIContent m_CameraSpeedMin; - GUIContent m_CameraSpeedMax; + GUIContent[] m_MinMaxContent; GUIContent m_FieldOfView; GUIContent m_DynamicClip; GUIContent m_OcclusionCulling; @@ -40,34 +41,41 @@ public static void Init() const int kFieldCount = 12; const int kWindowWidth = 290; - const int kWindowHeight = ((int)EditorGUI.kSingleLineHeight) * kFieldCount + kFrameWidth * 2; - const int kFrameWidth = 11; + const int kContentPadding = 4; + const int kWindowHeight = ((int)EditorGUI.kSingleLineHeight) * kFieldCount + kContentPadding * 2; const float kPrefixLabelWidth = 120f; - const float kMinSpeedLabelWidth = 25f; - const float kMaxSpeedLabelWidth = 29f; - const float kMinMaxSpeedFieldWidth = 50f; - const float kMinMaxSpeedSpace = 8f; const float kNearClipMin = .01f; + const int k_HeaderSpacing = 2; + Vector2 m_WindowSize; + Vector2 m_Scroll; float[] m_Vector2Floats = { 0, 0 }; + public static event Action additionalSettingsGui; + public override Vector2 GetWindowSize() { - return new Vector2(kWindowWidth, kWindowHeight); + return m_WindowSize; } + SceneViewCameraWindow() {} + public SceneViewCameraWindow(SceneView sceneView) { m_SceneView = sceneView; m_CameraSpeedSliderContent = EditorGUIUtility.TrTextContent("Camera Speed", "The current speed of the camera in the Scene view."); m_AccelerationEnabled = EditorGUIUtility.TrTextContent("Camera Acceleration", "Check this to enable acceleration when moving the camera. When enabled, camera speed is evaluated as a modifier. With acceleration disabled, the camera is accelerated to the Camera Speed."); - m_CameraSpeedMin = EditorGUIUtility.TrTextContent("Min", "The minimum speed of the camera in the Scene view. Valid values are between [0.01, 98]."); - m_CameraSpeedMax = EditorGUIUtility.TrTextContent("Max", "The maximum speed of the camera in the Scene view. Valid values are between [0.02, 99]."); m_FieldOfView = EditorGUIUtility.TrTextContent("Field of View", "The height of the camera's view angle. Measured in degrees vertically, or along the local Y axis."); m_DynamicClip = EditorGUIUtility.TrTextContent("Dynamic Clipping", "Check this to enable camera's near and far clipping planes to be calculated relative to the viewport size of the Scene."); m_OcclusionCulling = EditorGUIUtility.TrTextContent("Occlusion Culling", "Check this to enable occlusion culling in the Scene view. Occlusion culling disables rendering of objects when they\'re not currently seen by the camera because they\'re hidden (occluded) by other objects."); m_EasingEnabled = EditorGUIUtility.TrTextContent("Camera Easing", "Check this to enable camera movement easing. This makes the camera ease in when it starts moving and ease out when it stops."); + m_WindowSize = new Vector2(kWindowWidth, kWindowHeight); + m_MinMaxContent = new GUIContent[] + { + EditorGUIUtility.TrTextContent("Min", "The minimum speed of the camera in the Scene view. Valid values are between [0.001, 98]."), + EditorGUIUtility.TrTextContent("Max", "The maximum speed of the camera in the Scene view. Valid values are between [0.002, 99].") + }; } public override void OnGUI(Rect rect) @@ -85,26 +93,27 @@ public override void OnGUI(Rect rect) } } - private void Draw(Rect rect) + void Draw(Rect rect) { - var settings = m_SceneView.cameraSettings; Styles.Init(); - const int k_SettingsIconPad = 2; - Vector2 settingsSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.titleSettingsIcon); - Rect settingsRect = new Rect(rect.xMax - Styles.settingsArea.padding.right - k_SettingsIconPad - settingsSize.x, Styles.settingsArea.padding.top + k_SettingsIconPad, settingsSize.x, settingsSize.y); - - if (GUI.Button(settingsRect, EditorGUI.GUIContents.titleSettingsIcon, EditorStyles.iconButton)) - ShowContextMenu(); + var settings = m_SceneView.cameraSettings; - GUILayout.BeginArea(rect, Styles.settingsArea); + m_Scroll = GUILayout.BeginScrollView(m_Scroll); + GUILayout.BeginVertical(Styles.settingsArea); EditorGUI.BeginChangeCheck(); - var sceneCameraContent = EditorGUIUtility.TrTextContent("Scene Camera"); - EditorGUIUtility.labelWidth = Mathf.Max(kPrefixLabelWidth, EditorGUI.CalcPrefixLabelWidth(sceneCameraContent, EditorStyles.boldLabel)); + GUILayout.Space(k_HeaderSpacing); - GUILayout.Label(sceneCameraContent, EditorStyles.boldLabel); + GUILayout.BeginHorizontal(); + GUILayout.Label(EditorGUIUtility.TrTextContent("Scene Camera"), EditorStyles.boldLabel); + GUILayout.FlexibleSpace(); + if (GUILayout.Button(EditorGUI.GUIContents.titleSettingsIcon, EditorStyles.iconButton)) + ShowContextMenu(); + GUILayout.EndHorizontal(); + + EditorGUIUtility.labelWidth = kPrefixLabelWidth; // fov isn't applicable in orthographic mode, and orthographic size is controlled by the user zoom using (new EditorGUI.DisabledScope(m_SceneView.orthographic)) @@ -130,13 +139,18 @@ private void Draw(Rect rect) if (EditorGUI.EndChangeCheck()) m_SceneView.Repaint(); + EditorGUILayout.Space(k_HeaderSpacing); + GUILayout.Label(EditorGUIUtility.TrTextContent("Navigation"), EditorStyles.boldLabel); settings.easingEnabled = EditorGUILayout.Toggle(m_EasingEnabled, settings.easingEnabled); - settings.accelerationEnabled = EditorGUILayout.Toggle(m_AccelerationEnabled, settings.accelerationEnabled); - settings.speed = EditorGUILayout.Slider(m_CameraSpeedSliderContent, settings.speed, settings.speedMin, settings.speedMax); + EditorGUI.BeginChangeCheck(); + float min = settings.speedMin, max = settings.speedMax, speed = settings.RoundSpeedToNearestSignificantDecimal(settings.speed); + speed = EditorGUILayout.Slider(m_CameraSpeedSliderContent, speed, min, max); + if (EditorGUI.EndChangeCheck()) + settings.speed = settings.RoundSpeedToNearestSignificantDecimal(speed); EditorGUI.BeginChangeCheck(); @@ -150,7 +164,17 @@ private void Draw(Rect rect) EditorGUIUtility.labelWidth = 0f; - GUILayout.EndArea(); + if (additionalSettingsGui != null) + { + EditorGUILayout.Space(k_HeaderSpacing); + additionalSettingsGui(m_SceneView); + } + + if (Event.current.type == EventType.Repaint) + m_WindowSize.y = Math.Min(GUILayoutUtility.GetLastRect().yMax + kContentPadding, kWindowHeight * 3); + + GUILayout.BeginVertical(Styles.settingsArea); + GUILayout.EndScrollView(); } void DrawSpeedMinMaxFields() @@ -158,13 +182,7 @@ void DrawSpeedMinMaxFields() GUILayout.BeginHorizontal(); GUILayout.Space(EditorGUIUtility.labelWidth); Rect r = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight, EditorStyles.numberField); - r.width = kMinSpeedLabelWidth + kMinMaxSpeedFieldWidth; - EditorGUIUtility.labelWidth = kMinSpeedLabelWidth; - m_Vector2Floats[0] = EditorGUI.FloatField(r, m_CameraSpeedMin, m_Vector2Floats[0]); - r.x += r.width + kMinMaxSpeedSpace; - r.width = kMaxSpeedLabelWidth + kMinMaxSpeedFieldWidth; - EditorGUIUtility.labelWidth = kMaxSpeedLabelWidth; - m_Vector2Floats[1] = EditorGUI.FloatField(r, m_CameraSpeedMax, m_Vector2Floats[1]); + EditorGUI.MultiFloatField(r, m_MinMaxContent, m_Vector2Floats); GUILayout.EndHorizontal(); } diff --git a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs index 84e07ca1de..c5d24562b6 100644 --- a/Editor/Mono/AssemblyInfo/AssemblyInfo.cs +++ b/Editor/Mono/AssemblyInfo/AssemblyInfo.cs @@ -9,6 +9,7 @@ [assembly: InternalsVisibleTo("Unity.LiveNotes")] [assembly: InternalsVisibleTo("Unity.Burst")] [assembly: InternalsVisibleTo("Unity.Burst.Editor")] +[assembly: InternalsVisibleTo("Unity.Cloud.Collaborate.Editor")] [assembly: InternalsVisibleTo("Unity.CollabProxy.Editor")] [assembly: InternalsVisibleTo("Unity.CollabProxy.EditorTests")] [assembly: InternalsVisibleTo("Unity.CollabProxy.UI")] diff --git a/Editor/Mono/AssetDatabase/AssetDatabase.cs b/Editor/Mono/AssetDatabase/AssetDatabase.cs index 712d81c13c..e26d48c55f 100644 --- a/Editor/Mono/AssetDatabase/AssetDatabase.cs +++ b/Editor/Mono/AssetDatabase/AssetDatabase.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using UnityEngine.Scripting; +using uei = UnityEngine.Internal; namespace UnityEditor { @@ -56,7 +57,7 @@ private static void Internal_CallImportPackageFailed(string packageName, string importPackageFailed(packageName, errorMessage); } - public static void IsOpenForEdit(string[] assetOrMetaFilePaths, List outNotEditablePaths, StatusQueryOptions statusQueryOptions = StatusQueryOptions.UseCachedIfPossible) + public static void IsOpenForEdit(string[] assetOrMetaFilePaths, List outNotEditablePaths, [uei.DefaultValue("StatusQueryOptions.UseCachedIfPossible")] StatusQueryOptions statusQueryOptions = StatusQueryOptions.UseCachedIfPossible) { if (assetOrMetaFilePaths == null) throw new ArgumentNullException(nameof(assetOrMetaFilePaths)); diff --git a/Editor/Mono/AssetDatabase/AssetPreview.bindings.cs b/Editor/Mono/AssetDatabase/AssetPreview.bindings.cs index 44d04e28d4..4cca1c5fc8 100644 --- a/Editor/Mono/AssetDatabase/AssetPreview.bindings.cs +++ b/Editor/Mono/AssetDatabase/AssetPreview.bindings.cs @@ -33,6 +33,14 @@ internal static Texture2D GetAssetPreview(int instanceID) [FreeFunction("AssetPreviewBindings::HasAssetPreview")] internal static extern bool HasAssetPreview(int instanceID, int clientID); + internal static Texture2D GetAssetPreviewFromGUID(string guid) + { + return GetAssetPreviewFromGUID(guid, kSharedClientID); + } + + [FreeFunction("AssetPreviewBindings::GetAssetPreviewFromGUID")] + internal static extern Texture2D GetAssetPreviewFromGUID(string guid, int clientID); + public static bool IsLoadingAssetPreview(int instanceID) { return IsLoadingAssetPreview(instanceID, kSharedClientID); diff --git a/Editor/Mono/AssetModificationProcessor.cs b/Editor/Mono/AssetModificationProcessor.cs index ec42dbf5d3..ce9668cc87 100644 --- a/Editor/Mono/AssetModificationProcessor.cs +++ b/Editor/Mono/AssetModificationProcessor.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using UnityEngine; using UnityEditor.VersionControl; using UnityEditorInternal; @@ -11,8 +12,17 @@ using System.Linq; using System.Reflection; +[Obsolete("Use UnityEditor.AssetModificationProcessor")] +public class AssetModificationProcessor +{ +} + namespace UnityEditor { + public class AssetModificationProcessor + { + } + internal class AssetModificationProcessorInternal { enum FileMode @@ -27,7 +37,7 @@ static bool CheckArgumentTypes(Type[] types, MethodInfo method) if (types.Length != parameters.Length) { - Debug.LogWarning("Parameter count did not match. Expected: " + types.Length.ToString() + " Got: " + parameters.Length.ToString() + " in " + method.DeclaringType.ToString() + "." + method.Name); + Debug.LogWarning("Parameter count did not match. Expected: " + types.Length + " Got: " + parameters.Length + " in " + method.DeclaringType + "." + method.Name); return false; } @@ -37,7 +47,7 @@ static bool CheckArgumentTypes(Type[] types, MethodInfo method) ParameterInfo pInfo = parameters[i]; if (type != pInfo.ParameterType) { - Debug.LogWarning("Parameter type mismatch at parameter " + i + ". Expected: " + type.ToString() + " Got: " + pInfo.ParameterType.ToString() + " in " + method.DeclaringType.ToString() + "." + method.Name); + Debug.LogWarning("Parameter type mismatch at parameter " + i + ". Expected: " + type + " Got: " + pInfo.ParameterType + " in " + method.DeclaringType + "." + method.Name); return false; } ++i; @@ -50,7 +60,7 @@ static bool CheckArgumentTypesAndReturnType(Type[] types, MethodInfo method, Sys { if (returnType != method.ReturnType) { - Debug.LogWarning("Return type mismatch. Expected: " + returnType.ToString() + " Got: " + method.ReturnType.ToString() + " in " + method.DeclaringType.ToString() + "." + method.Name); + Debug.LogWarning("Return type mismatch. Expected: " + returnType + " Got: " + method.ReturnType + " in " + method.DeclaringType + "." + method.Name); return false; } @@ -274,11 +284,26 @@ static MethodInfo[] GetIsOpenForEditMethods() return isOpenForEditMethods; } - static bool IsAssetInReadOnlyFolder(string assetPath) + enum Editability { + Never, + Always, + Maybe + } + + static Editability GetPathEditability(string assetPath) + { + // read-only asset locations (e.g. shared packages) are considered not editable bool rootFolder, readOnly; bool validPath = AssetDatabase.GetAssetFolderInfo(assetPath, out rootFolder, out readOnly); - return validPath && readOnly; + if (validPath && readOnly) + return Editability.Never; + + // other paths that are not know to asset database, and not versioned, are considered always editable + if (!Provider.PathIsVersioned(assetPath)) + return Editability.Always; + + return Editability.Maybe; } static bool IsOpenForEditViaScriptCallbacks(string assetPath, ref string message) @@ -301,7 +326,10 @@ internal static bool IsOpenForEdit(string assetPath, out string message, StatusQ if (string.IsNullOrEmpty(assetPath)) return true; // treat empty/null paths as editable (might be under Library folders etc.) - if (IsAssetInReadOnlyFolder(assetPath)) + var editability = GetPathEditability(assetPath); + if (editability == Editability.Always) + return true; + if (editability == Editability.Never) return false; if (!AssetModificationHook.IsOpenForEdit(assetPath, out message, statusOptions)) return false; @@ -322,7 +350,10 @@ internal static void IsOpenForEdit(string[] assetOrMetaFilePaths, List o { if (string.IsNullOrEmpty(path)) continue; // treat empty/null paths as editable (might be under Library folders etc.) - if (IsAssetInReadOnlyFolder(path)) + var editability = GetPathEditability(path); + if (editability == Editability.Always) + continue; + if (editability == Editability.Never) { outNotEditablePaths.Add(path); continue; diff --git a/Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs b/Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs index 96d819c81a..cd013b7b80 100644 --- a/Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs +++ b/Editor/Mono/AssetPipeline/AssetImportContext.bindings.cs @@ -30,6 +30,8 @@ public class AssetImportContext AssetImportContext() {} public extern string assetPath { get; internal set; } + public extern string GetResultPath(string extension); + public extern BuildTarget selectedBuildTarget { get; } extern void LogMessage(string msg, string file, int line, UnityEngine.Object obj, bool isAnError); diff --git a/Editor/Mono/AssetPipeline/MaterialDescription.bindings.cs b/Editor/Mono/AssetPipeline/MaterialDescription.bindings.cs index 1e697cd014..d069614cb1 100644 --- a/Editor/Mono/AssetPipeline/MaterialDescription.bindings.cs +++ b/Editor/Mono/AssetPipeline/MaterialDescription.bindings.cs @@ -19,7 +19,7 @@ public struct TexturePropertyDescription public Texture texture; public string relativePath; public string path; - }; + } [RequiredByNativeCode] [NativeHeader("Editor/Src/AssetPipeline/ModelImporting/MaterialDescription.h")] diff --git a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs index 93a608e77b..e368f12d59 100644 --- a/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureGenerator.bindings.cs @@ -53,7 +53,7 @@ public struct TextureGenerationOutput public string[] importWarnings { get { return m_ImportWarnings; } } public Texture2D thumbNail { get { return m_ThumbNail; } } public Sprite[] sprites { get { return m_Sprites; } } - }; + } [StructLayout(LayoutKind.Sequential)] @@ -73,7 +73,7 @@ public class SourceTextureInformation public int height { get { return m_Height; } set {m_Height = value; } } public bool containsAlpha { get { return m_SourceContainsAlpha; } set {m_SourceContainsAlpha = value; } } public bool hdr { get { return m_SourceWasHDR; } set {m_SourceWasHDR = value; } } - }; + } [StructLayout(LayoutKind.Sequential)] public struct TextureGenerationSettings @@ -214,7 +214,7 @@ public TextureGenerationSettings(TextureImporterType type) public SpriteImportData[] spriteImportData { get { return m_SpriteImportData; } set { m_SpriteImportData = value; } } public string spritePackingTag { get { return m_SpritePackingTag; } set { m_SpritePackingTag = value; } } public SecondarySpriteTexture[] secondarySpriteTextures { get { return m_SecondarySpriteTextures; } set { m_SecondarySpriteTextures = value; } } - }; + } [NativeHeader("Editor/Src/AssetPipeline/TextureImporting/TextureGenerator.h")] diff --git a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs index 89f7e58e77..4be6cc6837 100644 --- a/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureImporter.bindings.cs @@ -423,5 +423,7 @@ public void SetTextureSettings(TextureImporterSettings src) // This is pure backward compatibility codepath. It can be removed when we decide that the time has come internal extern bool ShouldShowRemoveMatteOption(); internal extern bool removeMatte { get; set; } + + public extern bool ignorePngGamma { get; set; } } } diff --git a/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs b/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs index 67188cb7e1..2a5a040b5b 100644 --- a/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs +++ b/Editor/Mono/AssetPipeline/TextureImporterTypes.bindings.cs @@ -95,6 +95,9 @@ public sealed partial class TextureImporterSettings [SerializeField] int m_AlphaIsTransparency; + [SerializeField] + bool m_IgnorePngGamma; + [SerializeField] float m_SpriteTessellationDetail; @@ -334,6 +337,12 @@ public bool alphaIsTransparency set { m_AlphaIsTransparency = value ? 1 : 0; } } + public bool ignorePngGamma + { + get { return m_IgnorePngGamma; } + set { m_IgnorePngGamma = value; } + } + public int spriteMode { get {return m_SpriteMode; } diff --git a/Editor/Mono/AssetPostprocessor.cs b/Editor/Mono/AssetPostprocessor.cs index 7cf90e2ea0..ba88dd9d74 100644 --- a/Editor/Mono/AssetPostprocessor.cs +++ b/Editor/Mono/AssetPostprocessor.cs @@ -77,7 +77,6 @@ static void LogPostProcessorMissingDefaultConstructor(Type type) // Postprocess on all assets once an automatic import has completed static void PostprocessAllAssets(string[] importedAssets, string[] addedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPathAssets) { - bool profile = Profiler.enabled; object[] args = { importedAssets, deletedAssets, movedAssets, movedFromPathAssets }; foreach (var assetPostprocessorClass in GetCachedAssetPostprocessorClasses()) { diff --git a/Editor/Mono/AssetStore/AssetStoreAssetSelection.cs b/Editor/Mono/AssetStore/AssetStoreAssetSelection.cs index 64e139622d..826574be61 100644 --- a/Editor/Mono/AssetStore/AssetStoreAssetSelection.cs +++ b/Editor/Mono/AssetStore/AssetStoreAssetSelection.cs @@ -203,7 +203,7 @@ public static void RefreshFromServer(AssetsRefreshed callback) AssetStoreClient.AssetsInfo(queryAssets, delegate(AssetStoreAssetsInfo results) { AssetStoreAssetInspector.paymentAvailability = AssetStoreAssetInspector.PaymentAvailability.ServiceDisabled; - if (results.error != null && results.error != "") + if (!string.IsNullOrEmpty(results.error)) { System.Console.WriteLine("Error performing Asset Store Info search: " + results.error); AssetStoreAssetInspector.OfflineNoticeEnabled = true; diff --git a/Editor/Mono/AssetStore/AssetStoreClient.cs b/Editor/Mono/AssetStore/AssetStoreClient.cs index 6667ea7388..21b534456a 100644 --- a/Editor/Mono/AssetStore/AssetStoreClient.cs +++ b/Editor/Mono/AssetStore/AssetStoreClient.cs @@ -60,7 +60,7 @@ public override string ToString() string delim = ""; foreach (KeyValuePair kv in dict) { - res += delim + '"' + EncodeString(kv.Key) + "\" : " + kv.Value.ToString(); + res += delim + '"' + EncodeString(kv.Key) + "\" : " + kv.Value; delim = ", "; } return res + "}"; @@ -130,7 +130,7 @@ public static Group Create() public string name; public int offset; public int limit; - }; + } internal List groups = new List(); @@ -401,7 +401,7 @@ internal enum LoginState IN_PROGRESS, LOGGED_IN, LOGIN_ERROR - }; + } static string s_AssetStoreUrl = null; static string s_AssetStoreSearchUrl = null; @@ -806,7 +806,7 @@ internal static AsyncHTTPClient AssetsInfo(List assets, AssetSt { string url = APIUrl("/assets/list"); foreach (AssetStoreAsset asset in assets) - url += "&id=" + asset.id.ToString(); + url += "&id=" + asset.id; // Debug.Log(url); AssetStoreAssetsInfo r = new AssetStoreAssetsInfo(callback, assets); return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); }); @@ -827,7 +827,7 @@ internal static AsyncHTTPClient DirectPurchase(int packageID, string password, P internal static AsyncHTTPClient BuildPackage(AssetStoreAsset asset, BuildPackageResult.Callback callback) { - string url = APIUrl("/content/download/" + asset.packageID.ToString()); + string url = APIUrl("/content/download/" + asset.packageID); // Debug.Log(url); BuildPackageResult r = new BuildPackageResult(asset, callback); return CreateJSONRequest(url, delegate(AssetStoreResponse ar) { r.Parse(ar); }); diff --git a/Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs b/Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs index 10553e0aa3..1cdfc0cd9d 100644 --- a/Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs +++ b/Editor/Mono/AssetStore/AssetStoreInstaBuyWindow.cs @@ -29,7 +29,7 @@ enum PurchaseStatus StartBuild, Building, Downloading - }; + } // Open the dialog to allow the user to purchase the asset static public AssetStoreInstaBuyWindow ShowAssetStoreInstaBuyWindow(AssetStoreAsset asset, string purchaseMessage, string paymentMethodCard, string paymentMethodExpire, string priceText) @@ -184,8 +184,8 @@ void PasswordGUI() GUILayout.Label(s_AssetStoreLogo, GUIStyle.none, GUILayout.ExpandWidth(false)); GUILayout.BeginVertical(); GUILayout.Label("Complete purchase by entering your AssetStore password", EditorStyles.boldLabel); - bool hasMessage = m_PurchaseMessage != null && m_PurchaseMessage != ""; - bool hasErrorMessage = m_Message != null && m_Message != ""; + bool hasMessage = !string.IsNullOrEmpty(m_PurchaseMessage); + bool hasErrorMessage = !string.IsNullOrEmpty(m_Message); float newHeight = kStandardHeight + (hasMessage ? 20 : 0) + (hasErrorMessage ? 20 : 0); if (newHeight != position.height) position = new Rect(position.x, position.y, position.width, newHeight); @@ -247,7 +247,7 @@ void PurchaseSuccessGUI() GUILayout.Label("Purchase completed succesfully", EditorStyles.boldLabel); GUILayout.Label("You will receive a receipt in your email soon."); - bool hasMessage = m_Message != null && m_Message != ""; + bool hasMessage = !string.IsNullOrEmpty(m_Message); float newHeight = kStandardHeight + (hasMessage ? 20 : 0); if (newHeight != position.height) position = new Rect(position.x, position.y, position.width, newHeight); @@ -300,7 +300,7 @@ void DownloadingGUI() if (Event.current.type == EventType.Repaint) { Rect r = GUILayoutUtility.GetLastRect(); - r.height += 1; + r.height += 4; bool downloading = item.downloadProgress >= 0; EditorGUI.ProgressBar(r, downloading ? item.downloadProgress : item.buildProgress, @@ -333,7 +333,7 @@ void PurchaseDeclinedGUI() GUILayout.Label("Purchase declined", EditorStyles.boldLabel); GUILayout.Label("No money has been drawn from you credit card"); - bool hasMessage = m_Message != null && m_Message != ""; + bool hasMessage = !string.IsNullOrEmpty(m_Message); float newHeight = kStandardHeight + (hasMessage ? 20 : 0); if (newHeight != position.height) position = new Rect(position.x, position.y, position.width, newHeight); @@ -463,7 +463,7 @@ void BuildPackage() } string url = result.asset.previewInfo.packageUrl; - if (url != null && url != "") + if (!string.IsNullOrEmpty(url)) { DownloadPackage(); } diff --git a/Editor/Mono/AssetStore/AssetStorePreviewManager.cs b/Editor/Mono/AssetStore/AssetStorePreviewManager.cs index 1a4e5b02a7..f7579935f2 100644 --- a/Editor/Mono/AssetStore/AssetStorePreviewManager.cs +++ b/Editor/Mono/AssetStore/AssetStorePreviewManager.cs @@ -201,7 +201,7 @@ private static AsyncHTTPClient SetupTextureDownload(CachedAssetStoreImage cached { if (client.state != AsyncHTTPClient.State.ABORTED) { - string err = "error " + client.text + " " + client.state.ToString() + " '" + url + "'"; + string err = "error " + client.text + " " + client.state + " '" + url + "'"; if (ObjectListArea.s_Debug) Debug.LogError(err); else @@ -344,7 +344,7 @@ public static bool CheckRepaint() // Abort fetching all previews with the specified size public static void AbortSize(int size) { - AsyncHTTPClient.AbortByTag("previewSize-" + size.ToString()); + AsyncHTTPClient.AbortByTag("previewSize-" + size); // Mark any pending requests for that width in the cases as invalid // now that requests has been aborted. diff --git a/Editor/Mono/AssetStore/Json.cs b/Editor/Mono/AssetStore/Json.cs index 02877138bf..65b5abe410 100644 --- a/Editor/Mono/AssetStore/Json.cs +++ b/Editor/Mono/AssetStore/Json.cs @@ -280,7 +280,7 @@ public override string ToString() string delim = ""; foreach (JSONValue i in AsList()) { - res += delim + i.ToString(); + res += delim + i; delim = ", "; } return res + "]"; @@ -291,7 +291,7 @@ public override string ToString() string delim = ""; foreach (KeyValuePair kv in AsDict()) { - res += delim + '"' + EncodeString(kv.Key) + "\" : " + kv.Value.ToString(); + res += delim + '"' + EncodeString(kv.Key) + "\" : " + kv.Value; delim = ", "; } return res + "}"; @@ -427,7 +427,7 @@ private void SkipWs() private string PosMsg() { - return "line " + line.ToString() + ", column " + linechar.ToString(); + return "line " + line + ", column " + linechar; } private JSONValue ParseValue() diff --git a/Editor/Mono/Audio/Effects/DuckVolumeGUI.cs b/Editor/Mono/Audio/Effects/DuckVolumeGUI.cs index 392832bd10..de297bec76 100644 --- a/Editor/Mono/Audio/Effects/DuckVolumeGUI.cs +++ b/Editor/Mono/Audio/Effects/DuckVolumeGUI.cs @@ -66,7 +66,7 @@ public enum DragType ThresholdAndKnee, Ratio, MakeupGain, - }; + } private static DragType dragtype = DragType.None; diff --git a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs index 00f9e559c1..d2bf250d0a 100644 --- a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs +++ b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerController.cs @@ -791,7 +791,7 @@ public string GetDisplayString() s += s_GroupEffectDisplaySeperator + FixNameForPopupMenu(effect.effectName); return s; } - }; + } // Builds a graph over all connections going out of a group (the parent counts as one). // While building the map, the existing routing of effectSlotUnderTest are ignored and pretended it is connected to targetToTest instead. diff --git a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs index fa92fd4ebc..53f582860d 100644 --- a/Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs +++ b/Editor/Mono/Audio/Mixer/Bindings/AudioMixerGroup.cs @@ -45,7 +45,7 @@ public void DumpHierarchy(string title, int level) prefix += " "; foreach (var f in effects) - Console.WriteLine(prefix + "effect=" + f.ToString()); + Console.WriteLine(prefix + "effect=" + f); foreach (var g in children) g.DumpHierarchy("", level + 1); diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs index d9a074e5ca..7a395e3e55 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerChannelStripView.cs @@ -366,7 +366,7 @@ class PatchSlot { public AudioMixerGroupController group; public float x, y; - }; + } GUIContent bypassButtonContent = EditorGUIUtility.TrTextContent("", "Toggle bypass on this effect"); void EffectSlot(Rect effectRect, AudioMixerSnapshotController snapshot, AudioMixerEffectController effect, int effectIndex, ref int highlightEffectIndex, ChannelStripParams p, ref Dictionary patchslots) diff --git a/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs b/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs index ba9ada5dac..e1336b5fd1 100644 --- a/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs +++ b/Editor/Mono/Audio/Mixer/GUI/AudioMixerWindow.cs @@ -27,7 +27,7 @@ enum SectionType GroupTree, ViewList, SnapshotList - }; + } public enum LayoutMode { diff --git a/Editor/Mono/BuildPipeline/AssemblyStripper.cs b/Editor/Mono/BuildPipeline/AssemblyStripper.cs index ea642b36a5..0414643850 100644 --- a/Editor/Mono/BuildPipeline/AssemblyStripper.cs +++ b/Editor/Mono/BuildPipeline/AssemblyStripper.cs @@ -110,7 +110,7 @@ private static bool StripAssembliesTo(string outputFolder, out string output, ou { var platform = runInformation.platformProvider.Platform; if (string.IsNullOrEmpty(platform)) - throw new ArgumentException($"Platform is required if AllowOutputToBeMadePlatformDependent is true"); + throw new ArgumentException("Platform is required if AllowOutputToBeMadePlatformDependent is true"); args.Add($"--platform={platform}"); } @@ -119,7 +119,7 @@ private static bool StripAssembliesTo(string outputFolder, out string output, ou { var architecture = runInformation.platformProvider.Architecture; if (string.IsNullOrEmpty(architecture)) - throw new ArgumentException($"Architecture is required if AllowOutputToBeMadeArchitectureDependent is true"); + throw new ArgumentException("Architecture is required if AllowOutputToBeMadeArchitectureDependent is true"); args.Add($"--architecture={architecture}"); } diff --git a/Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs b/Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs index 82be57f2b6..bf44d343d6 100644 --- a/Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs +++ b/Editor/Mono/BuildPipeline/AssemblyTypeInfoGenerator.cs @@ -33,14 +33,14 @@ public struct FieldInfo public FieldInfoFlags flags; public int fixedBufferLength; public string fixedBufferTypename; - }; + } [StructLayout(LayoutKind.Sequential)] public struct ClassInfo { public string name; public FieldInfo[] fields; - }; + } private AssemblyDefinition assembly_; diff --git a/Editor/Mono/BuildPipeline/BuildPlatform.cs b/Editor/Mono/BuildPipeline/BuildPlatform.cs index e4b681fdd6..24e5e00293 100644 --- a/Editor/Mono/BuildPipeline/BuildPlatform.cs +++ b/Editor/Mono/BuildPipeline/BuildPlatform.cs @@ -41,7 +41,7 @@ public BuildPlatform(string locTitle, string tooltip, string iconId, BuildTarget this.forceShowTarget = forceShowTarget; this.defaultTarget = defaultTarget; } - }; + } internal class BuildPlatforms { @@ -144,10 +144,7 @@ private int BuildPlatformIndexFromTargetGroup(BuildTargetGroup group) public bool ContainsBuildTarget(BuildTargetGroup group) { - if (BuildPlatformIndexFromTargetGroup(group) < 0) - return false; - - return true; + return BuildPlatformIndexFromTargetGroup(group) >= 0; } public BuildPlatform BuildPlatformFromTargetGroup(BuildTargetGroup group) @@ -170,5 +167,5 @@ public List GetValidPlatforms() { return GetValidPlatforms(false); } - }; + } } diff --git a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs index 41666532b1..c8f5bbf86d 100644 --- a/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs +++ b/Editor/Mono/BuildPipeline/DesktopStandalonePostProcessor.cs @@ -124,7 +124,7 @@ private void CopyNativePlugins(BuildPostProcessArgs args, out List cppPl // HACK: This should never happen. if (string.IsNullOrEmpty(imp.assetPath)) { - UnityEngine.Debug.LogWarning("Got empty plugin importer path for " + args.target.ToString()); + UnityEngine.Debug.LogWarning("Got empty plugin importer path for " + args.target); continue; } diff --git a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs index 814a6c2978..65b33e8dba 100644 --- a/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs +++ b/Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs @@ -440,12 +440,6 @@ private void ConvertPlayerDlltoCpp(Il2CppBuildPipelineData data, string outputDi if (m_BuildForMonoRuntime) arguments.Add("--mono-runtime"); - // Working around gcc bug 41091 - if (m_PlatformProvider.target == BuildTarget.StandaloneLinux64) - { - arguments.Add("--disable-aggressive-inlining"); - } - var buildTargetGroup = BuildPipeline.GetBuildTargetGroup(m_PlatformProvider.target); var apiCompatibilityLevel = PlayerSettings.GetApiCompatibilityLevel(buildTargetGroup); arguments.Add(string.Format("--dotnetprofile=\"{0}\"", IL2CPPUtils.ApiCompatibilityLevelToDotNetProfileArgument(apiCompatibilityLevel))); diff --git a/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs b/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs index a3ea6cd179..c38b7675ab 100644 --- a/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs +++ b/Editor/Mono/BuildPipeline/PostprocessBuildPlayer.cs @@ -105,7 +105,7 @@ internal static bool InstallPluginsByExtension(string pluginSourceFolder, string bool filenameMatch = fileExtension.Equals(extension, StringComparison.OrdinalIgnoreCase) || fileName.Equals(extension, StringComparison.OrdinalIgnoreCase); - bool debugMatch = debugExtension != null && debugExtension.Length != 0 && + bool debugMatch = !string.IsNullOrEmpty(debugExtension) && (fileExtension.Equals(debugExtension, StringComparison.OrdinalIgnoreCase) || fileName.Equals(debugExtension, StringComparison.OrdinalIgnoreCase)); diff --git a/Editor/Mono/BuildPlayerWindowBuildMethods.cs b/Editor/Mono/BuildPlayerWindowBuildMethods.cs index c935003e08..926378f094 100644 --- a/Editor/Mono/BuildPlayerWindowBuildMethods.cs +++ b/Editor/Mono/BuildPlayerWindowBuildMethods.cs @@ -272,7 +272,7 @@ internal static BuildPlayerOptions GetBuildPlayerOptionsInternal(bool askForBuil if (newLocation.Length == 0) { - throw new BuildMethodException("Build location for buildTarget " + buildTarget.ToString() + "is not valid."); + throw new BuildMethodException("Build location for buildTarget " + buildTarget + "is not valid."); } if (!askForBuildLocation) @@ -290,7 +290,7 @@ internal static BuildPlayerOptions GetBuildPlayerOptionsInternal(bool askForBuil newLocation = EditorUserBuildSettings.GetBuildLocation(buildTarget); if (!BuildLocationIsValid(newLocation)) - throw new BuildMethodException("Build location for buildTarget " + buildTarget.ToString() + "is not valid."); + throw new BuildMethodException("Build location for buildTarget " + buildTarget + "is not valid."); break; } @@ -429,7 +429,8 @@ internal static bool IsBuildPathValid(string path) var settingsPath = NormalizePath(basePath + "/ProjectSettings"); var tempPath = NormalizePath(basePath + "/Temp"); var libraryPath = NormalizePath(basePath + "/Library"); - if (basePath.Contains(cleanedPath) || cleanedPath == assetsPath || cleanedPath == settingsPath || cleanedPath == tempPath || cleanedPath == libraryPath) + var userSettingsPath = NormalizePath(basePath + "/UserSettings"); + if (basePath.Contains(cleanedPath) || cleanedPath == assetsPath || cleanedPath == settingsPath || cleanedPath == tempPath || cleanedPath == libraryPath || cleanedPath == userSettingsPath) { Debug.LogError("Invalid build path: " + cleanedPath); return false; diff --git a/Editor/Mono/BuildTargetDiscovery.bindings.cs b/Editor/Mono/BuildTargetDiscovery.bindings.cs index 3a927494ad..eab6ca1a6b 100644 --- a/Editor/Mono/BuildTargetDiscovery.bindings.cs +++ b/Editor/Mono/BuildTargetDiscovery.bindings.cs @@ -42,7 +42,7 @@ public enum TargetAttributes StrippingNotSupported = (1 << 16), DisableNativeHDRLightmaps = (1 << 17), UsesNativeHDR = (1 << 18), - ProtectedGraphicsMem = (1 << 19), + // ProtectedGraphicsMem = (1 << 19), This was removed. IsMTRenderingDisabledByDefault = (1 << 20) } diff --git a/Editor/Mono/CodeEditor/CodeEditor.cs b/Editor/Mono/CodeEditor/CodeEditor.cs index 2d7004c744..d93b97fce8 100644 --- a/Editor/Mono/CodeEditor/CodeEditor.cs +++ b/Editor/Mono/CodeEditor/CodeEditor.cs @@ -30,7 +30,7 @@ public struct Installation } [RequiredByNativeCode] - static bool OpenFileAtLineColumn(string path, int line, int column) + static bool OpenProject(string path, int line, int column) { return Editor.Current.OpenProject(path, line, column); } @@ -156,6 +156,11 @@ public static void Unregister(IExternalCodeEditor externalCodeEditor) public static string CurrentEditorInstallation => Editor.EditorInstallation.Path; + public static bool OSOpenFile(string appPath, string arguments) + { + return ExternalEditor.OSOpenFileWithArgument(appPath, arguments); + } + public static string ParseArgument(string arguments, string path, int line, int column) { var newArgument = arguments.Replace("$(ProjectPath)", QuoteForProcessStart(Directory.GetParent(Application.dataPath).FullName)); diff --git a/Editor/Mono/CodeEditor/DefaultExternalCodeEditor.cs b/Editor/Mono/CodeEditor/DefaultExternalCodeEditor.cs index e35b8f24a4..f4889f5a84 100644 --- a/Editor/Mono/CodeEditor/DefaultExternalCodeEditor.cs +++ b/Editor/Mono/CodeEditor/DefaultExternalCodeEditor.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 System.Diagnostics; using System.IO; +using System.Linq; using Unity.CodeEditor; using UnityEngine; @@ -12,6 +14,8 @@ namespace UnityEditor internal class DefaultExternalCodeEditor : IExternalCodeEditor { static readonly GUIContent k_ResetArguments = EditorGUIUtility.TrTextContent("Reset argument"); + static bool IsOSX => Application.platform == RuntimePlatform.OSXEditor; + string m_ChosenInstallation; const string k_ArgumentKey = "kScriptEditorArgs"; const string k_DefaultArgument = "$(File)"; @@ -83,9 +87,45 @@ public void Initialize(string editorInstallationPath) m_ChosenInstallation = editorInstallationPath; } + static string[] defaultExtensions + { + get + { + var customExtensions = new[] {"json", "asmdef", "log"}; + return EditorSettings.projectGenerationBuiltinExtensions + .Concat(EditorSettings.projectGenerationUserExtensions) + .Concat(customExtensions) + .Distinct().ToArray(); + } + } + + static bool SupportsExtension(string path) + { + var extension = Path.GetExtension(path); + if (string.IsNullOrEmpty(extension)) + return false; + return defaultExtensions.Contains(extension.TrimStart('.')); + } + public bool OpenProject(string path, int line, int column) { + if (path != "" && !SupportsExtension(path)) // Assets - Open C# Project passes empty path here + { + return false; + } + string applicationPath = EditorPrefs.GetString("kScriptsDefaultApp"); + if (string.IsNullOrEmpty(applicationPath.Trim())) + { + return false; + } + + + if (IsOSX) + { + return CodeEditor.OSOpenFile(applicationPath, CodeEditor.ParseArgument(Arguments, path, line, column)); + } + var process = new Process { StartInfo = new ProcessStartInfo diff --git a/Editor/Mono/CodeEditor/ExternalEditor.bindings.cs b/Editor/Mono/CodeEditor/ExternalEditor.bindings.cs new file mode 100644 index 0000000000..4e94506f0d --- /dev/null +++ b/Editor/Mono/CodeEditor/ExternalEditor.bindings.cs @@ -0,0 +1,15 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEngine.Bindings; + +namespace Unity.CodeEditor +{ + [NativeHeader("Editor/Platform/Interface/ExternalEditor.h")] + internal class ExternalEditor + { + [FreeFunction("PlatformSpecificOpenFileAtLine")] + internal static extern bool OSOpenFileWithArgument(string appPath, string arguments); + } +} diff --git a/Editor/Mono/Collab/Collab.cs b/Editor/Mono/Collab/Collab.cs index 5a3a96c851..4c6df31559 100644 --- a/Editor/Mono/Collab/Collab.cs +++ b/Editor/Mono/Collab/Collab.cs @@ -80,7 +80,7 @@ public enum Operation ChooseMine = 1 << 9, ChooseTheirs = 1 << 10, ExternalMerge = 1 << 11, - }; + } // Must keep in sync with C++ in CollabCommon.h // Explicit uint so "Any" state works with C++ @@ -120,9 +120,9 @@ public enum CollabStates : uint kAnyLocalChanged = (kCollabAddedLocal | kCollabCheckedOutLocal | kCollabDeletedLocal | kCollabMovedLocal), kAnyLocalEdited = (kCollabAddedLocal | kCollabCheckedOutLocal | kCollabMovedLocal), kCollabAny = 0xFFFFFFFF - }; + } - internal enum CollabStateID { None, Uninitialized, Initialized }; + internal enum CollabStateID { None, Uninitialized, Initialized } public static string[] clientType = { diff --git a/Editor/Mono/Collab/CollabChange.cs b/Editor/Mono/Collab/CollabChange.cs index c14d5ffb66..1297fdb044 100644 --- a/Editor/Mono/Collab/CollabChange.cs +++ b/Editor/Mono/Collab/CollabChange.cs @@ -36,7 +36,7 @@ public enum RevertableStates : uint // do not exceed Javascript Number range InvalidRevertableState = (uint)1 << 31 - }; + } string m_Path; Collab.CollabStates m_State; diff --git a/Editor/Mono/Collab/CollabDialogs.cs b/Editor/Mono/Collab/CollabDialogs.cs index a49b50cdcf..155f8766e1 100644 --- a/Editor/Mono/Collab/CollabDialogs.cs +++ b/Editor/Mono/Collab/CollabDialogs.cs @@ -86,7 +86,7 @@ public void OnGUI() } public PublishDialogOptions Options; - }; + } internal class CollabCannotPublishDialog : EditorWindow { @@ -142,5 +142,5 @@ public void OnGUI() GUILayout.EndVertical(); } - }; + } } diff --git a/Editor/Mono/Collab/CollabProgressInfo.cs b/Editor/Mono/Collab/CollabProgressInfo.cs index 5853470748..5727a41a7d 100644 --- a/Editor/Mono/Collab/CollabProgressInfo.cs +++ b/Editor/Mono/Collab/CollabProgressInfo.cs @@ -22,7 +22,7 @@ public enum ProgressType : uint Count = 1, Percent = 2, Both = 3 - }; + } int m_JobId; string m_Title; diff --git a/Editor/Mono/ConsoleWindow.cs b/Editor/Mono/ConsoleWindow.cs index e40715eb6b..108af72774 100644 --- a/Editor/Mono/ConsoleWindow.cs +++ b/Editor/Mono/ConsoleWindow.cs @@ -11,6 +11,7 @@ using UnityEngine.Experimental.Networking.PlayerConnection; using UnityEditor.Experimental.Networking.PlayerConnection; using ConnectionGUILayout = UnityEditor.Experimental.Networking.PlayerConnection.EditorGUILayout; +using System.Collections.Generic; namespace UnityEditor { @@ -124,6 +125,7 @@ private static void UpdateLogStyleFixedHeights() ListViewState m_ListView; string m_ActiveText = ""; + StringBuilder m_CopyString; private int m_ActiveInstanceID = 0; bool m_DevBuild; @@ -211,7 +213,7 @@ internal enum Mode GraphCompileError = 1 << 20, ScriptingAssertion = 1 << 21, VisualScriptingError = 1 << 22 - }; + } enum ConsoleFlags { @@ -227,7 +229,7 @@ enum ConsoleFlags LogLevelError = 1 << 9, ShowTimestamp = 1 << 10, ClearOnBuild = 1 << 11, - }; + } static ConsoleWindow ms_ConsoleWindow = null; private string m_SearchText; @@ -291,6 +293,7 @@ public ConsoleWindow() { position = new Rect(200, 200, 800, 400); m_ListView = new ListViewState(0, 0); + m_CopyString = new StringBuilder(); m_SearchText = string.Empty; EditorGUI.hyperLinkClicked += EditorGUI_HyperLinkClicked; } @@ -432,6 +435,7 @@ void SetActiveEntry(LogEntry entry) m_ActiveText = string.Empty; m_ActiveInstanceID = 0; m_ListView.row = -1; + m_CopyString.Clear(); } } @@ -554,7 +558,7 @@ internal void OnGUI() int selectedRow = -1; bool openSelectedItem = false; bool collapsed = HasFlag(ConsoleFlags.Collapse); - foreach (ListViewElement el in ListViewGUI.ListView(m_ListView, Constants.Box)) + foreach (ListViewElement el in ListViewGUI.ListView(m_ListView, ListViewOptions.wantsRowMultiSelection, Constants.Box)) { if (e.type == EventType.MouseDown && e.button == 0 && el.position.Contains(e.mousePosition)) { @@ -573,7 +577,7 @@ internal void OnGUI() // Draw the background GUIStyle s = el.row % 2 == 0 ? Constants.OddBackground : Constants.EvenBackground; - s.Draw(el.position, false, false, m_ListView.row == el.row, false); + s.Draw(el.position, false, false, m_ListView.selectedItems != null && m_ListView.selectedItems.Length == m_ListView.totalRows && m_ListView.selectedItems[el.row], false); // Draw the icon GUIStyle iconStyle = GetStyleForErrorMode(mode, true, Constants.LogStyleLineCount == 1); @@ -581,7 +585,7 @@ internal void OnGUI() iconRect.x += offset; iconRect.y += 2; - iconStyle.Draw(iconRect, false, false, m_ListView.row == el.row, false); + iconStyle.Draw(iconRect, false, false, m_ListView.selectedItems != null && m_ListView.selectedItems.Length == m_ListView.totalRows && m_ListView.selectedItems[el.row], false); // Draw the text tempContent.text = text; @@ -652,8 +656,21 @@ internal void OnGUI() { SetActiveEntry(entry); } - } + // If copy, get the messages from selected rows + if (e.type == EventType.ExecuteCommand && e.commandName == EventCommandNames.Copy && m_ListView.selectedItems != null) + { + m_CopyString.Clear(); + for (int rowIndex = 0; rowIndex < m_ListView.selectedItems.Length; rowIndex++) + { + if (m_ListView.selectedItems[rowIndex]) + { + LogEntries.GetEntryInternal(rowIndex, entry); + m_CopyString.AppendLine(entry.message); + } + } + } + } // Open entry using return key if ((GUIUtility.keyboardControl == m_ListView.ID) && (e.type == EventType.KeyDown) && (e.keyCode == KeyCode.Return) && (m_ListView.row != 0)) @@ -690,10 +707,10 @@ internal void OnGUI() SplitterGUILayout.EndVerticalSplit(); // Copy & Paste selected item - if ((e.type == EventType.ValidateCommand || e.type == EventType.ExecuteCommand) && e.commandName == EventCommandNames.Copy && m_ActiveText != string.Empty) + if ((e.type == EventType.ValidateCommand || e.type == EventType.ExecuteCommand) && e.commandName == EventCommandNames.Copy && m_CopyString != null) { if (e.type == EventType.ExecuteCommand) - EditorGUIUtility.systemCopyBuffer = m_ActiveText; + EditorGUIUtility.systemCopyBuffer = m_CopyString.ToString(); e.Use(); } } @@ -835,8 +852,7 @@ public void ToggleLogStackTracesForAll(object userData) public void AddItemsToMenu(GenericMenu menu) { - if (Application.platform == RuntimePlatform.OSXEditor) - menu.AddItem(EditorGUIUtility.TrTextContent("Open Player Log"), false, UnityEditorInternal.InternalEditorUtility.OpenPlayerConsole); + menu.AddItem(EditorGUIUtility.TrTextContent("Open Player Log"), false, UnityEditorInternal.InternalEditorUtility.OpenPlayerConsole); menu.AddItem(EditorGUIUtility.TrTextContent("Open Editor Log"), false, UnityEditorInternal.InternalEditorUtility.OpenEditorConsole); menu.AddItem(EditorGUIUtility.TrTextContent("Show Timestamp"), HasFlag(ConsoleFlags.ShowTimestamp), SetTimestamp); diff --git a/Editor/Mono/ContainerWindow.cs b/Editor/Mono/ContainerWindow.cs index 15b6e96207..8cefa3be83 100644 --- a/Editor/Mono/ContainerWindow.cs +++ b/Editor/Mono/ContainerWindow.cs @@ -337,6 +337,8 @@ public SplitView rootSplitView { if (m_ShowMode == (int)ShowMode.MainWindow && rootView && rootView.children.Length == 3) return rootView.children[1] as SplitView; + if (m_ShowMode == (int)ShowMode.MainWindow && rootView && rootView.children.Length == 2) + return rootView.children[0] as SplitView; else return rootView as SplitView; } @@ -364,7 +366,7 @@ public void HandleWindowDecorationEnd(Rect windowPosition) public void HandleWindowDecorationStart(Rect windowPosition) { - bool hasTitleBar = (windowPosition.y == 0 && showMode != ShowMode.Utility && !isPopup); + bool hasTitleBar = (windowPosition.y == 0 && (showMode != ShowMode.Utility && showMode != ShowMode.MainWindow) && !isPopup); if (!hasTitleBar) return; diff --git a/Editor/Mono/EditorAssemblies.cs b/Editor/Mono/EditorAssemblies.cs index 22b31ce5d9..c6848d1635 100644 --- a/Editor/Mono/EditorAssemblies.cs +++ b/Editor/Mono/EditorAssemblies.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; -using Unity.Profiling; using UnityEngine; using UnityEngine.Scripting; @@ -33,6 +32,12 @@ public class InitializeOnLoadMethodAttribute : Attribute { } + [RequiredByNativeCode] + [AttributeUsage(AttributeTargets.Method)] + public class InitializeOnEnterPlayModeAttribute : Attribute + { + } + /// /// Holds information about the current set of editor assemblies. /// diff --git a/Editor/Mono/EditorBuildSettings.bindings.cs b/Editor/Mono/EditorBuildSettings.bindings.cs index f8c11af2e1..4913631261 100644 --- a/Editor/Mono/EditorBuildSettings.bindings.cs +++ b/Editor/Mono/EditorBuildSettings.bindings.cs @@ -106,7 +106,7 @@ enum ConfigObjectResult FailedNonPersistedObj, FailedEntryExists, FailedTypeMismatch - }; + } [NativeMethod("AddConfigObject")] static extern ConfigObjectResult AddConfigObjectInternal(string name, Object obj, bool overwrite); diff --git a/Editor/Mono/EditorConnectionInternal.bindings.cs b/Editor/Mono/EditorConnectionInternal.bindings.cs new file mode 100644 index 0000000000..3df14a3537 --- /dev/null +++ b/Editor/Mono/EditorConnectionInternal.bindings.cs @@ -0,0 +1,129 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine; +using UnityEngine.Bindings; + +namespace UnityEditor +{ + [NativeHeader("Runtime/Network/PlayerCommunicator/GeneralConnection.h")] + enum GeneralConnectionSendMode + { + NoBlocking, + AllowBlocking + } + + [StaticAccessor("EditorConnection::Get()", StaticAccessorType.Dot)] + [NativeHeader("Runtime/Network/PlayerCommunicator/EditorConnection.h")] + [NativeHeader("Runtime/Network/PlayerCommunicator/ManagedProxy/EditorConnectionManaged.h")] + internal class EditorConnectionInternal : IPlayerEditorConnectionNative + { + void IPlayerEditorConnectionNative.SendMessage(Guid messageId, byte[] data, int playerId) + { + if (messageId == Guid.Empty) + { + throw new ArgumentException(nameof(messageId) + " must not be empty"); + } + SendMessage(messageId.ToString("N"), data, playerId); + } + + bool IPlayerEditorConnectionNative.TrySendMessage(Guid messageId, byte[] data, int playerId) + { + if (messageId == Guid.Empty) + { + throw new ArgumentException(nameof(messageId) + " must not be empty"); + } + return TrySendMessage(messageId.ToString("N"), data, playerId); + } + + void IPlayerEditorConnectionNative.Poll() + { + PollInternal(); + } + + void IPlayerEditorConnectionNative.RegisterInternal(Guid messageId) + { + RegisterInternal(messageId.ToString("N")); + } + + void IPlayerEditorConnectionNative.UnregisterInternal(Guid messageId) + { + UnregisterInternal(messageId.ToString("N")); + } + + void IPlayerEditorConnectionNative.Initialize() + { + Initialize(); + } + + void IPlayerEditorConnectionNative.DisconnectAll() + { + DisconnectAll(); + } + + public bool IsConnected() + { + throw new NotSupportedException("Check the connected players list instead"); + } + + [NativeConditional("ENABLE_PLAYERCONNECTION && UNITY_EDITOR")] + [FreeFunction("EditorConnectionManaged::Get")] + public extern static void Initialize(); + + public static void UnregisterInternal(string messageId) + { + UnregisterInternal(new GUID(messageId)); + } + + [NativeConditional("ENABLE_PLAYERCONNECTION && UNITY_EDITOR")] + [StaticAccessor("EditorConnectionManaged::Get()", StaticAccessorType.Dot)] + [NativeName("Unregister")] + private extern static void UnregisterInternal(UnityEditor.GUID messageId); + + public static void RegisterInternal(string messageId) { RegisterInternal(new GUID(messageId)); } + + [NativeConditional("ENABLE_PLAYERCONNECTION && UNITY_EDITOR")] + [StaticAccessor("EditorConnectionManaged::Get()", StaticAccessorType.Dot)] + [NativeName("Register")] + private extern static void RegisterInternal(UnityEditor.GUID messageId); + + + [NativeConditional("ENABLE_PLAYERCONNECTION && UNITY_EDITOR")] + [NativeName("SendMessage")] + private extern unsafe static void SendMessageInternal(int playerId, GUID messageId, byte* data, int dataSize, GeneralConnectionSendMode sendMode); + + //playerId 0 is ANY_PLAYERCONNECTION + public static void SendMessage(string messageId, byte[] data, int playerId) + { + unsafe + { + fixed(byte* dataBytes = data) + SendMessageInternal(playerId, new GUID(messageId), dataBytes, data?.Length ?? 0, GeneralConnectionSendMode.AllowBlocking); + } + } + + [NativeConditional("ENABLE_PLAYERCONNECTION && UNITY_EDITOR")] + [NativeName("TrySendMessage")] + private extern unsafe static bool TrySendMessageInternal(int playerId, GUID messageId, byte* data, int dataSize); + + //playerId 0 is ANY_PLAYERCONNECTION + public static bool TrySendMessage(string messageId, byte[] data, int playerId) + { + unsafe + { + fixed(byte* dataBytes = data) + return TrySendMessageInternal(playerId, new GUID(messageId), dataBytes, data?.Length ?? 0); + } + } + + [NativeName("Poll")] + public extern static void PollInternal(); + + public extern static int ConnectPlayerProxy(string IP, int port); + + [NativeConditional("ENABLE_PLAYERCONNECTION && UNITY_EDITOR")] + public extern static void DisconnectAll(); + } +} diff --git a/Editor/Mono/EditorGUI.cs b/Editor/Mono/EditorGUI.cs index 6b78ada58f..8324e9678e 100644 --- a/Editor/Mono/EditorGUI.cs +++ b/Editor/Mono/EditorGUI.cs @@ -1616,6 +1616,13 @@ internal static string TextFieldInternal(Rect position, GUIContent label, string return text; } + internal static string TextFieldInternal(int id, Rect position, GUIContent label, string text, GUIStyle style) + { + bool dummy; + text = DoTextField(s_RecycledEditor, id, PrefixLabel(position, id, label), text, style, null, out dummy, false, false, false); + return text; + } + internal static string ToolbarSearchField(Rect position, string text, bool showWithPopupArrow) { int id = GUIUtility.GetControlID(s_SearchFieldHash, FocusType.Keyboard, position); @@ -2409,6 +2416,12 @@ internal static GenericMenu FillPropertyContextMenu(SerializedProperty property, GenericMenu pm = menu ?? new GenericMenu(); + var itargetobjects = property.serializedObject.targetObjectsCount; + for (int icount = 0; icount < itargetobjects; icount++) + { + if (!property.serializedObject.targetObjects[icount]) + return null; + } // Since the menu items are invoked with delay, we can't assume a SerializedObject we don't own // will still be around at that time. Hence create our own copy. (case 1051734) SerializedObject serializedObjectCopy = new SerializedObject(property.serializedObject.targetObjects); @@ -2514,7 +2527,7 @@ internal static void DoPropertyContextMenu(SerializedProperty property, Serializ { GenericMenu pm = FillPropertyContextMenu(property, linkedProperty, menu); - if (pm.GetItemCount() == 0) + if (pm == null || pm.GetItemCount() == 0) { return; } @@ -3919,7 +3932,10 @@ private static Rect RectFieldNoIndent(Rect position, Rect value) s_Vector2Floats[0] = value.x; s_Vector2Floats[1] = value.y; BeginChangeCheck(); - MultiFloatField(position, s_XYLabels, s_Vector2Floats); + // Right align the text + var oldAlignment = EditorStyles.label.alignment; + EditorStyles.label.alignment = TextAnchor.MiddleRight; + MultiFloatFieldInternal(position, s_XYLabels, s_Vector2Floats, kMiniLabelW); if (EndChangeCheck()) { value.x = s_Vector2Floats[0]; @@ -3929,12 +3945,13 @@ private static Rect RectFieldNoIndent(Rect position, Rect value) s_Vector2Floats[0] = value.width; s_Vector2Floats[1] = value.height; BeginChangeCheck(); - MultiFloatField(position, s_WHLabels, s_Vector2Floats); + MultiFloatFieldInternal(position, s_WHLabels, s_Vector2Floats, kMiniLabelW); if (EndChangeCheck()) { value.width = s_Vector2Floats[0]; value.height = s_Vector2Floats[1]; } + EditorStyles.label.alignment = oldAlignment; return value; } @@ -4170,7 +4187,7 @@ public static void MultiFloatField(Rect position, GUIContent[] subLabels, float[ MultiFloatFieldInternal(position, subLabels, values); } - internal static void MultiFloatFieldInternal(Rect position, GUIContent[] subLabels, float[] values) + internal static void MultiFloatFieldInternal(Rect position, GUIContent[] subLabels, float[] values, float prefixLabelWidth = -1) { int eCount = values.Length; float w = (position.width - (eCount - 1) * kSpacingSubLabel) / eCount; @@ -4180,7 +4197,7 @@ internal static void MultiFloatFieldInternal(Rect position, GUIContent[] subLabe indentLevel = 0; for (int i = 0; i < values.Length; i++) { - EditorGUIUtility.labelWidth = EditorGUI.CalcPrefixLabelWidth(subLabels[i]); + EditorGUIUtility.labelWidth = prefixLabelWidth > 0 ? prefixLabelWidth : EditorGUI.CalcPrefixLabelWidth(subLabels[i]); values[i] = FloatField(nr, subLabels[i], values[i]); nr.x += w + kSpacingSubLabel; } @@ -4867,12 +4884,19 @@ internal static void DoInspectorTitlebar(Rect position, int id, bool foldout, Ob { GUIStyle textStyle = EditorStyles.inspectorTitlebarText; GUIStyle iconButtonStyle = EditorStyles.iconButton; + Event evt = Event.current; + bool pressed = GUIUtility.hotControl == id; + bool hasFocus = GUIUtility.HasKeyFocus(id); + bool hovered = position.Contains(evt.mousePosition); Rect iconRect = GetIconRect(position, baseStyle); Rect settingsRect = GetSettingsRect(position, baseStyle, iconButtonStyle); Rect textRect = GetTextRect(position, iconRect, settingsRect, baseStyle, textStyle); - Event evt = Event.current; + if (evt.type == EventType.Repaint) + { + baseStyle.Draw(position, GUIContent.none, hovered, pressed, foldout, hasFocus); + } bool isAddedComponentAndEventIsRepaint = false; Component comp = targetObjs[0] as Component; @@ -4999,8 +5023,7 @@ internal static void DoInspectorTitlebar(Rect position, int id, bool foldout, Ob } break; case EventType.Repaint: - baseStyle.Draw(position, GUIContent.none, id, foldout, position.Contains(Event.current.mousePosition)); - textStyle.Draw(textRect, EditorGUIUtility.TempContent(ObjectNames.GetInspectorTitle(targetObjs[0])), id, foldout, textRect.Contains(Event.current.mousePosition)); + textStyle.Draw(textRect, EditorGUIUtility.TempContent(ObjectNames.GetInspectorTitle(targetObjs[0])), hovered, pressed, foldout, hasFocus); if (EditorGUIUtility.comparisonViewMode == EditorGUIUtility.ComparisonViewMode.None) { EditorStyles.optionsButtonStyle.Draw(settingsRect, GUIContent.none, id, foldout, settingsRect.Contains(Event.current.mousePosition)); @@ -5158,15 +5181,38 @@ internal static bool FoldoutTitlebar(Rect position, GUIContent label, bool foldo // Important to get controlId for the foldout first, so it gets keyboard focus before the toggle does. int id = GUIUtility.GetControlID(s_TitlebarHash, FocusType.Keyboard, position); - if (Event.current.type == EventType.Repaint) + switch (Event.current.type) { - GUIStyle foldoutStyle = EditorStyles.foldout; - Rect textRect = new Rect(position.x + baseStyle.padding.left + (skipIconSpacing ? 0 : (kInspTitlebarIconWidth + kInspTitlebarSpacing)), position.y + baseStyle.padding.top, EditorGUIUtility.labelWidth, kInspTitlebarIconWidth); + case EventType.KeyDown: + if (GUIUtility.keyboardControl == id) + { + KeyCode kc = Event.current.keyCode; + if (kc == KeyCode.LeftArrow && foldout || (kc == KeyCode.RightArrow && foldout == false)) + { + foldout = !foldout; + GUI.changed = true; + Event.current.Use(); + return foldout; + } + } - baseStyle.Draw(position, GUIContent.none, id, foldout); - foldoutStyle.Draw(GetInspectorTitleBarObjectFoldoutRenderRect(position, baseStyle), GUIContent.none, id, foldout); - position = baseStyle.padding.Remove(position); - textStyle.Draw(textRect, EditorGUIUtility.TempContent(label.text), id, foldout); + break; + case EventType.Repaint: + GUIStyle foldoutStyle = EditorStyles.foldout; + Rect textRect = + new Rect( + position.x + baseStyle.padding.left + + (skipIconSpacing ? 0 : (kInspTitlebarIconWidth + kInspTitlebarSpacing)), + position.y + baseStyle.padding.top, EditorGUIUtility.labelWidth, kInspTitlebarIconWidth); + bool hovered = position.Contains(Event.current.mousePosition); + baseStyle.Draw(position, GUIContent.none, id, foldout, hovered); + foldoutStyle.Draw(GetInspectorTitleBarObjectFoldoutRenderRect(position, baseStyle), GUIContent.none, + id, foldout, hovered); + position = baseStyle.padding.Remove(position); + textStyle.Draw(textRect, EditorGUIUtility.TempContent(label.text), id, foldout, hovered); + break; + default: + break; } return EditorGUIInternal.DoToggleForward(IndentedRect(position), id, foldout, GUIContent.none, GUIStyle.none); @@ -9659,8 +9705,6 @@ internal static int BeginPlatformGrouping(BuildPlatform[] platforms, GUIContent startIndex = -1; } - float buttonWidth = buttonCount > 0 ? r.width / buttonCount : 0; - int buttonIndex = 0; for (int i = startIndex; i < platformCount; i++, buttonIndex++) { diff --git a/Editor/Mono/EditorGUIUtility.bindings.cs b/Editor/Mono/EditorGUIUtility.bindings.cs index feccfbbfd6..fc3bb6a891 100644 --- a/Editor/Mono/EditorGUIUtility.bindings.cs +++ b/Editor/Mono/EditorGUIUtility.bindings.cs @@ -150,7 +150,7 @@ public static void RenderGameViewCameras(RenderTexture target, int targetDisplay internal static extern Texture2D GetIconForObject(Object obj); // Render all ingame cameras bound to a specific Display. - internal static extern void RenderPreviewCamerasInternal(RenderTexture target, int targetDisplay, Vector2 mousePosition, bool gizmos, bool renderIMGUI); + internal static extern void RenderPlayModeViewCamerasInternal(RenderTexture target, int targetDisplay, Vector2 mousePosition, bool gizmos, bool renderIMGUI); internal static extern void SetupWindowSpaceAndVSyncInternal(Rect screenRect); private static extern Texture2D FindTextureByName(string name); diff --git a/Editor/Mono/EditorGUIUtility.cs b/Editor/Mono/EditorGUIUtility.cs index 0cac3e680f..64637bae7a 100644 --- a/Editor/Mono/EditorGUIUtility.cs +++ b/Editor/Mono/EditorGUIUtility.cs @@ -98,6 +98,18 @@ internal static Material GUITextureBlitSceneGUIMaterial static EditorGUIUtility() { GUISkin.m_SkinChanged += SkinChanged; + s_HasCurrentWindowKeyFocusFunc = HasCurrentWindowKeyFocus; + } + + // returns position and size of the main Unity Editor window + public static Rect GetMainWindowPosition() + { + foreach (var win in ContainerWindow.windows) + { + if (win.IsMainWindow()) + return win.position; + } + return new Rect(0, 0, 1000, 600); } internal static void RepaintCurrentWindow() diff --git a/Editor/Mono/EditorMode/ModeService.cs b/Editor/Mono/EditorMode/ModeService.cs index b875b82a9f..0507bb93ca 100644 --- a/Editor/Mono/EditorMode/ModeService.cs +++ b/Editor/Mono/EditorMode/ModeService.cs @@ -83,6 +83,7 @@ public struct ModeChangedArgs public static string currentId => currentIndex == -1 ? k_DefaultModeId : modes[currentIndex].id; public static int currentIndex { get; private set; } private static ModeEntry[] modes { get; set; } = new ModeEntry[0]; + internal static bool hasSwitchableModes { get; private set; } public static event Action modeChanged; @@ -290,9 +291,41 @@ private static void LoadModes(bool checkStartupMode = false) EditorApplication.delayCall += () => RaiseModeChanged(-1, currentIndex); } - private static void ScanModes() + private static void FillModeData(string path, Dictionary modesData) + { + try + { + var json = SJSON.Load(path); + foreach (var rawModeId in json.Keys) + { + var modeId = ((string)rawModeId).ToLower(); + if (IsValidModeId(modeId)) + { + object modeData = null; + if (modesData.TryGetValue(modeId, out modeData)) + modesData[modeId] = JsonUtils.DeepMerge(modeData as JSONObject, json[modeId] as JSONObject); + else + modesData[modeId] = json[modeId]; + } + else + { + Debug.LogWarning($"Invalid Mode Id: {modeId} contains non alphanumeric characters."); + } + } + } + catch (Exception ex) + { + Debug.LogError($"[ModeService] Error while parsing mode file {path}.\n{ex}"); + } + } + + internal static void ScanModes() { var modesData = new Dictionary { [k_DefaultModeId] = new Dictionary { [k_LabelSectionName] = "Default" } }; + + var builtinModeFile = Path.Combine(EditorApplication.applicationContentsPath, "Resources/default.mode"); + FillModeData(builtinModeFile, modesData); + var modeDescriptors = AssetDatabase.EnumerateAllAssets(new SearchFilter { searchArea = SearchFilter.SearchArea.InPackagesOnly, @@ -305,39 +338,20 @@ private static void ScanModes() var md = modeDescriptors.Current.pptrValue as ModeDescriptor; if (md == null) continue; - try - { - var json = SJSON.Load(md.path); - foreach (var rawModeId in json.Keys) - { - var modeId = ((string)rawModeId).ToLower(); - if (IsValidModeId(modeId)) - { - if (modesData.ContainsKey(modeId)) - modesData[modeId] = JsonUtils.DeepMerge(modesData[modeId] as JSONObject, json[modeId] as JSONObject); - else - modesData[modeId] = json[modeId]; - } - else - { - Debug.LogWarning($"Invalid Mode Id: {modeId} contains non alphanumeric characters."); - } - } - } - catch (Exception ex) - { - Debug.LogError($"[ModeService] Error while parsing mode file {md.path}.\n{ex}"); - } + FillModeData(md.path, modesData); } modes = new ModeEntry[modesData.Keys.Count]; modes[0] = CreateEntry(k_DefaultModeId, (JSONObject)modesData[k_DefaultModeId]); var modeIndex = 1; + hasSwitchableModes = false; foreach (var modeId in modesData.Keys) { if (modeId == k_DefaultModeId) continue; - modes[modeIndex] = CreateEntry(modeId, (JSONObject)modesData[modeId]); + var modeFields = (JSONObject)modesData[modeId]; + modes[modeIndex] = CreateEntry(modeId, modeFields); + hasSwitchableModes |= !JsonUtils.JsonReadBoolean(modeFields, "builtin"); modeIndex++; } } @@ -352,13 +366,6 @@ private static ModeEntry CreateEntry(string modeId, JSONObject data) }; } - private static bool IsEditorModeDescriptor(string path) - { - var pathLowerCased = path.ToLower(); - // Limit the authoring of editor modes to Unity packages for now. - return pathLowerCased.StartsWith("packages/com.unity") && pathLowerCased.EndsWith(".mode"); - } - private static void SetModeIndex(int modeIndex) { currentIndex = Math.Max(0, Math.Min(modeIndex, modeCount - 1)); @@ -522,7 +529,8 @@ private static void OnModeChangeLayouts(ModeChangedArgs args) } } - WindowLayout.ReloadWindowLayoutMenu(); + if (HasCapability(ModeCapability.LayoutWindowMenu, true)) + WindowLayout.ReloadWindowLayoutMenu(); } private static void OnModeChangeUpdate(ModeChangedArgs args) diff --git a/Editor/Mono/EditorResources.bindings.cs b/Editor/Mono/EditorResources.bindings.cs index 4533e14a07..0b469adc9b 100644 --- a/Editor/Mono/EditorResources.bindings.cs +++ b/Editor/Mono/EditorResources.bindings.cs @@ -22,6 +22,7 @@ partial class EditorResources [NativeProperty("k_GeneratedIconsPath", true, TargetType.Field)] public static extern string generatedIconsPath { get; } [NativeProperty("k_FolderIconName", true, TargetType.Field)] public static extern string folderIconName { get; } [NativeProperty("k_EmptyFolderIconName", true, TargetType.Field)] public static extern string emptyFolderIconName { get; } + [NativeProperty("k_OpenedFolderIconName", true, TargetType.Field)] internal static extern string openedFolderIconName { get; } [NativeProperty("k_EditorDefaultResourcesPath", true, TargetType.Field)] public static extern string editorDefaultResourcesPath { get; } [NativeProperty("k_LibraryBundlePath", true, TargetType.Field)] public static extern string libraryBundlePath { get; } diff --git a/Editor/Mono/EditorResources.cs b/Editor/Mono/EditorResources.cs index aa403b2f2b..113b74b171 100644 --- a/Editor/Mono/EditorResources.cs +++ b/Editor/Mono/EditorResources.cs @@ -50,10 +50,7 @@ private static bool IsEditorStyleSheet(string path) internal static string GetDefaultFont() { - if (Application.platform == RuntimePlatform.WindowsEditor) - return "Verdana"; - else - return "Roboto"; + return "Inter"; } internal static string GetCurrentFont() @@ -84,9 +81,9 @@ internal static Font GetSmallFont() } else { - if (currentFont == "Roboto") + if (currentFont == "Inter") { - s_SmallFont = EditorGUIUtility.LoadRequired("Fonts/roboto/Roboto-Small.ttf") as Font; + s_SmallFont = EditorGUIUtility.LoadRequired("Fonts/Inter/Inter-Small.ttf") as Font; } else if (currentFont == "Lucida Grande") { @@ -137,9 +134,9 @@ internal static Font GetBoldFont() } else { - if (currentFont == "Roboto") + if (currentFont == "Inter") { - s_BoldFont = EditorGUIUtility.LoadRequired("Fonts/roboto/Roboto-Bold.ttf") as Font; + s_BoldFont = EditorGUIUtility.LoadRequired("Fonts/Inter/Inter-Bold.ttf") as Font; } else if (currentFont == "Lucida Grande") { @@ -165,7 +162,7 @@ internal static List GetSupportedFonts() if (Application.platform == RuntimePlatform.WindowsEditor) { - s_SupportedFonts.Add("Segoe UI"); + s_SupportedFonts.Add("Verdana"); } foreach (var builtinFont in EditorResources.builtInFonts.Keys) @@ -188,7 +185,7 @@ internal static Dictionary builtInFonts { s_BuiltInFonts = new Dictionary { - ["Roboto"] = "Fonts/roboto/Roboto-Regular.ttf" + ["Inter"] = "Fonts/Inter/Inter-Regular.ttf" }; if (Application.platform != RuntimePlatform.WindowsEditor) @@ -230,36 +227,41 @@ private static List GetDefaultStyleCatalogPaths() return catalogFiles; } - [UsedImplicitly, RequiredByNativeCode] internal static void BuildCatalog() { - s_StyleCatalog = new StyleCatalog(); - s_RefreshGlobalStyleCatalog = false; + using (new PerformanceTracker(nameof(BuildCatalog))) + { + s_StyleCatalog = new StyleCatalog(); + s_RefreshGlobalStyleCatalog = false; - var paths = GetDefaultStyleCatalogPaths(); - foreach (var editorUssPath in AssetDatabase.FindAssets("t:StyleSheet").Select(AssetDatabase.GUIDToAssetPath).Where(IsEditorStyleSheet)) - paths.Add(editorUssPath); + var paths = GetDefaultStyleCatalogPaths(); + foreach (var editorUssPath in AssetDatabase.FindAssets("t:StyleSheet").Select(AssetDatabase.GUIDToAssetPath).Where(IsEditorStyleSheet)) + paths.Add(editorUssPath); - Console.WriteLine($"Building style catalogs ({paths.Count})\r\n\t{String.Join("\r\n\t", paths.ToArray())}"); - styleCatalog.Load(paths); + Console.WriteLine($"Building style catalogs ({paths.Count})\r\n\t{String.Join("\r\n\t", paths.ToArray())}"); + styleCatalog.Load(paths); + } } internal static void RefreshSkin() { - if (!CanEnableExtendedStyles()) - return; + using (new PerformanceTracker(nameof(RefreshSkin))) + { + if (!CanEnableExtendedStyles()) + return; - GUIStyle.onDraw = StylePainter.DrawStyle; + GUIStyle.onDraw = StylePainter.DrawStyle; - // Update gui skin style layouts - var skin = GUIUtility.GetDefaultSkin(); - if (skin != null) - { - // TODO: Emit OnStyleCatalogLoaded - if (Path.GetFileName(Path.GetDirectoryName(Application.dataPath)) == "editor_resources") - ConverterUtils.ResetSkinToPristine(skin, EditorGUIUtility.isProSkin ? SkinTarget.Dark : SkinTarget.Light); - skin.font = GetNormalFont(); - UpdateGUIStyleProperties(skin); + // Update gui skin style layouts + var skin = GUIUtility.GetDefaultSkin(); + if (skin != null) + { + // TODO: Emit OnStyleCatalogLoaded + if (Path.GetFileName(Path.GetDirectoryName(Application.dataPath)) == "editor_resources") + ConverterUtils.ResetSkinToPristine(skin, EditorGUIUtility.isProSkin ? SkinTarget.Dark : SkinTarget.Light); + skin.font = GetNormalFont(); + UpdateGUIStyleProperties(skin); + } } } @@ -303,7 +305,7 @@ private static void ResetDeprecatedBackgroundImage(GUIStyleState state) internal static void RefreshStyles() { Unsupported.ClearSkinCache(); - InternalEditorUtility.RequestScriptReload(); + EditorUtility.RequestScriptReload(); InternalEditorUtility.RepaintAllViews(); Debug.Log($"Style refreshed {DateTime.Now}"); } diff --git a/Editor/Mono/EditorSceneManager.cs b/Editor/Mono/EditorSceneManager.cs index 5ca3cadc69..4e22e647d5 100644 --- a/Editor/Mono/EditorSceneManager.cs +++ b/Editor/Mono/EditorSceneManager.cs @@ -11,9 +11,9 @@ namespace UnityEditor.SceneManagement { // Must match same enums in C++ - public enum OpenSceneMode { Single, Additive, AdditiveWithoutLoading }; - public enum NewSceneMode { Single, Additive }; - public enum NewSceneSetup { EmptyScene, DefaultGameObjects }; + public enum OpenSceneMode { Single, Additive, AdditiveWithoutLoading } + public enum NewSceneMode { Single, Additive } + public enum NewSceneSetup { EmptyScene, DefaultGameObjects } public sealed partial class EditorSceneManager : SceneManager { diff --git a/Editor/Mono/EditorWindow.cs b/Editor/Mono/EditorWindow.cs index 2d0c07136e..dd8a4c8aaa 100644 --- a/Editor/Mono/EditorWindow.cs +++ b/Editor/Mono/EditorWindow.cs @@ -359,9 +359,11 @@ public bool maximized } } - internal bool hasFocus { get { return m_Parent && m_Parent.actualView == this; } } + // Is EditorWindow focused? + public bool hasFocus { get { return m_Parent && m_Parent.actualView == this; } } - internal bool docked { get { return m_Parent != null && m_Parent.window != null && !m_Parent.window.IsNotDocked(); } } + // Is EditorWindow docked? + public bool docked { get { return m_Parent != null && m_Parent.window != null && !m_Parent.window.IsNotDocked(); } } // This property can be used to stop OS events from being sent to the EditorWindow internal bool disableInputEvents diff --git a/Editor/Mono/GI/LightingSettings.bindings.cs b/Editor/Mono/GI/LightingSettings.bindings.cs new file mode 100644 index 0000000000..abcb6acc8c --- /dev/null +++ b/Editor/Mono/GI/LightingSettings.bindings.cs @@ -0,0 +1,263 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using UnityEngine.Bindings; +using UnityEngine; + +namespace UnityEditor +{ + [NativeHeader("Runtime/Graphics/LightingSettings.h")] + [NativeClass(null)] + public sealed partial class LightingSettings : Object + { + public LightingSettings() + { + Internal_Create(this); + } + + private extern static void Internal_Create([Writable] LightingSettings self); + + internal void CreateAsset() + { + if (string.IsNullOrEmpty(name)) + { + name = "New Lighting Settings"; + } + + ProjectWindowUtil.CreateAsset(this, (name + ".lighting")); + } + + // Which baking backend is used. + public enum Lightmapper + { + // Lightmaps are baked by Enlighten + Enlighten = 0, + + // 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. + public enum Sampling + { + // Convergence testing is automatic, stops when lightmap has converged. + Auto = 0, + + // No convergence testing, always uses the given number of samples. + Fixed = 1 + } + + // Set the path tracer filter mode. + public enum FilterMode + { + // Do not filter. + None = 0, + + // Select settings for filtering automatically + Auto = 1, + + // Setup filtering manually + Advanced = 2 + } + + // Which path tracer denoiser is used. + public enum DenoiserType + { + // No denoiser + None = 0, + + // The NVIDIA Optix AI denoiser is applied. + Optix = 1, + + // The Intel Open Image AI denoiser is applied. + OpenImage = 2 + } + + // Which path tracer filter is used. + public enum FilterType + { + // A Gaussian filter is applied. + Gaussian = 0, + + // An A-Trous filter is applied. + ATrous = 1, + + // No filter + None = 2 + } + + [NativeName("GIWorkflowMode")] + internal extern Lightmapping.GIWorkflowMode giWorkflowMode { get; set; } + + public bool autoGenerate + { + get { return giWorkflowMode == Lightmapping.GIWorkflowMode.Iterative; } + set { giWorkflowMode = (value ? Lightmapping.GIWorkflowMode.Iterative : Lightmapping.GIWorkflowMode.OnDemand); } + } + + [NativeName("EnableBakedLightmaps")] + public extern bool bakedGI { get; set; } + + [NativeName("EnableRealtimeLightmaps")] + public extern bool realtimeGI { get; set; } + + [NativeName("RealtimeEnvironmentLighting")] + public extern bool realtimeEnvironmentLighting { get; set; } + + [NativeName("MixedBakeMode")] + public extern MixedLightingMode mixedBakeMode { get; set; } + + [NativeName("AlbedoBoost")] + public extern float albedoBoost { get; set; } + + [NativeName("BakeBackend")] + public extern Lightmapper lightmapper { get; set; } + + // The maximum size of an individual lightmap texture. + [NativeName("LightmapMaxSize")] + public extern int lightmapMaxSize { get; set; } + + // Static lightmap resolution in texels per world unit. + [NativeName("BakeResolution")] + public extern float lightmapResolution { get; set; } + + // Texel separation between shapes. + [NativeName("Padding")] + public extern int lightmapPadding { get; set; } + + // Whether to use DXT1 compression on the generated lightmaps. + [NativeName("TextureCompression")] + public extern bool compressLightmaps { get; set; } + + // Whether to apply ambient occlusion to the lightmap. + [NativeName("AO")] + public extern bool ao { get; set; } + + // Beyond this distance a ray is considered to be un-occluded. + [NativeName("AOMaxDistance")] + public extern float aoMaxDistance { get; set; } + + // Exponent for ambient occlusion on indirect lighting. + [NativeName("CompAOExponent")] + public extern float aoExponentIndirect { get; set; } + + // Exponent for ambient occlusion on direct lighting. + [NativeName("CompAOExponentDirect")] + public extern float aoExponentDirect { get; set; } + + // If we should write out AO to disk. Only works in On Demand bakes + [NativeName("ExtractAO")] + public extern bool extractAO { get; set; } + + [NativeName("LightmapsBakeMode")] + public extern LightmapsMode directionalityMode { get; set; } + + [NativeName("FilterMode")] + internal extern UnityEngine.FilterMode lightmapFilterMode { get; set; } + + public extern bool exportTrainingData { get; set; } + + public extern string trainingDataDestination { get; set; } + + // Realtime lightmap resolution in texels per world unit. Also used for indirect resolution when using baked GI. + [NativeName("RealtimeResolution")] + public extern float indirectResolution { get; set; } + + [NativeName("ForceWhiteAlbedo")] + internal extern bool realtimeForceWhiteAlbedo { get; set; } + + [NativeName("ForceUpdates")] + internal extern bool realtimeForceUpdates { get; set; } + + internal extern bool finalGather { get; set; } + + internal extern float finalGatherRayCount { get; set; } + + internal extern bool finalGatherFiltering { get; set; } + + [NativeName("PVRSampling")] + public extern Sampling sampling { get; set; } + + [NativeName("PVRDirectSampleCount")] + public extern int directSampleCount { get; set; } + + [NativeName("PVRSampleCount")] + public extern int indirectSampleCount { get; set; } + + // Amount of light bounce used for the path tracer. + [NativeName("PVRBounces")] + public extern int bounces { get; set; } + + // Is view prioritisation enabled? + [NativeName("PVRCulling")] + public extern bool prioritizeView { get; set; } + + // Which path tracer filtering mode is used. + [NativeName("PVRFilteringMode")] + public extern FilterMode filteringMode { get; set; } + + // Which path tracer denoiser is used for the direct light. + [NativeName("PVRDenoiserTypeDirect")] + public extern DenoiserType denoiserTypeDirect { get; set; } + + // Which path tracer denoiser is used for the indirect light. + [NativeName("PVRDenoiserTypeIndirect")] + public extern DenoiserType denoiserTypeIndirect { get; set; } + + // Which path tracer denoiser is used for ambient occlusion. + [NativeName("PVRDenoiserTypeAO")] + public extern DenoiserType denoiserTypeAO { get; set; } + + // Which path tracer filter is used for the direct light. + [NativeName("PVRFilterTypeDirect")] + public extern FilterType filterTypeDirect { get; set; } + + // Which path tracer filter is used for the indirect light. + [NativeName("PVRFilterTypeIndirect")] + public extern FilterType filterTypeIndirect { get; set; } + + // Which path tracer filter is used for ambient occlusion. + [NativeName("PVRFilterTypeAO")] + public extern FilterType filterTypeAO { get; set; } + + // Which radius is used for the direct light path tracer filter if gauss is chosen. + [NativeName("PVRFilteringGaussRadiusDirect")] + public extern int filteringGaussRadiusDirect { get; set; } + + // Which radius is used for the indirect light path tracer filter if gauss is chosen. + [NativeName("PVRFilteringGaussRadiusIndirect")] + public extern int filteringGaussRadiusIndirect { get; set; } + + // Which radius is used for AO path tracer filter if gauss is chosen. + [NativeName("PVRFilteringGaussRadiusAO")] + public extern int filteringGaussRadiusAO { get; set; } + + // Which position sigma is used for the direct light path tracer filter if Atrous is chosen. + [NativeName("PVRFilteringAtrousPositionSigmaDirect")] + public extern float filteringAtrousPositionSigmaDirect { get; set; } + + // Which position sigma is used for the indirect light path tracer filter if Atrous is chosen. + [NativeName("PVRFilteringAtrousPositionSigmaIndirect")] + public extern float filteringAtrousPositionSigmaIndirect { get; set; } + + // Which position sigma is used for AO path tracer filter if Atrous is chosen. + [NativeName("PVRFilteringAtrousPositionSigmaAO")] + public extern float filteringAtrousPositionSigmaAO { get; set; } + + // Whether to enable or disable environment multiple importance sampling + [NativeName("PVREnvironmentMIS")] + internal extern int environmentMIS { get; set; } + + // How many samples to use for environment sampling + [NativeName("PVREnvironmentSampleCount")] + public extern int environmentSampleCount { get; set; } + + // How many reference points to generate when using MIS + [NativeName("PVREnvironmentReferencePointCount")] + internal extern int environmentReferencePointCount { get; set; } + } +} diff --git a/Editor/Mono/GUI/AboutWindow.cs b/Editor/Mono/GUI/AboutWindow.cs index 945f7962c9..df817275d8 100644 --- a/Editor/Mono/GUI/AboutWindow.cs +++ b/Editor/Mono/GUI/AboutWindow.cs @@ -218,7 +218,7 @@ private void ListenForSecretCodes() bool enabled = !EditorPrefs.GetBool("DeveloperMode", false); EditorPrefs.SetBool("DeveloperMode", enabled); ShowNotification(new GUIContent(string.Format(L10n.Tr("Developer Mode {0}"), (enabled ? L10n.Tr("On") : L10n.Tr("Off"))))); - InternalEditorUtility.RequestScriptReload(); + EditorUtility.RequestScriptReload(); // Repaint all views to show/hide debug repaint indicator InternalEditorUtility.RepaintAllViews(); diff --git a/Editor/Mono/GUI/AnimatedValues.cs b/Editor/Mono/GUI/AnimatedValues.cs index 2811aa5c6c..6316a4f5d9 100644 --- a/Editor/Mono/GUI/AnimatedValues.cs +++ b/Editor/Mono/GUI/AnimatedValues.cs @@ -112,9 +112,7 @@ protected void StopAnim(T newValue) // If the new value is different, or we might be in the middle of a fade, we need to refresh. // Checking GetValue is not reliable on its own, since for e.g. bool it'll return the "closest" value, // but that doesn't mean the fade is done. - bool invoke = false; - if ((!newValue.Equals(GetValue()) || m_LerpPosition < 1) && valueChanged != null) - invoke = true; + bool invoke = (!newValue.Equals(GetValue()) || m_LerpPosition < 1) && valueChanged != null; m_Target = newValue; m_Start = newValue; diff --git a/Editor/Mono/GUI/AppStatusBar.cs b/Editor/Mono/GUI/AppStatusBar.cs index 1995ed7344..9cc38375e8 100644 --- a/Editor/Mono/GUI/AppStatusBar.cs +++ b/Editor/Mono/GUI/AppStatusBar.cs @@ -172,7 +172,7 @@ protected override void OldOnGUI() } else if (Unsupported.IsDeveloperMode()) { - GUI.Label(new Rect(progressBarHorizontalPosition - 200 - spacing, 0, 200, barHeight), m_MiniMemoryOverview, EditorStyles.progressBarText); + GUI.Label(new Rect(progressBarHorizontalPosition - 300 - spacing, 0, 300, barHeight), m_MiniMemoryOverview, EditorStyles.progressBarText); EditorGUIUtility.CleanCache(m_MiniMemoryOverview); } } diff --git a/Editor/Mono/GUI/DockArea.cs b/Editor/Mono/GUI/DockArea.cs index 8668e6d428..c51664a6ec 100644 --- a/Editor/Mono/GUI/DockArea.cs +++ b/Editor/Mono/GUI/DockArea.cs @@ -332,7 +332,6 @@ protected override void OldOnGUI() background = "dockarea"; Rect dockAreaRect = new Rect(0, 0, position.width, position.height); - Rect wPos = windowPosition; Rect containerWindowPosition = window.position; containerWindowPosition.width = Mathf.Ceil(containerWindowPosition.width); containerWindowPosition.height = Mathf.Ceil(containerWindowPosition.height); @@ -1077,7 +1076,9 @@ protected override void OldOnGUI() // Call reset GUI state as first thing so GUI.color is correct when drawing window decoration. EditorGUIUtility.ResetGUIState(); - Rect maximizedViewRect = position; + Rect maximizedViewRect = Rect.zero; + + maximizedViewRect.size = position.size; maximizedViewRect = Styles.background.margin.Remove(maximizedViewRect); Rect backRect = new Rect(maximizedViewRect.x + 1, maximizedViewRect.y, maximizedViewRect.width - 2, DockArea.kTabHeight); diff --git a/Editor/Mono/GUI/EditorApplicationLayout.cs b/Editor/Mono/GUI/EditorApplicationLayout.cs index af33df0b54..79d79e85c0 100644 --- a/Editor/Mono/GUI/EditorApplicationLayout.cs +++ b/Editor/Mono/GUI/EditorApplicationLayout.cs @@ -23,13 +23,13 @@ namespace UnityEditor { internal class EditorApplicationLayout { - static private PreviewEditorWindow m_PreviewWindow = null; + static private PlayModeView m_PlayModeView = null; static private bool m_MaximizePending = false; static internal bool IsInitializingPlaymodeLayout() { - return m_PreviewWindow != null; + return m_PlayModeView != null; } static internal void SetPlaymodeLayout() @@ -52,34 +52,34 @@ static internal void SetPausemodeLayout() static internal void InitPlaymodeLayout() { - m_PreviewWindow = WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(true) as PreviewEditorWindow; - if (m_PreviewWindow == null) + m_PlayModeView = WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(true) as PlayModeView; + if (m_PlayModeView == null) return; - if (m_PreviewWindow.maximizeOnPlay) + if (m_PlayModeView.maximizeOnPlay) { - DockArea da = m_PreviewWindow.m_Parent as DockArea; + DockArea da = m_PlayModeView.m_Parent as DockArea; if (da != null) m_MaximizePending = WindowLayout.MaximizePrepare(da.actualView); } - // Mark this preview window as the start preview so the backend - // can set size and mouseoffset properly for this preview - m_PreviewWindow.m_Parent.SetAsStartView(); - m_PreviewWindow.m_Parent.SetAsLastPlayModeView(); + // Mark this PlayModeView window as the start view so the backend + // can set size and mouseoffset properly for this view + m_PlayModeView.m_Parent.SetAsStartView(); + m_PlayModeView.m_Parent.SetAsLastPlayModeView(); Toolbar.RepaintToolbar(); } static internal void FinalizePlaymodeLayout() { - if (m_PreviewWindow != null) + if (m_PlayModeView != null) { if (m_MaximizePending) - WindowLayout.MaximizePresent(m_PreviewWindow); + WindowLayout.MaximizePresent(m_PlayModeView); - m_PreviewWindow.m_Parent.ClearStartView(); + m_PlayModeView.m_Parent.ClearStartView(); } Clear(); @@ -88,7 +88,7 @@ static internal void FinalizePlaymodeLayout() static private void Clear() { m_MaximizePending = false; - m_PreviewWindow = null; + m_PlayModeView = null; } } } // namespace diff --git a/Editor/Mono/GUI/EditorStyles.cs b/Editor/Mono/GUI/EditorStyles.cs index 6f760d6f53..a83ee44d26 100644 --- a/Editor/Mono/GUI/EditorStyles.cs +++ b/Editor/Mono/GUI/EditorStyles.cs @@ -5,6 +5,7 @@ using UnityEditor.Experimental; using UnityEditor.StyleSheets; using UnityEngine; +using UnityEngine.Internal; // See Style Guide in wiki for more information on editor styles. @@ -355,12 +356,14 @@ public sealed class EditorStyles // the list of editor styles to use private static EditorStyles[] s_CachedStyles = { null, null }; - internal static GUIStyle FromUSS(string ussStyleRuleName, string ussInPlaceStyleOverride = null) + [ExcludeFromDocs] + public static GUIStyle FromUSS(string ussStyleRuleName, string ussInPlaceStyleOverride = null) { return GUIStyleExtensions.FromUSS(ussStyleRuleName, ussInPlaceStyleOverride); } - internal static GUIStyle ApplyUSS(GUIStyle style, string ussStyleRuleName, string ussInPlaceStyleOverride = null) + [ExcludeFromDocs] + public static GUIStyle ApplyUSS(GUIStyle style, string ussStyleRuleName, string ussInPlaceStyleOverride = null) { return GUIStyleExtensions.ApplyUSS(style, ussStyleRuleName, ussInPlaceStyleOverride); } @@ -492,7 +495,7 @@ private void InitSharedStyles() { padding = new RectOffset( InspectorWindow.kInspectorPaddingLeft, - InspectorWindow.kInspectorPaddingRight, 0, 0) + InspectorWindow.kInspectorPaddingRight, InspectorWindow.kInspectorPaddingTop, 0) }; // For the full width margins, use padding from right side in both sides, diff --git a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs index 5f88d5e77f..3798200651 100644 --- a/Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs +++ b/Editor/Mono/GUI/FlexibleMenu/FlexibleMenuModifyItemUI.cs @@ -9,7 +9,7 @@ namespace UnityEditor { abstract class FlexibleMenuModifyItemUI : PopupWindowContent { - public enum MenuType { Add, Edit }; + public enum MenuType { Add, Edit } protected MenuType m_MenuType; public object m_Object; protected Action m_AcceptedCallback; diff --git a/Editor/Mono/GUI/FoldoutHeader.cs b/Editor/Mono/GUI/FoldoutHeader.cs index 564f1793b9..7b9bb0d12c 100644 --- a/Editor/Mono/GUI/FoldoutHeader.cs +++ b/Editor/Mono/GUI/FoldoutHeader.cs @@ -33,6 +33,7 @@ public static void EndFoldoutHeaderGroup() public sealed partial class EditorGUI { static bool s_FoldoutHeaderGroupActive; + private static readonly int s_FoldoutHeaderHash = "FoldoutHeader".GetHashCode(); public static bool BeginFoldoutHeaderGroup(Rect position, bool foldout, string content, [DefaultValue("EditorStyles.foldoutHeader")] GUIStyle style = null, Action menuAction = null, GUIStyle menuIcon = null) @@ -46,6 +47,7 @@ public static bool BeginFoldoutHeaderGroup(Rect position, bool foldout, GUIConte if (EditorGUIUtility.hierarchyMode) { position.xMin -= EditorStyles.inspectorDefaultMargins.padding.left - EditorStyles.inspectorDefaultMargins.padding.right; + position.xMax += EditorStyles.inspectorDefaultMargins.padding.right; } if (style == null) @@ -72,8 +74,22 @@ public static bool BeginFoldoutHeaderGroup(Rect position, bool foldout, GUIConte menuAction.Invoke(menuRect); Event.current.Use(); } + int id = GUIUtility.GetControlID(s_FoldoutHeaderHash, FocusType.Keyboard, position); - foldout = GUI.Toggle(position, foldout, content, style); + if (Event.current.type == EventType.KeyDown && GUIUtility.keyboardControl == id) + { + KeyCode kc = Event.current.keyCode; + if (kc == KeyCode.LeftArrow && foldout || (kc == KeyCode.RightArrow && foldout == false)) + { + foldout = !foldout; + GUI.changed = true; + Event.current.Use(); + } + } + else + { + foldout = EditorGUIInternal.DoToggleForward(position, id, foldout, content, style); + } // Menu icon if (menuAction != null && Event.current.type == EventType.Repaint) diff --git a/Editor/Mono/GUI/ListViewGUI.cs b/Editor/Mono/GUI/ListViewGUI.cs index 9e1d4eb3eb..f024303ef1 100644 --- a/Editor/Mono/GUI/ListViewGUI.cs +++ b/Editor/Mono/GUI/ListViewGUI.cs @@ -49,10 +49,11 @@ static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState s state.draggedTo = -1; state.fileNames = null; - if ((lvOptions & ListViewOptions.wantsReordering) != 0) ilvState.wantsReordering = true; - if ((lvOptions & ListViewOptions.wantsExternalFiles) != 0) ilvState.wantsExternalFiles = true; - if ((lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0) ilvState.wantsToStartCustomDrag = true; - if ((lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0) ilvState.wantsToAcceptCustomDrag = true; + ilvState.wantsReordering = (lvOptions & ListViewOptions.wantsReordering) != 0; + ilvState.wantsExternalFiles = (lvOptions & ListViewOptions.wantsExternalFiles) != 0; + ilvState.wantsToStartCustomDrag = (lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0; + ilvState.wantsToAcceptCustomDrag = (lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0; + ilvState.wantsRowMultiSelection = (lvOptions & ListViewOptions.wantsRowMultiSelection) != 0; return DoListView(GUILayoutUtility.GetRect(1, state.totalRows * state.rowHeight + 3), state, colWidths, string.Empty); } diff --git a/Editor/Mono/GUI/ListViewGUILayout.cs b/Editor/Mono/GUI/ListViewGUILayout.cs index 706c09d9e4..de94fdf056 100644 --- a/Editor/Mono/GUI/ListViewGUILayout.cs +++ b/Editor/Mono/GUI/ListViewGUILayout.cs @@ -44,10 +44,11 @@ static public ListViewShared.ListViewElementsEnumerator ListView(ListViewState s state.draggedTo = -1; state.fileNames = null; - if ((lvOptions & ListViewOptions.wantsReordering) != 0) state.ilvState.wantsReordering = true; - if ((lvOptions & ListViewOptions.wantsExternalFiles) != 0) state.ilvState.wantsExternalFiles = true; - if ((lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0) state.ilvState.wantsToStartCustomDrag = true; - if ((lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0) state.ilvState.wantsToAcceptCustomDrag = true; + state.ilvState.wantsReordering = (lvOptions & ListViewOptions.wantsReordering) != 0; + state.ilvState.wantsExternalFiles = (lvOptions & ListViewOptions.wantsExternalFiles) != 0; + state.ilvState.wantsToStartCustomDrag = (lvOptions & ListViewOptions.wantsToStartCustomDrag) != 0; + state.ilvState.wantsToAcceptCustomDrag = (lvOptions & ListViewOptions.wantsToAcceptCustomDrag) != 0; + state.ilvState.wantsRowMultiSelection = (lvOptions & ListViewOptions.wantsRowMultiSelection) != 0; return DoListView(state, null, dragTitle); } diff --git a/Editor/Mono/GUI/ListViewOptions.cs b/Editor/Mono/GUI/ListViewOptions.cs index f488faf3aa..349ad77d4a 100644 --- a/Editor/Mono/GUI/ListViewOptions.cs +++ b/Editor/Mono/GUI/ListViewOptions.cs @@ -4,5 +4,5 @@ namespace UnityEditor { - internal enum ListViewOptions { wantsReordering = 1, wantsExternalFiles = 2, wantsToStartCustomDrag = 4, wantsToAcceptCustomDrag = 8 }; + internal enum ListViewOptions { wantsReordering = 1, wantsExternalFiles = 2, wantsToStartCustomDrag = 4, wantsToAcceptCustomDrag = 8, wantsRowMultiSelection = 16 } } diff --git a/Editor/Mono/GUI/ListViewShared.cs b/Editor/Mono/GUI/ListViewShared.cs index fe40495b3d..c8ea934bbd 100644 --- a/Editor/Mono/GUI/ListViewShared.cs +++ b/Editor/Mono/GUI/ListViewShared.cs @@ -30,6 +30,7 @@ internal class InternalListViewState public bool wantsExternalFiles = false; public bool wantsToStartCustomDrag = false; public bool wantsToAcceptCustomDrag = false; + public bool wantsRowMultiSelection = false; public int dragItem; } @@ -117,6 +118,8 @@ internal static bool SendKey(InternalListViewState ilvState, KeyCode keyCode, in { var state = ilvState.state; + int previousRow = state.row; + //ilvState.state.row, ref ilvState.state.column, ref ilvState.state.scrollPos switch (keyCode) { @@ -172,15 +175,35 @@ internal static bool SendKey(InternalListViewState ilvState, KeyCode keyCode, in } break; } + case KeyCode.A: // must evade the return false and be handled by MultiSelection if needed + if (!(ilvState.wantsRowMultiSelection && EditorGUI.actionKey)) + return false; + break; default: return false; } - state.scrollPos = ListViewScrollToRow(ilvState, state.scrollPos, state.row); + if (ilvState.wantsRowMultiSelection) + MultiSelection(ilvState, previousRow); // scrollPos is set during MultiSelection + else + state.scrollPos = ListViewScrollToRow(ilvState, state.scrollPos, state.row); Event.current.Use(); return true; } + internal static void MultiSelection(InternalListViewState ilvState, int previousRow) + { + var state = ilvState.state; + + // initializing and updating the array if needed + if (state.selectedItems == null) + state.selectedItems = new bool[state.totalRows]; + else if (state.selectedItems.Length != state.totalRows) + System.Array.Resize(ref state.selectedItems, state.totalRows); + + MultiSelection(ilvState, previousRow, state.row, ref state.initialRow, ref state.selectedItems); + } + static internal bool HasMouseDown(InternalListViewState ilvState, Rect r) { return HasMouseDown(ilvState, r, 0); @@ -233,12 +256,24 @@ static internal bool MultiSelection(InternalListViewState ilvState, int prevSele if ((shiftIsDown || ctrlIsDown) && (initialSelected == -1)) initialSelected = prevSelected; + // Select all : Ctrl + A + bool selectAll = ctrlIsDown && Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.A; + int prevInitialSelected = initialSelected; + if (selectAll) + { + shiftIsDown = true; + + initialSelected = selectedItems.Length - 1; + currSelected = 0; + } + // multi selection if (shiftIsDown) { int from = System.Math.Min(initialSelected, currSelected); int to = System.Math.Max(initialSelected, currSelected); + // shift only: remove the items not between the initial and the current if (!ctrlIsDown) { for (int i = 0; i < from; i++) @@ -260,7 +295,7 @@ static internal bool MultiSelection(InternalListViewState ilvState, int prevSele if (from < 0) from = to; - + // select the items between the initial and the current for (int i = from; i <= to; i++) { if (!selectedItems[i]) @@ -292,6 +327,9 @@ static internal bool MultiSelection(InternalListViewState ilvState, int prevSele selectedItems[currSelected] = true; } + if (selectAll) // revert the value + initialSelected = prevInitialSelected; + if (ilvState != null) ilvState.state.scrollPos = ListViewScrollToRow(ilvState, currSelected); @@ -376,11 +414,15 @@ public bool MoveNext() { if (ListViewShared.HasMouseDown(ilvState, rect)) { + var previousRow = ilvState.state.row; ilvState.state.selectionChanged = true; ilvState.state.row = yPos; ilvState.state.column = xPos; ilvState.state.scrollPos = ListViewShared.ListViewScrollToRow(ilvState, yPos); // this is about clicking on a row that is partially visible + if (ilvState.wantsRowMultiSelection) + MultiSelection(ilvState, previousRow); + if ((ilvState.wantsReordering || ilvState.wantsToStartCustomDrag) && (GUIUtility.hotControl == ilvState.state.ID)) { DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), ilvState.state.ID); diff --git a/Editor/Mono/GUI/ListViewState.cs b/Editor/Mono/GUI/ListViewState.cs index 5126afd108..6582e62bb1 100644 --- a/Editor/Mono/GUI/ListViewState.cs +++ b/Editor/Mono/GUI/ListViewState.cs @@ -12,6 +12,8 @@ internal class ListViewState { const int c_rowHeight = 16; //TODO: public int row; + public bool[] selectedItems; + public int initialRow = -1; public int column; public Vector2 scrollPos; public int totalRows; diff --git a/Editor/Mono/GUI/MainView.cs b/Editor/Mono/GUI/MainView.cs index 1f41368a2a..cf3be9b500 100644 --- a/Editor/Mono/GUI/MainView.cs +++ b/Editor/Mono/GUI/MainView.cs @@ -10,7 +10,7 @@ internal class MainView : View, ICleanuppable { const float kStatusbarHeight = 20; - private static readonly Vector2 kMinSize = new Vector2(950, 300); + private static readonly Vector2 kMinSize = new Vector2(875, 300); private static readonly Vector2 kMaxSize = new Vector2(10000, 10000); void OnEnable() @@ -23,22 +23,36 @@ protected override void SetPosition(Rect newPos) base.SetPosition(newPos); if (children.Length == 0) return; - Toolbar t = (Toolbar)children[0]; - children[0].position = new Rect(0, 0, newPos.width, t.CalcHeight()); if (children.Length > 2) { + // toolbar - dock area view - status bar + Toolbar t = (Toolbar)children[0]; + children[0].position = new Rect(0, 0, newPos.width, t.CalcHeight()); children[1].position = new Rect(0, t.CalcHeight(), newPos.width, newPos.height - t.CalcHeight() - children[2].position.height); children[2].position = new Rect(0, newPos.height - children[2].position.height, newPos.width, children[2].position.height); } + else + { + // dock area view - status bar + children[0].position = new Rect(0, 0, newPos.width, newPos.height - children[1].position.height); + children[1].position = new Rect(0, newPos.height - children[1].position.height, newPos.width, children[1].position.height); + } } protected override void ChildrenMinMaxChanged() { - if (children.Length == 3) + if (children.Length == 3 && children[0] is Toolbar) { + // toolbar - dock area view - status bar Toolbar t = (Toolbar)children[0]; - var min = new Vector2(kMinSize.x, Mathf.Max(kMinSize.y, t.CalcHeight() + kStatusbarHeight + children[1].minSize.y)); - SetMinMaxSizes(min, kMaxSize); + var min = new Vector2(minSize.x, Mathf.Max(minSize.y, t.CalcHeight() + kStatusbarHeight + children[1].minSize.y)); + SetMinMaxSizes(min, maxSize); + } + else if (children.Length == 2) + { + // dock area view - status bar + var min = new Vector2(minSize.x, Mathf.Max(minSize.y, kStatusbarHeight + children[1].minSize.y)); + SetMinMaxSizes(min, maxSize); } base.ChildrenMinMaxChanged(); } @@ -65,7 +79,7 @@ public void Cleanup() // If we only have one child left, this means all views have been dragged out. // So we resize the window to be just the toolbar // On windows, this might need some special handling for the main menu - if (children[1].children.Length == 0) + if (children.Length == 3 && children[1].children.Length == 0) { Rect r = window.position; Toolbar t = (Toolbar)children[0]; diff --git a/Editor/Mono/GUI/ObjectField.cs b/Editor/Mono/GUI/ObjectField.cs index 8d543d952a..689d798617 100644 --- a/Editor/Mono/GUI/ObjectField.cs +++ b/Editor/Mono/GUI/ObjectField.cs @@ -86,6 +86,41 @@ static private Rect GetButtonRect(ObjectFieldVisualType visualType, Rect positio } } + static bool HasValidScript(UnityEngine.Object obj) + { + MonoScript script = MonoScript.FromScriptedObject(obj); + if (script == null) + { + return false; + } + Type type = script.GetClass(); + if (type == null) + { + return false; + } + return true; + } + + static bool ValidDroppedObject(Object[] references, System.Type objType, SerializedProperty property, out string errorString) + { + errorString = ""; + if (references == null || references.Length == 0) + { + return true; + } + + var reference = references[0]; + Object obj = EditorUtility.InstanceIDToObject(reference.GetInstanceID()); + if (obj is MonoBehaviour || obj is ScriptableObject) + { + if (!HasValidScript(obj)) + { + errorString = $"Type cannot be found: {reference.GetType()}. Containing file and class name must match."; + } + } + return true; + } + internal static Object DoObjectField(Rect position, Rect dropRect, int id, Object obj, System.Type objType, SerializedProperty property, ObjectFieldValidator validator, bool allowSceneObjects, GUIStyle style) { if (validator == null) @@ -122,6 +157,17 @@ internal static Object DoObjectField(Rect position, Rect dropRect, int id, Objec case EventType.DragUpdated: case EventType.DragPerform: + if (eventType == EventType.DragPerform) + { + string errorString; + if (!ValidDroppedObject(DragAndDrop.objectReferences, objType, property, out errorString)) + { + Object reference = DragAndDrop.objectReferences[0]; + EditorUtility.DisplayDialog("Can't assign script", errorString, "OK"); + break; + } + } + if (dropRect.Contains(Event.current.mousePosition) && GUI.enabled) { Object[] references = DragAndDrop.objectReferences; diff --git a/Editor/Mono/GUI/PackageExportTreeView.cs b/Editor/Mono/GUI/PackageExportTreeView.cs index 155a48a7bb..14d8a223c6 100644 --- a/Editor/Mono/GUI/PackageExportTreeView.cs +++ b/Editor/Mono/GUI/PackageExportTreeView.cs @@ -25,7 +25,7 @@ public enum EnabledState None = 0, All = 1, Mixed = 2 - }; + } private PackageExport m_PackageExport; diff --git a/Editor/Mono/GUI/PackageImportTreeView.cs b/Editor/Mono/GUI/PackageImportTreeView.cs index 633a8438d1..3c9a6d289b 100644 --- a/Editor/Mono/GUI/PackageImportTreeView.cs +++ b/Editor/Mono/GUI/PackageImportTreeView.cs @@ -25,7 +25,7 @@ public enum EnabledState None = 0, All = 1, Mixed = 2 - }; + } private PackageImport m_PackageImport; diff --git a/Editor/Mono/GUI/ReorderableList.cs b/Editor/Mono/GUI/ReorderableList.cs index 300ef3d086..34dfabe574 100644 --- a/Editor/Mono/GUI/ReorderableList.cs +++ b/Editor/Mono/GUI/ReorderableList.cs @@ -163,7 +163,7 @@ public void DoAddButton(ReorderableList list) if (elementType == typeof(string)) list.index = list.list.Add(""); else if (elementType != null && elementType.GetConstructor(Type.EmptyTypes) == null) - Debug.LogError("Cannot add element. Type " + elementType.ToString() + " has no default constructor. Implement a default constructor or implement your own add behaviour."); + Debug.LogError("Cannot add element. Type " + elementType + " has no default constructor. Implement a default constructor or implement your own add behaviour."); else if (list.list.GetType().GetGenericArguments()[0] != null) list.index = list.list.Add(Activator.CreateInstance(list.list.GetType().GetGenericArguments()[0])); else if (elementType != null) diff --git a/Editor/Mono/GUI/SplitView.cs b/Editor/Mono/GUI/SplitView.cs index c4abe998e4..e396550914 100644 --- a/Editor/Mono/GUI/SplitView.cs +++ b/Editor/Mono/GUI/SplitView.cs @@ -639,7 +639,6 @@ public void Cleanup() } ic.Cleanup(); } - return; } else { diff --git a/Editor/Mono/GUI/Toolbar.cs b/Editor/Mono/GUI/Toolbar.cs index afcfa91635..0495e65995 100644 --- a/Editor/Mono/GUI/Toolbar.cs +++ b/Editor/Mono/GUI/Toolbar.cs @@ -200,8 +200,7 @@ void ReserveWidthRight(float width, ref Rect pos) protected override void OldOnGUI() { - const float space = 10; - const float largeSpace = 20; + const float space = 8; const float standardButtonWidth = 32; const float dropdownWidth = 80; const float playPauseStopWidth = 140; @@ -222,12 +221,12 @@ protected override void OldOnGUI() ReserveWidthRight(standardButtonWidth * s_ShownToolIcons.Length, ref pos); DoToolButtons(EditorToolGUI.GetThickArea(pos)); - ReserveWidthRight(largeSpace, ref pos); + ReserveWidthRight(space, ref pos); int playModeControlsStart = Mathf.RoundToInt((position.width - playPauseStopWidth) / 2); pos.x += pos.width; - pos.width = (playModeControlsStart - pos.x) - largeSpace; + pos.width = (playModeControlsStart - pos.x) - space; DoToolSettings(EditorToolGUI.GetThickArea(pos)); // Position centered controls. @@ -286,7 +285,7 @@ protected override void OldOnGUI() subToolbar.OnGUI(EditorToolGUI.GetThinArea(pos)); } - if (ModeService.modeCount > 1 && Unsupported.IsDeveloperBuild()) + if (Unsupported.IsDeveloperBuild() && ModeService.hasSwitchableModes) { EditorGUI.BeginChangeCheck(); ReserveWidthLeft(space, ref pos); diff --git a/Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs index b262019563..bb91d1b807 100644 --- a/Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs +++ b/Editor/Mono/GUI/TreeView/AssetsTreeViewDataSource.cs @@ -11,6 +11,7 @@ using UnityEngine; using UnityEditorInternal; using UnityEditor.Experimental; +using AssetReference = UnityEditorInternal.InternalEditorUtility.AssetReference; namespace UnityEditor { @@ -61,6 +62,50 @@ public AssetsTreeViewDataSource(TreeViewController treeView, int rootInstanceID) m_rootInstanceID = rootInstanceID; } + public override List GetNewSelection(TreeViewItem clickedItem, TreeViewSelectState selectState) + { + var assetTreeClickedItem = clickedItem as IAssetTreeViewItem; + var clickedEntry = new AssetReference() { instanceID = clickedItem.id }; + if (clickedItem.id == 0 && assetTreeClickedItem != null) + clickedEntry.guid = assetTreeClickedItem.Guid; + + // Get ids from items + var visibleRows = GetRows(); + var allIDs = new List(visibleRows.Count); + var allGuids = new List(visibleRows.Count); + + for (int i = 0; i < visibleRows.Count; ++i) + { + int instanceID = visibleRows[i].id; + string guid = null; + if (instanceID == 0) + { + var assetTreeViewItem = visibleRows[i] as IAssetTreeViewItem; + if (assetTreeViewItem != null) + guid = assetTreeViewItem.Guid; + } + + allGuids.Add(guid); + allIDs.Add(instanceID); + } + + List selectedIDs = selectState.selectedIDs; + int lastClickedID = selectState.lastClickedID; + bool allowMultiselection = CanBeMultiSelected(clickedItem); + + var result = InternalEditorUtility.GetNewSelection(ref clickedEntry, allIDs, allGuids, selectedIDs, lastClickedID, selectState.keepMultiSelection, selectState.useShiftAsActionKey, allowMultiselection); + + clickedItem.id = clickedEntry.instanceID; + + for (int i = 0; i < allIDs.Count; ++i) + { + if (allGuids[i] != null && allIDs[i] != 0) + visibleRows[i].id = allIDs[i]; + } + + return result; + } + static string CreateDisplayName(int instanceID) { return Path.GetFileNameWithoutExtension(AssetDatabase.GetAssetPath(instanceID)); @@ -119,7 +164,6 @@ public override void FetchData() } m_Rows = new List(m_Roots.Count * 256); - Texture2D emptyFolderIcon = EditorGUIUtility.FindTexture(EditorResources.emptyFolderIconName); Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName); var assetsInstanceIDs = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID("Assets"); var projectPath = Path.GetFileName(Directory.GetCurrentDirectory()); @@ -131,6 +175,7 @@ public override void FetchData() var rootInstanceID = root.instanceID; var displayName = root.displayName ?? CreateDisplayName(rootInstanceID); var rootPath = root.path ?? AssetDatabase.GetAssetPath(rootInstanceID); + var rootGuid = AssetDatabase.AssetPathToGUID(rootPath); var property = new HierarchyProperty(rootPath); if (!root.skipValidation && !property.Find(rootInstanceID, null)) @@ -165,7 +210,7 @@ public override void FetchData() // Create root item TreeView item if (subDepth > 0) - rootItem = new FolderTreeItem(rootInstanceID, rootDepth, parentItem, displayName); + rootItem = new FolderTreeItem(rootGuid, rootInstanceID, rootDepth, parentItem, displayName); else rootItem = new RootTreeItem(rootInstanceID, rootDepth, parentItem, displayName); rootItem.icon = folderIcon; @@ -195,14 +240,11 @@ public override void FetchData() depth = property.depth - minDepth; TreeViewItem item; if (property.isFolder) - item = new FolderTreeItem(property.instanceID, depth + subDepth, null, property.name); + item = new FolderTreeItem(property.guid, property.instanceID, depth + subDepth, null, property.name); else - item = new NonFolderTreeItem(property.instanceID, depth + subDepth, null, property.name); + item = new NonFolderTreeItem(property.guid, property.GetInstanceIDIfImported(), depth + subDepth, null, property.name); - if (property.isFolder && !property.hasChildren) - item.icon = emptyFolderIcon; - else - item.icon = property.icon; + item.icon = property.icon; if (property.hasChildren) { @@ -473,25 +515,52 @@ public int Compare(TreeViewItem x, TreeViewItem y) } // Classes used for type checking - internal class RootTreeItem : TreeViewItem + internal interface IAssetTreeViewItem + { + string Guid { get; } + } + + internal abstract class FolderTreeItemBase : TreeViewItem + { + protected FolderTreeItemBase(int id, int depth, TreeViewItem parent, string displayName) + : base(id, depth, parent, displayName) + { + } + } + + internal class RootTreeItem : FolderTreeItemBase { public RootTreeItem(int id, int depth, TreeViewItem parent, string displayName) : base(id, depth, parent, displayName) { } } - class FolderTreeItem : TreeViewItem + internal class PackageTreeItem : FolderTreeItemBase { - public FolderTreeItem(int id, int depth, TreeViewItem parent, string displayName) + public PackageTreeItem(int id, int depth, TreeViewItem parent, string displayName) : base(id, depth, parent, displayName) { } } - class NonFolderTreeItem : TreeViewItem + + internal class FolderTreeItem : FolderTreeItemBase, IAssetTreeViewItem + { + public string Guid { get; } + + public FolderTreeItem(string guid, int id, int depth, TreeViewItem parent, string displayName) + : base(id, depth, parent, displayName) + { + Guid = guid; + } + } + + class NonFolderTreeItem : TreeViewItem, IAssetTreeViewItem { - public NonFolderTreeItem(int id, int depth, TreeViewItem parent, string displayName) + public string Guid { get; } + public NonFolderTreeItem(string guid, int id, int depth, TreeViewItem parent, string displayName) : base(id, depth, parent, displayName) { + Guid = guid; } } } diff --git a/Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs b/Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs index a2e7afe610..84577e4451 100644 --- a/Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs +++ b/Editor/Mono/GUI/TreeView/AssetsTreeViewGUI.cs @@ -8,6 +8,7 @@ using UnityEditorInternal.VersionControl; using UnityEditor.VersionControl; using System.Collections.Generic; +using UnityEditor.Experimental; using UnityEngine.Assertions; namespace UnityEditor @@ -17,6 +18,17 @@ internal class AssetsTreeViewGUI : TreeViewGUI static bool s_VCEnabled; const float k_IconOverlayPadding = 7f; + internal static ScalableGUIContent s_OpenFolderIcon = new ScalableGUIContent(null, null, EditorResources.openedFolderIconName); + + internal static Texture2D openFolderTexture + { + get + { + GUIContent folderContent = s_OpenFolderIcon; + return folderContent.image as Texture2D; + } + } + internal delegate void OnAssetIconDrawDelegate(Rect iconRect, string guid); internal static event OnAssetIconDrawDelegate postAssetIconDrawCallback = null; @@ -134,6 +146,14 @@ protected override Texture GetIconForItem(TreeViewItem item) string path = AssetDatabase.GetAssetPath(item.id); icon = AssetDatabase.GetCachedIcon(path); } + + AssetsTreeViewDataSource.FolderTreeItemBase folderItem = item as AssetsTreeViewDataSource.FolderTreeItemBase; + + if (folderItem != null && m_TreeView.data.IsExpanded(folderItem)) + { + icon = openFolderTexture; + } + return icon; } diff --git a/Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs index c64838a2dc..d8486cfc8b 100644 --- a/Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs +++ b/Editor/Mono/GUI/TreeView/ITreeViewDataSource.cs @@ -64,6 +64,7 @@ internal interface ITreeViewDataSource // Selection bool CanBeMultiSelected(TreeViewItem item); bool CanBeParent(TreeViewItem item); + List GetNewSelection(TreeViewItem clickedItem, TreeViewSelectState selectState); // Renaming bool IsRenamingItemAllowed(TreeViewItem item); diff --git a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs b/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs index 94199e0b84..211dc1d487 100644 --- a/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs +++ b/Editor/Mono/GUI/TreeView/TreeViewControl/TreeViewControl.cs @@ -250,6 +250,11 @@ protected TreeViewItem FindItem(int id, TreeViewItem searchFromThisItem) return TreeViewUtility.FindItem(id, searchFromThisItem); } + protected int FindRowOfItem(TreeViewItem item) + { + return GetRows().IndexOf(item); + } + protected void GetFirstAndLastVisibleRows(out int firstRowVisible, out int lastRowVisible) { m_GUI.GetFirstAndLastRowVisible(out firstRowVisible, out lastRowVisible); @@ -744,7 +749,7 @@ void ValidateOverriddenMethods(TreeView treeView) Debug.LogError(type.Name + ": If you are overriding SetupDragAndDrop you should also override CanStartDrag (to allow dragging)."); } } - }; + } // Nested because they are used by protected methods protected struct RowGUIArgs diff --git a/Editor/Mono/GUI/TreeView/TreeViewController.cs b/Editor/Mono/GUI/TreeView/TreeViewController.cs index 8132a7119b..25c28c6559 100644 --- a/Editor/Mono/GUI/TreeView/TreeViewController.cs +++ b/Editor/Mono/GUI/TreeView/TreeViewController.cs @@ -9,7 +9,6 @@ using UnityEngine; using UnityEditorInternal; - namespace UnityEditor.IMGUI.Controls { /* @@ -59,6 +58,14 @@ internal virtual void OnAwake() } } + internal struct TreeViewSelectState + { + public List selectedIDs; + public int lastClickedID; + public bool keepMultiSelection; + public bool useShiftAsActionKey; + } + internal class TreeViewController { public System.Action selectionChangedCallback { get; set; } // ids @@ -110,6 +117,7 @@ internal class TreeViewController bool m_HadFocusLastEvent; // Cached from last event for keyboard focus changed event int m_KeyboardControlID; + const double kSlowSelectTimeout = 0.2; const float kSpaceForScrollBar = 16f; public TreeViewItem hoveredItem { get; set; } @@ -201,7 +209,7 @@ public bool IsSelected(int id) public bool HasSelection() { - return state.selectedIDs.Count() > 0; + return state.selectedIDs.Count > 0; } public int[] GetSelection() @@ -333,13 +341,16 @@ public void HandleUnusedMouseEventsForItem(Rect rect, TreeViewItem item, int row } else { - var dragSelection = GetNewSelection(item, true, false); - bool canStartDrag = dragging != null && dragSelection.Count != 0 && dragging.CanStartDrag(item, dragSelection, Event.current.mousePosition); + double selectStartTime = Time.realtimeSinceStartup; + var dragSelection = GetNewSelection(item, true, false); + bool dragAbortedBySlowSelect = (Time.realtimeSinceStartup - selectStartTime) > kSlowSelectTimeout; + + bool canStartDrag = !dragAbortedBySlowSelect && dragging != null && dragSelection.Count != 0 && dragging.CanStartDrag(item, dragSelection, Event.current.mousePosition); if (canStartDrag) { // Prepare drag and drop delay (we start the drag after a couple of pixels mouse drag: See the case MouseDrag below) m_DragSelection = dragSelection; - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), itemControlID); + DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), GetItemControlID(item)); delay.mouseDownPosition = Event.current.mousePosition; } else @@ -357,7 +368,7 @@ public void HandleUnusedMouseEventsForItem(Rect rect, TreeViewItem item, int row itemSingleClickedCallback(item.id); } - GUIUtility.hotControl = itemControlID; + GUIUtility.hotControl = GetItemControlID(item); } evt.Use(); } @@ -606,13 +617,16 @@ public void OnGUI(Rect rect, int keyboardControlID) gui.EndRowGUI(); + // Keep inside clip region so callbacks that might want to get + // rects of rows have correct context. + KeyboardGUI(); + if (m_UseScrollView) GUI.EndScrollView(showingVerticalScrollBar); else GUI.EndClip(); HandleUnusedEvents(); - KeyboardGUI(); // Call after iterating rows since selecting a row takes keyboard focus HandleTreeViewGotFocus(isMouseDownInTotalRect); @@ -1135,17 +1149,15 @@ List GetNewSelection(TreeViewItem clickedItem, bool keepMultiSelection, boo { if (getNewSelectionOverride != null) return getNewSelectionOverride(clickedItem, keepMultiSelection, useShiftAsActionKey); - // Get ids from items - var visibleRows = data.GetRows(); - List allIDs = new List(visibleRows.Count); - for (int i = 0; i < visibleRows.Count; ++i) - allIDs.Add(visibleRows[i].id); - List selectedIDs = state.selectedIDs; - int lastClickedID = state.lastClickedID; - bool allowMultiselection = data.CanBeMultiSelected(clickedItem); + var selectState = new TreeViewSelectState() { + selectedIDs = state.selectedIDs, + lastClickedID = state.lastClickedID, + keepMultiSelection = keepMultiSelection, + useShiftAsActionKey = useShiftAsActionKey + }; - return InternalEditorUtility.GetNewSelection(clickedItem.id, allIDs, selectedIDs, lastClickedID, keepMultiSelection, useShiftAsActionKey, allowMultiselection); + return data.GetNewSelection(clickedItem, selectState); } void SelectionByKey(TreeViewItem itemSelected) diff --git a/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs b/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs index e7932ba3b2..4c0c9d6b46 100644 --- a/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs +++ b/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEditorInternal; namespace UnityEditor.IMGUI.Controls { @@ -349,6 +350,19 @@ virtual public bool CanBeParent(TreeViewItem item) return true; } + virtual public List GetNewSelection(TreeViewItem clickedItem, TreeViewSelectState selectState) + { + // Get ids from items + var visibleRows = GetRows(); + List allIDs = new List(visibleRows.Count); + for (int i = 0; i < visibleRows.Count; ++i) + allIDs.Add(visibleRows[i].id); + + bool allowMultiselection = CanBeMultiSelected(clickedItem); + + return InternalEditorUtility.GetNewSelection(clickedItem.id, allIDs, selectState.selectedIDs, selectState.lastClickedID, selectState.keepMultiSelection, selectState.useShiftAsActionKey, allowMultiselection); + } + virtual public void OnExpandedStateChanged() { if (m_TreeView.expandedStateChanged != null) diff --git a/Editor/Mono/GUI/WindowLayout.cs b/Editor/Mono/GUI/WindowLayout.cs index a299c80203..93dfc45fe9 100644 --- a/Editor/Mono/GUI/WindowLayout.cs +++ b/Editor/Mono/GUI/WindowLayout.cs @@ -174,8 +174,11 @@ static WindowLayout() { EditorApplication.delayCall += () => { - ReloadWindowLayoutMenu(); - EditorUtility.Internal_UpdateAllMenus(); + if (ModeService.HasCapability(ModeCapability.LayoutWindowMenu, true)) + { + ReloadWindowLayoutMenu(); + EditorUtility.Internal_UpdateAllMenus(); + } }; } @@ -250,14 +253,14 @@ internal static EditorWindow TryGetLastFocusedWindowInSameDock() if (windowTypeName != "") type = Type.GetType(windowTypeName); - // Also get the Preview Window - var previewWindow = PreviewEditorWindow.GetMainPreviewWindow(); - if (type != null && previewWindow && previewWindow.m_Parent != null && previewWindow.m_Parent is DockArea) + // Also get the PlayModeView Window + var playModeView = PlayModeView.GetMainPlayModeView(); + if (type != null && playModeView && playModeView != null && playModeView.m_Parent is DockArea) { // Get all windows of that type object[] potentials = Resources.FindObjectsOfTypeAll(type); - DockArea dock = previewWindow.m_Parent as DockArea; + DockArea dock = playModeView.m_Parent as DockArea; // Find the one that is actually docked together with the GameView for (int i = 0; i < potentials.Length; i++) @@ -295,14 +298,14 @@ internal static EditorWindow TryFocusAppropriateWindow(bool enteringPlaymode) { if (enteringPlaymode) { - var previewWindow = PreviewEditorWindow.GetMainPreviewWindow(); - if (previewWindow) + var playModeView = PlayModeView.GetMainPlayModeView(); + if (playModeView) { - SaveCurrentFocusedWindowInSameDock(previewWindow); - previewWindow.Focus(); + SaveCurrentFocusedWindowInSameDock(playModeView); + playModeView.Focus(); } - return previewWindow; + return playModeView; } else { @@ -820,10 +823,10 @@ public static bool LoadWindowLayout(string path, bool newProjectLayoutWasCreated containerWindow.Show(containerWindow.showMode, loadPosition: false, displayImmediately: true, setFocus: true); } - // Unmaximize maximized Preview window if maximize on play is enabled - PreviewEditorWindow preview = GetMaximizedWindow() as PreviewEditorWindow; - if (preview != null && preview.maximizeOnPlay) - Unmaximize(preview); + // Unmaximize maximized PlayModeView window if maximize on play is enabled + PlayModeView playModeView = GetMaximizedWindow() as PlayModeView; + if (playModeView != null && playModeView.maximizeOnPlay) + Unmaximize(playModeView); } catch (Exception ex) { diff --git a/Editor/Mono/GameView/GameView.cs b/Editor/Mono/GameView/GameView.cs index 8e081d8a98..14d37c34cb 100644 --- a/Editor/Mono/GameView/GameView.cs +++ b/Editor/Mono/GameView/GameView.cs @@ -30,7 +30,7 @@ Floating GameView in separate window namespace UnityEditor { [EditorWindowTitle(title = "Game", useTypeNameAsIconName = true)] - internal class GameView : PreviewEditorWindow, IHasCustomMenu, IGameViewSizeMenuUser + internal class GameView : PlayModeView, IHasCustomMenu, IGameViewSizeMenuUser { const int kScaleSliderMinWidth = 30; const int kScaleSliderMaxWidth = 150; @@ -102,7 +102,7 @@ static Styles() gameViewBackgroundStyle = "GameViewBackground"; renderdocContent = EditorGUIUtility.TrIconContent("renderdoc", UnityEditor.RenderDocUtil.openInRenderDocLabel); } - }; + } static double s_LastScrollTime; @@ -110,7 +110,7 @@ public GameView() { autoRepaintOnSceneChange = true; InitializeZoomArea(); - previewName = "GameView"; + playModeViewName = "GameView"; clearColor = kClearBlack; showGizmos = m_Gizmos; targetDisplay = 0; @@ -292,7 +292,7 @@ public void OnDisable() [UsedImplicitly] // This is here because NGUI uses it via reflection (noted in https://confluence.hq.unity3d.com/display/DEV/Game+View+Bucket) internal static Vector2 GetSizeOfMainGameView() { - return GetMainPreviewTargetSize(); + return GetMainPlayModeViewTargetSize(); } private void UpdateZoomAreaAndParent() @@ -666,7 +666,7 @@ public void RenderToHMDOnly() showGizmos = false; renderIMGUI = false; - m_RenderTexture = RenderPreview(mousePos, clearTexture: false); + m_RenderTexture = RenderView(mousePos, clearTexture: false); } private void OnPlayModeStateChanged(PlayModeStateChange state) @@ -772,8 +772,9 @@ private void OnGUI() clearColor = kClearBlack; renderIMGUI = true; - if (!EditorApplication.isPlaying || (EditorApplication.isPlaying && Time.frameCount % OnDemandRendering.GetRenderFrameInterval() == 0)) - m_RenderTexture = RenderPreview(gameMousePosition, clearTexture); + if (!EditorApplication.isPlaying || (EditorApplication.isPlaying && Time.frameCount % OnDemandRendering.renderFrameInterval == 0)) + m_RenderTexture = RenderView(gameMousePosition, clearTexture); + if (m_TargetClamped) Debug.LogWarningFormat("GameView reduced to a reasonable size for this system ({0}x{1})", targetSize.x, targetSize.y); EditorGUIUtility.SetupWindowSpaceAndVSyncInternal(GUIClip.Unclip(viewInWindow)); diff --git a/Editor/Mono/GameView/GameViewSize.cs b/Editor/Mono/GameView/GameViewSize.cs index ce5c9e3855..c138ca1470 100644 --- a/Editor/Mono/GameView/GameViewSize.cs +++ b/Editor/Mono/GameView/GameViewSize.cs @@ -11,7 +11,7 @@ internal enum GameViewSizeType { AspectRatio, FixedResolution - }; + } [Serializable] internal class GameViewSize diff --git a/Editor/Mono/Grids/GridShortcuts.cs b/Editor/Mono/Grids/GridShortcuts.cs index 0e90989232..a886feecdf 100644 --- a/Editor/Mono/Grids/GridShortcuts.cs +++ b/Editor/Mono/Grids/GridShortcuts.cs @@ -43,7 +43,6 @@ internal static void ResetGridSize() internal static void MenuNudgePerspectiveBackward() { SceneView sv = SceneView.lastActiveSceneView; - SceneViewGrid.Grid grid = sv.sceneViewGrids.activeGrid; SceneViewGrid.GridRenderAxis axis = sv.sceneViewGrids.gridAxis; Vector3 v = sv.sceneViewGrids.GetPivot(axis); switch (axis) @@ -67,7 +66,6 @@ internal static void MenuNudgePerspectiveBackward() internal static void MenuNudgePerspectiveForward() { SceneView sv = SceneView.lastActiveSceneView; - SceneViewGrid.Grid grid = sv.sceneViewGrids.activeGrid; SceneViewGrid.GridRenderAxis axis = sv.sceneViewGrids.gridAxis; Vector3 v = sv.sceneViewGrids.GetPivot(axis); switch (axis) diff --git a/Editor/Mono/HandleUtility.cs b/Editor/Mono/HandleUtility.cs index b04f6926b0..b61ad6f5cc 100644 --- a/Editor/Mono/HandleUtility.cs +++ b/Editor/Mono/HandleUtility.cs @@ -378,7 +378,7 @@ internal static float DistanceToPolyLineOnPlane(Vector3[] points, Vector3 center float enter; if (!p.Raycast(r, out enter)) - return -1; + return DistanceToPolyLine(points); Vector3 intersect = r.GetPoint(enter); diff --git a/Editor/Mono/Handles.cs b/Editor/Mono/Handles.cs index 2afcfafcf2..490c976a3a 100644 --- a/Editor/Mono/Handles.cs +++ b/Editor/Mono/Handles.cs @@ -332,11 +332,11 @@ public static void DrawWireCube(Vector3 center, Vector3 size) public static bool ShouldRenderGizmos() { - var preview = PreviewEditorWindow.GetRenderingPreview(); + var playModeView = PlayModeView.GetRenderingView(); SceneView sv = SceneView.currentDrawingSceneView; - if (preview != null) - return preview.IsShowingGizmos(); + if (playModeView != null) + return playModeView.IsShowingGizmos(); if (sv != null) return sv.drawGizmos; @@ -1311,10 +1311,10 @@ internal static Rect GetCameraRect(Rect position) return cameraRect; } - // Get the size of the main preview window + // Get the size of the main playModeView window public static Vector2 GetMainGameViewSize() { - return PreviewEditorWindow.GetMainPreviewTargetSize(); + return PlayModeView.GetMainPlayModeViewTargetSize(); } // Clears the camera. diff --git a/Editor/Mono/Hardware.bindings.cs b/Editor/Mono/Hardware.bindings.cs new file mode 100644 index 0000000000..b11a72526b --- /dev/null +++ b/Editor/Mono/Hardware.bindings.cs @@ -0,0 +1,128 @@ +// Unity C# 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 UnityEditor.Hardware +{ + [RequiredByNativeCode(GenerateProxy = true)] + [StructLayout(LayoutKind.Sequential)] + public struct UsbDevice + { + readonly public int vendorId; + readonly public int productId; + readonly public int revision; + readonly public string udid; + readonly public string name; + + public override string ToString() + { + return name + " (udid:" + udid + ", vid: " + vendorId.ToString("X4") + ", pid: " + productId.ToString("X4") + ", rev: " + revision.ToString("X4") + ")"; + } + } + + public sealed class Usb + { + public delegate void OnDevicesChangedHandler(UsbDevice[] devices); + + public static event OnDevicesChangedHandler DevicesChanged; + + [RequiredByNativeCode] + public static void OnDevicesChanged(UsbDevice[] devices) + { + if ((DevicesChanged != null) && (devices != null)) + DevicesChanged(devices); + } + } + + // Keep in sync with DevDeviceState enum in DevDevice.h + public enum DevDeviceState + { + Disconnected = 0, + Connected = 1, + } + + // Keep in sync with DevDeviceFeatures enum in DevDevice.h + [Flags] + public enum DevDeviceFeatures + { + None = 0, + PlayerConnection = 1 << 0, + RemoteConnection = 1 << 1, + } + + [RequiredByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public partial struct DevDevice + { + readonly public string id; + readonly public string name; + readonly public string type; + readonly public string module; + readonly public DevDeviceState state; + readonly public DevDeviceFeatures features; + + public bool isConnected { get { return state == DevDeviceState.Connected; } } + + public static DevDevice none { get { return new DevDevice("None", "None", "none", "internal", DevDeviceState.Disconnected, DevDeviceFeatures.None); } } + + public override string ToString() + { + return name + " (id:" + id + ", type: " + type + ", module: " + module + ", state: " + state + ", features: " + features + ")"; + } + + public DevDevice(string id, string name, string type, string module, DevDeviceState state, DevDeviceFeatures features) + { + this.id = id; + this.name = name; + this.type = type; + this.module = module; + this.state = state; + this.features = features; + } + } + + [NativeHeader("Editor/Src/Devices/DevDevice.h")] + public sealed class DevDeviceList + { + public delegate void OnChangedHandler(); + public static event OnChangedHandler Changed; + + public static void OnChanged() + { + if (Changed != null) + Changed(); + } + + public static bool FindDevice(string deviceId, out DevDevice device) + { + foreach (var d in GetDevices()) + { + if (d.id == deviceId) + { + device = d; + return true; + } + } + + device = new DevDevice(); + return false; + } + + internal static void Update(string target, DevDevice[] devices) + { + UpdateInternal(target, devices); + OnChanged(); + } + + [FreeFunction("GetDeviceList")] + public static extern DevDevice[] GetDevices(); + + [FreeFunction("UpdateDeviceList")] + internal static extern void UpdateInternal(string target, DevDevice[] devices); + } +} diff --git a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs index b307c51f52..effc6d66f7 100644 --- a/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs +++ b/Editor/Mono/ImportSettings/DesktopPluginImporterExtension.cs @@ -18,7 +18,7 @@ internal enum DesktopPluginCPUArchitecture AnyCPU, x86, x86_64 - }; + } internal class DesktopSingleCPUProperty : Property { diff --git a/Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs b/Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs index d6866b0f13..94002a718b 100644 --- a/Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs +++ b/Editor/Mono/ImportSettings/EditorPluginImporterExtension.cs @@ -19,7 +19,7 @@ internal enum EditorPluginCPUArchitecture AnyCPU, x86, x86_64 - }; + } internal enum EditorPluginOSArchitecture { @@ -27,7 +27,7 @@ internal enum EditorPluginOSArchitecture OSX, Windows, Linux - }; + } internal class EditorProperty : Property { diff --git a/Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs b/Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs index bf2a469f15..bf42097c5e 100644 --- a/Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs +++ b/Editor/Mono/ImportSettings/SpeedTreeImporterInspector.cs @@ -149,7 +149,7 @@ private void GenerateMaterials() } bool doGenerate = true; - if (paths.Count() > 0) + if (paths.Count > 0) doGenerate = Provider.PromptAndCheckoutIfNeeded(paths.ToArray(), String.Format("Materials will be checked out in:\n{0}", String.Join("\n", matFolders.ToArray()))); if (doGenerate) diff --git a/Editor/Mono/ImportSettings/SpeedTreeImporterModelEditor.cs b/Editor/Mono/ImportSettings/SpeedTreeImporterModelEditor.cs index abfa2245b5..1ec32f1938 100644 --- a/Editor/Mono/ImportSettings/SpeedTreeImporterModelEditor.cs +++ b/Editor/Mono/ImportSettings/SpeedTreeImporterModelEditor.cs @@ -42,7 +42,7 @@ private class Styles public static GUIContent ApplyAndGenerate = EditorGUIUtility.TrTextContent("Apply & Generate Materials", "Apply current importer settings and generate materials with new settings."); public static GUIContent Regenerate = EditorGUIUtility.TrTextContent("Regenerate Materials", "Regenerate materials from the current importer settings."); - }; + } private SerializedProperty m_LODSettings; private SerializedProperty m_EnableSmoothLOD; diff --git a/Editor/Mono/ImportSettings/TextureImporterInspector.cs b/Editor/Mono/ImportSettings/TextureImporterInspector.cs index 277a7f420a..461d48057d 100644 --- a/Editor/Mono/ImportSettings/TextureImporterInspector.cs +++ b/Editor/Mono/ImportSettings/TextureImporterInspector.cs @@ -25,7 +25,7 @@ public enum TextureImporterCubemapConvolution Specular = 1, // Convolve for diffuse-only reflection (irradiance cubemap). Diffuse = 2 - }; + } // Kept for backward compatibility public enum TextureImporterRGBMMode @@ -58,6 +58,7 @@ private enum TextureInspectorGUIElement CubeMapping = 1 << 9, StreamingMipmaps = 1 << 10, SingleChannelComponent = 1 << 11, + PngGamma = 1 << 12 } private struct TextureInspectorTypeGUIProperties @@ -355,6 +356,8 @@ internal class Styles public readonly GUIContent psdRemoveMatteURLButton = EditorGUIUtility.TrTextContent("How to handle PSD with alpha"); public readonly string psdRemoveMatteURL = "https://docs.unity3d.com/Manual/HOWTO-alphamaps.html"; + public readonly GUIContent ignorePngGamma = EditorGUIUtility.TrTextContent("Ignore PNG file gamma", "Ignore the Gamma value attribute in PNG files, this setting has no effect on other file formats."); + public Styles() { // This is far from ideal, but it's better than having tons of logic in the GUI code itself. @@ -435,6 +438,7 @@ void EnumPopup(SerializedProperty property, System.Type type, GUIContent label) SerializedProperty m_SpriteGenerateFallbackPhysicsShape; SerializedProperty m_AlphaIsTransparency; + SerializedProperty m_IgnorePngGamma; SerializedProperty m_PSDRemoveMatte; SerializedProperty m_TextureShape; @@ -497,6 +501,7 @@ void CacheSerializedProperties() m_SpriteGenerateFallbackPhysicsShape = serializedObject.FindProperty("m_SpriteGenerateFallbackPhysicsShape"); m_AlphaIsTransparency = serializedObject.FindProperty("m_AlphaIsTransparency"); + m_IgnorePngGamma = serializedObject.FindProperty("m_IgnorePngGamma"); m_PSDRemoveMatte = serializedObject.FindProperty("m_PSDRemoveMatte"); m_TextureType = serializedObject.FindProperty("m_TextureType"); @@ -518,32 +523,32 @@ void InitializeGUI() // TODO: Maybe complement the bitfield with a list to add a concept of order in the display. Not sure if necessary... TextureImporterShape shapeCapsAll = TextureImporterShape.Texture2D | TextureImporterShape.TextureCube; - m_TextureTypeGUIElements[(int)TextureImporterType.Default] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.ColorSpace | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.CubeMapConvolution | TextureInspectorGUIElement.CubeMapping, + m_TextureTypeGUIElements[(int)TextureImporterType.Default] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.ColorSpace | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.CubeMapConvolution | TextureInspectorGUIElement.CubeMapping, TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.StreamingMipmaps , shapeCapsAll); - m_TextureTypeGUIElements[(int)TextureImporterType.NormalMap] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.NormalMap | TextureInspectorGUIElement.CubeMapping, + m_TextureTypeGUIElements[(int)TextureImporterType.NormalMap] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.NormalMap | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.CubeMapping, TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.StreamingMipmaps , shapeCapsAll); m_TextureTypeGUIElements[(int)TextureImporterType.Sprite] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.Sprite, - TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.ColorSpace, + TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.ColorSpace, TextureImporterShape.Texture2D); - m_TextureTypeGUIElements[(int)TextureImporterType.Cookie] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.Cookie | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.CubeMapping, + m_TextureTypeGUIElements[(int)TextureImporterType.Cookie] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.Cookie | TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.CubeMapping, TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, TextureImporterShape.Texture2D | TextureImporterShape.TextureCube); - m_TextureTypeGUIElements[(int)TextureImporterType.SingleChannel] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.SingleChannelComponent | TextureInspectorGUIElement.CubeMapping, + m_TextureTypeGUIElements[(int)TextureImporterType.SingleChannel] = new TextureInspectorTypeGUIProperties(TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.SingleChannelComponent | TextureInspectorGUIElement.CubeMapping, TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.StreamingMipmaps , shapeCapsAll); m_TextureTypeGUIElements[(int)TextureImporterType.GUI] = new TextureInspectorTypeGUIProperties(0, - TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, + TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, TextureImporterShape.Texture2D); m_TextureTypeGUIElements[(int)TextureImporterType.Cursor] = new TextureInspectorTypeGUIProperties(0, - TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, + TextureInspectorGUIElement.AlphaHandling | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps, TextureImporterShape.Texture2D); m_TextureTypeGUIElements[(int)TextureImporterType.Lightmap] = new TextureInspectorTypeGUIProperties(0, - TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.MipMaps + TextureInspectorGUIElement.PowerOfTwo | TextureInspectorGUIElement.Readable | TextureInspectorGUIElement.PngGamma | TextureInspectorGUIElement.MipMaps | TextureInspectorGUIElement.StreamingMipmaps , TextureImporterShape.Texture2D); @@ -553,6 +558,7 @@ void InitializeGUI() m_GUIElementMethods.Add(TextureInspectorGUIElement.StreamingMipmaps, this.StreamingMipmapsGUI); m_GUIElementMethods.Add(TextureInspectorGUIElement.ColorSpace, this.ColorSpaceGUI); m_GUIElementMethods.Add(TextureInspectorGUIElement.AlphaHandling, this.AlphaHandlingGUI); + m_GUIElementMethods.Add(TextureInspectorGUIElement.PngGamma, this.PngGammaGUI); m_GUIElementMethods.Add(TextureInspectorGUIElement.MipMaps, this.MipMapGUI); m_GUIElementMethods.Add(TextureInspectorGUIElement.NormalMap, this.BumpGUI); m_GUIElementMethods.Add(TextureInspectorGUIElement.Sprite, this.SpriteGUI); @@ -567,6 +573,7 @@ void InitializeGUI() m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Cookie); m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.ColorSpace); m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.AlphaHandling); + m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.PngGamma); m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.SingleChannelComponent); m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.NormalMap); m_GUIElementsDisplayOrder.Add(TextureInspectorGUIElement.Sprite); @@ -647,6 +654,7 @@ void SetSerializedPropertySettings(TextureImporterSettings settings) m_Aniso.intValue = settings.aniso; m_AlphaIsTransparency.intValue = settings.alphaIsTransparency ? 1 : 0; + m_IgnorePngGamma.boolValue = settings.ignorePngGamma; m_TextureType.intValue = (int)settings.textureType; m_TextureShape.intValue = (int)settings.textureShape; @@ -767,6 +775,9 @@ internal TextureImporterSettings GetSerializedPropertySettings(TextureImporterSe if (!m_SingleChannelComponent.hasMultipleDifferentValues) settings.singleChannelComponent = (TextureImporterSingleChannelComponent)m_SingleChannelComponent.intValue; + if (!m_IgnorePngGamma.hasMultipleDifferentValues) + settings.ignorePngGamma = m_IgnorePngGamma.boolValue; + return settings; } @@ -1055,6 +1066,11 @@ void MipMapGUI(TextureInspectorGUIElement guiElements) EditorGUILayout.EndFadeGroup(); } + void PngGammaGUI(TextureInspectorGUIElement guiElements) + { + EditorGUILayout.PropertyField(m_IgnorePngGamma); + } + void BumpGUI(TextureInspectorGUIElement guiElements) { EditorGUI.BeginChangeCheck(); @@ -1213,7 +1229,7 @@ public override void OnInspectorGUI() showAdvanced = true; int iteratedTextureType = (int)m_TextureTypes[0]; TextureInspectorGUIElement firstAdvancedElements = m_TextureTypeGUIElements[iteratedTextureType].advancedElements; - for (int selectionIndex = 1; selectionIndex < m_TextureTypes.Count(); selectionIndex++) + for (int selectionIndex = 1; selectionIndex < m_TextureTypes.Count; selectionIndex++) { iteratedTextureType = (int)m_TextureTypes[selectionIndex]; if (firstAdvancedElements != m_TextureTypeGUIElements[iteratedTextureType].advancedElements) diff --git a/Editor/Mono/Inspector/AnimationClipEditor.cs b/Editor/Mono/Inspector/AnimationClipEditor.cs index 083203825a..00263dcc54 100644 --- a/Editor/Mono/Inspector/AnimationClipEditor.cs +++ b/Editor/Mono/Inspector/AnimationClipEditor.cs @@ -1664,7 +1664,7 @@ public EventModificationContextMenuObject(AnimationClipInfoProperties info, floa m_Index = index; m_Selected = selected; } - }; + } public void EventLineContextMenuAdd(object obj) { @@ -1730,7 +1730,7 @@ public void Draw(Rect window) EditorGUI.indentLevel--; - if (m_InstantTooltipText != null && m_InstantTooltipText != "") + if (!string.IsNullOrEmpty(m_InstantTooltipText)) { // Draw body of tooltip GUIStyle style = (GUIStyle)"AnimationEventTooltip"; diff --git a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs b/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs index f963fd1cf1..e81b09d005 100644 --- a/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs +++ b/Editor/Mono/Inspector/AssemblyDefinitionImporterInspector.cs @@ -41,6 +41,8 @@ internal class Styles public static readonly GUIContent loadError = EditorGUIUtility.TrTextContent("Load error"); public static readonly GUIContent expressionOutcome = EditorGUIUtility.TrTextContent("Expression outcome", "Shows the mathematical equation that your Expression represents."); public static readonly GUIContent noEngineReferences = EditorGUIUtility.TrTextContent("No Engine References", "When enabled, references to UnityEngine/UnityEditor will not be added when compiling this assembly."); + public static readonly GUIContent validDefineConstraint = new GUIContent(EditorGUIUtility.FindTexture("TestPassed"), L10n.Tr("Define constraint is valid.")); + public static readonly GUIContent invalidDefineConstraint = new GUIContent(EditorGUIUtility.FindTexture("TestFailed"), L10n.Tr("Define constraint is invalid.")); } GUIStyle m_TextStyle; @@ -51,14 +53,6 @@ internal class DefineConstraint public string name; } - [Serializable] - internal class VersionDefine - { - public string name; - public string expression; - public string define; - } - [Serializable] internal class AssemblyDefinitionReference { @@ -92,10 +86,7 @@ internal class PrecompiledReference class AssemblyDefinitionState : ScriptableObject { - public string path - { - get { return AssetDatabase.GetAssetPath(asset); } - } + public string path => AssetDatabase.GetAssetPath(asset); public string assemblyName; public AssemblyDefinitionAsset asset; @@ -113,6 +104,7 @@ public string path } SemVersionRangesFactory m_SemVersionRanges; + ReorderableList m_ReferencesList; ReorderableList m_PrecompiledReferencesList; ReorderableList m_VersionDefineList; @@ -130,7 +122,7 @@ public string path string[] m_Defines; Exception initializeException; - public override bool showImportedObject { get { return false; } } + public override bool showImportedObject => false; public override void OnEnable() { @@ -147,6 +139,20 @@ public override void OnEnable() m_CompatibleWithAnyPlatform = extraDataSerializedObject.FindProperty("compatibleWithAnyPlatform"); m_PlatformCompatibility = extraDataSerializedObject.FindProperty("platformCompatibility"); m_NoEngineReferences = extraDataSerializedObject.FindProperty("noEngineReferences"); + AssemblyReloadEvents.afterAssemblyReload += AfterAssemblyReload; + } + + public override void OnDisable() + { + base.OnDisable(); + AssemblyReloadEvents.afterAssemblyReload -= AfterAssemblyReload; + } + + void AfterAssemblyReload() + { + var selector = (ObjectSelector)WindowLayout.FindEditorWindowOfType(typeof(ObjectSelector)); + if (selector != null && selector.hasFocus) + selector.Close(); } public override void OnInspectorGUI() @@ -160,7 +166,7 @@ public override void OnInspectorGUI() extraDataSerializedObject.Update(); - var platforms = Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms(); + var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms(); using (new EditorGUI.DisabledScope(false)) { if (targets.Length > 1) @@ -187,6 +193,32 @@ public override void OnInspectorGUI() GUILayout.Space(10f); GUILayout.Label(Styles.defineConstraints, EditorStyles.boldLabel); + if (m_DefineConstraints.serializedProperty.arraySize > 0) + { + var defineConstraintsValid = true; + for (var i = 0; i < m_DefineConstraints.serializedProperty.arraySize && defineConstraintsValid; ++i) + { + var defineConstraint = m_DefineConstraints.serializedProperty.GetArrayElementAtIndex(i).FindPropertyRelative("name").stringValue; + if (!DefineConstraintsHelper.IsDefineConstraintValid(m_Defines, defineConstraint)) + { + defineConstraintsValid = false; + } + } + var constraintValidityRect = new Rect(GUILayoutUtility.GetLastRect()); + constraintValidityRect.x += constraintValidityRect.width - 23; + if (defineConstraintsValid) + { + constraintValidityRect.width = Styles.validDefineConstraint.image.width; + constraintValidityRect.height = Styles.validDefineConstraint.image.height; + EditorGUI.LabelField(constraintValidityRect, Styles.validDefineConstraint); + } + else + { + constraintValidityRect.width = Styles.invalidDefineConstraint.image.width; + constraintValidityRect.height = Styles.invalidDefineConstraint.image.height; + EditorGUI.LabelField(constraintValidityRect, Styles.invalidDefineConstraint); + } + } m_DefineConstraints.DoLayoutList(); GUILayout.Label(Styles.references, EditorStyles.boldLabel); @@ -311,7 +343,7 @@ protected override void Apply() static void InversePlatformCompatibility(AssemblyDefinitionState state) { - var platforms = Compilation.CompilationPipeline.GetAssemblyDefinitionPlatforms(); + var platforms = CompilationPipeline.GetAssemblyDefinitionPlatforms(); for (int i = 0; i < platforms.Length; ++i) state.platformCompatibility[i] = !state.platformCompatibility[i]; } @@ -332,7 +364,7 @@ protected override void InitializeExtraDataInstance(Object extraTarget, int targ { try { - LoadAssemblyDefintionState((AssemblyDefinitionState)extraTarget, ((AssetImporter)targets[targetIndex]).assetPath); + LoadAssemblyDefinitionState((AssemblyDefinitionState)extraTarget, ((AssetImporter)targets[targetIndex]).assetPath); initializeException = null; } catch (Exception e) @@ -378,9 +410,9 @@ private void DrawDefineConstraintListElement(Rect rect, int index, bool isactive rect.height -= EditorGUIUtility.standardVerticalSpacing; - var textFieldRect = new Rect(rect.x, rect.y + 1, rect.width - ReorderableList.Defaults.dragHandleWidth, rect.height); + var textFieldRect = new Rect(rect.x, rect.y + 1, rect.width - ReorderableList.Defaults.dragHandleWidth + 1, rect.height); - var validRect = new Rect(rect.width + ReorderableList.Defaults.dragHandleWidth + 1, rect.y + 1, ReorderableList.Defaults.dragHandleWidth, rect.height); + var constraintValidityRect = new Rect(rect.width + ReorderableList.Defaults.dragHandleWidth + ReorderableList.Defaults.dragHandleWidth / 2f - Styles.invalidDefineConstraint.image.width / 2f, rect.y , ReorderableList.Defaults.dragHandleWidth, rect.height); string noValue = L10n.Tr("(Missing)"); @@ -392,9 +424,18 @@ private void DrawDefineConstraintListElement(Rect rect, int index, bool isactive if (m_Defines != null) { - EditorGUI.BeginDisabled(true); - EditorGUI.Toggle(validRect, DefineConstraintsHelper.IsDefineConstraintValid(m_Defines, defineConstraint.stringValue)); - EditorGUI.EndDisabled(); + if (DefineConstraintsHelper.IsDefineConstraintValid(m_Defines, defineConstraint.stringValue)) + { + constraintValidityRect.width = Styles.validDefineConstraint.image.width; + constraintValidityRect.height = Styles.validDefineConstraint.image.height; + EditorGUI.LabelField(constraintValidityRect, Styles.validDefineConstraint); + } + else + { + constraintValidityRect.width = Styles.invalidDefineConstraint.image.width; + constraintValidityRect.height = Styles.invalidDefineConstraint.image.height; + EditorGUI.LabelField(constraintValidityRect, Styles.invalidDefineConstraint); + } } if (!string.IsNullOrEmpty(textFieldValue) && textFieldValue != noValue) @@ -545,7 +586,7 @@ static void AddPrecompiledReferenceListElement(ReorderableList list) newProp.FindPropertyRelative("fileName").stringValue = string.Empty; } - static void LoadAssemblyDefintionState(AssemblyDefinitionState state, string path) + static void LoadAssemblyDefinitionState(AssemblyDefinitionState state, string path) { var asset = AssetDatabase.LoadAssetAtPath(path); if (asset == null) @@ -584,20 +625,7 @@ static void LoadAssemblyDefintionState(AssemblyDefinitionState state, string pat { foreach (var versionDefine in data.versionDefines) { - if (!SymbolNameRestrictions.IsValid(versionDefine.define)) - { - var exception = new AssemblyDefinitionException($"Invalid version define {versionDefine.define}", path); - Debug.LogException(exception, asset); - } - else - { - state.versionDefines.Add(new VersionDefine - { - name = versionDefine.name, - expression = versionDefine.expression, - define = versionDefine.define, - }); - } + state.versionDefines.Add(versionDefine); } } @@ -645,7 +673,7 @@ static void LoadAssemblyDefintionState(AssemblyDefinitionState state, string pat } catch (AssemblyDefinitionException e) { - UnityEngine.Debug.LogException(e, asset); + Debug.LogException(e, asset); state.references.Add(new AssemblyDefinitionReference()); } } @@ -742,20 +770,13 @@ static void SaveAssemblyDefinitionState(AssemblyDefinitionState state) .Select(r => r.name) .ToArray(); - data.versionDefines = state.versionDefines.Select(x => new UnityEditor.Scripting.ScriptCompilation.VersionDefine - { - name = x.name, - expression = x.expression, - define = x.define, - }).ToArray(); - + data.versionDefines = state.versionDefines.ToArray(); data.autoReferenced = state.autoReferenced; data.overrideReferences = state.overrideReferences; data.precompiledReferences = state.precompiledReferences .Select(r => r.name).ToArray(); - data.allowUnsafeCode = state.allowUnsafeCode; data.noEngineReferences = state.noEngineReferences; diff --git a/Editor/Mono/Inspector/AssetStoreAssetInspector.cs b/Editor/Mono/Inspector/AssetStoreAssetInspector.cs index a5822314f3..c9627d795e 100644 --- a/Editor/Mono/Inspector/AssetStoreAssetInspector.cs +++ b/Editor/Mono/Inspector/AssetStoreAssetInspector.cs @@ -185,9 +185,9 @@ public override void OnInspectorGUI() { EditorGUILayout.LabelField("Name", info == null ? "-" : info.packageName); EditorGUILayout.LabelField("Version", info == null ? "-" : info.packageVersion); - string price = info == null ? "-" : (activeAsset.price != null && activeAsset.price != "" ? activeAsset.price : "free"); + string price = info == null ? "-" : (!string.IsNullOrEmpty(activeAsset.price) ? activeAsset.price : "free"); EditorGUILayout.LabelField("Price", price); - string rating = info != null && info.packageRating >= 0 ? info.packageRating.ToString() + " of 5" : "-"; + string rating = info != null && info.packageRating >= 0 ? info.packageRating + " of 5" : "-"; EditorGUILayout.LabelField("Rating", rating); EditorGUILayout.LabelField("Size", info == null ? "-" : intToSizeString(info.packageSize)); string assetCount = info != null && info.packageAssetCount >= 0 ? info.packageAssetCount.ToString() : "-"; diff --git a/Editor/Mono/Inspector/AudioClipInspector.cs b/Editor/Mono/Inspector/AudioClipInspector.cs index d41ad1cbdf..3eb5c19eef 100644 --- a/Editor/Mono/Inspector/AudioClipInspector.cs +++ b/Editor/Mono/Inspector/AudioClipInspector.cs @@ -272,7 +272,7 @@ public override void OnPreviewGUI(Rect r, GUIStyle background) if (c > 1 && r.width > 64) { var labelRect = new Rect(s_WantedRect.x + 5, s_WantedRect.y + (s_WantedRect.height / c) * i, 30, 20); - EditorGUI.DropShadowLabel(labelRect, "ch " + (i + 1).ToString()); + EditorGUI.DropShadowLabel(labelRect, "ch " + (i + 1)); } } @@ -309,12 +309,12 @@ public override string GetInfoString() { AudioClip clip = target as AudioClip; int c = AudioUtil.GetChannelCount(clip); - string ch = c == 1 ? "Mono" : c == 2 ? "Stereo" : (c - 1).ToString() + ".1"; + string ch = c == 1 ? "Mono" : c == 2 ? "Stereo" : (c - 1) + ".1"; AudioCompressionFormat platformFormat = AudioUtil.GetTargetPlatformSoundCompressionFormat(clip); AudioCompressionFormat editorFormat = AudioUtil.GetSoundCompressionFormat(clip); string s = platformFormat.ToString(); if (platformFormat != editorFormat) - s += " (" + editorFormat.ToString() + " in editor" + ")"; + s += " (" + editorFormat + " in editor" + ")"; s += ", " + AudioUtil.GetFrequency(clip) + " Hz, " + ch + ", "; System.TimeSpan ts = new System.TimeSpan(0, 0, 0, 0, (int)AudioUtil.GetDuration(clip)); diff --git a/Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs b/Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs index f959e5132f..7a7630724b 100644 --- a/Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs +++ b/Editor/Mono/Inspector/Avatar/AvatarAutoMapper.cs @@ -773,7 +773,6 @@ private void EvaluateBoneMatch(BoneMatch match, bool confirmedChoice) // Best best child matches bool sameAsParentOrChild = (match.bone == match.humanBoneParent.bone); - int childCount = 0; if (childMatchesLists.Count > 0) { SimpleProfiler.Begin("GetBestChildMatches"); @@ -788,7 +787,6 @@ private void EvaluateBoneMatch(BoneMatch match, bool confirmedChoice) EvaluateBoneMatch(childMatch, confirmedChoice); // Transfer info from best child match to parent - childCount++; match.score += childMatch.score; if (kDebug) match.debugTracker.AddRange(childMatch.debugTracker); diff --git a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs b/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs index 0a401c9782..5a9313b2fb 100644 --- a/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs +++ b/Editor/Mono/Inspector/Avatar/AvatarMappingEditor.cs @@ -22,7 +22,7 @@ public enum BoneState InvalidHierarchy, BoneLenghtIsZero, Valid - }; + } [System.Serializable] internal class AvatarMappingEditor : AvatarSubEditor diff --git a/Editor/Mono/Inspector/AvatarMaskInspector.cs b/Editor/Mono/Inspector/AvatarMaskInspector.cs index 2e01ae3b9d..f3172b3db5 100644 --- a/Editor/Mono/Inspector/AvatarMaskInspector.cs +++ b/Editor/Mono/Inspector/AvatarMaskInspector.cs @@ -139,7 +139,7 @@ protected static void DoPicking(Rect rect, SerializedProperty bodyMask, int coun for (int i = 0; i < count && !atLeastOneSelected; i++) { - atLeastOneSelected = bodyMask.GetArrayElementAtIndex(i).intValue == 1 ? true : false; + atLeastOneSelected = bodyMask.GetArrayElementAtIndex(i).intValue == 1; } for (int i = 0; i < count; i++) @@ -675,7 +675,7 @@ private void InitTreeView() private class SerializedNodeInfo : ToggleTreeViewItem { - public enum State { Disabled, Enabled, Invalid }; + public enum State { Disabled, Enabled, Invalid } public State m_State; // SerializedProperties diff --git a/Editor/Mono/Inspector/BillboardAssetInspector.cs b/Editor/Mono/Inspector/BillboardAssetInspector.cs index 86c5a5c904..3df671ffda 100644 --- a/Editor/Mono/Inspector/BillboardAssetInspector.cs +++ b/Editor/Mono/Inspector/BillboardAssetInspector.cs @@ -38,7 +38,7 @@ private class GUIStyles public readonly GUIContent m_Shaded = EditorGUIUtility.TrTextContent("Shaded"); public readonly GUIContent m_Geometry = EditorGUIUtility.TrTextContent("Geometry"); public readonly GUIStyle m_DropdownButton = "MiniPopup"; - }; + } private static GUIStyles s_Styles = null; private static GUIStyles Styles diff --git a/Editor/Mono/Inspector/BlendTreeInspector.cs b/Editor/Mono/Inspector/BlendTreeInspector.cs index e0089c0b4a..63a65940c4 100644 --- a/Editor/Mono/Inspector/BlendTreeInspector.cs +++ b/Editor/Mono/Inspector/BlendTreeInspector.cs @@ -505,7 +505,6 @@ public float ClickDragFloat(Rect position, float value, bool alignRight) GUIUtility.hotControl = id; GUIUtility.keyboardControl = id; EditorGUIUtility.editingTextField = false; - break; } break; case EventType.MouseDrag: @@ -620,7 +619,7 @@ private void BlendGraph(Rect area) // draw the animation triangle float last = (i == 0) ? points[i] : points[i - 1]; float next = (i == points.Length - 1) ? points[i] : points[i + 1]; - bool drawSelected = (m_ReorderableList.index == i) ? true : false; + bool drawSelected = (m_ReorderableList.index == i); DrawAnimation(points[i], last, next, drawSelected, area); } Color oldColor = Handles.color; @@ -988,7 +987,7 @@ private void BlendGraph2D(Rect area) for (int i = 0; i < points.Length; i++) { Rect pointRect = new Rect(points[i].x - 6, points[i].y - 6, 13, 13); - bool drawSelected = (m_ReorderableList.index == i) ? true : false; + bool drawSelected = (m_ReorderableList.index == i); if (presences[i] < 0) GUI.color = styles.visPointEmptyColor; diff --git a/Editor/Mono/Inspector/CameraEditor.cs b/Editor/Mono/Inspector/CameraEditor.cs index 0d4e4d119e..dad2a8adac 100644 --- a/Editor/Mono/Inspector/CameraEditor.cs +++ b/Editor/Mono/Inspector/CameraEditor.cs @@ -456,7 +456,7 @@ private bool wantDeferredRendering } } - enum ProjectionType { Perspective, Orthographic }; + enum ProjectionType { Perspective, Orthographic } private Camera m_PreviewCamera; protected Camera previewCamera @@ -626,7 +626,7 @@ private void CommandBufferGUI() { cam.RemoveCommandBuffer(ce, cb); SceneView.RepaintAll(); - PreviewEditorWindow.RepaintAll(); + PlayModeView.RepaintAll(); GUIUtility.ExitGUI(); } } @@ -640,7 +640,7 @@ private void CommandBufferGUI() { cam.RemoveAllCommandBuffers(); SceneView.RepaintAll(); - PreviewEditorWindow.RepaintAll(); + PlayModeView.RepaintAll(); } } EditorGUI.indentLevel--; @@ -720,7 +720,7 @@ public virtual void OnOverlayGUI(Object target, SceneView sceneView) if (targetStage != sceneViewStage) return; - Vector2 previewSize = c.targetTexture ? new Vector2(c.targetTexture.width, c.targetTexture.height) : PreviewEditorWindow.GetMainPreviewTargetSize(); + Vector2 previewSize = c.targetTexture ? new Vector2(c.targetTexture.width, c.targetTexture.height) : PlayModeView.GetMainPlayModeViewTargetSize(); if (previewSize.x < 0f) { @@ -823,7 +823,7 @@ private RenderTexture GetPreviewTextureWithSize(int width, int height) [RequiredByNativeCode] internal static float GetGameViewAspectRatio() { - Vector2 gameViewSize = PreviewEditorWindow.GetMainPreviewTargetSize(); + Vector2 gameViewSize = PlayModeView.GetMainPlayModeViewTargetSize(); if (gameViewSize.x < 0f) { // Fallback to Scene View of not a valid game view size @@ -835,9 +835,9 @@ internal static float GetGameViewAspectRatio() } [RequiredByNativeCode] - internal static Vector2 GetMainPreviewSize() + internal static void GetMainPlayModeViewSize(out Vector2 size) { - return PreviewEditorWindow.GetMainPreviewTargetSize(); + size = PlayModeView.GetMainPlayModeViewTargetSize(); } // Called from C++ when we need to render a Camera's gizmo @@ -846,7 +846,7 @@ internal static void RenderGizmo(Camera camera) CameraEditorUtils.DrawFrustumGizmo(camera); } - private static Vector2 s_PreviousMainGameViewTargetSize; + private static Vector2 s_PreviousMainPlayModeViewTargetSize; public virtual void OnSceneGUI() { if (!target) @@ -856,12 +856,12 @@ public virtual void OnSceneGUI() if (!CameraEditorUtils.IsViewportRectValidToRender(c.rect)) return; - Vector2 currentMainGameViewTargetSize = PreviewEditorWindow.GetMainPreviewTargetSize(); - if (s_PreviousMainGameViewTargetSize != currentMainGameViewTargetSize) + Vector2 currentMainPlayModeViewTargetSize = PlayModeView.GetMainPlayModeViewTargetSize(); + if (s_PreviousMainPlayModeViewTargetSize != currentMainPlayModeViewTargetSize) { // a gameView size change can affect horizontal FOV, refresh the inspector when that happens. Repaint(); - s_PreviousMainGameViewTargetSize = currentMainGameViewTargetSize; + s_PreviousMainPlayModeViewTargetSize = currentMainPlayModeViewTargetSize; } SceneViewOverlay.Window(EditorGUIUtility.TrTextContent("Camera Preview"), OnOverlayGUI, (int)SceneViewOverlay.Ordering.Camera, target, SceneViewOverlay.WindowDisplayOption.OneWindowPerTarget); diff --git a/Editor/Mono/Inspector/ClothInspector.cs b/Editor/Mono/Inspector/ClothInspector.cs index 5d46640c90..dd3f11534e 100644 --- a/Editor/Mono/Inspector/ClothInspector.cs +++ b/Editor/Mono/Inspector/ClothInspector.cs @@ -43,11 +43,11 @@ class ClothInspectorState : ScriptableSingleton [CanEditMultipleObjects] class ClothInspector : Editor { - public enum DrawMode { MaxDistance = 1, CollisionSphereDistance }; - public enum ToolMode { Select, Paint, GradientTool }; - public enum CollToolMode { Select, Paint, Erase }; - enum RectSelectionMode { Replace, Add, Substract }; - public enum CollisionVisualizationMode { SelfCollision, InterCollision }; + public enum DrawMode { MaxDistance = 1, CollisionSphereDistance } + public enum ToolMode { Select, Paint, GradientTool } + public enum CollToolMode { Select, Paint, Erase } + enum RectSelectionMode { Replace, Add, Substract } + public enum CollisionVisualizationMode { SelfCollision, InterCollision } bool[] m_ParticleSelection; bool[] m_ParticleRectSelection; @@ -95,6 +95,7 @@ public enum CollisionVisualizationMode { SelfCollision, InterCollision }; int m_NumSelection = 0; SkinnedMeshRenderer m_SkinnedMeshRenderer; + Transform m_RootBone; private static class Styles { @@ -106,6 +107,7 @@ private static class Styles public static readonly GUIContent paintCollisionParticles = EditorGUIUtility.TrTextContent("Paint Collision Particles"); public static readonly GUIContent selectCollisionParticles = EditorGUIUtility.TrTextContent("Select Collision Particles"); public static readonly GUIContent brushRadiusString = EditorGUIUtility.TrTextContent("Brush Radius"); + public static readonly GUIContent constraintSizeString = EditorGUIUtility.TrTextContent("Constraint Size"); public static readonly GUIContent gradientStartString = EditorGUIUtility.TrTextContent("Gradient Start"); public static readonly GUIContent gradientEndString = EditorGUIUtility.TrTextContent("Gradient End"); public static readonly GUIContent setMaxDistanceString = EditorGUIUtility.TrTextContent("Max Distance"); @@ -259,12 +261,20 @@ public override void OnInspectorGUI() GUILayout.EndHorizontal(); } + // If the Skinned Mesh Renderer's transform has changed we need to re-initialise the inspector if (m_SkinnedMeshRenderer.transform.hasChanged) { - InitClothParticlesInWorldSpace(); + InitInspector(); m_SkinnedMeshRenderer.transform.hasChanged = false; } + // If the Skinned Mesh Renderer's root bone has changed we need to re-initialise the inspector + if (m_RootBone != m_SkinnedMeshRenderer.actualRootBone) + { + InitInspector(); + m_RootBone = m_SkinnedMeshRenderer.actualRootBone; + } + if (editingSelfAndInterCollisionParticles) { if ((state.SetSelfAndInterCollision) || ((state.CollToolMode == CollToolMode.Paint) || (state.CollToolMode == CollToolMode.Erase))) @@ -356,7 +366,6 @@ bool SelectionMeshDirty() { if (m_LastVertices != null) { - Transform t = m_SkinnedMeshRenderer.actualRootBone; int numLastVertices = m_LastVertices.Length; if (numLastVertices != m_NumVerts) return true; @@ -382,7 +391,6 @@ void GenerateSelectionMesh() m_ParticleRectSelection = new bool[m_NumVerts]; m_LastVertices = new Vector3[m_NumVerts]; - Transform t = m_SkinnedMeshRenderer.actualRootBone; for (int i = 0; i < m_NumVerts; i++) { m_LastVertices[i] = m_ClothParticlesInWorldSpace[i]; @@ -403,14 +411,9 @@ void InitSelfAndInterCollisionSelection() cloth.GetSelfAndInterCollisionIndices(selfAndInterCollisionIndices); int length = selfAndInterCollisionIndices.Count; - // if the number of self and inter collision indices are different then don't copy - // as this means the underlying meshes have changed so copying these values is meaningless in this situation - if (length == m_NumVerts) + for (int i = 0; i < length; i++) { - for (int i = 0; i < length; i++) - { - m_SelfAndInterCollisionSelection[selfAndInterCollisionIndices[i]] = true; - } + m_SelfAndInterCollisionSelection[selfAndInterCollisionIndices[i]] = true; } } @@ -465,11 +468,11 @@ void DrawSelfAndInterCollisionParticles() bool forwardFacing = Vector3.Dot(m_ClothNormalsInWorldSpace[i], Camera.current.transform.forward) <= 0; if (forwardFacing || state.ManipulateBackfaces) { - if ((m_SelfAndInterCollisionSelection[i] == true) && !(m_ParticleSelection[i] == true)) + if (m_SelfAndInterCollisionSelection[i] && !m_ParticleSelection[i]) { Handles.color = s_SelfAndInterCollisionParticleColor; } - else if (!(m_SelfAndInterCollisionSelection[i] == true) && !(m_ParticleSelection[i] == true)) + else if (!m_SelfAndInterCollisionSelection[i] && !m_ParticleSelection[i]) { Handles.color = s_UnselectedSelfAndInterCollisionParticleColor; } @@ -507,6 +510,7 @@ void OnEnable() s_ColorTexture = GenerateColorTexture(100); m_SkinnedMeshRenderer = cloth.GetComponent(); + m_RootBone = m_SkinnedMeshRenderer.actualRootBone; InitInspector(); @@ -772,6 +776,8 @@ void SelectionGUI() } cloth.coefficients = coefficients; } + + EditConstraintSize(); } void GradientToolGUI() @@ -975,6 +981,19 @@ void EditBrushSize() } } + void EditConstraintSize() + { + EditorGUI.BeginChangeCheck(); + float fieldValue = EditorGUILayout.FloatField(Styles.constraintSizeString, state.ConstraintSize); + bool changed = EditorGUI.EndChangeCheck(); + if (changed) + { + state.ConstraintSize = fieldValue; + if (state.ConstraintSize < 0.0f) + state.ConstraintSize = 0.0f; + } + } + void EditGradientStart() { EditorGUI.BeginChangeCheck(); @@ -1022,6 +1041,7 @@ void PaintGUI() } EditBrushSize(); + EditConstraintSize(); } int GetMouseVertex(Event e) @@ -1035,11 +1055,9 @@ int GetMouseVertex(Event e) return -1; } - ClothSkinningCoefficient[] coefficients = cloth.coefficients; Ray mouseRay = HandleUtility.GUIPointToWorldRay(e.mousePosition); float minDistance = 1000; int found = -1; - Quaternion rotation = m_SkinnedMeshRenderer.actualRootBone.rotation; for (int i = 0; i < m_NumVerts; i++) { Vector3 dir = m_LastVertices[i] - mouseRay.origin; @@ -1146,8 +1164,6 @@ bool UpdateRectParticleSelection() Plane left = new Plane(topLeft.origin + topLeft.direction, botLeft.origin + botLeft.direction, botLeft.origin); Plane right = new Plane(botRight.origin + botRight.direction, topRight.origin + topRight.direction, topRight.origin); - Quaternion rotation = m_SkinnedMeshRenderer.actualRootBone.rotation; - int length = coefficients.Length; for (int i = 0; i < length; i++) { @@ -1313,7 +1329,6 @@ void GetBrushedConstraints(Event e) } ClothSkinningCoefficient[] coefficients = cloth.coefficients; - Quaternion rotation = m_SkinnedMeshRenderer.actualRootBone.rotation; for (int i = 0; i < m_NumVerts; i++) { Vector3 distanceBetween = m_ClothParticlesInWorldSpace[i] - m_BrushPos; @@ -1398,7 +1413,6 @@ void PaintPreSceneGUI(int id) EventType type = e.GetTypeForControl(id); if (type == EventType.MouseDown || type == EventType.MouseDrag) { - ClothSkinningCoefficient[] coefficients = cloth.coefficients; if (GUIUtility.hotControl != id && (e.alt || e.control || e.command || e.button != 0)) return; if (type == EventType.MouseDown) @@ -1614,7 +1628,6 @@ public void OnSceneGUI() if (editingSelfAndInterCollisionParticles) { OnSceneEditSelfAndInterCollisionParticlesGUI(); - return; } } diff --git a/Editor/Mono/Inspector/Collider2DEditorBase.cs b/Editor/Mono/Inspector/Collider2DEditorBase.cs index 60a4691e3c..77dc4fe161 100644 --- a/Editor/Mono/Inspector/Collider2DEditorBase.cs +++ b/Editor/Mono/Inspector/Collider2DEditorBase.cs @@ -93,7 +93,7 @@ public override void OnInspectorGUI() EditorGUILayout.EndFadeGroup(); // Only show 'Used By Composite' if all targets are capable of being composited. - if (targets.Where(x => (x as Collider2D).compositeCapable == false).Count() == 0) + if (targets.Count(x => (x as Collider2D).compositeCapable == false) == 0) EditorGUILayout.PropertyField(m_UsedByComposite); if (m_AutoTiling != null) diff --git a/Editor/Mono/Inspector/CompositeCollider2DEditor.cs b/Editor/Mono/Inspector/CompositeCollider2DEditor.cs index 9e9cf73bda..d49834ecc5 100644 --- a/Editor/Mono/Inspector/CompositeCollider2DEditor.cs +++ b/Editor/Mono/Inspector/CompositeCollider2DEditor.cs @@ -30,9 +30,9 @@ public override void OnEnable() m_VertexDistance = serializedObject.FindProperty("m_VertexDistance"); m_EdgeRadius = serializedObject.FindProperty("m_EdgeRadius"); m_OffsetDistance = serializedObject.FindProperty("m_OffsetDistance"); - m_ShowEdgeRadius.value = targets.Where(x => (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Polygons).Count() == 0; + m_ShowEdgeRadius.value = targets.Count(x => (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Polygons) == 0; m_ShowEdgeRadius.valueChanged.AddListener(Repaint); - m_ShowManualGenerationButton.value = targets.Where(x => (x as CompositeCollider2D).generationType != CompositeCollider2D.GenerationType.Manual).Count() == 0; + m_ShowManualGenerationButton.value = targets.Count(x => (x as CompositeCollider2D).generationType != CompositeCollider2D.GenerationType.Manual) == 0; m_ShowManualGenerationButton.valueChanged.AddListener(Repaint); } @@ -53,7 +53,7 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(m_VertexDistance); EditorGUILayout.PropertyField(m_OffsetDistance); - m_ShowManualGenerationButton.target = targets.Where(x => (x as CompositeCollider2D).generationType != CompositeCollider2D.GenerationType.Manual).Count() == 0; + m_ShowManualGenerationButton.target = targets.Count(x => (x as CompositeCollider2D).generationType != CompositeCollider2D.GenerationType.Manual) == 0; if (EditorGUILayout.BeginFadeGroup(m_ShowManualGenerationButton.faded)) { if (GUILayout.Button("Regenerate Collider")) @@ -62,15 +62,14 @@ public override void OnInspectorGUI() } EditorGUILayout.EndFadeGroup(); - m_ShowEdgeRadius.target = targets.Where(x => (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Polygons).Count() == 0; + m_ShowEdgeRadius.target = targets.All(x => (x as CompositeCollider2D).geometryType != CompositeCollider2D.GeometryType.Polygons); if (EditorGUILayout.BeginFadeGroup(m_ShowEdgeRadius.faded)) EditorGUILayout.PropertyField(m_EdgeRadius); EditorGUILayout.EndFadeGroup(); - if (targets.Where(x => - (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Outlines && + if (targets.Count(x => (x as CompositeCollider2D).geometryType == CompositeCollider2D.GeometryType.Outlines && (x as CompositeCollider2D).attachedRigidbody != null && - (x as CompositeCollider2D).attachedRigidbody.bodyType == RigidbodyType2D.Dynamic).Count() > 0) + (x as CompositeCollider2D).attachedRigidbody.bodyType == RigidbodyType2D.Dynamic) > 0) EditorGUILayout.HelpBox("Outline geometry is composed of edges and will not preserve the original collider's center-of-mass or rotational inertia. The CompositeCollider2D is attached to a Dynamic Rigidbody2D so you may need to explicitly set these if they are required.", MessageType.Info); serializedObject.ApplyModifiedProperties(); diff --git a/Editor/Mono/Inspector/ComputeShaderInspector.cs b/Editor/Mono/Inspector/ComputeShaderInspector.cs index 708f3442f2..c997c4a6f4 100644 --- a/Editor/Mono/Inspector/ComputeShaderInspector.cs +++ b/Editor/Mono/Inspector/ComputeShaderInspector.cs @@ -21,7 +21,7 @@ class KernelInfo { internal string name; internal string platforms; - }; + } internal class Styles { diff --git a/Editor/Mono/Inspector/EditorDragging.cs b/Editor/Mono/Inspector/EditorDragging.cs index dceb8d9c82..250b6b0907 100644 --- a/Editor/Mono/Inspector/EditorDragging.cs +++ b/Editor/Mono/Inspector/EditorDragging.cs @@ -260,7 +260,7 @@ void HandleDragPerformEvent(Editor[] editors, Event evt, ref int targetIndex) foreach (var targetComponent in targetComponents) { var gameObject = targetComponent.gameObject; - if (scripts.Any(s => !ComponentUtility.WarnCanAddScriptComponent(targetComponent.gameObject, s))) + if (scripts.Any(s => !ComponentUtility.WarnCanAddScriptComponent(gameObject, s))) { valid = false; break; diff --git a/Editor/Mono/Inspector/EditorElement.cs b/Editor/Mono/Inspector/EditorElement.cs index ab614d245c..8a1dd9a6bd 100644 --- a/Editor/Mono/Inspector/EditorElement.cs +++ b/Editor/Mono/Inspector/EditorElement.cs @@ -226,6 +226,8 @@ void HeaderOnGUI() if (wasVisible != IsElementVisible(m_InspectorElement)) { SetElementVisible(m_InspectorElement, wasVisible); + + m_Footer.style.marginTop = wasVisible ? 0 : -kFooterDefaultHeight; } var multiEditingSupported = inspectorWindow.IsMultiEditingSupported(editor, target); @@ -296,7 +298,13 @@ bool DrawEditorLargeHeader(ref bool wasVisible) var importedObjectBarRect = GUILayoutUtility.GetRect(16, 20); importedObjectBarRect.height = 21; - var headerText = m_Editors[0] is PrefabImporterEditor ? "Root in Prefab Asset" : "Imported Object"; + var headerText = "Imported Object"; + if (m_Editors.Length > 1) + { + if (m_Editors[0] is PrefabImporterEditor && m_Editors[1] is GameObjectInspector) + headerText = "Root in Prefab Asset"; + } + GUILayout.Label(headerText, Styles.importedObjectsHeaderStyle, GUILayout.ExpandWidth(true)); GUILayout.Space(-7f); // Ensures no spacing between this header and the next header } @@ -333,13 +341,7 @@ Rect DrawEditorSmallHeader(Object target, bool wasVisible) using (new EditorGUI.DisabledScope(!currentEditor.IsEnabled())) { - // Woraround: Temporarily adjust the top padding to 2px in order to vertically center the content of the titlebar. - // This is because there is a 3px bottom margin used to be able to pick and drag a component section - var oldPadding = EditorStyles.inspectorTitlebar.padding.top; - EditorStyles.inspectorTitlebar.padding.top = 2; - bool isVisible = EditorGUILayout.InspectorTitlebar(wasVisible, currentEditor); - EditorStyles.inspectorTitlebar.padding.top = oldPadding; if (wasVisible != isVisible) { diff --git a/Editor/Mono/Inspector/EditorSettingsInspector.cs b/Editor/Mono/Inspector/EditorSettingsInspector.cs index ba6633eb26..1613ae2d29 100644 --- a/Editor/Mono/Inspector/EditorSettingsInspector.cs +++ b/Editor/Mono/Inspector/EditorSettingsInspector.cs @@ -11,6 +11,7 @@ using UnityEditor.SceneManagement; using UnityEditor.Collaboration; using UnityEditor.Web; +using System.IO; namespace UnityEditor { @@ -38,8 +39,8 @@ class Content public static GUIContent overwriteFailedCheckoutAssets = EditorGUIUtility.TrTextContent("Overwrite Failed Checkout Assets", "When on, assets that can not be checked out will get saved anyway."); public static GUIContent overlayIcons = EditorGUIUtility.TrTextContent("Overlay Icons", "Should version control status icons be shown in project view."); - public static GUIContent assetPipeline = EditorGUIUtility.TrTextContent("Asset Pipeline (experimental)"); - public static GUIContent cacheServer = EditorGUIUtility.TrTextContent("Cache Server"); + public static GUIContent assetPipeline = EditorGUIUtility.TrTextContent("Asset Pipeline"); + public static GUIContent cacheServer = EditorGUIUtility.TrTextContent("Cache Server (project specific)"); public static GUIContent assetSerialization = EditorGUIUtility.TrTextContent("Asset Serialization"); public static GUIContent defaultBehaviorMode = EditorGUIUtility.TrTextContent("Default Behaviour Mode"); @@ -179,13 +180,13 @@ public PopupElement(string content, bool requiresTeamLicense) private PopupElement[] assetPipelineModePopupList = { - new PopupElement("Version 1"), - new PopupElement("Version 2 (experimental)"), + new PopupElement("Version 1 (deprecated)"), + new PopupElement("Version 2"), }; private PopupElement[] cacheServerModePopupList = { - new PopupElement("As preferences"), + new PopupElement("Use global settings (stored in preferences)"), new PopupElement("Enabled"), new PopupElement("Disabled"), }; @@ -238,11 +239,11 @@ private enum CacheServerMode } ReorderableList m_CacheServerList; - enum CacheServerConnectionState { Unknown, Success, Failure }; + enum CacheServerConnectionState { Unknown, Success, Failure } private CacheServerConnectionState m_CacheServerConnectionState; private static string s_ForcedAssetPipelineWarning; - const string kEditorUserSettingsPath = "Library/EditorUserSettings.asset"; + const string kEditorUserSettingsPath = "UserSettings/EditorUserSettings.asset"; SerializedObject m_EditorUserSettings; SerializedProperty m_AssetPipelineMode; SerializedProperty m_CacheServerMode; @@ -275,8 +276,9 @@ public void OnEnable() public void OnDisable() { DevDeviceList.Changed -= OnDeviceListChanged; - if (m_EditorUserSettings.targetObject != null && EditorUtility.IsDirty(m_EditorUserSettings.targetObject)) + if (m_EditorUserSettings != null && m_EditorUserSettings.targetObject != null && EditorUtility.IsDirty(m_EditorUserSettings.targetObject)) InternalEditorUtility.SaveToSerializedFileAndForget(new[] { m_EditorUserSettings.targetObject }, kEditorUserSettingsPath, true); + m_EditorUserSettings = null; } void OnDeviceListChanged() @@ -284,6 +286,7 @@ void OnDeviceListChanged() BuildRemoteDeviceList(); } + private static readonly int s_ServerTextFieldHash = "CacheServerTextField".GetHashCode(); private void DrawCacheServerListElement(Rect rect, int index, bool selected, bool focused) { rect.height -= 2; // nicer looking with selected list row and a text field in it @@ -292,10 +295,30 @@ private void DrawCacheServerListElement(Rect rect, int index, bool selected, boo // Will have space in front of label for more space between it and the drag handle. rect.xMin -= ReorderableList.Defaults.dragHandleWidth; - string oldName = m_CacheServers.GetArrayElementAtIndex(index).stringValue; + // Get the current name at a given index, or an empty string if it's an invalid index + string oldName = (index < 0 || index >= m_CacheServers.arraySize) ? string.Empty : m_CacheServers.GetArrayElementAtIndex(index).stringValue; if (string.IsNullOrEmpty(oldName)) - oldName = ""; - string newName = EditorGUI.TextField(rect, " Server " + index, oldName); + oldName = string.Empty; + + // Grow the array if the index is invalid + if (index >= m_CacheServers.arraySize) { index = m_CacheServers.arraySize; m_CacheServers.arraySize = index + 1; } + + // Show the draggable handle + ReorderableList.defaultBehaviours.DrawElementDraggingHandle(rect, index, selected, focused, true); + + // Show the textbox + var elementContentRect = rect; + elementContentRect.y++; + elementContentRect.xMin += ReorderableList.Defaults.dragHandleWidth; + elementContentRect.xMax -= ReorderableList.Defaults.padding; + + int prevId = GUIUtility.keyboardControl; + int id = GUIUtility.GetControlID(s_ServerTextFieldHash, FocusType.Keyboard, elementContentRect); + string newName = EditorGUI.TextFieldInternal(id, elementContentRect, EditorGUIUtility.TempContent(" Server " + index), oldName, EditorStyles.textField); + + // When we focus on the text field, we want to select that line in the m_CacheServerList ReorderableList + if (prevId != id && GUIUtility.keyboardControl == id) + m_CacheServerList.index = index; if (newName != oldName) { @@ -612,17 +635,39 @@ private void LoadEditorUserSettings() m_CacheServerConnectionState = CacheServerConnectionState.Unknown; s_ForcedAssetPipelineWarning = null; - if (m_CacheServerList == null) + + m_CacheServerList = new ReorderableList(m_EditorUserSettings, + m_CacheServers, + draggable: true, + displayHeader: false, + displayAddButton: true, + displayRemoveButton: true) { - m_CacheServerList = new ReorderableList(serializedObject, m_CacheServers, true, false, true, true); - m_CacheServerList.onReorderCallback = (ReorderableList list) => { serializedObject.ApplyModifiedProperties(); }; - m_CacheServerList.onAddCallback = (ReorderableList list) => { m_CacheServers.arraySize += 1; serializedObject.ApplyModifiedProperties(); }; - m_CacheServerList.onRemoveCallback = (ReorderableList list) => { ReorderableList.defaultBehaviours.DoRemoveButton(list); serializedObject.ApplyModifiedProperties(); }; - m_CacheServerList.onCanRemoveCallback = (ReorderableList list) => { return list.index < m_CacheServers.arraySize && list.index >= 0; }; - m_CacheServerList.drawElementCallback = DrawCacheServerListElement; - m_CacheServerList.elementHeight = EditorGUIUtility.singleLineHeight + 2; - m_CacheServerList.headerHeight = 3; - } + drawElementCallback = DrawCacheServerListElement, + elementHeight = EditorGUIUtility.singleLineHeight + 2, + headerHeight = 3, + + onAddCallback = (ReorderableList list) => { list.serializedProperty.arraySize += 1; }, + onReorderCallback = (ReorderableList list) => { list.serializedProperty.serializedObject.ApplyModifiedProperties(); }, + onChangedCallback = (ReorderableList list) => { list.serializedProperty.serializedObject.ApplyModifiedProperties(); }, + onCanRemoveCallback = (ReorderableList list) => { return list.index < list.serializedProperty.arraySize && list.index >= 0; }, + + onRemoveCallback = (ReorderableList list) => + { + if (list.serializedProperty.arraySize == 0) + return; + + list.GrabKeyboardFocus(); // de-focuses the text field, so it doesn't end up showing the old value after the deletion + + if (list.index < list.serializedProperty.arraySize) + list.serializedProperty.DeleteArrayElementAtIndex(list.index); + else + list.serializedProperty.arraySize--; + + if (list.index >= list.serializedProperty.arraySize - 1) + list.index = list.serializedProperty.arraySize - 1; + } + }; } private void DoProjectGenerationSettings() @@ -677,7 +722,7 @@ private static string GetForcedAssetPipelineWarning() else if (CacheServerPreferences.GetMagicFileAssetPipelineOverride()) s_ForcedAssetPipelineWarning = "Asset pipeline mode was forced via via magic adb2.txt file in project root. The above setting is not in effect before restarting without the magic file."; else - s_ForcedAssetPipelineWarning = ""; + s_ForcedAssetPipelineWarning = string.Empty; } return s_ForcedAssetPipelineWarning; } @@ -699,7 +744,14 @@ private void DoAssetPipelineSettings() if (!string.IsNullOrEmpty(assetPipelineWarning)) EditorGUILayout.HelpBox(assetPipelineWarning, MessageType.Info, true); else if (isAssetPipelineVersion1 != AssetDatabase.IsV1Enabled()) - EditorGUILayout.HelpBox("Changes in asset pipeline version will take effect after saving and restarting the project.", MessageType.Info, true); + { + var message = "Changes in Asset Pipeline Version will take effect after saving and restarting the project."; + + if (isAssetPipelineVersion1) + message += "\nPlease note that Asset Pipeline Version 1 is now deprecated."; + + EditorGUILayout.HelpBox(message, MessageType.Info, true); + } } private void DoCacheServerSettings() diff --git a/Editor/Mono/Inspector/Enlighten/LightmapParameters.cs b/Editor/Mono/Inspector/Enlighten/LightmapParameters.cs index 28b256d8a2..b3760dd287 100644 --- a/Editor/Mono/Inspector/Enlighten/LightmapParameters.cs +++ b/Editor/Mono/Inspector/Enlighten/LightmapParameters.cs @@ -139,6 +139,6 @@ private class Styles public static readonly GUIContent bakedLightmapTagContent = EditorGUIUtility.TrTextContent("Baked Tag", "An integer that lets you force an object into a different baked lightmap even though all the other parameters are the same. This can be useful e.g. when streaming in sections of a level."); public static readonly GUIContent limitLightmapCount = EditorGUIUtility.TrTextContent("Limit Lightmap Count", "If enabled, objects with the same baked GI settings will be packed into a specified number of lightmaps. This may reduce the objects' lightmap resolution."); public static readonly GUIContent lightmapMaxCount = EditorGUIUtility.TrTextContent("Max Lightmaps", "The maximum number of lightmaps into which objects will be packed."); - }; + } } } diff --git a/Editor/Mono/Inspector/GameObjectInspector.cs b/Editor/Mono/Inspector/GameObjectInspector.cs index ed38c9bd9c..b90e10aec5 100644 --- a/Editor/Mono/Inspector/GameObjectInspector.cs +++ b/Editor/Mono/Inspector/GameObjectInspector.cs @@ -234,6 +234,11 @@ private static bool ShowMixedStaticEditorFlags(StaticEditorFlags mask) return countedBits > 0 && countedBits != numFlags; } + public override bool UseDefaultMargins() + { + return false; + } + protected override void OnHeaderGUI() { bool enabledTemp = GUI.enabled; diff --git a/Editor/Mono/Inspector/GenericInspector.cs b/Editor/Mono/Inspector/GenericInspector.cs index d44688db83..5172a33430 100644 --- a/Editor/Mono/Inspector/GenericInspector.cs +++ b/Editor/Mono/Inspector/GenericInspector.cs @@ -64,9 +64,9 @@ internal override bool GetOptimizedGUIBlock(bool isDirty, bool isVisible, out fl while (property.NextVisible(childrenAreExpanded)) { var handler = ScriptAttributeUtility.GetHandler(property); - height += handler.GetHeight(property, null, false) + EditorGUI.kControlVerticalSpacing; - - childrenAreExpanded = property.isExpanded && EditorGUI.HasVisibleChildFields(property); + var hasPropertyDrawer = handler.propertyDrawer != null; + height += handler.GetHeight(property, null, hasPropertyDrawer) + EditorGUI.kControlVerticalSpacing; + childrenAreExpanded = !hasPropertyDrawer && property.isExpanded && EditorGUI.HasVisibleChildFields(property); } m_LastHeight = height; @@ -99,16 +99,16 @@ internal override bool OnOptimizedInspectorGUI(Rect contentRect) while (property.NextVisible(childrenAreExpanded)) { var handler = ScriptAttributeUtility.GetHandler(property); - contentRect.height = handler.GetHeight(property, null, false); + var hasPropertyDrawer = handler.propertyDrawer != null; + childrenAreExpanded = !hasPropertyDrawer && property.isExpanded && EditorGUI.HasVisibleChildFields(property); + contentRect.height = handler.GetHeight(property, null, hasPropertyDrawer); if (contentRect.Overlaps(visibleRect)) { EditorGUI.indentLevel = property.depth; using (new EditorGUI.DisabledScope(isInspectorModeNormal && "m_Script" == property.propertyPath)) - childrenAreExpanded = handler.OnGUI(contentRect, property, null, false, visibleRect) && property.isExpanded; + childrenAreExpanded &= handler.OnGUI(contentRect, property, null, false, visibleRect); } - else - childrenAreExpanded = property.isExpanded && EditorGUI.HasVisibleChildFields(property); contentRect.y += contentRect.height + EditorGUI.kControlVerticalSpacing; } diff --git a/Editor/Mono/Inspector/GraphicsSettingsInspector.cs b/Editor/Mono/Inspector/GraphicsSettingsInspector.cs index 8d9ef53c1d..e666c75101 100644 --- a/Editor/Mono/Inspector/GraphicsSettingsInspector.cs +++ b/Editor/Mono/Inspector/GraphicsSettingsInspector.cs @@ -156,8 +156,12 @@ public override void OnInspectorGUI() EditorGUILayout.Space(); } + float labelWidth = EditorGUIUtility.labelWidth; + TierSettingsGUI(); + EditorGUIUtility.labelWidth = labelWidth; + GUILayout.Label(Styles.builtinSettings, EditorStyles.boldLabel); if (!usingSRP) builtinShadersEditor.OnInspectorGUI(); diff --git a/Editor/Mono/Inspector/HingeJoint2DEditor.cs b/Editor/Mono/Inspector/HingeJoint2DEditor.cs index b4d6023e1b..b5c2bdae91 100644 --- a/Editor/Mono/Inspector/HingeJoint2DEditor.cs +++ b/Editor/Mono/Inspector/HingeJoint2DEditor.cs @@ -46,7 +46,6 @@ static Styles() public override void OnInspectorGUI() { - HingeJoint2D joint = (HingeJoint2D)target; EditMode.DoEditModeInspectorModeButton( EditMode.SceneViewEditMode.JointAngularLimits, "Edit Joint Angular Limits", diff --git a/Editor/Mono/Inspector/InspectorWindow.cs b/Editor/Mono/Inspector/InspectorWindow.cs index 25e7a32321..b055b7911c 100644 --- a/Editor/Mono/Inspector/InspectorWindow.cs +++ b/Editor/Mono/Inspector/InspectorWindow.cs @@ -48,6 +48,7 @@ internal InspectorMode inspectorMode const float kAddComponentButtonHeight = 45f; internal const int kInspectorPaddingLeft = 8 + 10; internal const int kInspectorPaddingRight = 4; + internal const int kInspectorPaddingTop = 4; internal const float kEditorElementPaddingBottom = 2f; const float k_MinAreaAbovePreview = 130; @@ -55,6 +56,7 @@ internal InspectorMode inspectorMode const float k_InspectorPreviewMinTotalHeight = k_InspectorPreviewMinHeight + kBottomToolbarHeight; const int k_MinimumRootVisualHeight = 81; const int k_MinimumWindowWidth = 275; + const int k_AutoScrollZoneHeight = 24; private const long delayRepaintWhilePlayingAnimation = 150; // Delay between repaints in milliseconds while playing animation private long s_LastUpdateWhilePlayingAnimation = 0; @@ -110,6 +112,10 @@ internal InspectorMode inspectorMode VisualElement m_MultiEditLabel; + ScrollView m_ScrollView; + [SerializeField] int m_LastInspectedObjectInstanceID = -1; + [SerializeField] float m_LastVerticalScrollValue = 0; + VisualElement FindVisualElementInTreeByClassName(string elementClassName) { var element = rootVisualElement.Q(className: elementClassName); @@ -148,7 +154,7 @@ internal static class Styles public static readonly GUIContent vcsLock = EditorGUIUtility.TrTextContent("Lock"); public static readonly GUIContent vcsUnlock = EditorGUIUtility.TrTextContent("Unlock"); public static readonly GUIContent vcsSubmit = EditorGUIUtility.TrTextContent("Submit"); - public static GUIStyle vcsButtonStyle = "preButton"; + public static readonly GUIStyle vcsButtonStyle = EditorStyles.miniButton; 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." ); @@ -230,6 +236,7 @@ private void LoadVisualTreeFromUxml() var container = tpl.CloneTree(); container.AddToClassList(s_MainContainerClassName); rootVisualElement.hierarchy.Add(container); + m_ScrollView = container.Q(); var multiContainer = rootVisualElement.Q(className: s_MultiEditClassName); multiContainer.Query().ForEach((label) => label.text = L10n.Tr(label.text)); @@ -252,6 +259,7 @@ void OnGeometryChanged(GeometryChangedEvent e) m_PreviewResizer.SetExpanded(false); } } + RestoreVerticalScrollIfNeeded(); } private void OnProjectWasLoaded() @@ -280,6 +288,10 @@ private void OnProjectWasLoaded() protected virtual void OnDisable() { + // save vertical scroll position + m_LastInspectedObjectInstanceID = GetInspectedObject()?.GetInstanceID() ?? -1; + m_LastVerticalScrollValue = m_ScrollView?.verticalScroller.value ?? 0; + RemoveInspectorWindow(this); m_LockTracker?.lockStateChanged.RemoveListener(LockStateChanged); @@ -783,6 +795,21 @@ void DragOverBottomArea(DragUpdatedEvent dragUpdatedEvent) { if (editorsElement.ContainsPoint(editorsElement.WorldToLocal(dragUpdatedEvent.mousePosition))) { + if (m_ScrollView != null) + { + // implement auto-scroll for easier component drag'n'drop, + // we define a zone of height = k_AutoScrollZoneHeight + // at the top/bottom of the scrollView viewport, + // while dragging, when the mouse moves in these zones, + // we automatically scroll up/down + var localDragPosition = m_ScrollView.contentViewport.WorldToLocal(dragUpdatedEvent.mousePosition); + + if (localDragPosition.y < k_AutoScrollZoneHeight) + m_ScrollView.verticalScroller.ScrollPageUp(); + else if (localDragPosition.y > m_ScrollView.contentViewport.rect.height - k_AutoScrollZoneHeight) + m_ScrollView.verticalScroller.ScrollPageDown(); + } + return; } @@ -1257,9 +1284,8 @@ internal static void VersionControlBar(Editor assetEditor) var hasAssetState = !string.IsNullOrEmpty(currentState); var hasMetaState = !string.IsNullOrEmpty(currentMetaState); - GUILayout.Label(GUIContent.none, Styles.preToolbar, GUILayout.Height(kBottomToolbarHeight)); - - var rect = GUILayoutUtility.GetLastRect(); + GUILayout.BeginHorizontal(GUIContent.none, EditorStyles.toolbar); + var rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.toolbar, GUILayout.ExpandWidth(true)); var icon = AssetDatabase.GetCachedIcon(assetPath) as Texture2D; var overlayRect = new Rect(rect.x, rect.y + 1, 28, 16); @@ -1294,6 +1320,7 @@ internal static void VersionControlBar(Editor assetEditor) fullState = "State: " + fullState; content.tooltip = fullState; GUI.Label(textRect, content, EditorStyles.label); + GUILayout.EndHorizontal(); VersionControlCheckoutHint(assetEditor, connected); } @@ -1325,6 +1352,7 @@ static float VersionControlBarButtons(Editor assetEditor, Rect rect, Asset asset var buttonRect = rect; var buttonStyle = Styles.vcsButtonStyle; + buttonRect.y += 1; buttonRect.height = buttonStyle.CalcSize(Styles.vcsAdd).y; var isFolder = asset.isFolder && !Provider.isVersioningFolders; @@ -1502,6 +1530,16 @@ void DrawEditors(Editor[] editors) } } + void RestoreVerticalScrollIfNeeded() + { + if (m_LastInspectedObjectInstanceID == -1) + return; + var inspectedObjectInstanceID = GetInspectedObject()?.GetInstanceID() ?? -1; + if (inspectedObjectInstanceID == m_LastInspectedObjectInstanceID && inspectedObjectInstanceID != -1) + m_ScrollView.verticalScroller.value = m_LastVerticalScrollValue; + m_LastInspectedObjectInstanceID = -1; // reset to make sure the restore occurs once + } + void AddRemovedPrefabComponentElement(GameObject targetGameObject, Component nextInSource, VisualElement element) { if (ShouldDisplayRemovedComponent(targetGameObject, nextInSource)) @@ -1782,7 +1820,8 @@ void PrepareLockedObjectsForSerialization() { if (!EditorUtility.IsPersistent(m_ObjectsLockedBeforeSerialization[i])) { - m_InstanceIDsLockedBeforeSerialization.Add(m_ObjectsLockedBeforeSerialization[i].GetInstanceID()); + if (m_ObjectsLockedBeforeSerialization[i] != null) + m_InstanceIDsLockedBeforeSerialization.Add(m_ObjectsLockedBeforeSerialization[i].GetInstanceID()); m_ObjectsLockedBeforeSerialization.RemoveAt(i); } } diff --git a/Editor/Mono/Inspector/JointEditor.cs b/Editor/Mono/Inspector/JointEditor.cs index 9466513f3c..694b154aba 100644 --- a/Editor/Mono/Inspector/JointEditor.cs +++ b/Editor/Mono/Inspector/JointEditor.cs @@ -58,7 +58,7 @@ public override void OnInspectorGUI() protected void DoInspectorEditButtons() { T joint = (T)target; - EditorGUI.BeginDisabledGroup(joint.gameObject.activeSelf == false); + EditorGUI.BeginDisabledGroup(joint.gameObject.activeInHierarchy == false); EditorGUILayout.EditorToolbarForTarget(EditorGUIUtility.TrTempContent("Edit Angular Limits"), target); EditorGUI.EndDisabledGroup(); } diff --git a/Editor/Mono/Inspector/LODGroupEditor.cs b/Editor/Mono/Inspector/LODGroupEditor.cs index 2dba9a03e6..53c308aa97 100644 --- a/Editor/Mono/Inspector/LODGroupEditor.cs +++ b/Editor/Mono/Inspector/LODGroupEditor.cs @@ -381,7 +381,7 @@ private void HandleAddRenderer(Rect position, IEnumerable alreadyDrawn, Re break; // If we are over a valid range, make sure we have a game object... - if (DragAndDrop.objectReferences.Count() > 0) + if (DragAndDrop.objectReferences.Length > 0) { DragAndDrop.visualMode = m_IsPrefab ? DragAndDropVisualMode.None : DragAndDropVisualMode.Copy; @@ -903,7 +903,7 @@ private void DrawLODLevelSlider(Rect sliderPosition, List l // Actually set LOD level now m_SelectedLOD = lodLevel; - if (DragAndDrop.objectReferences.Count() > 0) + if (DragAndDrop.objectReferences.Length > 0) { DragAndDrop.visualMode = m_IsPrefab ? DragAndDropVisualMode.None : DragAndDropVisualMode.Copy; @@ -939,7 +939,6 @@ private void DrawLODLevelSlider(Rect sliderPosition, List l } } evt.Use(); - break; } break; diff --git a/Editor/Mono/Inspector/LayoutDropdownWindow.cs b/Editor/Mono/Inspector/LayoutDropdownWindow.cs index 31c167a38e..d6d338f462 100644 --- a/Editor/Mono/Inspector/LayoutDropdownWindow.cs +++ b/Editor/Mono/Inspector/LayoutDropdownWindow.cs @@ -219,11 +219,7 @@ void TableGUI(Rect rect) bool selected = (cellHMode == hMode) && (cellVMode == vMode); - bool selectedHeader = false; - if (i == 0 && cellVMode == vMode) - selectedHeader = true; - if (j == 0 && cellHMode == hMode) - selectedHeader = true; + bool selectedHeader = (i == 0 && cellVMode == vMode) || (j == 0 && cellHMode == hMode); if (Event.current.type == EventType.Repaint) { diff --git a/Editor/Mono/Inspector/LightEditor.cs b/Editor/Mono/Inspector/LightEditor.cs index 8ce72e2081..efaf02a84a 100644 --- a/Editor/Mono/Inspector/LightEditor.cs +++ b/Editor/Mono/Inspector/LightEditor.cs @@ -682,7 +682,7 @@ private void CommandBufferGUI() { light.RemoveCommandBuffer(le, cb); SceneView.RepaintAll(); - PreviewEditorWindow.RepaintAll(); + PlayModeView.RepaintAll(); GUIUtility.ExitGUI(); } } @@ -696,7 +696,7 @@ private void CommandBufferGUI() { light.RemoveAllCommandBuffers(); SceneView.RepaintAll(); - PreviewEditorWindow.RepaintAll(); + PlayModeView.RepaintAll(); } } EditorGUI.indentLevel--; diff --git a/Editor/Mono/Inspector/LightingSettingsInspector.cs b/Editor/Mono/Inspector/LightingSettingsInspector.cs index 822fe7ede3..29616ad18a 100644 --- a/Editor/Mono/Inspector/LightingSettingsInspector.cs +++ b/Editor/Mono/Inspector/LightingSettingsInspector.cs @@ -49,12 +49,14 @@ static class Styles public static readonly GUIContent NoNormalsNoLightmapping = EditorGUIUtility.TrTextContent("Mesh used by the renderer doesn't have normals. Normals are needed for lightmapping."); public static readonly GUIContent NoVerticesNoLightmapping = EditorGUIUtility.TrTextContent("Mesh used by the renderer doesn't have vertices. Vertices are needed for lightmapping."); public static readonly GUIContent UnsupportedTopology = EditorGUIUtility.TrTextContent("Mesh with point, strip or line topology is not supported by lightmapping."); - public static readonly GUIContent UVOverlap = EditorGUIUtility.TrTextContent("This GameObject has overlapping UVs. Please enable 'Generate Lightmap UVs' on the Asset or fix in your modelling package."); + public static readonly GUIContent UVOverlap = EditorGUIUtility.TrTextContent("This GameObject has overlapping UVs. Please adjust Mesh Importer settings or increase chart padding in your modeling package."); public static readonly GUIContent Atlas = EditorGUIUtility.TrTextContent("Baked Lightmap"); public static readonly GUIContent RealtimeLM = EditorGUIUtility.TrTextContent("Realtime Lightmap"); public static readonly GUIContent ScaleInLightmap = EditorGUIUtility.TrTextContent("Scale In Lightmap", "Specifies the relative size of object's UVs within a lightmap. A value of 0 will result in the object not being lightmapped, but still contribute lighting to other objects in the Scene."); public static readonly GUIContent AlbedoScale = EditorGUIUtility.TrTextContent("Albedo Scale", "Specifies the relative size of object's UVs within its albedo texture that is used when calculating the influence on surrounding objects."); public static readonly GUIContent AtlasIndex = EditorGUIUtility.TrTextContent("Lightmap Index"); + public static readonly GUIContent LightmapResolution = EditorGUIUtility.TrTextContent("Lightmap Resolution"); + public static readonly GUIContent LightmapObjectScale = EditorGUIUtility.TrTextContent("Lightmap Object Scale"); public static readonly GUIContent PVRInstanceHash = EditorGUIUtility.TrTextContent("Instance Hash", "The hash of the baked GI instance."); public static readonly GUIContent PVRAtlasHash = EditorGUIUtility.TrTextContent("Atlas Hash", "The hash of the atlas this baked GI instance is a part of."); public static readonly GUIContent PVRAtlasInstanceOffset = EditorGUIUtility.TrTextContent("Atlas Instance Offset", "The offset into the transform array instances of this atlas start at."); @@ -133,6 +135,21 @@ private bool isPrefabAsset } } + private float CalcLODScale(bool isMeshRenderer) + { + float lodScale = 1.0f; + if (isMeshRenderer) + { + lodScale = LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[0]); + for (int i = 1; i < m_Renderers.Length; i++) + { + if (!Mathf.Approximately(lodScale, LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[i]))) + lodScale = 1.0F; + } + } + return lodScale; + } + public LightingSettingsInspector(SerializedObject serializedObject) { m_SerializedObject = serializedObject; @@ -432,17 +449,7 @@ void LightmapScaleGUI(bool meshRenderer, GUIContent title, bool isSSD) if (isSSD && LightmapEditorSettings.lightmapper != LightmapEditorSettings.Lightmapper.Enlighten) return; - float lodScale = 1.0f; - if (meshRenderer) - { - lodScale = LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[0]); - for (int i = 1; i < m_Renderers.Length; i++) - { - if (!Mathf.Approximately(lodScale, LightmapVisualization.GetLightmapLODLevelScale(m_Renderers[i]))) - lodScale = 1.0F; - } - } - + float lodScale = CalcLODScale(meshRenderer); float lightmapScale = lodScale * m_LightmapScale.floatValue; Rect rect = EditorGUILayout.GetControlRect(); @@ -499,12 +506,18 @@ void ShowAtlasGUI(int instanceID) GUILayout.BeginVertical(); - GUILayout.Label(Styles.AtlasIndex.text + ": " + m_LightmapIndex.intValue.ToString()); + GUILayout.Label(Styles.AtlasIndex.text + ": " + m_LightmapIndex.intValue); GUILayout.Label(Styles.AtlasTilingX.text + ": " + m_LightmapTilingOffsetX.floatValue.ToString(CultureInfo.InvariantCulture.NumberFormat)); GUILayout.Label(Styles.AtlasTilingY.text + ": " + m_LightmapTilingOffsetY.floatValue.ToString(CultureInfo.InvariantCulture.NumberFormat)); GUILayout.Label(Styles.AtlasOffsetX.text + ": " + m_LightmapTilingOffsetZ.floatValue.ToString(CultureInfo.InvariantCulture.NumberFormat)); GUILayout.Label(Styles.AtlasOffsetY.text + ": " + m_LightmapTilingOffsetW.floatValue.ToString(CultureInfo.InvariantCulture.NumberFormat)); + float lightmapResolution = LightmapEditorSettings.bakeResolution * CalcLODScale(true) * m_LightmapScale.floatValue; + Transform transform = m_Renderers[0].GetComponent(); + float lightmapObjectScale = System.Math.Min(System.Math.Min(transform.localScale.x, transform.localScale.y), transform.localScale.z); + GUILayout.Label(Styles.LightmapResolution.text + ": " + lightmapResolution.ToString(CultureInfo.InvariantCulture.NumberFormat)); + GUILayout.Label(Styles.LightmapObjectScale.text + ": " + lightmapObjectScale.ToString(CultureInfo.InvariantCulture.NumberFormat)); + GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); @@ -557,7 +570,7 @@ void ShowRealtimeLMGUI(Terrain terrain) int numChunksInX, numChunksInY; if (LightmapEditorSettings.GetTerrainSystemResolution(terrain, out width, out height, out numChunksInX, out numChunksInY)) { - var str = width.ToString() + "x" + height.ToString(); + var str = width + "x" + height; if (numChunksInX > 1 || numChunksInY > 1) str += string.Format(" ({0}x{1} chunks)", numChunksInX, numChunksInY); GUILayout.Label(Styles.RealtimeLMResolution.text + ": " + str); @@ -597,13 +610,13 @@ void ShowRealtimeLMGUI(Renderer renderer) int instWidth, instHeight; if (LightmapEditorSettings.GetInstanceResolution(renderer, out instWidth, out instHeight)) { - GUILayout.Label(Styles.RealtimeLMInstanceResolution.text + ": " + instWidth.ToString() + "x" + instHeight.ToString()); + GUILayout.Label(Styles.RealtimeLMInstanceResolution.text + ": " + instWidth + "x" + instHeight); } int width, height; if (LightmapEditorSettings.GetSystemResolution(renderer, out width, out height)) { - GUILayout.Label(Styles.RealtimeLMResolution.text + ": " + width.ToString() + "x" + height.ToString()); + GUILayout.Label(Styles.RealtimeLMResolution.text + ": " + width + "x" + height); } GUILayout.EndVertical(); @@ -719,7 +732,6 @@ private void DisplayMeshWarning() if (LightmapEditorSettings.HasZeroAreaMesh(m_Renderers[0])) { EditorGUILayout.HelpBox(Styles.ZeroAreaPackingMesh.text, MessageType.Warning); - return; } } } diff --git a/Editor/Mono/Inspector/MeshRendererEditor.cs b/Editor/Mono/Inspector/MeshRendererEditor.cs index 3a83e07d98..476eaf5827 100644 --- a/Editor/Mono/Inspector/MeshRendererEditor.cs +++ b/Editor/Mono/Inspector/MeshRendererEditor.cs @@ -15,7 +15,7 @@ internal class MeshRendererEditor : RendererEditorBase class Styles { public static readonly GUIContent materialWarning = EditorGUIUtility.TrTextContent("This renderer has more materials than the Mesh has submeshes. Multiple materials will be applied to the same submesh, which costs performance. Consider using multiple shader passes."); - public static readonly GUIContent staticBatchingWarning = EditorGUIUtility.TrTextContent("This renderer is statically batched and uses an instanced shader at the same time. Instancing will be disabled in such a case. Consider disabling static batching if you want it to be instanced."); + public static readonly GUIContent staticBatchingWarning = EditorGUIUtility.TrTextContent("This Renderer uses static batching and instanced Shaders. When the Player is active, instancing is disabled. If you want instanced Shaders at run time, disable static batching."); } private SerializedObject m_GameObjectsSerializedObject; diff --git a/Editor/Mono/Inspector/MinMaxGradientPropertyDrawer.cs b/Editor/Mono/Inspector/MinMaxGradientPropertyDrawer.cs index 22e85698b7..52b9fd8a33 100644 --- a/Editor/Mono/Inspector/MinMaxGradientPropertyDrawer.cs +++ b/Editor/Mono/Inspector/MinMaxGradientPropertyDrawer.cs @@ -35,7 +35,7 @@ class Styles EditorGUIUtility.TrTextContent("Random Between Two Gradients"), EditorGUIUtility.TrTextContent("Random Color") }; - }; + } static Styles s_Styles; void Init(SerializedProperty property) diff --git a/Editor/Mono/Inspector/NavMeshAgentInspector.cs b/Editor/Mono/Inspector/NavMeshAgentInspector.cs index 69b0b785bb..6e008245f7 100644 --- a/Editor/Mono/Inspector/NavMeshAgentInspector.cs +++ b/Editor/Mono/Inspector/NavMeshAgentInspector.cs @@ -32,7 +32,7 @@ private class Styles public readonly GUIContent m_AgentSteeringHeader = EditorGUIUtility.TrTextContent("Steering"); public readonly GUIContent m_AgentAvoidanceHeader = EditorGUIUtility.TrTextContent("Obstacle Avoidance"); public readonly GUIContent m_AgentPathFindingHeader = EditorGUIUtility.TrTextContent("Path Finding"); - }; + } static Styles s_Styles; diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs index 20a2f9f04b..3899e9b18c 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsEditor.cs @@ -88,7 +88,6 @@ class SettingsContent public static readonly GUIContent iPhoneScriptCallOptimization = EditorGUIUtility.TrTextContent("Script Call Optimization*"); public static readonly GUIContent enableInternalProfiler = EditorGUIUtility.TrTextContent("Enable Internal Profiler* (Deprecated)", "Internal profiler counters should be accessed by scripts using UnityEngine.Profiling::Profiler API."); public static readonly GUIContent stripUnusedMeshComponents = EditorGUIUtility.TrTextContent("Optimize Mesh Data*", "Remove unused mesh components"); - public static readonly GUIContent protectGraphicsMemory = EditorGUIUtility.TrTextContent("Protect Graphics Memory", "Protect GPU memory from being read (on supported devices). Will prevent user from taking screenshots"); public static readonly GUIContent enableFrameTimingStats = EditorGUIUtility.TrTextContent("Enable Frame Timing Stats", "Enable gathering of CPU/GPU frame timing statistics."); public static readonly GUIContent useOSAutoRotation = EditorGUIUtility.TrTextContent("Use Animated Autorotation", "If set OS native animated autorotation method will be used. Otherwise orientation will be changed immediately."); public static readonly GUIContent UIPrerenderedIcon = EditorGUIUtility.TrTextContent("Prerendered Icon"); @@ -138,8 +137,9 @@ class SettingsContent public static readonly GUIContent mTRendering = EditorGUIUtility.TrTextContent("Multithreaded Rendering*"); public static readonly GUIContent staticBatching = EditorGUIUtility.TrTextContent("Static Batching"); public static readonly GUIContent dynamicBatching = EditorGUIUtility.TrTextContent("Dynamic Batching"); - public static readonly GUIContent graphicsJobs = EditorGUIUtility.TrTextContent("Graphics Jobs"); - public static readonly GUIContent graphicsJobsMode = EditorGUIUtility.TrTextContent("Graphics Jobs Mode*"); + public static readonly GUIContent graphicsJobsNonExperimental = EditorGUIUtility.TrTextContent("Graphics Jobs"); + public static readonly GUIContent graphicsJobsExperimental = EditorGUIUtility.TrTextContent("Graphics Jobs (Experimental)"); + public static readonly GUIContent graphicsJobsMode = EditorGUIUtility.TrTextContent("Graphics Jobs Mode"); public static readonly GUIContent applicationBuildNumber = EditorGUIUtility.TrTextContent("Build"); public static readonly GUIContent appleDeveloperTeamID = EditorGUIUtility.TrTextContent("iOS Developer Team ID", "Developers can retrieve their Team ID by visiting the Apple Developer site under Account > Membership."); public static readonly GUIContent useOnDemandResources = EditorGUIUtility.TrTextContent("Use on-demand resources*"); @@ -195,7 +195,8 @@ class SettingsContent public static string undoChangedIconString { get { return LocalizationDatabase.GetLocalizedString("Changed Icon"); } } public static string undoChangedGraphicsAPIString { get { return LocalizationDatabase.GetLocalizedString("Changed Graphics API Settings"); } } public static string undoChangedScriptingDefineString { get { return LocalizationDatabase.GetLocalizedString("Changed Scripting Define Settings"); } } - public static string undoChangedGraphicsJobsString { get { return LocalizationDatabase.GetLocalizedString("Changed Graphics Jobs Settings"); } } + public static string undoChangedGraphicsJobsString { get { return LocalizationDatabase.GetLocalizedString("Changed Graphics Jobs Setting"); } } + public static string undoChangedGraphicsJobModeString { get { return LocalizationDatabase.GetLocalizedString("Changed Graphics Job Mode Setting"); } } } // Icon layout constants @@ -816,11 +817,6 @@ private static bool TargetSupportsOptionalBuiltinSplashScreen(BuildTargetGroup t return targetGroup == BuildTargetGroup.Standalone; } - private static bool TargetSupportsProtectedGraphicsMem(BuildTargetGroup targetGroup) - { - return BuildTargetDiscovery.PlatformGroupHasFlag(targetGroup, TargetAttributes.ProtectedGraphicsMem); - } - public void ResolutionSectionGUI(BuildTargetGroup targetGroup, ISettingEditorExtension settingsExtension, int sectionIndex = 0) { if (BeginSettingsBox(sectionIndex, SettingsContent.resolutionPresentationTitle)) @@ -1643,6 +1639,7 @@ private void OtherSectionRenderingGUI(BuildPlatform platform, BuildTargetGroup t bool graphicsJobsOptionEnabled = true; bool graphicsJobs = PlayerSettings.GetGraphicsJobsForPlatform(platform.defaultTarget); bool newGraphicsJobs = graphicsJobs; + bool graphicsJobsModeOptionEnabled = graphicsJobs; if (targetGroup == BuildTargetGroup.XboxOne) { @@ -1650,31 +1647,44 @@ private void OtherSectionRenderingGUI(BuildPlatform platform, BuildTargetGroup t // no need for a drop down popup for XBoxOne // also if XboxOneD3D12 is selected as GraphicsAPI, then we want to set graphics jobs and disable the user option GraphicsDeviceType[] gfxAPIs = PlayerSettings.GetGraphicsAPIs(platform.defaultTarget); + GraphicsJobMode newGfxJobMode = GraphicsJobMode.Legacy; if (gfxAPIs[0] == GraphicsDeviceType.XboxOneD3D12) { - PlayerSettings.graphicsJobMode = GraphicsJobMode.Native; + newGfxJobMode = GraphicsJobMode.Native; graphicsJobsOptionEnabled = false; if (graphicsJobs == false) { PlayerSettings.SetGraphicsJobsForPlatform(platform.defaultTarget, true); + graphicsJobs = true; newGraphicsJobs = true; } } - else - { - PlayerSettings.graphicsJobMode = GraphicsJobMode.Legacy; - } + PlayerSettings.SetGraphicsJobModeForPlatform(platform.defaultTarget, newGfxJobMode); + graphicsJobsModeOptionEnabled = false; } EditorGUI.BeginChangeCheck(); + GUIContent graphicsJobsGUI = SettingsContent.graphicsJobsNonExperimental; + switch (platform.defaultTarget) + { + case BuildTarget.StandaloneOSX: + case BuildTarget.iOS: + case BuildTarget.tvOS: + case BuildTarget.Android: + graphicsJobsGUI = SettingsContent.graphicsJobsExperimental; + break; + default: + break; + } + using (new EditorGUI.DisabledScope(!graphicsJobsOptionEnabled)) { if (GUI.enabled) { - newGraphicsJobs = EditorGUILayout.Toggle(SettingsContent.graphicsJobs, graphicsJobs); + newGraphicsJobs = EditorGUILayout.Toggle(graphicsJobsGUI, graphicsJobs); } else { - EditorGUILayout.Toggle(SettingsContent.graphicsJobs, false); + EditorGUILayout.Toggle(graphicsJobsGUI, graphicsJobs); } } if (EditorGUI.EndChangeCheck() && (newGraphicsJobs != graphicsJobs)) @@ -1685,13 +1695,15 @@ private void OtherSectionRenderingGUI(BuildPlatform platform, BuildTargetGroup t if (gfxJobModesSupported) { - using (new EditorGUI.DisabledScope(!graphicsJobs)) + EditorGUI.BeginChangeCheck(); + using (new EditorGUI.DisabledScope(!graphicsJobsModeOptionEnabled)) { - GraphicsJobMode currGfxJobMode = PlayerSettings.graphicsJobMode; + GraphicsJobMode currGfxJobMode = PlayerSettings.GetGraphicsJobModeForPlatform(platform.defaultTarget); GraphicsJobMode newGfxJobMode = BuildEnumPopup(SettingsContent.graphicsJobsMode, currGfxJobMode, m_GfxJobModeValues, m_GfxJobModeNames); - if (newGfxJobMode != currGfxJobMode) + if (EditorGUI.EndChangeCheck() && (newGfxJobMode != currGfxJobMode)) { - PlayerSettings.graphicsJobMode = newGfxJobMode; + Undo.RecordObject(target, SettingsContent.undoChangedGraphicsJobModeString); + PlayerSettings.SetGraphicsJobModeForPlatform(platform.defaultTarget, newGfxJobMode); } } } @@ -1770,11 +1782,6 @@ private void OtherSectionRenderingGUI(BuildPlatform platform, BuildTargetGroup t } } - if (TargetSupportsProtectedGraphicsMem(targetGroup)) - { - PlayerSettings.protectGraphicsMemory = EditorGUILayout.Toggle(SettingsContent.protectGraphicsMemory, PlayerSettings.protectGraphicsMemory); - } - if (targetGroup == BuildTargetGroup.Standalone || (settingsExtension != null && settingsExtension.SupportsFrameTimingStatistics())) { PlayerSettings.enableFrameTimingStats = EditorGUILayout.Toggle(SettingsContent.enableFrameTimingStats, PlayerSettings.enableFrameTimingStats); @@ -2014,6 +2021,19 @@ private void OtherSectionConfigurationGUI(BuildPlatform platform, BuildTargetGro } } + bool showPrivacyPermissions = + targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS || + platform.defaultTarget == BuildTarget.StandaloneOSX; + + if (showPrivacyPermissions) + { + EditorGUILayout.PropertyField(m_CameraUsageDescription, SettingsContent.cameraUsageDescription); + EditorGUILayout.PropertyField(m_MicrophoneUsageDescription, SettingsContent.microphoneUsageDescription); + + if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) + EditorGUILayout.PropertyField(m_LocationUsageDescription, SettingsContent.locationUsageDescription); + } + bool showMobileSection = targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS || @@ -2033,13 +2053,6 @@ private void OtherSectionConfigurationGUI(BuildPlatform platform, BuildTargetGro if (supportsAccelerometerFrequency) EditorGUILayout.PropertyField(m_AccelerometerFrequency, SettingsContent.accelerometerFrequency); - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS) - { - EditorGUILayout.PropertyField(m_CameraUsageDescription, SettingsContent.cameraUsageDescription); - EditorGUILayout.PropertyField(m_LocationUsageDescription, SettingsContent.locationUsageDescription); - EditorGUILayout.PropertyField(m_MicrophoneUsageDescription, SettingsContent.microphoneUsageDescription); - } - if (targetGroup == BuildTargetGroup.iOS || targetGroup == BuildTargetGroup.tvOS || targetGroup == BuildTargetGroup.Android) { EditorGUILayout.PropertyField(m_MuteOtherAudioSources, SettingsContent.muteOtherAudioSources); diff --git a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs index e5457d5b0b..3226a81819 100644 --- a/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs +++ b/Editor/Mono/Inspector/PlayerSettingsEditor/PlayerSettingsSplashScreenEditor.cs @@ -215,7 +215,7 @@ private void DrawLogoListElementCallback(Rect rect, int index, bool isActive, bo private void DrawLogoListFooterCallback(Rect rect) { float totalDuration = Mathf.Max(k_MinLogoTime, m_TotalLogosDuration); - EditorGUI.LabelField(rect, "Splash Screen Duration: " + totalDuration.ToString(), EditorStyles.miniBoldLabel); + EditorGUI.LabelField(rect, "Splash Screen Duration: " + totalDuration, EditorStyles.miniBoldLabel); ReorderableList.defaultBehaviours.DrawFooter(rect, m_LogoList); } @@ -331,11 +331,11 @@ private void BuiltinCustomSplashScreenGUI() if (SplashScreen.isFinished) { SplashScreen.Begin(); - PreviewEditorWindow.RepaintAll(); - var preview = PreviewEditorWindow.GetMainPreviewWindow(); - if (preview) + PlayModeView.RepaintAll(); + var playModeView = PlayModeView.GetMainPlayModeView(); + if (playModeView) { - preview.Focus(); + playModeView.Focus(); } EditorApplication.update += PollSplashState; } @@ -423,12 +423,13 @@ private void BuiltinCustomSplashScreenGUI() void PollSplashState() { // Force the GameViews to repaint whilst showing the splash(1166664) - PreviewEditorWindow.RepaintAll(); + PlayModeView.RepaintAll(); // When the splash screen is playing we need to keep track so that we can update the preview button when it has finished. if (SplashScreen.isFinished) { - m_Owner.Repaint(); + var window = SettingsWindow.FindWindowByScope(SettingsScope.Project); + window?.Repaint(); EditorApplication.update -= PollSplashState; } } diff --git a/Editor/Mono/Inspector/PolygonEditorUtility.cs b/Editor/Mono/Inspector/PolygonEditorUtility.cs index 96a5e4cf0a..9fe0573ef1 100644 --- a/Editor/Mono/Inspector/PolygonEditorUtility.cs +++ b/Editor/Mono/Inspector/PolygonEditorUtility.cs @@ -109,7 +109,7 @@ public void OnSceneGUI() HandleUtility.s_CustomPickDistance = k_HandlePickDistance; // Find mouse positions in local and world space - Plane plane = new Plane(-transform.forward, Vector3.zero); + Plane plane = new Plane(-transform.forward, new Vector3(0f, 0f, transform.position.z)); Ray mouseRay = HandleUtility.GUIPointToWorldRay(evt.mousePosition); float dist; plane.Raycast(mouseRay, out dist); @@ -197,13 +197,13 @@ public void OnSceneGUI() p1 += colliderOffset; Vector3 worldPosV0 = transform.TransformPoint(p0); Vector3 worldPosV1 = transform.TransformPoint(p1); - worldPosV0.z = worldPosV1.z = 0; Handles.color = Color.green; Handles.DrawAAPolyLine(4.0f, new Vector3[] { worldPosV0, worldPosV1 }); Handles.color = Color.white; - Vector2 newPoint = GetNearestPointOnEdge(transform.TransformPoint(mouseLocalPos), worldPosV0, worldPosV1); + Vector3 newPoint = GetNearestPointOnEdge(transform.TransformPoint(mouseLocalPos), worldPosV0, worldPosV1); + newPoint.z = transform.position.z; EditorGUI.BeginChangeCheck(); float guiSize = HandleUtility.GetHandleSize(newPoint) * 0.04f; @@ -236,7 +236,6 @@ public void OnSceneGUI() PolygonEditor.GetPoint(m_SelectedPath, m_SelectedVertex, out point); point += colliderOffset; Vector3 worldPos = transform.TransformPoint(point); - worldPos.z = 0; Vector2 screenPos = HandleUtility.WorldToGUIPoint(worldPos); float guiSize = HandleUtility.GetHandleSize(worldPos) * 0.04f; @@ -322,7 +321,6 @@ private void DrawPolygonCollider(Transform transform) Vector3 worldPosV0 = transform.TransformPoint(p0); Vector3 worldPosV1 = transform.TransformPoint(p1); - worldPosV0.z = worldPosV1.z = transform.position.z; Handles.color = Color.green; Handles.DrawAAPolyLine(1.0f, new Vector3[] { worldPosV0, worldPosV1 }); @@ -359,7 +357,6 @@ private void DrawEdgesForSelectedPoint(Vector3 worldPos, Transform transform, bo p1 += colliderOffset; Vector3 worldPosV0 = transform.TransformPoint(p0); Vector3 worldPosV1 = transform.TransformPoint(p1); - worldPosV0.z = worldPosV1.z = worldPos.z; float lineWidth = 4.0f; if (drawLeft) diff --git a/Editor/Mono/Inspector/PropertyDrawerCache.cs b/Editor/Mono/Inspector/PropertyDrawerCache.cs index 2a0a64eb61..b64e2f3ace 100644 --- a/Editor/Mono/Inspector/PropertyDrawerCache.cs +++ b/Editor/Mono/Inspector/PropertyDrawerCache.cs @@ -32,7 +32,7 @@ private static int GetPropertyHash(SerializedProperty property) return 0; // For efficiency, ignore indices inside brackets [] in order to make array elements share handlers. - int key = property.serializedObject.targetObject.GetInstanceID() ^ property.hashCodeForPropertyPathWithoutArrayIndex; + int key = property.serializedObject.targetObject.GetInstanceID() ^ property.hashCodeForPropertyPath; if (property.propertyType == SerializedPropertyType.ObjectReference) { key ^= property.objectReferenceInstanceIDValue; diff --git a/Editor/Mono/Inspector/QualitySettingsEditor.cs b/Editor/Mono/Inspector/QualitySettingsEditor.cs index 84e1288005..2913ef2779 100644 --- a/Editor/Mono/Inspector/QualitySettingsEditor.cs +++ b/Editor/Mono/Inspector/QualitySettingsEditor.cs @@ -172,9 +172,7 @@ private int DoQualityLevelSelection(int currentQualitylevel, IList 0) - DrawLabelBetweenPoints(points[axis, 0] - dir, points[axis, 1] - dir, GUIContent.Temp(startValue.ToString() + "%")); + DrawLabelBetweenPoints(points[axis, 0] - dir, points[axis, 1] - dir, GUIContent.Temp(startValue + "%")); if (midValue > 0) - DrawLabelBetweenPoints(points[axis, 1] - dir, points[axis, 2] - dir, GUIContent.Temp(midValue.ToString() + "%")); + DrawLabelBetweenPoints(points[axis, 1] - dir, points[axis, 2] - dir, GUIContent.Temp(midValue + "%")); if (endValue > 0) - DrawLabelBetweenPoints(points[axis, 2] - dir, points[axis, 3] - dir, GUIContent.Temp(endValue.ToString() + "%")); + DrawLabelBetweenPoints(points[axis, 2] - dir, points[axis, 3] - dir, GUIContent.Temp(endValue + "%")); } } diff --git a/Editor/Mono/Inspector/RenderPipelineEditorUtility.cs b/Editor/Mono/Inspector/RenderPipelineEditorUtility.cs index 241c0c0a52..f44bb55b9f 100644 --- a/Editor/Mono/Inspector/RenderPipelineEditorUtility.cs +++ b/Editor/Mono/Inspector/RenderPipelineEditorUtility.cs @@ -15,7 +15,7 @@ public class ScriptableRenderPipelineExtensionAttribute : Attribute public ScriptableRenderPipelineExtensionAttribute(Type renderPipelineAsset) { if (!(renderPipelineAsset?.IsSubclassOf(typeof(RenderPipelineAsset)) ?? false)) - throw new ArgumentException($"Given renderPipelineAsset must derive from RenderPipelineAsset"); + throw new ArgumentException("Given renderPipelineAsset must derive from RenderPipelineAsset"); renderPipelineType = renderPipelineAsset; } diff --git a/Editor/Mono/Inspector/Rigidbody2DEditor.cs b/Editor/Mono/Inspector/Rigidbody2DEditor.cs index 92227aed1d..885c7a173e 100644 --- a/Editor/Mono/Inspector/Rigidbody2DEditor.cs +++ b/Editor/Mono/Inspector/Rigidbody2DEditor.cs @@ -144,6 +144,14 @@ public override void OnInspectorGUI() EditorGUILayout.PropertyField(m_CollisionDetection); EditorGUILayout.PropertyField(m_SleepingMode); EditorGUILayout.PropertyField(m_Interpolate); + if (targets.Any(x => (x as Rigidbody2D).interpolation != RigidbodyInterpolation2D.None)) + { + if (Physics2D.simulationMode == SimulationMode2D.Update) + EditorGUILayout.HelpBox("The physics simulation mode is set to run per-frame. Any interpolation mode will be ignored and can be set to 'None'.", MessageType.Info); + + if (Physics2D.simulationMode == SimulationMode2D.Script) + EditorGUILayout.HelpBox("The physics simulation mode is set to run manually in the scripts. Some or all selected Rigidbody2D are using an interpolation mode other than 'None' which will be executed per-frame. If the manual simulation is being run per-frame then the interpolation mode should be set to 'None'.", MessageType.Info); + } GUILayout.BeginHorizontal(); m_Constraints.isExpanded = EditorGUILayout.Foldout(m_Constraints.isExpanded, "Constraints", true); @@ -157,10 +165,6 @@ public override void OnInspectorGUI() ToggleFreezeRotation(constraints, m_FreezeRotationLabel, 2); EditorGUI.indentLevel--; } - - // Provide end-user warning about the equivalence of all constraints on versus no Rigidbody2D component. - if (constraints == RigidbodyConstraints2D.FreezeAll) - EditorGUILayout.HelpBox("Rather than turning on all constraints, you may want to consider removing the Rigidbody2D component which makes any colliders static. This gives far better performance overall.", MessageType.Info); } EditorGUILayout.EndFadeGroup(); } diff --git a/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs b/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs index 537657f819..b657681b01 100644 --- a/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs +++ b/Editor/Mono/Inspector/ScriptExecutionOrderInspector.cs @@ -667,6 +667,8 @@ class DragReorderGUI private static bool IsDefaultTimeElement(MonoScript element) { + if (element == null) + return true; return (element.name == string.Empty); } diff --git a/Editor/Mono/Inspector/ShaderInspector.cs b/Editor/Mono/Inspector/ShaderInspector.cs index 082bd99238..6113464b36 100644 --- a/Editor/Mono/Inspector/ShaderInspector.cs +++ b/Editor/Mono/Inspector/ShaderInspector.cs @@ -59,6 +59,19 @@ internal class Styles static readonly int kErrorViewHash = "ShaderErrorView".GetHashCode(); Vector2 m_ScrollPosition = Vector2.zero; + private Material m_SrpCompatibilityCheckMaterial = null; + + public Material srpCompatibilityCheckMaterial + { + get + { + if (m_SrpCompatibilityCheckMaterial == null) + { + m_SrpCompatibilityCheckMaterial = new Material(target as Shader); + } + return m_SrpCompatibilityCheckMaterial; + } + } public virtual void OnEnable() { @@ -66,6 +79,14 @@ public virtual void OnEnable() ShaderUtil.FetchCachedMessages(s); } + public virtual void OnDisable() + { + if (m_SrpCompatibilityCheckMaterial != null) + { + GameObject.DestroyImmediate(m_SrpCompatibilityCheckMaterial); + } + } + private static string GetPropertyType(Shader s, int index) { ShaderUtil.ShaderPropertyType type = ShaderUtil.GetPropertyType(s, index); @@ -116,8 +137,8 @@ public override void OnInspectorGUI() // 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 + // NOTE: Force the shader compilation to ensure GetSRPBatcherCompatibilityCode will be up to date + srpCompatibilityCheckMaterial.SetPass(0); int subShader = ShaderUtil.GetShaderActiveSubshaderIndex(s); int SRPErrCode = ShaderUtil.GetSRPBatcherCompatibilityCode(s, subShader); string result = (0 == SRPErrCode) ? "compatible" : "not compatible"; @@ -127,6 +148,7 @@ public override void OnInspectorGUI() EditorGUILayout.HelpBox(ShaderUtil.GetSRPBatcherCompatibilityIssueReason(s, subShader, SRPErrCode), MessageType.Info); } } + ShowShaderProperties(s); } } @@ -692,7 +714,7 @@ void DoShaderVariants(EditorWindow caller, ref Rect drawPos) buttonRect.width -= Styles.menuItem.padding.left + 4; GUI.Label(buttonRect, variantText); buttonRect.xMin = buttonRect.xMax - 40; - if (GUI.Button(buttonRect, "Show", EditorStyles.miniButton)) + if (GUI.Button(buttonRect, "Show", EditorStyles.miniButtonMid)) { ShaderUtil.OpenShaderCombinations(m_Shader, strip); caller.Close(); diff --git a/Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs b/Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs index 1e03433cc8..a5c24551d1 100644 --- a/Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs +++ b/Editor/Mono/Inspector/ShaderVariantCollectionInspector.cs @@ -343,7 +343,7 @@ private void Draw(Rect windowRect) var passType = (UnityEngine.Rendering.PassType)m_FilteredVariantTypes[i]; var wasSelected = m_SelectedVariants.Contains(i); var keywordString = string.IsNullOrEmpty(m_FilteredVariantKeywords[i][0]) ? "" : string.Join(" ", m_FilteredVariantKeywords[i]); - var displayString = passType.ToString() + " " + keywordString.ToLowerInvariant(); + var displayString = passType + " " + keywordString.ToLowerInvariant(); var isSelected = GUI.Toggle(rect, wasSelected, displayString, Styles.sMenuItem); rect.y += rect.height; diff --git a/Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs b/Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs index dc1b27b34d..cce5cd35d5 100644 --- a/Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs +++ b/Editor/Mono/Inspector/ShadowCascadeSplitGUI.cs @@ -47,7 +47,7 @@ public DragCache(int activePartition, float normalizedPartitionSize, Vector2 cur m_NormalizedPartitionSize = normalizedPartitionSize; m_LastCachedMousePosition = currentMousePos; } - }; + } private static DragCache s_DragCache; private static readonly int s_CascadeSliderId = "s_CascadeSliderId".GetHashCode(); diff --git a/Editor/Mono/Inspector/TextureInspector.cs b/Editor/Mono/Inspector/TextureInspector.cs index 338b561fe0..44d4db529b 100644 --- a/Editor/Mono/Inspector/TextureInspector.cs +++ b/Editor/Mono/Inspector/TextureInspector.cs @@ -121,7 +121,7 @@ enum PreviewMode G, B, A, - }; + } private PreviewMode m_PreviewMode = PreviewMode.RGB; public bool showAlpha @@ -789,7 +789,7 @@ public override string GetInfoString() Texture t = target as Texture; Texture2D t2 = target as Texture2D; TextureImporter textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(t)) as TextureImporter; - string info = t.width.ToString() + "x" + t.height.ToString(); + string info = t.width + "x" + t.height; bool showSize = true; bool isPackedSprite = textureImporter && textureImporter.qualifiesForSpritePacking; diff --git a/Editor/Mono/Inspector/TimelineControl.cs b/Editor/Mono/Inspector/TimelineControl.cs index 1117bb7ccd..36bdad390f 100644 --- a/Editor/Mono/Inspector/TimelineControl.cs +++ b/Editor/Mono/Inspector/TimelineControl.cs @@ -44,7 +44,7 @@ internal class TimelineControl private float m_TimeStartDrag = 0f; private float m_TimeOffset = 0f; - private enum DragStates { None, LeftSelection, RightSelection, FullSelection, Destination, Source, Playhead, TimeArea }; + private enum DragStates { None, LeftSelection, RightSelection, FullSelection, Destination, Source, Playhead, TimeArea } private DragStates m_DragState = DragStates.None; private int id = -1; diff --git a/Editor/Mono/Inspector/WebCamTextureInspector.cs b/Editor/Mono/Inspector/WebCamTextureInspector.cs index 2dd9740e3d..13d1690a54 100644 --- a/Editor/Mono/Inspector/WebCamTextureInspector.cs +++ b/Editor/Mono/Inspector/WebCamTextureInspector.cs @@ -100,7 +100,7 @@ public void OnDisable() public override string GetInfoString() { Texture t = target as Texture; - string info = t.width.ToString() + "x" + t.height.ToString(); + string info = t.width + "x" + t.height; GraphicsFormat format = GraphicsFormatUtility.GetFormat(t); info += " " + GraphicsFormatUtility.GetFormatString(format); return info; diff --git a/Editor/Mono/InternalEditorUtility.bindings.cs b/Editor/Mono/InternalEditorUtility.bindings.cs index e99cce90f8..4b8b95d57a 100644 --- a/Editor/Mono/InternalEditorUtility.bindings.cs +++ b/Editor/Mono/InternalEditorUtility.bindings.cs @@ -198,8 +198,11 @@ internal static void FixNormalmapTexture(MaterialProperty prop) [FreeFunction("InternalEditorUtilityBindings::CreateScriptableObjectUnchecked")] extern internal static int CreateScriptableObjectUnchecked(MonoScript script); - [StaticAccessor("GetApplication()", StaticAccessorType.Dot)] - extern public static void RequestScriptReload(); + [Obsolete("RequestScriptReload has been deprecated. Use UnityEditor.EditorUtility.RequestScriptReload instead (UnityUpgradable) -> [UnityEditor] UnityEditor.EditorUtility.RequestScriptReload(*)")] + public static void RequestScriptReload() + { + EditorUtility.RequestScriptReload(); + } // Repaint all views on next tick. Used when the user changes skins in the prefs. [StaticAccessor("GetApplication()", StaticAccessorType.Dot)] @@ -620,6 +623,9 @@ extern public static float remoteScreenHeight [FreeFunction] extern public static string GetNoDiffToolsDetectedMessage(); + [FreeFunction("SetCustomDiffToolData")] + extern internal static void SetCustomDiffToolData(string path, string diff2Command, string diff3Command, string mergeCommand); + [FreeFunction("InternalEditorUtilityBindings::TransformBounds")] extern public static Bounds TransformBounds(Bounds b, Transform t); diff --git a/Editor/Mono/InternalEditorUtility.cs b/Editor/Mono/InternalEditorUtility.cs index 0a1e272ff0..2e490d7845 100644 --- a/Editor/Mono/InternalEditorUtility.cs +++ b/Editor/Mono/InternalEditorUtility.cs @@ -150,52 +150,163 @@ public static void ShowGameView() WindowLayout.ShowAppropriateViewOnEnterExitPlaymode(true); } - // Multi selection handling. Returns new list of selected instanceIDs + internal struct AssetReference + { + // The guid is always valid. Assets not yet present will not have an instanceID yet. + // Could be because it is on-demand imported. + public string guid; + public int instanceID; // instanceID of an object in an asset if the asset is available in imported form. Else 0. + + public sealed class GuidThenInstanceIDEqualityComparer : IEqualityComparer + { + public bool Equals(AssetReference x, AssetReference y) + { + if (!string.IsNullOrEmpty(x.guid) || !string.IsNullOrEmpty(y.guid)) + string.Equals(x.guid, y.guid); + + // Both guids are nullOrEmpty now + return x.instanceID == y.instanceID; + } + + public int GetHashCode(AssetReference assetReference) + { + return (assetReference.instanceID * 397) + ^ (assetReference.guid != null ? assetReference.guid.GetHashCode() : 0); + } + } + } + public static List GetNewSelection(int clickedInstanceID, List allInstanceIDs, List selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection) { - List newSelection = new List(); + return GetNewSelection(clickedInstanceID, allInstanceIDs, selectedInstanceIDs, lastClickedInstanceID, keepMultiSelection, useShiftAsActionKey, allowMultiSelection, Event.current.shift, EditorGUI.actionKey); + } + + internal static List GetNewSelection(int clickedInstanceID, List allInstanceIDs, List selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection, bool shiftKeyIsDown, bool actionKeyIsDown) + { + List allGuids = null; + var clicked = new AssetReference() { guid = null, instanceID = clickedInstanceID }; - bool useShift = Event.current.shift || (EditorGUI.actionKey && useShiftAsActionKey); - bool useActionKey = EditorGUI.actionKey && !useShiftAsActionKey; + return GetNewSelection(ref clicked, allInstanceIDs, allGuids, selectedInstanceIDs, lastClickedInstanceID, keepMultiSelection, useShiftAsActionKey, allowMultiSelection, shiftKeyIsDown, actionKeyIsDown); + } + + internal static void EnsureInstanceId(ref AssetReference entry) + { + if (entry.instanceID != 0 || string.IsNullOrEmpty(entry.guid)) + return; + + var guids = new string[] { entry.guid }; + UnityEditor.Experimental.AssetDatabaseExperimental.GetArtifactHashes(guids); + string path = AssetDatabase.GUIDToAssetPath(entry.guid); + entry.instanceID = AssetDatabase.GetMainAssetInstanceID(path); + } + + internal static List EnsureInstanceIds(List entryInstanceIds, List entryInstanceGuids, int from, int to) + { + List guids = new List(); + + for (int i = from; i <= to; ++i) + { + if (entryInstanceIds[i] == 0) + guids.Add(entryInstanceGuids[i]); + } + + // Force import if needed so that we can get an instance ID for the entry + + if (guids.Count == 0) + { + return entryInstanceIds.GetRange(from, to - from + 1); + } + else + { + UnityEditor.Experimental.AssetDatabaseExperimental.GetArtifactHashes(guids.ToArray()); + var newSelection = new List(to - from + 1); + + for (int i = from; i <= to; ++i) + { + int instanceID = entryInstanceIds[i]; + if (instanceID == 0) + { + string path = AssetDatabase.GUIDToAssetPath(entryInstanceGuids[i]); + instanceID = AssetDatabase.GetMainAssetInstanceID(path); + entryInstanceIds[i] = instanceID; + } + newSelection.Add(instanceID); + } + return newSelection; + } + } + + internal static List GetNewSelection(ref AssetReference clickedEntry, List allEntryInstanceIDs, List allEntryGuids, List selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection) + { + return GetNewSelection(ref clickedEntry, allEntryInstanceIDs, allEntryGuids, selectedInstanceIDs, lastClickedInstanceID, keepMultiSelection, useShiftAsActionKey, allowMultiSelection, Event.current.shift, EditorGUI.actionKey); + } + + // Multi selection handling. Returns new list of selected instanceIDs + internal static List GetNewSelection(ref AssetReference clickedEntry, List allEntryInstanceIDs, List allEntryGuids, List selectedInstanceIDs, int lastClickedInstanceID, bool keepMultiSelection, bool useShiftAsActionKey, bool allowMultiSelection, bool shiftKeyIsDown, bool actionKeyIsDown) + { + bool useShift = shiftKeyIsDown || (actionKeyIsDown && useShiftAsActionKey); + bool useActionKey = actionKeyIsDown && !useShiftAsActionKey; if (!allowMultiSelection) useShift = useActionKey = false; // Toggle selected node from selection if (useActionKey) { - newSelection.AddRange(selectedInstanceIDs); - if (newSelection.Contains(clickedInstanceID)) - newSelection.Remove(clickedInstanceID); + var newSelection = new List(selectedInstanceIDs); + if (newSelection.Contains(clickedEntry.instanceID)) + newSelection.Remove(clickedEntry.instanceID); else - newSelection.Add(clickedInstanceID); + { + EnsureInstanceId(ref clickedEntry); + newSelection.Add(clickedEntry.instanceID); + } + return newSelection; } // Select everything between the first selected object and the selected else if (useShift) { - if (clickedInstanceID == lastClickedInstanceID) + if (clickedEntry.instanceID == lastClickedInstanceID) { - newSelection.AddRange(selectedInstanceIDs); - return newSelection; + return new List(selectedInstanceIDs); } int firstIndex; int lastIndex; - if (!GetFirstAndLastSelected(allInstanceIDs, selectedInstanceIDs, out firstIndex, out lastIndex)) + if (!GetFirstAndLastSelected(allEntryInstanceIDs, selectedInstanceIDs, out firstIndex, out lastIndex)) { // We had no selection - newSelection.Add(clickedInstanceID); + EnsureInstanceId(ref clickedEntry); + var newSelection = new List(1); + newSelection.Add(clickedEntry.instanceID); return newSelection; } int newIndex = -1; int prevIndex = -1; - for (int i = 0; i < allInstanceIDs.Count; ++i) + + // Only valid in case the selection concerns assets + + EnsureInstanceId(ref clickedEntry); + int clickedInstanceID = clickedEntry.instanceID; + + if (lastClickedInstanceID != 0) { - if (allInstanceIDs[i] == clickedInstanceID) - newIndex = i; - if (lastClickedInstanceID != 0) - if (allInstanceIDs[i] == lastClickedInstanceID) + for (int i = 0; i < allEntryInstanceIDs.Count; ++i) + { + if (allEntryInstanceIDs[i] == clickedInstanceID) + newIndex = i; + + if (allEntryInstanceIDs[i] == lastClickedInstanceID) prevIndex = i; + } + } + else + { + for (int i = 0; i < allEntryInstanceIDs.Count; ++i) + { + if (allEntryInstanceIDs[i] == clickedInstanceID) + newIndex = i; + } } System.Diagnostics.Debug.Assert(newIndex != -1); // new item should be part of visible folder set @@ -229,10 +340,11 @@ public static List GetNewSelection(int clickedInstanceID, List allInst } // Outcomment to debug - //Debug.Log (clickedInstanceID + ", firstIndex " + firstIndex + ", lastIndex " + lastIndex + ", newIndex " + newIndex + " " + ", lastClickedIndex " + prevIndex + ", from " + from + ", to " + to); - - for (int i = from; i <= to; ++i) - newSelection.Add(allInstanceIDs[i]); + //Debug.Log (clickedEntry + ", firstIndex " + firstIndex + ", lastIndex " + lastIndex + ", newIndex " + newIndex + " " + ", lastClickedIndex " + prevIndex + ", from " + from + ", to " + to); + if (allEntryGuids == null) + return allEntryInstanceIDs.GetRange(from, to - from + 1); + else + return EnsureInstanceIds(allEntryInstanceIDs, allEntryGuids, from, to); } // Just set the selection to the clicked object else @@ -241,26 +353,26 @@ public static List GetNewSelection(int clickedInstanceID, List allInst { // Don't change selection on mouse down when clicking on selected item. // This is for dragging in case with multiple items selected or right click (mouse down should not unselect the rest). - if (selectedInstanceIDs.Contains(clickedInstanceID)) + if (selectedInstanceIDs.Contains(clickedEntry.instanceID)) { - newSelection.AddRange(selectedInstanceIDs); - return newSelection; + return new List(selectedInstanceIDs); } } - newSelection.Add(clickedInstanceID); + EnsureInstanceId(ref clickedEntry); + var newSelection = new List(1); + newSelection.Add(clickedEntry.instanceID); + return newSelection; } - - return newSelection; } - static bool GetFirstAndLastSelected(List allInstanceIDs, List selectedInstanceIDs, out int firstIndex, out int lastIndex) + static bool GetFirstAndLastSelected(List allEntries, List selectedInstanceIDs, out int firstIndex, out int lastIndex) { firstIndex = -1; lastIndex = -1; - for (int i = 0; i < allInstanceIDs.Count; ++i) + for (int i = 0; i < allEntries.Count; ++i) { - if (selectedInstanceIDs.Contains(allInstanceIDs[i])) + if (selectedInstanceIDs.Contains(allEntries[i])) { if (firstIndex == -1) firstIndex = i; @@ -424,10 +536,10 @@ internal static string[] GetCompilationDefines(EditorScriptCompilationOptions op public static void SetShowGizmos(bool value) { - var view = PreviewEditorWindow.GetMainPreviewWindow(); + var view = PlayModeView.GetMainPlayModeView(); if (view == null) - view = PreviewEditorWindow.GetRenderingPreview(); + view = PlayModeView.GetRenderingView(); if (view == null) return; diff --git a/Editor/Mono/JSProxy/JSProxyMgr.cs b/Editor/Mono/JSProxy/JSProxyMgr.cs index 84f96dc753..8166afc896 100644 --- a/Editor/Mono/JSProxy/JSProxyMgr.cs +++ b/Editor/Mono/JSProxy/JSProxyMgr.cs @@ -104,7 +104,7 @@ public JspmMethodInfo(string name, string[] parameters) this.name = name; this.parameters = parameters; } - }; + } internal class JspmStubInfo { @@ -118,7 +118,7 @@ public JspmStubInfo(JspmPropertyInfo[] properties, JspmMethodInfo[] methods, str this.properties = properties; this.events = events; } - }; + } internal class JspmResult { @@ -139,7 +139,7 @@ public JspmResult(long messageID, int status) this.messageID = messageID; this.status = status; } - }; + } internal class JspmError : JspmResult { @@ -151,7 +151,7 @@ public JspmError(long messageID, int status, string errorClass, string message) public string errorClass; public string message; - }; + } internal class JspmSuccess : JspmResult { @@ -164,7 +164,7 @@ public JspmSuccess(long messageID, object result, string type) this.result = result; this.type = type; } - }; + } internal class JspmStubInfoSuccess : JspmSuccess { @@ -175,7 +175,7 @@ public JspmStubInfoSuccess(long messageID, string reference, JspmPropertyInfo[] { this.reference = reference; } - }; + } [InitializeOnLoad] internal class JSProxyMgr diff --git a/Editor/Mono/JSProxy/WebScriptObject.cs b/Editor/Mono/JSProxy/WebScriptObject.cs index aebfd4ae11..bbe9a6fdfd 100644 --- a/Editor/Mono/JSProxy/WebScriptObject.cs +++ b/Editor/Mono/JSProxy/WebScriptObject.cs @@ -48,5 +48,5 @@ public bool processMessage(string jsonRequest, WebViewV8CallbackCSharp callback) { return ProcessMessage(jsonRequest, callback); } - }; + } } diff --git a/Editor/Mono/LODUtility.bindings.cs b/Editor/Mono/LODUtility.bindings.cs new file mode 100644 index 0000000000..53d4426ba7 --- /dev/null +++ b/Editor/Mono/LODUtility.bindings.cs @@ -0,0 +1,50 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using UnityEngine; +using UnityEngine.Bindings; + +namespace UnityEditor +{ + internal struct LODVisualizationInformation + { + public int triangleCount; + public int vertexCount; + public int rendererCount; + public int submeshCount; + + public int activeLODLevel; + public float activeLODFade; + public float activeDistance; + public float activeRelativeScreenSize; + public float activePixelSize; + public float worldSpaceSize; + } + + [NativeHeader("Editor/Mono/LODUtility.bindings.h")] + public sealed class LODUtility + { + [FreeFunction("LODUtilityBindings::CalculateVisualizationData")] + extern internal static LODVisualizationInformation CalculateVisualizationData(Camera camera, LODGroup group, int lodLevel); + + [FreeFunction("LODUtilityBindings::CalculateDistance")] + extern internal static float CalculateDistance(Camera camera, float relativeScreenHeight, LODGroup group); + + internal static Vector3 CalculateWorldReferencePoint(LODGroup group) + { + return group.worldReferencePoint; + } + + [FreeFunction] + extern internal static bool NeedUpdateLODGroupBoundingBox(LODGroup group); + + public static void CalculateLODGroupBoundingBox(LODGroup group) + { + if (group == null) + throw new ArgumentNullException("group"); + group.RecalculateBounds(); + } + } +} diff --git a/Editor/Mono/ModuleMetadata.bindings.cs b/Editor/Mono/ModuleMetadata.bindings.cs new file mode 100644 index 0000000000..aaa1d009e9 --- /dev/null +++ b/Editor/Mono/ModuleMetadata.bindings.cs @@ -0,0 +1,56 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Linq; +using UnityEngine; +using UnityEngine.Bindings; + +namespace UnityEditor +{ + [NativeHeader("Editor/Src/BuildPipeline/ModuleMetadata.h")] + internal enum ModuleIncludeSetting + { + Auto = 0, + ForceExclude = 1, + ForceInclude = 2 + } + + [StaticAccessor("ModuleMetadata::Get()", StaticAccessorType.Dot)] + [NativeHeader("Editor/Src/BuildPipeline/ModuleMetadata.h")] + [NativeHeader("Editor/Mono/ModuleMetadata.bindings.h")] + internal sealed class ModuleMetadata + { + [FreeFunction("ModuleMetadataBindings::GetModuleNames")] + public extern static string[] GetModuleNames(); + + [FreeFunction("ModuleMetadataBindings::GetModuleDependencies")] + public extern static string[] GetModuleDependencies(string moduleName); + + [FreeFunction("ModuleMetadataBindings::IsStrippableModule")] + extern public static bool IsStrippableModule(string moduleName); + + public static UnityType[] GetModuleTypes(string moduleName) + { + var runtimeTypeIndices = GetModuleTypeIndices(moduleName); + return runtimeTypeIndices.Select(index => UnityType.GetTypeByRuntimeTypeIndex(index)).ToArray(); + } + + [NativeName("GetModuleIncludeSetting")] + extern public static ModuleIncludeSetting GetModuleIncludeSettingForModule(string module); + + [FreeFunction("ModuleMetadataBindings::SetModuleIncludeSettingForModule")] + extern public static void SetModuleIncludeSettingForModule(string module, ModuleIncludeSetting setting); + + [FreeFunction("ModuleMetadataBindings::GetModuleIncludeSettingForObject")] + extern internal static ModuleIncludeSetting GetModuleIncludeSettingForObject(Object o); + + [FreeFunction("ModuleMetadataBindings::GetModuleForObject")] + extern internal static string GetModuleForObject(Object o); + + [FreeFunction("ModuleMetadataBindings::GetModuleTypeIndices")] + extern internal static uint[] GetModuleTypeIndices(string moduleName); + + extern public static string GetICallModule(string icall); + } +} diff --git a/Editor/Mono/Modules/DefaultPluginImporterExtension.cs b/Editor/Mono/Modules/DefaultPluginImporterExtension.cs index 4e27dd1fb8..45e5937d1d 100644 --- a/Editor/Mono/Modules/DefaultPluginImporterExtension.cs +++ b/Editor/Mono/Modules/DefaultPluginImporterExtension.cs @@ -3,12 +3,13 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Collections.Generic; using System.ComponentModel; +using System.IO; +using System.Linq; using System.Text; +using UnityEditor.Compilation; using UnityEngine; -using System.Linq; -using System.IO; -using System.Collections.Generic; namespace UnityEditor.Modules { @@ -150,7 +151,14 @@ public virtual string CalculateFinalPluginPath(string platformName, PluginImport protected Dictionary> GetCompatiblePlugins(string buildTargetName) { - IEnumerable plugins = PluginImporter.GetAllImporters().Where(imp => imp.GetCompatibleWithPlatformOrAnyPlatformBuildTarget(buildTargetName)); + var assemblies = CompilationPipeline.GetAssemblies(); + var assemblyDefines = new Dictionary(assemblies.Length); + foreach (var assembly in assemblies) + { + assemblyDefines.Add(assembly.name, assembly.defines); + } + + IEnumerable plugins = PluginImporter.GetAllImporters().Where(imp => imp.GetCompatibleWithPlatformOrAnyPlatformBuildTarget(buildTargetName) && imp.IsCompatibleWithDefines(assemblyDefines.ContainsKey(imp.name) ? assemblyDefines[imp.name] : null)); Dictionary> matchingPlugins = new Dictionary>(); foreach (var plugin in plugins) diff --git a/Editor/Mono/Modules/ModuleManager.cs b/Editor/Mono/Modules/ModuleManager.cs index 28ebb3b3ed..f422ac3700 100644 --- a/Editor/Mono/Modules/ModuleManager.cs +++ b/Editor/Mono/Modules/ModuleManager.cs @@ -317,7 +317,6 @@ static void LoadLegacyExtensionsFromIvyFiles() catch (Exception ex) { Console.WriteLine("Error scanning for extensions. {0}", ex); - return; } } @@ -341,7 +340,7 @@ static bool TryParseBuildTarget(string targetString, out BuildTargetGroup buildT private static void RegisterPlatformSupportModules() { var allTypesWithInterface = TypeCache.GetTypesDerivedFrom(); - s_PlatformModules = new Dictionary(allTypesWithInterface.Count()); + s_PlatformModules = new Dictionary(allTypesWithInterface.Count); foreach (var type in allTypesWithInterface) { diff --git a/Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs b/Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs index d8a39190c8..df9422f8f4 100644 --- a/Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs +++ b/Editor/Mono/Networking/PlayerConnection/AttachToPlayerGUI.cs @@ -118,7 +118,7 @@ public string connectionName get { string name = ProfilerDriver.GetConnectionIdentifier(ProfilerDriver.connectedProfiler); - if (m_EditorModeTargetState.HasValue && name.StartsWith(k_EditorConnectionName)) + if (m_EditorModeTargetState.HasValue && name.Contains(k_EditorConnectionName)) { if (m_EditorModeTargetConnectionStatus(EditorConnectionTarget.MainEditorProcessEditmode)) name = Content.Editmode.text; @@ -177,7 +177,7 @@ private static void SuccessfullyConnectedToPlayer(string player, EditorConnectio } else { - if (player.StartsWith(k_EditorConnectionName)) + if (player.Contains(k_EditorConnectionName)) { // if e.g. the console or the memory profiler connects to the Editor, the profiler should switch to PlayMode profiling, not to Editmode profiling // especially since falling back onto the Editor is the default. @@ -261,9 +261,9 @@ void AddAvailablePlayerConnections(GenericMenu menuOptions, ref bool hasOpenConn } if (enabled) { - if (m_EditorModeTargetState.HasValue && name.StartsWith(k_EditorConnectionName)) + if (m_EditorModeTargetState.HasValue && name.Contains(k_EditorConnectionName)) { - menuOptions.AddItem(Content.Playmode, isConnected && m_EditorModeTargetConnectionStatus(EditorConnectionTarget.MainEditorProcessPlaymode), () => + menuOptions.AddItem(Content.Playmode, isConnected && !m_EditorModeTargetConnectionStatus(EditorConnectionTarget.MainEditorProcessPlaymode), () => { ProfilerDriver.connectedProfiler = guid; SuccessfullyConnectedToPlayer(connectionName, EditorConnectionTarget.MainEditorProcessPlaymode); diff --git a/Editor/Mono/ObjectListArea.cs b/Editor/Mono/ObjectListArea.cs index ea3cf67bc5..0a3a95e2f4 100644 --- a/Editor/Mono/ObjectListArea.cs +++ b/Editor/Mono/ObjectListArea.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using UnityEditorInternal; +using AssetReference = UnityEditorInternal.InternalEditorUtility.AssetReference; namespace UnityEditor { @@ -111,7 +112,7 @@ static GUIStyle GetStyle(string styleName) public bool foldersFirst { get; set; } int m_KeyboardControlID; - Dictionary m_InstanceIDToCroppedNameMap = new Dictionary(); + Dictionary m_AssetReferenceToCroppedNameMap = new Dictionary(new AssetReference.GuidThenInstanceIDEqualityComparer()); int m_WidthUsedForCroppingName; bool m_AllowRenameOnMouseUp = true; @@ -264,6 +265,9 @@ public void Init(Rect rect, HierarchyType hierarchyType, SearchFilter searchFilt // Prepare data SetupData(true); + + // End renaming if a rename was in progress + EndRename(true); } bool HasFocus() @@ -319,7 +323,7 @@ void QueryAssetStore() if (queryFilter != m_LastAssetStoreQuerySearchFilter + m_LastAssetStoreQueryClassName + m_LastAssetStoreQueryLabels) m_RequeryAssetStore = true; - if (results.error != null && results.error != "") + if (!string.IsNullOrEmpty(results.error)) { if (s_Debug) Debug.LogError("Error performing Asset Store search: " + results.error); @@ -427,7 +431,6 @@ void RequeryAssetStore() void ClearAssetStoreGroups() { - EndRename(true); m_Groups.Clear(); m_Groups.Add(m_LocalAssets); m_StoreAssets.Clear(); @@ -529,9 +532,12 @@ public void OnGUI(Rect position, int keyboardControlID) // For key navigation: Auto set selection to first element if selection is not shown currently when tabbing if (evt.keyCode == KeyCode.Tab && evt.type == EventType.KeyDown && !hasKeyboardFocus && !IsShowingAny(GetSelection())) { - int firstInstanceID; - if (m_LocalAssets.InstanceIdAtIndex(0, out firstInstanceID)) - Selection.activeInstanceID = firstInstanceID; + AssetReference firstAssetReference; + if (m_LocalAssets.AssetReferenceAtIndex(0, out firstAssetReference)) + { + m_LocalAssets.GetNewSelection(ref firstAssetReference, false, false); + Selection.activeInstanceID = firstAssetReference.instanceID; + } } @@ -760,8 +766,12 @@ public bool IsLastClickedItemVisible() public void SelectAll() { - List list = m_LocalAssets.GetInstanceIDs(); - SetSelection(list.ToArray(), false); + List instanceIDs; + List guids; + m_LocalAssets.GetAssetReferences(out instanceIDs, out guids); + if (instanceIDs.Count != 0) + InternalEditorUtility.EnsureInstanceIds(instanceIDs, guids, 0, instanceIDs.Count - 1); + SetSelection(instanceIDs.ToArray(), false); } void SetSelection(int[] selectedInstanceIDs, bool doubleClicked) @@ -959,7 +969,6 @@ void DoOffsetSelectionSpecialKeys(int idx, int maxIndex) { m_State.m_ScrollPosition.y -= m_TotalRect.height; m_SelectionOffset = 0; - return; } else { @@ -974,7 +983,6 @@ void DoOffsetSelectionSpecialKeys(int idx, int maxIndex) { m_State.m_ScrollPosition.y += m_TotalRect.height; m_SelectionOffset = 0; - return; } else { @@ -1044,19 +1052,11 @@ public void SelectFirst() SetSelectedAssetByIdx(startIndex); } - public int GetInstanceIDByIndex(int index) - { - int instanceID; - if (m_LocalAssets.InstanceIdAtIndex(index, out instanceID)) - return instanceID; - return 0; - } - void SetSelectedAssetByIdx(int selectedIdx) { // instanceID can be 0 if 'None' item is at index - int instanceID; - if (m_LocalAssets.InstanceIdAtIndex(selectedIdx, out instanceID)) + AssetReference assetReference; + if (m_LocalAssets.AssetReferenceAtIndex(selectedIdx, out assetReference)) { Rect r = m_LocalAssets.m_Grid.CalcRect(selectedIdx, 0f); ScrollToPosition(AdjustRectForFraming(r)); @@ -1064,12 +1064,12 @@ void SetSelectedAssetByIdx(int selectedIdx) int[] newSelection; if (IsLocalAssetsCurrentlySelected()) - newSelection = m_LocalAssets.GetNewSelection(instanceID, false, true).ToArray(); // Handle multi selection + newSelection = m_LocalAssets.GetNewSelection(ref assetReference, false, true).ToArray(); // Handle multi selection else - newSelection = new[] {instanceID}; // If current selection is asset store asset do not allow multiselection + newSelection = m_LocalAssets.GetNewSelection(ref assetReference, false, false).ToArray(); // If current selection is asset store asset do not allow multiselection SetSelection(newSelection, false); - m_State.m_LastClickedInstanceID = instanceID; + m_State.m_LastClickedInstanceID = assetReference.instanceID; return; } @@ -1530,20 +1530,20 @@ public void OnInspectorUpdate() void ClearCroppedLabelCache() { - m_InstanceIDToCroppedNameMap.Clear(); + m_AssetReferenceToCroppedNameMap.Clear(); } - protected string GetCroppedLabelText(int instanceID, string fullText, float cropWidth) + protected string GetCroppedLabelText(AssetReference assetReference, string fullText, float cropWidth) { // Clear when width changes if (m_WidthUsedForCroppingName != (int)cropWidth) ClearCroppedLabelCache(); string croppedText; - if (!m_InstanceIDToCroppedNameMap.TryGetValue(instanceID, out croppedText)) + if (!m_AssetReferenceToCroppedNameMap.TryGetValue(assetReference, out croppedText)) { // Ensure to clean up once in a while - if (m_InstanceIDToCroppedNameMap.Count > GetMaxNumVisibleItems() * 2 + 30) + if (m_AssetReferenceToCroppedNameMap.Count > GetMaxNumVisibleItems() * 2 + 30) ClearCroppedLabelCache(); // Check if we need to crop @@ -1559,7 +1559,7 @@ protected string GetCroppedLabelText(int instanceID, string fullText, float crop else croppedText = fullText; - m_InstanceIDToCroppedNameMap[instanceID] = croppedText; + m_AssetReferenceToCroppedNameMap[assetReference] = croppedText; m_WidthUsedForCroppingName = (int)cropWidth; } return croppedText; @@ -1636,8 +1636,8 @@ public void BeginPing(int instanceID) m_pingIndex = index; float vcPadding = s_VCEnabled ? k_ListModeVersionControlOverlayPadding : 0f; - - GUIContent cont = new GUIContent(m_LocalAssets.ListMode ? name : GetCroppedLabelText(instanceID, name, m_WidthUsedForCroppingName)); + var assetReference = new AssetReference() { instanceID = instanceID }; + GUIContent cont = new GUIContent(m_LocalAssets.ListMode ? name : GetCroppedLabelText(assetReference, name, m_WidthUsedForCroppingName)); string label = cont.text; if (m_LocalAssets.ListMode) diff --git a/Editor/Mono/ObjectListAssetStoreGroup.cs b/Editor/Mono/ObjectListAssetStoreGroup.cs index 5fd769ca52..a1a6cee1d0 100644 --- a/Editor/Mono/ObjectListAssetStoreGroup.cs +++ b/Editor/Mono/ObjectListAssetStoreGroup.cs @@ -250,7 +250,8 @@ void DrawLabel(Rect position, AssetStoreAsset assetStoreResource, bool selected) { // We crop the text in Preview mode int pseudoInstanceID = assetStoreResource.id + 10000000; // we add a large offset to the asset store id to ensure there is no overlap with instanceIDs - string labeltext = m_Owner.GetCroppedLabelText(pseudoInstanceID, assetStoreResource.displayName, position.width); + var assetReference = new InternalEditorUtility.AssetReference() { instanceID = pseudoInstanceID }; + string labeltext = m_Owner.GetCroppedLabelText(assetReference, assetStoreResource.displayName, position.width); position.height -= s_Styles.resultsGridLabel.fixedHeight; // The -1 is to ensure the label has same width as the image and that it aligns with the bottom of the image s_Styles.resultsGridLabel.Draw(new Rect(position.x, position.yMax + 1, position.width - 1, diff --git a/Editor/Mono/ObjectListGroup.cs b/Editor/Mono/ObjectListGroup.cs index fea946f05b..a7ef86e0f8 100644 --- a/Editor/Mono/ObjectListGroup.cs +++ b/Editor/Mono/ObjectListGroup.cs @@ -243,7 +243,7 @@ protected void DrawItemCount(Rect rect) // Draw item count in group const float rightMargin = 4f; - string label = ItemsAvailable.ToString() + " Total"; + string label = ItemsAvailable + " Total"; Vector2 labelDims = s_Styles.groupHeaderLabelCount.CalcSize(new GUIContent(label)); if (labelDims.x < rect.width) rect.x = m_Owner.GetVisibleWidth() - labelDims.x - rightMargin; // right align if room diff --git a/Editor/Mono/ObjectListLocalGroup.cs b/Editor/Mono/ObjectListLocalGroup.cs index 0fbb018377..f9b8336c20 100644 --- a/Editor/Mono/ObjectListLocalGroup.cs +++ b/Editor/Mono/ObjectListLocalGroup.cs @@ -11,6 +11,7 @@ using System.Linq; using Math = System.Math; using IndexOutOfRangeException = System.IndexOutOfRangeException; +using AssetReference = UnityEditorInternal.InternalEditorUtility.AssetReference; namespace UnityEditor { @@ -290,7 +291,7 @@ protected override void HandleUnusedDragEvents(float yOffset) } } - void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) + void HandleMouseWithDragging(ref AssetReference assetReference, int controlID, Rect rect) { // Handle mouse down on entire line Event evt = Event.current; @@ -303,17 +304,30 @@ void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) if (evt.clickCount == 2) { // Double clicked - m_Owner.SetSelection(new[] {instanceID}, true); + var newSelection = GetNewSelection(ref assetReference, false, false); + m_Owner.SetSelection(newSelection.ToArray(), true); m_DragSelection.Clear(); } else { // Begin drag - m_DragSelection = GetNewSelection(instanceID, true, false); + var newSelection = GetNewSelection(ref assetReference, false, false); + var oldItemControlID = controlID; + controlID = GetControlIDFromInstanceID(assetReference.instanceID); + if (controlID == oldItemControlID) + { + newSelection = GetNewSelection(ref assetReference, true, false); + m_DragSelection = newSelection; + DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), controlID); + delay.mouseDownPosition = Event.current.mousePosition; + m_Owner.ScrollToPosition(ObjectListArea.AdjustRectForFraming(rect)); + } + else + { + m_Owner.SetSelection(newSelection.ToArray(), false); + m_DragSelection.Clear(); + } GUIUtility.hotControl = controlID; - DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), controlID); - delay.mouseDownPosition = Event.current.mousePosition; - m_Owner.ScrollToPosition(ObjectListArea.AdjustRectForFraming(rect)); } evt.Use(); @@ -321,7 +335,7 @@ void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) else if (Event.current.button == 1 && rect.Contains(Event.current.mousePosition)) { // Right mouse down selection (do NOT use event since we need ContextClick event, which is not fired if right click is used) - m_Owner.SetSelection(GetNewSelection(instanceID, true, false).ToArray(), false); + m_Owner.SetSelection(GetNewSelection(ref assetReference, true, false).ToArray(), false); } break; case EventType.MouseDrag: @@ -330,7 +344,7 @@ void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) DragAndDropDelay delay = (DragAndDropDelay)GUIUtility.GetStateObject(typeof(DragAndDropDelay), controlID); if (delay.CanStartDrag()) { - StartDrag(instanceID, m_DragSelection); + StartDrag(assetReference.instanceID, m_DragSelection); GUIUtility.hotControl = 0; } @@ -343,7 +357,7 @@ void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) bool perform = evt.type == EventType.DragPerform; if (rect.Contains(evt.mousePosition)) { - DragAndDropVisualMode mode = DoDrag(instanceID, perform); + DragAndDropVisualMode mode = DoDrag(assetReference.instanceID, perform); if (mode != DragAndDropVisualMode.None) { if (perform) @@ -382,13 +396,13 @@ void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) } List selected = m_Owner.m_State.m_SelectedInstanceIDs; - if (clickedOnText && m_Owner.allowRenaming && m_Owner.m_AllowRenameOnMouseUp && selected.Count == 1 && selected[0] == instanceID && !EditorGUIUtility.HasHolddownKeyModifiers(evt)) + if (clickedOnText && m_Owner.allowRenaming && m_Owner.m_AllowRenameOnMouseUp && selected.Count == 1 && selected[0] == assetReference.instanceID && !EditorGUIUtility.HasHolddownKeyModifiers(evt)) { m_Owner.BeginRename(0.5f); } else { - List newSelection = GetNewSelection(instanceID, false, false); + List newSelection = GetNewSelection(ref assetReference, false, false); m_Owner.SetSelection(newSelection.ToArray(), false); } @@ -413,7 +427,7 @@ void HandleMouseWithDragging(int instanceID, int controlID, Rect rect) } } - void HandleMouseWithoutDragging(int instanceID, int controlID, Rect position) + void HandleMouseWithoutDragging(ref AssetReference assetReference, int controlID, Rect position) { Event evt = Event.current; @@ -430,7 +444,7 @@ void HandleMouseWithoutDragging(int instanceID, int controlID, Rect position) } evt.Use(); - List newSelection = GetNewSelection(instanceID, false, false); + List newSelection = GetNewSelection(ref assetReference, false, false); m_Owner.SetSelection(newSelection.ToArray(), evt.clickCount == 2); } break; @@ -439,7 +453,8 @@ void HandleMouseWithoutDragging(int instanceID, int controlID, Rect position) if (position.Contains(evt.mousePosition)) { // Select it - m_Owner.SetSelection(new[] {instanceID}, false); + List newSelection = GetNewSelection(ref assetReference, false, false); + m_Owner.SetSelection(newSelection.ToArray(), false); Rect overlayPos = position; overlayPos.x += 2; @@ -595,27 +610,28 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR Event evt = Event.current; Rect itemRect = position; - int instanceID = 0; + var assetReference = new AssetReference() { instanceID = 0 }; bool showFoldout = false; if (filterItem != null) { - instanceID = filterItem.instanceID; + assetReference.instanceID = filterItem.instanceID; + assetReference.guid = filterItem.guid; showFoldout = filterItem.hasChildren && !filterItem.isFolder && isFolderBrowsing; // we do not want to be able to expand folders } else if (builtinResource != null) { - instanceID = builtinResource.m_InstanceID; + assetReference.instanceID = builtinResource.m_InstanceID; } - int controlID = GetControlIDFromInstanceID(instanceID); + int controlID = GetControlIDFromInstanceID(assetReference.instanceID); bool selected; if (m_Owner.allowDragging) - selected = m_DragSelection.Count > 0 ? m_DragSelection.Contains(instanceID) : m_Owner.IsSelected(instanceID); + selected = m_DragSelection.Count > 0 ? m_DragSelection.Contains(assetReference.instanceID) : m_Owner.IsSelected(assetReference.instanceID); else - selected = m_Owner.IsSelected(instanceID); + selected = m_Owner.IsSelected(assetReference.instanceID); - if (selected && instanceID == m_Owner.m_State.m_LastClickedInstanceID) + if (selected && assetReference.instanceID == m_Owner.m_State.m_LastClickedInstanceID) m_LastClickedDrawTime = EditorApplication.timeSinceStartup; Rect foldoutRect = new Rect(position.x + s_Styles.groupFoldout.margin.left, position.y, s_Styles.groupFoldout.padding.left, position.height); // ListMode foldout @@ -649,10 +665,10 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR case KeyCode.LeftArrow: if (ListMode || m_Owner.IsPreviewIconExpansionModifierPressed()) { - if (IsExpanded(instanceID)) + if (IsExpanded(assetReference.instanceID)) toggleState = true; else - SelectAndFrameParentOf(instanceID); + SelectAndFrameParentOf(assetReference.instanceID); evt.Use(); } break; @@ -661,7 +677,7 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR case KeyCode.RightArrow: if (ListMode || m_Owner.IsPreviewIconExpansionModifierPressed()) { - if (!IsExpanded(instanceID)) + if (!IsExpanded(assetReference.instanceID)) toggleState = true; evt.Use(); } @@ -675,15 +691,15 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR if (toggleState) { - bool expanded = !IsExpanded(instanceID); + bool expanded = !IsExpanded(assetReference.instanceID); if (expanded) - m_ItemFader.Start(m_FilteredHierarchy.GetSubAssetInstanceIDs(instanceID)); - ChangeExpandedState(instanceID, expanded); + m_ItemFader.Start(m_FilteredHierarchy.GetSubAssetInstanceIDs(assetReference.instanceID)); + ChangeExpandedState(assetReference.instanceID, expanded); evt.Use(); GUIUtility.ExitGUI(); } - bool isRenaming = IsRenaming(instanceID); + bool isRenaming = IsRenaming(assetReference.instanceID); Rect labelRect = position; if (!ListMode) @@ -723,14 +739,21 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR m_Content.image = null; Texture2D icon; - if (m_Owner.GetCreateAssetUtility().instanceID == instanceID && m_Owner.GetCreateAssetUtility().icon != null) + if (assetReference.instanceID != 0 && m_Owner.GetCreateAssetUtility().instanceID == assetReference.instanceID && m_Owner.GetCreateAssetUtility().icon != null) { // If we are creating a new asset we might have an icon to use icon = m_Owner.GetCreateAssetUtility().icon; } else { - icon = filterItem != null ? filterItem.icon : AssetPreview.GetAssetPreview(instanceID, m_Owner.GetAssetPreviewManagerID()); + icon = filterItem != null ? filterItem.icon : null; + if (icon == null) + { + if (assetReference.instanceID != 0) + icon = AssetPreview.GetAssetPreview(assetReference.instanceID, m_Owner.GetAssetPreviewManagerID()); + else if (!string.IsNullOrEmpty(assetReference.guid)) + icon = AssetPreview.GetAssetPreviewFromGUID(assetReference.guid, m_Owner.GetAssetPreviewManagerID()); + } } if (selected) @@ -744,13 +767,13 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR // Foldout if (showFoldout) - s_Styles.groupFoldout.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(instanceID), false); + s_Styles.groupFoldout.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(assetReference.instanceID), false); } else // Icon grid { // Get icon bool drawDropShadow = false; - if (m_Owner.GetCreateAssetUtility().instanceID == instanceID && m_Owner.GetCreateAssetUtility().icon != null) + if (m_Owner.GetCreateAssetUtility().instanceID == assetReference.instanceID && m_Owner.GetCreateAssetUtility().icon != null) { // If we are creating a new asset we might have an icon to use m_Content.image = m_Owner.GetCreateAssetUtility().icon; @@ -758,7 +781,13 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR else { // Check for asset preview - m_Content.image = AssetPreview.GetAssetPreview(instanceID, m_Owner.GetAssetPreviewManagerID()); + Texture image = null; + if (assetReference.instanceID != 0) + image = AssetPreview.GetAssetPreview(assetReference.instanceID, m_Owner.GetAssetPreviewManagerID()); + else if (!string.IsNullOrEmpty(assetReference.guid)) + image = AssetPreview.GetAssetPreviewFromGUID(assetReference.guid, m_Owner.GetAssetPreviewManagerID()); + + m_Content.image = image; if (m_Content.image != null) drawDropShadow = true; @@ -836,7 +865,7 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR if (isDropTarget) s_Styles.resultsLabel.Draw(new Rect(labelRect.x - 10, labelRect.y, labelRect.width + 20, labelRect.height), GUIContent.none, true, true, false, false); - labeltext = m_Owner.GetCroppedLabelText(instanceID, labeltext, position.width); + labeltext = m_Owner.GetCroppedLabelText(assetReference, labeltext, position.width); var labelNewRect = s_Styles.resultsGridLabel.CalcSizeWithConstraints(GUIContent.Temp(labeltext), position.size); labelRect.x = position.x + (position.width - labelNewRect.x) / 2.0f; labelRect.width = labelNewRect.x; @@ -855,7 +884,7 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR { style = s_Styles.subAssetExpandButtonMedium; } - style.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(instanceID), false); + style.Draw(foldoutRect, !ListMode, !ListMode, IsExpanded(assetReference.instanceID), false); } if (filterItem != null && filterItem.isMainRepresentation) @@ -893,9 +922,12 @@ void DrawItem(Rect position, FilteredHierarchy.FilterResult filterItem, BuiltinR // Mouse handling (must be after rename overlay to ensure overlay get mouseevents) if (m_Owner.allowDragging) - HandleMouseWithDragging(instanceID, controlID, position); + HandleMouseWithDragging(ref assetReference, controlID, position); else - HandleMouseWithoutDragging(instanceID, controlID, position); + HandleMouseWithoutDragging(ref assetReference, controlID, position); + + if (filterItem != null && filterItem.instanceID == 0) + filterItem.instanceID = assetReference.instanceID; } private static Rect ActualImageDrawPosition(Rect position, float imageWidth, float imageHeight) @@ -939,37 +971,51 @@ private void BeginPing(int instanceID) { } - public List GetInstanceIDs() + public void GetAssetReferences(out List instanceIDs, out List guids) { - List result = new List(); + instanceIDs = new List(); + guids = new List(); // 1. None item if (m_NoneList.Length > 0) - result.Add(m_NoneList[0].m_InstanceID); // 0 + { + instanceIDs.Add(m_NoneList[0].m_InstanceID); // 0 + guids.Add(null); + } // 2. Project Assets foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results) - result.Add(r.instanceID); + { + instanceIDs.Add(r.instanceID); + guids.Add(r.guid); + } + if (m_Owner.m_State.m_NewAssetIndexInList >= 0) - result.Add(m_Owner.GetCreateAssetUtility().instanceID); + { + instanceIDs.Add(m_Owner.GetCreateAssetUtility().instanceID); + guids.Add(null); + } // 3. Builtin for (int i = 0; i < m_ActiveBuiltinList.Length; ++i) - result.Add(m_ActiveBuiltinList[i].m_InstanceID); - - return result; + { + instanceIDs.Add(m_ActiveBuiltinList[i].m_InstanceID); + guids.Add(null); + } } // Returns list of selected instanceIDs - public List GetNewSelection(int clickedInstanceID, bool beginOfDrag, bool useShiftAsActionKey) + public List GetNewSelection(ref AssetReference clickedAssetReference, bool beginOfDrag, bool useShiftAsActionKey) { // Flatten grid - List allInstanceIDs = GetInstanceIDs(); + List instanceIDs; + List guids; + GetAssetReferences(out instanceIDs, out guids); List selectedInstanceIDs = m_Owner.m_State.m_SelectedInstanceIDs; int lastClickedInstanceID = m_Owner.m_State.m_LastClickedInstanceID; bool allowMultiselection = m_Owner.allowMultiSelect; - return InternalEditorUtility.GetNewSelection(clickedInstanceID, allInstanceIDs, selectedInstanceIDs, lastClickedInstanceID, beginOfDrag, useShiftAsActionKey, allowMultiselection); + return InternalEditorUtility.GetNewSelection(ref clickedAssetReference, instanceIDs, guids, selectedInstanceIDs, lastClickedInstanceID, beginOfDrag, useShiftAsActionKey, allowMultiselection); } public override void UpdateFilter(HierarchyType hierarchyType, SearchFilter searchFilter, bool foldersFirst) @@ -1076,7 +1122,7 @@ private void InitBuiltinAssetType(System.Type type) Debug.LogWarning("ObjectSelector::InitBuiltinAssetType: type is null!"); return; } - string typeName = type.ToString().Substring(type.Namespace.ToString().Length + 1); + string typeName = type.ToString().Substring(type.Namespace.Length + 1); var unityType = UnityType.FindTypeByName(typeName); if (unityType == null) @@ -1228,9 +1274,9 @@ public FilteredHierarchy.FilterResult LookupByInstanceID(int instanceID) } // Returns true if index was valid. Note that instance can be 0 if 'None' item was found at index - public bool InstanceIdAtIndex(int index, out int instanceID) + public bool AssetReferenceAtIndex(int index, out AssetReference assetReference) { - instanceID = 0; + assetReference = new AssetReference() { instanceID = 0 }; if (index >= m_Grid.rows * m_Grid.columns) return false; @@ -1248,7 +1294,8 @@ public bool InstanceIdAtIndex(int index, out int instanceID) // 2. Project assets foreach (FilteredHierarchy.FilterResult r in m_FilteredHierarchy.results) { - instanceID = r.instanceID; + assetReference.instanceID = r.instanceID; + assetReference.guid = r.guid; if (idx == index) return true; idx++; @@ -1257,7 +1304,7 @@ public bool InstanceIdAtIndex(int index, out int instanceID) // 3. Builtin resources foreach (BuiltinResource b in m_ActiveBuiltinList) { - instanceID = b.m_InstanceID; + assetReference.instanceID = b.m_InstanceID; if (idx == index) return true; idx++; diff --git a/Editor/Mono/PerformanceTools/FrameDebugger.cs b/Editor/Mono/PerformanceTools/FrameDebugger.cs index e03ab8932a..9a004caa6b 100644 --- a/Editor/Mono/PerformanceTools/FrameDebugger.cs +++ b/Editor/Mono/PerformanceTools/FrameDebugger.cs @@ -51,13 +51,13 @@ internal enum FrameEventType NextSubpass, EndSubpass // ReSharper restore InconsistentNaming - }; + } internal enum ShowAdditionalInfo { Preview, ShaderProperties - }; + } // Match C++ ScriptingShaderFloatInfo memory layout! [StructLayout(LayoutKind.Sequential)] @@ -485,10 +485,10 @@ private void ClickEnableFrameDebugger() // Make sure game view is visible when enabling frame debugger locally if (FrameDebuggerUtility.IsLocalEnabled()) { - var previewWindow = PreviewEditorWindow.GetMainPreviewWindow(); - if (previewWindow) + var playModeView = PlayModeView.GetMainPlayModeView(); + if (playModeView) { - previewWindow.ShowTab(); + playModeView.ShowTab(); } } @@ -506,7 +506,7 @@ void BuildCurEventDataStrings() m_CurEventDataStrings.shader = string.Format("{0}, SubShader #{1}", m_CurEventData.shaderName, m_CurEventData.subShaderIndex.ToString()); // pass name & LightMode tag - string passName = string.IsNullOrEmpty(m_CurEventData.passName) ? "#" + m_CurEventData.shaderPassIndex.ToString() : m_CurEventData.passName; + string passName = string.IsNullOrEmpty(m_CurEventData.passName) ? "#" + m_CurEventData.shaderPassIndex : m_CurEventData.passName; string lightMode = string.IsNullOrEmpty(m_CurEventData.passLightMode) ? "" : string.Format(" ({0})", m_CurEventData.passLightMode); m_CurEventDataStrings.pass = passName + lightMode; @@ -1214,7 +1214,7 @@ void DrawShaderProperties(ShaderProperties props) { m_ScrollViewShaderProps = GUILayout.BeginScrollView(m_ScrollViewShaderProps); - if (props.textures.Count() > 0) + if (props.textures.Length > 0) { GUILayout.Label("Textures", EditorStyles.boldLabel); @@ -1224,7 +1224,7 @@ void DrawShaderProperties(ShaderProperties props) } } - if (props.floats.Count() > 0) + if (props.floats.Length > 0) { GUILayout.Label("Floats", EditorStyles.boldLabel); @@ -1236,7 +1236,7 @@ void DrawShaderProperties(ShaderProperties props) } } - if (props.vectors.Count() > 0) + if (props.vectors.Length > 0) { GUILayout.Label("Vectors", EditorStyles.boldLabel); @@ -1248,7 +1248,7 @@ void DrawShaderProperties(ShaderProperties props) } } - if (props.matrices.Count() > 0) + if (props.matrices.Length > 0) { GUILayout.Label("Matrices", EditorStyles.boldLabel); @@ -1260,7 +1260,7 @@ void DrawShaderProperties(ShaderProperties props) } } - if (props.buffers.Count() > 0) + if (props.buffers.Length > 0) { GUILayout.Label("Buffers", EditorStyles.boldLabel); diff --git a/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs b/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs index 805128f141..204a8038e7 100644 --- a/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs +++ b/Editor/Mono/PlatformSupport/PlayerSettingsPlatformIcons.bindings.cs @@ -311,7 +311,7 @@ public static void SetPlatformIcons(BuildTargetGroup platform, PlatformIconKind else if (requiredIconCount != icons.Length) { throw new InvalidOperationException(string.Format("Attempting to set an incorrect number of icons for {0} {1} kind, it requires {2} icons but trying to assign {3}.", platform.ToString(), - kind.ToString(), + kind, requiredIconCount, icons.Length) ); diff --git a/Editor/Mono/Preview/PreviewEditorWindow.cs b/Editor/Mono/PlayModeView/PlayModeView.cs similarity index 75% rename from Editor/Mono/Preview/PreviewEditorWindow.cs rename to Editor/Mono/PlayModeView/PlayModeView.cs index f25d814aff..e92e41939b 100644 --- a/Editor/Mono/Preview/PreviewEditorWindow.cs +++ b/Editor/Mono/PlayModeView/PlayModeView.cs @@ -13,14 +13,22 @@ namespace UnityEditor { + internal static class PreviewEditorWindow + { + internal static void RepaintAll() + { + PlayModeView.RepaintAll(); + } + } + [Serializable] - internal abstract class PreviewEditorWindow : EditorWindow + internal abstract class PlayModeView : EditorWindow { - static List s_PreviewWindows = new List(); - static PreviewEditorWindow s_LastFocused; - static PreviewEditorWindow s_RenderingPreview; + static List s_PlayModeViews = new List(); + static PlayModeView s_LastFocused; + static PlayModeView s_RenderingView; - [SerializeField] string m_PreviewName; + [SerializeField] string m_PlayModeViewName; [SerializeField] bool m_ShowGizmos; [SerializeField] int m_TargetDisplay; [SerializeField] Color m_ClearColor; @@ -32,10 +40,10 @@ internal abstract class PreviewEditorWindow : EditorWindow private Dictionary m_AvailableWindowTypes; - protected string previewName + protected string playModeViewName { - get { return m_PreviewName; } - set { m_PreviewName = value; } + get { return m_PlayModeViewName; } + set { m_PlayModeViewName = value; } } protected bool showGizmos @@ -92,13 +100,13 @@ public bool maximizeOnPlay RenderTexture m_TargetTexture; ColorSpace m_CurrentColorSpace = ColorSpace.Uninitialized; - class RenderingPreview : IDisposable + class RenderingView : IDisposable { bool disposed = false; - public RenderingPreview(PreviewEditorWindow previewWindow) + public RenderingView(PlayModeView playModeView) { - PreviewEditorWindow.s_RenderingPreview = previewWindow; + PlayModeView.s_RenderingView = playModeView; } public void Dispose() @@ -115,22 +123,22 @@ protected virtual void Dispose(bool disposing) if (disposing) { - PreviewEditorWindow.s_RenderingPreview = null; + PlayModeView.s_RenderingView = null; } disposed = true; } } - protected PreviewEditorWindow() + protected PlayModeView() { RegisterWindow(); SetPlayModeView(); } - protected RenderTexture RenderPreview(Vector2 mousePosition, bool clearTexture) + protected RenderTexture RenderView(Vector2 mousePosition, bool clearTexture) { - using (var renderingPreview = new RenderingPreview(this)) + using (var renderingView = new RenderingView(this)) { SetPlayModeViewSize(targetSize); var currentTargetDisplay = 0; @@ -141,7 +149,7 @@ protected RenderTexture RenderPreview(Vector2 mousePosition, bool clearTexture) currentTargetDisplay = targetDisplay; } - ConfigureTargetTexture((int)targetSize.x, (int)targetSize.y, clearTexture, previewName); + ConfigureTargetTexture((int)targetSize.x, (int)targetSize.y, clearTexture, playModeViewName); if (Event.current == null || Event.current.type != EventType.Repaint) return m_TargetTexture; @@ -150,7 +158,7 @@ protected RenderTexture RenderPreview(Vector2 mousePosition, bool clearTexture) GUIUtility.s_EditorScreenPointOffset = Vector2.zero; SavedGUIState oldState = SavedGUIState.Create(); - EditorGUIUtility.RenderPreviewCamerasInternal(m_TargetTexture, currentTargetDisplay, mousePosition, showGizmos, renderIMGUI); + EditorGUIUtility.RenderPlayModeViewCamerasInternal(m_TargetTexture, currentTargetDisplay, mousePosition, showGizmos, renderIMGUI); oldState.ApplyAndForget(); GUIUtility.s_EditorScreenPointOffset = oldOffset; @@ -167,17 +175,17 @@ protected string GetWindowTitle(Type type) protected Dictionary GetAvailableWindowTypes() { - return m_AvailableWindowTypes ?? (m_AvailableWindowTypes = TypeCache.GetTypesDerivedFrom(typeof(PreviewEditorWindow)).OrderBy(GetWindowTitle).ToDictionary(t => t, GetWindowTitle)); + return m_AvailableWindowTypes ?? (m_AvailableWindowTypes = TypeCache.GetTypesDerivedFrom(typeof(PlayModeView)).OrderBy(GetWindowTitle).ToDictionary(t => t, GetWindowTitle)); } protected void SwapMainWindow(Type type) { - if (type.BaseType != typeof(PreviewEditorWindow)) - throw new ArgumentException("Type should derive from " + typeof(PreviewEditorWindow).Name); + if (type.BaseType != typeof(PlayModeView)) + throw new ArgumentException("Type should derive from " + typeof(PlayModeView).Name); if (type.Name != GetType().Name) { - var window = CreateInstance(type) as PreviewEditorWindow; + var window = CreateInstance(type) as PlayModeView; window.autoRepaintOnSceneChange = true; var da = m_Parent as DockArea; if (da) @@ -234,18 +242,18 @@ private void ConfigureTargetTexture(int width, int height, bool clearTexture, st } } - internal static PreviewEditorWindow GetRenderingPreview() + internal static PlayModeView GetRenderingView() { - return s_RenderingPreview; + return s_RenderingView; } - internal static PreviewEditorWindow GetMainPreviewWindow() + internal static PlayModeView GetMainPlayModeView() { - if (s_LastFocused == null && s_PreviewWindows != null) + if (s_LastFocused == null && s_PlayModeViews != null) { RemoveDisabledWindows(); - if (s_PreviewWindows.Count > 0) - s_LastFocused = s_PreviewWindows[0]; + if (s_PlayModeViews.Count > 0) + s_LastFocused = s_PlayModeViews[0]; } return s_LastFocused; @@ -253,21 +261,21 @@ internal static PreviewEditorWindow GetMainPreviewWindow() private static void RemoveDisabledWindows() { - if (s_PreviewWindows == null) + if (s_PlayModeViews == null) return; - s_PreviewWindows.RemoveAll(window => window == null); + s_PlayModeViews.RemoveAll(window => window == null); } - internal static Vector2 GetMainPreviewTargetSize() + internal static Vector2 GetMainPlayModeViewTargetSize() { - var prevWindow = GetMainPreviewWindow(); + var prevWindow = GetMainPlayModeView(); if (prevWindow) - return prevWindow.GetPreviewSize(); + return prevWindow.GetPlayModeViewSize(); return new Vector2(640f, 480f); } - internal Vector2 GetPreviewSize() + internal Vector2 GetPlayModeViewSize() { return targetSize; } @@ -275,8 +283,8 @@ internal Vector2 GetPreviewSize() private void RegisterWindow() { RemoveDisabledWindows(); - if (!s_PreviewWindows.Contains(this)) - s_PreviewWindows.Add(this); + if (!s_PlayModeViews.Contains(this)) + s_PlayModeViews.Add(this); } public bool IsShowingGizmos() @@ -310,24 +318,24 @@ protected void SetFocus(bool focused) } } - internal static bool IsPreviewWindowOpen() + internal static bool IsPlayModeViewOpen() { - return GetMainPreviewWindow() != null; + return GetMainPlayModeView() != null; } internal static void RepaintAll() { - if (s_PreviewWindows == null) + if (s_PlayModeViews == null) return; - foreach (PreviewEditorWindow previewWindow in s_PreviewWindows) - previewWindow.Repaint(); + foreach (PlayModeView playModeView in s_PlayModeViews) + playModeView.Repaint(); } [RequiredByNativeCode] - private static void GetMainPreviewTargetSizeNoBox(out Vector2 result) + private static void GetMainPlayModeViewargetSizeNoBox(out Vector2 result) { - result = GetMainPreviewTargetSize(); + result = GetMainPlayModeViewTargetSize(); } } } diff --git a/Editor/Mono/PlayerSettings.bindings.cs b/Editor/Mono/PlayerSettings.bindings.cs index b4c303b380..11e88ea9fa 100644 --- a/Editor/Mono/PlayerSettings.bindings.cs +++ b/Editor/Mono/PlayerSettings.bindings.cs @@ -508,7 +508,8 @@ public static bool singlePassStereoRendering public static extern StereoRenderingPath stereoRenderingPath { get; set; } - public static extern bool protectGraphicsMemory { get; set; } + [Obsolete("protectGraphicsMemory is deprecated. This field has no effect.", false)] + public static bool protectGraphicsMemory { get { return false; } set {} } public static extern bool enableFrameTimingStats { get; set; } @@ -977,7 +978,17 @@ public static bool graphicsJobs [StaticAccessor("PlayerSettingsBindings", StaticAccessorType.DoubleColon)] internal static extern void SetGraphicsJobsForPlatform(BuildTarget platform, bool graphicsJobs); - public static extern GraphicsJobMode graphicsJobMode { get; set; } + public static GraphicsJobMode graphicsJobMode + { + get { return GetGraphicsJobModeForPlatform(EditorUserBuildSettings.activeBuildTarget); } + set { SetGraphicsJobModeForPlatform(EditorUserBuildSettings.activeBuildTarget, value); } + } + + [StaticAccessor("PlayerSettingsBindings", StaticAccessorType.DoubleColon)] + internal static extern GraphicsJobMode GetGraphicsJobModeForPlatform(BuildTarget platform); + + [StaticAccessor("PlayerSettingsBindings", StaticAccessorType.DoubleColon)] + internal static extern void SetGraphicsJobModeForPlatform(BuildTarget platform, GraphicsJobMode gfxJobMode); [Obsolete("GetPlatformVuforiaEnabled(BuildTargetGroup targetGroup) has been deprecated. Use vuforiaEnabled instead.")] [StaticAccessor("PlayerSettingsBindings", StaticAccessorType.DoubleColon)] diff --git a/Editor/Mono/PlayerSettingsMacOS.bindings.cs b/Editor/Mono/PlayerSettingsMacOS.bindings.cs index cae03b1091..a701772545 100644 --- a/Editor/Mono/PlayerSettingsMacOS.bindings.cs +++ b/Editor/Mono/PlayerSettingsMacOS.bindings.cs @@ -22,6 +22,14 @@ public static string buildNumber [NativeProperty("MacAppStoreCategory")] extern internal static string applicationCategoryType { get; set; } + + // these two are internal because we are not yet sure if we want to have them back in general PlayerSettings + // as we have several platforms that might want to use it + [NativeProperty("CameraUsageDescription")] + internal extern static string cameraUsageDescription { get; set; } + + [NativeProperty("MicrophoneUsageDescription")] + internal extern static string microphoneUsageDescription { get; set; } } } } diff --git a/Editor/Mono/PlayerSettingsWSA.cs b/Editor/Mono/PlayerSettingsWSA.cs index 52f30f309a..e9d8f9c846 100644 --- a/Editor/Mono/PlayerSettingsWSA.cs +++ b/Editor/Mono/PlayerSettingsWSA.cs @@ -141,7 +141,7 @@ public static bool GetCapability(WSACapability capability) } catch { - Debug.LogError("Failed to parse value ('" + capability.ToString() + "," + stringValue + "') to bool type."); + Debug.LogError("Failed to parse value ('" + capability + "," + stringValue + "') to bool type."); return false; } } @@ -163,7 +163,7 @@ public static bool GetTargetDeviceFamily(WSATargetFamily family) } catch { - Debug.LogError("Failed to parse value ('" + family.ToString() + "," + stringValue + "') to bool type."); + Debug.LogError("Failed to parse value ('" + family + "," + stringValue + "') to bool type."); return false; } } diff --git a/Editor/Mono/Plugins/PluginsHelper.cs b/Editor/Mono/Plugins/PluginsHelper.cs index 764f85c5e5..12ffd4c269 100644 --- a/Editor/Mono/Plugins/PluginsHelper.cs +++ b/Editor/Mono/Plugins/PluginsHelper.cs @@ -19,7 +19,7 @@ public static bool CheckFileCollisions(BuildTarget buildTarget) pluginImporterExtension = ModuleManager.GetPluginImporterExtension(buildTarget); if (pluginImporterExtension == null) { - // Some platforms don't have platform specific settings for plugins, but we still wan't to check that plugins don't collide, use default path in this case + // Some platforms don't have platform specific settings for plugins, but we still want to check that plugins don't collide, use default path in this case if (BuildPipeline.GetBuildTargetGroup(buildTarget) == BuildTargetGroup.Standalone) pluginImporterExtension = new DesktopPluginImporterExtension(); else diff --git a/Editor/Mono/Prefabs/PrefabImporterEditor.cs b/Editor/Mono/Prefabs/PrefabImporterEditor.cs index 1377abaa0a..b1a0e91ede 100644 --- a/Editor/Mono/Prefabs/PrefabImporterEditor.cs +++ b/Editor/Mono/Prefabs/PrefabImporterEditor.cs @@ -119,6 +119,9 @@ internal void SaveDirtyPrefabAssets() if (!EditorUtility.IsPersistent(asset)) continue; + if (!(asset is GameObject)) + continue; + var rootGameObject = (GameObject)asset; if (IsDirty(rootGameObject)) { @@ -142,6 +145,9 @@ internal bool HasDirtyPrefabAssets() if (assetTarget == null) return false; + if (typeof(GameObject) != assetTarget.GetType()) + return false; + // We just check one target since we assume that a multi-edit will // always edit that target. So no need to spend resources on checking // all targets in multiselection. @@ -209,6 +215,11 @@ internal override string targetTitle internal override void OnHeaderControlsGUI() { + if (assetTarget is DefaultAsset) + { + return; + } + var variantBase = PrefabUtility.GetCorrespondingObjectFromSource(assetTarget); if (variantBase != null) { @@ -230,6 +241,11 @@ internal override void OnHeaderControlsGUI() public override void OnInspectorGUI() { + if (assetTarget is DefaultAsset) + { + return; + } + EditorGUILayout.BeginVertical(EditorStyles.inspectorFullWidthMargins); // Allow opening prefab even if file is not open for edit. diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs index 97fe906114..b8444068ea 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverride.cs @@ -12,13 +12,29 @@ namespace UnityEditor.SceneManagement { public abstract class PrefabOverride { - public abstract void Apply(string prefabAssetPath); - public abstract void Revert(); + public abstract void Apply(string prefabAssetPath, InteractionMode mode); + public abstract void Revert(InteractionMode mode); public void Apply() { var asset = GetAssetObject(); - Apply(AssetDatabase.GetAssetPath(asset)); + Apply(AssetDatabase.GetAssetPath(asset), InteractionMode.UserAction); + } + + public void Apply(string prefabAssetPath) + { + Apply(prefabAssetPath, InteractionMode.UserAction); + } + + public void Apply(InteractionMode mode) + { + var asset = GetAssetObject(); + Apply(AssetDatabase.GetAssetPath(asset), mode); + } + + public void Revert() + { + Revert(InteractionMode.UserAction); } protected UnityObject FindApplyTargetAssetObject(string prefabAssetPath) @@ -36,6 +52,14 @@ protected UnityObject FindApplyTargetAssetObject(string prefabAssetPath) public abstract UnityObject GetAssetObject(); + // Returns the object the override relates to. + // For ObjectOverride, it's the object on the instance that has the overrides. + // For AddedComponent, it's the added component on the instance. + // For AddedGameObject, it's the added GameObject on the instance. + // For RemovedComponent, it's the component on the Prefab Asset corresponding to the removed component on the instance. + // For RemovedGameObject, it's the GameObject on the Prefab Asset corresponding to the removed GameObject on the instance. + internal abstract UnityObject GetObject(); + internal void HandleApplyMenuItems(GenericMenu menu, GenericMenu.MenuFunction2 applyAction) { PrefabUtility.HandleApplyMenuItems( @@ -60,19 +84,19 @@ public class ObjectOverride : PrefabOverride public UnityObject instanceObject { get; set; } public PrefabOverride coupledOverride { get; set; } - public override void Apply(string prefabAssetPath) + public override void Apply(string prefabAssetPath, InteractionMode mode) { PrefabUtility.ApplyObjectOverride( instanceObject, prefabAssetPath, - InteractionMode.UserAction); + mode); } - public override void Revert() + public override void Revert(InteractionMode mode) { PrefabUtility.RevertObjectOverride( instanceObject, - InteractionMode.UserAction); + mode); coupledOverride?.Revert(); } @@ -81,18 +105,23 @@ public override UnityObject GetAssetObject() { return PrefabUtility.GetCorrespondingObjectFromSource(instanceObject); } + + internal override UnityObject GetObject() + { + return instanceObject; + } } public class AddedComponent : PrefabOverride { public Component instanceComponent { get; set; } - public override void Apply(string prefabAssetPath) + public override void Apply(string prefabAssetPath, InteractionMode mode) { PrefabUtility.ApplyAddedComponent( instanceComponent, prefabAssetPath, - InteractionMode.UserAction); + mode); var coupledComponent = instanceComponent.GetCoupledComponent(); if (coupledComponent != null) @@ -104,18 +133,19 @@ public override void Apply(string prefabAssetPath) } } - public override void Revert() + public override void Revert(InteractionMode mode) { + var coupledComponent = instanceComponent.GetCoupledComponent(); + PrefabUtility.RevertAddedComponent( instanceComponent, - InteractionMode.UserAction); + mode); - var coupledComponent = instanceComponent.GetCoupledComponent(); if (coupledComponent != null) { PrefabUtility.RevertAddedComponent( coupledComponent, - InteractionMode.UserAction); + mode); } } @@ -123,6 +153,11 @@ public override UnityObject GetAssetObject() { return PrefabUtility.GetCorrespondingObjectFromSource(instanceComponent.gameObject); } + + internal override UnityObject GetObject() + { + return instanceComponent; + } } public class RemovedComponent : PrefabOverride @@ -130,20 +165,20 @@ public class RemovedComponent : PrefabOverride public GameObject containingInstanceGameObject { get; set; } public Component assetComponent { get; set; } - public override void Apply(string prefabAssetPath) + public override void Apply(string prefabAssetPath, InteractionMode mode) { PrefabUtility.ApplyRemovedComponent( containingInstanceGameObject, (Component)FindApplyTargetAssetObject(prefabAssetPath), - InteractionMode.UserAction); + mode); } - public override void Revert() + public override void Revert(InteractionMode mode) { PrefabUtility.RevertRemovedComponent( containingInstanceGameObject, assetComponent, - InteractionMode.UserAction); + mode); var coupledComponent = assetComponent.GetCoupledComponent(); if (coupledComponent != null) @@ -151,7 +186,7 @@ public override void Revert() PrefabUtility.RevertRemovedComponent( containingInstanceGameObject, coupledComponent, - InteractionMode.UserAction); + mode); } } @@ -159,6 +194,11 @@ public override UnityObject GetAssetObject() { return assetComponent; } + + internal override UnityObject GetObject() + { + return assetComponent; + } } public class AddedGameObject : PrefabOverride @@ -166,19 +206,19 @@ public class AddedGameObject : PrefabOverride public GameObject instanceGameObject { get; set; } public int siblingIndex { get; set; } - public override void Apply(string prefabAssetPath) + public override void Apply(string prefabAssetPath, InteractionMode mode) { PrefabUtility.ApplyAddedGameObject( instanceGameObject, prefabAssetPath, - InteractionMode.UserAction); + mode); } - public override void Revert() + public override void Revert(InteractionMode mode) { PrefabUtility.RevertAddedGameObject( instanceGameObject, - InteractionMode.UserAction); + mode); } public override UnityObject GetAssetObject() @@ -186,5 +226,10 @@ public override UnityObject GetAssetObject() GameObject parent = instanceGameObject.transform.parent.gameObject; return PrefabUtility.GetCorrespondingObjectFromSource(parent); } + + internal override UnityObject GetObject() + { + return instanceGameObject; + } } } diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs index da24ffbc5c..e2a8f41a6f 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesTreeView.cs @@ -22,8 +22,8 @@ class PrefabOverridesTreeView : TreeView int m_LastShownPreviewWindowRowID = -1; PrefabOverridesWindow m_Window; - enum ToggleValue { FALSE, TRUE, MIXED }; - enum ItemType { PREFAB_OBJECT, ADDED_OBJECT, REMOVED_OBJECT }; + enum ToggleValue { FALSE, TRUE, MIXED } + enum ItemType { PREFAB_OBJECT, ADDED_OBJECT, REMOVED_OBJECT } class PrefabOverridesTreeViewItem : TreeViewItem { @@ -114,6 +114,15 @@ public void SetApplyTarget(GameObject prefabInstanceRoot, GameObject prefabAsset EnableAllItems(true); } + public void CullNonExistingItemsFromSelection() + { + for (int i = state.selectedIDs.Count - 1; i >= 0; i--) + { + if (TreeViewUtility.FindItem(state.selectedIDs[i], rootItem) == null) + state.selectedIDs.RemoveAt(i); + } + } + void BuildPrefabOverridesPerObject(out Dictionary instanceIDToPrefabOverridesMap) { instanceIDToPrefabOverridesMap = new Dictionary(); @@ -376,16 +385,6 @@ protected override void RowGUI(RowGUIArgs args) GUI.DrawTexture(rect, item.overlayIcon, ScaleMode.ScaleToFit); } } - - 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); - } } internal void ReloadOverridesDisplay() @@ -397,13 +396,32 @@ internal void ReloadOverridesDisplay() // before collecting overrides. Canvas.ForceUpdateCanvases(); - base.Reload(); if (m_Window != null) m_Window.RefreshStatus(); } - void DoPreviewPopup(PrefabOverridesTreeViewItem item, Rect rowRect) + protected override void SelectionChanged(IList selectedIds) { + DoPreviewPopup(); + } + + protected override void SingleClickedItem(int id) + { + // Ensure preview is shown when clicking on an already selected item + // (the preview might have been closed). + DoPreviewPopup(); + } + + void DoPreviewPopup() + { + if (state.selectedIDs.Count != 1) + { + PopupWindowWithoutFocus.Hide(); + return; + } + + var item = FindItem(state.selectedIDs[0], rootItem) as PrefabOverridesTreeViewItem; + if (item == null || item.obj == null) return; @@ -413,7 +431,11 @@ void DoPreviewPopup(PrefabOverridesTreeViewItem item, Rect rowRect) return; } - Rect buttonRect = rowRect; + int row = FindRowOfItem(item); + if (row == -1) + return; + + Rect buttonRect = GetRowRect(row); buttonRect.width = EditorGUIUtility.currentViewWidth; Object rowObject = item.obj; @@ -454,6 +476,14 @@ struct ChangedModification public string propertyPath { get; set; } } + public PrefabOverride FindOverride(int itemId) + { + var item = FindItem(itemId, rootItem) as PrefabOverridesTreeViewItem; + if (item == null) + return null; + return item.singleModification; + } + class IdSequence { public int get() { return m_NextId++; } diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs index f6ccf7c5cb..1adf18cc8c 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesUtility.cs @@ -105,6 +105,10 @@ static void CheckForAddedComponents(Transform transform, object userData) if (component == null) continue; + // Don't list DontSave objects as they won't get applied or reverted. + if ((component.hideFlags & HideFlags.DontSaveInEditor) != 0) + continue; + bool isAddedObject = PrefabUtility.GetCorrespondingObjectFromSource(component) == null; if (isAddedObject) { @@ -206,6 +210,10 @@ public static List GetAddedGameObjects(GameObject prefabInstanc static bool CheckForAddedGameObjectAndIfSoAddItAndReturnFalse(Transform transform, object userData) { + // Don't list DontSave objects or their children as they won't get applied or reverted. + if ((transform.gameObject.hideFlags & HideFlags.DontSaveInEditor) != 0) + return false; + var addedGameObjectUserData = (AddedGameObjectUserData)userData; if (IsAddedGameObject(addedGameObjectUserData.contextGameObject, transform.gameObject)) { diff --git a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs index 377099b659..ad7e8ef692 100644 --- a/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs +++ b/Editor/Mono/Prefabs/PrefabOverrides/PrefabOverridesWindow.cs @@ -16,6 +16,7 @@ internal class PrefabOverridesWindow : PopupWindowContent RectOffset k_TreeViewPadding = new RectOffset(0, 0, 4, 4); const float k_HeaderHeight = 40f; const float k_ButtonWidth = 120; + const float k_ButtonWidthVariant = 135; const float k_HeaderLeftMargin = 6; const float k_NoOverridesLabelHeight = 26f; const float k_ApplyButtonHeight = 36f; @@ -31,6 +32,9 @@ internal class PrefabOverridesWindow : PopupWindowContent GUIContent m_InstanceContent = new GUIContent(); GUIContent m_RevertAllContent = new GUIContent(); GUIContent m_ApplyAllContent = new GUIContent(); + GUIContent m_RevertSelectedContent = new GUIContent(); + GUIContent m_ApplySelectedContent = new GUIContent(); + float m_ButtonWidth; bool m_AnyOverrides; bool m_Disconnected; @@ -42,8 +46,11 @@ internal class PrefabOverridesWindow : PopupWindowContent static class Styles { public static GUIContent revertAllContent = EditorGUIUtility.TrTextContent("Revert All", "Revert all overrides."); + public static GUIContent revertSelectedContent = EditorGUIUtility.TrTextContent("Revert Selected", "Revert selected overrides."); public static GUIContent applyAllContent = EditorGUIUtility.TrTextContent("Apply All", "Apply all overrides to Prefab source '{0}'."); + public static GUIContent applySelectedContent = EditorGUIUtility.TrTextContent("Apply Selected", "Apply selected overrides to Prefab source '{0}'."); public static GUIContent applyAllToBaseContent = EditorGUIUtility.TrTextContent("Apply All to Base", "Apply all overrides to base Prefab source '{0}'."); + public static GUIContent applySelectedToBaseContent = EditorGUIUtility.TrTextContent("Apply Selected to Base", "Apply selected overrides to base Prefab source '{0}'."); public static GUIContent instanceLabel = EditorGUIUtility.TrTextContent("Overrides to"); public static GUIContent contextLabel = EditorGUIUtility.TrTextContent("in"); @@ -91,6 +98,12 @@ internal PrefabOverridesWindow(GameObject[] selectedGameObjects) internal void RefreshStatus() { + if (m_TreeView != null) + { + m_TreeView.Reload(); + m_TreeView.CullNonExistingItemsFromSelection(); + } + if (m_SelectedGameObjects.Length == 1) UpdateTextSingle(PrefabUtility.GetCorrespondingObjectFromSource(m_SelectedGameObjects[0])); else @@ -262,25 +275,55 @@ public override void OnGUI(Rect rect) GUILayout.FlexibleSpace(); using (new EditorGUI.DisabledScope(m_InvalidComponentOnAsset)) { - if (GUILayout.Button(m_RevertAllContent, GUILayout.Width(k_ButtonWidth))) + if (m_TreeView != null && m_TreeView.GetSelection().Count > 1) { - if (RevertAll() && editorWindow != null) + if (GUILayout.Button(m_RevertSelectedContent, GUILayout.Width(m_ButtonWidth))) { - editorWindow.Close(); - GUIUtility.ExitGUI(); + if (OperateSelectedOverrides(PrefabUtility.OverrideOperation.Revert)) + { + RefreshStatus(); + // We don't close the window even if there are no more overrides left. + // We want to diplay explicit confirmation, since it's not a given outcome + // when using Revert Selected. Only Revert All button closes the window. + } } - } - using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + { + if (GUILayout.Button(m_ApplySelectedContent, GUILayout.Width(m_ButtonWidth))) + { + if (OperateSelectedOverrides(PrefabUtility.OverrideOperation.Apply)) + { + RefreshStatus(); + // We don't close the window even if there are no more overrides left. + // We want to diplay explicit confirmation, since it's not a given outcome + // when using Apply Selected. Only Apply All button closes the window. + } + } + } + } + else { - if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(k_ButtonWidth))) + if (GUILayout.Button(m_RevertAllContent, GUILayout.Width(m_ButtonWidth))) { - if (ApplyAll() && editorWindow != null) + if (RevertAll() && editorWindow != null) { editorWindow.Close(); GUIUtility.ExitGUI(); } } + + using (new EditorGUI.DisabledScope(m_Immutable || m_InvalidComponentOnInstance)) + { + if (GUILayout.Button(m_ApplyAllContent, GUILayout.Width(m_ButtonWidth))) + { + if (ApplyAll() && editorWindow != null) + { + editorWindow.Close(); + GUIUtility.ExitGUI(); + } + } + } } } @@ -291,7 +334,7 @@ struct ApplyAllUndo { public GameObject correspondingSourceObject; public HashSet prefabHierarchy; - }; + } bool ApplyAll() { @@ -364,6 +407,25 @@ bool RevertAll() return true; } + bool OperateSelectedOverrides(PrefabUtility.OverrideOperation operation) + { + List overrides = new List(); + + // Get all overrides from selection. Immediately accept any overrides with no dependencies. + var selection = m_TreeView.GetSelection(); + for (int i = 0; i < selection.Count; i++) + { + PrefabOverride singleOverride = m_TreeView.FindOverride(selection[i]); + if (singleOverride != null) + overrides.Add(singleOverride); + } + + bool success = PrefabUtility.ProcessMultipleOverrides(m_SelectedGameObjects[0], overrides, operation, InteractionMode.UserAction); + if (success) + EditorUtility.ForceRebuildInspectors(); + return success; + } + void UpdateTextSingle(GameObject prefabAsset) { Texture2D icon = (Texture2D)AssetDatabase.GetCachedIcon(AssetDatabase.GetAssetPath(prefabAsset)); @@ -395,15 +457,23 @@ void UpdateText(Texture assetIcon, string assetName) m_InstanceContent.image = assetIcon; m_InstanceContent.text = assetName; - m_RevertAllContent.text = Styles.revertAllContent.text; - m_RevertAllContent.tooltip = Styles.revertAllContent.tooltip; + m_RevertAllContent = Styles.revertAllContent; + m_RevertSelectedContent = Styles.revertSelectedContent; + m_ButtonWidth = k_ButtonWidth; var applyAllContent = Styles.applyAllContent; + var applySelectedContent = Styles.applySelectedContent; if (stage.isPrefabStage && PrefabUtility.IsPartOfVariantPrefab(AssetDatabase.LoadAssetAtPath(stage.prefabAssetPath))) + { + m_ButtonWidth = k_ButtonWidthVariant; applyAllContent = Styles.applyAllToBaseContent; + applySelectedContent = Styles.applySelectedToBaseContent; + } m_ApplyAllContent.text = applyAllContent.text; m_ApplyAllContent.tooltip = string.Format(applyAllContent.tooltip, assetName); + m_ApplySelectedContent.text = applySelectedContent.text; + m_ApplySelectedContent.tooltip = string.Format(applySelectedContent.tooltip, assetName); } } } diff --git a/Editor/Mono/Prefabs/PrefabUtility.cs b/Editor/Mono/Prefabs/PrefabUtility.cs index fa3ee9b0a3..44a28201ab 100644 --- a/Editor/Mono/Prefabs/PrefabUtility.cs +++ b/Editor/Mono/Prefabs/PrefabUtility.cs @@ -760,6 +760,19 @@ public static void ApplyAddedComponent(Component component, string assetPath, In var actionName = "Apply Added Component"; if (action == InteractionMode.UserAction) { + string dependentComponents = string.Join( + ", ", + GetAddedComponentDependencies(component, OverrideOperation.Apply).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray()); + if (!string.IsNullOrEmpty(dependentComponents)) + { + string error = String.Format( + L10n.Tr("Can't apply added component {0} because it depends on {1}."), + ObjectNames.GetInspectorTitle(component), + dependentComponents); + EditorUtility.DisplayDialog(L10n.Tr("Can't apply added component"), error, L10n.Tr("OK")); + return; + } + Undo.RegisterFullObjectHierarchyUndo(prefabSourceGameObject, actionName); Undo.RegisterFullObjectHierarchyUndo(component, actionName); } @@ -807,11 +820,11 @@ public static void RevertAddedComponent(Component component, InteractionMode act { string dependentComponents = string.Join( ", ", - GetDependentComponents(component).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray()); + GetAddedComponentDependencies(component, OverrideOperation.Revert).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"), + 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")); @@ -866,6 +879,19 @@ public static void ApplyRemovedComponent(GameObject instanceGameObject, Componen if (action == InteractionMode.UserAction) { + string dependentComponents = string.Join( + ", ", + GetRemovedComponentDependencies(assetComponent, instanceGameObject, OverrideOperation.Apply).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray()); + if (!string.IsNullOrEmpty(dependentComponents)) + { + string error = String.Format( + L10n.Tr("Can't apply removed component {0} because {1} component in the Prefab Asset depends on it."), + ObjectNames.GetInspectorTitle(assetComponent), + dependentComponents); + EditorUtility.DisplayDialog(L10n.Tr("Can't apply removed component"), error, L10n.Tr("OK")); + return; + } + Undo.DestroyObjectUndoable(assetComponent, actionName); // Undo.DestroyObjectUndoable saves prefab asset internally. } @@ -920,7 +946,22 @@ public static void RevertRemovedComponent(GameObject instanceGameObject, Compone var prefabInstanceObject = PrefabUtility.GetPrefabInstanceHandle(instanceGameObject); if (action == InteractionMode.UserAction) + { + string dependentComponents = string.Join( + ", ", + GetRemovedComponentDependencies(assetComponent, instanceGameObject, OverrideOperation.Revert).Select(e => ObjectNames.GetInspectorTitle(e)).ToArray()); + if (!string.IsNullOrEmpty(dependentComponents)) + { + string error = String.Format( + L10n.Tr("Can't revert removed component {0} because it depends on {1}."), + ObjectNames.GetInspectorTitle(assetComponent), + dependentComponents); + EditorUtility.DisplayDialog(L10n.Tr("Can't revert removed component"), error, L10n.Tr("OK")); + return; + } + Undo.RegisterCompleteObjectUndo(instanceGameObject, actionName); + } RemoveRemovedComponentOverride(prefabInstanceObject, assetComponent); @@ -1654,6 +1695,9 @@ internal static bool HasInvalidComponent(Object gameObjectOrComponent) gameObjectOrComponent = (GameObject)comp.gameObject; } + if (!(gameObjectOrComponent is GameObject)) + return false; + GameObject go; go = (GameObject)gameObjectOrComponent; TransformVisitor transformVisitor = new TransformVisitor(); @@ -1863,27 +1907,263 @@ internal static List GetApplyTargets(Object instanceOrAssetObject, bool return applyTargets; } - static List GetDependentComponents(Component component) + internal enum OverrideOperation + { + Apply, + Revert + } + + // Applying/reverting multiple overrides at once is surprisingly tricky because + // we have to handle components with dependencies on other components in just the right order. + internal static bool ProcessMultipleOverrides(GameObject prefabInstanceRoot, List overrides, PrefabUtility.OverrideOperation operation, InteractionMode mode) + { + Dictionary> overrideDependencies = + new Dictionary>(); + List acceptedOverrides = new List(); + List acceptedRemovedComponentOverrides = new List(); + List remainingOverrides = new List(); + HashSet acceptedOverrideObjects = new HashSet(); + + // Iterate over overrides. Immediately accept any overrides with no dependencies. + // Otherwise save dependencies in dictionary for quick lookup. + for (int i = 0; i < overrides.Count; i++) + { + PrefabOverride singleOverride = overrides[i]; + if (singleOverride == null) + continue; + bool hasDependencies = false; + + RemovedComponent removedComponent = singleOverride as RemovedComponent; + if (removedComponent != null) + { + var deps = PrefabUtility.GetRemovedComponentDependencies( + removedComponent.assetComponent, + removedComponent.containingInstanceGameObject, + operation); + if (deps.Count > 0) + { + overrideDependencies[singleOverride] = deps; + hasDependencies = true; + } + } + + AddedComponent addedComponent = singleOverride as AddedComponent; + if (addedComponent != null) + { + var deps = PrefabUtility.GetAddedComponentDependencies( + addedComponent.instanceComponent, + operation); + if (deps.Count > 0) + { + overrideDependencies[singleOverride] = deps; + hasDependencies = true; + } + } + + if (hasDependencies) + { + remainingOverrides.Add(singleOverride); + } + else + { + if (singleOverride is RemovedComponent) + acceptedRemovedComponentOverrides.Add(singleOverride); + else + acceptedOverrides.Add(singleOverride); + acceptedOverrideObjects.Add(singleOverride.GetObject()); + } + } + + // Iteratively accept overrides whose dependencies are all in the accepted overrides. + // Theoretically this algorithm is worst case n*n. + // However, long dependency chains are uncommon, so in practise it's much closer to just n. + while (true) + { + bool didAcceptNewOverrides = false; + + for (int i = remainingOverrides.Count - 1; i >= 0; i--) + { + var o = remainingOverrides[i]; + var dependencies = overrideDependencies[o]; + bool allDependenciesSatisfied = true; + for (int j = 0; j < dependencies.Count; j++) + { + if (!acceptedOverrideObjects.Contains(dependencies[j])) + { + allDependenciesSatisfied = false; + break; + } + } + if (allDependenciesSatisfied) + { + if (o is RemovedComponent) + acceptedRemovedComponentOverrides.Add(o); + else + acceptedOverrides.Add(o); + acceptedOverrideObjects.Add(o.GetObject()); + remainingOverrides.RemoveAt(i); + didAcceptNewOverrides = true; + } + } + + if (!didAcceptNewOverrides) + break; + } + + if (remainingOverrides.Count > 0) + { + string dependenciesString = ""; + foreach (var singleOverride in remainingOverrides) + { + var dependencies = overrideDependencies[singleOverride]; + foreach (var dep in dependencies) + { + // The dependency direction is different for apply versus revert AND for added versus removed components. + bool dependsOnOther = (singleOverride is AddedComponent) ^ (operation == PrefabUtility.OverrideOperation.Revert); + dependenciesString += "\n" + string.Format( + dependsOnOther ? L10n.Tr("{0} depends on {1}") : L10n.Tr("{0} is depended on by {1}"), + ObjectNames.GetInspectorTitle(singleOverride.GetObject()), + ObjectNames.GetInspectorTitle(dep)); + } + } + + string error = null; + string dialogTitle = null; + if (operation == PrefabUtility.OverrideOperation.Apply) + { + dialogTitle = L10n.Tr("Can't apply selected overrides"); + error = L10n.Tr("Can't apply selected overrides due to dependencies with non-selected overrides:") + dependenciesString; + } + else + { + dialogTitle = L10n.Tr("Can't revert selected overrides"); + error = L10n.Tr("Can't revert selected overrides due to dependencies with non-selected overrides.") + dependenciesString; + } + + if (mode == InteractionMode.UserAction) + { + EditorUtility.DisplayDialog(dialogTitle, error, L10n.Tr("OK")); + } + else + { + throw new ArgumentException(error); + } + + return false; + } + + if (operation == PrefabUtility.OverrideOperation.Apply) + { + if (mode == InteractionMode.UserAction) + { + // Make sure asset is checked out in version control. + string prefabAssetPath = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(prefabInstanceRoot); + if (!PrefabUtility.PromptAndCheckoutPrefabIfNeeded(prefabAssetPath, PrefabUtility.SaveVerb.Apply)) + return false; + } + + // Apply overrides *in the order* they were added, but all removed components first, so removed + // and added component of same type can't cause GameObject to temporarily have two at once. + for (int i = 0; i < acceptedRemovedComponentOverrides.Count; i++) + acceptedRemovedComponentOverrides[i].Apply(mode); + for (int i = 0; i < acceptedOverrides.Count; i++) + acceptedOverrides[i].Apply(mode); + } + else + { + // Revert overrides *in the order* they were added, but all removed components last, so removed + // and added component of same type can't cause GameObject to temporarily have two at once. + for (int i = 0; i < acceptedOverrides.Count; i++) + acceptedOverrides[i].Revert(mode); + for (int i = 0; i < acceptedRemovedComponentOverrides.Count; i++) + acceptedRemovedComponentOverrides[i].Revert(mode); + } + + return true; + } + + internal static List GetAddedComponentDependencies(Component component, OverrideOperation op) + { + GameObject instanceGameObject = component.gameObject; + List addedComponentsOnGO = + GetAddedComponents(instanceGameObject) + .Select(e => e.instanceComponent) + .Where(e => e.gameObject == instanceGameObject) + .ToList(); + if (op == OverrideOperation.Apply) + // We can't apply an added component if it depends on a different added component. + // This would violate a dependency in the asset. + return GetComponentsWhichThisDependsOn(component, addedComponentsOnGO); + else + // We can't revert an added component if another added component depends on it. + // This would violate a dependency in the instance. + return GetComponentsWhichDependOnThis(component, addedComponentsOnGO); + } + + internal static List GetRemovedComponentDependencies(Component assetComponent, GameObject instanceGameObject, OverrideOperation op) + { + GameObject assetGameObject = assetComponent.gameObject; + List removedComponentsOnAssetGO = + GetRemovedComponents(instanceGameObject) + .Select(e => e.assetComponent) + .Where(e => e.gameObject == assetGameObject) + .ToList(); + if (op == OverrideOperation.Apply) + // We can't apply a removed component if another removed component depends on it. + // This would violate a dependency in the asset. + return GetComponentsWhichDependOnThis(assetComponent, removedComponentsOnAssetGO); + else + // We can't revert a removed component if it depends on another removed component. + // This would violate a dependency in the instance. + return GetComponentsWhichThisDependsOn(assetComponent, removedComponentsOnAssetGO); + } + + static List GetComponentsWhichDependOnThis(Component component, List componentsToConsider) { 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++) + // Iterate all components. + for (int i = 0; i < componentsToConsider.Count; i++) { - var comp = allComponents[i]; + var comp = componentsToConsider[i]; - // Ignore components that are not added. - if (GetCorrespondingObjectFromSource(comp) != null) + // Ignore component itself. + if (comp == component) continue; - // Ignore component itself the user is reverting. + 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; + } + + static List GetComponentsWhichThisDependsOn(Component component, List componentsToConsider) + { + var requiredComps = component.GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true); + List dependencies = new List(); + if (requiredComps.Count() == 0) + return dependencies; + + // Iterate all components. + for (int i = 0; i < componentsToConsider.Count; i++) + { + var comp = componentsToConsider[i]; + + // Ignore component itself. if (comp == component) continue; - var requiredComps = comp.GetType().GetCustomAttributes(typeof(RequireComponent), inherit: true); + var componentType = comp.GetType(); foreach (RequireComponent reqComp in requiredComps) { if (reqComp.m_Type0 == componentType || reqComp.m_Type1 == componentType || reqComp.m_Type2 == componentType) diff --git a/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs b/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs index cdee1c88fd..74cefa5f16 100644 --- a/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs +++ b/Editor/Mono/PreferencesWindow/CacheServerPreferences.cs @@ -23,8 +23,8 @@ internal class Properties public static readonly GUIContent cleanCache = EditorGUIUtility.TrTextContent("Clean Cache"); public static readonly GUIContent enumerateCache = EditorGUIUtility.TrTextContent("Check Cache Size", "Check the size of the local asset cache server - can take a while"); public static readonly GUIContent browseCacheLocation = EditorGUIUtility.TrTextContent("Browse for local asset cache server location"); - public static readonly GUIContent assetPipelineVersion1 = EditorGUIUtility.TrTextContent("Asset pipeline v1"); - public static readonly GUIContent assetPipelineVersion2 = EditorGUIUtility.TrTextContent("Asset pipeline v2 (experimental)"); + public static readonly GUIContent assetPipelineVersion1 = EditorGUIUtility.TrTextContent("Asset pipeline v1 (deprecated)"); + public static readonly GUIContent assetPipelineVersion2 = EditorGUIUtility.TrTextContent("Asset pipeline v2"); public static readonly GUIContent newProjectsAssetPipeline = EditorGUIUtility.TrTextContent("New Projects default asset pipeline", "The default asset pipeline used when creating a new project. Note that this default can be overridden by using a -adb1 or -adb2 command line argument."); public static readonly GUIContent activeAssetPipelineVersionLabel = EditorGUIUtility.TrTextContent("Active version", activeAssetPipelineVersionTooltip); public static readonly GUIContent activeAssetPipelineVersion = new GUIContent(AssetDatabase.IsV1Enabled() ? "1" : "2", activeAssetPipelineVersionTooltip); @@ -53,7 +53,7 @@ static Styles() private static bool s_PrefsLoaded; private static bool s_HasPendingChanges = false; - enum ConnectionState { Unknown, Success, Failure }; + enum ConnectionState { Unknown, Success, Failure } private static ConnectionState s_ConnectionState; public enum AssetPipelineVersion { Version1, Version2 } public static AssetPipelineVersion s_AssetPipelineVersionForNewProjects; @@ -160,7 +160,7 @@ public static string GetCommandLineRemoteAddressOverride() [SettingsProvider] internal static SettingsProvider CreateSettingsProvider() { - return new SettingsProvider("Preferences/Cache Server", SettingsScope.User) + return new SettingsProvider("Preferences/Cache Server (global)", SettingsScope.User) { guiHandler = searchContext => { diff --git a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs index 5318819e18..3739fdb574 100644 --- a/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs +++ b/Editor/Mono/PreferencesWindow/PreferencesSettingsProviders.cs @@ -167,6 +167,9 @@ private struct GICacheSettings private string[] m_ImageApps; private string[] m_DiffTools; + private string m_CustomDiffToolPath = ""; + private string[] m_CustomDiffToolArguments = new[] {"", "", ""}; + private string m_noDiffToolsMessage = string.Empty; private string[] m_ScriptAppDisplayNames; @@ -191,6 +194,7 @@ private struct GICacheSettings private static int kMaxSpriteCacheSizeInGigabytes = 200; private List m_SystemFonts = new List(); + private const int k_browseButtonWidth = 80; class RefString { @@ -391,6 +395,25 @@ private void ShowExternalApplications(string searchContext) using (new EditorGUI.DisabledScope(!InternalEditorUtility.HasTeamLicense())) { m_DiffToolIndex = EditorGUILayout.Popup(ExternalProperties.revisionControlDiffMerge, m_DiffToolIndex, m_DiffTools); + if (m_DiffToolIndex == m_DiffTools.Length - 1) + { + GUILayout.BeginHorizontal(); + m_CustomDiffToolPath = EditorGUILayout.DelayedTextField("Tool Path", m_CustomDiffToolPath); + + if (GUILayout.Button("Browse", GUILayout.Width(k_browseButtonWidth))) + { + string path = EditorUtility.OpenFilePanel("Browse for application", "", InternalEditorUtility.GetApplicationExtensionForRuntimePlatform(Application.platform)); + if (path.Length != 0) + { + m_CustomDiffToolPath = path; + } + } + + GUILayout.EndHorizontal(); + m_CustomDiffToolArguments[0] = EditorGUILayout.DelayedTextField("Two-way diff command line", m_CustomDiffToolArguments[0]); + m_CustomDiffToolArguments[1] = EditorGUILayout.DelayedTextField("Three-way diff command line", m_CustomDiffToolArguments[1]); + m_CustomDiffToolArguments[2] = EditorGUILayout.DelayedTextField("Merge arguments", m_CustomDiffToolArguments[2]); + } } if (m_noDiffToolsMessage != string.Empty) @@ -550,7 +573,6 @@ private void ShowGeneral(string searchContext) // Refresh skin to get new font Unsupported.ClearSkinCache(); - EditorResources.BuildCatalog(); InternalEditorUtility.RequestScriptReload(); InternalEditorUtility.RepaintAllViews(); } @@ -803,7 +825,7 @@ private void ShowLanguage(string searchContext) { SystemLanguage lang = (SystemLanguage)Enum.Parse(typeof(SystemLanguage), m_SelectedLanguage); EditorGUIUtility.NotifyLanguageChanged(lang); - InternalEditorUtility.RequestScriptReload(); + EditorUtility.RequestScriptReload(); } ApplyChangesToPrefs(); @@ -899,6 +921,10 @@ private void WritePreferences() EditorPrefs.SetString("kImagesDefaultApp", m_ImageAppPath); EditorPrefs.SetString("kDiffsDefaultApp", m_DiffTools.Length == 0 ? "" : m_DiffTools[m_DiffToolIndex]); + EditorPrefs.SetString("customDiffToolPath", m_CustomDiffToolPath); + EditorPrefs.SetString("twoWayDiffArguments", m_CustomDiffToolArguments[0]); + EditorPrefs.SetString("threeWayDiffArguments", m_CustomDiffToolArguments[1]); + EditorPrefs.SetString("mergeArguments", m_CustomDiffToolArguments[2]); WriteRecentAppsList(m_ScriptApps, m_ScriptEditorPath, kRecentScriptAppsKey); WriteRecentAppsList(m_ImageApps, m_ImageAppPath, kRecentImageAppsKey); @@ -1009,8 +1035,15 @@ private void ReadPreferences() m_DiffTools = InternalEditorUtility.GetAvailableDiffTools(); + m_CustomDiffToolPath = EditorPrefs.GetString("customDiffToolPath", m_CustomDiffToolPath); + m_CustomDiffToolArguments[0] = EditorPrefs.GetString("twoWayDiffArguments", m_CustomDiffToolArguments[0]); + m_CustomDiffToolArguments[1] = EditorPrefs.GetString("threeWayDiffArguments", m_CustomDiffToolArguments[1]); + m_CustomDiffToolArguments[2] = EditorPrefs.GetString("mergeArguments", m_CustomDiffToolArguments[2]); + InternalEditorUtility.SetCustomDiffToolData(m_CustomDiffToolPath, m_CustomDiffToolArguments[0], m_CustomDiffToolArguments[1], m_CustomDiffToolArguments[2]); + + // only show warning if has team license - if ((m_DiffTools == null || m_DiffTools.Length == 0) && InternalEditorUtility.HasTeamLicense()) + if ((m_DiffTools == null || (m_DiffTools.Length == 1 && m_CustomDiffToolPath.Equals(""))) && InternalEditorUtility.HasTeamLicense()) { m_noDiffToolsMessage = InternalEditorUtility.GetNoDiffToolsDetectedMessage(); } diff --git a/Editor/Mono/ProjectBrowser.cs b/Editor/Mono/ProjectBrowser.cs index c3439d35f9..c9dee2b801 100644 --- a/Editor/Mono/ProjectBrowser.cs +++ b/Editor/Mono/ProjectBrowser.cs @@ -2165,7 +2165,7 @@ void ToggleExpansionAnimationPreference() { bool oldValue = EditorPrefs.GetBool(TreeViewController.kExpansionAnimationPrefKey, false); EditorPrefs.SetBool(TreeViewController.kExpansionAnimationPrefKey, !oldValue); - InternalEditorUtility.RequestScriptReload(); + EditorUtility.RequestScriptReload(); } public virtual void AddItemsToMenu(GenericMenu menu) diff --git a/Editor/Mono/ProjectBrowser/SavedSearchFilter.cs b/Editor/Mono/ProjectBrowser/SavedSearchFilter.cs index 7d35db412b..be7debc7fa 100644 --- a/Editor/Mono/ProjectBrowser/SavedSearchFilter.cs +++ b/Editor/Mono/ProjectBrowser/SavedSearchFilter.cs @@ -117,7 +117,7 @@ public static string GetName(int instanceID) if (filter != null) return filter.m_Name; - Debug.LogError("Could not find saved filter " + instanceID + " " + instance.ToString()); + Debug.LogError("Could not find saved filter " + instanceID + " " + instance); return ""; } @@ -130,7 +130,7 @@ public static void SetName(int instanceID, string name) instance.Changed(); } else - Debug.LogError("Could not set name of saved filter " + instanceID + " " + instance.ToString()); + Debug.LogError("Could not set name of saved filter " + instanceID + " " + instance); } public static void UpdateExistingSavedFilter(int instanceID, SearchFilter filter, float previewSize) @@ -273,7 +273,7 @@ void UpdateFilter(int instanceID, SearchFilter filter, float previewSize) } else { - Debug.LogError("Could not find saved filter " + instanceID + " " + instance.ToString()); + Debug.LogError("Could not find saved filter " + instanceID + " " + instance); } } diff --git a/Editor/Mono/ProjectBrowserColumnOne.cs b/Editor/Mono/ProjectBrowserColumnOne.cs index 7656301614..9d4fd78feb 100644 --- a/Editor/Mono/ProjectBrowserColumnOne.cs +++ b/Editor/Mono/ProjectBrowserColumnOne.cs @@ -112,7 +112,17 @@ bool IsVisibleRootNode(TreeViewItem item) protected override Texture GetIconForItem(TreeViewItem item) { if (item != null && item.icon != null) - return item.icon; + { + var icon = item.icon; + AssetsTreeViewDataSource.FolderTreeItemBase folderItem = item as AssetsTreeViewDataSource.FolderTreeItemBase; + + if (folderItem != null && m_TreeView.data.IsExpanded(folderItem)) + { + icon = openFolderTexture; + } + + return icon; + } SearchFilterTreeItem searchFilterItem = item as SearchFilterTreeItem; if (searchFilterItem != null) @@ -265,6 +275,8 @@ public override void FetchData() m_RootItem = new TreeViewItem(0, 0, null, "Invisible Root Item"); SetExpanded(m_RootItem, true); // ensure always visible + Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName); + // We want three roots: Favorites, Assets, and Saved Filters List visibleRoots = new List(); @@ -272,18 +284,16 @@ public override void FetchData() int assetsFolderInstanceID = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID("Assets"); int depth = 0; string displayName = "Assets"; //CreateDisplayName (assetsFolderInstanceID); - TreeViewItem assetRootItem = new TreeViewItem(assetsFolderInstanceID, depth, m_RootItem, displayName); + AssetsTreeViewDataSource.RootTreeItem assetRootItem = new AssetsTreeViewDataSource.RootTreeItem(assetsFolderInstanceID, depth, m_RootItem, displayName); + assetRootItem.icon = folderIcon; ReadAssetDatabase("Assets", assetRootItem, depth + 1); // Fetch packages folder displayName = PackageManager.Folders.GetPackagesPath(); - TreeViewItem packagesRootItem = new TreeViewItem(ProjectBrowser.kPackagesFolderInstanceId, depth, m_RootItem, displayName); + AssetsTreeViewDataSource.RootTreeItem packagesRootItem = new AssetsTreeViewDataSource.RootTreeItem(ProjectBrowser.kPackagesFolderInstanceId, depth, m_RootItem, displayName); depth++; - Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName); - Texture2D emptyFolderIcon = EditorGUIUtility.FindTexture(EditorResources.emptyFolderIconName); - - packagesRootItem.icon = emptyFolderIcon; + packagesRootItem.icon = folderIcon; var packages = PackageManagerUtilityInternal.GetAllVisiblePackages(skipHiddenPackages); foreach (var package in packages) @@ -291,10 +301,10 @@ public override void FetchData() var packageFolderInstanceId = AssetDatabase.GetMainAssetOrInProgressProxyInstanceID(package.assetPath); displayName = !string.IsNullOrEmpty(package.displayName) ? package.displayName : package.name; - TreeViewItem packageItem = new TreeViewItem(packageFolderInstanceId, depth, packagesRootItem, displayName); + AssetsTreeViewDataSource.PackageTreeItem packageItem = new AssetsTreeViewDataSource.PackageTreeItem(packageFolderInstanceId, depth, packagesRootItem, displayName); + packageItem.icon = folderIcon; packagesRootItem.AddChild(packageItem); ReadAssetDatabase(package.assetPath, packageItem, depth + 1); - packagesRootItem.icon = folderIcon; } // Fetch saved filters @@ -328,15 +338,14 @@ private void ReadAssetDatabase(string assetFolderRootPath, TreeViewItem parent, property.Reset(); Texture2D folderIcon = EditorGUIUtility.FindTexture(EditorResources.folderIconName); - Texture2D emptyFolderIcon = EditorGUIUtility.FindTexture(EditorResources.emptyFolderIconName); List allFolders = new List(); while (property.Next(null)) { if (property.isFolder) { - TreeViewItem folderItem = new TreeViewItem(property.instanceID, baseDepth + property.depth, null, property.name); - folderItem.icon = property.hasChildren ? folderIcon : emptyFolderIcon; + AssetsTreeViewDataSource.FolderTreeItem folderItem = new AssetsTreeViewDataSource.FolderTreeItem(property.guid, property.instanceID, baseDepth + property.depth, null, property.name); + folderItem.icon = folderIcon; allFolders.Add(folderItem); } } diff --git a/Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs b/Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs index 6519d69063..ab112805c5 100644 --- a/Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs +++ b/Editor/Mono/ProjectWindow/CachedFilteredHierachy.cs @@ -33,7 +33,8 @@ public Texture2D icon // Note: Do not set m_Icon as GetCachedIcon uses its own cache that is cleared on reaching a max limit. // This is because when having e.g very large projects (1000s of textures with unique icons) we do not want all icons loaded // at the same time so don't keep a reference in m_Icon here - string path = AssetDatabase.GetAssetPath(instanceID); + string path = instanceID == 0 ? null : AssetDatabase.GetAssetPath(instanceID); + if (path != null) // Finding icon based on only file extension fails in several ways, and a different approach have to be found. // Using InternalEditorUtility.FindIconForFile first in revision f25945218bb6 / 29b23dbe4b5c introduced several regressions. @@ -44,6 +45,10 @@ public Texture2D icon // Support for specific file types based on file extensiom have to be supported inside AssetDatabase.GetCachedIcon // itself to work correctly and universally. for e.g. uxml files from within GetCachedIcon without relying on FindIconForFile. return AssetDatabase.GetCachedIcon(path) as Texture2D; + + path = string.IsNullOrEmpty(m_Guid) ? null : AssetDatabase.GUIDToAssetPath(m_Guid); + if (path != null) + return UnityEditorInternal.InternalEditorUtility.FindIconForFile(path); } else if (type == HierarchyType.GameObjects) { @@ -65,15 +70,21 @@ public Texture2D icon } private Texture2D m_Icon; + internal string m_Guid; + public string guid { get { if (type == HierarchyType.Assets) { - string path = AssetDatabase.GetAssetPath(instanceID); - if (path != null) - return AssetDatabase.AssetPathToGUID(path); + if (instanceID != 0 && string.IsNullOrEmpty(m_Guid)) + { + string path = AssetDatabase.GetAssetPath(instanceID); + if (path != null) + m_Guid = AssetDatabase.AssetPathToGUID(path); + } + return m_Guid; } return null; } @@ -162,7 +173,7 @@ void CopyPropertyData(ref FilterResult result, HierarchyProperty property) if (result == null) result = new FilterResult(); - result.instanceID = property.instanceID; + result.instanceID = property.GetInstanceIDIfImported(); result.name = property.name; result.hasChildren = property.hasChildren; result.colorCode = property.colorCode; @@ -176,10 +187,11 @@ void CopyPropertyData(ref FilterResult result, HierarchyProperty property) // Otherwise, don't - as this may cause Textures to load unintendedly (e.g if we have 3000 search results we do not want to load icons before needed when rendering) if (!property.isMainRepresentation) result.icon = property.icon; - else if (property.isFolder && !property.hasChildren) - result.icon = EditorGUIUtility.FindTexture(EditorResources.emptyFolderIconName); else result.icon = null; + + if (m_HierarchyType == HierarchyType.Assets) + result.m_Guid = property.guid; } void SearchAllAssets(SearchFilter.SearchArea area) @@ -456,7 +468,13 @@ public void Reset() public int instanceID { - get { return m_Hierarchy.results[m_Position].instanceID; } + get + { + var id = m_Hierarchy.results[m_Position].instanceID; + if (id == 0) + m_Hierarchy.results[m_Position].instanceID = AssetDatabase.GetMainAssetInstanceID(guid); + return m_Hierarchy.results[m_Position].instanceID; + } } public Object pptrValue @@ -591,5 +609,10 @@ public int CountRemaining(int[] expanded) { return m_Hierarchy.results.Length - m_Position - 1; } + + public int GetInstanceIDIfImported() + { + return m_Hierarchy.results[m_Position].instanceID; + } } } diff --git a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs index 6aa10d95f0..11b1702521 100644 --- a/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs +++ b/Editor/Mono/ProjectWindow/ProjectWindowUtil.cs @@ -93,7 +93,7 @@ public override void Action(int instanceId, string pathName, string resourceFile internal class DoCreateFolderWithTemplates : EndNameEditAction { - private const string kResourcesTemplatePath = "Resources/ScriptTemplates"; + public string kResourcesTemplatePath = "Resources/ScriptTemplates"; public IList templates { get; set; } @@ -259,13 +259,21 @@ public static void CreateAsset(Object asset, string pathName) // Create a folder public static void CreateFolder() { - StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Folder", EditorGUIUtility.IconContent(EditorResources.emptyFolderIconName).image as Texture2D, null); + StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance(), "New Folder", EditorGUIUtility.IconContent(EditorResources.folderIconName).image as Texture2D, null); } internal static void CreateFolderWithTemplates(string defaultName, params string[] templates) { var endNameEditAction = ScriptableObject.CreateInstance(); endNameEditAction.templates = templates; + StartNameEditingIfProjectWindowExists(0, endNameEditAction, defaultName, EditorGUIUtility.IconContent(EditorResources.folderIconName).image as Texture2D, null); + } + + internal static void CreateFolderWithTemplatesWithCustomResourcesPath(string defaultName, string customResPath, params string[] templates) + { + var endNameEditAction = ScriptableObject.CreateInstance(); + endNameEditAction.templates = templates; + endNameEditAction.kResourcesTemplatePath = customResPath; StartNameEditingIfProjectWindowExists(0, endNameEditAction, defaultName, EditorGUIUtility.IconContent(EditorResources.emptyFolderIconName).image as Texture2D, null); } diff --git a/Editor/Mono/ProjectWindow/SearchableEditorWindow.cs b/Editor/Mono/ProjectWindow/SearchableEditorWindow.cs index 26c2dd57d6..67c0d7d265 100644 --- a/Editor/Mono/ProjectWindow/SearchableEditorWindow.cs +++ b/Editor/Mono/ProjectWindow/SearchableEditorWindow.cs @@ -10,8 +10,8 @@ namespace UnityEditor { public class SearchableEditorWindow : EditorWindow { - public enum SearchMode { All, Name, Type, Label, AssetBundleName }; - public enum SearchModeHierarchyWindow { All, Name, Type }; + public enum SearchMode { All, Name, Type, Label, AssetBundleName } + public enum SearchModeHierarchyWindow { All, Name, Type } internal static SearchFilter CreateFilter(string searchString, SearchMode searchMode) { @@ -145,8 +145,8 @@ internal static void SearchForReferencesToInstanceID(int instanceID) { string searchFilter; - // only main assets have unique paths (remove "Assets" to make string simpler) - string path = AssetDatabase.GetAssetPath(instanceID).Substring(7); + // Don't remove "Assets" prefix, we need to support Packages as well (https://fogbugz.unity3d.com/f/cases/1161019/) + string path = AssetDatabase.GetAssetPath(instanceID); if (path.IndexOf(' ') != -1) path = '"' + path + '"'; diff --git a/Editor/Mono/RagdollBuilder.cs b/Editor/Mono/RagdollBuilder.cs index 785a2c58b7..88f1a1f04e 100644 --- a/Editor/Mono/RagdollBuilder.cs +++ b/Editor/Mono/RagdollBuilder.cs @@ -271,7 +271,7 @@ void BuildCapsules() } } - CapsuleCollider collider = (CapsuleCollider)bone.anchor.gameObject.AddComponent(); + CapsuleCollider collider = Undo.AddComponent(bone.anchor.gameObject); collider.direction = direction; Vector3 center = Vector3.zero; @@ -291,15 +291,15 @@ void Cleanup() Component[] joints = bone.anchor.GetComponentsInChildren(typeof(Joint)); foreach (Joint joint in joints) - DestroyImmediate(joint); + Undo.DestroyObjectImmediate(joint); Component[] bodies = bone.anchor.GetComponentsInChildren(typeof(Rigidbody)); foreach (Rigidbody body in bodies) - DestroyImmediate(body); + Undo.DestroyObjectImmediate(body); Component[] colliders = bone.anchor.GetComponentsInChildren(typeof(Collider)); foreach (Collider collider in colliders) - DestroyImmediate(collider); + Undo.DestroyObjectImmediate(collider); } } @@ -307,7 +307,7 @@ void BuildBodies() { foreach (BoneInfo bone in bones) { - bone.anchor.gameObject.AddComponent(); + Undo.AddComponent(bone.anchor.gameObject); bone.anchor.GetComponent().mass = bone.density; } } @@ -319,7 +319,7 @@ void BuildJoints() if (bone.parent == null) continue; - CharacterJoint joint = bone.anchor.gameObject.AddComponent(); + CharacterJoint joint = Undo.AddComponent(bone.anchor.gameObject); bone.joint = joint; // Setup connection and axis @@ -479,12 +479,12 @@ void AddBreastColliders() // Middle spine bounds bounds = Clip(GetBreastBounds(pelvis), pelvis, middleSpine, false); - box = (BoxCollider)pelvis.gameObject.AddComponent(); + box = Undo.AddComponent(pelvis.gameObject); box.center = bounds.center; box.size = bounds.size; bounds = Clip(GetBreastBounds(middleSpine), middleSpine, middleSpine, true); - box = (BoxCollider)middleSpine.gameObject.AddComponent(); + box = Undo.AddComponent(middleSpine.gameObject); box.center = bounds.center; box.size = bounds.size; } @@ -500,7 +500,7 @@ void AddBreastColliders() Vector3 size = bounds.size; size[SmallestComponent(bounds.size)] = size[LargestComponent(bounds.size)] / 2.0F; - BoxCollider box = pelvis.gameObject.AddComponent(); + BoxCollider box = Undo.AddComponent(pelvis.gameObject); box.center = bounds.center; box.size = size; } @@ -514,7 +514,7 @@ void AddHeadCollider() float radius = Vector3.Distance(leftArm.transform.position, rightArm.transform.position); radius /= 4; - SphereCollider sphere = head.gameObject.AddComponent(); + SphereCollider sphere = Undo.AddComponent(head.gameObject); sphere.radius = radius; Vector3 center = Vector3.zero; diff --git a/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs b/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs index a13ddaa765..d85ceff3d3 100644 --- a/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs +++ b/Editor/Mono/SceneModeWindows/DefaultLightingExplorerExtension.cs @@ -62,7 +62,7 @@ private static bool IsEditable(Object target) protected virtual UnityEngine.Object[] GetLights() { - return UnityEngine.Object.FindObjectsOfType(); + return Resources.FindObjectsOfTypeAll(); } protected virtual LightingExplorerTableColumn[] GetLightColumns() @@ -161,7 +161,7 @@ protected virtual LightingExplorerTableColumn[] GetLightColumns() protected virtual UnityEngine.Object[] GetReflectionProbes() { - return UnityEngine.Object.FindObjectsOfType(); + return Resources.FindObjectsOfTypeAll(); } protected virtual LightingExplorerTableColumn[] GetReflectionProbeColumns() @@ -188,7 +188,7 @@ protected virtual LightingExplorerTableColumn[] GetReflectionProbeColumns() protected virtual UnityEngine.Object[] GetLightProbes() { - return UnityEngine.Object.FindObjectsOfType(); + return Resources.FindObjectsOfTypeAll(); } protected virtual LightingExplorerTableColumn[] GetLightProbeColumns() @@ -202,7 +202,7 @@ protected virtual LightingExplorerTableColumn[] GetLightProbeColumns() protected virtual UnityEngine.Object[] GetEmissives() { - return Object.FindObjectsOfType().Where((MeshRenderer mr) => { + return Resources.FindObjectsOfTypeAll().Where((MeshRenderer mr) => { return (GameObjectUtility.AreStaticEditorFlagsSet(mr.gameObject, StaticEditorFlags.ContributeGI)); }).SelectMany(meshRenderer => meshRenderer.sharedMaterials).Where((Material m) => { return m != null && ((m.globalIlluminationFlags & MaterialGlobalIlluminationFlags.AnyEmissive) != 0) && m.HasProperty("_EmissionColor"); diff --git a/Editor/Mono/SceneModeWindows/LightingExplorerTab.cs b/Editor/Mono/SceneModeWindows/LightingExplorerTab.cs index d48b19997c..3ead7b9fc6 100644 --- a/Editor/Mono/SceneModeWindows/LightingExplorerTab.cs +++ b/Editor/Mono/SceneModeWindows/LightingExplorerTab.cs @@ -29,12 +29,6 @@ public LightingExplorerTab(string title, Func objects, Fun m_Title = EditorGUIUtility.TrTextContent(title); } - internal void OnEnable() - { - if (m_LightTable != null) - m_LightTable.OnEnable(); - } - internal void OnDisable() { if (m_LightTable != null) diff --git a/Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs b/Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs index 2e53d0379a..f7ab74b3bd 100644 --- a/Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs +++ b/Editor/Mono/SceneModeWindows/LightingExplorerWindow.cs @@ -54,11 +54,6 @@ void OnEnable() UpdateTabs(); - for (int i = 0; i < m_TableTabs.Length; i++) - { - m_TableTabs[i].OnEnable(); - } - EditorApplication.searchChanged += Repaint; Repaint(); } diff --git a/Editor/Mono/SceneModeWindows/LightingWindow.cs b/Editor/Mono/SceneModeWindows/LightingWindow.cs index 5d2475efa6..32da822636 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindow.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindow.cs @@ -99,7 +99,7 @@ void OnSelectionChange() static internal void RepaintSceneAndGameViews() { SceneView.RepaintAll(); - PreviewEditorWindow.RepaintAll(); + PlayModeView.RepaintAll(); } void OnGUI() diff --git a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs index baec1cdd39..843e719978 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowBakeSettings.cs @@ -144,9 +144,9 @@ public void OnEnable() { InitSettings(); - m_ShowGeneralLightmapSettings = new SavedBool($"LightingWindow.ShowGeneralLightmapSettings", true); - m_ShowRealtimeLightsSettings = new SavedBool($"LightingWindow.ShowRealtimeLightsSettings", true); - m_ShowMixedLightsSettings = new SavedBool($"LightingWindow.ShowMixedLightsSettings", true); + m_ShowGeneralLightmapSettings = new SavedBool("LightingWindow.ShowGeneralLightmapSettings", true); + m_ShowRealtimeLightsSettings = new SavedBool("LightingWindow.ShowRealtimeLightsSettings", true); + m_ShowMixedLightsSettings = new SavedBool("LightingWindow.ShowMixedLightsSettings", true); } public void OnDisable() @@ -349,7 +349,7 @@ public void DeveloperBuildSettingsGUI() Lightmapping.enlightenForceUpdates = EditorGUILayout.Toggle(Styles.ForceUpdates, Lightmapping.enlightenForceUpdates); Lightmapping.enlightenForceWhiteAlbedo = EditorGUILayout.Toggle(Styles.ForceWhiteAlbedo, Lightmapping.enlightenForceWhiteAlbedo); - if (m_BakeBackend.intValue == (int)LightmapEditorSettings.Lightmapper.ProgressiveCPU) + if (m_BakeBackend.intValue != (int)LightmapEditorSettings.Lightmapper.Enlighten) { EditorGUILayout.PropertyField(m_ExportTrainingData, Styles.ExportTrainingData); diff --git a/Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs b/Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs index c517df122f..61491f08c1 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowLightingTab.cs @@ -168,9 +168,9 @@ public void OnEnable() InitLightmapSettings(); - m_ShowOtherSettings = new SavedBool($"LightingWindow.ShowOtherSettings", true); - m_ShowDebugSettings = new SavedBool($"LightingWindow.ShowDebugSettings", false); - m_ShowProbeDebugSettings = new SavedBool($"LightingWindow.ShowProbeDebugSettings", false); + m_ShowOtherSettings = new SavedBool("LightingWindow.ShowOtherSettings", true); + m_ShowDebugSettings = new SavedBool("LightingWindow.ShowDebugSettings", false); + m_ShowProbeDebugSettings = new SavedBool("LightingWindow.ShowProbeDebugSettings", false); } public void OnDisable() @@ -473,14 +473,12 @@ void Summary() int numConvergedLightmapsNotInView = 0; int numNotConvergedLightmapsNotInView = 0; - int numInvalidConvergenceLightmaps = 0; int numLightmaps = LightmapSettings.lightmaps.Length; for (int i = 0; i < numLightmaps; ++i) { LightmapConvergence lc = Lightmapping.GetLightmapConvergence(i); if (!lc.IsValid()) { - numInvalidConvergenceLightmaps++; continue; } diff --git a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs b/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs index ae9dc43f55..56ad971bb4 100644 --- a/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs +++ b/Editor/Mono/SceneModeWindows/LightingWindowLightmapPreviewTab.cs @@ -421,7 +421,7 @@ private void ShowObjectNamesSizesAndCounts(string foldoutName, string editorPref if (objectNames.Length == 0) return; - string countString = counts.Length > 0 ? (SumCounts(counts).ToString() + " tris, ") : ""; + string countString = counts.Length > 0 ? (SumCounts(counts) + " tris, ") : ""; string sizeString = SizeString(SumSizes(sizes)); string foldoutNameFull = foldoutName + " (" + countString + sizeString + ")"; bool showDetailsOld = EditorPrefs.GetBool(editorPrefsName, false); diff --git a/Editor/Mono/SceneModeWindows/NavigationWindow.cs b/Editor/Mono/SceneModeWindows/NavigationWindow.cs index 732f6c9bbd..9a02202ab2 100644 --- a/Editor/Mono/SceneModeWindows/NavigationWindow.cs +++ b/Editor/Mono/SceneModeWindows/NavigationWindow.cs @@ -95,7 +95,7 @@ private class Styles EditorGUIUtility.TrTextContent("Bake", "Navmesh bake settings."), EditorGUIUtility.TrTextContent("Object", "Bake settings for the currently selected object."), }; - }; + } [MenuItem("Window/AI/Navigation", false, 1)] public static void SetupWindow() @@ -454,7 +454,7 @@ public void OnBecameInvisible() static void RepaintSceneAndGameViews() { SceneView.RepaintAll(); - PreviewEditorWindow.RepaintAll(); + PlayModeView.RepaintAll(); } public void OnSceneViewGUI(SceneView sceneView) diff --git a/Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs b/Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs index 51ed489cc1..a93b0655a3 100644 --- a/Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs +++ b/Editor/Mono/SceneModeWindows/OcclusionCullingWindow.cs @@ -46,7 +46,7 @@ class Styles public GUIContent farClipPlane = EditorGUIUtility.TrTextContent("Far Clip Plane", "Far Clip Plane used during baking. This should match the largest far clip plane used by any camera in the scene. A value of 0.0 sets the far plane to Infinity."); public GUIContent smallestOccluder = EditorGUIUtility.TrTextContent("Smallest Occluder", "The size of the smallest object that will be used to hide other objects when doing occlusion culling. For example, if a value of 4 is chosen, then all the objects that are higher or wider than 4 meters will block visibility and the objects that are smaller than that will not. This value is a tradeoff between occlusion accuracy and storage size."); public GUIContent defaultParameterText = EditorGUIUtility.TrTextContent("Default Parameters", "The default parameters guarantee that any given scene computes fast and the occlusion culling results are good. As the parameters are always scene specific, better results will be achieved when fine tuning the parameters on a scene to scene basis. All the parameters are dependent on the unit scale of the scene and it is imperative that the unit scale parameter is set correctly before setting the default values."); - }; + } enum Mode { diff --git a/Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs b/Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs index 59ae581bd0..551bac305b 100644 --- a/Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs +++ b/Editor/Mono/SceneModeWindows/PhysicsDebugWindow.cs @@ -85,10 +85,10 @@ public static PhysicsDebugWindow ShowWindow() public void OnEnable() { - m_ShowInfoFoldout = new SavedBool($"PhysicsDebugWindow.ShowFoldout", false); - m_ShowColliderTypeFoldout = new SavedBool($"PhysicsDebugWindow.ShowColliderType", false); - m_ColorFoldout = new SavedBool($"PhysicsDebugWindow.ShowColorFoldout", false); - m_RenderingFoldout = new SavedBool($"PhysicsDebugWindow.ShowRenderingFoldout", false); + m_ShowInfoFoldout = new SavedBool("PhysicsDebugWindow.ShowFoldout", false); + m_ShowColliderTypeFoldout = new SavedBool("PhysicsDebugWindow.ShowColliderType", false); + m_ColorFoldout = new SavedBool("PhysicsDebugWindow.ShowColorFoldout", false); + m_RenderingFoldout = new SavedBool("PhysicsDebugWindow.ShowRenderingFoldout", false); } void AddPicker() diff --git a/Editor/Mono/SceneView/SceneView.cs b/Editor/Mono/SceneView/SceneView.cs index 96a09aabac..65e696010e 100644 --- a/Editor/Mono/SceneView/SceneView.cs +++ b/Editor/Mono/SceneView/SceneView.cs @@ -472,10 +472,11 @@ public bool showGrid public class CameraSettings { const float defaultEasingDuration = .4f; - const float kAbsoluteSpeedMin = .01f; + const float kAbsoluteSpeedMin = .001f; const float kAbsoluteSpeedMax = 99f; const float kAbsoluteEasingDurationMin = .1f; const float kAbsoluteEasingDurationMax = 2f; + const float kMinSpeedMinMaxRange = .001f; [SerializeField] float m_Speed; @@ -507,7 +508,7 @@ public CameraSettings() { m_Speed = 1f; m_SpeedNormalized = .5f; - m_SpeedMin = .01f; + m_SpeedMin = kAbsoluteSpeedMin; m_SpeedMax = 2f; m_EasingEnabled = true; m_EasingDuration = defaultEasingDuration; @@ -540,10 +541,7 @@ public float speedNormalized set { m_SpeedNormalized = Mathf.Clamp01(value); - float speed = Mathf.Lerp(m_SpeedMin, m_SpeedMax, m_SpeedNormalized); - // Round to nearest decimal: 2 decimal points when between [0.01, 0.1]; 1 decimal point when between [0.1, 10]; integral between [10, 99] - speed = (float)(System.Math.Round((double)speed, speed < 0.1f ? 2 : speed < 10f ? 1 : 0)); - m_Speed = Mathf.Clamp(speed, m_SpeedMin, m_SpeedMax); + m_Speed = Mathf.Lerp(m_SpeedMin, m_SpeedMax, m_SpeedNormalized); } } @@ -592,7 +590,7 @@ public float easingDuration set { // Clamp and round to 1 decimal point - m_EasingDuration = (float)(Math.Round((double)Mathf.Clamp(value, kAbsoluteEasingDurationMin, kAbsoluteEasingDurationMax), 1)); + m_EasingDuration = (float)Math.Round(Mathf.Clamp(value, kAbsoluteEasingDurationMin, kAbsoluteEasingDurationMax), 1); } } @@ -604,24 +602,25 @@ public bool accelerationEnabled set { m_AccelerationEnabled = value; } } - internal void SetSpeedMinMax(float[] floatValues) + // this ensures that the resolution the slider snaps to is sufficient given the minimum speed, and the + // range of appropriate values + internal float RoundSpeedToNearestSignificantDecimal(float value) { - // Round to nearest decimal: 2 decimal points when between [0.01, 0.1]; 1 decimal point when between [0.1, 10]; integral between [10, 99] - floatValues[0] = (float)(Math.Round((double)floatValues[0], floatValues[0] < 0.1f ? 2 : floatValues[0] < 10f ? 1 : 0)); - floatValues[1] = (float)(Math.Round((double)floatValues[1], floatValues[1] < 0.1f ? 2 : floatValues[1] < 10f ? 1 : 0)); - - floatValues[0] = Mathf.Clamp(floatValues[0], kAbsoluteSpeedMin, kAbsoluteSpeedMax - 1f); - - bool floatsAreEqual = Mathf.Abs(floatValues[0] - floatValues[1]) < Mathf.Epsilon; - - // Ensure there is at least a range of 1 - if (floatsAreEqual || floatValues[0] > floatValues[1]) - floatValues[1] = floatValues[0] + 1f; + float rng = speedMax - speedMin; + int min_rnd = speedMin < .01f ? 3 : speedMin < .1f ? 2 : speedMin < 1f ? 1 : 0; + int rng_rnd = rng < 1f ? 2 : rng < 10f ? 1 : 0; + return (float)Math.Round(value, Mathf.Max(min_rnd, rng_rnd)); + } - floatValues[1] = Mathf.Clamp(floatValues[1], kAbsoluteSpeedMin + 0.01f, kAbsoluteSpeedMax); + internal void SetSpeedMinMax(float[] floatValues) + { + // Clamp min to valid ranges + float min = Mathf.Clamp(floatValues[0], kAbsoluteSpeedMin, kAbsoluteSpeedMax - kMinSpeedMinMaxRange); + float minRange = min < .1f ? .01f : min < 1f ? .1f : 1f; + float max = Mathf.Clamp(floatValues[1], min + minRange, kAbsoluteSpeedMax); - m_SpeedMin = floatValues[0]; - m_SpeedMax = floatValues[1]; + m_SpeedMin = min; + m_SpeedMax = max; // This will clamp the speed to the new range speed = m_Speed; @@ -916,10 +915,10 @@ internal override void SetSearchFilter(string searchFilter, SearchMode mode, boo internal void OnLostFocus() { // don't bleed our scene view rendering into game view - var previewWindow = PreviewEditorWindow.GetMainPreviewWindow(); - if (previewWindow && previewWindow.m_Parent != null && m_Parent != null && previewWindow.m_Parent == m_Parent) + var playModeView = PlayModeView.GetMainPlayModeView(); + if (playModeView && playModeView.m_Parent != null && m_Parent != null && playModeView.m_Parent == m_Parent) { - previewWindow.m_Parent.backgroundValid = false; + playModeView.m_Parent.backgroundValid = false; } if (s_LastActiveSceneView == this) @@ -3655,9 +3654,9 @@ static void ShowCompileErrorNotification() internal static void ShowSceneViewPlayModeSaveWarning() { // In this case, we want to explicitly try the GameView before passing it on to whatever notificationView we have - var preview = (PreviewEditorWindow)WindowLayout.FindEditorWindowOfType(typeof(PreviewEditorWindow)); - if (preview != null && preview.hasFocus) - preview.ShowNotification(EditorGUIUtility.TrTextContent("You must exit play mode to save the scene!")); + var playModeView = (PlayModeView)WindowLayout.FindEditorWindowOfType(typeof(PlayModeView)); + if (playModeView != null && playModeView.hasFocus) + playModeView.ShowNotification(EditorGUIUtility.TrTextContent("You must exit play mode to save the scene!")); else ShowNotification("You must exit play mode to save the scene!"); } diff --git a/Editor/Mono/SceneView/SceneViewGrid.cs b/Editor/Mono/SceneView/SceneViewGrid.cs index 869a272209..66dedba527 100644 --- a/Editor/Mono/SceneView/SceneViewGrid.cs +++ b/Editor/Mono/SceneView/SceneViewGrid.cs @@ -167,33 +167,36 @@ internal Vector3 GetPivot(GridRenderAxis axis) internal void UpdateGridsVisibility(Quaternion rotation, bool orthoMode) { - bool _xGrid = false, _yGrid = false, _zGrid = false; + bool showX = false, showY = false, showZ = false; if (showGrid) { if (orthoMode) { Vector3 fwd = rotation * Vector3.forward; - // Show horizontal grid as long as angle is not too small - if (Mathf.Abs(fwd.y) > 0.2f) - _yGrid = true; - // Show xy and zy planes only when straight on + + // Show xy, zy and xz planes only when straight on + if (fwd == Vector3.up || fwd == Vector3.down) + showY = true; else if (fwd == Vector3.left || fwd == Vector3.right) - _xGrid = true; + showX = true; else if (fwd == Vector3.forward || fwd == Vector3.back) - _zGrid = true; + showZ = true; } - else + + // Main path for perspective mode. + // In ortho, fallback on this path if camera is not aligned with X, Y or Z axis. + if (!showX && !showY && !showZ) { - _xGrid = (gridAxis == GridRenderAxis.X || gridAxis == GridRenderAxis.All); - _yGrid = (gridAxis == GridRenderAxis.Y || gridAxis == GridRenderAxis.All); - _zGrid = (gridAxis == GridRenderAxis.Z || gridAxis == GridRenderAxis.All); + showX = (gridAxis == GridRenderAxis.X || gridAxis == GridRenderAxis.All); + showY = (gridAxis == GridRenderAxis.Y || gridAxis == GridRenderAxis.All); + showZ = (gridAxis == GridRenderAxis.Z || gridAxis == GridRenderAxis.All); } } - xGrid.fade.target = _xGrid; - yGrid.fade.target = _yGrid; - zGrid.fade.target = _zGrid; + xGrid.fade.target = showX; + yGrid.fade.target = showY; + zGrid.fade.target = showZ; } internal void ApplySnapConstraintsInPerspectiveMode() @@ -285,11 +288,11 @@ internal DrawGridParameters PrepareGridRenderOrthogonalMode(Camera camera, Vecto // but if it's orbited rapidly, it can end up at this angle faster than the fading has kicked in. // For these cases hiding it abruptly looks better. // The popping isn't noticable because the user is orbiting rapidly to begin with. - if (Mathf.Abs(direction.x) >= k_AngleThresholdForOrthographicGrid) + if (xGrid.fade.target && Mathf.Abs(direction.x) >= k_AngleThresholdForOrthographicGrid) parameters = xGrid.PrepareGridRender(0, gridOpacity); - else if (Mathf.Abs(direction.y) >= k_AngleThresholdForOrthographicGrid) + else if (yGrid.fade.target && Mathf.Abs(direction.y) >= k_AngleThresholdForOrthographicGrid) parameters = yGrid.PrepareGridRender(1, gridOpacity); - else if (Mathf.Abs(direction.z) >= k_AngleThresholdForOrthographicGrid) + else if (zGrid.fade.target && Mathf.Abs(direction.z) >= k_AngleThresholdForOrthographicGrid) parameters = zGrid.PrepareGridRender(2, gridOpacity); return parameters; diff --git a/Editor/Mono/SceneView/SceneViewMotion.cs b/Editor/Mono/SceneView/SceneViewMotion.cs index b36470f86c..365923f456 100644 --- a/Editor/Mono/SceneView/SceneViewMotion.cs +++ b/Editor/Mono/SceneView/SceneViewMotion.cs @@ -393,11 +393,16 @@ private static void HandleScrollWheel(SceneView view, bool zoomTowardsCenter) { float scrollWheelDelta = Event.current.delta.y * s_FPSScrollWheelMultiplier; view.cameraSettings.speedNormalized -= scrollWheelDelta; - float cameraSettingsSpeed = view.cameraSettings.speed; - string cameraSpeedDisplayValue = cameraSettingsSpeed.ToString(cameraSettingsSpeed < 0.1f ? "F2" : cameraSettingsSpeed < 10f ? "F1" : "F0"); + string cameraSpeedDisplayValue = cameraSettingsSpeed.ToString( + cameraSettingsSpeed < 0.01f ? "F3" : + cameraSettingsSpeed < 0.1f ? "F2" : + cameraSettingsSpeed < 10f ? "F1" : + "F0"); + if (cameraSettingsSpeed < 0.1f) cameraSpeedDisplayValue = cameraSpeedDisplayValue.TrimStart(new Char[] {'0'}); + GUIContent cameraSpeedContent = EditorGUIUtility.TempContent(string.Format("{0}{1}", cameraSpeedDisplayValue, s_SceneView.cameraSettings.accelerationEnabled ? "x" : "")); @@ -975,9 +980,7 @@ internal void ViewAxisDirection(SceneView view, int dir) { // If holding shift or clicking with middle mouse button, orthographic is enforced, otherwise not altered. // Note: This function can also be called from a context menu where Event.current is null. - bool ortho = view.orthographic; - if (Event.current != null && (Event.current.shift || Event.current.button == 2)) - ortho = true; + bool ortho = view.orthographic || Event.current != null && (Event.current.shift || Event.current.button == 2); ViewAxisDirection(view, dir, ortho); } diff --git a/Editor/Mono/SceneView/SceneViewOverlay.cs b/Editor/Mono/SceneView/SceneViewOverlay.cs index 5d3906e588..f47200f806 100644 --- a/Editor/Mono/SceneView/SceneViewOverlay.cs +++ b/Editor/Mono/SceneView/SceneViewOverlay.cs @@ -51,7 +51,7 @@ public int CompareTo(OverlayWindow other) result = other.m_SecondaryOrder.CompareTo(m_SecondaryOrder); return result; } - }; + } public delegate void WindowFunction(Object target, SceneView sceneView); static List m_Windows; diff --git a/Editor/Mono/SceneVisibilityManager.cs b/Editor/Mono/SceneVisibilityManager.cs index c87c74f016..af6f8de469 100644 --- a/Editor/Mono/SceneVisibilityManager.cs +++ b/Editor/Mono/SceneVisibilityManager.cs @@ -268,6 +268,9 @@ private void Show(Scene scene, bool sendContentChangedEvent) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + SceneVisibilityState.ShowScene(scene); if (sendContentChangedEvent) @@ -281,6 +284,9 @@ private void EnablePickingNoUndo(Scene scene) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + SceneVisibilityState.EnablePicking(scene); } @@ -289,6 +295,9 @@ public void Show(Scene scene) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + Undo.RecordObject(SceneVisibilityState.GetInstance(), "Show Scene"); Show(scene, true); } @@ -298,6 +307,9 @@ public void EnablePicking(Scene scene) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + Undo.RecordObject(SceneVisibilityState.GetInstance(), "Enable Picking Scene"); EnablePickingNoUndo(scene); } @@ -307,6 +319,9 @@ private void HideNoUndo(Scene scene) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + SceneVisibilityState.ShowScene(scene); SceneVisibilityState.SetGameObjectsHidden(scene.GetRootGameObjects(), true, true); } @@ -316,6 +331,9 @@ internal void DisablePickingNoUndo(Scene scene) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + SceneVisibilityState.EnablePicking(scene); SceneVisibilityState.SetGameObjectsPickingDisabled(scene.GetRootGameObjects(), true, true); } @@ -325,6 +343,9 @@ public void Hide(Scene scene) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + Undo.RecordObject(SceneVisibilityState.GetInstance(), "Hide Scene"); HideNoUndo(scene); } @@ -334,6 +355,9 @@ public void DisablePicking(Scene scene) if (!scene.IsValid()) return; + if (!scene.isLoaded) + return; + Undo.RecordObject(SceneVisibilityState.GetInstance(), "Disable Picking Scene"); DisablePickingNoUndo(scene); } diff --git a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs b/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs index 4ccb6a8b45..cce7ce545c 100644 --- a/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs +++ b/Editor/Mono/ScriptAttributeGUI/PropertyHandler.cs @@ -43,7 +43,7 @@ public bool empty } } - public void HandleAttribute(PropertyAttribute attribute, FieldInfo field, Type propertyType) + public void HandleAttribute(SerializedProperty property, PropertyAttribute attribute, FieldInfo field, Type propertyType) { if (attribute is TooltipAttribute) { @@ -63,12 +63,12 @@ public void HandleAttribute(PropertyAttribute attribute, FieldInfo field, Type p } // Look for its drawer type of this attribute - HandleDrawnType(attribute.GetType(), propertyType, field, attribute); + HandleDrawnType(property, attribute.GetType(), propertyType, field, attribute); } - public void HandleDrawnType(Type drawnType, Type propertyType, FieldInfo field, PropertyAttribute attribute) + public void HandleDrawnType(SerializedProperty property, Type drawnType, Type propertyType, FieldInfo field, PropertyAttribute attribute) { - Type drawerType = ScriptAttributeUtility.GetDrawerTypeForType(drawnType); + Type drawerType = ScriptAttributeUtility.GetDrawerTypeForPropertyAndType(property, drawnType); // If we found a drawer type, instantiate the drawer, cache it, and return it. if (drawerType != null) diff --git a/Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs b/Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs index 95448db5da..311e189856 100644 --- a/Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs +++ b/Editor/Mono/ScriptAttributeGUI/ScriptAttributeUtility.cs @@ -116,6 +116,15 @@ private static void BuildDrawerTypeForTypeDictionary() } } + /// + /// Builds the drawer cache and checks for the drawer cache for a statically + /// defined drawer for a given type. + /// NOTE: The world 'statically' in this context means that what is being + /// looked up is only what is in the cache, which might not play well with + /// Managed References types (where the dynamic type matters). + /// + /// + /// internal static Type GetDrawerTypeForType(Type type) { if (s_DrawerTypeForType == null) @@ -126,6 +135,7 @@ internal static Type GetDrawerTypeForType(Type type) if (drawerType.drawer != null) return drawerType.drawer; + // // now check for base generic versions of the drawers... if (type.IsGenericType) s_DrawerTypeForType.TryGetValue(type.GetGenericTypeDefinition(), out drawerType); @@ -133,6 +143,46 @@ internal static Type GetDrawerTypeForType(Type type) return drawerType.drawer; } + /// + /// Does the same thing as 'GetDrawerTypeForType' (with the same side effect of building the cache) + /// but also plays well with Managed References. If the property that is used as a reference for the drawer + /// query is of a managed reference type, the class parents are also looked up as fallbacks. + /// + /// + /// + /// The custom property drawer type or 'null' if not found. + internal static Type GetDrawerTypeForPropertyAndType(SerializedProperty property, Type type) + { + // As a side effect this also builds the drawer cache dict + var staticDrawerType = GetDrawerTypeForType(type); + if (staticDrawerType != null) + return staticDrawerType; + + // Special case for managed references. + // The custom property drawers for those are defined with 'useForChildren=false' + // (otherwise the dynamic type is not taking into account in the custom property + // drawer resolution) so even if 's_DrawerTypeForType' is built (based on static types) + // we have to check base types for custom property drawers manually. + // Managed references with no drawers should properly try to fallback + if (property.propertyType == SerializedPropertyType.ManagedReference) + { + DrawerKeySet drawerTypes; + + FieldInfo foundField = null; + for (Type currentType = type; foundField == null && currentType != null; currentType = currentType.BaseType) + { + s_DrawerTypeForType.TryGetValue(currentType, out drawerTypes); + if (drawerTypes.drawer != null) + { + s_DrawerTypeForType.Add(type, drawerTypes); + return drawerTypes.drawer; + } + } + } + + return null; + } + private static List GetFieldAttributes(FieldInfo field) { if (field == null) @@ -145,7 +195,14 @@ private static List GetFieldAttributes(FieldInfo field) return null; } - internal static FieldInfo GetFieldInfoFromProperty(SerializedProperty property, out Type type) + /// + /// Returns the field info and field type for the property. The types are based on the + /// static field definition. + /// + /// + /// + /// + internal static FieldInfo GetFieldInfoAndStaticTypeFromProperty(SerializedProperty property, out Type type) { var classType = GetScriptTypeFromProperty(property); if (classType == null) @@ -156,6 +213,60 @@ internal static FieldInfo GetFieldInfoFromProperty(SerializedProperty property, return GetFieldInfoFromPropertyPath(classType, property.propertyPath, out type); } + /// + /// Returns the field info and type for the property. Contrary to GetFieldInfoAndStaticTypeFromProperty, + /// when confronted with a managed reference the dynamic instance type is returned. + /// + /// + /// + /// + internal static FieldInfo GetFieldInfoFromProperty(SerializedProperty property, out Type type) + { + var fieldInfo = GetFieldInfoAndStaticTypeFromProperty(property, out type); + if (fieldInfo == null) + return fieldInfo; + + // Managed references are a special case, we need to override the static type + // returned by 'GetFieldInfoFromPropertyPath' for custom property handler matching + // by the dynamic type of the instance. + if (property.propertyType == SerializedPropertyType.ManagedReference) + { + Type managedReferenceInstanceType; + + // Try to get a Type instance for the managed reference + if (GetTypeFromManagedReferenceFullTypeName(property.managedReferenceFullTypename, out managedReferenceInstanceType)) + { + type = managedReferenceInstanceType; + } + + // We keep the fallback to the field type returned by 'GetFieldInfoFromPropertyPath'. + } + + return fieldInfo; + } + + /// + /// Create a Type instance from the managed reference full type name description. + /// The expected format for the typename string is the one returned by SerializedProperty.managedReferenceFullTypename. + /// + /// + /// + /// + internal static bool GetTypeFromManagedReferenceFullTypeName(string managedReferenceFullTypename, out Type managedReferenceInstanceType) + { + managedReferenceInstanceType = null; + + var parts = managedReferenceFullTypename.Split(' '); + if (parts.Length == 2) + { + var assemblyPart = parts[0]; + var nsClassnamePart = parts[1]; + managedReferenceInstanceType = Type.GetType($"{nsClassnamePart}, {assemblyPart}"); + } + + return managedReferenceInstanceType != null; + } + private static Type GetScriptTypeFromProperty(SerializedProperty property) { if (property.serializedObject.targetObject != null) @@ -305,12 +416,12 @@ internal static PropertyHandler GetHandler(SerializedProperty property) if (attributes != null) { for (int i = attributes.Count - 1; i >= 0; i--) - handler.HandleAttribute(attributes[i], field, propertyType); + handler.HandleAttribute(property, attributes[i], field, propertyType); } // Field has no CustomPropertyDrawer attribute with matching drawer so look for default drawer for field type if (!handler.hasPropertyDrawer && propertyType != null) - handler.HandleDrawnType(propertyType, propertyType, field, null); + handler.HandleDrawnType(property, propertyType, propertyType, field, null); if (handler.empty) { diff --git a/Editor/Mono/Scripting/APIUpdater/APIUpdaterManager.bindings.cs b/Editor/Mono/Scripting/APIUpdater/APIUpdaterManager.bindings.cs index 12997385c3..902a530f2e 100644 --- a/Editor/Mono/Scripting/APIUpdater/APIUpdaterManager.bindings.cs +++ b/Editor/Mono/Scripting/APIUpdater/APIUpdaterManager.bindings.cs @@ -38,7 +38,7 @@ internal enum APIUpdaterStatus None, Offered, Accepted - }; + } //*undocumented* [NativeHeader("Editor/Src/Scripting/APIUpdater/APIUpdaterManager.h")] @@ -551,7 +551,7 @@ private static string ResolveAssemblyPath(string assemblyName) var resolvedList = assetsAssemblies.Where(a => CompareIgnoreCase(AssemblyNameFromPath(a), assemblyName)).ToArray(); var assemblyPathInAssetsFolder = resolvedList.OrderBy(path => path.Length).FirstOrDefault(); - if (resolvedList.Count() > 1 && !resolvedList.All(a => a.IsUnityExtension())) + if (resolvedList.Length > 1 && !resolvedList.All(a => a.IsUnityExtension())) { APIUpdaterLogger.WriteToFile("Warning : Multiple matches found for assembly name '{0}'. Shortest path one ({1}) choosen as the source of updates. Full list: {2}", assemblyName, assemblyPathInAssetsFolder, string.Join(Environment.NewLine, resolvedList)); } diff --git a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs index 24027f9cfe..c8920a1827 100644 --- a/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs +++ b/Editor/Mono/Scripting/Compilers/ScriptCompilerBase.cs @@ -378,7 +378,7 @@ protected static string PrepareFileName(string fileName) //do not change the returntype, native unity depends on this one. public virtual CompilerMessage[] GetCompilerMessages() { - if (!Poll()) + if (process != null && !process.HasExited) Debug.LogWarning("Compile process is not finished yet. This should not happen."); if (process == null) diff --git a/Editor/Mono/Scripting/Compilers/UWPReferences.cs b/Editor/Mono/Scripting/Compilers/UWPReferences.cs index d2c2861e13..0dea724f72 100644 --- a/Editor/Mono/Scripting/Compilers/UWPReferences.cs +++ b/Editor/Mono/Scripting/Compilers/UWPReferences.cs @@ -311,7 +311,6 @@ private static IEnumerable GetExtensionSDKs(string sdkFolder, s if (File.Exists(manifest)) { extensions.Add(new UWPExtensionSDK(extensionName, "1.0", manifest)); - continue; } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs b/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs index 060e9b77ea..39ad3ce324 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/AssemblyBuilder.cs @@ -21,7 +21,7 @@ public enum AssemblyBuilderFlags None = 0, EditorAssembly = 1, DevelopmentBuild = 2, - }; + } [Flags] public enum ReferencesOptions @@ -100,7 +100,8 @@ internal bool Build(EditorCompilation editorCompilation) var scriptAssembly = editorCompilation.CreateScriptAssembly(this); compilationTask = new CompilationTask(new ScriptAssembly[] { scriptAssembly }, scriptAssembly.OutputDirectory, this, - EditorScriptCompilationOptions.BuildingEmpty, CompilationTaskOptions.StopOnFirstError, 1); + EditorScriptCompilationOptions.BuildingEmpty, CompilationTaskOptions.StopOnFirstError, 1, + editorCompilation.ILPostProcessing.PostProcess); compilationTask.OnCompilationTaskStarted += (context) => { diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs b/Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs index 97db5c2ecc..507e7e4c24 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/AssemblyFlags.cs @@ -22,5 +22,5 @@ enum AssemblyFlags ExplicitReferences = (1 << 7), UnityModule = (1 << 8), NoEngineReferences = (1 << 9) - }; + } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/AssetPathMetaData.cs b/Editor/Mono/Scripting/ScriptCompilation/AssetPathMetaData.cs index a075bc7b49..bbc1d4d11a 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/AssetPathMetaData.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/AssetPathMetaData.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Diagnostics; using System.Runtime.InteropServices; using UnityEngine.Bindings; using UnityEngine.Scripting; @@ -14,6 +15,7 @@ namespace UnityEditor.Scripting.ScriptCompilation [RequiredByNativeCode(GenerateProxy = true)] [NativeHeader("Runtime/Scripting/ScriptingManagedProxySupport.h")] [NativeHeader("Runtime/ScriptingBackend/ScriptingNativeTypes.h")] + [DebuggerDisplay("{DirectoryPath}")] class AssetPathMetaData { public string DirectoryPath; diff --git a/Editor/Mono/Scripting/ScriptCompilation/AutoReferencedPackageAssemblies.cs b/Editor/Mono/Scripting/ScriptCompilation/AutoReferencedPackageAssemblies.cs index 6eab9084a8..4e8c35923f 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/AutoReferencedPackageAssemblies.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/AutoReferencedPackageAssemblies.cs @@ -40,7 +40,7 @@ static AutoReferencedPackageAssemblies() public static void AddReferences(Dictionary customTargetAssemblies, EditorScriptCompilationOptions options, Func shouldAdd) { - if (customTargetAssemblies == null || customTargetAssemblies.Count() == 0) + if (customTargetAssemblies == null || customTargetAssemblies.Count == 0) return; bool buildingForEditor = (options & EditorScriptCompilationOptions.BuildingForEditor) == EditorScriptCompilationOptions.BuildingForEditor; diff --git a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs index edd8731646..c5c0c0c0bd 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CSharpNamespaceParser.cs @@ -241,7 +241,7 @@ static bool CheckForNamespaceModification(Stack> namespaceScope { foreach (var tuple in namespaceScopeStack) { - if (tuple.Item1 && tuple.Item2 == stackCount) + if (tuple.Item1 && (stackCount == -1 || tuple.Item2 == stackCount)) return true; } return false; @@ -261,11 +261,11 @@ static string ReduceCodeAndCheckForNamespacesModification(string source, string foreach (var s in split) { - // Check for new namespace deeper than top level of directives + // Check for new namespace declarations, when we have are inside of multiple #ifs, + // and also have seen previous namespace declarations (likely namespace modification). if (k_Namespace.IsMatch(s)) { - if (stack.Count > 1) - namespaceModificationFound = true; + namespaceModificationFound |= (stack.Count > 1 && CheckForNamespaceModification(namespaceScopeStack, -1)); foundNamespace = true; } if (s.IndexOf("{", StringComparison.Ordinal) >= 0) @@ -291,7 +291,7 @@ static string ReduceCodeAndCheckForNamespacesModification(string source, string var directive = match.Groups[1].Value; if (directive == "else") { - namespaceModificationFound = CheckForNamespaceModification(namespaceScopeStack, stack.Count); + namespaceModificationFound |= CheckForNamespaceModification(namespaceScopeStack, stack.Count); var elseEmitting = stack.Peek().Item2; stack.Pop(); stack.Push(new Tuple(elseEmitting, false)); @@ -316,7 +316,7 @@ static string ReduceCodeAndCheckForNamespacesModification(string source, string } else if (directive == "elif") { - namespaceModificationFound = CheckForNamespaceModification(namespaceScopeStack, stack.Count); + namespaceModificationFound |= CheckForNamespaceModification(namespaceScopeStack, stack.Count); var evalResult = true; var elseEmitting = stack.Peek().Item2; stack.Pop(); diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs index 440d3ed406..b3a69805f0 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CompilationPipeline.cs @@ -501,5 +501,15 @@ internal static string GetAssemblyDefinitionFilePathFromScriptPath(EditorCompila return null; } } + + public static void RequestScriptCompilation() + { + RequestScriptCompilation(EditorCompilationInterface.Instance); + } + + internal static void RequestScriptCompilation(EditorCompilation editorCompilation) + { + editorCompilation.DirtyAllScripts(); + } } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs index 8468fe0497..558087c083 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CompilationTask.cs @@ -6,7 +6,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Threading; using UnityEditor.Scripting.Compilers; +using System.IO; namespace UnityEditor.Scripting.ScriptCompilation { @@ -14,7 +16,8 @@ namespace UnityEditor.Scripting.ScriptCompilation enum CompilationTaskOptions { None = 0, - StopOnFirstError = (1 << 0) + StopOnFirstError = (1 << 0), + RunPostProcessors = (1 << 1) } // CompilationTask represents one complete rebuild of all the ScriptAssembly's that are passed in the constructor. @@ -29,8 +32,11 @@ enum CompilionTaskState } HashSet pendingAssemblies; + Dictionary compiledAssemblies = new Dictionary(); Dictionary processedAssemblies = new Dictionary(); Dictionary compilerTasks = new Dictionary(); + List postProcessorTasks = new List(); + string buildOutputDirectory; object context; int compilePhase = 0; @@ -38,11 +44,13 @@ enum CompilionTaskState CompilationTaskOptions compilationTaskOptions; int maxConcurrentCompilers; CompilionTaskState state = CompilionTaskState.Started; + Func, string, List> postProcessFunc; public event Action OnCompilationTaskStarted; public event Action OnCompilationTaskFinished; public event Action OnBeforeCompilationStarted; public event Action OnCompilationStarted; + public event Action OnPostProcessingStarted; public event Action> OnCompilationFinished; public bool Stopped { get; private set; } @@ -53,7 +61,8 @@ public CompilationTask(ScriptAssembly[] scriptAssemblies, object context, EditorScriptCompilationOptions options, CompilationTaskOptions compilationTaskOptions, - int maxConcurrentCompilers) + int maxConcurrentCompilers, + Func, string, List> postProcessFunc) { pendingAssemblies = new HashSet(scriptAssemblies); CompileErrors = false; @@ -62,11 +71,12 @@ public CompilationTask(ScriptAssembly[] scriptAssemblies, this.options = options; this.compilationTaskOptions = compilationTaskOptions; this.maxConcurrentCompilers = maxConcurrentCompilers; + this.postProcessFunc = postProcessFunc; } public bool IsCompiling { - get { return pendingAssemblies.Count > 0 || compilerTasks.Count > 0; } + get { return pendingAssemblies.Count > 0 || compilerTasks.Count > 0 || postProcessorTasks.Count > 0; } } public Dictionary CompilerMessages @@ -152,15 +162,38 @@ public bool Poll() var compiler = task.Value; var messages = compiler.GetCompilerMessages(); - - // Convert messages to list, OnCompilationFinished callbacks might add - // more messages var messagesList = messages.ToList(); - if (OnCompilationFinished != null) - OnCompilationFinished(assembly, messagesList); + compiledAssemblies.Add(assembly, messagesList.ToArray()); + + if (RunPostProcessors && !messagesList.Any(m => m.type == CompilerMessageType.Error)) + { + var sourcePath = AssetPath.Combine(buildOutputDirectory, assembly.Filename); + + try + { + File.Copy(sourcePath, assembly.FullPath, true); + var postProcessorTask = new PostProcessorTask(assembly, messagesList, buildOutputDirectory, postProcessFunc); + + postProcessorTask.Poll(); + OnPostProcessingStarted?.Invoke(assembly); - processedAssemblies.Add(assembly, messagesList.ToArray()); + postProcessorTasks.Add(postProcessorTask); + } + catch (IOException e) + { + UnityEngine.Debug.LogError($"Fail to copy {sourcePath} to {assembly.FullPath} before post processing the assembly. Skipping post processing.\n{e}"); + // OnCompilationFinished callbacks might add more compiler messages + OnCompilationFinished?.Invoke(assembly, messagesList); + processedAssemblies.Add(assembly, messagesList.ToArray()); + } + } + else + { + // OnCompilationFinished callbacks might add more compiler messages + OnCompilationFinished?.Invoke(assembly, messagesList); + processedAssemblies.Add(assembly, messagesList.ToArray()); + } if (!CompileErrors) CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); @@ -169,6 +202,44 @@ public bool Poll() compiler.Dispose(); } + HashSet finishedPostProcessorTasks = null; + + foreach (var postProcessorTask in postProcessorTasks) + { + // We break out of this loop instead to continuing to ensure that + // OnCompilationFinished events are emitted in the same order as + // they finished compiling. + + if (!postProcessorTask.Poll()) + break; + + // Do not copy the post processed assembly in OnCompilationFinished + // if any of the running compilers have a reference to the assembly. + // As we might copy it while the compiler has the assembly open. + if (AnyRunningCompilerHasReference(postProcessorTask.Assembly)) + break; + + var messagesList = postProcessorTask.CompilerMessages; + + // OnCompilationFinished callbacks might add more compiler messages + OnCompilationFinished?.Invoke(postProcessorTask.Assembly, messagesList); + processedAssemblies.Add(postProcessorTask.Assembly, messagesList.ToArray()); + + if (!CompileErrors) + CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); + + if (finishedPostProcessorTasks == null) + finishedPostProcessorTasks = new HashSet(); + + finishedPostProcessorTasks.Add(postProcessorTask); + } + + if (finishedPostProcessorTasks != null) + foreach (var finishedPostProcessorTask in finishedPostProcessorTasks) + { + postProcessorTasks.Remove(finishedPostProcessorTask); + } + // If StopOnFirstError is set, do not queue assemblies for compilation in case of compile errors. bool stopOnFirstError = (compilationTaskOptions & CompilationTaskOptions.StopOnFirstError) == CompilationTaskOptions.StopOnFirstError; @@ -176,28 +247,53 @@ public bool Poll() { pendingAssemblies.Clear(); - bool finishedRunningCompilerTasks = (compilerTasks.Count == 0); - - if (finishedRunningCompilerTasks) + if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } - return finishedRunningCompilerTasks; + return FinishedCompilation; } // Queue pending assemblies for compilation if we have no running compilers or if compilers have finished. if (compilerTasks.Count == 0 || (finishedCompilerTasks != null && finishedCompilerTasks.Count > 0)) QueuePendingAssemblies(); - bool finishedCompilation = (pendingAssemblies.Count == 0 && compilerTasks.Count == 0); - - if (finishedCompilation) + if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } - return finishedCompilation; + return FinishedCompilation; + } + + bool RunPostProcessors + { + get + { + return (compilationTaskOptions & CompilationTaskOptions.RunPostProcessors) > 0; + } + } + + bool FinishedCompilation + { + get + { + return pendingAssemblies.Count == 0 && compilerTasks.Count == 0 && postProcessorTasks.Count == 0; + } + } + + bool AnyRunningCompilerHasReference(ScriptAssembly assembly) + { + foreach (var compilerTask in compilerTasks) + { + var compilerAssembly = compilerTask.Key; + + if (compilerAssembly.ScriptAssemblyReferences.Contains(assembly)) + return true; + } + + return false; } void QueuePendingAssemblies() @@ -217,7 +313,7 @@ void QueuePendingAssemblies() { CompilerMessage[] messages; - if (!processedAssemblies.TryGetValue(reference, out messages)) + if (!compiledAssemblies.TryGetValue(reference, out messages)) { // If a reference is not compiling and not pending // also remove this assembly from pending. @@ -271,7 +367,7 @@ void QueuePendingAssemblies() // No assemblies to compile, need to wait for more references to finish compiling. if (assemblyCompileQueue == null) { - if (compilerTasks.Count() == 0) + if (compilerTasks.Count == 0) throw new Exception("No pending assemblies queued for compilation and no compilers running. Compilation will never finish."); return; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs index 09b6224f83..55d8de9719 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/CustomScriptAssembly.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using UnityEditor.Compilation; using UnityEditor; @@ -136,7 +137,7 @@ static void UpdateRenamedReferences(CustomScriptAssemblyData data) additionalReferences.Add(newReference); } - if (additionalReferences != null && additionalReferences.Count() > 0) + if (additionalReferences != null && additionalReferences.Count > 0) { for (int i = 0; i < data.references.Length; ++i) { @@ -146,7 +147,7 @@ static void UpdateRenamedReferences(CustomScriptAssemblyData data) additionalReferences.Remove(reference); } - if (additionalReferences.Count() > 0) + if (additionalReferences.Count > 0) data.references = data.references.Concat(additionalReferences).ToArray(); } } @@ -202,6 +203,7 @@ public CustomScriptAssemblyPlatform(string name, BuildTarget buildTarget) : this } } + [DebuggerDisplay("{Name}")] class CustomScriptAssembly { public string FilePath { get; set; } diff --git a/Editor/Mono/Scripting/ScriptCompilation/DefineConstraintsHelper.cs b/Editor/Mono/Scripting/ScriptCompilation/DefineConstraintsHelper.cs index 5af84d5a28..0224e170c8 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/DefineConstraintsHelper.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/DefineConstraintsHelper.cs @@ -5,15 +5,19 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; using UnityEngine.Scripting; namespace UnityEditor.Scripting.ScriptCompilation { - internal static class DefineConstraintsHelper + static class DefineConstraintsHelper { public const string Not = "!"; public const string Or = "||"; + public static readonly char[] k_ValidWhitespaces = { ' ', '\t' }; + public static readonly char[] k_Whitespaces = { ' ', '\t', '\r', '\n' }; + [RequiredByNativeCode] public static bool IsDefineConstraintsCompatible(string[] defines, string[] defineConstraints) { @@ -40,10 +44,26 @@ static void GetDefineConstraintsValidity(string[] defines, string[] defineConstr internal static bool IsDefineConstraintValid(string[] defines, string defineConstraints) { - var splitDefines = new HashSet(defineConstraints.Split(new[] { Or }, StringSplitOptions.RemoveEmptyEntries)); + // Split by "||" (OR) and keep it in the resulting array + var splitDefines = Regex.Split(defineConstraints, "(\\|\\|)"); + + // Trim what we consider valid space characters + for (var i = 0; i < splitDefines.Length; ++i) + { + splitDefines[i] = splitDefines[i].Trim(k_ValidWhitespaces); + } + + // Check for consecutive Or + for (var i = 0; i < splitDefines.Length; ++i) + { + if (splitDefines[i] == Or && (i < splitDefines.Length - 1 && splitDefines[i + 1] == Or)) + { + return false; + } + } - var notExpectedDefines = new HashSet(splitDefines.Where(x => x.StartsWith(Not)).Select(x => x.Substring(1))); - var expectedDefines = new HashSet(splitDefines.Where(x => !x.StartsWith(Not))); + var notExpectedDefines = new HashSet(splitDefines.Where(x => x.StartsWith(Not.ToString()) && x != Or).Select(x => x.Substring(1))); + var expectedDefines = new HashSet(splitDefines.Where(x => !x.StartsWith(Not.ToString()) && x != Or)); if (defines == null) { @@ -51,9 +71,26 @@ internal static bool IsDefineConstraintValid(string[] defines, string defineCons { return false; } + return true; } + foreach (var define in expectedDefines) + { + if (!IsTokenValid(define)) + { + return false; + } + } + + foreach (var define in notExpectedDefines) + { + if (!IsTokenValid(define)) + { + return false; + } + } + if (expectedDefines.Overlaps(notExpectedDefines)) { var complement = new HashSet(expectedDefines); @@ -73,5 +110,20 @@ internal static bool IsDefineConstraintValid(string[] defines, string defineCons return expectedDefines.Any(defines.Contains) || !notExpectedDefines.Any(defines.Contains); } + + static bool IsTokenValid(string token) + { + if (string.IsNullOrEmpty(token)) + { + return false; + } + + if (k_Whitespaces.Any(token.Contains)) + { + return false; + } + + return true; + } } } diff --git a/Runtime/Export/iOS/OnDemandResources.bindings.cs b/Editor/Mono/Scripting/ScriptCompilation/DirtySource.cs similarity index 51% rename from Runtime/Export/iOS/OnDemandResources.bindings.cs rename to Editor/Mono/Scripting/ScriptCompilation/DirtySource.cs index 79b789f004..69d01b4854 100644 --- a/Runtime/Export/iOS/OnDemandResources.bindings.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/DirtySource.cs @@ -3,10 +3,15 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; -using System.Runtime.InteropServices; using UnityEngine.Bindings; -using UsedByNativeCodeAttribute = UnityEngine.Scripting.UsedByNativeCodeAttribute; -namespace UnityEngine.iOS +namespace UnityEditor.Scripting.ScriptCompilation { + internal enum DirtySource + { + None = 0, + DirtyScript = 1, + DirtyAssembly = 2, + DirtyReference = 3, + } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs index f779f65259..b9e7b43f83 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorBuildRules.cs @@ -333,10 +333,10 @@ public static ScriptAssembly[] GetAllScriptAssemblies(Dictionary String projectDirectory, ScriptAssemblySettings settings, CompilationAssemblies assemblies, HashSet runUpdaterAssemblies, TargetAssemblyType onlyIncludeType = TargetAssemblyType.Undefined) { - if (allSourceFiles == null || allSourceFiles.Count() == 0) + if (allSourceFiles == null || allSourceFiles.Count == 0) return new ScriptAssembly[0]; - var targetAssemblyFiles = new Dictionary>(); + var targetAssemblyFiles = new Dictionary(); foreach (var entry in allSourceFiles) { @@ -360,39 +360,39 @@ public static ScriptAssembly[] GetAllScriptAssemblies(Dictionary if (targetAssembly.Language == null && targetAssembly.Type == TargetAssemblyType.Custom) targetAssembly.Language = scriptLanguage; - HashSet assemblySourceFiles; + DirtyTargetAssembly dirtyTargetAssembly; - if (!targetAssemblyFiles.TryGetValue(targetAssembly, out assemblySourceFiles)) + if (!targetAssemblyFiles.TryGetValue(targetAssembly, out dirtyTargetAssembly)) { - assemblySourceFiles = new HashSet(); - targetAssemblyFiles[targetAssembly] = assemblySourceFiles; + dirtyTargetAssembly = new DirtyTargetAssembly(DirtySource.None); + targetAssemblyFiles[targetAssembly] = dirtyTargetAssembly; } - assemblySourceFiles.Add(AssetPath.Combine(projectDirectory, scriptFile)); + dirtyTargetAssembly.SourceFiles.Add(AssetPath.Combine(projectDirectory, scriptFile)); } - return ToScriptAssemblies(targetAssemblyFiles, settings, assemblies, runUpdaterAssemblies).ScriptAssemblies; + return ToScriptAssemblies(targetAssemblyFiles, settings, assemblies, runUpdaterAssemblies); } - public class ScriptAssembliesResult + internal class DirtyTargetAssembly { - public ScriptAssembliesResult(ScriptAssembly[] scriptAssemblies, bool pendingCodeGenAssembly) + public DirtyTargetAssembly(DirtySource dirtySource) { - ScriptAssemblies = scriptAssemblies; - PendingCodeGenAssembly = pendingCodeGenAssembly; + SourceFiles = new HashSet(); + DirtySource = dirtySource; } - public bool PendingCodeGenAssembly { get; private set; } - public ScriptAssembly[] ScriptAssemblies { get; private set; } + public HashSet SourceFiles { get; set; } + public DirtySource DirtySource { get; set; } } - public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateChangedScriptAssembliesArgs args) + public static ScriptAssembly[] GenerateChangedScriptAssemblies(GenerateChangedScriptAssembliesArgs args) { - var dirtyTargetAssemblies = new Dictionary>(); + var dirtyTargetAssemblies = new Dictionary(); // Add initial dirty target assemblies foreach (var dirtyTargetAssembly in args.DirtyTargetAssemblies) - dirtyTargetAssemblies[dirtyTargetAssembly] = new HashSet(); + dirtyTargetAssemblies[dirtyTargetAssembly] = new DirtyTargetAssembly(DirtySource.DirtyAssembly); // Dirty custom script assemblies that have explicit references to // explicitly referenced dirty precompiled assemblies. @@ -407,7 +407,8 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha var customTargetAssembly = entry.Value; if (customTargetAssembly.PrecompiledReferences.Contains(dirtyPrecompiledAssembly)) { - dirtyTargetAssemblies[customTargetAssembly] = new HashSet(); + dirtyTargetAssemblies[customTargetAssembly] = new DirtyTargetAssembly(DirtySource.DirtyReference); + break; } } @@ -423,7 +424,7 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha foreach (var assemblyFilename in args.RunUpdaterAssemblies) { var targetAssembly = allTargetAssemblies.First(a => a.Filename == assemblyFilename); - dirtyTargetAssemblies[targetAssembly] = new HashSet(); + dirtyTargetAssemblies[targetAssembly] = new DirtyTargetAssembly(DirtySource.DirtyAssembly); } // Collect all dirty TargetAssemblies @@ -442,7 +443,7 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha if (!IsCompatibleWithPlatformAndDefines(targetAssembly, args.Settings)) continue; - HashSet assemblySourceFiles; + DirtyTargetAssembly dirtyTargetAssembly; var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(dirtySourceFile); SupportedLanguage scriptLanguage = null; @@ -459,16 +460,16 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha continue; } - if (!dirtyTargetAssemblies.TryGetValue(targetAssembly, out assemblySourceFiles)) + if (!dirtyTargetAssemblies.TryGetValue(targetAssembly, out dirtyTargetAssembly)) { - assemblySourceFiles = new HashSet(); - dirtyTargetAssemblies[targetAssembly] = assemblySourceFiles; + dirtyTargetAssembly = new DirtyTargetAssembly(DirtySource.DirtyScript); + dirtyTargetAssemblies[targetAssembly] = dirtyTargetAssembly; if (targetAssembly.Type == TargetAssemblyType.Custom) targetAssembly.Language = scriptLanguage; } - assemblySourceFiles.Add(AssetPath.Combine(args.ProjectDirectory, dirtySourceFile)); + dirtyTargetAssembly.SourceFiles.Add(AssetPath.Combine(args.ProjectDirectory, dirtySourceFile)); if (targetAssembly.Language == null && targetAssembly.Type == TargetAssemblyType.Custom) targetAssembly.Language = scriptLanguage; @@ -496,13 +497,13 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha continue; if (!dirtyTargetAssemblies.ContainsKey(assembly)) - dirtyTargetAssemblies[assembly] = new HashSet(); + dirtyTargetAssemblies[assembly] = new DirtyTargetAssembly(DirtySource.DirtyReference); } } // Return empty array in case of no dirty target assemblies if (dirtyTargetAssemblies.Count == 0) - return new ScriptAssembliesResult(new ScriptAssembly[0], false); + return new ScriptAssembly[0]; // Collect any TargetAssemblies that reference the dirty TargetAssemblies, as they will also be dirty. int dirtyAssemblyCount; @@ -523,7 +524,7 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha foreach (var reference in assembly.References) if (dirtyTargetAssemblies.ContainsKey(reference)) { - dirtyTargetAssemblies[assembly] = new HashSet(); + dirtyTargetAssemblies[assembly] = new DirtyTargetAssembly(DirtySource.DirtyReference); dirtyAssemblyCount++; break; } @@ -547,7 +548,7 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha if (!IsCompatibleWithPlatformAndDefines(targetAssembly, args.Settings)) continue; - HashSet assemblySourceFiles; + DirtyTargetAssembly dirtyTargetAssembly; var scriptExtension = ScriptCompilers.GetExtensionOfSourceFile(sourceFile); var scriptLanguage = ScriptCompilers.GetLanguageFromExtension(scriptExtension); @@ -559,8 +560,8 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha if (scriptLanguage != targetAssembly.Language) args.NotCompiledTargetAssemblies.Add(targetAssembly); - if (dirtyTargetAssemblies.TryGetValue(targetAssembly, out assemblySourceFiles)) - assemblySourceFiles.Add(AssetPath.Combine(args.ProjectDirectory, sourceFile)); + if (dirtyTargetAssemblies.TryGetValue(targetAssembly, out dirtyTargetAssembly)) + dirtyTargetAssembly.SourceFiles.Add(AssetPath.Combine(args.ProjectDirectory, sourceFile)); } // Remove any target assemblies which have no source files associated with them. @@ -568,7 +569,7 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha foreach (var entry in dirtyTargetAssemblies) { - if (entry.Value.Count == 0 && entry.Key.Type == TargetAssemblyType.Custom) + if (entry.Value.SourceFiles.Count == 0 && entry.Key.Type == TargetAssemblyType.Custom) { noScriptsCustomTargetAssemblies.Add(entry.Key); } @@ -576,7 +577,7 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha args.NoScriptsCustomTargetAssemblies = noScriptsCustomTargetAssemblies.ToArray(); - dirtyTargetAssemblies = dirtyTargetAssemblies.Where(e => e.Value.Count > 0).ToDictionary(e => e.Key, e => e.Value); + dirtyTargetAssemblies = dirtyTargetAssemblies.Where(e => e.Value.SourceFiles.Count > 0).ToDictionary(e => e.Key, e => e.Value); // Remove any target assemblies which have been marked as do not compile. foreach (var removeAssembly in args.NotCompiledTargetAssemblies) @@ -587,7 +588,7 @@ public static ScriptAssembliesResult GenerateChangedScriptAssemblies(GenerateCha return scriptAssemblies; } - internal static ScriptAssembliesResult ToScriptAssemblies(IDictionary> targetAssemblies, ScriptAssemblySettings settings, + internal static ScriptAssembly[] ToScriptAssemblies(IDictionary targetAssemblies, ScriptAssemblySettings settings, CompilationAssemblies assemblies, HashSet runUpdaterAssemblies) { var scriptAssemblies = new ScriptAssembly[targetAssemblies.Count]; @@ -599,7 +600,7 @@ internal static ScriptAssembliesResult ToScriptAssemblies(IDictionary ScriptAssembly mapping for converting references @@ -612,6 +613,7 @@ internal static ScriptAssembliesResult ToScriptAssemblies(IDictionary IsCompatibleWithEditor(settings), - scriptCompilerOptions) - { - }; + scriptCompilerOptions); var editor = new TargetAssembly("Assembly-" + languageName + "-Editor" + ".dll", language, @@ -954,9 +952,7 @@ internal static TargetAssembly[] CreatePredefinedTargetAssemblies() null, FilterAssemblyInEditorFolder, (settings, defines) => IsCompatibleWithEditor(settings), - scriptCompilerOptions) - { - }; + scriptCompilerOptions); runtimeFirstPassAssemblies.Add(runtimeFirstPass); runtimeAssemblies.Add(runtime); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs index 985432b05a..17345eee36 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilation.cs @@ -4,17 +4,15 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; -using Unity.CompilationPipeline.Common.Diagnostics; -using Unity.CompilationPipeline.Common.ILPostProcessing; using UnityEditor.Compilation; using UnityEditor.Modules; using UnityEditor.Scripting.Compilers; using UnityEditorInternal; -using UnityEngine; using UnityEngine.Profiling; using CompilerMessage = UnityEditor.Scripting.Compilers.CompilerMessage; using CompilerMessageType = UnityEditor.Scripting.Compilers.CompilerMessageType; @@ -153,6 +151,7 @@ public override void PostprocessMessage(ref CompilerMessage message) } } + Dictionary stopWatchDict = new Dictionary(); bool areAllScriptsDirty; bool areAllPrecompiledAssembliesDirty; string projectDirectory = string.Empty; @@ -188,6 +187,8 @@ public override void PostprocessMessage(ref CompilerMessage message) public bool IsCodeGenAssemblyChanged { get; set; } + public ILPostProcessing ILPostProcessing = new ILPostProcessing(); + static EditorCompilation() {} public void Initialize() @@ -195,6 +196,8 @@ public void Initialize() // Initialize maxConcurrentCompilers if it hasn't been set already. if (maxConcurrentCompilers == 0) SetMaxConcurrentCompilers(UnityEngine.SystemInfo.processorCount); + + ILPostProcessing.ILPostProcessors = ILPostProcessing.FindAllPostProcessors(); } public void SetMaxConcurrentCompilers(int maxCompilers) @@ -222,6 +225,7 @@ internal void SetAssetPathsMetaData(AssetPathMetaData[] assetPathMetaDatas) .SelectMany(x => x.VersionMetaDatas ?? new AssetPathVersionMetaData[0]) .Distinct(assetPathVersionMetaDataComparer) .ToDictionary(x => x.Name, x => x.Version); + UpdateCustomTargetAssembliesAssetPathsMetaData(customScriptAssemblies, assetPathMetaDatas, forceUpdate: true); } internal AssetPathMetaData[] GetAssetPathsMetaData() @@ -277,13 +281,60 @@ public void DirtyAllScripts() areAllScriptsDirty = true; } - public void DirtyAllNonCodeGenAssemblies() + public class ILPostProcessCompiledTargetAssembly : ILPostProcessCompiledAssembly { - foreach (KeyValuePair customTargetAssembly in customTargetAssemblies) + public EditorBuildRules.TargetAssembly TargetAssembly { get; private set; } + + public ILPostProcessCompiledTargetAssembly(EditorBuildRules.TargetAssembly targetAssembly, string outputPath) + : base(targetAssembly, outputPath) + { + TargetAssembly = targetAssembly; + } + } + + public void DirtyAllNonCodeGenAssemblies(EditorScriptCompilationOptions additionalOptions) + { + var ilPostProcessors = ILPostProcessing.ILPostProcessors; + + if (ilPostProcessors.Length == 0) + { + return; + } + + var scriptAssemblySettings = CreateEditorScriptAssemblySettings(EditorScriptCompilationOptions.BuildingForEditor | additionalOptions); + + var allTargetAssemblies = new Dictionary(customTargetAssemblies); + + foreach (var predefinedTargetAssembly in EditorBuildRules.GetPredefinedTargetAssemblies()) { - if (!UnityCodeGenHelpers.IsCodeGen(customTargetAssembly.Key)) + allTargetAssemblies.Add(predefinedTargetAssembly.Filename, predefinedTargetAssembly); + } + + var ilCompiledAssemblies = new List(customScriptAssemblies.Length); + + foreach (var entry in allTargetAssemblies) + { + var targetAssembly = entry.Value; + + if (UnityCodeGenHelpers.IsCodeGen(targetAssembly.Filename)) + continue; + + if (dirtyTargetAssemblies.Contains(targetAssembly)) + continue; + + var compiledAssembly = new ILPostProcessCompiledTargetAssembly(targetAssembly, outputDirectory); + ilCompiledAssemblies.Add(compiledAssembly); + } + + foreach (var ilCompiledAssembly in ilCompiledAssemblies) + { + foreach (var ilPostProcessor in ilPostProcessors) { - dirtyTargetAssemblies.Add(customTargetAssembly.Value); + if (!ilPostProcessor.WillProcess(ilCompiledAssembly)) + continue; + + dirtyTargetAssemblies.Add(ilCompiledAssembly.TargetAssembly); + break; } } } @@ -552,7 +603,7 @@ public TargetAssemblyInfo[] GetAllCompiledAndResolvedCustomTargetAssemblies(Edit while (removed); var count = customTargetAssemblyCompiledPaths.Count; - var targetAssemblies = new TargetAssemblyInfo[customTargetAssemblyCompiledPaths.Count]; + var targetAssemblies = new TargetAssemblyInfo[count]; int index = 0; foreach (var entry in customTargetAssemblyCompiledPaths) @@ -711,7 +762,7 @@ public static Exception[] UpdateCustomScriptAssemblies(CustomScriptAssembly[] cu AssetPathMetaData[] assetPathsMetaData) { var asmrefLookup = customScriptAssemblyReferences.ToLookup(x => x.Reference); - var exceptions = new List(); + // Add AdditionalPrefixes foreach (var assembly in customScriptAssemblies) @@ -722,49 +773,60 @@ public static Exception[] UpdateCustomScriptAssemblies(CustomScriptAssembly[] cu assembly.AdditionalPrefixes = foundAsmRefs.Any() ? foundAsmRefs.Select(ar => ar.PathPrefix).ToArray() : null; } - // Add AssetPathMetaData - if (assetPathsMetaData != null) + var exceptions = UpdateCustomTargetAssembliesAssetPathsMetaData(customScriptAssemblies, assetPathsMetaData); + return exceptions.ToArray(); + } + + static Exception[] UpdateCustomTargetAssembliesAssetPathsMetaData(CustomScriptAssembly[] customScriptAssemblies, + AssetPathMetaData[] assetPathsMetaData, bool forceUpdate = false) + { + if (assetPathsMetaData == null) { - var assetMetaDataPaths = new string[assetPathsMetaData.Length]; - var lowerAssetMetaDataPaths = new string[assetPathsMetaData.Length]; + return new Exception[0]; + } + + var exceptions = new List(); + var assetMetaDataPaths = new string[assetPathsMetaData.Length]; + var lowerAssetMetaDataPaths = new string[assetPathsMetaData.Length]; - for (int i = 0; i < assetPathsMetaData.Length; ++i) + for (int i = 0; i < assetPathsMetaData.Length; ++i) + { + var assetPathMetaData = assetPathsMetaData[i]; + assetMetaDataPaths[i] = AssetPath.ReplaceSeparators(assetPathMetaData.DirectoryPath + AssetPath.Separator); + lowerAssetMetaDataPaths[i] = Utility.FastToLower(assetMetaDataPaths[i]); + } + + foreach (var assembly in customScriptAssemblies) + { + if (assembly.AssetPathMetaData != null && !forceUpdate) { - var assetPathMetaData = assetPathsMetaData[i]; - assetMetaDataPaths[i] = AssetPath.ReplaceSeparators(assetPathMetaData.DirectoryPath + AssetPath.Separator); - lowerAssetMetaDataPaths[i] = Utility.FastToLower(assetMetaDataPaths[i]); + continue; } - foreach (var assembly in customScriptAssemblies) + try { - try + for (int i = 0; i < assetMetaDataPaths.Length; ++i) { - if (assembly.AssetPathMetaData == null) + var path = assetMetaDataPaths[i]; + var lowerPath = lowerAssetMetaDataPaths[i]; + + if (Utility.FastStartsWith(assembly.PathPrefix, path, lowerPath)) { - for (int i = 0; i < assetMetaDataPaths.Length; ++i) - { - var path = assetMetaDataPaths[i]; - var lowerPath = lowerAssetMetaDataPaths[i]; - - if (Utility.FastStartsWith(assembly.PathPrefix, path, lowerPath)) - { - assembly.AssetPathMetaData = assetPathsMetaData[i]; - break; - } - } + assembly.AssetPathMetaData = assetPathsMetaData[i]; + break; } } - catch (Exception e) - { - exceptions.Add(e); - } + } + catch (Exception e) + { + exceptions.Add(e); } } return exceptions.ToArray(); } - Exception[] UpdateCustomTargetAssemblies() + Exception[] UpdateCustomTargetAssemblies(bool forceUpdateAssetMetadata = false) { var exceptions = UpdateCustomScriptAssemblies(customScriptAssemblies, customScriptAssemblyReferences, m_AssetPathsMetaData); @@ -939,7 +1001,7 @@ public Exception[] SetAllCustomScriptAssemblyJsonContents(string[] paths, string HashSet predefinedAssemblyNames = null; // To check if a path prefix is already being used we use a Dictionary where the key is the prefix and the value is the file path. - var prefixToFilePathLookup = customScriptAssemblyReferences.ToDictionary(x => x.PathPrefix, x => new List(){ x.FilePath }, StringComparer.OrdinalIgnoreCase); + var prefixToFilePathLookup = customScriptAssemblyReferences.ToDictionary(x => x.PathPrefix, x => new List() { x.FilePath }, StringComparer.OrdinalIgnoreCase); ClearCompilationSetupErrorFlags(CompilationSetupErrorFlags.loadError); @@ -1386,8 +1448,7 @@ internal CompileStatus CompileScripts(ScriptAssemblySettings scriptAssemblySetti RunUpdaterAssemblies = runScriptUpdaterAssemblies }; - EditorBuildRules.ScriptAssembliesResult changedScriptAssemblies = EditorBuildRules.GenerateChangedScriptAssemblies(args); - ScriptAssembly[] scriptAssemblies = changedScriptAssemblies.ScriptAssemblies; + ScriptAssembly[] scriptAssemblies = EditorBuildRules.GenerateChangedScriptAssemblies(args); foreach (var customTargetAssembly in args.NoScriptsCustomTargetAssemblies) { @@ -1424,7 +1485,7 @@ internal CompileStatus CompileScripts(ScriptAssemblySettings scriptAssemblySetti if (!scriptAssemblies.Any()) return CompileStatus.Idle; - bool compiling = CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.StopOnFirstError, CompileScriptAssembliesOptions.none, changedScriptAssemblies.PendingCodeGenAssembly); + bool compiling = CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.StopOnFirstError, CompileScriptAssembliesOptions.none); return compiling ? CompileStatus.CompilationStarted : CompileStatus.Idle; } @@ -1440,16 +1501,7 @@ internal bool CompileCustomScriptAssemblies(ScriptAssemblySettings scriptAssembl DeleteUnusedAssemblies(); var scriptAssemblies = GetAllScriptAssembliesOfType(scriptAssemblySettings, EditorBuildRules.TargetAssemblyType.Custom); - bool hasPreprocessor = false; - foreach (var scriptAssembly in scriptAssemblies) - { - if (UnityCodeGenHelpers.IsCodeGen(scriptAssembly.Filename)) - { - hasPreprocessor = true; - } - } - - return CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.None, CompileScriptAssembliesOptions.skipSetupChecks, hasPreprocessor); + return CompileScriptAssemblies(scriptAssemblies, scriptAssemblySettings, tempBuildDirectory, options, CompilationTaskOptions.None, CompileScriptAssembliesOptions.skipSetupChecks); } internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, @@ -1457,8 +1509,7 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, string tempBuildDirectory, EditorScriptCompilationOptions options, CompilationTaskOptions compilationTaskOptions, - CompileScriptAssembliesOptions compileScriptAssembliesOptions, - bool pendingCodeGenAssembly = false) + CompileScriptAssembliesOptions compileScriptAssembliesOptions) { StopAllCompilation(); @@ -1482,21 +1533,53 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, if (!Directory.Exists(tempBuildDirectory)) Directory.CreateDirectory(tempBuildDirectory); - var allTargetAssemblies = new Dictionary(customTargetAssemblies); - foreach (var predefinedTargetAssembly in EditorBuildRules.GetPredefinedTargetAssemblies()) + // CodeGen/ILPostProcessor + var scriptCodegenAssemblies = UnityCodeGenHelpers.ToScriptCodeGenAssemblies(scriptAssemblies); + var pendingCodeGenAssembly = scriptCodegenAssemblies.CodeGenAssemblies.Any(); + + // Do compile codegen assemblies that were scheduled for compilation + // because one of it's references changed. Only compile them when + // their source files are modified or the compilation is forced. + if (pendingCodeGenAssembly) { - allTargetAssemblies.Add(predefinedTargetAssembly.Filename, predefinedTargetAssembly); + var newScriptAssemblies = new List(scriptCodegenAssemblies.ScriptAssemblies); + + foreach (var codegenAssembly in scriptCodegenAssemblies.CodeGenAssemblies) + { + if (codegenAssembly.DirtySource == DirtySource.DirtyReference) + continue; + + newScriptAssemblies.Add(codegenAssembly); + } + + pendingCodeGenAssembly = newScriptAssemblies.Count > scriptCodegenAssemblies.ScriptAssemblies.Count; + scriptAssemblies = newScriptAssemblies.ToArray(); } - var findReferences = new FindReferences(allTargetAssemblies, scriptAssemblySettings); - var fullPathToTempOutputFolder = Path.GetFullPath(tempBuildDirectory); - ILPostProcessor[] ilPostProcessors = null; + // If we are not compiling any codegen assemblies and there are post processors, + // then run them after finishing compiling each assembly in + // MicrosoftCSharpCompilerWithPostProcessing.Poll() + if (!pendingCodeGenAssembly && ILPostProcessing.HasPostProcessors) + { + compilationTaskOptions |= CompilationTaskOptions.RunPostProcessors; + } // Compile to tempBuildDirectory - compilationTask = new CompilationTask(scriptAssemblies, tempBuildDirectory, "Editor Compilation", options, compilationTaskOptions, maxConcurrentCompilers); + compilationTask = new CompilationTask(scriptAssemblies, + tempBuildDirectory, + "Editor Compilation", + options, + compilationTaskOptions, + maxConcurrentCompilers, + ILPostProcessing.PostProcess); compilationTask.OnCompilationTaskStarted += (context) => { + Console.WriteLine("- Starting script compilation"); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + stopWatchDict[context] = stopwatch; + InvokeCompilationStarted(context); }; @@ -1506,7 +1589,14 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, { IsCodeGenAssemblyChanged = pendingCodeGenAssembly; } + InvokeCompilationFinished(context); + + var stopwatch = stopWatchDict[context]; + var elapsed = stopwatch.Elapsed; + stopWatchDict.Remove(context); + + Console.WriteLine($"- Finished script compilation in {elapsed.TotalSeconds:0.######} seconds"); }; compilationTask.OnBeforeCompilationStarted += (assembly, phase) => @@ -1516,9 +1606,12 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, compilationTask.OnCompilationStarted += (assembly, phase) => { + var stopwatch = new Stopwatch(); + stopwatch.Start(); var assemblyOutputPath = AssetPath.Combine(scriptAssemblySettings.OutputDirectory, assembly.Filename); Console.WriteLine("- Starting compile {0}", assemblyOutputPath); InvokeAssemblyCompilationStarted(assemblyOutputPath); + stopWatchDict[assemblyOutputPath] = stopwatch; }; compilationTask.OnCompilationFinished += (assembly, messages) => @@ -1528,46 +1621,7 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, var assemblyOutputPath = AssetPath.Combine(scriptAssemblySettings.OutputDirectory, assembly.Filename); var hasCompileError = messages.Any(m => m.type == CompilerMessageType.Error); - if (!pendingCodeGenAssembly && !hasCompileError) - { - if (ilPostProcessors == null) - { - ilPostProcessors = FindAllPostProcessors(); - } - - if (!UnityCodeGenHelpers.IsCodeGen(assembly.Filename)) - { - try - { - List diagnostics = RunILPostProcessors(ilPostProcessors, assembly, fullPathToTempOutputFolder, findReferences); - foreach (var message in diagnostics) - { - if (message.DiagnosticType == DiagnosticType.Error) - { - hasCompileError = true; - } - messages.Add(new CompilerMessage - { - assemblyName = message.File, - message = message.MessageData, - type = message.DiagnosticType == DiagnosticType.Error ? CompilerMessageType.Error : CompilerMessageType.Warning, - }); - } - } - catch (Exception exception) - { - messages.Add(new CompilerMessage - { - assemblyName = assembly.Filename, - message = $"Something went wrong while Post Processing the assembly ({assembly.Filename}) : {Environment.NewLine} {exception.Message} {Environment.NewLine}{exception.StackTrace}", - type = CompilerMessageType.Error, - }); - hasCompileError = true; - } - } - } - Console.WriteLine("- Finished compile {0}", assemblyOutputPath); changedAssemblies.Add(assembly.Filename); if (runScriptUpdaterAssemblies.Contains(assembly.Filename)) @@ -1591,73 +1645,24 @@ internal bool CompileScriptAssemblies(ScriptAssembly[] scriptAssemblies, } InvokeAssemblyCompilationFinished(assemblyOutputPath, messages); - }; - - compilationTask.Poll(); - return true; - } - static ILPostProcessor[] FindAllPostProcessors() - { - TypeCache.TypeCollection typesDerivedFrom = TypeCache.GetTypesDerivedFrom(); - ILPostProcessor[] ilPostProcessors = new ILPostProcessor[typesDerivedFrom.Count]; + Stopwatch stopwatch = null; - for (int i = 0; i < typesDerivedFrom.Count; i++) - { try { - ilPostProcessors[i] = (ILPostProcessor)Activator.CreateInstance(typesDerivedFrom[i]); - } - catch (Exception exception) - { - Console.WriteLine($"Could not create ILPostProcessor ({typesDerivedFrom[i].FullName}):{Environment.NewLine}{exception.StackTrace}"); + stopwatch = stopWatchDict[assemblyOutputPath]; + var elapsed = stopwatch.Elapsed; + Console.WriteLine($"- Finished compile {assemblyOutputPath} in {elapsed.TotalSeconds:0.######} seconds"); + stopWatchDict.Remove(assemblyOutputPath); } - } - - return ilPostProcessors; - } - - static List RunILPostProcessors(ILPostProcessor[] ilPostProcessors, ScriptAssembly assembly, string outputTempPath, FindReferences findReferences) - { - var assemblyPath = Path.Combine(outputTempPath, assembly.Filename); - - var resultMessages = new List(); - if (!File.Exists(assemblyPath)) - { - resultMessages.Add(new DiagnosticMessage - { - File = assemblyPath, - MessageData = $"Could not find {assemblyPath} for post processing", - DiagnosticType = DiagnosticType.Error, - }); - } - - bool isILProcessed = false; - var ilPostProcessCompiledAssembly = new ILPostProcessCompiledAssembly(assembly, outputTempPath, findReferences); - - InMemoryAssembly postProcessedInMemoryAssembly = null; - foreach (var ilPostProcessor in ilPostProcessors) - { - Console.WriteLine($"IL PostProcessor {ilPostProcessor.GetType().Name} processing: {assembly.Filename}"); - var ilPostProcessResult = ilPostProcessor.Process(ilPostProcessCompiledAssembly); - postProcessedInMemoryAssembly = ilPostProcessResult?.InMemoryAssembly; - if (ilPostProcessResult?.InMemoryAssembly != null) + catch (Exception) { - isILProcessed = true; - ilPostProcessCompiledAssembly.InMemoryAssembly = postProcessedInMemoryAssembly; + Console.WriteLine("- Finished compile {0}", assemblyOutputPath); } + }; - if (ilPostProcessResult?.Diagnostics != null) - { - resultMessages.AddRange(ilPostProcessResult.Diagnostics); - } - } - if (isILProcessed) - { - ilPostProcessCompiledAssembly.WriteAssembly(); - } - - return resultMessages; + compilationTask.Poll(); + return true; } static void RunScriptUpdater( @@ -1824,7 +1829,7 @@ public bool IsCompilationPending() // then compilation will trigger on next TickCompilationPipeline. return DoesProjectFolderHaveAnyDirtyScripts() || ArePrecompiledAssembliesDirty() || - runScriptUpdaterAssemblies.Count() > 0 || + runScriptUpdaterAssemblies.Count > 0 || recompileAllScriptsOnNextTick; } @@ -1927,7 +1932,7 @@ public TargetAssemblyInfo[] GetTargetAssemblies() { EditorBuildRules.TargetAssembly[] predefindTargetAssemblies = EditorBuildRules.GetPredefinedTargetAssemblies(); - TargetAssemblyInfo[] targetAssemblyInfo = new TargetAssemblyInfo[predefindTargetAssemblies.Length + (customTargetAssemblies != null ? customTargetAssemblies.Count() : 0)]; + TargetAssemblyInfo[] targetAssemblyInfo = new TargetAssemblyInfo[predefindTargetAssemblies.Length + (customTargetAssemblies != null ? customTargetAssemblies.Count : 0)]; for (int i = 0; i < predefindTargetAssemblies.Length; ++i) targetAssemblyInfo[i] = ToTargetAssemblyInfo(predefindTargetAssemblies[i]); @@ -2116,35 +2121,39 @@ private static void SetTargetAssemblyDefines(EditorBuildRules.TargetAssembly tar for (int i = 0; i < targetAssemblyVersionDefines.Count; i++) { - if (!assetPathVersionMetaDatas.ContainsKey(targetAssemblyVersionDefines[i].name)) + var targetAssemblyVersionDefine = targetAssemblyVersionDefines[i]; + if (!assetPathVersionMetaDatas.ContainsKey(targetAssemblyVersionDefine.name)) { continue; } - if (string.IsNullOrEmpty(targetAssemblyVersionDefines[i].expression)) + if (string.IsNullOrEmpty(targetAssemblyVersionDefine.expression)) { - var define = targetAssemblyVersionDefines[i].define; + var define = targetAssemblyVersionDefine.define; if (!string.IsNullOrEmpty(define)) { defines[populatedVersionDefinesCount] = define; - populatedVersionDefinesCount++; + ++populatedVersionDefinesCount; } continue; } - var versionDefineExpression = semVersionRangesFactory.GetExpression(targetAssemblyVersionDefines[i].expression); - var assetPathVersionMetaData = assetPathVersionMetaDatas[targetAssemblyVersionDefines[i].name]; - var semVersion = SemVersionParser.Parse(assetPathVersionMetaData); - - if (versionDefineExpression.IsValid(semVersion)) + try { - var define = targetAssemblyVersionDefines[i].define; - if (!string.IsNullOrEmpty(define)) + var versionDefineExpression = semVersionRangesFactory.GetExpression(targetAssemblyVersionDefine.expression); + var assetPathVersionMetaData = assetPathVersionMetaDatas[targetAssemblyVersionDefine.name]; + var semVersion = SemVersionParser.Parse(assetPathVersionMetaData); + if (versionDefineExpression.IsValid(semVersion)) { - defines[populatedVersionDefinesCount] = define; - populatedVersionDefinesCount++; + defines[populatedVersionDefinesCount] = targetAssemblyVersionDefine.define; + ++populatedVersionDefinesCount; } } + catch (Exception e) + { + var asset = AssetDatabase.LoadAssetAtPath(EditorCompilationInterface.Instance.FindCustomTargetAssemblyFromTargetAssembly(targetAssembly).FilePath); + UnityEngine.Debug.LogException(e, asset); + } } Array.Resize(ref defines, populatedVersionDefinesCount); diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs index e43b43e120..ded6c3376c 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorCompilationInterface.cs @@ -336,7 +336,8 @@ public static bool ShouldRecompileNonCodeGenAssembliesAfterReload() [RequiredByNativeCode] public static void DirtyAllNonCodeGenAssemblies() { - EmitExceptionAsError(() => Instance.DirtyAllNonCodeGenAssemblies()); + var options = GetAdditionalEditorScriptCompilationOptions(); + EmitExceptionAsError(() => Instance.DirtyAllNonCodeGenAssemblies(options)); } [RequiredByNativeCode] diff --git a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs index c2cc1d0136..bcaba829ca 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/EditorScriptCompilationOptions.cs @@ -19,5 +19,5 @@ enum EditorScriptCompilationOptions BuildingIncludingTestAssemblies = 1 << 5, BuildingPredefinedAssembliesAllowUnsafeCode = (1 << 6), BuildingForHeadlessPlayer = 1 << 7 - }; + } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/FindReferences.cs b/Editor/Mono/Scripting/ScriptCompilation/FindReferences.cs deleted file mode 100644 index 8e35ea3f5c..0000000000 --- a/Editor/Mono/Scripting/ScriptCompilation/FindReferences.cs +++ /dev/null @@ -1,137 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Unity.CompilationPipeline.Common.ILPostProcessing; - -namespace UnityEditor.Scripting.ScriptCompilation -{ - [Flags] - internal enum FindReferencesQueryOptions - { - Direct = 1, - Indirect = 2, - Transitive = Indirect | Direct, - } - - internal class FindReferences - { - readonly Dictionary m_AllTargetAssemblies; - readonly Dictionary m_CompatibleTargetAssemblies = new Dictionary(); - readonly ScriptAssemblySettings m_AssemblySettings; - - readonly Dictionary> m_AssemblyNameReferences = - new Dictionary>(); - - public FindReferences(Dictionary targetAssemblies, - ScriptAssemblySettings assemblySettings) - { - m_AllTargetAssemblies = targetAssemblies; - m_AssemblySettings = assemblySettings; - } - - public HashSet Execute(string assembly, string[] searchReferences, - FindReferencesQueryOptions referencesOptions) - { - if (searchReferences.Length <= 0) - { - return new HashSet(); - } - - var searchQuery = new HashSet(searchReferences); - HashSet result = new HashSet(); - if ((referencesOptions & FindReferencesQueryOptions.Direct) == FindReferencesQueryOptions.Direct) - { - HashSet directResult = AllDirectReferences(m_AllTargetAssemblies[assembly]); - result.UnionWith(directResult); - result.IntersectWith(searchReferences); - } - - if ((referencesOptions & FindReferencesQueryOptions.Indirect) == FindReferencesQueryOptions.Indirect) - { - foreach (var reference in m_AllTargetAssemblies[assembly].References) - { - if (searchQuery.Count <= 0) - { - break; - } - result.UnionWith(FindReferencesRecursive(reference, searchQuery)); - } - } - - return result; - } - - private bool IsCompatibleCached(EditorBuildRules.TargetAssembly targetAssembly) - { - bool isCompatible; - if (m_CompatibleTargetAssemblies.TryGetValue(targetAssembly.Filename, out isCompatible)) - { - return isCompatible; - } - - isCompatible = targetAssembly.IsCompatibleFunc(m_AssemblySettings, targetAssembly.Defines ?? new string[0]); - m_CompatibleTargetAssemblies.Add(targetAssembly.Filename, isCompatible); - return isCompatible; - } - - private HashSet AllDirectReferences(EditorBuildRules.TargetAssembly targetAssembly) - { - HashSet references; - if (m_AssemblyNameReferences.TryGetValue(targetAssembly.Filename, out references)) - { - return references; - } - - references = new HashSet(); - foreach (var targetAssemblyReference in targetAssembly.References) - { - if (IsCompatibleCached(targetAssemblyReference)) - { - references.Add(targetAssemblyReference.Filename); - } - } - - foreach (var assemblyPrecompiledReference in targetAssembly.PrecompiledReferences) - { - var fileName = Path.GetFileName(assemblyPrecompiledReference.Path); - references.Add(fileName); - } - - m_AssemblyNameReferences.Add(targetAssembly.Filename, references); - return references; - } - - private List FindReferencesRecursive(EditorBuildRules.TargetAssembly targetAssembly, - HashSet searchFor) - { - var result = new List(searchFor.Count); - var allDirectReferences = AllDirectReferences(targetAssembly); - allDirectReferences.IntersectWith(searchFor); - result.AddRange(allDirectReferences); - - searchFor.ExceptWith(result); - if (!searchFor.Any()) - { - return result; - } - - foreach (var assemblyReference in targetAssembly.References) - { - if (!searchFor.Any()) - { - continue; - } - - var referenceResult = FindReferencesRecursive(assemblyReference, searchFor); - result.AddRange(referenceResult); - } - - return result; - } - } -} diff --git a/Editor/Mono/Scripting/ScriptCompilation/ILPostProcessCompiledAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/ILPostProcessCompiledAssembly.cs index 42370bb97c..cc7a15e32a 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/ILPostProcessCompiledAssembly.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/ILPostProcessCompiledAssembly.cs @@ -8,22 +8,35 @@ using System.Linq; using Unity.CompilationPipeline.Common.ILPostProcessing; using UnityEditor.Scripting.ScriptCompilation; +using UnityEngine.Profiling; internal class ILPostProcessCompiledAssembly : ICompiledAssembly { - readonly ScriptAssembly m_ScriptAssembly; + readonly string m_AssemblyFilename; readonly string m_OutputPath; - readonly FindReferences m_FindReferences; InMemoryAssembly m_InMemoryAssembly; - public ILPostProcessCompiledAssembly(ScriptAssembly scriptAssembly, string outputPath, FindReferences findReferences) + public ILPostProcessCompiledAssembly(ScriptAssembly scriptAssembly, string outputPath) { - m_ScriptAssembly = scriptAssembly; - Name = Path.GetFileNameWithoutExtension(scriptAssembly.Filename); - References = scriptAssembly.GetAllReferences().Select(Path.GetFileName).ToArray(); + m_AssemblyFilename = scriptAssembly.Filename; + Name = Path.GetFileNameWithoutExtension(m_AssemblyFilename); + References = scriptAssembly.GetAllReferences(); + + m_OutputPath = outputPath; + } + + public ILPostProcessCompiledAssembly(EditorBuildRules.TargetAssembly targetAssembly, string outputPath) + { + m_AssemblyFilename = targetAssembly.Filename; + + Name = Path.GetFileNameWithoutExtension(m_AssemblyFilename); + + var precompiledAssemblyReferences = targetAssembly.PrecompiledReferences.Select(a => a.Path); + var targetAssemblyReferences = targetAssembly.References.Select(a => a.FullPath(outputPath)); + + References = precompiledAssemblyReferences.Concat(targetAssemblyReferences).ToArray(); m_OutputPath = outputPath; - m_FindReferences = findReferences; } private InMemoryAssembly CreateOrGetInMemoryAssembly() @@ -33,9 +46,9 @@ private InMemoryAssembly CreateOrGetInMemoryAssembly() return m_InMemoryAssembly; } - byte[] peData = File.ReadAllBytes(Path.Combine(m_OutputPath, m_ScriptAssembly.Filename)); + byte[] peData = File.ReadAllBytes(Path.Combine(m_OutputPath, m_AssemblyFilename)); - var pdbFileName = Path.GetFileNameWithoutExtension(m_ScriptAssembly.Filename) + ".pdb"; + var pdbFileName = Path.GetFileNameWithoutExtension(m_AssemblyFilename) + ".pdb"; byte[] pdbData = File.ReadAllBytes(Path.Combine(m_OutputPath, pdbFileName)); m_InMemoryAssembly = new InMemoryAssembly(peData, pdbData); @@ -51,52 +64,24 @@ public InMemoryAssembly InMemoryAssembly public string Name { get; set; } public string[] References { get; set; } - public ReferenceQueryResult HasReferences(ReferenceQueryInput input) - { - if (input.References == null) - { - throw new ArgumentNullException(nameof(input.References)); - } - - HashSet result = m_FindReferences.Execute(m_ScriptAssembly.Filename, input.References, (FindReferencesQueryOptions)input.Options); - var found = new bool[input.References.Length]; - var isAllReferencesFound = result.Any(); - for (int i = 0; i < input.References.Length; i++) - { - found[i] = result.Contains(input.References[i]); - isAllReferencesFound &= found[i]; - } - - return new ReferenceQueryResult(found, isAllReferencesFound); - } - - public bool HasReference(string reference, ReferencesQueryOptions options = ReferencesQueryOptions.Direct) - { - if (string.IsNullOrEmpty(reference)) - { - throw new ArgumentException(nameof(reference)); - } - - var hasReferencesResult = HasReferences(new ReferenceQueryInput() - { - References = new string[] { reference }, - Options = options - }); - return hasReferencesResult.HasAllReferences && hasReferencesResult.HasReference.All(x => x); - } - public void WriteAssembly() { + Profiler.BeginSample("ILPostProcessCompiledAssembly.WriteAssembly"); + if (m_InMemoryAssembly == null) { throw new ArgumentException("InMemoryAssembly has never been accessed or modified"); } - var assemblyPath = Path.Combine(m_OutputPath, m_ScriptAssembly.Filename); - var pdbFileName = Path.GetFileNameWithoutExtension(m_ScriptAssembly.Filename) + ".pdb"; + Profiler.BeginSample("ILPostProcessCompiledAssembly.WriteAssembly"); + + var assemblyPath = Path.Combine(m_OutputPath, m_AssemblyFilename); + var pdbFileName = Path.GetFileNameWithoutExtension(m_AssemblyFilename) + ".pdb"; var pdbPath = Path.Combine(m_OutputPath, pdbFileName); File.WriteAllBytes(assemblyPath, InMemoryAssembly.PeData); File.WriteAllBytes(pdbPath, InMemoryAssembly.PdbData); + + Profiler.EndSample(); } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/ILPostProcessing.cs b/Editor/Mono/Scripting/ScriptCompilation/ILPostProcessing.cs new file mode 100644 index 0000000000..ddcf5249d9 --- /dev/null +++ b/Editor/Mono/Scripting/ScriptCompilation/ILPostProcessing.cs @@ -0,0 +1,153 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Unity.CompilationPipeline.Common.Diagnostics; +using Unity.CompilationPipeline.Common.ILPostProcessing; +using UnityEditor.Scripting.Compilers; +using UnityEngine.Profiling; + +namespace UnityEditor.Scripting.ScriptCompilation +{ + internal class ILPostProcessing + { + public ILPostProcessor[] ILPostProcessors { get; set; } + + public bool HasPostProcessors + { + get + { + return ILPostProcessors != null && ILPostProcessors.Length > 0; + } + } + + public List PostProcess(ScriptAssembly assembly, List messages, string outputTempPath) + { + var hasCompileError = messages.Any(m => m.type == CompilerMessageType.Error); + + if (hasCompileError) + return messages; + + if (UnityCodeGenHelpers.IsCodeGen(assembly.Filename)) + return messages; + + if (!HasPostProcessors) + return messages; + + try + { + List diagnostics = RunILPostProcessors(assembly, outputTempPath); + foreach (var message in diagnostics) + { + if (message.DiagnosticType == DiagnosticType.Error) + { + hasCompileError = true; + } + messages.Add(new CompilerMessage + { + assemblyName = message.File, + column = message.Column, + line = message.Line, + message = message.MessageData, + type = message.DiagnosticType == DiagnosticType.Error ? CompilerMessageType.Error : CompilerMessageType.Warning, + }); + } + } + catch (Exception exception) + { + messages.Add(new CompilerMessage + { + assemblyName = assembly.Filename, + message = $"Something went wrong while Post Processing the assembly ({assembly.Filename}) : {Environment.NewLine} {exception.Message} {Environment.NewLine}{exception.StackTrace}", + type = CompilerMessageType.Error, + }); + } + + return messages; + } + + public static ILPostProcessor[] FindAllPostProcessors() + { + TypeCache.TypeCollection typesDerivedFrom = TypeCache.GetTypesDerivedFrom(); + ILPostProcessor[] localILPostProcessors = new ILPostProcessor[typesDerivedFrom.Count]; + + for (int i = 0; i < typesDerivedFrom.Count; i++) + { + try + { + localILPostProcessors[i] = (ILPostProcessor)Activator.CreateInstance(typesDerivedFrom[i]); + } + catch (Exception exception) + { + Console.WriteLine($"Could not create ILPostProcessor ({typesDerivedFrom[i].FullName}):{Environment.NewLine}{exception.StackTrace}"); + } + } + + return localILPostProcessors; + } + + List RunILPostProcessors(ScriptAssembly assembly, string outputTempPath) + { + Profiler.BeginSample("CompilationPipeline.RunILPostProcessors"); + var assemblyPath = Path.Combine(outputTempPath, assembly.Filename); + + var resultMessages = new List(); + + if (!File.Exists(assemblyPath)) + { + resultMessages.Add(new DiagnosticMessage + { + File = assemblyPath, + MessageData = $"Could not find {assemblyPath} for post processing", + DiagnosticType = DiagnosticType.Error, + }); + } + + bool isILProcessed = false; + var ilPostProcessCompiledAssembly = new ILPostProcessCompiledAssembly(assembly, outputTempPath); + + InMemoryAssembly postProcessedInMemoryAssembly = null; + foreach (var ilPostProcessor in ILPostProcessors) + { + Profiler.BeginSample($"{ilPostProcessor.GetType().FullName}.Process({assembly.Filename})"); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + Console.WriteLine($" - Starting ILPostProcessor '{ilPostProcessor.GetType().FullName}' on {assembly.Filename}"); + var ilPostProcessorInstance = ilPostProcessor.GetInstance(); + var ilPostProcessResult = ilPostProcessorInstance.Process(ilPostProcessCompiledAssembly); + stopwatch.Stop(); + Profiler.EndSample(); + + var elapsed = stopwatch.Elapsed; + + Console.WriteLine($" - Finished ILPostProcessor '{ilPostProcessor.GetType().FullName}' on {assembly.Filename} in {elapsed.TotalSeconds:0.######} seconds"); + postProcessedInMemoryAssembly = ilPostProcessResult?.InMemoryAssembly; + + if (ilPostProcessResult?.InMemoryAssembly != null) + { + isILProcessed = true; + ilPostProcessCompiledAssembly.InMemoryAssembly = postProcessedInMemoryAssembly; + } + + if (ilPostProcessResult?.Diagnostics != null) + { + resultMessages.AddRange(ilPostProcessResult.Diagnostics); + } + } + + if (isILProcessed) + { + ilPostProcessCompiledAssembly.WriteAssembly(); + } + + Profiler.EndSample(); + + return resultMessages; + } + } +} diff --git a/Editor/Mono/Scripting/ScriptCompilation/PostProcessorTask.cs b/Editor/Mono/Scripting/ScriptCompilation/PostProcessorTask.cs new file mode 100644 index 0000000000..d312a6de61 --- /dev/null +++ b/Editor/Mono/Scripting/ScriptCompilation/PostProcessorTask.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 UnityEditor.Scripting.Compilers; +using System.Threading; +using System.Collections.Generic; +using System; + +namespace UnityEditor.Scripting.ScriptCompilation +{ + class PostProcessorTask + { + public ScriptAssembly Assembly { get; private set; } + public List CompilerMessages { get; private set; } + string tempOutputDirectory; + Func, string, List> postProcessFunc; + Thread postProcessingThread; + + public PostProcessorTask(ScriptAssembly assembly, + List compilerMessages, + string tempOutputDirectory, + Func, string, List> postProcessFunc) + { + Assembly = assembly; + CompilerMessages = compilerMessages; + this.tempOutputDirectory = tempOutputDirectory; + this.postProcessFunc = postProcessFunc; + } + + public bool Poll() + { + if (postProcessingThread == null) + { + postProcessingThread = new Thread(() => + { + CompilerMessages = postProcessFunc(Assembly, CompilerMessages, tempOutputDirectory); + }); + + postProcessingThread.Start(); + } + + return !postProcessingThread.IsAlive; + } + } +} diff --git a/Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs index 537cb7334e..617b725a0a 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/PrecompiledAssembly.cs @@ -17,5 +17,5 @@ struct PrecompiledAssembly public string Path; [NativeName("flags")] public AssemblyFlags Flags; - }; + } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs b/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs index d660bac2c6..c502866cfd 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/ScriptAssembly.cs @@ -66,6 +66,12 @@ class ScriptAssembly public bool CallOnBeforeCompilationStarted { get; set; } public ScriptCompilerOptions CompilerOptions { get; set; } public string GeneratedResponseFile { get; set; } + public DirtySource DirtySource { get; set; } + + public ScriptAssembly() + { + DirtySource = DirtySource.None; + } public string FullPath { get { return AssetPath.Combine(OutputDirectory, Filename); } } diff --git a/Editor/Mono/Scripting/ScriptCompilation/SemVersion.cs b/Editor/Mono/Scripting/ScriptCompilation/SemVersion.cs index 2e02640757..c8332c2b62 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/SemVersion.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/SemVersion.cs @@ -129,7 +129,10 @@ private static int CompareExtension(string current, string other, bool lower = f if (currentPartIsNumber && otherPartIsNumber) { result = currentNumber.CompareTo(otherNumber); - if (result != 0) return currentPart.CompareTo(otherNumber); + if (result != 0) + { + return result; + } } else { @@ -145,10 +148,11 @@ private static int CompareExtension(string current, string other, bool lower = f result = string.CompareOrdinal(currentPart, otherPart); if (result != 0) + { return result; + } } } - return currentParts.Length.CompareTo(otherParts.Length); } diff --git a/Editor/Mono/Scripting/ScriptCompilation/SemVersionRangesFactory.cs b/Editor/Mono/Scripting/ScriptCompilation/SemVersionRangesFactory.cs index c0bf19defb..94ec2fc804 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/SemVersionRangesFactory.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/SemVersionRangesFactory.cs @@ -6,9 +6,9 @@ namespace UnityEditor.Scripting.ScriptCompilation { - internal class SemVersionRangesFactory + class SemVersionRangesFactory { - private SemVersionRanges m_SemVersionRanges; + SemVersionRanges m_SemVersionRanges; public SemVersionRangesFactory() { diff --git a/Editor/Mono/Scripting/ScriptCompilation/UnityCodeGenHelpers.cs b/Editor/Mono/Scripting/ScriptCompilation/UnityCodeGenHelpers.cs index 14033e5ba0..c31024d405 100644 --- a/Editor/Mono/Scripting/ScriptCompilation/UnityCodeGenHelpers.cs +++ b/Editor/Mono/Scripting/ScriptCompilation/UnityCodeGenHelpers.cs @@ -3,6 +3,7 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor.Scripting.ScriptCompilation; @@ -23,34 +24,50 @@ internal static class UnityCodeGenHelpers const string k_UnityEditorModules = "UnityEditor"; const string k_UnityEditorModulesLower = "unityeditor"; + public struct ScriptCodeGenAssemblies + { + public List ScriptAssemblies; + public List CodeGenAssemblies; + } + public static bool IsCodeGen(string assemblyName, bool includesExtension = true) { var name = (includesExtension ? Path.GetFileNameWithoutExtension(assemblyName) : assemblyName); - var isCodeGen = name.StartsWith(k_CodeGenPrefix) && name.EndsWith(k_CodeGenSuffix, StringComparison.OrdinalIgnoreCase); + var isCodeGen = name.StartsWith(k_CodeGenPrefix, StringComparison.OrdinalIgnoreCase) && name.EndsWith(k_CodeGenSuffix, StringComparison.OrdinalIgnoreCase); return isCodeGen; } public static void UpdateCodeGenScriptAssembly(ref ScriptAssembly scriptAssembly) { - scriptAssembly.ScriptAssemblyReferences = new ScriptAssembly[0]; + int referencesLength = scriptAssembly.References.Length; + var newReferences = new string[referencesLength + 1]; + Array.Copy(scriptAssembly.References, newReferences, referencesLength); + newReferences[referencesLength] = AssetPath.Combine(EditorApplication.applicationContentsPath, "Managed", "Unity.CompilationPipeline.Common.dll"); + scriptAssembly.References = newReferences; + } + + public static ScriptCodeGenAssemblies ToScriptCodeGenAssemblies(ScriptAssembly[] scriptAssemblies) + { + var result = new ScriptCodeGenAssemblies(); - int newReferenceCount = 0; - var references = new string[scriptAssembly.References.Length]; + result.ScriptAssemblies = new List(scriptAssemblies.Length); + result.CodeGenAssemblies = new List(scriptAssemblies.Length); - foreach (var reference in scriptAssembly.References) + foreach (var scriptAssembly in scriptAssemblies) { - var name = AssetPath.GetFileName(reference); - if (!Utility.FastStartsWith(name, k_UnityEngineModules, k_UnityEngineModulesLower) - && !Utility.FastStartsWith(name, k_UnityEditorModules, k_UnityEditorModulesLower)) + bool isCodeGen = IsCodeGen(scriptAssembly.Filename, true); + + if (isCodeGen) { - references[newReferenceCount] = reference; - newReferenceCount++; + result.CodeGenAssemblies.Add(scriptAssembly); + } + else + { + result.ScriptAssemblies.Add(scriptAssembly); } } - var result = new string[newReferenceCount + 1]; - Array.Copy(references, result, newReferenceCount); - result[newReferenceCount] = AssetPath.Combine(EditorApplication.applicationContentsPath, "Managed", "Unity.CompilationPipeline.Common.dll"); - scriptAssembly.References = result; + + return result; } } } diff --git a/Editor/Mono/SearchUtility.cs b/Editor/Mono/SearchUtility.cs index 9b36997ade..149ef0ac18 100644 --- a/Editor/Mono/SearchUtility.cs +++ b/Editor/Mono/SearchUtility.cs @@ -187,14 +187,18 @@ internal static bool CheckForKeyWords(string searchString, SearchFilter filter, if (count < 0 || quote2 == -1) count = searchString.Length - startIndex; - // Strip filepath from quotes - assetPath = "Assets/" + searchString.Substring(startIndex, count); + // Strip filepath from quotes, don't prefix with Assets/, we need to support Packages/ (https://fogbugz.unity3d.com/f/cases/1161019/) + assetPath = searchString.Substring(startIndex, count); } else - // Otherwise use string from colon to end - assetPath = "Assets/" + searchString.Substring(firstColon + 1); + // Otherwise use string from colon to end, don't prefix with Assets/, we need to support Packages/ (https://fogbugz.unity3d.com/f/cases/1161019/) + assetPath = searchString.Substring(firstColon + 1); Object obj = AssetDatabase.LoadMainAssetAtPath(assetPath); + if (obj == null) + // Backward compatibility, in case Assets/ was strip from path + obj = AssetDatabase.LoadMainAssetAtPath("Assets/" + assetPath); + if (obj != null) instanceID = obj.GetInstanceID(); //else diff --git a/Editor/Mono/SerializedProperty.bindings.cs b/Editor/Mono/SerializedProperty.bindings.cs index 4bbb965dac..4907078bac 100644 --- a/Editor/Mono/SerializedProperty.bindings.cs +++ b/Editor/Mono/SerializedProperty.bindings.cs @@ -9,6 +9,8 @@ using UnityEngine.Bindings; using UnityObject = UnityEngine.Object; +using System.Reflection; +using System.Text.RegularExpressions; namespace UnityEditor { @@ -74,6 +76,9 @@ public enum SerializedPropertyType // Bounds with int property. BoundsInt = 23, + + // Managed reference property. + ManagedReference = 24, } [NativeHeader("Editor/Src/Utility/SerializedProperty.h")] @@ -487,6 +492,28 @@ public string propertyPath [NativeName("GetPropertyPath")] private extern string GetPropertyPathInternal(); + /// + /// This is a more generic and less specialized form as the one below + /// 'hashCodeForPropertyPathWithoutArrayIndex' that assumes that + /// we dont have managed references. + /// + internal int hashCodeForPropertyPath + { + get + { + Verify(); + + // For managed references we cannot ignore the array index since + // instances might change from index to index. + if (propertyType == SerializedPropertyType.ManagedReference) + { + return GetHashCodeForPropertyPathInternal(); + } + + return hashCodeForPropertyPathWithoutArrayIndex; + } + } + internal int hashCodeForPropertyPathWithoutArrayIndex { get @@ -499,6 +526,9 @@ internal int hashCodeForPropertyPathWithoutArrayIndex [NativeName("GetHasCodeForPropertyPathWithoutArrayIndex")] private extern int GetHasCodeForPropertyPathWithoutArrayIndexInternal(); + [NativeName("GetHashCodeForPropertyPath")] + private extern int GetHashCodeForPropertyPathInternal(); + // Is this property editable? (RO) public bool editable { @@ -863,6 +893,87 @@ public UnityObject objectReferenceValue } } + // Value of an object reference property. + public object managedReferenceValue + { + set + { + if (propertyType != SerializedPropertyType.ManagedReference) + { + throw new System.InvalidOperationException( + $"Attempting to set the managed reference value on a SerializedProperty that is set to a '{this.type}'"); + } + + // Make sure that the underlying base type is compatible with the current object + Type type; + var fieldInfo = UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out type); + var propertyBaseType = type; + + if (!propertyBaseType.IsAssignableFrom(value.GetType())) + { + throw new System.InvalidOperationException( + $"Cannot assign an object of type '{value.GetType().Name}' to a managed reference with a base type of '{propertyBaseType.Name}': types are not compatible"); + } + + Verify(VerifyFlags.IteratorNotAtEnd); + SetManagedReferenceValueInternal(value); + } + // No getter for managed reference since it adds a few notions that might be hard to reason about from the user's perspective. + // A serializedobject is a serialized version of a UnityObject. A serialized property is a view on that serialized object. + // All operations and all that a serialized knows about are around that serialzied view of the managed world. + // Managed references in the context of SO/SP does not have the same semantics as C# references. All the references are + // serialized properly but the original C# reference is lost in the process and cannot be retrieved unless e.g. cached locally + // on the C# side (i.e. in this file). BUT this would not world properly or involve tricky reconstruction with domain reloads + // after which all those C# references would have to be reconstructed etc. + // So for now we dont allow getting a managed reference. + + // If we ever wanted to add one though, the approach would be to add an explicit setting that takes an reference ID and an object instance as + // input, this would allow serialized properties to edit relations between managed references. We would also need a method to get + // an instance from a managed reference id along with a nice safe API around it. + } + + // Dynamic type for the current managed reference. + public string managedReferenceFullTypename + { + get + { + if (propertyType != SerializedPropertyType.ManagedReference) + { + throw new System.InvalidOperationException( + $"Attempting to get the managed reference full typename on a SerializedProperty that is set to a '{this.type}'"); + } + if (serializedObject.targetObject == null) + { + return null; + } + return GetManagedReferenceFullTypeNameInternal(); + } + } + + // Static type for the current managed reference. + public string managedReferenceFieldTypename + { + get + { + if (propertyType != SerializedPropertyType.ManagedReference) + { + throw new System.InvalidOperationException( + $"Attempting to get the managed reference full typename on a SerializedProperty that is set to a '{this.type}'"); + } + + Type type; + var fieldInfo = UnityEditor.ScriptAttributeUtility.GetFieldInfoAndStaticTypeFromProperty(this, out type); + + return $"{type.Assembly.GetName().Name} {type.FullName.Replace("+", "/")}"; + } + } + + [NativeName("GetManagedReferenceFullTypeName")] + private extern string GetManagedReferenceFullTypeNameInternal(); + + [NativeName("SetManagedReferenceValue")] + private extern void SetManagedReferenceValueInternal(object value); + [NativeName("GetPPtrValue")] private extern UnityObject GetPPtrValueInternal(); diff --git a/Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs b/Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs index 6e82b7ae85..ffa8e15271 100644 --- a/Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs +++ b/Editor/Mono/SerializedProperty/SerializedPropertyFilters.cs @@ -24,7 +24,7 @@ internal abstract class SerializableFilter : IFilter public abstract void OnGUI(Rect r); // draws the filter control public string SerializeState() { return JsonUtility.ToJson(this); } public void DeserializeState(string state) { JsonUtility.FromJsonOverwrite(state, this); } - }; + } internal class String : SerializableFilter @@ -41,18 +41,21 @@ static class Styles public override bool Filter(SerializedProperty prop) { return prop.stringValue.IndexOf(m_Text, 0, System.StringComparison.OrdinalIgnoreCase) >= 0; } public override void OnGUI(Rect r) { - r.width -= 15; - m_Text = EditorGUI.TextField(r, GUIContent.none, m_Text, Styles.searchField); + bool empty = string.IsNullOrEmpty(m_Text); + + Rect buttonRect = r; + buttonRect.x += (r.width - 15); + buttonRect.width = 15; + GUIStyle buttonStyle = empty ? Styles.searchFieldCancelButtonEmpty : Styles.searchFieldCancelButton; - // draw the cancel button - r.x += r.width; - r.width = 15; - bool notEmpty = m_Text != ""; - if (GUI.Button(r, GUIContent.none, notEmpty ? Styles.searchFieldCancelButton : Styles.searchFieldCancelButtonEmpty) && notEmpty) + if (GUI.Button(buttonRect, GUIContent.none, buttonStyle) && !empty) { m_Text = ""; GUIUtility.keyboardControl = 0; } + + m_Text = EditorGUI.TextField(r, GUIContent.none, m_Text, Styles.searchField); + GUI.Button(buttonRect, GUIContent.none, buttonStyle); } } diff --git a/Editor/Mono/SerializedProperty/SerializedPropertyTable.cs b/Editor/Mono/SerializedProperty/SerializedPropertyTable.cs index 3fbd034cf9..8862d387a6 100644 --- a/Editor/Mono/SerializedProperty/SerializedPropertyTable.cs +++ b/Editor/Mono/SerializedProperty/SerializedPropertyTable.cs @@ -10,11 +10,6 @@ namespace UnityEditor { internal class SerializedPropertyTable { - static class Styles - { - public static readonly GUIStyle DragHandle = "RL DragHandle"; - } - internal delegate SerializedPropertyTreeView.Column[] HeaderDelegate(); SerializedPropertyDataStore.GatherDelegate m_GatherDelegate; @@ -25,23 +20,14 @@ static class Styles SerializedPropertyTreeView m_TreeView; SerializedPropertyDataStore m_DataStore; float m_ColumnHeaderHeight; - float m_TableHeight = 200; string m_SerializationUID; - static readonly string s_TableHeight = "_TableHeight"; - bool m_DragHandleEnabled = false; readonly float m_FilterHeight = 20; - readonly float m_DragHeight = 20; - readonly float m_DragWidth = 32; - - public bool dragHandleEnabled { get { return m_DragHandleEnabled; } set { m_DragHandleEnabled = value; } } public SerializedPropertyTable(string serializationUID, SerializedPropertyDataStore.GatherDelegate gatherDelegate, HeaderDelegate headerDelegate) { m_SerializationUID = serializationUID; m_GatherDelegate = gatherDelegate; m_HeaderDelegate = headerDelegate; - - OnEnable(); } void InitIfNeeded() @@ -83,14 +69,6 @@ string[] GetPropertyNames(SerializedPropertyTreeView.Column[] columns) return propNames; } - float GetMinHeight() - { - float rowHeight = EditorGUIUtility.singleLineHeight; - float fixedHeight = m_FilterHeight + m_ColumnHeaderHeight + rowHeight + m_DragHeight; - - return fixedHeight + rowHeight * 3; // three rows - } - public void OnInspectorUpdate() { if (m_DataStore != null && m_DataStore.Repopulate() && m_TreeView != null) @@ -127,12 +105,7 @@ public void OnGUI() Profiler.BeginSample("SerializedPropertyTable.OnGUI"); InitIfNeeded(); - Rect r; - - if (dragHandleEnabled) - r = GUILayoutUtility.GetRect(0, 10000, m_TableHeight, m_TableHeight); - else - r = GUILayoutUtility.GetRect(0, float.MaxValue, 0, float.MaxValue); + Rect r = GUILayoutUtility.GetRect(0, float.MaxValue, 0, float.MaxValue); if (Event.current.type == EventType.Layout) { @@ -140,10 +113,8 @@ public void OnGUI() return; } - float windowWidth = r.width; - float tableHeight = r.height - m_FilterHeight - (dragHandleEnabled ? m_DragHeight : 0); + float tableHeight = r.height - m_FilterHeight; // filter rect - float h = r.height; r.height = m_FilterHeight; Rect filterRect = r; // table rect @@ -156,32 +127,6 @@ public void OnGUI() m_TreeView.OnGUI(tableRect); Profiler.EndSample(); - if (dragHandleEnabled) - { - // separator rect - r.y += tableHeight + 1; - r.height = 1; - Rect sepRect = r; - // drag rect - r.height = 10; - r.y += 10; - r.x += (r.width - m_DragWidth) * 0.5f; - r.width = m_DragWidth; - - m_TableHeight = EditorGUI.HeightResizer(r, m_TableHeight, GetMinHeight(), float.MaxValue); - - // separator (TODO: this doesn't quite work in the case where the vertical bar is visible and the last column overlaps it) - // once trunk is merged again the treeview will provide a routine to draw the separator for us - if (m_MultiColumnHeaderState.widthOfAllVisibleColumns <= windowWidth) - { - Rect uv = new Rect(0, 1f, 1, 1f - 1f / EditorStyles.inspectorTitlebar.normal.background.height); - GUI.DrawTextureWithTexCoords(sepRect, EditorStyles.inspectorTitlebar.normal.background, uv); - } - - if (Event.current.type == EventType.Repaint) - Styles.DragHandle.Draw(r, false, false, false, false); - } - m_TreeView.OnFilterGUI(filterRect); if (m_TreeView.IsFilteredDirty()) @@ -190,17 +135,10 @@ public void OnGUI() Profiler.EndSample(); } - public void OnEnable() - { - m_TableHeight = SessionState.GetFloat(m_SerializationUID + s_TableHeight, 200); - } - public void OnDisable() { if (m_TreeView != null) m_TreeView.SerializeState(m_SerializationUID); - - SessionState.SetFloat(m_SerializationUID + s_TableHeight, m_TableHeight); } } } diff --git a/Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs b/Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs index 0c3f218b86..a62023c210 100644 --- a/Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs +++ b/Editor/Mono/SerializedProperty/SerializedPropertyTreeView.cs @@ -59,13 +59,26 @@ public int objectId } } + public bool activeInHierarchy + { + get + { + if (m_Object != null && typeof(Component).IsAssignableFrom(m_Object.GetType())) + { + return ((Component)m_Object).gameObject.activeInHierarchy; + } + + return false; + } + } + public bool Update() { return m_Object != null ? m_SerializedObject.UpdateIfRequiredOrScript() : false; } public void Store() { if (m_Object != null) { m_SerializedObject.ApplyModifiedProperties(); } } } // LightTreeDataStore members internal delegate UnityEngine.Object[] GatherDelegate(); - UnityEngine.Object[] m_Objects; + UnityEngine.Object[] m_Objects; // only used to keep track of changes Data[] m_Elements; string[] m_PropNames; GatherDelegate m_GatherDel; @@ -103,8 +116,21 @@ public bool Repopulate() // Recreate data store m_Objects = objs; m_Elements = new Data[objs.Length]; + + int elementIndex = 0; for (int i = 0; i < objs.Length; i++) - m_Elements[i] = new Data(objs[i], m_PropNames); + { + // we don't want to list hidden objects + if (objs[i].hideFlags == HideFlags.HideAndDontSave) + continue; + + m_Elements[elementIndex] = new Data(objs[i], m_PropNames); + + elementIndex++; + } + + if (elementIndex < objs.Length) + System.Array.Resize(ref m_Elements, elementIndex); return true; } @@ -133,15 +159,15 @@ internal static class Styles public static readonly string serializeTreeViewState = "_TreeViewState"; public static readonly string serializeColumnHeaderState = "_ColumnHeaderState"; public static readonly string serializeFilter = "_Filter_"; - public static readonly GUIContent filterSelection = EditorGUIUtility.TrTextContent("Lock Selection", "Limits the table contents to the active selection."); - public static readonly GUIContent filterDisable = EditorGUIUtility.TrTextContent("Disable All", "Disables all filters."); - public static readonly GUIContent filterInvert = EditorGUIUtility.TrTextContent("Invert Result", "Inverts the filtered results."); + public static readonly GUIContent filterSelection = EditorGUIUtility.TrTextContent("Isolate Selection", "Limits the table contents to the active selection."); + public static readonly GUIContent showInactiveObjects = EditorGUIUtility.TrTextContent("Show Inactive Objects", "Show objects that are not active in the hierarchy but contains the component."); } // this gets stuffed into the view and displayed on screen. It is a visible subset of the actual data internal class SerializedPropertyItem : TreeViewItem { SerializedPropertyDataStore.Data m_Data; + public SerializedPropertyItem(int id, int depth, SerializedPropertyDataStore.Data ltd) : base(id, depth, ltd != null ? ltd.name : "root") { m_Data = ltd; @@ -182,12 +208,12 @@ public static void OverwriteSerializedFields(MultiColumnHeaderState source, Mult } } } - }; + } private struct ColumnInternal { public SerializedProperty[] dependencyProps; // helper array, must be the same size as dependencyIndices - }; + } internal class DefaultDelegates { @@ -246,6 +272,7 @@ internal class DefaultDelegates List m_Items; int m_ChangedId; bool m_bFilterSelection; + bool m_ShowInactiveObjects; int[] m_SelectionFilter; public SerializedPropertyTreeView(TreeViewState state, MultiColumnHeader multicolumnHeader, SerializedPropertyDataStore dataStore) : base(state, multicolumnHeader) @@ -272,6 +299,7 @@ public SerializedPropertyTreeView(TreeViewState state, MultiColumnHeader multico public void SerializeState(string uid) { SessionState.SetBool(uid + Styles.serializeFilterSelection, m_bFilterSelection); + SessionState.SetBool(uid + Styles.showInactiveObjects, m_ShowInactiveObjects); for (int i = 0; i < multiColumnHeader.state.columns.Length; i++) { @@ -295,6 +323,7 @@ public void SerializeState(string uid) public void DeserializeState(string uid) { m_bFilterSelection = SessionState.GetBool(uid + Styles.serializeFilterSelection, false); + m_ShowInactiveObjects = SessionState.GetBool(uid + Styles.showInactiveObjects, false); MultiColumnHeaderState headerState = new MultiColumnHeaderState(multiColumnHeader.state.columns); string columnHeaderState = EditorPrefs.GetString(uid + Styles.serializeColumnHeaderState, ""); @@ -378,6 +407,9 @@ protected override IList BuildRows(TreeViewItem root) // filtering IEnumerable tmprows = m_Items; + if (!m_ShowInactiveObjects) + tmprows = m_Items.Where((TreeViewItem item) => { return ((SerializedPropertyItem)item).GetData().activeInHierarchy; }); + if (m_bFilterSelection) { if (m_SelectionFilter == null) @@ -424,7 +456,10 @@ void CellGUI(Rect cellRect, SerializedPropertyItem item, int columnIndex, ref Ro { // default drawing Profiler.BeginSample("SerializedPropertyTreeView.OnItemGUI.LabelField"); - DefaultGUI.Label(cellRect, ltd.name, IsSelected(args.item.id), false); + using (new EditorGUI.DisabledScope(!ltd.activeInHierarchy)) + { + DefaultGUI.Label(cellRect, ltd.name, IsSelected(args.item.id), false); + } Profiler.EndSample(); } else if (column.drawDelegate != null) @@ -516,6 +551,7 @@ public void OnFilterGUI(Rect r) EditorGUI.BeginChangeCheck(); float fullWidth = r.width; + float windowPadding = r.x; float toggleWidth = 16; r.width = toggleWidth; @@ -524,8 +560,15 @@ public void OnFilterGUI(Rect r) r.width = GUI.skin.label.CalcSize(SerializedPropertyTreeView.Styles.filterSelection).x; EditorGUI.LabelField(r, SerializedPropertyTreeView.Styles.filterSelection); + r.x += r.width + 10; + r.width = toggleWidth; + m_ShowInactiveObjects = EditorGUI.Toggle(r, m_ShowInactiveObjects); + r.x += toggleWidth; + r.width = GUI.skin.label.CalcSize(SerializedPropertyTreeView.Styles.showInactiveObjects).x; + EditorGUI.LabelField(r, SerializedPropertyTreeView.Styles.showInactiveObjects); + r.width = Mathf.Min(fullWidth - (r.x + r.width), 300); - r.x = fullWidth - r.width + 10; + r.x = fullWidth - r.width + windowPadding; for (int i = 0; i < multiColumnHeader.state.columns.Length; i++) { diff --git a/Editor/Mono/Settings/SettingsService.cs b/Editor/Mono/Settings/SettingsService.cs index af49bc0371..958acd9a7b 100644 --- a/Editor/Mono/Settings/SettingsService.cs +++ b/Editor/Mono/Settings/SettingsService.cs @@ -32,8 +32,11 @@ public static void NotifySettingsProviderChanged() const string k_ProjectSettings = "Edit/Project Settings"; static SettingsService() { - EditorApplication.update -= CheckProjectSettings; - EditorApplication.update += CheckProjectSettings; + if (Unity.MPE.ProcessService.level == Unity.MPE.ProcessLevel.UMP_MASTER) + { + EditorApplication.update -= CheckProjectSettings; + EditorApplication.update += CheckProjectSettings; + } } internal static event Action settingsProviderChanged; diff --git a/Editor/Mono/ShaderUtil.bindings.cs b/Editor/Mono/ShaderUtil.bindings.cs index c89ec5d4cc..44cee7f118 100644 --- a/Editor/Mono/ShaderUtil.bindings.cs +++ b/Editor/Mono/ShaderUtil.bindings.cs @@ -110,7 +110,7 @@ public enum ShaderPropertyType Float, Range, TexEnv, - }; + } extern internal static int GetAvailableShaderCompilerPlatforms(); diff --git a/Editor/Mono/ShaderUtil.bindings.deprecated.cs b/Editor/Mono/ShaderUtil.bindings.deprecated.cs index e942dacc56..6c8919715e 100644 --- a/Editor/Mono/ShaderUtil.bindings.deprecated.cs +++ b/Editor/Mono/ShaderUtil.bindings.deprecated.cs @@ -23,6 +23,6 @@ public enum ShaderPropertyTexDim TexDim3D = 3, TexDimCUBE = 4, TexDimAny = 6, - }; + } } } diff --git a/Editor/Mono/Sprites/SpritePacker.cs b/Editor/Mono/Sprites/SpritePacker.cs index 05aafa45dc..c61581c27e 100644 --- a/Editor/Mono/Sprites/SpritePacker.cs +++ b/Editor/Mono/Sprites/SpritePacker.cs @@ -71,7 +71,6 @@ private static void RegenerateList() { Type otherT = m_policyTypeCache[t.Name]; Debug.LogError(string.Format("Duplicate Sprite Packer policies found: {0} and {1}. Please rename one.", t.FullName, otherT.FullName)); - continue; } else m_policyTypeCache[t.Name] = t; diff --git a/Editor/Mono/Sprites/SpritePackerWindow.cs b/Editor/Mono/Sprites/SpritePackerWindow.cs index f5e504bc98..8796f25e1d 100644 --- a/Editor/Mono/Sprites/SpritePackerWindow.cs +++ b/Editor/Mono/Sprites/SpritePackerWindow.cs @@ -48,7 +48,7 @@ public override int GetHashCode() { return (v0 << 16 | v1) ^ (v1 << 16 | v0).GetHashCode(); } - }; + } private static string[] s_AtlasNamesEmpty = new string[1] { "Sprite atlas cache is empty" }; private string[] m_AtlasNames = s_AtlasNamesEmpty; diff --git a/Editor/Mono/StateMachine.bindings.cs b/Editor/Mono/StateMachine.bindings.cs index 646b26256d..dcb8dee6b2 100644 --- a/Editor/Mono/StateMachine.bindings.cs +++ b/Editor/Mono/StateMachine.bindings.cs @@ -148,7 +148,7 @@ extern public TransitionInterruptionSource interruptionSource [NativeHeader("Editor/Src/Animation/StateMachine.h")] [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] [NativeHeader("Editor/Src/Animation/StateMachineBehaviourScripting.h")] - public partial class AnimatorState : Object + public sealed partial class AnimatorState : Object { public AnimatorState() { @@ -217,6 +217,17 @@ public T AddStateMachineBehaviour() where T : StateMachineBehaviour { return AddStateMachineBehaviour(typeof(T)) as T; } + + public StateMachineBehaviour[] behaviours + { + get { return Array.ConvertAll(behaviours_Internal, so => (StateMachineBehaviour)so); } + set { behaviours_Internal = Array.ConvertAll(value, smb => (ScriptableObject)smb); } + } + + [NativeName("Behaviours")] + private extern ScriptableObject[] behaviours_Internal { get; set; } + + internal extern MonoScript GetBehaviourMonoScript(int index); } [NativeHeader("Editor/Src/Animation/StateMachine.h")] @@ -247,7 +258,7 @@ public struct ChildAnimatorStateMachine [NativeHeader("Editor/Src/Animation/StateMachine.h")] [NativeHeader("Editor/Src/Animation/StateMachine.bindings.h")] [NativeHeader("Editor/Src/Animation/StateMachineBehaviourScripting.h")] - public partial class AnimatorStateMachine : Object + public sealed partial class AnimatorStateMachine : Object { public AnimatorStateMachine() { @@ -319,5 +330,16 @@ extern internal int transitionCount { get; } + + public StateMachineBehaviour[] behaviours + { + get { return Array.ConvertAll(behaviours_Internal, so => (StateMachineBehaviour)so); } + set { behaviours_Internal = Array.ConvertAll(value, smb => (ScriptableObject)smb); } + } + + [NativeName("Behaviours")] + private extern ScriptableObject[] behaviours_Internal { get; set; } + + internal extern MonoScript GetBehaviourMonoScript(int index); } } diff --git a/Editor/Mono/SyncProject.cs b/Editor/Mono/SyncProject.cs index 7a7a2438e6..6808dac155 100644 --- a/Editor/Mono/SyncProject.cs +++ b/Editor/Mono/SyncProject.cs @@ -12,6 +12,7 @@ using UnityEngine; using UnityEngine.Scripting; using UnityEditorInternal; +using Unity.CodeEditor; namespace UnityEditor { @@ -42,10 +43,14 @@ public VisualStudioPath(string path, string edition = "") [InitializeOnLoad] internal partial class SyncVS : AssetPostprocessor { + static bool s_Enabled = false; static bool s_AlreadySyncedThisDomainReload; static SyncVS() { + s_Enabled = Unity.MPE.ProcessService.level == Unity.MPE.ProcessLevel.UMP_MASTER; + if (!s_Enabled) + return; Synchronizer = new SolutionSynchronizer(Directory.GetParent(Application.dataPath).FullName, new SolutionSynchronizationSettings()); try { @@ -160,7 +165,11 @@ public void OnActiveBuildTargetChanged(BuildTarget oldTarget, BuildTarget newTar [RequiredByNativeCode] public static void SyncVisualStudioProjectIfItAlreadyExists() { - if (Synchronizer.SolutionExists()) + if (!s_Enabled) + return; + + #pragma warning disable 618 + if (Synchronizer.SolutionExists() && ScriptEditorUtility.GetScriptEditorFromPath(CodeEditor.CurrentEditorInstallation) != ScriptEditorUtility.ScriptEditor.Other) { Synchronizer.Sync(); } @@ -174,6 +183,9 @@ public static void PostprocessSyncProject( string[] movedAssets, string[] movedFromAssetPaths) { + if (!s_Enabled) + return; + Synchronizer.SyncIfNeeded(addedAssets.Union(deletedAssets.Union(movedAssets.Union(movedFromAssetPaths))), importedAssets); } diff --git a/Editor/Mono/UIElements/Controls/BindingExtensions.cs b/Editor/Mono/UIElements/Controls/BindingExtensions.cs index 9821996507..b7909040e9 100644 --- a/Editor/Mono/UIElements/Controls/BindingExtensions.cs +++ b/Editor/Mono/UIElements/Controls/BindingExtensions.cs @@ -115,7 +115,14 @@ public static void Unbind(this VisualElement element) public static SerializedProperty BindProperty(this IBindable field, SerializedObject obj) { - return BindPropertyWithParent(field, new SerializedObjectUpdateWrapper(obj), null); + var property = obj?.FindProperty(field.bindingPath); + + if (property != null) + { + Bind(field as VisualElement, new SerializedObjectUpdateWrapper(obj), null); + } + + return property; } public static void BindProperty(this IBindable field, SerializedProperty property) @@ -125,7 +132,8 @@ public static void BindProperty(this IBindable field, SerializedProperty propert throw new ArgumentNullException(nameof(property)); } - DoBindProperty(field, new SerializedObjectUpdateWrapper(property.serializedObject), property); + field.bindingPath = property.propertyPath; + Bind(field as VisualElement, new SerializedObjectUpdateWrapper(property.serializedObject), null); } private static void DoBindProperty(IBindable field, SerializedObjectUpdateWrapper obj, SerializedProperty property) @@ -916,7 +924,7 @@ protected void UpdateFieldIsAttached() else { //we're not dealing with VisualElement - if (!isFieldAttached) + if (m_Field != null && !isFieldAttached) { isFieldAttached = true; ResetCachedValues(); diff --git a/Editor/Mono/UIElements/Controls/EnumField.cs b/Editor/Mono/UIElements/Controls/EnumField.cs index 08117f7730..dcea25d208 100644 --- a/Editor/Mono/UIElements/Controls/EnumField.cs +++ b/Editor/Mono/UIElements/Controls/EnumField.cs @@ -15,7 +15,7 @@ public class EnumField : BaseField public new class UxmlTraits : BaseField.UxmlTraits { #pragma warning disable 414 - private UxmlStringAttributeDescription m_Type = EnumFieldHelpers.type; + private UxmlTypeAttributeDescription m_Type = EnumFieldHelpers.type; private UxmlStringAttributeDescription m_Value = EnumFieldHelpers.value; private UxmlBoolAttributeDescription m_IncludeObsoleteValues = EnumFieldHelpers.includeObsoleteValues; #pragma warning restore 414 diff --git a/Editor/Mono/UIElements/Controls/EnumFlagsField.cs b/Editor/Mono/UIElements/Controls/EnumFlagsField.cs index 703733679b..e3add12b3c 100644 --- a/Editor/Mono/UIElements/Controls/EnumFlagsField.cs +++ b/Editor/Mono/UIElements/Controls/EnumFlagsField.cs @@ -12,28 +12,21 @@ namespace UnityEditor.UIElements { static class EnumFieldHelpers { - internal static readonly UxmlStringAttributeDescription type = new UxmlStringAttributeDescription { name = "type" }; + internal static readonly UxmlTypeAttributeDescription type = new UxmlTypeAttributeDescription { name = "type" }; internal static readonly UxmlStringAttributeDescription value = new UxmlStringAttributeDescription { name = "value" }; internal static readonly UxmlBoolAttributeDescription includeObsoleteValues = new UxmlBoolAttributeDescription() { name = "include-obsolete-values", defaultValue = false }; internal static bool ExtractValue(IUxmlAttributes bag, CreationContext cc, out Enum resEnumValue, out bool resIncludeObsoleteValues) { - string enumType = null; resIncludeObsoleteValues = false; resEnumValue = null; - if (!type.TryGetValueFromBag(bag, cc, ref enumType)) + var systemType = type.GetValueFromBag(bag, cc); + if (systemType == null) { return false; } - Type systemType = Type.GetType(enumType); - if (systemType == null || !systemType.IsEnum) - { - Debug.LogError($"EnumField: Invalid enum type \"{enumType}\""); - return false; - } - string specifiedValue = null; if (value.TryGetValueFromBag(bag, cc, ref specifiedValue) && !Enum.IsDefined(systemType, specifiedValue)) { @@ -55,7 +48,7 @@ public class EnumFlagsField : BaseMaskField public new class UxmlTraits : BaseMaskField.UxmlTraits { #pragma warning disable 414 - private UxmlStringAttributeDescription m_Type = EnumFieldHelpers.type; + private UxmlTypeAttributeDescription m_Type = EnumFieldHelpers.type; private UxmlStringAttributeDescription m_Value = EnumFieldHelpers.value; private UxmlBoolAttributeDescription m_IncludeObsoleteValues = EnumFieldHelpers.includeObsoleteValues; #pragma warning restore 414 diff --git a/Editor/Mono/UIElements/Controls/ListViewBindings.cs b/Editor/Mono/UIElements/Controls/ListViewBindings.cs index 56706556bd..005f432291 100644 --- a/Editor/Mono/UIElements/Controls/ListViewBindings.cs +++ b/Editor/Mono/UIElements/Controls/ListViewBindings.cs @@ -43,12 +43,12 @@ protected void SetBinding(ListView listView, if (listView.makeItem == null) { - listView.makeItem = MakeListViewItem; + listView.makeItem = () => MakeListViewItem(); } if (listView.bindItem == null) { - listView.bindItem = BindListViewItem; + listView.bindItem = (v, i) => BindListViewItem(v, i); } listView.itemsSource = m_DataList; diff --git a/Editor/Mono/UIElements/Controls/ObjectField.cs b/Editor/Mono/UIElements/Controls/ObjectField.cs index 2107c11dea..17a7a7f063 100644 --- a/Editor/Mono/UIElements/Controls/ObjectField.cs +++ b/Editor/Mono/UIElements/Controls/ObjectField.cs @@ -17,12 +17,14 @@ public class ObjectField : BaseField public new class UxmlTraits : BaseField.UxmlTraits { UxmlBoolAttributeDescription m_AllowSceneObjects = new UxmlBoolAttributeDescription { name = "allow-scene-objects", defaultValue = true }; + UxmlTypeAttributeDescription m_ObjectType = new UxmlTypeAttributeDescription { name = "type" }; public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) { base.Init(ve, bag, cc); ((ObjectField)ve).allowSceneObjects = m_AllowSceneObjects.GetValueFromBag(bag, cc); + ((ObjectField)ve).objectType = m_ObjectType.GetValueFromBag(bag, cc); } } diff --git a/Editor/Mono/UIElements/Controls/PopupField.cs b/Editor/Mono/UIElements/Controls/PopupField.cs index 3d31175b02..548b56162a 100644 --- a/Editor/Mono/UIElements/Controls/PopupField.cs +++ b/Editor/Mono/UIElements/Controls/PopupField.cs @@ -89,6 +89,10 @@ public int index public new static readonly string labelUssClassName = ussClassName + "__label"; public new static readonly string inputUssClassName = ussClassName + "__input"; + public PopupField() + : this(null) + {} + public PopupField(string label = null) : base(label) { diff --git a/Editor/Mono/UIElements/UIElementsViewImporter.cs b/Editor/Mono/UIElements/UIElementsViewImporter.cs index 32dfc09606..7e4ffd4cda 100644 --- a/Editor/Mono/UIElements/UIElementsViewImporter.cs +++ b/Editor/Mono/UIElements/UIElementsViewImporter.cs @@ -327,11 +327,7 @@ void ImportXml(string xmlPath, out VisualTreeAsset vta) } LoadXmlRoot(doc, vta); - - StyleSheet inlineSheet = ScriptableObject.CreateInstance(); - inlineSheet.name = "inlineStyle"; - m_Builder.BuildTo(inlineSheet); - vta.inlineSheet = inlineSheet; + TryCreateInlineStyleSheet(vta); } internal void ImportXmlFromString(string xml, out VisualTreeAsset vta) @@ -358,6 +354,30 @@ internal void ImportXmlFromString(string xml, out VisualTreeAsset vta) } LoadXmlRoot(doc, vta); + TryCreateInlineStyleSheet(vta); + } + + void TryCreateInlineStyleSheet(VisualTreeAsset vta) + { + if (m_Context != null) + { + foreach (var e in m_Errors) + { + if (e.isWarning) + m_Context.LogImportWarning(e.ToString(), e.assetPath, e.line); + else + m_Context.LogImportError(e.ToString(), e.assetPath, e.line); + } + } + + if (m_Errors.hasErrors) + { + // in case of errors preventing the creation of the inline stylesheet, + // reset rule indices + foreach (var asset in vta.visualElementAssets) + asset.ruleIndex = -1; + return; + } StyleSheet inlineSheet = ScriptableObject.CreateInstance(); inlineSheet.name = "inlineStyle"; diff --git a/Editor/Mono/Undo.cs b/Editor/Mono/Undo.cs index bc9171b6ef..9b2ca4580b 100644 --- a/Editor/Mono/Undo.cs +++ b/Editor/Mono/Undo.cs @@ -10,7 +10,7 @@ namespace UnityEditor { public partial class Undo { - internal enum UndoRedoType { Undo, Redo }; + internal enum UndoRedoType { Undo, Redo } [RequiredByNativeCode] static void OnSelectionUndo(bool redo) diff --git a/Editor/Mono/UnityConnect/UnityConnect.bindings.cs b/Editor/Mono/UnityConnect/UnityConnect.bindings.cs index db28653977..502d11e657 100644 --- a/Editor/Mono/UnityConnect/UnityConnect.bindings.cs +++ b/Editor/Mono/UnityConnect/UnityConnect.bindings.cs @@ -283,7 +283,7 @@ internal enum UnityErrorPriority Warning, Info, None - }; + } [Flags] internal enum UnityErrorBehaviour @@ -293,7 +293,7 @@ internal enum UnityErrorBehaviour Hidden, ConsoleOnly, Reconnect - }; + } [Flags] internal enum UnityErrorFilter @@ -302,7 +302,7 @@ internal enum UnityErrorFilter ByParent = 2, ByChild = 4, All = 7 - }; + } private UnityConnect() { @@ -520,6 +520,13 @@ public string GetUserName() return GetUserName_Internal(); } + [NativeMethod("GetUserDisplayName")] + private static extern string GetUserDisplayName_Internal(); + public string GetUserDisplayName() + { + return GetUserDisplayName_Internal(); + } + [NativeMethod("GetAccessToken")] private static extern string GetAccessToken_Internal(); public string GetAccessToken() diff --git a/Editor/Mono/UnityConnect/UnityConnectPrefs.cs b/Editor/Mono/UnityConnect/UnityConnectPrefs.cs index c120fce432..b7539b135c 100644 --- a/Editor/Mono/UnityConnect/UnityConnectPrefs.cs +++ b/Editor/Mono/UnityConnect/UnityConnectPrefs.cs @@ -38,7 +38,7 @@ public void StoreCloudServicePref() public int m_CloudPanelServer; public string m_CloudPanelCustomUrl; public int m_CloudPanelCustomPort; - }; + } protected static CloudPanelPref GetPanelPref(string serviceName) { diff --git a/Editor/Mono/UnityStats.bindings.cs b/Editor/Mono/UnityStats.bindings.cs new file mode 100644 index 0000000000..22d60dfadb --- /dev/null +++ b/Editor/Mono/UnityStats.bindings.cs @@ -0,0 +1,179 @@ +// Unity C# 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; + +namespace UnityEditor +{ + [StructLayout(LayoutKind.Sequential)] + struct StateStats + { + public UInt64 vboUploadBytes; + public UInt64 ibUploadBytes; + public int vboUploads; + public int ibUploads; + public int renderTexture; + } + + [NativeType(CodegenOptions.Force)] + struct ClientStats + { + public int shadowCasters; + } + + [NativeType(CodegenOptions.Force)] + struct DrawStats + { + public int batches; + public int calls; + public UInt64 tris, trisSent; + public UInt64 verts; + public int dynamicBatches; + public int dynamicBatchedCalls; + public UInt64 dynamicBatchedTris; + public UInt64 dynamicBatchedVerts; + public int staticBatches; + public int staticBatchedCalls; + public UInt64 staticBatchedTris; + public UInt64 staticBatchedVerts; + public int instancedBatches; + public int instancedBatchedCalls; + public UInt64 instancedTris; + public UInt64 instancedVerts; + public UInt64 setPassCalls; + + public int usedTextureCount; + public Int64 usedTextureBytes; + } + + [StructLayout(LayoutKind.Sequential)] + struct MemoryStats + { + public int screenWidth, screenHeight; + public int screenFrontBPP, screenBackBPP, screenDepthBPP; + public UInt64 screenBytes; // memory for backbuffer + frontbuffer + public Int64 renderTextureBytes; + } + + //*undocumented* + // Undocumented, but left public. Some people want to figure out draw calls from editor scripts to do some performance checking + // optimizations. + [StaticAccessor("GetGfxDevice().GetFrameStats()", StaticAccessorType.Dot)] + [NativeHeader("Runtime/GfxDevice/GfxDevice.h")] + [NativeHeader("Modules/Audio/Public/AudioManager.h")] + [NativeHeader("Runtime/Graphics/RenderTexture.h")] + public sealed class UnityStats + { + internal extern static DrawStats drawStats { get; } + internal extern static MemoryStats memoryStats { get; } + internal extern static ClientStats clientStats { get; } + internal extern static StateStats stateChanges { get; } + + + // The number of batches rendered this frame. + public static int batches => drawStats.batches; + + // The number of draw calls made this frame. + public static int drawCalls => drawStats.calls; + + // The number of draw calls that got dynamically batched this frame. + public static int dynamicBatchedDrawCalls => drawStats.dynamicBatchedCalls; + + // The number of draw calls that got statically batched this frame. + public static int staticBatchedDrawCalls => drawStats.staticBatchedCalls; + + // The number of draw calls that got instanced this frame. + public static int instancedBatchedDrawCalls => drawStats.instancedBatchedCalls; + + // The number of dynamic batches rendered this frame. + public static int dynamicBatches => drawStats.dynamicBatches; + + // The number of static batches rendered this frame. + public static int staticBatches => drawStats.staticBatches; + + // The number of instanced batches rendered this frame. + public static int instancedBatches => drawStats.instancedBatches; + + // The number of calls to SetPass. + public static int setPassCalls => (int)drawStats.setPassCalls; + + public static int triangles => (int)drawStats.tris; + public static int vertices => (int)drawStats.verts; + + // Temporary API for game view stats window, so it can display proper numbers for >2B cases. Profiling Counters API + // should happen in the future to solve this properly. + internal static long trianglesLong => (long)drawStats.tris; + internal static long verticesLong => (long)drawStats.verts; + + // The number of shadow casters rendered in this frame. + public static int shadowCasters => clientStats.shadowCasters; + + // The number of render texture changes made this frame. + public static int renderTextureChanges => stateChanges.renderTexture; + + [NativeName("ClientFrameTime")] public extern static float frameTime { get; } + [NativeName("RenderFrameTime")] public extern static float renderTime { get; } + + public extern static float audioLevel { [FreeFunction("GetAudioManager().GetMasterGroupLevel")] get; } + public extern static float audioClippingAmount { [FreeFunction("GetAudioManager().GetMasterGroupClippingAmount")] get; } + public extern static float audioDSPLoad { [FreeFunction("GetAudioManager().GetDSPLoad")] get; } + public extern static float audioStreamLoad { [FreeFunction("GetAudioManager().GetStreamLoad")] get; } + + public extern static int renderTextureCount { [FreeFunction("RenderTexture::GetCreatedRenderTextureCount")] get; } + public extern static int renderTextureBytes { [FreeFunction("RenderTexture::GetCreatedRenderTextureBytes")] get; } + + public static int usedTextureMemorySize + { + get + { + return 0; + } + } + + public static int usedTextureCount + { + get + { + return 0; + } + } + + public static string screenRes + { + get + { + var stats = memoryStats; + return $"{memoryStats.screenWidth}x{memoryStats.screenHeight}"; + } + } + + public static int screenBytes => (int)memoryStats.screenBytes; + + public extern static int vboTotal { [FreeFunction("GetGfxDevice().GetTotalBufferCount")] get; } + public extern static int vboTotalBytes { [FreeFunction("GetGfxDevice().GetTotalBufferBytes")] get; } + + public static int vboUploads => stateChanges.vboUploads; + public static int vboUploadBytes => (int)stateChanges.vboUploadBytes; + public static int ibUploads => stateChanges.ibUploads; + public static int ibUploadBytes => (int)stateChanges.ibUploadBytes; + + public extern static int visibleSkinnedMeshes + { + [NativeConditional("ENABLE_PROFILER")] + [FreeFunction("SkinnedMeshRenderer::GetVisibleSkinnedMeshRendererCount")] + [NativeHeader("Runtime/Graphics/Mesh/SkinnedMeshRenderer.h")] + get; + } + + public extern static int visibleAnimations + { + [NativeConditional("ENABLE_PROFILER")] + [FreeFunction("GetAnimationManager().GetUpdatedAnimationCount")] + [NativeHeader("Modules/Animation/AnimationManager.h")] + get; + } + } +} diff --git a/Editor/Mono/Unsupported.bindings.cs b/Editor/Mono/Unsupported.bindings.cs index b34d05aa61..4e617d6af8 100644 --- a/Editor/Mono/Unsupported.bindings.cs +++ b/Editor/Mono/Unsupported.bindings.cs @@ -24,7 +24,7 @@ internal enum DisallowCursorLockReasons Focus = 1 << 2, SizeMove = 1 << 3, ModalDialog = 1 << 4, - }; + } internal static extern Vector3 MakeNiceVector3(Vector3 vector); diff --git a/Editor/Mono/Utils/StateCache.cs b/Editor/Mono/Utils/StateCache.cs index e24a23ac21..cf6f6e0957 100644 --- a/Editor/Mono/Utils/StateCache.cs +++ b/Editor/Mono/Utils/StateCache.cs @@ -60,7 +60,7 @@ public void SetState(string key, T obj) } catch (Exception e) { - Debug.LogError(string.Format("Error saving file {0}. Error: {1}", filePath, e.ToString())); + Debug.LogError(string.Format("Error saving file {0}. Error: {1}", filePath, e)); } m_Cache[key] = obj; @@ -85,7 +85,7 @@ public T GetState(string key) } catch (Exception e) { - Debug.LogError(string.Format("Error loading file {0}. Error: {1}", filePath, e.ToString())); + Debug.LogError(string.Format("Error loading file {0}. Error: {1}", filePath, e)); return default(T); } @@ -95,7 +95,7 @@ public T GetState(string key) } catch (ArgumentException exception) { - Debug.LogError(string.Format("Invalid file content for {0}. Removing file. Error: {1}", filePath, exception.ToString())); + Debug.LogError(string.Format("Invalid file content for {0}. Removing file. Error: {1}", filePath, exception)); RemoveState(key); return default(T); } diff --git a/Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs b/Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs index 9bcd90bb04..c3b98b9de5 100644 --- a/Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs +++ b/Editor/Mono/VersionControl/Common/VCAssetModificationHooks.cs @@ -64,6 +64,11 @@ public static AssetMoveResult OnWillMoveAsset(string from, string to) if (!Provider.enabled || EditorUserSettings.WorkOffline) return AssetMoveResult.DidNotMove; + if (!Provider.PathIsVersioned(from)) + return AssetMoveResult.DidNotMove; + if (!Provider.PathIsVersioned(to)) + return AssetMoveResult.DidNotMove; + if (InternalEditorUtility.isHumanControllingUs && Directory.Exists(from) && !EditorUtility.DisplayDialog("Confirm version control operation", L10n.Tr($"You are about to move or rename a folder that is under version control.\n\nFrom:\t{from}\nTo:\t{to}\n\nAre you sure you want to perform this action?"), "Yes", "No")) { return AssetMoveResult.FailedMove; @@ -109,6 +114,9 @@ public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetO if (!Provider.enabled || EditorUserSettings.WorkOffline) return AssetDeleteResult.DidNotDelete; + if (!Provider.PathIsVersioned(assetPath)) + return AssetDeleteResult.DidNotDelete; + Task task = Provider.Delete(assetPath); task.SetCompletionAction(CompletionAction.UpdatePendingWindow); task.Wait(); diff --git a/Editor/Mono/VersionControl/Common/VCProvider.cs b/Editor/Mono/VersionControl/Common/VCProvider.cs index 76266a378d..e6e1800964 100644 --- a/Editor/Mono/VersionControl/Common/VCProvider.cs +++ b/Editor/Mono/VersionControl/Common/VCProvider.cs @@ -8,10 +8,10 @@ namespace UnityEditor.VersionControl { [System.Flags] - public enum CheckoutMode { Asset = 1, Meta = 2, Both = 3, Exact = 4 }; + public enum CheckoutMode { Asset = 1, Meta = 2, Both = 3, Exact = 4 } [System.Flags] - public enum ResolveMethod { UseMine = 1, UseTheirs = 2, UseMerged }; + public enum ResolveMethod { UseMine = 1, UseTheirs = 2, UseMerged } [System.Flags] public enum MergeMethod @@ -20,16 +20,16 @@ public enum MergeMethod MergeAll = 1, [System.Obsolete("This member is no longer supported (UnityUpgradable) -> MergeNone", true)] MergeNonConflicting = 2 - }; + } [System.Flags] - public enum OnlineState { Updating = 0, Online = 1, Offline = 2 }; + public enum OnlineState { Updating = 0, Online = 1, Offline = 2 } [System.Flags] - public enum RevertMode { Normal = 0, Unchanged = 1, KeepModifications = 2 }; + public enum RevertMode { Normal = 0, Unchanged = 1, KeepModifications = 2 } [System.Flags] - public enum FileMode { None = 0, Binary = 1, Text = 2 }; + public enum FileMode { None = 0, Binary = 1, Text = 2 } public partial class Provider { @@ -184,12 +184,22 @@ static private Task CheckCallbackAndCheckout(AssetList assets, CheckoutMode mode return Internal_Checkout(consolidatedAssetList.ToArray(), mode, changeset); } - static public Task Checkout(AssetList assets, CheckoutMode mode, ChangeSet changeset = null) + static public Task Checkout(AssetList assets, CheckoutMode mode) + { + return Checkout(assets, mode, null); + } + + static public Task Checkout(AssetList assets, CheckoutMode mode, ChangeSet changeset) { return CheckCallbackAndCheckout(assets, mode, changeset); } - static public Task Checkout(string[] assets, CheckoutMode mode, ChangeSet changeset = null) + static public Task Checkout(string[] assets, CheckoutMode mode) + { + return Checkout(assets, mode, null); + } + + static public Task Checkout(string[] assets, CheckoutMode mode, ChangeSet changeset) { var assetList = new AssetList(); foreach (var path in assets) @@ -201,7 +211,12 @@ static public Task Checkout(string[] assets, CheckoutMode mode, ChangeSet change return CheckCallbackAndCheckout(assetList, mode, changeset); } - static public Task Checkout(Object[] assets, CheckoutMode mode, ChangeSet changeset = null) + static public Task Checkout(Object[] assets, CheckoutMode mode) + { + return Checkout(assets, mode, null); + } + + static public Task Checkout(Object[] assets, CheckoutMode mode, ChangeSet changeset) { var assetList = new AssetList(); foreach (var o in assets) @@ -222,7 +237,12 @@ static public bool CheckoutIsValid(Asset asset, CheckoutMode mode) return Internal_CheckoutIsValid(new Asset[] { asset }, mode); } - static public Task Checkout(Asset asset, CheckoutMode mode, ChangeSet changeset = null) + static public Task Checkout(Asset asset, CheckoutMode mode) + { + return Checkout(asset, mode, null); + } + + static public Task Checkout(Asset asset, CheckoutMode mode, ChangeSet changeset) { var assetList = new AssetList(); assetList.Add(asset); @@ -230,7 +250,12 @@ static public Task Checkout(Asset asset, CheckoutMode mode, ChangeSet changeset return CheckCallbackAndCheckout(assetList, mode, changeset); } - static public Task Checkout(string asset, CheckoutMode mode, ChangeSet changeset = null) + static public Task Checkout(string asset, CheckoutMode mode) + { + return Checkout(asset, mode, null); + } + + static public Task Checkout(string asset, CheckoutMode mode, ChangeSet changeset) { var assetList = new AssetList(); assetList.Add(GetAssetByPath(asset)); @@ -238,7 +263,12 @@ static public Task Checkout(string asset, CheckoutMode mode, ChangeSet changeset return CheckCallbackAndCheckout(assetList, mode, changeset); } - static public Task Checkout(UnityEngine.Object asset, CheckoutMode mode, ChangeSet changeset = null) + static public Task Checkout(UnityEngine.Object asset, CheckoutMode mode) + { + return Checkout(asset, mode, null); + } + + static public Task Checkout(UnityEngine.Object asset, CheckoutMode mode, ChangeSet changeset) { var path = AssetDatabase.GetAssetPath(asset); var vcasset = GetAssetByPath(path); @@ -268,7 +298,7 @@ static internal bool PromptAndCheckoutIfNeeded(string[] assets, string promptIfC var changesetTask = CheckAndCreateUserSuppliedChangeSet(changesetID, changesetDescription, ref changeset); if (changesetTask != null) { - Debug.LogError("Tried to create/rename remote ChangeSet to match the one specified in user-supplied callback but failed with error code: " + changesetTask.resultCode.ToString()); + Debug.LogError("Tried to create/rename remote ChangeSet to match the one specified in user-supplied callback but failed with error code: " + changesetTask.resultCode); return false; } var newAssets = new List(); diff --git a/Editor/Mono/VersionControl/UI/VCListControl.cs b/Editor/Mono/VersionControl/UI/VCListControl.cs index a84b24137b..e9feff68fa 100644 --- a/Editor/Mono/VersionControl/UI/VCListControl.cs +++ b/Editor/Mono/VersionControl/UI/VCListControl.cs @@ -269,7 +269,7 @@ public ListItem Add(ListItem parent, string name, ChangeSet change) insert.Add(item); // Create a lookup table - pathSearch[c_changeKeyPrefix + change.id.ToString()] = item; + pathSearch[c_changeKeyPrefix + change.id] = item; return item; } @@ -973,7 +973,7 @@ internal bool IsSelected(ListItem item) if (item.Asset != null) return selectList.ContainsKey(item.Asset.path.ToLower()); if (item.Change != null) - return selectList.ContainsKey(c_changeKeyPrefix + item.Change.id.ToString()); + return selectList.ContainsKey(c_changeKeyPrefix + item.Change.id); return false; } @@ -1027,7 +1027,7 @@ public void SelectedSet(ListItem item) } else if (item.Change != null) { - selectList[c_changeKeyPrefix + item.Change.id.ToString()] = item; + selectList[c_changeKeyPrefix + item.Change.id] = item; } } @@ -1142,7 +1142,7 @@ public void SelectedAdd(ListItem item) void SelectedRemove(ListItem item) { - string name = item.Asset != null ? item.Asset.path.ToLower() : c_changeKeyPrefix + item.Change.id.ToString(); + string name = item.Asset != null ? item.Asset.path.ToLower() : c_changeKeyPrefix + item.Change.id; // Remove item selectList.Remove(name); @@ -1311,7 +1311,7 @@ internal string DisplayName(ListItem item) { if (item.Change != null) { - name = item.Change.id.ToString() + " " + item.Change.description; + name = item.Change.id + " " + item.Change.description; } } diff --git a/Editor/Mono/VersionControl/UI/VCMenuPending.cs b/Editor/Mono/VersionControl/UI/VCMenuPending.cs index f324d0a51a..3b839ea279 100644 --- a/Editor/Mono/VersionControl/UI/VCMenuPending.cs +++ b/Editor/Mono/VersionControl/UI/VCMenuPending.cs @@ -37,7 +37,7 @@ static void Revert(int userData) //[MenuItem ("CONTEXT/Pending/Revert Unchanged", true, 201)] static bool RevertUnchangedTest(int userData) { - return Provider.RevertIsValid(ListControl.FromID(userData).SelectedAssets, RevertMode.Normal); + return Provider.RevertIsValid(ListControl.FromID(userData).SelectedAssets, RevertMode.Unchanged); } //[MenuItem ("CONTEXT/Pending/Revert Unchanged", false, 201)] diff --git a/Editor/Mono/VersionControl/UI/VCMenuProject.cs b/Editor/Mono/VersionControl/UI/VCMenuProject.cs index 5bd45a8543..efce119452 100644 --- a/Editor/Mono/VersionControl/UI/VCMenuProject.cs +++ b/Editor/Mono/VersionControl/UI/VCMenuProject.cs @@ -153,7 +153,7 @@ static void Revert(ShortcutArguments args) static bool RevertUnchangedTest(MenuCommand cmd) { AssetList selected = Provider.GetAssetListFromSelection(); - return Provider.enabled && Provider.RevertIsValid(selected, RevertMode.Normal); + return Provider.enabled && Provider.RevertIsValid(selected, RevertMode.Unchanged); } // Called from native class VCSAssetMenuHandler as "Assets/Version Control/Revert Unchanged" menu handler diff --git a/Editor/Mono/VersionControl/UI/VCWindowPending.cs b/Editor/Mono/VersionControl/UI/VCWindowPending.cs index 30483d9609..e15a994f33 100644 --- a/Editor/Mono/VersionControl/UI/VCWindowPending.cs +++ b/Editor/Mono/VersionControl/UI/VCWindowPending.cs @@ -406,7 +406,6 @@ void OnGUI() CreateResources(); - Event e = Event.current; float toolBarHeight = EditorStyles.toolbar.fixedHeight; bool refresh = false; @@ -420,7 +419,7 @@ void OnGUI() int incomingChangesetCount = incomingList.Root == null ? 0 : incomingList.Root.ChildCount; m_ShowIncoming = !GUILayout.Toggle(!m_ShowIncoming, "Outgoing", EditorStyles.toolbarButton); - GUIContent cont = GUIContent.Temp("Incoming" + (incomingChangesetCount == 0 ? "" : " (" + incomingChangesetCount.ToString() + ")")); + GUIContent cont = GUIContent.Temp("Incoming" + (incomingChangesetCount == 0 ? "" : " (" + incomingChangesetCount + ")")); m_ShowIncoming = GUILayout.Toggle(m_ShowIncoming, cont, EditorStyles.toolbarButton); if (EditorGUI.EndChangeCheck()) @@ -455,11 +454,8 @@ void OnGUI() GUIUtility.ExitGUI(); } - Color origColor = GUI.color; - GUI.color = new Color(1, 1, 1, 1 * .5f); bool refreshButtonClicked = GUILayout.Button(refreshIcon, EditorStyles.toolbarButton); refresh = refresh || refreshButtonClicked; - GUI.color = origColor; if (refresh) { @@ -481,7 +477,6 @@ void OnGUI() if (EditorUserSettings.WorkOffline) { - Color tmpColor = GUI.color; GUI.color = new Color(0.8f, 0.5f, 0.5f); rect.height = toolBarHeight; GUILayout.BeginArea(rect); diff --git a/Editor/Mono/VersionControl/UI/VCWindowResolve.cs b/Editor/Mono/VersionControl/UI/VCWindowResolve.cs index 3eb049cb07..7ded8b41b6 100644 --- a/Editor/Mono/VersionControl/UI/VCWindowResolve.cs +++ b/Editor/Mono/VersionControl/UI/VCWindowResolve.cs @@ -88,6 +88,17 @@ void RefreshList() Repaint(); } + void SimpleMerge(ResolveMethod resolveMethod) + { + AssetList selAssets = resolveList.SelectedAssets; + Provider.Resolve(selAssets, resolveMethod).Wait(); + + DoOpen(assetList); + + if (assetList.Count == 0) + Close(); + } + void OnGUI() { cancelled = false; @@ -110,18 +121,12 @@ void OnGUI() GUILayout.Label("Resolve selection by:"); if (GUILayout.Button("using local version")) { - AssetList selAssets = resolveList.SelectedAssets; - Provider.Resolve(selAssets, ResolveMethod.UseMine).Wait(); - AssetDatabase.Refresh(); - Close(); + SimpleMerge(ResolveMethod.UseMine); } if (GUILayout.Button("using incoming version")) { - AssetList selAssets = resolveList.SelectedAssets; - Provider.Resolve(selAssets, ResolveMethod.UseTheirs).Wait(); - AssetDatabase.Refresh(); - Close(); + SimpleMerge(ResolveMethod.UseTheirs); } MergeMethod mergeMethod = MergeMethod.MergeNone; diff --git a/Editor/Mono/VersionControl/VCMessage.bindings.cs b/Editor/Mono/VersionControl/VCMessage.bindings.cs index 7ed3af48c8..1abed821a2 100644 --- a/Editor/Mono/VersionControl/VCMessage.bindings.cs +++ b/Editor/Mono/VersionControl/VCMessage.bindings.cs @@ -23,7 +23,7 @@ public enum Severity Info = 2, Warning = 3, Error = 4 - }; + } // The bindings generator will set the instance pointer in this field IntPtr m_Self; diff --git a/Editor/Mono/View.cs b/Editor/Mono/View.cs index b4efc75a90..0d3b87b56f 100644 --- a/Editor/Mono/View.cs +++ b/Editor/Mono/View.cs @@ -32,7 +32,7 @@ internal string DebugHierarchy(int level) { prefix = prefix + " "; } - s = s + prefix + this.ToString() + " p:" + position; + s = s + prefix + this + " p:" + position; if (children.Length > 0) { s += " {\n"; diff --git a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs b/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs index 394ea49a36..7c08b48b3d 100644 --- a/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs +++ b/Editor/Mono/VisualStudioIntegration/UnityVSSupport.cs @@ -336,7 +336,7 @@ public static void ScriptEditorChanged(string editorPath) // We reload the domain because selecting a different editor requires loading a different UnityVS Initialize(editorPath); - InternalEditorUtility.RequestScriptReload(); + EditorUtility.RequestScriptReload(); } public static string GetAboutWindowLabel() diff --git a/External/JsonParsers/MiniJson/MiniJSON.cs b/External/JsonParsers/MiniJson/MiniJSON.cs index f72afda7b7..e7e5be0e31 100644 --- a/External/JsonParsers/MiniJson/MiniJSON.cs +++ b/External/JsonParsers/MiniJson/MiniJSON.cs @@ -117,7 +117,7 @@ enum TOKEN TRUE, FALSE, NULL - }; + } StringReader json; diff --git a/External/MonoBleedingEdge/builds/monodistribution/lib/mono/4.5/Facades/netstandard.dll b/External/MonoBleedingEdge/builds/monodistribution/lib/mono/4.5/Facades/netstandard.dll index 73897a6699..9350e84c4a 100644 Binary files a/External/MonoBleedingEdge/builds/monodistribution/lib/mono/4.5/Facades/netstandard.dll and b/External/MonoBleedingEdge/builds/monodistribution/lib/mono/4.5/Facades/netstandard.dll differ diff --git a/External/Unity.Compiler.Client/Unity.CompilationPipeline.Common.dll b/External/Unity.Compiler.Client/Unity.CompilationPipeline.Common.dll index b90e62f25e..d20bef6cec 100644 Binary files a/External/Unity.Compiler.Client/Unity.CompilationPipeline.Common.dll and b/External/Unity.Compiler.Client/Unity.CompilationPipeline.Common.dll differ diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000000..2303b574a4 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1 @@ +For terms of use, see https://unity3d.com/legal/licenses/Unity_Reference_Only_License diff --git a/Modules/AR/ScriptBindings/ARBackgroundRenderer.cs b/Modules/AR/ScriptBindings/ARBackgroundRenderer.cs index 568c3453c1..54c32681ef 100644 --- a/Modules/AR/ScriptBindings/ARBackgroundRenderer.cs +++ b/Modules/AR/ScriptBindings/ARBackgroundRenderer.cs @@ -12,7 +12,7 @@ public enum ARRenderMode { StandardBackground, MaterialAsBackground - }; + } public partial class ARBackgroundRenderer { @@ -57,7 +57,7 @@ public Texture backgroundTexture } set { - if (m_BackgroundTexture = value) + if (m_BackgroundTexture == value) return; RemoveCommandBuffersIfNeeded(); diff --git a/Modules/AndroidJNI/AndroidJava.cs b/Modules/AndroidJNI/AndroidJava.cs index 8690e5c33c..4c01f8b817 100644 --- a/Modules/AndroidJNI/AndroidJava.cs +++ b/Modules/AndroidJNI/AndroidJava.cs @@ -155,7 +155,7 @@ public virtual int hashCode() public virtual string toString() { - return this.ToString() + " "; + return this + " "; } internal IntPtr proxyObject = IntPtr.Zero; @@ -343,7 +343,7 @@ protected void DebugPrint(string call, string methodName, string signature, obje sb.Append(", "); sb.Append(obj == null ? "" : obj.GetType().ToString()); } - Debug.Log(call + "(\"" + methodName + "\"" + sb.ToString() + ") = " + signature); + Debug.Log(call + "(\"" + methodName + "\"" + sb + ") = " + signature); } //=================================================================== diff --git a/Modules/Animation/ScriptBindings/Animation.bindings.cs b/Modules/Animation/ScriptBindings/Animation.bindings.cs new file mode 100644 index 0000000000..ec2ce89c05 --- /dev/null +++ b/Modules/Animation/ScriptBindings/Animation.bindings.cs @@ -0,0 +1,293 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections; +using System.Runtime.InteropServices; +using UnityEngine.Bindings; +using UnityEngine.Scripting; +using uei = UnityEngine.Internal; + +namespace UnityEngine +{ + // Used by Animation.Play function. + public enum PlayMode + { + // Will stop all animations that were started in the same layer. This is the default when playing animations. + StopSameLayer = 0, + // Will stop all animations that were started with this component before playing + StopAll = 4, + } + + // Used by Animation.Play function. + public enum QueueMode + { + // Will start playing after all other animations have stopped playing + CompleteOthers = 0, + // Starts playing immediately. This can be used if you just want to quickly create a duplicate animation. + PlayNow = 2 + } + + // Used by Animation.Play function. + public enum AnimationBlendMode + { + // Animations will be blended + Blend = 0, + // Animations will be added + Additive = 1 + } + + // considered deprecated + public enum AnimationPlayMode { Stop = 0, Queue = 1, Mix = 2 } + + // This enum controlls culling of Animation component. + public enum AnimationCullingType + { + // Animation culling is disabled - object is animated even when offscreen. + AlwaysAnimate = 0, + // Animation is disabled when renderers are not visible. + BasedOnRenderers = 1, + + // Animation is disabled when localBounds are not visible. + [System.Obsolete("Enum member AnimatorCullingMode.BasedOnClipBounds has been deprecated. Use AnimationCullingType.AlwaysAnimate or AnimationCullingType.BasedOnRenderers instead")] + BasedOnClipBounds = 2, + // Animation is disabled when localBounds are not visible. + [System.Obsolete("Enum member AnimatorCullingMode.BasedOnUserBounds has been deprecated. Use AnimationCullingType.AlwaysAnimate or AnimationCullingType.BasedOnRenderers instead")] + BasedOnUserBounds = 3 + } + + internal enum AnimationEventSource + { + NoSource = 0, + Legacy = 1, + Animator = 2, + } + + // The animation component is used to play back animations. + [NativeHeader("Modules/Animation/Animation.h")] + public sealed class Animation : Behaviour, IEnumerable + { + public extern AnimationClip clip { get; set; } + public extern bool playAutomatically { get; set; } + public extern WrapMode wrapMode { get; set; } + + public extern void Stop(); + public void Stop(string name) { StopNamed(name); } + [NativeName("Stop")] private extern void StopNamed(string name); + public extern void Rewind(); + public void Rewind(string name) { RewindNamed(name); } + [NativeName("Rewind")] private extern void RewindNamed(string name); + + public extern void Sample(); + public extern bool isPlaying { [NativeName("IsPlaying")] get; } + public extern bool IsPlaying(string name); + + public AnimationState this[string name] { get { return GetState(name); } } + + [uei.ExcludeFromDocs] public bool Play() { return Play(PlayMode.StopSameLayer); } + public bool Play([uei.DefaultValue("PlayMode.StopSameLayer")] PlayMode mode) { return PlayDefaultAnimation(mode); } + [NativeName("Play")] extern private bool PlayDefaultAnimation(PlayMode mode); + + [uei.ExcludeFromDocs] public bool Play(string animation) { return Play(animation, PlayMode.StopSameLayer); } + extern public bool Play(string animation, [uei.DefaultValue("PlayMode.StopSameLayer")] PlayMode mode); + + [uei.ExcludeFromDocs] public void CrossFade(string animation) { CrossFade(animation, 0.3f); } + [uei.ExcludeFromDocs] public void CrossFade(string animation, float fadeLength) { CrossFade(animation, fadeLength, PlayMode.StopSameLayer); } + extern public void CrossFade(string animation, [uei.DefaultValue("0.3F")] float fadeLength, [uei.DefaultValue("PlayMode.StopSameLayer")] PlayMode mode); + + [uei.ExcludeFromDocs] public void Blend(string animation) { Blend(animation, 1.0f); } + [uei.ExcludeFromDocs] public void Blend(string animation, float targetWeight) { Blend(animation, targetWeight, 0.3f); } + extern public void Blend(string animation, [uei.DefaultValue("1.0F")] float targetWeight, [uei.DefaultValue("0.3F")] float fadeLength); + + [uei.ExcludeFromDocs] public AnimationState CrossFadeQueued(string animation) { return CrossFadeQueued(animation, 0.3F); } + [uei.ExcludeFromDocs] public AnimationState CrossFadeQueued(string animation, float fadeLength) { return CrossFadeQueued(animation, fadeLength, QueueMode.CompleteOthers); } + [uei.ExcludeFromDocs] public AnimationState CrossFadeQueued(string animation, float fadeLength, QueueMode queue) { return CrossFadeQueued(animation, fadeLength, queue, PlayMode.StopSameLayer); } + [FreeFunction("AnimationBindings::CrossFadeQueuedImpl", HasExplicitThis = true)] + extern public AnimationState CrossFadeQueued(string animation, [uei.DefaultValue("0.3F")] float fadeLength, [uei.DefaultValue("QueueMode.CompleteOthers")] QueueMode queue, [uei.DefaultValue("PlayMode.StopSameLayer")] PlayMode mode); + + [uei.ExcludeFromDocs] public AnimationState PlayQueued(string animation) { return PlayQueued(animation, QueueMode.CompleteOthers); } + [uei.ExcludeFromDocs] public AnimationState PlayQueued(string animation, QueueMode queue) { return PlayQueued(animation, queue, PlayMode.StopSameLayer); } + [FreeFunction("AnimationBindings::PlayQueuedImpl", HasExplicitThis = true)] + extern public AnimationState PlayQueued(string animation, [uei.DefaultValue("QueueMode.CompleteOthers")] QueueMode queue, [uei.DefaultValue("PlayMode.StopSameLayer")] PlayMode mode); + + public void AddClip(AnimationClip clip, string newName) { AddClip(clip, newName, Int32.MinValue, Int32.MaxValue); } + [uei.ExcludeFromDocs] public void AddClip(AnimationClip clip, string newName, int firstFrame, int lastFrame) { AddClip(clip, newName, firstFrame, lastFrame, false); } + extern public void AddClip(AnimationClip clip, string newName, int firstFrame, int lastFrame, [uei.DefaultValue("false")] bool addLoopFrame); + + extern public void RemoveClip(AnimationClip clip); + + public void RemoveClip(string clipName) { RemoveClipNamed(clipName); } + [NativeName("RemoveClip")] extern private void RemoveClipNamed(string clipName); + + extern public int GetClipCount(); + + [System.Obsolete("use PlayMode instead of AnimationPlayMode.")] + public bool Play(AnimationPlayMode mode) { return PlayDefaultAnimation((PlayMode)mode); } + [System.Obsolete("use PlayMode instead of AnimationPlayMode.")] + public bool Play(string animation, AnimationPlayMode mode) { return Play(animation, (PlayMode)mode); } + + extern public void SyncLayer(int layer); + + public IEnumerator GetEnumerator() { return new Animation.Enumerator(this); } + + private sealed partial class Enumerator : IEnumerator + { + Animation m_Outer; + int m_CurrentIndex = -1; + + internal Enumerator(Animation outer) { m_Outer = outer; } + public object Current + { + get { return m_Outer.GetStateAtIndex(m_CurrentIndex); } + } + public bool MoveNext() + { + int childCount = m_Outer.GetStateCount(); + m_CurrentIndex++; + return m_CurrentIndex < childCount; + } + + public void Reset() { m_CurrentIndex = -1; } + } + + [FreeFunction("AnimationBindings::GetState", HasExplicitThis = true)] + extern internal AnimationState GetState(string name); + + [FreeFunction("AnimationBindings::GetStateAtIndex", HasExplicitThis = true, ThrowsException = true)] + extern internal AnimationState GetStateAtIndex(int index); + + [NativeName("GetAnimationStateCount")] extern internal int GetStateCount(); + + public AnimationClip GetClip(string name) + { + AnimationState state = GetState(name); + if (state) + return state.clip; + else + return null; + } + + extern public bool animatePhysics { get; set; } + + [System.Obsolete("Use cullingType instead")] + public extern bool animateOnlyIfVisible + { + [FreeFunction("AnimationBindings::GetAnimateOnlyIfVisible", HasExplicitThis = true)] get; + [FreeFunction("AnimationBindings::SetAnimateOnlyIfVisible", HasExplicitThis = true)] set; + } + + extern public AnimationCullingType cullingType { get; set; } + extern public Bounds localBounds { [NativeName("GetLocalAABB")] get; [NativeName("SetLocalAABB")] set; } + } + + [NativeHeader("Modules/Animation/AnimationState.h")] + [UsedByNativeCode] + public sealed class AnimationState : TrackedReference + { + extern public bool enabled { get; set; } + extern public float weight { get; set; } + extern public WrapMode wrapMode { get; set; } + extern public float time { get; set; } + extern public float normalizedTime { get; set; } + extern public float speed { get; set; } + extern public float normalizedSpeed { get; set; } + extern public float length { get; } + extern public int layer { get; set; } + extern public AnimationClip clip { get; } + extern public string name { get; set; } + extern public AnimationBlendMode blendMode { get; set; } + + [uei.ExcludeFromDocs] public void AddMixingTransform(Transform mix) { AddMixingTransform(mix, true); } + extern public void AddMixingTransform(Transform mix, [uei.DefaultValue("true")] bool recursive); + + extern public void RemoveMixingTransform(Transform mix); + } + + [System.Serializable] + [StructLayout(LayoutKind.Sequential)] + [RequiredByNativeCode] + public sealed class AnimationEvent + { + internal float m_Time; + internal string m_FunctionName; + internal string m_StringParameter; + internal Object m_ObjectReferenceParameter; + internal float m_FloatParameter; + internal int m_IntParameter; + + internal int m_MessageOptions; + internal AnimationEventSource m_Source; + internal AnimationState m_StateSender; + internal AnimatorStateInfo m_AnimatorStateInfo; + internal AnimatorClipInfo m_AnimatorClipInfo; + + public AnimationEvent() + { + m_Time = 0.0f; + m_FunctionName = ""; + m_StringParameter = ""; + m_ObjectReferenceParameter = null; + m_FloatParameter = 0.0f; + m_IntParameter = 0; + m_MessageOptions = 0; + m_Source = AnimationEventSource.NoSource; + m_StateSender = null; + } + + [System.Obsolete("Use stringParameter instead")] + public string data { get { return m_StringParameter; } set { m_StringParameter = value; } } + + public string stringParameter { get { return m_StringParameter; } set { m_StringParameter = value; } } + public float floatParameter { get { return m_FloatParameter; } set { m_FloatParameter = value; } } + public int intParameter { get { return m_IntParameter; } set { m_IntParameter = value; } } + public Object objectReferenceParameter { get { return m_ObjectReferenceParameter; } set { m_ObjectReferenceParameter = value; } } + public string functionName { get { return m_FunctionName; } set { m_FunctionName = value; } } + public float time { get { return m_Time; } set { m_Time = value; } } + public SendMessageOptions messageOptions { get { return (SendMessageOptions)m_MessageOptions; } set { m_MessageOptions = (int)value; } } + + public bool isFiredByLegacy { get { return m_Source == AnimationEventSource.Legacy; } } + public bool isFiredByAnimator { get { return m_Source == AnimationEventSource.Animator; } } + + public AnimationState animationState + { + get + { + if (!isFiredByLegacy) + Debug.LogError("AnimationEvent was not fired by Animation component, you shouldn't use AnimationEvent.animationState"); + return m_StateSender; + } + } + + public AnimatorStateInfo animatorStateInfo + { + get + { + if (!isFiredByAnimator) + Debug.LogError("AnimationEvent was not fired by Animator component, you shouldn't use AnimationEvent.animatorStateInfo"); + return m_AnimatorStateInfo; + } + } + + public AnimatorClipInfo animatorClipInfo + { + get + { + if (!isFiredByAnimator) + Debug.LogError("AnimationEvent was not fired by Animator component, you shouldn't use AnimationEvent.animatorClipInfo"); + return m_AnimatorClipInfo; + } + } + + internal int GetHash() + { + unchecked + { + int hash = 0; + hash = functionName.GetHashCode(); + hash = 33 * hash + time.GetHashCode(); + return hash; + } + } + } +} diff --git a/Modules/Animation/ScriptBindings/AnimationClip.bindings.cs b/Modules/Animation/ScriptBindings/AnimationClip.bindings.cs index 08a9f68d5f..f3303527be 100644 --- a/Modules/Animation/ScriptBindings/AnimationClip.bindings.cs +++ b/Modules/Animation/ScriptBindings/AnimationClip.bindings.cs @@ -9,8 +9,7 @@ namespace UnityEngine // Stores keyframe based animations. [NativeHeader("Modules/Animation/ScriptBindings/AnimationClip.bindings.h")] [NativeType("Modules/Animation/AnimationClip.h")] - - public sealed partial class AnimationClip : Motion + public sealed class AnimationClip : Motion { // Creates a new animation clip public AnimationClip() @@ -109,23 +108,31 @@ extern public bool hasRootCurves get; } - // Adds an animation event to the clip. - //[FreeFunction("AnimationClipBindings::Internal_AddEvent", HasExplicitThis = true)] - //extern public void AddEvent([NotNull] AnimationEvent evt); - - //Retrieves all animation events associated with the animation clip - //extern public AnimationEvent[] events - //{ - // [FreeFunction("AnimationClipBindings::Internal_GetEvents", HasExplicitThis = true)] - // get; - // [FreeFunction("AnimationClipBindings::Internal_SetEvents", HasExplicitThis = true)] - // set; - //} - internal extern bool hasRootMotion { [FreeFunction(Name = "AnimationClipBindings::Internal_GetHasRootMotion", HasExplicitThis = true)] get; } + + public void AddEvent(AnimationEvent evt) + { + if (evt == null) + throw new ArgumentNullException("evt"); + AddEventInternal(evt); + } + + [FreeFunction(Name = "AnimationClipBindings::AddEventInternal", HasExplicitThis = true)] + extern private void AddEventInternal(System.Object evt); + + // Retrieves all animation events associated with the animation clip + public AnimationEvent[] events + { + get { return (AnimationEvent[])GetEventsInternal(); } + set { SetEventsInternal(value); } + } + [FreeFunction(Name = "AnimationClipBindings::SetEventsInternal", HasExplicitThis = true)] + extern private void SetEventsInternal(System.Array value); + [FreeFunction(Name = "AnimationClipBindings::GetEventsInternal", HasExplicitThis = true)] + extern private System.Array GetEventsInternal(); } } diff --git a/Modules/Animation/ScriptBindings/AnimationPlayableExtensions.bindings.cs b/Modules/Animation/ScriptBindings/AnimationPlayableExtensions.bindings.cs index 356401eb41..f5574314ae 100644 --- a/Modules/Animation/ScriptBindings/AnimationPlayableExtensions.bindings.cs +++ b/Modules/Animation/ScriptBindings/AnimationPlayableExtensions.bindings.cs @@ -24,5 +24,5 @@ public static void SetAnimatedProperties(this U playable, AnimationClip clip) [NativeThrows] extern internal static void SetAnimatedPropertiesInternal(ref PlayableHandle playable, AnimationClip animatedProperties); - }; + } } diff --git a/Modules/Animation/ScriptBindings/AnimationPlayableOutputExtensions.bindings.cs b/Modules/Animation/ScriptBindings/AnimationPlayableOutputExtensions.bindings.cs index f3439bd196..1462265e33 100644 --- a/Modules/Animation/ScriptBindings/AnimationPlayableOutputExtensions.bindings.cs +++ b/Modules/Animation/ScriptBindings/AnimationPlayableOutputExtensions.bindings.cs @@ -51,5 +51,5 @@ public static void SetSortingOrder(this AnimationPlayableOutput output, ushort s extern private static int InternalGetSortingOrder(PlayableOutputHandle output); [NativeThrows] extern private static void InternalSetSortingOrder(PlayableOutputHandle output, int sortingOrder); - }; + } } diff --git a/Modules/Animation/ScriptBindings/HumanPoseHandler.bindings.cs b/Modules/Animation/ScriptBindings/HumanPoseHandler.bindings.cs index 3ccacda487..2542a531f2 100644 --- a/Modules/Animation/ScriptBindings/HumanPoseHandler.bindings.cs +++ b/Modules/Animation/ScriptBindings/HumanPoseHandler.bindings.cs @@ -8,6 +8,9 @@ using UnityEngine.Scripting; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Collections.Generic; +using Unity.Collections; +using Unity.Collections.LowLevel.Unsafe; namespace UnityEngine { @@ -46,7 +49,10 @@ public class HumanPoseHandler : IDisposable internal IntPtr m_Ptr; [FreeFunction("AnimationBindings::CreateHumanPoseHandler")] - extern private static IntPtr Internal_Create(Avatar avatar, Transform root); + extern private static IntPtr Internal_CreateFromRoot(Avatar avatar, Transform root); + + [FreeFunction("AnimationBindings::CreateHumanPoseHandler", IsThreadSafe = true)] + extern private static IntPtr Internal_CreateFromJointPaths(Avatar avatar, string[] jointPaths); [FreeFunction("AnimationBindings::DestroyHumanPoseHandler")] extern private static void Internal_Destroy(IntPtr ptr); @@ -54,6 +60,18 @@ public class HumanPoseHandler : IDisposable extern private void GetHumanPose(out Vector3 bodyPosition, out Quaternion bodyRotation, [Out] float[] muscles); extern private void SetHumanPose(ref Vector3 bodyPosition, ref Quaternion bodyRotation, float[] muscles); + [ThreadSafe] + extern private void GetInternalHumanPose(out Vector3 bodyPosition, out Quaternion bodyRotation, [Out] float[] muscles); + + [ThreadSafe] + extern private void SetInternalHumanPose(ref Vector3 bodyPosition, ref Quaternion bodyRotation, float[] muscles); + + [ThreadSafe] + extern private unsafe void GetInternalAvatarPose(void* avatarPose, int avatarPoseLength); + + [ThreadSafe] + extern private unsafe void SetInternalAvatarPose(void* avatarPose, int avatarPoseLength); + public void Dispose() { if (m_Ptr != IntPtr.Zero) @@ -81,7 +99,26 @@ public HumanPoseHandler(Avatar avatar, Transform root) if (!avatar.isHuman) throw new ArgumentException("HumanPoseHandler avatar is not human"); - m_Ptr = Internal_Create(avatar, root); + m_Ptr = Internal_CreateFromRoot(avatar, root); + } + + public HumanPoseHandler(Avatar avatar, string[] jointPaths) + { + m_Ptr = IntPtr.Zero; + + if (jointPaths == null) + throw new ArgumentNullException("HumanPoseHandler jointPaths array is null"); + + if (avatar == null) + throw new ArgumentNullException("HumanPoseHandler avatar is null"); + + if (!avatar.isValid) + throw new ArgumentException("HumanPoseHandler avatar is invalid"); + + if (!avatar.isHuman) + throw new ArgumentException("HumanPoseHandler avatar is not human"); + + m_Ptr = Internal_CreateFromJointPaths(avatar, jointPaths); } public void GetHumanPose(ref HumanPose humanPose) @@ -101,5 +138,39 @@ public void SetHumanPose(ref HumanPose humanPose) humanPose.Init(); SetHumanPose(ref humanPose.bodyPosition, ref humanPose.bodyRotation, humanPose.muscles); } + + public void GetInternalHumanPose(ref HumanPose humanPose) + { + if (m_Ptr == IntPtr.Zero) + throw new NullReferenceException("HumanPoseHandler is not initialized properly"); + + humanPose.Init(); + GetInternalHumanPose(out humanPose.bodyPosition, out humanPose.bodyRotation, humanPose.muscles); + } + + public void SetInternalHumanPose(ref HumanPose humanPose) + { + if (m_Ptr == IntPtr.Zero) + throw new NullReferenceException("HumanPoseHandler is not initialized properly"); + + humanPose.Init(); + SetInternalHumanPose(ref humanPose.bodyPosition, ref humanPose.bodyRotation, humanPose.muscles); + } + + public unsafe void GetInternalAvatarPose(NativeArray avatarPose) + { + if (m_Ptr == IntPtr.Zero) + throw new NullReferenceException("HumanPoseHandler is not initialized properly"); + + GetInternalAvatarPose(avatarPose.GetUnsafePtr(), avatarPose.Length); + } + + public unsafe void SetInternalAvatarPose(NativeArray avatarPose) + { + if (m_Ptr == IntPtr.Zero) + throw new NullReferenceException("HumanPoseHandler is not initialized properly"); + + SetInternalAvatarPose(avatarPose.GetUnsafeReadOnlyPtr(), avatarPose.Length); + } } } diff --git a/Modules/AssetBundle/Managed/AssetBundle.bindings.cs b/Modules/AssetBundle/Managed/AssetBundle.bindings.cs index f7cfe65ab3..9c818e92d8 100644 --- a/Modules/AssetBundle/Managed/AssetBundle.bindings.cs +++ b/Modules/AssetBundle/Managed/AssetBundle.bindings.cs @@ -28,7 +28,7 @@ public enum AssetBundleLoadResult FailedDeleteRecompressionTarget, RecompressionTargetIsLoaded, RecompressionTargetExistsButNotArchive - }; + } [NativeHeader("Modules/AssetBundle/Public/AssetBundleLoadFromFileAsyncOperation.h")] [NativeHeader("Modules/AssetBundle/Public/AssetBundleLoadFromMemoryAsyncOperation.h")] diff --git a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs index 6740f25314..b0cc3e74d5 100644 --- a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs +++ b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabase.bindings.cs @@ -65,6 +65,10 @@ public partial class AssetDatabase extern internal static void RegisterAssetFolder(string path, bool immutable, string guid); extern internal static void UnregisterAssetFolder(string path); + // used by integration tests + extern internal static void RegisterRedirectedAssetFolder(string mountPoint, string folder, string physicalPath, bool immutable, string guid); + extern internal static void UnregisterRedirectedAssetFolder(string mountPoint, string folder); + // returns true if the folder is known by the asset database // rootFolder is true if the path is a registered root folder // immutable is true when the root of the path was registered with the immutable flag (e.g. shared package) @@ -292,72 +296,66 @@ public static void ExportPackage(string assetPathName, string fileName, ExportPa extern internal static string GetUniquePathNameAtSelectedPath(string fileName); - [System.Obsolete("AssetDatabase.IsOpenForEdit without StatusQueryOptions has been deprecated. Use the version with StatusQueryOptions instead. This will always request the cached status (StatusQueryOptions.UseCachedIfPossible)")] - public static bool IsOpenForEdit(UnityEngine.Object assetObject) + [uei.ExcludeFromDocs] public static bool IsOpenForEdit(UnityEngine.Object assetObject) { return IsOpenForEdit(assetObject, StatusQueryOptions.UseCachedIfPossible); } - public static bool IsOpenForEdit(UnityEngine.Object assetObject, StatusQueryOptions StatusQueryOptions) + public static bool IsOpenForEdit(UnityEngine.Object assetObject, [uei.DefaultValue("StatusQueryOptions.UseCachedIfPossible")] StatusQueryOptions statusOptions) { string assetPath = GetAssetOrScenePath(assetObject); - return IsOpenForEdit(assetPath, StatusQueryOptions); + return IsOpenForEdit(assetPath, statusOptions); } - [System.Obsolete("AssetDatabase.IsOpenForEdit without StatusQueryOptions has been deprecated. Use the version with StatusQueryOptions instead. This will always request the cached status (StatusQueryOptions.UseCachedIfPossible)")] - public static bool IsOpenForEdit(string assetOrMetaFilePath) + [uei.ExcludeFromDocs] public static bool IsOpenForEdit(string assetOrMetaFilePath) { return IsOpenForEdit(assetOrMetaFilePath, StatusQueryOptions.UseCachedIfPossible); } - public static bool IsOpenForEdit(string assetOrMetaFilePath, StatusQueryOptions StatusQueryOptions) + public static bool IsOpenForEdit(string assetOrMetaFilePath, [uei.DefaultValue("StatusQueryOptions.UseCachedIfPossible")] StatusQueryOptions statusOptions) { string message; - return IsOpenForEdit(assetOrMetaFilePath, out message, StatusQueryOptions); + return IsOpenForEdit(assetOrMetaFilePath, out message, statusOptions); } - [System.Obsolete("AssetDatabase.IsOpenForEdit without StatusQueryOptions has been deprecated. Use the version with StatusQueryOptions instead. This will always request the cached status (StatusQueryOptions.UseCachedIfPossible)")] - public static bool IsOpenForEdit(UnityEngine.Object assetObject, out string message) + [uei.ExcludeFromDocs] public static bool IsOpenForEdit(UnityEngine.Object assetObject, out string message) { return IsOpenForEdit(assetObject, out message, StatusQueryOptions.UseCachedIfPossible); } - public static bool IsOpenForEdit(UnityEngine.Object assetObject, out string message, StatusQueryOptions statusOptions) + public static bool IsOpenForEdit(UnityEngine.Object assetObject, out string message, [uei.DefaultValue("StatusQueryOptions.UseCachedIfPossible")] StatusQueryOptions statusOptions) { string assetPath = GetAssetOrScenePath(assetObject); return IsOpenForEdit(assetPath, out message, statusOptions); } - [System.Obsolete("AssetDatabase.IsOpenForEdit without StatusQueryOptions has been deprecated. Use the version with StatusQueryOptions instead. This will always request the cached status (StatusQueryOptions.UseCachedIfPossible)")] - public static bool IsOpenForEdit(string assetOrMetaFilePath, out string message) + [uei.ExcludeFromDocs] public static bool IsOpenForEdit(string assetOrMetaFilePath, out string message) { return IsOpenForEdit(assetOrMetaFilePath, out message, StatusQueryOptions.UseCachedIfPossible); } - public static bool IsOpenForEdit(string assetOrMetaFilePath, out string message, StatusQueryOptions statusOptions) + public static bool IsOpenForEdit(string assetOrMetaFilePath, out string message, [uei.DefaultValue("StatusQueryOptions.UseCachedIfPossible")] StatusQueryOptions statusOptions) { return AssetModificationProcessorInternal.IsOpenForEdit(assetOrMetaFilePath, out message, statusOptions); } - [System.Obsolete("AssetDatabase.IsMetaFileOpenForEdit without StatusQueryOptions has been deprecated. Use the version with StatusQueryOptions instead. This will always request the cached status (StatusQueryOptions.UseCachedIfPossible)")] - public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject) + [uei.ExcludeFromDocs] public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject) { return IsMetaFileOpenForEdit(assetObject, StatusQueryOptions.UseCachedIfPossible); } - public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject, StatusQueryOptions statusOptions) + public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject, [uei.DefaultValue("StatusQueryOptions.UseCachedIfPossible")] StatusQueryOptions statusOptions) { string message; return IsMetaFileOpenForEdit(assetObject, out message, statusOptions); } - [System.Obsolete("AssetDatabase.IsMetaFileOpenForEdit without StatusQueryOptions has been deprecated. Use the version with StatusQueryOptions instead. This will always request the cached status (StatusQueryOptions.UseCachedIfPossible)")] - public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject, out string message) + [uei.ExcludeFromDocs] public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject, out string message) { return IsMetaFileOpenForEdit(assetObject, out message, StatusQueryOptions.UseCachedIfPossible); } - public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject, out string message, StatusQueryOptions statusOptions) + public static bool IsMetaFileOpenForEdit(UnityEngine.Object assetObject, out string message, [uei.DefaultValue("StatusQueryOptions.UseCachedIfPossible")] StatusQueryOptions statusOptions) { string assetPath = GetAssetOrScenePath(assetObject); string metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(assetPath); @@ -385,8 +383,6 @@ internal extern static string assetFolderGUID extern internal static bool IsV1Enabled(); [FreeFunction("AssetDatabase::IsV2Enabled")] extern internal static bool IsV2Enabled(); - [FreeFunction("AssetDatabase::IsOnDemandModeEnabled")] - extern internal static bool IsOnDemandModeEnabled(); [FreeFunction("AssetDatabase::CloseCachedFiles")] extern internal static void CloseCachedFiles(); diff --git a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs index b7a42b491d..fcad2f6947 100644 --- a/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs +++ b/Modules/AssetDatabase/Editor/ScriptBindings/AssetDatabaseExperimental.bindings.cs @@ -3,6 +3,8 @@ // https://unity3d.com/legal/licenses/Unity_Reference_Only_License using System; +using System.Runtime.InteropServices; + using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -12,11 +14,42 @@ namespace UnityEditor.Experimental { + public enum OnDemandState + { + Unavailable = 0, + Processing = 1, + Downloading = 2, + Available = 3 + } + + [NativeHeader("Modules/AssetDatabase/Editor/Public/AssetDatabaseTypes.h")] + [RequiredByNativeCode] + [StructLayout(LayoutKind.Sequential)] + public struct OnDemandProgress + { + public OnDemandState state; + public float progress; + } + [NativeHeader("Modules/AssetDatabase/Editor/V2/AssetDatabaseCounters.h")] [NativeHeader("Modules/AssetDatabase/Editor/V2/V1Compatibility.h")] [NativeHeader("Modules/AssetDatabase/Editor/Public/AssetDatabaseExperimental.h")] public sealed partial class AssetDatabaseExperimental { + public enum OnDemandMode + { + Off = 0, + Lazy = 1, + Background = 2 + } + + public enum ImportSyncMode + { + Block = 0, + Queue = 1, + Poll = 2 + } + public struct AssetDatabaseCounters { public struct Counter @@ -85,16 +118,22 @@ public void ResetDeltas() [FreeFunction("ImportCountersResetDeltas")] private extern static void ImportCountersResetDeltas(); - private extern static Hash128 GetArtifactHash_Internal_Guid_SelectImporter(string guid); - private extern static Hash128 GetArtifactHash_Internal_Guid(string guid, Type importerType); + public extern static OnDemandMode ActiveOnDemandMode + { + [FreeFunction("GetOnDemandModeV2")] get; + [FreeFunction("SetOnDemandModeV2")] set; + } + private extern static Hash128 GetArtifactHash_Internal_Guid_SelectImporter(string guid, ImportSyncMode mode); + private extern static Hash128 GetArtifactHash_Internal_Guid(string guid, Type importerType, ImportSyncMode mode); + private extern static Hash128[] GetArtifactHashes_Internal_Guids_SelectImporter(string[] guid, ImportSyncMode mode); - [uei.ExcludeFromDocs] public static Hash128 GetArtifactHash(string guid) { return GetArtifactHash(guid, null); } - public static Hash128 GetArtifactHash(string guid, [uei.DefaultValue("null")] Type importerType) + [uei.ExcludeFromDocs] public static Hash128 GetArtifactHash(string guid, ImportSyncMode mode = ImportSyncMode.Block) { return GetArtifactHash(guid, null, mode); } + public static Hash128 GetArtifactHash(string guid, [uei.DefaultValue("null")] Type importerType, ImportSyncMode mode = ImportSyncMode.Block) { if (importerType == null) - return GetArtifactHash_Internal_Guid_SelectImporter(guid); + return GetArtifactHash_Internal_Guid_SelectImporter(guid, mode); else - return GetArtifactHash_Internal_Guid(guid, importerType); + return GetArtifactHash_Internal_Guid(guid, importerType, mode); } public static bool GetArtifactPaths(Hash128 hash, out string[] paths) @@ -105,8 +144,26 @@ public static bool GetArtifactPaths(Hash128 hash, out string[] paths) return success; } + public static Hash128[] GetArtifactHashes(string[] guids, ImportSyncMode mode = ImportSyncMode.Block) + { + return GetArtifactHashes_Internal_Guids_SelectImporter(guids, mode); + } + extern private static string[] GetArtifactPathsImpl(Hash128 hash, out bool success); + private extern static OnDemandProgress GetOnDemandArtifactProgress_Internal_SelectImporter(string guid); + private extern static OnDemandProgress GetOnDemandArtifactProgress_Internal(string guid, Type importerType); + + public static OnDemandProgress GetOnDemandArtifactProgress(string guid) + { + return GetOnDemandArtifactProgress_Internal_SelectImporter(guid); + } + + public static OnDemandProgress GetOnDemandArtifactProgress(string guid, Type importerType) + { + return GetOnDemandArtifactProgress_Internal(guid, importerType); + } + [RequiredByNativeCode] static string[] OnSourceAssetsModified(string[] changedAssets, string[] addedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { diff --git a/Modules/AssetPipelineEditor/AssetPostprocessors/ModelImporterPostProcessor.cs b/Modules/AssetPipelineEditor/AssetPostprocessors/ModelImporterPostProcessor.cs index 9f65f30847..6e3c1bfbd3 100644 --- a/Modules/AssetPipelineEditor/AssetPostprocessors/ModelImporterPostProcessor.cs +++ b/Modules/AssetPipelineEditor/AssetPostprocessors/ModelImporterPostProcessor.cs @@ -17,7 +17,7 @@ internal class ModelImporterPostProcessor : AssetPostprocessor static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath) { - if (AssetDatabase.IsOnDemandModeEnabled()) + if (UnityEditor.Experimental.AssetDatabaseExperimental.ActiveOnDemandMode != UnityEditor.Experimental.AssetDatabaseExperimental.OnDemandMode.Off) { // This PostProcessAllAssets will forcefully import everything in on-demand mode // We need to find a better way of filtering on asset type without forcing an import diff --git a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterMaterialEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterMaterialEditor.cs index c35651de02..d0572c9437 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterMaterialEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterMaterialEditor.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using UnityEditor.Experimental.AssetImporters; using UnityEngine; using Object = UnityEngine.Object; @@ -181,6 +182,14 @@ internal override void OnEnable() BuildMaterialsCache(); BuildExternalObjectsCache(); } + + Undo.undoRedoPerformed += ResetValues; + } + + internal override void OnDisable() + { + Undo.undoRedoPerformed -= ResetValues; + base.OnDisable(); } private void BuildMaterialsCache() @@ -385,25 +394,17 @@ private bool MaterialRemapOptions() { if (GUILayout.Button(Styles.RemapMaterialsInProject)) { - try - { - AssetDatabase.StartAssetEditing(); - - foreach (var t in targets) - { - var importer = t as ModelImporter; - // SearchAndReplaceMaterials will ensure the material name and search options get saved, while all other pending changes stay pending. - importer.SearchAndRemapMaterials((ModelImporterMaterialName)m_MaterialName.intValue, (ModelImporterMaterialSearch)m_MaterialSearch.intValue); - - AssetDatabase.WriteImportSettingsIfDirty(importer.assetPath); - AssetDatabase.ImportAsset(importer.assetPath, ImportAssetOptions.ForceUpdate); - } - } - finally + Undo.RecordObjects(targets, "Search and Remap Materials"); + foreach (var t in targets) { - AssetDatabase.StopAssetEditing(); + var importer = t as ModelImporter; + // SearchAndReplaceMaterials will ensure the material name and search options get saved, while all other pending changes stay pending. + importer.SearchAndRemapMaterials((ModelImporterMaterialName)m_MaterialName.intValue, (ModelImporterMaterialSearch)m_MaterialSearch.intValue); } + ResetValues(); + EditorGUIUtility.ExitGUI(); + return true; } } @@ -522,8 +523,7 @@ void DoMaterialsGUI() { GUILayout.Label(Styles.ExternalMaterialMappings, EditorStyles.boldLabel); - if (MaterialRemapOptions()) - return; + MaterialRemapOptions(); DoMaterialRemapList(); } @@ -531,12 +531,16 @@ void DoMaterialsGUI() internal override void ResetValues() { + serializedObject.Update(); BuildMaterialsCache(); BuildExternalObjectsCache(); } void DoMaterialRemapList() { + // OnEnabled is not called consistently when the asset gets reimported, we need to rebuild the cache here if it's outdated. + if (m_ExternalObjects.arraySize != m_ExternalObjectsCache.Count()) + ResetValues(); // The list of material names is immutable, whereas the map of external objects can change based on user actions. // For each material name, map the external object associated with it. // The complexity comes from the fact that we may not have an external object in the map, so we can't make a property out of it diff --git a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs index a25492512e..eca8c9f157 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterModelEditor.cs @@ -39,7 +39,10 @@ internal class ModelImporterModelEditor : BaseAssetImporterTabUI SerializedProperty m_SecondaryUVAngleDistortion; SerializedProperty m_SecondaryUVAreaDistortion; SerializedProperty m_SecondaryUVHardAngle; + SerializedProperty m_SecondaryUVMarginMethod; SerializedProperty m_SecondaryUVPackMargin; + SerializedProperty m_SecondaryUVMinLightmapResolution; + SerializedProperty m_SecondaryUVMinObjectScale; protected SerializedProperty m_NormalImportMode; protected SerializedProperty m_NormalCalculationMode; @@ -76,7 +79,10 @@ internal override void OnEnable() m_SecondaryUVAngleDistortion = serializedObject.FindProperty("secondaryUVAngleDistortion"); m_SecondaryUVAreaDistortion = serializedObject.FindProperty("secondaryUVAreaDistortion"); m_SecondaryUVHardAngle = serializedObject.FindProperty("secondaryUVHardAngle"); + m_SecondaryUVMarginMethod = serializedObject.FindProperty("secondaryUVMarginMethod"); m_SecondaryUVPackMargin = serializedObject.FindProperty("secondaryUVPackMargin"); + m_SecondaryUVMinLightmapResolution = serializedObject.FindProperty("secondaryUVMinLightmapResolution"); + m_SecondaryUVMinObjectScale = serializedObject.FindProperty("secondaryUVMinObjectScale"); m_NormalSmoothAngle = serializedObject.FindProperty("normalSmoothAngle"); m_NormalImportMode = serializedObject.FindProperty("normalImportMode"); m_NormalCalculationMode = serializedObject.FindProperty("normalCalculationMode"); @@ -130,12 +136,19 @@ protected static class Styles public static GUIContent NormalSmoothingSourceLabel = EditorGUIUtility.TrTextContent("Smoothness Source", "How to determine which edges should be smooth and which should be sharp."); public static GUIContent SwapUVChannels = EditorGUIUtility.TrTextContent("Swap UVs", "Swaps the 2 UV channels in meshes. Use if your diffuse texture uses UVs from the lightmap."); - public static GUIContent GenerateSecondaryUV = EditorGUIUtility.TrTextContent("Generate Lightmap UVs", "Generate lightmap UVs into UV2."); - public static GUIContent GenerateSecondaryUVAdvanced = EditorGUIUtility.TrTextContent("Lightmap UVs settings", "Advanced settings for Lightmap UVs generation"); - public static GUIContent secondaryUVAngleDistortion = EditorGUIUtility.TrTextContent("Angle Error", "Measured in percents. Angle error measures deviation of UV angles from geometry angles. Area error measures deviation of UV triangles area from geometry triangles if they were uniformly scaled."); - public static GUIContent secondaryUVAreaDistortion = EditorGUIUtility.TrTextContent("Area Error"); - public static GUIContent secondaryUVHardAngle = EditorGUIUtility.TrTextContent("Hard Angle", "Angle between neighbor triangles that will generate seam."); - public static GUIContent secondaryUVPackMargin = EditorGUIUtility.TrTextContent("Pack Margin", "Measured in pixels, assuming mesh will cover an entire 1024x1024 lightmap."); + public static GUIContent GenerateSecondaryUV = EditorGUIUtility.TrTextContent("Generate Lightmap UVs", "Generate lightmap UVs into UV2."); + public static GUIContent GenerateSecondaryUVAdvanced = EditorGUIUtility.TrTextContent("Lightmap UVs settings", "Advanced settings for Lightmap UVs generation"); + + public static GUIContent secondaryUVAngleDistortion = EditorGUIUtility.TrTextContent("Angle Error", "Measured in percents. Angle error measures deviation of UV angles from geometry angles. Area error measures deviation of UV triangles area from geometry triangles if they were uniformly scaled."); + public static GUIContent secondaryUVAreaDistortion = EditorGUIUtility.TrTextContent("Area Error"); + public static GUIContent secondaryUVHardAngle = EditorGUIUtility.TrTextContent("Hard Angle", "Angle between neighbor triangles that will generate seam."); + public static GUIContent secondaryUVMarginMethod = EditorGUIUtility.TrTextContent("Margin Method", "Method to handle margins between UV charts."); + public static GUIContent secondaryUVPackMargin = EditorGUIUtility.TrTextContent("Pack Margin", "Measured in pixels, assuming mesh will cover an entire 1024x1024 lightmap."); + public static GUIContent secondaryUVMinLightmapResolution = EditorGUIUtility.TrTextContent("Min Lightmap Resolution", "The minimum lightmap resolution at which this object will be used. Used to determine a packing which ensures no texel bleeding."); + public static GUIContent secondaryUVMinObjectScale = EditorGUIUtility.TrTextContent("Min Object Scale", "The smallest scale at which this mesh will be used. Used to determine a packing which ensures no texel bleeding."); + + public static GUIContent secondaryUVMinLightmapResolutionNotice = EditorGUIUtility.TrTextContent("The active scene's Lightmap Resolution is less than the specified Min Lightmap Resolution.", EditorGUIUtility.GetHelpIcon(MessageType.Info)); + public static GUIContent LegacyComputeNormalsFromSmoothingGroupsWhenMeshHasBlendShapes = EditorGUIUtility.TrTextContent("Legacy Blend Shape Normals", "Compute normals from smoothing groups when the mesh has BlendShapes."); } @@ -380,16 +393,45 @@ protected void UvsGUI() { using (new EditorGUI.IndentLevelScope()) { - // TODO: all slider min/max values should be revisited EditorGUI.BeginChangeCheck(); + EditorGUILayout.Slider(m_SecondaryUVHardAngle, 0, 180, Styles.secondaryUVHardAngle); - EditorGUILayout.Slider(m_SecondaryUVPackMargin, 1, 64, Styles.secondaryUVPackMargin); EditorGUILayout.Slider(m_SecondaryUVAngleDistortion, 1, 75, Styles.secondaryUVAngleDistortion); EditorGUILayout.Slider(m_SecondaryUVAreaDistortion, 1, 75, Styles.secondaryUVAreaDistortion); + + using (var horizontal = new EditorGUILayout.HorizontalScope()) + { + using (var prop = new EditorGUI.PropertyScope(horizontal.rect, Styles.secondaryUVMarginMethod, m_SecondaryUVMarginMethod)) + { + EditorGUI.BeginChangeCheck(); + var newValue = (int)(ModelImporterSecondaryUVMarginMethod)EditorGUILayout.EnumPopup(prop.content, (ModelImporterSecondaryUVMarginMethod)m_SecondaryUVMarginMethod.intValue); + if (EditorGUI.EndChangeCheck()) + { + m_SecondaryUVMarginMethod.intValue = newValue; + } + } + } + if (m_SecondaryUVMarginMethod.intValue == (int)ModelImporterSecondaryUVMarginMethod.Calculate) + { + EditorGUILayout.PropertyField(m_SecondaryUVMinLightmapResolution, Styles.secondaryUVMinLightmapResolution); + if (LightmapEditorSettings.bakeResolution < m_SecondaryUVMinLightmapResolution.floatValue) + { + EditorGUILayout.HelpBox(Styles.secondaryUVMinLightmapResolutionNotice); + } + + EditorGUILayout.PropertyField(m_SecondaryUVMinObjectScale, Styles.secondaryUVMinObjectScale); + } + else + { + EditorGUILayout.Slider(m_SecondaryUVPackMargin, 1, 64, Styles.secondaryUVPackMargin); + } + if (EditorGUI.EndChangeCheck()) { m_SecondaryUVHardAngle.floatValue = Mathf.Round(m_SecondaryUVHardAngle.floatValue); m_SecondaryUVPackMargin.floatValue = Mathf.Round(m_SecondaryUVPackMargin.floatValue); + m_SecondaryUVMinLightmapResolution.floatValue = Mathf.Round(m_SecondaryUVMinLightmapResolution.floatValue); + m_SecondaryUVMinObjectScale.floatValue = m_SecondaryUVMinObjectScale.floatValue; m_SecondaryUVAngleDistortion.floatValue = Mathf.Round(m_SecondaryUVAngleDistortion.floatValue); m_SecondaryUVAreaDistortion.floatValue = Mathf.Round(m_SecondaryUVAreaDistortion.floatValue); } diff --git a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterRigEditor.cs b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterRigEditor.cs index e19b56dc76..bef932f66a 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/ModelImporterRigEditor.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/ModelImporterRigEditor.cs @@ -358,7 +358,7 @@ void ConfigureAvatarGUI() if (singleImporter.transformPaths.Length <= HumanTrait.RequiredBoneCount) { - GUILayout.Label(string.Format("Not enough bones to create human avatar (requires {0})", HumanTrait.RequiredBoneCount, EditorStyles.helpBox)); + GUILayout.Label(string.Format("Not enough bones to create human avatar (requires {0})", HumanTrait.RequiredBoneCount), EditorStyles.helpBox); } // Validation text diff --git a/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs b/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs index dc63be90a9..118f92d8fa 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/PluginImporterInspector.cs @@ -478,7 +478,7 @@ public override void OnEnable() case DllType.WinMDNET40: info = "Managed WinMD"; break; case DllType.WinMDNative: info = "Native WinMD"; break; default: - throw new Exception("Unknown managed dll type: " + importer.dllType.ToString()); + throw new Exception("Unknown managed dll type: " + importer.dllType); } m_PluginInformation["Assembly Info"] = info; @@ -585,7 +585,7 @@ private Compatibility SwitchToExclude(Compatibility value) case Compatibility.Compatible: return Compatibility.NotCompatible; case Compatibility.NotCompatible: return Compatibility.Compatible; default: - throw new InvalidEnumArgumentException("Invalid value: " + value.ToString()); + throw new InvalidEnumArgumentException("Invalid value: " + value); } } diff --git a/Modules/AssetPipelineEditor/ImportSettings/VideoClipImporterInspector.cs b/Modules/AssetPipelineEditor/ImportSettings/VideoClipImporterInspector.cs index 59e56e2ccd..e82c25434b 100644 --- a/Modules/AssetPipelineEditor/ImportSettings/VideoClipImporterInspector.cs +++ b/Modules/AssetPipelineEditor/ImportSettings/VideoClipImporterInspector.cs @@ -109,7 +109,7 @@ private string GetAudioTrackDescription(VideoClipImporter importer, ushort audio channelCount == 1 ? "Mono" : channelCount == 2 ? "Stereo" : channelCount == 4 ? channelCount.ToString() : // Can be 3.1 or quad - ((channelCount - 1).ToString() + ".1"); + ((channelCount - 1) + ".1"); return importer.GetSourceAudioSampleRate(audioTrackIdx) + " Hz, " + channelCountStr; } @@ -197,7 +197,7 @@ class Styles "Transcode was skipped for some clips and they don't match import settings. Reimport to resolve."); public GUIContent sRGBTextureContent = EditorGUIUtility.TrTextContent( "sRGB (Color Texture)", "Texture content is stored in gamma space."); - }; + } static Styles s_Styles; @@ -213,7 +213,7 @@ protected override void InitializeExtraDataInstance(Object extraData, int target if (targetSettings != null && currentTarget != null) { var validPlatforms = BuildPlatforms.instance.GetValidPlatforms(); - targetSettings.allSettings = new List(validPlatforms.Count() + 1); + targetSettings.allSettings = new List(validPlatforms.Count + 1); var defaultSetting = new InspectorTargetSettings(); defaultSetting.target = BuildTargetGroup.Unknown; @@ -629,7 +629,6 @@ public override GUIContent GetPreviewTitle() public override void OnPreviewSettings() { - VideoClipImporter importer = (VideoClipImporter)target; EditorGUI.BeginDisabledGroup(Application.isPlaying); m_IsPlaying = PreviewGUI.CycleButton(m_IsPlaying ? 1 : 0, s_Styles.playIcons) != 0; EditorGUI.EndDisabledGroup(); diff --git a/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs b/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs index 24159f47ac..da50c4990b 100644 --- a/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs +++ b/Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.bindings.cs @@ -226,7 +226,7 @@ public enum ModelImporterMaterialLocation [InspectorName("Use Embedded Materials")] [Tooltip("Embed the material inside the imported asset.")] InPrefab = 1 - }; + } [NativeType(Header = "Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.h")] public enum ModelImporterMaterialImportMode @@ -239,7 +239,7 @@ public enum ModelImporterMaterialImportMode [InspectorName("Import (Experimental)")] [Tooltip("Use AssetPostprocessor.OnPreprocessMaterialDescription")] Import = 2 - }; + } public enum ModelImporterTangentSpaceMode { @@ -363,6 +363,14 @@ public enum ModelImporterHumanoidOversampling X8 = 8 } + [NativeType(Header = "Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.h")] + public enum ModelImporterSecondaryUVMarginMethod + { + Manual = 0, + + Calculate = 1, + } + [NativeType(Header = "Modules/AssetPipelineEditor/Public/ModelImporting/ModelImporter.h")] public enum ModelImporterAvatarSetup { @@ -593,12 +601,30 @@ public extern float secondaryUVHardAngle set; } + public extern ModelImporterSecondaryUVMarginMethod secondaryUVMarginMethod + { + get; + set; + } + public extern float secondaryUVPackMargin { get; set; } + public extern float secondaryUVMinLightmapResolution + { + get; + set; + } + + public extern float secondaryUVMinObjectScale + { + get; + set; + } + public extern ModelImporterGenerateAnimations generateAnimations { [NativeMethod("GetLegacyGenerateAnimations")] diff --git a/Modules/BuildPipeline/Editor/Managed/ResourceFile.cs b/Modules/BuildPipeline/Editor/Managed/ResourceFile.cs index abfa4a04cc..a4d54370ce 100644 --- a/Modules/BuildPipeline/Editor/Managed/ResourceFile.cs +++ b/Modules/BuildPipeline/Editor/Managed/ResourceFile.cs @@ -16,14 +16,14 @@ public struct ResourceFile { [NativeName("fileName")] internal string m_FileName; - public string fileName { get { return m_FileName; } } + public string fileName { get { return m_FileName; } set { m_FileName = value; } } [NativeName("fileAlias")] internal string m_FileAlias; - public string fileAlias { get { return m_FileAlias; } } + public string fileAlias { get { return m_FileAlias; } set { m_FileAlias = value; } } [NativeName("serializedFile")] internal bool m_SerializedFile; - public bool serializedFile { get { return m_SerializedFile; } } + public bool serializedFile { get { return m_SerializedFile; } set { m_SerializedFile = value; } } } } diff --git a/Modules/Cloth/Cloth.bindings.cs b/Modules/Cloth/Cloth.bindings.cs index c208f05e3f..de1f4c84f8 100644 --- a/Modules/Cloth/Cloth.bindings.cs +++ b/Modules/Cloth/Cloth.bindings.cs @@ -103,7 +103,7 @@ public sealed partial class Cloth : UnityEngine.Component [Obsolete("Parameter solverFrequency is obsolete and no longer supported. Please use clothSolverFrequency instead.")] public bool solverFrequency { - get { return clothSolverFrequency > 0.0f ? true : false; } + get { return clothSolverFrequency > 0.0f; } set { clothSolverFrequency = value == true ? 120f : 0.0f; } // use the default value } diff --git a/Modules/GameCenter/Managed/GameCenterServices.cs b/Modules/GameCenter/Managed/GameCenterServices.cs deleted file mode 100644 index b8a1c97fa2..0000000000 --- a/Modules/GameCenter/Managed/GameCenterServices.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Unity C# reference source -// Copyright (c) Unity Technologies. For terms of use, see -// https://unity3d.com/legal/licenses/Unity_Reference_Only_License - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using UnityEngine.Scripting; - -namespace UnityEngine.SocialPlatforms.GameCenter -{ -} diff --git a/Modules/GameCenter/Managed/LocalService.cs b/Modules/GameCenter/Managed/LocalService.cs index 75e802a137..dcd50abf14 100644 --- a/Modules/GameCenter/Managed/LocalService.cs +++ b/Modules/GameCenter/Managed/LocalService.cs @@ -490,7 +490,7 @@ public void ReportProgress(string id, double progress, System.Action callb // TODO: Only allow increase in progress, figure out if xbox/gc report errors when lower progress is reported if (achoo.id == id) { - bool completed = (progress >= 100.0 ? true : false); + bool completed = (progress >= 100.0); Achievement newAchievement = new Achievement(id, progress, completed, false, DateTime.Now); m_Achievements.Add(newAchievement); if (callback != null) diff --git a/Modules/GraphViewEditor/EdgeControl.cs b/Modules/GraphViewEditor/EdgeControl.cs index ff11e04a71..d4369398ef 100644 --- a/Modules/GraphViewEditor/EdgeControl.cs +++ b/Modules/GraphViewEditor/EdgeControl.cs @@ -849,7 +849,7 @@ void DrawEdge(MeshGenerationContext mgc) float halfWidth = edgeWidth * 0.5f; float currentLength = 0; - float flags = (float)VertexFlags.LastType; + Color32 flags = new Color32(0, 0, 0, (byte)VertexFlags.LastType); Vector2 unitPreviousSegment = Vector2.zero; for (int i = 0; i < cpt; ++i) @@ -883,8 +883,8 @@ void DrawEdge(MeshGenerationContext mgc) Vector2 uv = new Vector2(dir.y * halfWidth, -dir.x * halfWidth); // Normal scaled by half width Color32 tint = Color.LerpUnclamped(outColor, inColor, currentLength / polyLineLength); - md.SetNextVertex(new Vertex() { position = new Vector3(pos.x, pos.y, 1), uv = uv, tint = tint, flags = flags }); - md.SetNextVertex(new Vertex() { position = new Vector3(pos.x, pos.y, -1), uv = uv, tint = tint, flags = flags }); + md.SetNextVertex(new Vertex() { position = new Vector3(pos.x, pos.y, 1), uv = uv, tint = tint, idsFlags = flags }); + md.SetNextVertex(new Vertex() { position = new Vector3(pos.x, pos.y, -1), uv = uv, tint = tint, idsFlags = flags }); if (i < cpt - 2) { diff --git a/Modules/GraphViewEditor/Elements/ElementResizer.cs b/Modules/GraphViewEditor/Elements/ElementResizer.cs new file mode 100644 index 0000000000..4363dadccf --- /dev/null +++ b/Modules/GraphViewEditor/Elements/ElementResizer.cs @@ -0,0 +1,205 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +using UnityEngine; +using UnityEngine.UIElements; + +namespace UnityEditor.Experimental.GraphView +{ + internal class ElementResizer : MouseManipulator + { + private readonly ResizerDirection direction; + + private readonly VisualElement resizedElement; + + public ElementResizer(VisualElement resizedElement, ResizerDirection direction) + { + this.direction = direction; + this.resizedElement = resizedElement; + activators.Add(new ManipulatorActivationFilter() { button = MouseButton.LeftMouse }); + } + + protected override void RegisterCallbacksOnTarget() + { + target.RegisterCallback(OnMouseDown); + target.RegisterCallback(OnMouseUp); + } + + protected override void UnregisterCallbacksFromTarget() + { + target.UnregisterCallback(OnMouseDown); + target.UnregisterCallback(OnMouseUp); + } + + Vector2 m_StartMouse; + Vector2 m_StartSize; + + Vector2 m_MinSize; + Vector2 m_MaxSize; + + Vector2 m_StartPosition; + + bool m_DragStarted = false; + + bool m_Active = false; + + void OnMouseDown(MouseDownEvent e) + { + if (m_Active) + { + e.StopImmediatePropagation(); + return; + } + + if (!CanStartManipulation(e)) + return; + + m_Active = true; + + VisualElement resizedTarget = resizedElement.parent; + if (resizedTarget == null) + return; + VisualElement resizedBase = resizedTarget.parent; + if (resizedBase == null) + return; + target.RegisterCallback(OnMouseMove); + e.StopPropagation(); + target.CaptureMouse(); + m_StartMouse = resizedBase.WorldToLocal(e.mousePosition); + m_StartSize = new Vector2(resizedTarget.resolvedStyle.width, resizedTarget.resolvedStyle.height); + m_StartPosition = new Vector2(resizedTarget.resolvedStyle.left, resizedTarget.resolvedStyle.top); + + bool minWidthDefined = resizedTarget.resolvedStyle.minWidth != StyleKeyword.Auto; + bool maxWidthDefined = resizedTarget.resolvedStyle.maxWidth != StyleKeyword.None; + bool minHeightDefined = resizedTarget.resolvedStyle.minHeight != StyleKeyword.Auto; + bool maxHeightDefined = resizedTarget.resolvedStyle.maxHeight != StyleKeyword.None; + m_MinSize = new Vector2( + minWidthDefined ? resizedTarget.resolvedStyle.minWidth.value : Mathf.NegativeInfinity, + minHeightDefined ? resizedTarget.resolvedStyle.minHeight.value : Mathf.NegativeInfinity); + m_MaxSize = new Vector2( + maxWidthDefined ? resizedTarget.resolvedStyle.maxWidth.value : Mathf.Infinity, + maxHeightDefined ? resizedTarget.resolvedStyle.maxHeight.value : Mathf.Infinity); + + m_DragStarted = false; + } + + void OnMouseMove(MouseMoveEvent e) + { + if (!m_Active) + return; + + VisualElement resizedTarget = resizedElement.parent; + VisualElement resizedBase = resizedTarget.parent; + + Vector2 mousePos = resizedBase.WorldToLocal(e.mousePosition); + if (!m_DragStarted) + { + if (resizedTarget is IResizable) + (resizedTarget as IResizable).OnStartResize(); + m_DragStarted = true; + } + if (resizedTarget.isLayoutManual) + { + Rect layout = resizedTarget.layout; + if ((direction & ResizerDirection.Right) != 0) + { + layout.width = Mathf.Min(m_MaxSize.x, Mathf.Max(m_MinSize.x, m_StartSize.x + mousePos.x - m_StartMouse.x)); + } + else if ((direction & ResizerDirection.Left) != 0) + { + float delta = mousePos.x - m_StartMouse.x; + + if (m_StartSize.x - delta < m_MinSize.x) + delta = -m_MinSize.x + m_StartSize.x; + else if (m_StartSize.x - delta > m_MaxSize.x) + delta = -m_MaxSize.x + m_StartSize.x; + + layout.xMin = delta + m_StartPosition.x; + layout.width = -delta + m_StartSize.x; + } + if ((direction & ResizerDirection.Bottom) != 0) + { + layout.height = Mathf.Min(m_MaxSize.y, Mathf.Max(m_MinSize.y, m_StartSize.y + mousePos.y - m_StartMouse.y)); + } + else if ((direction & ResizerDirection.Top) != 0) + { + float delta = mousePos.y - m_StartMouse.y; + + if (m_StartSize.y - delta < m_MinSize.y) + delta = -m_MinSize.y + m_StartSize.y; + else if (m_StartSize.y - delta > m_MaxSize.y) + delta = -m_MaxSize.y + m_StartSize.y; + layout.yMin = delta + m_StartPosition.y; + layout.height = -delta + m_StartSize.y; + } + + if (direction != 0) + { + resizedTarget.layout = layout; + } + } + else + { + if ((direction & ResizerDirection.Right) != 0) + { + resizedTarget.style.width = Mathf.Min(m_MaxSize.x, Mathf.Max(m_MinSize.x, m_StartSize.x + mousePos.x - m_StartMouse.x)); + } + else if ((direction & ResizerDirection.Left) != 0) + { + float delta = mousePos.x - m_StartMouse.x; + + if (m_StartSize.x - delta < m_MinSize.x) + delta = -m_MinSize.x + m_StartSize.x; + else if (m_StartSize.x - delta > m_MaxSize.x) + delta = -m_MaxSize.x + m_StartSize.x; + + resizedTarget.style.left = delta + m_StartPosition.x; + resizedTarget.style.width = -delta + m_StartSize.x; + } + if ((direction & ResizerDirection.Bottom) != 0) + { + resizedTarget.style.height = Mathf.Min(m_MaxSize.y, Mathf.Max(m_MinSize.y, m_StartSize.y + mousePos.y - m_StartMouse.y)); + } + else if ((direction & ResizerDirection.Top) != 0) + { + float delta = mousePos.y - m_StartMouse.y; + + if (m_StartSize.y - delta < m_MinSize.y) + delta = -m_MinSize.y + m_StartSize.y; + else if (m_StartSize.y - delta > m_MaxSize.y) + delta = -m_MaxSize.y + m_StartSize.y; + resizedTarget.style.top = delta + m_StartPosition.y; + resizedTarget.style.height = -delta + m_StartSize.y; + } + } + e.StopPropagation(); + } + + void OnMouseUp(MouseUpEvent e) + { + if (!CanStopManipulation(e)) + return; + + if (m_Active) + { + VisualElement resizedTarget = resizedElement.parent; + if (resizedTarget.style.width != m_StartSize.x || resizedTarget.style.height != m_StartSize.y) + { + if (resizedTarget is IResizable) + (resizedTarget as IResizable).OnResized(); + } + target.UnregisterCallback(OnMouseMove); + target.ReleaseMouse(); + e.StopPropagation(); + + m_Active = false; + } + } + } +} diff --git a/Modules/GraphViewEditor/Elements/GraphElement.cs b/Modules/GraphViewEditor/Elements/GraphElement.cs index 0cd1c119cd..97d7367360 100644 --- a/Modules/GraphViewEditor/Elements/GraphElement.cs +++ b/Modules/GraphViewEditor/Elements/GraphElement.cs @@ -253,6 +253,8 @@ public virtual bool IsSelected(VisualElement selectionContainer) static void RegisterAll() { VisualElementFactoryRegistry.RegisterFactory(new Pill.UxmlFactory()); + VisualElementFactoryRegistry.RegisterFactory(new ResizableElement.UxmlFactory()); + VisualElementFactoryRegistry.RegisterFactory(new StickyNote.UxmlFactory()); } } } diff --git a/Runtime/Export/iOS/iOSReplayKit.bindings.cs b/Modules/GraphViewEditor/Elements/IResizable.cs similarity index 53% rename from Runtime/Export/iOS/iOSReplayKit.bindings.cs rename to Modules/GraphViewEditor/Elements/IResizable.cs index f664bb63a0..c9dcf07a29 100644 --- a/Runtime/Export/iOS/iOSReplayKit.bindings.cs +++ b/Modules/GraphViewEditor/Elements/IResizable.cs @@ -2,9 +2,11 @@ // Copyright (c) Unity Technologies. For terms of use, see // https://unity3d.com/legal/licenses/Unity_Reference_Only_License -using UnityEngine.Bindings; -using uei = UnityEngine.Internal; - -namespace UnityEngine.Apple.ReplayKit +namespace UnityEditor.Experimental.GraphView { + interface IResizable + { + void OnStartResize(); + void OnResized(); + } } diff --git a/Modules/GraphViewEditor/Elements/ResizableElement.cs b/Modules/GraphViewEditor/Elements/ResizableElement.cs new file mode 100644 index 0000000000..f8dac6973a --- /dev/null +++ b/Modules/GraphViewEditor/Elements/ResizableElement.cs @@ -0,0 +1,61 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +using UnityEngine; +using UnityEngine.UIElements; + +namespace UnityEditor.Experimental.GraphView +{ + [Flags] + public enum ResizerDirection + { + Top = 1 << 0, + Bottom = 1 << 1, + Left = 1 << 2, + Right = 1 << 3, + } + + public class ResizableElement : VisualElement + { + public new class UxmlFactory : UxmlFactory {} + + public ResizableElement() : this("UXML/GraphView/Resizable.uxml") + { + pickingMode = PickingMode.Ignore; + AddToClassList("resizableElement"); + } + + public ResizableElement(string uiFile) + { + var tpl = Resources.Load(uiFile); + if (tpl == null) + tpl = EditorGUIUtility.Load(uiFile) as VisualTreeAsset; + + var sheet = EditorGUIUtility.Load("StyleSheets/GraphView/Resizable.uss") as StyleSheet; + styleSheets.Add(sheet); + + tpl.CloneTree(this); + + foreach (ResizerDirection value in System.Enum.GetValues(typeof(ResizerDirection))) + { + VisualElement resizer = this.Q(value.ToString().ToLower() + "-resize"); + if (resizer != null) + resizer.AddManipulator(new ElementResizer(this, value)); + } + + foreach (ResizerDirection vertical in new[] { ResizerDirection.Top, ResizerDirection.Bottom }) + foreach (ResizerDirection horizontal in new[] { ResizerDirection.Left, ResizerDirection.Right }) + { + VisualElement resizer = this.Q(vertical.ToString().ToLower() + "-" + horizontal.ToString().ToLower() + "-resize"); + if (resizer != null) + resizer.AddManipulator(new ElementResizer(this, vertical | horizontal)); + } + } + } +} diff --git a/Modules/GraphViewEditor/Elements/Scope.cs b/Modules/GraphViewEditor/Elements/Scope.cs index 1c6831edf8..f6a054f199 100644 --- a/Modules/GraphViewEditor/Elements/Scope.cs +++ b/Modules/GraphViewEditor/Elements/Scope.cs @@ -289,9 +289,6 @@ public void UpdateGeometryFromContent() try { - GraphView graphView = GetFirstAncestorOfType(); - VisualElement viewport = graphView.contentViewContainer; - // Dirty the layout of the content container to recompute the content bounding rect m_ContentContainer.yogaNode.MarkDirty(); diff --git a/Modules/GraphViewEditor/Elements/StackNode.cs b/Modules/GraphViewEditor/Elements/StackNode.cs index 35f07f0dd3..c167492277 100644 --- a/Modules/GraphViewEditor/Elements/StackNode.cs +++ b/Modules/GraphViewEditor/Elements/StackNode.cs @@ -172,8 +172,6 @@ private void UpdateSeparators() // For the first separator, use the top of the first element if (i == 0) { - VisualElement firstElement = this[i]; - separatorCenterY = separatorHeight / 2; } // .. for the other separators, use the spacing between the current and the next separators @@ -187,8 +185,6 @@ private void UpdateSeparators() // .. for the last separator, use the bottom of the container else { - VisualElement element = this[i - 1]; - separatorCenterY = m_SeparatorContainer.layout.height - separatorHeight / 2; } separator.style.top = separatorCenterY - separator.resolvedStyle.height / 2; diff --git a/Modules/GraphViewEditor/Elements/StickyNote.cs b/Modules/GraphViewEditor/Elements/StickyNote.cs new file mode 100644 index 0000000000..56cfcbd443 --- /dev/null +++ b/Modules/GraphViewEditor/Elements/StickyNote.cs @@ -0,0 +1,405 @@ +// Unity C# reference source +// Copyright (c) Unity Technologies. For terms of use, see +// https://unity3d.com/legal/licenses/Unity_Reference_Only_License + +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +using UnityEngine; +using UnityEngine.UIElements; + +namespace UnityEditor.Experimental.GraphView +{ + public enum StickyNoteChange + { + Title, + Contents, + Theme, + FontSize, + Position, + } + public class StickyNoteChangeEvent : EventBase + { + public static StickyNoteChangeEvent GetPooled(StickyNote target, StickyNoteChange change) + { + var evt = GetPooled(); + evt.target = target; + evt.change = change; + return evt; + } + + public StickyNoteChange change {get; protected set; } + } + public enum StickyNoteTheme + { + Classic, + Black + } + public enum StickyNoteFontSize + { + Small, + Medium, + Large, + Huge + } + + public class StickyNote : GraphElement, IResizable + { + public new class UxmlFactory : UxmlFactory {} + + + StickyNoteTheme m_Theme = StickyNoteTheme.Classic; + public StickyNoteTheme theme + { + get + { + return m_Theme; + } + set + { + if (m_Theme != value) + { + m_Theme = value; + UpdateThemeClasses(); + } + } + } + + StickyNoteFontSize m_FontSize = StickyNoteFontSize.Medium; + public StickyNoteFontSize fontSize + { + get {return m_FontSize; } + set + { + if (m_FontSize != value) + { + m_FontSize = value; + UpdateSizeClasses(); + } + } + } + + Label m_Title; + TextField m_TitleField; + Label m_Contents; + TextField m_ContentsField; + + public StickyNote() : this(Vector2.zero) + {} + + public StickyNote(Vector2 position) : this("UXML/GraphView/StickyNote.uxml", position) + { + styleSheets.Add(EditorGUIUtility.Load("StyleSheets/GraphView/Selectable.uss") as StyleSheet); + styleSheets.Add(EditorGUIUtility.Load("StyleSheets/GraphView/StickyNote.uss") as StyleSheet); + } + + public StickyNote(string uiFile, Vector2 position) + { + var tpl = Resources.Load(uiFile); + if (tpl == null) + tpl = EditorGUIUtility.Load(uiFile) as VisualTreeAsset; + + tpl.CloneTree(this); + + capabilities = Capabilities.Movable | Capabilities.Deletable | Capabilities.Ascendable | Capabilities.Selectable; + + m_Title = this.Q