diff --git a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj
index 2388bd88fa..793953d705 100644
--- a/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj
+++ b/Editor/IncrementalBuildPipeline/BeeBuildProgramCommon.Data/BeeBuildProgramCommon.Data.gen.csproj
@@ -18,6 +18,10 @@
false
false
+
+ $(HOME)
+ $(USERPROFILE)
+
diff --git a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs
index 48b52443eb..02db58f293 100644
--- a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs
+++ b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/Data.cs
@@ -106,6 +106,7 @@ public class Il2CppConfig
public string RelativeDataPath;
public bool GenerateUsymFile;
public string UsymtoolPath;
+ public BuildProgramLTOMode LtoMode;
}
public class Services
@@ -129,4 +130,12 @@ public enum ScriptingBackend
IL2CPP,
CoreCLR,
}
+
+ // Keep in sync with bee LTO modes
+ public enum BuildProgramLTOMode
+ {
+ None = 0,
+ Thin = 1,
+ Full = 2,
+ }
}
diff --git a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj
index 515e2921e1..0a93d19a25 100644
--- a/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj
+++ b/Editor/IncrementalBuildPipeline/PlayerBuildProgramLibrary.Data/PlayerBuildProgramLibrary.Data.gen.csproj
@@ -19,6 +19,10 @@
false
PlayerBuildProgramLibrary.Data
+
+ $(HOME)
+ $(USERPROFILE)
+
diff --git a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj
index 79fabee04c..3e0fa83fc7 100644
--- a/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj
+++ b/Editor/IncrementalBuildPipeline/ScriptCompilationBuildProgram.Data/ScriptCompilationBuildProgram.Data.gen.csproj
@@ -18,6 +18,10 @@
false
false
+
+ $(HOME)
+ $(USERPROFILE)
+
diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs
index 12a8178c4f..a295a8d200 100644
--- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs
+++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporter.bindings.cs
@@ -15,7 +15,7 @@
namespace UnityEditor.U2D
{
// SpriteAtlas Importer lets you modify [[SpriteAtlas]]
- [HelpURL("https://docs.unity3d.com/6000.2/Documentation/Manual/sprite/atlas/v2/sprite-atlas-v2.html")]
+ [HelpURL("sprite/atlas/sprite-atlas-reference")]
[NativeHeader("Editor/Src/2D/SpriteAtlas/SpriteAtlasImporter.h")]
public sealed partial class SpriteAtlasImporter : AssetImporter
{
diff --git a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs
index 9fde0c7d30..2d61e1d87a 100644
--- a/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs
+++ b/Editor/Mono/2D/SpriteAtlas/SpriteAtlasImporterInspector.cs
@@ -317,6 +317,8 @@ private SerializedObject GetSerializedAssetObject()
public override void OnEnable()
{
base.OnEnable();
+ if (!AreImporterTargetsValid()) // asset gone: base already logged and bailed
+ return;
m_FilterMode = serializedObject.FindProperty("m_TextureSettings.filterMode");
m_AnisoLevel = serializedObject.FindProperty("m_TextureSettings.anisoLevel");
diff --git a/Editor/Mono/AI/EditorAIAssistantAnalytics.cs b/Editor/Mono/AI/EditorAIAssistantAnalytics.cs
new file mode 100644
index 0000000000..efe8c15dff
--- /dev/null
+++ b/Editor/Mono/AI/EditorAIAssistantAnalytics.cs
@@ -0,0 +1,58 @@
+// Unity 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.Analytics;
+
+namespace UnityEditor.Toolbars;
+
+enum UITriggerLocalEventSubType
+{
+ AIDropdownOpened,
+ AIInstallAccepted,
+}
+
+internal static class EditorAIAssistantAnalytics
+{
+ const string k_EventName = "AIAssistantUITriggerLocalEvent";
+ const string k_VendorKey = "unity.ai.assistant";
+
+ [Serializable]
+ class UITriggerLocalEventData : IAnalytic.IData
+ {
+ public UITriggerLocalEventData(UITriggerLocalEventSubType subType) => SubType = subType.ToString();
+
+ public string SubType;
+ }
+
+ [AnalyticInfo(eventName: k_EventName, vendorKey: k_VendorKey)]
+ class UITriggerLocalEvent : IAnalytic
+ {
+ readonly UITriggerLocalEventData m_Data;
+
+ public UITriggerLocalEvent(UITriggerLocalEventData data) => m_Data = data;
+
+ public bool TryGatherData(out IAnalytic.IData data, out Exception error)
+ {
+ error = null;
+ data = m_Data;
+ return true;
+ }
+ }
+
+ static void ReportUITriggerLocalEvent(UITriggerLocalEventData data)
+ {
+ EditorAnalytics.SendAnalytic(new UITriggerLocalEvent(data));
+ }
+
+ internal static void ReportAIDropdownOpenedEvent()
+ {
+ ReportUITriggerLocalEvent(new UITriggerLocalEventData(UITriggerLocalEventSubType.AIDropdownOpened));
+ }
+
+ internal static void ReportAIInstallAcceptedEvent()
+ {
+ ReportUITriggerLocalEvent(new UITriggerLocalEventData(UITriggerLocalEventSubType.AIInstallAccepted));
+ }
+}
diff --git a/Editor/Mono/Animation/AnimationMode.bindings.cs b/Editor/Mono/Animation/AnimationMode.bindings.cs
index bdcb21eeed..60e5bb053c 100644
--- a/Editor/Mono/Animation/AnimationMode.bindings.cs
+++ b/Editor/Mono/Animation/AnimationMode.bindings.cs
@@ -54,7 +54,6 @@ public class AnimationMode
static private AnimationModeDriver s_DummyDriver;
- static internal AnimationModeDriver GetDriver() => Internal_GetDriver() as AnimationModeDriver;
static private AnimationModeDriver DummyDriver()
{
if (s_DummyDriver == null)
@@ -234,7 +233,5 @@ public static void EndSampling()
[NativeMethod(ThrowsException = true)]
extern private static void Internal_StartCandidateRecording(Object driver);
-
- extern internal static Object Internal_GetDriver();
}
}
diff --git a/Editor/Mono/Animation/AnimationUtility.bindings.cs b/Editor/Mono/Animation/AnimationUtility.bindings.cs
index 0eb3e14223..24c7e6bd43 100644
--- a/Editor/Mono/Animation/AnimationUtility.bindings.cs
+++ b/Editor/Mono/Animation/AnimationUtility.bindings.cs
@@ -36,7 +36,7 @@ public class AnimationClipCurveData
// This is only used internally for deleting curves
internal int classID;
- internal int scriptInstanceID;
+ internal EntityId scriptInstanceID;
public AnimationClipCurveData()
{
diff --git a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs
index da21ea42d1..640deed5cf 100644
--- a/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs
+++ b/Editor/Mono/Animation/AnimationWindow/AnimEditor.cs
@@ -20,7 +20,7 @@ class AnimEditor : ScriptableObject
[SerializeReference] private AnimationWindowState m_State;
[SerializeReference] private DopeSheetEditor m_DopeSheet;
[SerializeReference] private CurveEditor m_CurveEditor;
- [SerializeField] private AnimationWindowHierarchy m_Hierarchy;
+ private AnimationWindowHierarchy m_Hierarchy;
[SerializeField] private UnityEditor.AnimationWindowBuiltin.AnimationEventTimeLine m_Events;
[SerializeField] private EditorWindow m_OwnerWindow;
@@ -59,6 +59,8 @@ private bool triggerFraming
internal string eventToolTipText => m_Events.tooltipText;
internal Vector2 eventToolTipPosition => m_Events.tooltipPosition;
+ internal bool initialized => m_Initialized;
+
internal void MainContentOnGUI(Rect contentLayoutRect)
{
// Bail out if the hierarchy in animator is optimized.
@@ -251,6 +253,9 @@ internal void EventLineOnGUI(Rect eventsRect)
internal void HierarchyOnGUI(Rect hierarchyLayoutRect)
{
+ if (m_State.disabled)
+ return;
+
if (!m_State.showReadOnly && m_State.selection.isReadOnly)
{
Vector2 labelSize = GUI.skin.label.CalcSize(AnimationWindowStyles.readOnlyPropertiesLabel);
@@ -275,8 +280,7 @@ internal void HierarchyOnGUI(Rect hierarchyLayoutRect)
return;
}
- if (!m_State.disabled)
- m_Hierarchy.OnGUI(hierarchyLayoutRect);
+ m_Hierarchy.OnGUI(hierarchyLayoutRect);
}
internal void DopeSheetOnGUI(Rect position)
diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs
index 2fd5613b12..2ae304cd06 100644
--- a/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs
+++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindow.cs
@@ -4,6 +4,7 @@
using System;
using UnityEngine;
+using UnityEngine.Bindings;
using System.Collections.Generic;
using UnityEditor.Callbacks;
using UnityObject = UnityEngine.Object;
@@ -80,6 +81,7 @@ public AnimationClip animationClip
set => clip = new UnityEditor.AnimationWindowBuiltin.AnimationWindowClip(value, state.activeRootGameObject);
}
+ [VisibleToOtherModules("UnityEditor.UIToolkitAuthoringModule")]
internal IAnimationWindowSelectionItem selection
{
get => state?.selection;
@@ -171,6 +173,8 @@ internal void RefreshClip()
void OnEnable()
{
+ titleContent = GetLocalizedTitleContent();
+
if (m_AnimEditor == null)
{
m_AnimEditor = CreateInstance();
@@ -184,6 +188,7 @@ void OnEnable()
Undo.undoRedoEvent += UndoRedoPerformed;
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
+ AssemblyReloadEvents.beforeAssemblyReload += PurgeSelection;
}
void OnDisable()
@@ -193,6 +198,7 @@ void OnDisable()
Undo.undoRedoEvent -= UndoRedoPerformed;
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
+ AssemblyReloadEvents.beforeAssemblyReload -= PurgeSelection;
}
void OnDestroy()
@@ -202,10 +208,15 @@ void OnDestroy()
void Update()
{
- state?.Update();
+ // AnimationWindowState has some data that still depends on IMGUI
+ // evaluation and is initialized just in time during rendering.
+ // Make sure AnimEditor has been initialized before updating
+ // AnimationWindowState and AnimEditor.
+ if (m_AnimEditor == null || !m_AnimEditor.initialized)
+ return;
- if (m_AnimEditor != null)
- m_AnimEditor.Update();
+ state?.Update();
+ m_AnimEditor.Update();
hasUnsavedChanges = selection?.hasUnsavedChanges ?? false;
@@ -415,6 +426,7 @@ void ShowButton(Rect r)
private void UndoRedoPerformed(in UndoRedoInfo info)
{
+ OnSelectionChangeInternal(false);
Repaint();
}
@@ -428,18 +440,41 @@ private void OnPlayModeStateChanged(PlayModeStateChange state)
}
else
{
- selection?.OnPlayModeStateChanged(state);
+ // Purge selection before domain reload to prevent stale GameObject references
+ PurgeSelection();
}
}
else
{
- selection?.OnPlayModeStateChanged(state);
+ // Purge selection before domain reload on ExitingPlayMode
+ if (state == PlayModeStateChange.ExitingPlayMode)
+ {
+ PurgeSelection();
+ }
if (state == PlayModeStateChange.EnteredEditMode)
{
- // Reload selection
+ // Reload selection when exiting play mode
OnSelectionChangeInternal(false);
}
+
+ if (state == PlayModeStateChange.EnteredPlayMode)
+ {
+ // Reload selection when entering play mode
+ OnSelectionChangeInternal(false);
+ }
+ }
+ }
+
+ private void PurgeSelection()
+ {
+ // Clear selection to prevent stale GameObject references during domain reload.
+ // Note: Dispose() will also stop preview by disposing the controller.
+ // This matches the behavior during assembly reload (script compilation).
+ if (state != null)
+ {
+ state.linkedWithSequencer = false;
+ state.selection = new FallbackSelectionItem();
}
}
diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs
index 64b64abac4..114ec86dcd 100644
--- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs
+++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowCurve.cs
@@ -35,8 +35,9 @@ class AnimationWindowCurve :
private bool m_IsPhantom;
public EditorCurveBinding binding { get { return m_Binding; } }
- public bool isPPtrCurve { get { return m_Binding.isPPtrCurve; } }
- public bool isDiscreteCurve { get { return m_Binding.isDiscreteCurve; } }
+ public bool isPPtrCurve => m_Binding.isPPtrCurve;
+ public bool isDiscreteCurve => m_Binding.isDiscreteCurve;
+ public bool isFloatCurve => !m_Binding.isDiscreteCurve && !m_Binding.isPPtrCurve;
public bool isSerializeReferenceCurve { get {return m_Binding.isSerializeReferenceCurve;}}
public bool isPhantom { get { return m_IsPhantom; } set { m_IsPhantom = value; } }
public InheritanceState inheritanceState { get; set; }
diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs
index 48a8eb193e..5e9d4224fe 100644
--- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs
+++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowHierarchyGUI.cs
@@ -43,6 +43,9 @@ internal class AnimationWindowHierarchyGUI : TreeViewGUI
private const float k_ValueFieldDragWidth = 15;
private const float k_ValueFieldWidth = 80;
private const float k_ValueFieldOffsetFromRightSide = 100;
+ private const float k_ObjectFieldAdditionalWidth = 30;
+ private const float k_ObjectFieldAdditionalOffset = k_ObjectFieldAdditionalWidth + 30;
+ private const float k_ObjectFieldMaxHeight = 18;
private const float k_ColorIndicatorTopMargin = 3;
public static readonly float k_DopeSheetRowHeight = EditorGUI.kSingleLineHeight;
public static readonly float k_DopeSheetRowHeightTall = k_DopeSheetRowHeight * 2f;
@@ -156,7 +159,7 @@ public override void BeginRowGUI()
for (int i = 0; i < rowCount; ++i)
{
var propertyNode = m_TreeView.data.GetItem(i) as AnimationWindowHierarchyPropertyNode;
- if (propertyNode != null && !propertyNode.isPPtrNode)
+ if (propertyNode != null)
m_HierarchyItemValueControlIDs[i] = GUIUtility.GetControlID(FocusType.Keyboard);
else
m_HierarchyItemValueControlIDs[i] = 0; // not needed.
@@ -320,6 +323,8 @@ private void DoIconAndName(Rect rect, AnimationWindowHierarchyNode node, bool se
GUI.Label(rect, Styles.content, lineStyle);
SetStyleTextColor(lineStyle, oldColor);
+
+ GUIView.current?.MarkHotRegion(GUIClip.UnclipToWindow(rect));
}
if (IsRenaming(node.id) && Event.current.type != EventType.Layout)
@@ -349,86 +354,98 @@ private void DoValueField(Rect rect, AnimationWindowHierarchyNode node, int row)
AnimationWindowCurve curve = curves[0];
object value = CurveBindingUtility.GetCurrentValue(state, curve);
- if (!curve.isPPtrCurve)
- {
- Rect valueFieldDragRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide - k_ValueFieldDragWidth, rect.y, k_ValueFieldDragWidth, rect.height);
- Rect valueFieldRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide, rect.y, k_ValueFieldWidth, rect.height);
+ int id = m_HierarchyItemValueControlIDs[row];
- if (Event.current.type == EventType.MouseMove && valueFieldRect.Contains(Event.current.mousePosition))
- s_WasInsideValueRectFrame = Time.frameCount;
+ Rect valueFieldDragRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide - k_ValueFieldDragWidth, rect.y, k_ValueFieldDragWidth, rect.height);
+ Rect valueFieldRect = new Rect(rect.xMax - k_ValueFieldOffsetFromRightSide, rect.y, k_ValueFieldWidth, rect.height);
- EditorGUI.BeginChangeCheck();
+ if (Event.current.type == EventType.MouseMove && valueFieldRect.Contains(Event.current.mousePosition))
+ s_WasInsideValueRectFrame = Time.frameCount;
+
+ EditorGUI.BeginChangeCheck();
+
+ if (curve.isPPtrCurve)
+ {
+ var objType = curve.valueType;
- if (curve.valueType == typeof(bool))
+ if (typeof(UnityEngine.Object).IsAssignableFrom(objType))
{
- value = GUI.Toggle(valueFieldRect, m_HierarchyItemValueControlIDs[row], Convert.ToSingle(value) != 0f, GUIContent.none, EditorStyles.toggle) ? 1f : 0f;
+ var height = Mathf.Min(k_ObjectFieldMaxHeight, valueFieldRect.height);
+ var yOffset = (valueFieldRect.height - height) * 0.5f;
+ valueFieldRect = new Rect(valueFieldRect.x - k_ObjectFieldAdditionalOffset, valueFieldRect.y + yOffset, valueFieldRect.width + k_ObjectFieldAdditionalWidth, height);
+
+ value = EditorGUI.DoObjectField(valueFieldRect, valueFieldRect, id, value as UnityEngine.Object, null, objType, null, false);
}
- else
+ }
+ else if (curve.valueType == typeof(bool))
+ {
+ value = GUI.Toggle(valueFieldRect, id, Convert.ToSingle(value) != 0f, GUIContent.none, EditorStyles.toggle) ? 1f : 0f;
+ }
+ else
+ {
+ bool enterInTextField = (EditorGUIUtility.keyboardControl == id
+ && EditorGUIUtility.editingTextField
+ && Event.current.type == EventType.KeyDown
+ && (Event.current.character == '\n' || (int)Event.current.character == 3));
+
+ // Force back keyboard focus to float field editor when editing it since the TreeView forces keyboard focus on itself at mouse down.
+ // The focus will be reclaimed after the TreeViewController.OnGUI call.
+ if (EditorGUI.s_RecycledEditor.controlID == id && Event.current.type == EventType.MouseDown && valueFieldRect.Contains(Event.current.mousePosition))
{
- int id = m_HierarchyItemValueControlIDs[row];
- bool enterInTextField = (EditorGUIUtility.keyboardControl == id
- && EditorGUIUtility.editingTextField
- && Event.current.type == EventType.KeyDown
- && (Event.current.character == '\n' || (int)Event.current.character == 3));
-
- // Force back keyboard focus to float field editor when editing it since the TreeView forces keyboard focus on itself at mouse down.
- // The focus will be reclaimed after the TreeViewController.OnGUI call.
- if (EditorGUI.s_RecycledEditor.controlID == id && Event.current.type == EventType.MouseDown && valueFieldRect.Contains(Event.current.mousePosition))
- {
- m_NeedsToReclaimFieldFocus = true;
- m_FieldToReclaimFocus = id;
- }
+ m_NeedsToReclaimFieldFocus = true;
+ m_FieldToReclaimFocus = id;
+ }
- if (curve.isDiscreteCurve)
+ if (curve.isDiscreteCurve)
+ {
+ value = EditorGUI.DoIntField(EditorGUI.s_RecycledEditor,
+ valueFieldRect,
+ valueFieldDragRect,
+ id,
+ Convert.ToInt32(value),
+ EditorGUI.kIntFieldFormatString,
+ m_AnimationSelectionTextField,
+ true,
+ 0);
+ if (enterInTextField)
{
- value = EditorGUI.DoIntField(EditorGUI.s_RecycledEditor,
- valueFieldRect,
- valueFieldDragRect,
- id,
- Convert.ToInt32(value),
- EditorGUI.kIntFieldFormatString,
- m_AnimationSelectionTextField,
- true,
- 0);
- if (enterInTextField)
- {
- GUI.changed = true;
- Event.current.Use();
- }
+ GUI.changed = true;
+ Event.current.Use();
}
- else
+ }
+ else
+ {
+ value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor,
+ valueFieldRect,
+ valueFieldDragRect,
+ id,
+ Convert.ToSingle(value),
+ "g5",
+ m_AnimationSelectionTextField,
+ true);
+ if (enterInTextField)
{
- value = EditorGUI.DoFloatField(EditorGUI.s_RecycledEditor,
- valueFieldRect,
- valueFieldDragRect,
- id,
- Convert.ToSingle(value),
- "g5",
- m_AnimationSelectionTextField,
- true);
- if (enterInTextField)
- {
- GUI.changed = true;
- Event.current.Use();
- }
-
- var floatValue = Convert.ToSingle(value);
- if (float.IsInfinity(floatValue) || float.IsNaN(floatValue))
- value = 0f;
+ GUI.changed = true;
+ Event.current.Use();
}
+
+ var floatValue = Convert.ToSingle(value);
+ if (float.IsInfinity(floatValue) || float.IsNaN(floatValue))
+ value = 0f;
}
+ }
- if (EditorGUI.EndChangeCheck())
- {
- string undoLabel = "Edit Key";
+ if (EditorGUI.EndChangeCheck())
+ {
+ string undoLabel = "Edit Key";
- AnimationKeyTime newAnimationKeyTime = AnimationKeyTime.Time(state.currentTime, curve.clip.frameRate);
- AnimationWindowUtility.AddKeyframeToCurve(curve, value, curve.valueType, newAnimationKeyTime);
+ AnimationKeyTime newAnimationKeyTime = AnimationKeyTime.Time(state.currentTime, curve.clip.frameRate);
+ AnimationWindowUtility.AddKeyframeToCurve(curve, value, curve.valueType, newAnimationKeyTime);
- state.SaveCurve(curve.clip, curve, undoLabel);
- curvesChanged = true;
- }
+ state.SaveCurve(curve.clip, curve, undoLabel);
+ curvesChanged = true;
}
+
}
if (curvesChanged)
@@ -458,6 +475,7 @@ private bool DoTreeViewButton(int id, Rect position, GUIContent content, GUIStyl
{
case EventType.Repaint:
style.Draw(position, content, id, false, position.Contains(evt.mousePosition));
+ GUIView.current?.MarkHotRegion(GUIClip.UnclipToWindow(position));
break;
case EventType.MouseDown:
if (position.Contains(evt.mousePosition) && evt.button == 0)
diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs
index 134bc4fac4..97295ebd4c 100644
--- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs
+++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowKeyframe.cs
@@ -101,8 +101,9 @@ public AnimationWindowCurve curve
}
}
- public bool isPPtrCurve { get { return curve.isPPtrCurve; } }
- public bool isDiscreteCurve { get { return curve.isDiscreteCurve; } }
+ public bool isPPtrCurve => curve.isPPtrCurve;
+ public bool isDiscreteCurve => curve.isDiscreteCurve;
+ public bool isFloatCurve => curve.isFloatCurve;
public AnimationWindowKeyframe()
{
diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs
index bed8e50ef2..3bc7d1e0fd 100644
--- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs
+++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowState.cs
@@ -7,7 +7,7 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
-using UnityEditor.IMGUI.Controls;
+using Unity.Collections;
using Object = UnityEngine.Object;
using TreeViewItem = UnityEditor.IMGUI.Controls.TreeViewItem;
using static UnityEditor.AnimationUtility;
@@ -74,7 +74,7 @@ public enum SnapMode
private EditorCurveBinding? m_lastAddedCurveBinding;
// Hash of all the things that require animationWindow to refresh if they change
- private int m_PreviousRefreshHash;
+ [NonSerialized] private int m_PreviousRefreshHash;
// Changing m_Refresh means you are ordering a refresh at the next Update ().
// CurvesOnly means that there is no need to refresh the hierarchy, since only the keyframe data changed.
@@ -334,16 +334,9 @@ public void RefreshCurve(EditorCurveBinding binding)
}
}
- private void PurgeSelection()
- {
- linkedWithSequencer = false;
- m_Selection = new FallbackSelectionItem();
- }
-
public void OnEnable()
{
Undo.undoRedoEvent += UndoRedoPerformed;
- AssemblyReloadEvents.beforeAssemblyReload += PurgeSelection;
AnimationUtility.onCurveWasModified += CurveWasModified;
// NoOps...
@@ -358,7 +351,6 @@ public void OnEnable()
public void OnDisable()
{
Undo.undoRedoEvent -= UndoRedoPerformed;
- AssemblyReloadEvents.beforeAssemblyReload -= PurgeSelection;
AnimationUtility.onCurveWasModified -= CurveWasModified;
previewing = false;
@@ -609,9 +601,7 @@ public bool ShouldShowCurve(AnimationWindowCurve curve)
Transform t = activeRootGameObject.transform.Find(curve.path);
if (t != null)
{
-#pragma warning disable UA2001 // The Banned API Analyzer produces compile errors for any new Linq code. This pre-existing usage has been suppressed, but should be rewritten if possible.
if (!m_SelectionFilter.Contains(t.gameObject.GetEntityId()))
-#pragma warning restore UA2001
return false;
}
else
diff --git a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs b/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs
index 1826e9f50a..9ceae02a7e 100644
--- a/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs
+++ b/Editor/Mono/Animation/AnimationWindow/AnimationWindowUtility.cs
@@ -314,7 +314,7 @@ public static bool ContainsFloatKeyframes(List keyframe
foreach (var key in keyframes)
{
- if (!key.isPPtrCurve)
+ if (key.isFloatCurve)
return true;
}
diff --git a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationClipSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationClipSelectionItem.cs
index dedcbc0b8e..dff9e4a52c 100644
--- a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationClipSelectionItem.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationClipSelectionItem.cs
@@ -16,6 +16,9 @@ internal class AnimationClipSelectionItem : AnimationWindowSelectionItem
{
}
+ public static AnimationClipSelectionItem Create(AnimationClip animationClip, Object sourceObject = null) =>
+ Create(null, animationClip, sourceObject);
+
public static AnimationClipSelectionItem Create(AnimationWindow window, AnimationClip animationClip, Object sourceObject = null)
{
var selectionItem = new AnimationClipSelectionItem(window);
diff --git a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowControl.cs b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowControl.cs
index 5608260b19..2e2cadfb13 100644
--- a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowControl.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowControl.cs
@@ -19,14 +19,6 @@ namespace UnityEditor.AnimationWindowBuiltin
[Serializable]
class AnimationWindowControl : IAnimationWindowController, IAnimationContextualResponder
{
- public AnimationWindowControl()
- {
- if (AnimationMode.GetDriver() is MainDriver mainDriver)
- m_Driver = mainDriver;
- }
-
- class MainDriver: AnimationModeDriver {}
- class CandidateDriver: AnimationModeDriver {}
class CandidateRecordingState : IAnimationRecordingState
{
public GameObject activeGameObject { get; private set; }
@@ -174,7 +166,9 @@ public void Dispose()
{
StopPreview();
if (m_Driver != null)
+ {
ScriptableObject.DestroyImmediate(m_Driver);
+ }
}
public void OnSelectionChanged()
@@ -186,15 +180,6 @@ public void OnSelectionChanged()
StopPreview();
}
- public void OnPlayModeStateChanged(PlayModeStateChange state)
- {
- if (state == PlayModeStateChange.ExitingPlayMode ||
- state == PlayModeStateChange.ExitingEditMode)
- {
- StopPreview();
- }
- }
-
public float time
{
get => m_Time.time;
@@ -361,8 +346,11 @@ public bool canPreview
if (state.activeAnimationPlayer is Animator{ isOptimizable:true, hasTransformHierarchy:false})
return false;
+
var driver = GetAnimationModeDriverNoAlloc();
- return (driver != null && AnimationMode.InAnimationMode(driver)) || !AnimationMode.InAnimationMode();
+
+ return !AnimationMode.InAnimationMode() // no one is in mode
+ || (driver != null && AnimationMode.InAnimationMode(driver));
}
}
@@ -696,7 +684,7 @@ private AnimationModeDriver GetAnimationModeDriver()
{
if (m_Driver == null)
{
- m_Driver = ScriptableObject.CreateInstance();
+ m_Driver = ScriptableObject.CreateInstance();
m_Driver.hideFlags = HideFlags.HideAndDontSave;
m_Driver.name = "AnimationWindowDriver";
m_Driver.isKeyCallback += (Object target, string propertyPath) =>
@@ -726,7 +714,7 @@ private AnimationModeDriver GetCandidateDriver()
{
if (m_CandidateDriver == null)
{
- m_CandidateDriver = ScriptableObject.CreateInstance();
+ m_CandidateDriver = ScriptableObject.CreateInstance();
m_CandidateDriver.name = "AnimationWindowCandidateDriver";
}
diff --git a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowEventInspector.cs b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowEventInspector.cs
index abf968e86b..0a97e3aca4 100644
--- a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowEventInspector.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowEventInspector.cs
@@ -16,7 +16,8 @@ namespace UnityEditor.AnimationWindowBuiltin
internal class AnimationWindowEventInspector : UnityEditor.Editor
{
public static GUIContent s_OverloadWarning = EditorGUIUtility.TrTextContent("Some functions were overloaded in MonoBehaviour components and may not work as intended if used with Animation Events!");
- public static GUIContent s_DuplicatesWarning = EditorGUIUtility.TrTextContent("Some functions have the same name across several Monobehaviour components and may not work as intended if used with Animation Events!");
+ public static GUIContent s_DuplicatesWarning = EditorGUIUtility.TrTextContent("Some functions have the same name across several MonoBehaviour components and may not work as intended if used with Animation Events!");
+ public static GUIContent s_RequireMethod = EditorGUIUtility.TrTextContent("Require Receiver", "When enabled, an error will be emitted if there is no matching method on the GameObject.");
const string kNotSupportedPostFix = " (Function Not Supported)";
const string kNoneSelected = "(No Function Selected)";
@@ -56,6 +57,7 @@ public static void OnEditAnimationEvents(AnimationWindowEvent[] awEvents, Animat
AnimationEvent firstEvent = data.selectedEvents[0];
bool singleFunctionName = Array.TrueForAll(data.selectedEvents, evt => evt.functionName == firstEvent.functionName);
+ bool singleMessageOptions = Array.TrueForAll(data.selectedEvents, evt => evt.messageOptions == firstEvent.messageOptions);
EditorGUI.BeginChangeCheck();
@@ -102,17 +104,38 @@ public static void OnEditAnimationEvents(AnimationWindowEvent[] awEvents, Animat
EditorGUIUtility.labelWidth = 130;
EditorGUI.showMixedValue = !singleFunctionName;
- int wasSelected = singleFunctionName ? selected : -1;
+
+ EditorGUI.BeginChangeCheck();
selected = EditorGUILayout.Popup("Function: ", selected, methodsFormatted);
- if (wasSelected != selected && selected != -1 && selected != notSupportedIndex)
+ if (EditorGUI.EndChangeCheck())
+ {
+ if (selected >= 0 && selected < notSupportedIndex)
+ {
+ foreach (var evt in data.selectedEvents)
+ {
+ evt.functionName = supportedMethods[selected].Name;
+ evt.stringParameter = string.Empty;
+ }
+ }
+ }
+
+ EditorGUI.showMixedValue = false;
+
+ EditorGUI.indentLevel++;
+ EditorGUI.showMixedValue = !singleMessageOptions;
+ bool requireReceiver = EditorGUILayout.Toggle(
+ s_RequireMethod,
+ firstEvent.messageOptions == SendMessageOptions.RequireReceiver);
+ var sendMessageOptions = requireReceiver ? SendMessageOptions.RequireReceiver : SendMessageOptions.DontRequireReceiver;
+ if (sendMessageOptions != firstEvent.messageOptions)
{
foreach (var evt in data.selectedEvents)
{
- evt.functionName = supportedMethods[selected].Name;
- evt.stringParameter = string.Empty;
+ evt.messageOptions = sendMessageOptions;
}
}
EditorGUI.showMixedValue = false;
+ EditorGUI.indentLevel--;
var selectedParameter = supportedMethods[selected].parameterType;
@@ -150,6 +173,7 @@ public static void OnEditAnimationEvents(AnimationWindowEvent[] awEvents, Animat
GUILayout.Label(duplicatedFunctionDetails, EditorStyles.helpBox);
}
}
+
}
else
{
@@ -165,6 +189,21 @@ public static void OnEditAnimationEvents(AnimationWindowEvent[] awEvents, Animat
}
EditorGUI.showMixedValue = false;
+ EditorGUI.indentLevel++;
+ EditorGUI.showMixedValue = !singleMessageOptions;
+ bool wasRequiringReceiver = firstEvent.messageOptions == SendMessageOptions.RequireReceiver;
+ bool nowRequireReceiver = EditorGUILayout.Toggle(s_RequireMethod, wasRequiringReceiver);
+ var sendMessageOptions = nowRequireReceiver ? SendMessageOptions.RequireReceiver : SendMessageOptions.DontRequireReceiver;
+ if (wasRequiringReceiver != nowRequireReceiver)
+ {
+ foreach (var evt in data.selectedEvents)
+ {
+ evt.messageOptions = sendMessageOptions;
+ }
+ }
+ EditorGUI.showMixedValue = false;
+ EditorGUI.indentLevel--;
+
if (singleFunctionName)
{
DoEditRegularParameters(data.selectedEvents, typeof(AnimationEvent));
@@ -228,6 +267,9 @@ public static void OnDisabledAnimationEvent()
using (new EditorGUI.DisabledScope(true))
{
dummyEvent.functionName = EditorGUILayout.TextField(EditorGUIUtility.TrTextContent("Function"), dummyEvent.functionName);
+ EditorGUI.indentLevel++;
+ dummyEvent.m_MessageOptions = EditorGUILayout.Toggle(s_RequireMethod, dummyEvent.messageOptions == SendMessageOptions.RequireReceiver) ? 0 : 1;
+ EditorGUI.indentLevel--;
DoEditRegularParameters(new AnimationEvent[] { dummyEvent }, typeof(AnimationEvent));
}
}
diff --git a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowSelectionItem.cs
index d9fac4d217..855d4f632b 100644
--- a/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowSelectionItem.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Builtin/AnimationWindowSelectionItem.cs
@@ -5,10 +5,12 @@
using System;
using UnityEditorInternal;
using UnityEngine;
+using UnityEngine.Bindings;
namespace UnityEditor.AnimationWindowBuiltin
{
[Serializable]
+ [VisibleToOtherModules("UnityEditor.UIToolkitAuthoringModule")]
abstract class AnimationWindowSelectionItem : System.IEquatable, IAnimationWindowSelectionItem
{
[SerializeField] protected AnimationWindow m_Window;
@@ -293,11 +295,6 @@ public void DiscardChanges()
throw new NotImplementedException();
}
- public virtual void OnPlayModeStateChanged(PlayModeStateChange state)
- {
- controller.OnPlayModeStateChanged(state);
- }
-
// When curve is modified, we never trigger refresh right away. We order a refresh at later time by setting refresh to appropriate value.
public virtual void CurveWasModified(AnimationClip clip, EditorCurveBinding binding, AnimationUtility.CurveModifiedType type)
{
diff --git a/Editor/Mono/Animation/AnimationWindow/Builtin/GameObjectSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/Builtin/GameObjectSelectionItem.cs
index 25df3002c7..03207e4d85 100644
--- a/Editor/Mono/Animation/AnimationWindow/Builtin/GameObjectSelectionItem.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Builtin/GameObjectSelectionItem.cs
@@ -5,10 +5,12 @@
using System;
using UnityEngine;
using UnityEditorInternal;
+using UnityEngine.Bindings;
namespace UnityEditor.AnimationWindowBuiltin
{
[Serializable]
+ [VisibleToOtherModules("UnityEditor.UIToolkitAuthoringModule")]
class GameObjectSelectionItem : AnimationWindowSelectionItem
{
protected GameObjectSelectionItem(AnimationWindow window) : base(window)
diff --git a/Editor/Mono/Animation/AnimationWindow/Builtin/RotationCurveInterpolation.cs b/Editor/Mono/Animation/AnimationWindow/Builtin/RotationCurveInterpolation.cs
index 271f2c8ecb..8847bc24d2 100644
--- a/Editor/Mono/Animation/AnimationWindow/Builtin/RotationCurveInterpolation.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Builtin/RotationCurveInterpolation.cs
@@ -11,7 +11,7 @@
namespace UnityEditor.AnimationWindowBuiltin
{
- class RotationCurveInterpolation
+ static class RotationCurveInterpolation
{
public struct State
{
@@ -36,7 +36,7 @@ internal static EditorCurveBinding[] GenerateTransformCurveBindingArray(string p
return bindings;
}
- static public EditorCurveBinding[] RemapAnimationBindingForAddKey(EditorCurveBinding binding, AnimationClip clip)
+ public static EditorCurveBinding[] RemapAnimationBindingForAddKey(EditorCurveBinding binding, AnimationClip clip)
{
if (!AnimationWindowUtility.IsTransformType(binding.type))
{
@@ -83,7 +83,7 @@ static EditorCurveBinding[] SelectRotationBindingForAddKey(EditorCurveBinding bi
}
}
- static public EditorCurveBinding RemapAnimationBindingForRotationCurves(EditorCurveBinding curveBinding, AnimationClip clip)
+ public static EditorCurveBinding RemapAnimationBindingForRotationCurves(EditorCurveBinding curveBinding, AnimationClip clip)
{
if (!AnimationWindowUtility.IsTransformType(curveBinding.type))
return curveBinding;
diff --git a/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs b/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs
index dbe8c45ece..a9b8945adb 100644
--- a/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs
+++ b/Editor/Mono/Animation/AnimationWindow/CurveEditorSettings.cs
@@ -2,6 +2,7 @@
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
+using System;
using UnityEngine;
namespace UnityEditor
@@ -46,6 +47,7 @@ public bool hasUnboundedRanges
// Offset to move the labels along the horizontal axis to make room for the overlaid scrollbar in the
// curve editor popup.
public float hTickLabelOffset = 0;
+ [NonSerialized]
public EditorGUIUtility.SkinnedColor wrapColor = new EditorGUIUtility.SkinnedColor(new Color(1.0f, 1.0f, 1.0f, 0.5f), new Color(.65f, .65f, .65f, 0.5f));
public bool useFocusColors = false;
public bool showAxisLabels = true;
diff --git a/Editor/Mono/Animation/AnimationWindow/DefaultAnimationWindowController.cs b/Editor/Mono/Animation/AnimationWindow/DefaultAnimationWindowController.cs
index 88b1161a2d..7ced4114fd 100644
--- a/Editor/Mono/Animation/AnimationWindow/DefaultAnimationWindowController.cs
+++ b/Editor/Mono/Animation/AnimationWindow/DefaultAnimationWindowController.cs
@@ -16,7 +16,6 @@ class DefaultAnimationWindowController : IAnimationWindowController
public void Dispose() {}
public void OnSelectionChanged() {}
- public void OnPlayModeStateChanged(PlayModeStateChange state) { }
public float time
{
diff --git a/Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs b/Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs
index daf0aee36a..f9d445e143 100644
--- a/Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs
+++ b/Editor/Mono/Animation/AnimationWindow/DopeSheetEditor.cs
@@ -255,7 +255,7 @@ public void OnGUI(Rect position, Vector2 scrollPosition)
Init();
// drag'n'drops outside any dopelines
- HandleDragAndDropToEmptyArea();
+ HandleDragAndDropToEmptyArea(position);
GUIClip.Push(position, scrollPosition, Vector2.zero, false);
@@ -589,7 +589,7 @@ private GenericMenu GenerateMenu(DopeLine dopeline)
Hashtable editorCurves = new Hashtable();
foreach (AnimationWindowKeyframe key in state.selectedKeys)
{
- if (key.isDiscreteCurve)
+ if (!key.isFloatCurve)
continue;
int index = key.curve.GetKeyframeIndex(AnimationKeyTime.Time(key.time, state.frameRate));
@@ -754,13 +754,17 @@ private void HandleSelectionRect(Rect rect)
}
// Handles drag and drop into empty area outside dopelines
- private void HandleDragAndDropToEmptyArea()
+ private void HandleDragAndDropToEmptyArea(Rect dopeSheetArea)
{
Event evt = Event.current;
if (evt.type != EventType.DragPerform && evt.type != EventType.DragUpdated)
return;
+ // Only handle drag and drop if the mouse is inside the DopeSheet area
+ if (!dopeSheetArea.Contains(evt.mousePosition))
+ return;
+
if (!ValidateDragAndDropObjects())
return;
@@ -1342,7 +1346,7 @@ internal class DopeSheetSelectionRect
enum SelectionType { Normal, Additive, Subtractive }
public readonly GUIStyle createRect = "U2D.createRect";
- static int s_RectSelectionID = GUIUtility.GetPermanentControlID();
+ readonly int m_RectSelectionID = GUIUtility.GetPermanentControlID();
public DopeSheetSelectionRect(DopeSheetEditor owner)
{
@@ -1353,7 +1357,7 @@ public void OnGUI(Rect position)
{
Event evt = Event.current;
Vector2 mousePos = evt.mousePosition;
- int id = s_RectSelectionID;
+ int id = m_RectSelectionID;
switch (evt.GetTypeForControl(id))
{
case EventType.MouseDown:
diff --git a/Editor/Mono/Animation/AnimationWindow/FallbackSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/FallbackSelectionItem.cs
index 0d922e35f6..8cde0bb53c 100644
--- a/Editor/Mono/Animation/AnimationWindow/FallbackSelectionItem.cs
+++ b/Editor/Mono/Animation/AnimationWindow/FallbackSelectionItem.cs
@@ -79,10 +79,6 @@ public Type GetValueType(EditorCurveBinding _)
return null;
}
- public void OnPlayModeStateChanged(PlayModeStateChange state)
- {
- }
-
public bool isImported => false;
public bool hasUnsavedChanges => false;
public void SaveChanges()
diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowClip.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowClip.cs
index f9f67978d3..f79200831d 100644
--- a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowClip.cs
+++ b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowClip.cs
@@ -6,12 +6,14 @@
using System.Collections.Generic;
using UnityEditorInternal;
using UnityEngine;
+using UnityEngine.Bindings;
namespace UnityEditor
{
///
/// Use this interface to control how an animation clip is authored in the AnimationWindow.
///
+ [VisibleToOtherModules("UnityEditor.UIToolkitAuthoringModule")]
interface IAnimationWindowClip : IEquatable
{
string name { get; }
diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs
index a0b2b49002..b95ff6fde8 100644
--- a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs
+++ b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowControl.cs
@@ -21,10 +21,6 @@ public virtual void OnEnable()
public abstract void OnSelectionChanged();
- public void OnPlayModeStateChanged(PlayModeStateChange state)
- {
- }
-
public void Init(AnimationWindowState state)
{
m_State = state;
diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowController.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowController.cs
index 730865cd50..5859e47c2e 100644
--- a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowController.cs
+++ b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowController.cs
@@ -13,8 +13,6 @@ interface IAnimationWindowController : IDisposable
{
void OnSelectionChanged();
- void OnPlayModeStateChanged(PlayModeStateChange state);
-
float time { get; set; }
int frame { get; set; }
diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowResponder.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowResponder.cs
index e5d8cd0184..4261bfca87 100644
--- a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowResponder.cs
+++ b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowResponder.cs
@@ -2,6 +2,8 @@
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
+using UnityEngine.Bindings;
+
namespace UnityEditor
{
///
@@ -9,6 +11,7 @@ namespace UnityEditor
/// This allow any custom component to provide its own [IAnimationWindowSelectionItem] to the AnimationWindow
/// and control how animation is authored and evaluated.
///
+ [VisibleToOtherModules("UnityEditor.UIToolkitAuthoringModule")]
interface IAnimationWindowResponder
{
bool OnSelectionChange(AnimationWindow window, UnityEngine.Object selectedObject, out IAnimationWindowSelectionItem newSelection);
diff --git a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowSelectionItem.cs b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowSelectionItem.cs
index 78c39215f6..305aac5f23 100644
--- a/Editor/Mono/Animation/AnimationWindow/IAnimationWindowSelectionItem.cs
+++ b/Editor/Mono/Animation/AnimationWindow/IAnimationWindowSelectionItem.cs
@@ -4,6 +4,7 @@
using System;
using UnityEngine;
+using UnityEngine.Bindings;
namespace UnityEditor
{
@@ -12,6 +13,7 @@ namespace UnityEditor
/// This allows to control how clips are created and managed in the AnimationWindow.
/// Also, this gives the ability to customize how animation is authored.
///
+ [VisibleToOtherModules("UnityEditor.UIToolkitAuthoringModule")]
interface IAnimationWindowSelectionItem : ISelectionBinding, IDisposable
{
GameObject gameObject { get; }
@@ -34,7 +36,6 @@ interface IAnimationWindowSelectionItem : ISelectionBinding, IDisposable
IAnimationWindowClip[] GetClips();
IAnimationWindowClip CreateNewClip();
bool InitializeSelection();
- void OnPlayModeStateChanged(PlayModeStateChange state);
bool IsCompatibleWith(UnityEngine.Object selectedObject);
EditorCurveBinding[] GetAnimatableBindings(GameObject gameObject);
diff --git a/Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs b/Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs
index ece0fffa22..26f6527822 100644
--- a/Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs
+++ b/Editor/Mono/Animation/AnimationWindow/RotationCurveInterpolation.cs
@@ -3,11 +3,13 @@
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
using UnityEditorInternal;
namespace UnityEditor
{
- partial class RotationCurveInterpolation
+ static partial class RotationCurveInterpolation
{
public enum Mode { Baked, NonBaked, RawQuaternions, RawEuler, Undefined }
@@ -42,27 +44,38 @@ public static string GetPrefixForInterpolation(Mode newInterpolationMode)
return null;
}
+ static List s_BindingsCache;
+ const string s_PropertyWithSuffixRegex = @"(?\.[xyz])$";
internal static EditorCurveBinding[] ConvertRotationPropertiesToInterpolationType(ReadOnlySpan selection, Mode newInterpolationMode)
{
- if (selection.Length != 4)
- return selection.ToArray();
+ s_BindingsCache ??= new List(4);
+ if (s_BindingsCache.Capacity < selection.Length)
+ s_BindingsCache.Capacity = selection.Length;
- if (GetModeFromCurveData(selection[0]) == Mode.RawQuaternions)
+ s_BindingsCache.Clear();
+ for (int i = 0; i < selection.Length; ++i)
{
- EditorCurveBinding[] newCurves = new EditorCurveBinding[3];
- newCurves[0] = selection[0];
- newCurves[1] = selection[1];
- newCurves[2] = selection[2];
+ if (GetModeFromCurveData(selection[i]) == Mode.RawQuaternions)
+ {
+ // Process x, y, z rotation bindings. Drop w channel.
+ var match = Regex.Match(selection[i].propertyName, s_PropertyWithSuffixRegex);
+ if (match.Success)
+ {
+ string prefix = GetPrefixForInterpolation(newInterpolationMode);
- string prefix = GetPrefixForInterpolation(newInterpolationMode);
- newCurves[0].propertyName = prefix + ".x";
- newCurves[1].propertyName = prefix + ".y";
- newCurves[2].propertyName = prefix + ".z";
+ var newBinding = selection[i];
+ newBinding.propertyName = prefix + match.Groups["suffix"];
- return newCurves;
+ s_BindingsCache.Add(newBinding);
+ }
+ }
+ else
+ {
+ s_BindingsCache.Add(selection[i]);
+ }
}
- else
- return selection.ToArray();
+
+ return s_BindingsCache.ToArray();
}
}
}
diff --git a/Editor/Mono/Animation/AnimationWindow/TimelineCompatibilityFunctions.cs b/Editor/Mono/Animation/AnimationWindow/TimelineCompatibilityFunctions.cs
index 68ec18ad67..ccdb8568df 100644
--- a/Editor/Mono/Animation/AnimationWindow/TimelineCompatibilityFunctions.cs
+++ b/Editor/Mono/Animation/AnimationWindow/TimelineCompatibilityFunctions.cs
@@ -10,7 +10,7 @@
// Compatibility functions to support Timeline's use of the AnimationWindow internal API
namespace UnityEditor
{
- partial class RotationCurveInterpolation
+ static partial class RotationCurveInterpolation
{
public static EditorCurveBinding RemapAnimationBindingForRotationCurves(EditorCurveBinding curveBinding, AnimationClip clip) =>
AnimationWindowBuiltin.RotationCurveInterpolation.RemapAnimationBindingForRotationCurves(curveBinding, clip);
diff --git a/Editor/Mono/Animation/AnimationWindow/Widgets/ClipDropdownField.cs b/Editor/Mono/Animation/AnimationWindow/Widgets/ClipDropdownField.cs
index d8ae89a452..9a8267c7f4 100644
--- a/Editor/Mono/Animation/AnimationWindow/Widgets/ClipDropdownField.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Widgets/ClipDropdownField.cs
@@ -55,14 +55,18 @@ internal override void AddMenuItems(AbstractGenericMenu menu)
choices = GetOrderedClipList();
foreach (var menuItem in choices)
{
- var isSelected = (menuItem == value) && !showMixedValue;
+ var isSelected = menuItem.Equals(value) && !showMixedValue;
menu.AddItem(
GetListItemToDisplay(menuItem),
isSelected,
() => ChangeValueFromMenu(menuItem));
}
- menu.AddSeparator(String.Empty);
- menu.AddItem(s_CreateNewClip, false, CreateNewClipFromMenu);
+
+ if (m_State.selection.canChangeClip)
+ {
+ menu.AddSeparator(String.Empty);
+ menu.AddItem(s_CreateNewClip, false, CreateNewClipFromMenu);
+ }
}
new string GetListItemToDisplay(IAnimationWindowClip clip) =>
diff --git a/Editor/Mono/Animation/AnimationWindow/Widgets/Layout.cs b/Editor/Mono/Animation/AnimationWindow/Widgets/Layout.cs
index 578cf5ae6b..918fe91192 100644
--- a/Editor/Mono/Animation/AnimationWindow/Widgets/Layout.cs
+++ b/Editor/Mono/Animation/AnimationWindow/Widgets/Layout.cs
@@ -13,6 +13,7 @@
using UnityEditor.Animations.AnimationWindow.TimelineFoundation;
using UnityEditor.AnimationWindowBuiltin;
using UnityEditor.Experimental;
+using UnityEditor.ShortcutManagement;
using UnityEditor.UIElements;
using UnityEngine.Playables;
@@ -27,6 +28,8 @@ class Layout : VisualElement, IDisposable
const string k_AnimationPropertyHeader = "animation-propertyHeader";
const string k_AnimationControls = "animation-controls";
const string k_AnimationTimeArea = "animation-timeArea";
+ const string k_AnimationTimeAreaLeftOverlap = "animation-timeArea-leftOverlap";
+ const string k_AnimationTimeAreaRightOverlap = "animation-timeArea-rightOverlap";
const string k_AnimationContentOverlay = "animation-contentsOverlay";
@@ -41,6 +44,7 @@ class Layout : VisualElement, IDisposable
const string k_AnimationAddPropertyButton = "animation-addPropertyButton";
const string k_AnimationAddKeyframeButton = "animation-addKeyframeButton";
const string k_AnimationAddEventButton = "animation-addEventButton";
+ const string k_AnimationModeRippleToggle = "animation-modeRippleToggle";
const string k_AnimationFilterBySelectionToggle = "animation-filterBySelectionToggle";
const string k_AnimationApplyButton = "animation-applyButton";
@@ -66,10 +70,11 @@ class Layout : VisualElement, IDisposable
static string s_RevertContentTooltip = L10n.Tr("Discard changes made to imported animation.");
static string s_ApplyContentTooltip = L10n.Tr("Apply changes made to imported animation.");
- static string s_AddKeyframeContentTooltip = L10n.Tr("Add keyframe.");
+ static string s_AddKeyframeContentTooltip = L10n.Tr("Add keyframe ({0}).");
static string s_AddEventContentTooltip = L10n.Tr("Add event.");
static string s_FilterBySelectionContentTooltip = L10n.Tr("Filter by selection.");
static string s_SequencerLinkContentTooltip = L10n.Tr("Animation Window is linked to Timeline Editor. Press to Unlink.");
+ static string s_ModeRippleContentTooltip = L10n.Tr("Ripple mode ({0}).");
const float k_LeftMargin = 40f;
const float k_RightMargin = 40f;
@@ -77,11 +82,13 @@ class Layout : VisualElement, IDisposable
class DopesheetButton : IToggleButtonItem
{
public string Name => L10n.Tr("Dopesheet");
+ public string Tooltip => L10n.Tr($"Show Dopesheet ({ShortcutManager.instance.GetShortcutBinding("Animation/Show Curves")})");
}
class CurveEditorButton : IToggleButtonItem
{
public string Name => L10n.Tr("Curves");
+ public string Tooltip => L10n.Tr($"Show Curves ({ShortcutManager.instance.GetShortcutBinding("Animation/Show Curves")})");
}
AnimEditor m_AnimEditor;
@@ -97,6 +104,8 @@ class CurveEditorButton : IToggleButtonItem
HierarchyElement m_HierarchyElement;
AnimationEventTimelineElement m_AnimationEventTimeline;
TimelineFoundation.TimeArea m_TimeArea;
+ VisualElement m_TimeAreaLeftOverlap;
+ VisualElement m_TimeAreaRightOverlap;
VisualElement m_OnboardingPanel;
Label m_OnboardingPanelLabel;
@@ -107,6 +116,7 @@ class CurveEditorButton : IToggleButtonItem
Button m_AddPropertyButton;
Button m_AddKeyframeButton;
Button m_AddEventButton;
+ ToolbarToggle m_ModeRippleToggle;
ToolbarToggle m_FilterBySelectionToggle;
ToggleButtonStrip m_ContentSwitcherButtons;
@@ -128,9 +138,7 @@ class CurveEditorButton : IToggleButtonItem
HeaderResizeManipulator m_HeaderResizeManipulator;
PlayHeadOverlay m_PlayHeadOverlay;
- PlayHeadOverlay m_DurationOverlay;
TimeDragManipulator m_PlayHeadDragManipulator;
- TimeDragManipulator m_DurationDragManipulator;
TimeDragManipulator m_TimeAreaDragManipulator;
EventsOverlay m_EventsOverlay;
@@ -184,14 +192,6 @@ void InitPlayHead()
m_Canvas = new CanvasManager(m_CanvasOverlayManager, state);
m_CanvasOverlayManager.canvas = m_Canvas;
- m_DurationOverlay = new PlayHeadOverlay();
- m_DurationOverlay.name = "preview-duration-overlay";
- m_CanvasOverlayManager.AddOverlay(m_DurationOverlay);
-
- m_DurationDragManipulator = new TimeDragManipulator(m_Canvas);
- SetupTimeDragManipulator(m_DurationDragManipulator);
- m_DurationOverlay.AddManipulator(m_DurationDragManipulator);
-
m_PlayHeadOverlay = new PlayHeadOverlay(PickingMode.Position);
m_CanvasOverlayManager.AddOverlay(m_PlayHeadOverlay);
@@ -241,6 +241,8 @@ void InitAnimationContent()
m_AnimationControls = this.Q(className: k_AnimationControls);
m_OnboardingPanel = this.Q(className: k_AnimationOnboarding);
+ m_OnboardingPanel.EnableInClassList(k_AnimationOnboarding + "__hidden", true);
+
m_OnboardingPanelLabel = m_OnboardingPanel.Q