diff options
| author | Andrew Lee <alee14498@protonmail.com> | 2020-04-19 17:19:32 -0400 |
|---|---|---|
| committer | Andrew Lee <alee14498@protonmail.com> | 2020-04-19 17:19:32 -0400 |
| commit | c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78 (patch) | |
| tree | ee4d51c7c1d633e11f46453ef1edd3c77c4ef9f7 /Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors | |
| download | Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.tar.gz Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.tar.bz2 Project-Sandbox-c55fba8ab2a1c9d3df65eda4a5a1e957f4aa1f78.zip | |
Inital commit
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors')
38 files changed, 3530 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationPlayableAssetInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationPlayableAssetInspector.cs new file mode 100644 index 0000000..2aaa970 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationPlayableAssetInspector.cs @@ -0,0 +1,341 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [CustomEditor(typeof(AnimationPlayableAsset)), CanEditMultipleObjects] + class AnimationPlayableAssetInspector : Editor + { + static class Styles + { + public static readonly GUIContent RotationText = EditorGUIUtility.TrTextContent("Rotation"); + public static readonly GUIContent AnimClipText = EditorGUIUtility.TrTextContent("Animation Clip"); + public static readonly GUIContent TransformOffsetTitle = EditorGUIUtility.TrTextContent("Clip Transform Offsets", "Use this to offset the root transform position and rotation relative to the track when playing this clip"); + public static readonly GUIContent AnimationClipName = EditorGUIUtility.TrTextContent("Animation Clip Name"); + public static readonly GUIContent MatchTargetFieldsTitle = EditorGUIUtility.TrTextContent("Offsets Match Fields", "Fields to apply when matching offsets on clips. The defaults can be set on the track."); + public static readonly GUIContent UseDefaults = EditorGUIUtility.TrTextContent("Use defaults"); + public static readonly GUIContent RemoveStartOffset = EditorGUIUtility.TrTextContent("Remove Start Offset", "Makes playback of the clip play relative to first key of the root transform"); + public static readonly GUIContent ApplyFootIK = EditorGUIUtility.TrTextContent("Foot IK", "Enable to apply foot IK to the AnimationClip when the target is humanoid."); + public static readonly GUIContent Loop = EditorGUIUtility.TrTextContent("Loop", "Whether the source Animation Clip loops during playback."); + } + + TimelineWindow m_TimelineWindow; + GameObject m_Binding; + + TimelineAnimationUtilities.OffsetEditMode m_OffsetEditMode = TimelineAnimationUtilities.OffsetEditMode.None; + EditorClip m_EditorClip; + EditorClip[] m_EditorClips; + + SerializedProperty m_PositionProperty; + SerializedProperty m_RotationProperty; + SerializedProperty m_AnimClipProperty; + SerializedProperty m_UseTrackMatchFieldsProperty; + SerializedProperty m_MatchTargetFieldsProperty; + SerializedObject m_SerializedAnimClip; + SerializedProperty m_SerializedAnimClipName; + SerializedProperty m_RemoveStartOffsetProperty; + SerializedProperty m_ApplyFootIK; + SerializedProperty m_Loop; + + Vector3 m_LastPosition; + Vector3 m_LastRotation; + + public override void OnInspectorGUI() + { + if (target == null) + return; + + serializedObject.Update(); + + if (!m_TimelineWindow) m_TimelineWindow = TimelineWindow.instance; + + ShowAnimationClipField(); + ShowRecordableClipRename(); + ShowAnimationClipWarnings(); + + EditorGUI.BeginChangeCheck(); + + TransformOffsetsGUI(); + + // extra checks are because the context menu may need to cause a re-evaluate + bool changed = EditorGUI.EndChangeCheck() || + m_LastPosition != m_PositionProperty.vector3Value || + m_LastRotation != m_RotationProperty.vector3Value; + m_LastPosition = m_PositionProperty.vector3Value; + m_LastRotation = m_RotationProperty.vector3Value; + + if (changed) + { + // updates the changed properties and pushes them to the active playable + serializedObject.ApplyModifiedProperties(); + ((AnimationPlayableAsset)target).LiveLink(); + + // force an evaluate to happen next frame + if (TimelineWindow.instance != null && TimelineWindow.instance.state != null) + { + TimelineWindow.instance.state.Evaluate(); + } + } + + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(m_ApplyFootIK, Styles.ApplyFootIK); + EditorGUILayout.PropertyField(m_Loop, Styles.Loop); + if (EditorGUI.EndChangeCheck()) + TimelineEditor.Refresh(RefreshReason.ContentsModified); + + serializedObject.ApplyModifiedProperties(); + } + + void ShowAnimationClipField() + { + bool disabled = m_EditorClips == null || m_EditorClips.Any(c => c.clip == null || c.clip.recordable); + using (new EditorGUI.DisabledScope(disabled)) + { + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(m_AnimClipProperty, Styles.AnimClipText); + if (EditorGUI.EndChangeCheck()) + { + // rename the timeline clips to match the animation name if it did previously + if (m_AnimClipProperty.objectReferenceValue != null && m_EditorClips != null) + { + var newName = m_AnimClipProperty.objectReferenceValue.name; + foreach (var c in m_EditorClips) + { + if (c == null || c.clip == null || c.clip.asset == null) + continue; + + var apa = c.clip.asset as AnimationPlayableAsset; + if (apa != null && apa.clip != null && c.clip.displayName == apa.clip.name) + { + if (c.clip.parentTrack != null) + Undo.RegisterCompleteObjectUndo(c.clip.parentTrack, "Inspector"); + c.clip.displayName = newName; + } + } + } + + TimelineEditor.Refresh(RefreshReason.ContentsModified); + } + } + } + + void TransformOffsetsMatchFieldsGUI() + { + var rect = EditorGUILayout.GetControlRect(true); + EditorGUI.BeginProperty(rect, Styles.MatchTargetFieldsTitle, m_UseTrackMatchFieldsProperty); + + rect = EditorGUI.PrefixLabel(rect, Styles.MatchTargetFieldsTitle); + int oldIndent = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + EditorGUI.BeginChangeCheck(); + bool val = m_UseTrackMatchFieldsProperty.boolValue; + val = EditorGUI.ToggleLeft(rect, Styles.UseDefaults, val); + if (EditorGUI.EndChangeCheck()) + m_UseTrackMatchFieldsProperty.boolValue = val; + + EditorGUI.indentLevel = oldIndent; + EditorGUI.EndProperty(); + + + if (!val || m_UseTrackMatchFieldsProperty.hasMultipleDifferentValues) + { + EditorGUI.indentLevel++; + AnimationTrackInspector.MatchTargetsFieldGUI(m_MatchTargetFieldsProperty); + EditorGUI.indentLevel--; + } + } + + void TransformOffsetsGUI() + { + if (ShouldShowOffsets()) + { + EditorGUILayout.Space(); + EditorGUILayout.LabelField(Styles.TransformOffsetTitle); + EditorGUI.indentLevel++; + + using (new EditorGUI.DisabledScope(targets.Length > 1)) + { + var previousOffsetMode = m_OffsetEditMode; + AnimationTrackInspector.ShowMotionOffsetEditModeToolbar(ref m_OffsetEditMode); + if (previousOffsetMode != m_OffsetEditMode) + { + SetTimeToClip(); + SceneView.RepaintAll(); + } + } + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_PositionProperty); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_RotationProperty, Styles.RotationText); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + + EditorGUI.indentLevel--; + + TransformOffsetsMatchFieldsGUI(); + + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(m_RemoveStartOffsetProperty, Styles.RemoveStartOffset); + if (EditorGUI.EndChangeCheck()) + { + TimelineEditor.Refresh(RefreshReason.ContentsAddedOrRemoved); + Repaint(); + } + } + } + + void Reevaluate() + { + if (m_TimelineWindow != null && m_TimelineWindow.state != null) + { + m_TimelineWindow.state.Refresh(); + m_TimelineWindow.state.EvaluateImmediate(); + } + } + + // Make sure the director time is within the bounds of the clip + void SetTimeToClip() + { + if (m_TimelineWindow != null && m_TimelineWindow.state != null) + { + m_TimelineWindow.state.editSequence.time = Math.Min(m_EditorClip.clip.end, Math.Max(m_EditorClip.clip.start, m_TimelineWindow.state.editSequence.time)); + } + } + + public void OnEnable() + { + if (target == null) // case 946080 + return; + + m_EditorClip = UnityEditor.Selection.activeObject as EditorClip; + m_EditorClips = UnityEditor.Selection.objects.OfType<EditorClip>().ToArray(); + SceneView.duringSceneGui += OnSceneGUI; + + m_PositionProperty = serializedObject.FindProperty("m_Position"); + m_PositionProperty.isExpanded = true; + m_RotationProperty = serializedObject.FindProperty("m_EulerAngles"); + m_AnimClipProperty = serializedObject.FindProperty("m_Clip"); + m_UseTrackMatchFieldsProperty = serializedObject.FindProperty("m_UseTrackMatchFields"); + m_MatchTargetFieldsProperty = serializedObject.FindProperty("m_MatchTargetFields"); + m_RemoveStartOffsetProperty = serializedObject.FindProperty("m_RemoveStartOffset"); + m_ApplyFootIK = serializedObject.FindProperty("m_ApplyFootIK"); + m_Loop = serializedObject.FindProperty("m_Loop"); + + m_LastPosition = m_PositionProperty.vector3Value; + m_LastRotation = m_RotationProperty.vector3Value; + } + + void OnDestroy() + { + SceneView.duringSceneGui -= OnSceneGUI; + } + + void OnSceneGUI(SceneView sceneView) + { + DoManipulators(); + } + + Transform GetTransform() + { + if (m_Binding != null) + return m_Binding.transform; + + if (m_TimelineWindow != null && m_TimelineWindow.state != null && + m_TimelineWindow.state.editSequence.director != null && + m_EditorClip != null && m_EditorClip.clip != null) + { + var obj = TimelineUtility.GetSceneGameObject(m_TimelineWindow.state.editSequence.director, + m_EditorClip.clip.parentTrack); + m_Binding = obj; + if (obj != null) + return obj.transform; + } + return null; + } + + void DoManipulators() + { + if (m_EditorClip == null || m_EditorClip.clip == null) + return; + + AnimationPlayableAsset animationPlayable = m_EditorClip.clip.asset as AnimationPlayableAsset; + AnimationTrack track = m_EditorClip.clip.parentTrack as AnimationTrack; + Transform transform = GetTransform(); + + if (transform != null && animationPlayable != null && m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None && track != null) + { + TimelineUndo.PushUndo(animationPlayable, "Inspector"); + Vector3 position = transform.position; + Quaternion rotation = transform.rotation; + + EditorGUI.BeginChangeCheck(); + if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Translation) + { + position = Handles.PositionHandle(position, Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : rotation); + } + else if (m_OffsetEditMode == TimelineAnimationUtilities.OffsetEditMode.Rotation) + { + rotation = Handles.RotationHandle(rotation, position); + } + + if (EditorGUI.EndChangeCheck()) + { + var res = TimelineAnimationUtilities.UpdateClipOffsets(animationPlayable, track, transform, position, rotation); + animationPlayable.position = res.position; + animationPlayable.eulerAngles = AnimationUtility.GetClosestEuler(res.rotation, animationPlayable.eulerAngles, RotationOrder.OrderZXY); + Reevaluate(); + Repaint(); + } + } + } + + void ShowAnimationClipWarnings() + { + AnimationClip clip = m_AnimClipProperty.objectReferenceValue as AnimationClip; + if (clip == null) + { + EditorGUILayout.HelpBox(AnimationPlayableAssetEditor.k_NoClipAssignedError, MessageType.Warning); + } + else if (clip.legacy) + { + EditorGUILayout.HelpBox(AnimationPlayableAssetEditor.k_LegacyClipError, MessageType.Warning); + } + } + + bool ShouldShowOffsets() + { + return targets.OfType<AnimationPlayableAsset>().All(x => x.hasRootTransforms); + } + + void ShowRecordableClipRename() + { + if (targets.Length > 1 || m_EditorClip == null || m_EditorClip.clip == null || !m_EditorClip.clip.recordable) + return; + + AnimationClip clip = m_AnimClipProperty.objectReferenceValue as AnimationClip; + if (clip == null || !AssetDatabase.IsSubAsset(clip)) + return; + + if (m_SerializedAnimClip == null) + { + m_SerializedAnimClip = new SerializedObject(clip); + m_SerializedAnimClipName = m_SerializedAnimClip.FindProperty("m_Name"); + } + + if (m_SerializedAnimClipName != null) + { + m_SerializedAnimClip.Update(); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.DelayedTextField(m_SerializedAnimClipName, Styles.AnimationClipName); + if (EditorGUI.EndChangeCheck()) + m_SerializedAnimClip.ApplyModifiedProperties(); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationPlayableAssetInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationPlayableAssetInspector.cs.meta new file mode 100644 index 0000000..b81fe24 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationPlayableAssetInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7852b99951997645ae7adaac5f0b083 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationTrackInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationTrackInspector.cs new file mode 100644 index 0000000..abcccf9 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationTrackInspector.cs @@ -0,0 +1,504 @@ +//#define PERF_PROFILE + +using System; +using System.ComponentModel; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; +using UnityEngine.Playables; + +namespace UnityEditor.Timeline +{ + [CustomEditor(typeof(AnimationTrack)), CanEditMultipleObjects] + class AnimationTrackInspector : TrackAssetInspector + { + static class Styles + { + public static GUIContent MatchTargetFieldsTitle = EditorGUIUtility.TrTextContent("Default Offset Match Fields", "Fields to apply when matching offsets on clips. These are the defaults, and can be overridden for each clip."); + public static readonly GUIContent PositionIcon = EditorGUIUtility.IconContent("MoveTool"); + public static readonly GUIContent RotationIcon = EditorGUIUtility.IconContent("RotateTool"); + + public static GUIContent XTitle = EditorGUIUtility.TextContent("X"); + public static GUIContent YTitle = EditorGUIUtility.TextContent("Y"); + public static GUIContent ZTitle = EditorGUIUtility.TextContent("Z"); + public static GUIContent PositionTitle = EditorGUIUtility.TrTextContent("Position"); + public static GUIContent RotationTitle = EditorGUIUtility.TrTextContent("Rotation"); + + public static readonly GUIContent OffsetModeTitle = EditorGUIUtility.TrTextContent("Track Offsets"); + public static readonly string TransformOffsetInfo = L10n.Tr("Transform offsets are applied to the entire track. Use this mode to play the animation track at a fixed position and rotation."); + public static readonly string SceneOffsetInfo = L10n.Tr("Scene offsets will use the existing transform as initial offsets. Use this to play the track from the gameObjects current position and rotation."); + public static readonly string AutoOffsetInfo = L10n.Tr("Auto will apply scene offsets if there is a controller attached to the animator and transform offsets otherwise."); + public static readonly string AutoOffsetWarning = L10n.Tr("This mode is deprecated may be removed in a future release."); + public static readonly string InheritedFromParent = L10n.Tr("Inherited"); + public static readonly string InheritedToolTip = L10n.Tr("This value is inherited from it's parent track."); + + public static readonly GUIContent RecordingOffsets = EditorGUIUtility.TrTextContent("Recorded Offsets", "Offsets applied to recorded position and rotation keys"); + + public static readonly GUIContent[] OffsetContents; + public static readonly GUIContent[] OffsetInheritContents; + + static Styles() + { + var values = Enum.GetValues(typeof(TrackOffset)); + OffsetContents = new GUIContent[values.Length]; + OffsetInheritContents = new GUIContent[values.Length]; + for (var index = 0; index < values.Length; index++) + { + var offset = (TrackOffset)index; + var name = ObjectNames.NicifyVariableName(L10n.Tr(offset.ToString())); + var memInfo = typeof(TrackOffset).GetMember(offset.ToString()); + var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); + if (attributes.Length > 0) + { + name = ((DescriptionAttribute)attributes[0]).Description; + } + + OffsetContents[index] = new GUIContent(name); + OffsetInheritContents[index] = new GUIContent(string.Format("{0} ({1})", InheritedFromParent, name)); + } + } + } + + TimelineAnimationUtilities.OffsetEditMode m_OffsetEditMode = TimelineAnimationUtilities.OffsetEditMode.None; + + SerializedProperty m_MatchFieldsProperty; + SerializedProperty m_TrackPositionProperty; + SerializedProperty m_TrackRotationProperty; + SerializedProperty m_AvatarMaskProperty; + SerializedProperty m_ApplyAvatarMaskProperty; + SerializedProperty m_TrackOffsetProperty; + + SerializedProperty m_RecordedOffsetPositionProperty; + SerializedProperty m_RecordedOffsetEulerProperty; + + Vector3 m_lastPosition; + Vector3 m_lastRotation; + + GUIContent m_TempContent = new GUIContent(); + + + void Evaluate() + { + if (timelineWindow.state != null && timelineWindow.state.editSequence.director != null) + { + // force the update immediately, the deferred doesn't always work with the inspector + timelineWindow.state.editSequence.director.Evaluate(); + } + } + + void RebuildGraph() + { + TimelineEditor.Refresh(RefreshReason.ContentsModified); + } + + public override void OnInspectorGUI() + { + using (new EditorGUI.DisabledScope(IsTrackLocked())) + { + serializedObject.Update(); + + DrawRootTransformOffset(); + + EditorGUI.BeginChangeCheck(); + DrawRecordedOffsetProperties(); + DrawAvatarProperties(); + if (EditorGUI.EndChangeCheck()) + RebuildGraph(); + + DrawMatchFieldsGUI(); + + serializedObject.ApplyModifiedProperties(); + } + } + + bool AnimatesRootTransform() + { + return targets.OfType<AnimationTrack>().All(t => t.AnimatesRootTransform()); + } + + bool ShouldDrawOffsets() + { + bool hasMultiple; + var offsetMode = GetOffsetMode(out hasMultiple); + if (hasMultiple) + return false; + + if (offsetMode == TrackOffset.ApplySceneOffsets) + return false; + + if (offsetMode == TrackOffset.ApplyTransformOffsets) + return true; + + // Auto mode. + PlayableDirector director = this.m_Context as PlayableDirector; + if (director == null) + return false; + + // If any bound animators have controllers don't show + foreach (var track in targets.OfType<AnimationTrack>()) + { + var animator = track.GetBinding(director); + if (animator != null && animator.runtimeAnimatorController != null) + return false; + } + + return true; + } + + void DrawRootTransformOffset() + { + if (!AnimatesRootTransform()) + return; + + bool showWarning = SetupOffsetTooltip(); + DrawRootTransformDropDown(); + + if (ShouldDrawOffsets()) + { + EditorGUI.indentLevel++; + DrawRootMotionToolBar(); + DrawRootMotionOffsetFields(); + EditorGUI.indentLevel--; + } + + if (showWarning) + { + EditorGUI.indentLevel++; + EditorGUILayout.HelpBox(Styles.AutoOffsetWarning, MessageType.Warning, true); + EditorGUI.indentLevel--; + } + } + + bool SetupOffsetTooltip() + { + Styles.OffsetModeTitle.tooltip = string.Empty; + bool hasMultiple; + var offsetMode = GetOffsetMode(out hasMultiple); + bool showWarning = false; + if (!hasMultiple) + { + if (offsetMode == TrackOffset.ApplyTransformOffsets) + Styles.OffsetModeTitle.tooltip = Styles.TransformOffsetInfo; + else if (offsetMode == TrackOffset.ApplySceneOffsets) + Styles.OffsetModeTitle.tooltip = Styles.SceneOffsetInfo; + else if (offsetMode == TrackOffset.Auto) + { + Styles.OffsetModeTitle.tooltip = Styles.AutoOffsetInfo; + showWarning = true; + } + } + + return showWarning; + } + + void DrawRootTransformDropDown() + { + bool anySubTracks = targets.OfType<AnimationTrack>().Any(t => t.isSubTrack); + bool allSubTracks = targets.OfType<AnimationTrack>().All(t => t.isSubTrack); + + bool mixed; + var rootOffsetMode = GetOffsetMode(out mixed); + + // if we are showing subtracks, we need to show the current mode from the parent + // BUT keep it disabled + if (anySubTracks) + { + m_TempContent.tooltip = string.Empty; + if (mixed) + m_TempContent.text = EditorGUI.mixedValueContent.text; + else if (!allSubTracks) + m_TempContent.text = Styles.OffsetContents[(int)rootOffsetMode].text; + else + { + m_TempContent.text = Styles.OffsetInheritContents[(int)rootOffsetMode].text; + m_TempContent.tooltip = Styles.InheritedToolTip; + } + + using (new EditorGUI.DisabledScope(true)) + EditorGUILayout.LabelField(Styles.OffsetModeTitle, m_TempContent, EditorStyles.popup); + } + else + { + // We use an enum popup explicitly because it will handle the description attribute on the enum + using (new GUIMixedValueScope(mixed)) + { + var rect = EditorGUILayout.GetControlRect(true, EditorGUI.kSingleLineHeight); + EditorGUI.BeginProperty(rect, Styles.OffsetModeTitle, m_TrackOffsetProperty); + EditorGUI.BeginChangeCheck(); + var result = (TrackOffset)EditorGUI.EnumPopup(rect, Styles.OffsetModeTitle, (TrackOffset)m_TrackOffsetProperty.intValue); + if (EditorGUI.EndChangeCheck()) + { + m_TrackOffsetProperty.enumValueIndex = (int)result; + + // this property changes the recordable state of the objects, so auto disable recording + if (TimelineWindow.instance != null) + { + if (TimelineWindow.instance.state != null) + TimelineWindow.instance.state.recording = false; + RebuildGraph(); + } + } + + EditorGUI.EndProperty(); + } + } + } + + void DrawMatchFieldsGUI() + { + if (!AnimatesRootTransform()) + return; + + m_MatchFieldsProperty.isExpanded = EditorGUILayout.Foldout(m_MatchFieldsProperty.isExpanded, Styles.MatchTargetFieldsTitle, true); + if (m_MatchFieldsProperty.isExpanded) + { + EditorGUI.indentLevel++; + MatchTargetsFieldGUI(m_MatchFieldsProperty); + EditorGUI.indentLevel--; + } + } + + void DrawRootMotionOffsetFields() + { + EditorGUI.BeginChangeCheck(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_TrackPositionProperty); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_TrackRotationProperty, Styles.RotationTitle); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Space(); + EditorGUILayout.Space(); + + if (EditorGUI.EndChangeCheck()) + { + UpdateOffsets(); + } + } + + void DrawRootMotionToolBar() + { + bool disable = targets.Length > 1; + bool changed = false; + + if (!disable) + { + // detects external changes + changed |= m_lastPosition != m_TrackPositionProperty.vector3Value || m_lastRotation != m_TrackRotationProperty.vector3Value; + m_lastPosition = m_TrackPositionProperty.vector3Value; + m_lastRotation = m_TrackRotationProperty.vector3Value; + SceneView.RepaintAll(); + } + + EditorGUI.BeginChangeCheck(); + using (new EditorGUI.DisabledScope(disable)) + ShowMotionOffsetEditModeToolbar(ref m_OffsetEditMode); + changed |= EditorGUI.EndChangeCheck(); + + if (changed) + { + UpdateOffsets(); + } + } + + void UpdateOffsets() + { + foreach (var track in targets.OfType<AnimationTrack>()) + track.UpdateClipOffsets(); + Evaluate(); + } + + void DrawAvatarProperties() + { + EditorGUILayout.PropertyField(m_ApplyAvatarMaskProperty); + if (m_ApplyAvatarMaskProperty.hasMultipleDifferentValues || m_ApplyAvatarMaskProperty.boolValue) + { + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(m_AvatarMaskProperty); + EditorGUI.indentLevel--; + } + EditorGUILayout.Space(); + } + + public static void ShowMotionOffsetEditModeToolbar(ref TimelineAnimationUtilities.OffsetEditMode motionOffset) + { + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + GUILayout.FlexibleSpace(); + + int newMotionOffsetMode = GUILayout.Toolbar((int)motionOffset, new[] { Styles.PositionIcon, Styles.RotationIcon }); + + if (GUI.changed) + { + if ((int)motionOffset == newMotionOffsetMode) //untoggle the button + motionOffset = TimelineAnimationUtilities.OffsetEditMode.None; + else + motionOffset = (TimelineAnimationUtilities.OffsetEditMode)newMotionOffsetMode; + } + + GUILayout.FlexibleSpace(); + GUILayout.EndHorizontal(); + GUILayout.Space(3); + } + + public override void OnEnable() + { + base.OnEnable(); + SceneView.duringSceneGui += OnSceneGUI; + + m_MatchFieldsProperty = serializedObject.FindProperty("m_MatchTargetFields"); + m_TrackPositionProperty = serializedObject.FindProperty("m_Position"); + m_TrackRotationProperty = serializedObject.FindProperty("m_EulerAngles"); + m_TrackOffsetProperty = serializedObject.FindProperty("m_TrackOffset"); + m_AvatarMaskProperty = serializedObject.FindProperty("m_AvatarMask"); + m_ApplyAvatarMaskProperty = serializedObject.FindProperty("m_ApplyAvatarMask"); + m_RecordedOffsetPositionProperty = serializedObject.FindProperty("m_InfiniteClipOffsetPosition"); + m_RecordedOffsetEulerProperty = serializedObject.FindProperty("m_InfiniteClipOffsetEulerAngles"); + + m_lastPosition = m_TrackPositionProperty.vector3Value; + m_lastRotation = m_TrackRotationProperty.vector3Value; + } + + public void OnDestroy() + { + SceneView.duringSceneGui -= OnSceneGUI; + } + + void OnSceneGUI(SceneView sceneView) + { + DoOffsetManipulator(); + } + + void DoOffsetManipulator() + { + if (targets.Length > 1) //do not edit the track offset on a multiple selection + return; + + if (timelineWindow == null || timelineWindow.state == null || timelineWindow.state.editSequence.director == null) + return; + + AnimationTrack animationTrack = target as AnimationTrack; + if (animationTrack != null && (animationTrack.trackOffset == TrackOffset.ApplyTransformOffsets) && m_OffsetEditMode != TimelineAnimationUtilities.OffsetEditMode.None) + { + var boundObject = TimelineUtility.GetSceneGameObject(timelineWindow.state.editSequence.director, animationTrack); + var boundObjectTransform = boundObject != null ? boundObject.transform : null; + + var offsets = TimelineAnimationUtilities.GetTrackOffsets(animationTrack, boundObjectTransform); + EditorGUI.BeginChangeCheck(); + + switch (m_OffsetEditMode) + { + case TimelineAnimationUtilities.OffsetEditMode.Translation: + offsets.position = Handles.PositionHandle(offsets.position, (Tools.pivotRotation == PivotRotation.Global) + ? Quaternion.identity + : offsets.rotation); + break; + case TimelineAnimationUtilities.OffsetEditMode.Rotation: + offsets.rotation = Handles.RotationHandle(offsets.rotation, offsets.position); + break; + } + + if (EditorGUI.EndChangeCheck()) + { + TimelineUndo.PushUndo(animationTrack, "Inspector"); + TimelineAnimationUtilities.UpdateTrackOffset(animationTrack, boundObjectTransform, offsets); + Evaluate(); + Repaint(); + } + } + } + + public void DrawRecordedOffsetProperties() + { + // only show if this applies to all targets + foreach (var track in targets) + { + var animationTrack = track as AnimationTrack; + if (animationTrack == null || animationTrack.inClipMode || animationTrack.infiniteClip == null || animationTrack.infiniteClip.empty) + return; + } + + GUILayout.Label(Styles.RecordingOffsets); + EditorGUI.indentLevel++; + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_RecordedOffsetPositionProperty, Styles.PositionTitle); + EditorGUILayout.EndHorizontal(); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_RecordedOffsetEulerProperty, Styles.RotationTitle); + EditorGUILayout.EndHorizontal(); + EditorGUI.indentLevel--; + EditorGUILayout.Space(); + } + + public static void MatchTargetsFieldGUI(SerializedProperty property) + { + const float ToggleWidth = 20; + int value = 0; + + MatchTargetFields enumValue = (MatchTargetFields)property.intValue; + + EditorGUI.BeginChangeCheck(); + Rect rect = EditorGUILayout.GetControlRect(false, kLineHeight * 2); + Rect itemRect = new Rect(rect.x, rect.y, rect.width, kLineHeight); + EditorGUI.BeginProperty(rect, Styles.MatchTargetFieldsTitle, property); + float minWidth = 0, maxWidth = 0; + EditorStyles.label.CalcMinMaxWidth(Styles.XTitle, out minWidth, out maxWidth); + float width = minWidth + ToggleWidth; + + GUILayout.BeginHorizontal(); + Rect r = EditorGUI.PrefixLabel(itemRect, Styles.PositionTitle); + int oldIndent = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + r.width = width; + value |= EditorGUI.ToggleLeft(r, Styles.XTitle, enumValue.HasAny(MatchTargetFields.PositionX)) ? (int)MatchTargetFields.PositionX : 0; + r.x += width; + value |= EditorGUI.ToggleLeft(r, Styles.YTitle, enumValue.HasAny(MatchTargetFields.PositionY)) ? (int)MatchTargetFields.PositionY : 0; + r.x += width; + value |= EditorGUI.ToggleLeft(r, Styles.ZTitle, enumValue.HasAny(MatchTargetFields.PositionZ)) ? (int)MatchTargetFields.PositionZ : 0; + EditorGUI.indentLevel = oldIndent; + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + itemRect.y += kLineHeight; + r = EditorGUI.PrefixLabel(itemRect, Styles.RotationTitle); + EditorGUI.indentLevel = 0; + r.width = width; + value |= EditorGUI.ToggleLeft(r, Styles.XTitle, enumValue.HasAny(MatchTargetFields.RotationX)) ? (int)MatchTargetFields.RotationX : 0; + r.x += width; + value |= EditorGUI.ToggleLeft(r, Styles.YTitle, enumValue.HasAny(MatchTargetFields.RotationY)) ? (int)MatchTargetFields.RotationY : 0; + r.x += width; + value |= EditorGUI.ToggleLeft(r, Styles.ZTitle, enumValue.HasAny(MatchTargetFields.RotationZ)) ? (int)MatchTargetFields.RotationZ : 0; + EditorGUI.indentLevel = oldIndent; + GUILayout.EndHorizontal(); + + EditorGUI.EndProperty(); + if (EditorGUI.EndChangeCheck()) + { + property.intValue = value; + } + } + + static TrackOffset GetOffsetMode(AnimationTrack track) + { + if (track.isSubTrack) + { + var parent = track.parent as AnimationTrack; + if (parent != null) // fallback to the current track if there is an error + track = parent; + } + + return track.trackOffset; + } + + // gets the current mode, + TrackOffset GetOffsetMode(out bool hasMultiple) + { + var rootOffsetMode = GetOffsetMode(target as AnimationTrack); + hasMultiple = targets.OfType<AnimationTrack>().Any(t => GetOffsetMode(t) != rootOffsetMode); + return rootOffsetMode; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationTrackInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationTrackInspector.cs.meta new file mode 100644 index 0000000..3f57ed4 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/AnimationTrackInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: edc553b1b3c8a25438b62783410b26ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BasicAssetInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BasicAssetInspector.cs new file mode 100644 index 0000000..d746c9f --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BasicAssetInspector.cs @@ -0,0 +1,41 @@ +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + // Simple inspector used by built in assets + // that only need to hide the script field + class BasicAssetInspector : Editor + { + public override void OnInspectorGUI() + { + EditorGUI.BeginChangeCheck(); + serializedObject.Update(); + + SerializedProperty property = serializedObject.GetIterator(); + bool expanded = true; + while (property.NextVisible(expanded)) + { + expanded = false; + if (SkipField(property.propertyPath)) + continue; + EditorGUILayout.PropertyField(property, true); + } + + serializedObject.ApplyModifiedProperties(); + EditorGUI.EndChangeCheck(); + } + + public virtual void ApplyChanges() + { + TimelineEditor.Refresh(RefreshReason.ContentsModified); + } + + static bool SkipField(string fieldName) + { + return fieldName == "m_Script"; + } + } + + [CustomEditor(typeof(ActivationPlayableAsset))] + class ActivationPlayableAssetInspector : BasicAssetInspector {} +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BasicAssetInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BasicAssetInspector.cs.meta new file mode 100644 index 0000000..f296b75 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BasicAssetInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e086b15460c228c4f9b116f0e3e2f175 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BuiltInCurvePresets.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BuiltInCurvePresets.cs new file mode 100644 index 0000000..2e5c8cf --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BuiltInCurvePresets.cs @@ -0,0 +1,58 @@ +using UnityEngine; + +namespace UnityEditor.Timeline +{ + // Preset libraries + static class BuiltInPresets + { + static CurvePresetLibrary s_BlendInPresets; + static CurvePresetLibrary s_BlendOutPresets; + + internal static CurvePresetLibrary blendInPresets + { + get + { + if (s_BlendInPresets == null) + { + s_BlendInPresets = ScriptableObject.CreateInstance<CurvePresetLibrary>(); + s_BlendInPresets.Add(new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), "None"); + s_BlendInPresets.Add(new AnimationCurve(CurveEditorWindow.GetLinearKeys()), "Linear"); + s_BlendInPresets.Add(new AnimationCurve(CurveEditorWindow.GetEaseInKeys()), "EaseIn"); + s_BlendInPresets.Add(new AnimationCurve(CurveEditorWindow.GetEaseOutKeys()), "EaseOut"); + s_BlendInPresets.Add(new AnimationCurve(CurveEditorWindow.GetEaseInOutKeys()), "EaseInOut"); + } + return s_BlendInPresets; + } + } + + internal static CurvePresetLibrary blendOutPresets + { + get + { + if (s_BlendOutPresets == null) + { + s_BlendOutPresets = ScriptableObject.CreateInstance<CurvePresetLibrary>(); + s_BlendOutPresets.Add(new AnimationCurve(CurveEditorWindow.GetConstantKeys(1f)), "None"); + s_BlendOutPresets.Add(ReverseCurve(new AnimationCurve(CurveEditorWindow.GetLinearKeys())), "Linear"); + s_BlendOutPresets.Add(ReverseCurve(new AnimationCurve(CurveEditorWindow.GetEaseInKeys())), "EaseIn"); + s_BlendOutPresets.Add(ReverseCurve(new AnimationCurve(CurveEditorWindow.GetEaseOutKeys())), "EaseOut"); + s_BlendOutPresets.Add(ReverseCurve(new AnimationCurve(CurveEditorWindow.GetEaseInOutKeys())), "EaseInOut"); + } + return s_BlendOutPresets; + } + } + + static AnimationCurve ReverseCurve(AnimationCurve curve) + { + Keyframe[] keys = curve.keys; + for (int i = 0; i < keys.Length; i++) + { + keys[i].value = 1 - keys[i].value; + keys[i].inTangent *= -1; + keys[i].outTangent *= -1; + } + curve.keys = keys; + return curve; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BuiltInCurvePresets.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BuiltInCurvePresets.cs.meta new file mode 100644 index 0000000..d294670 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/BuiltInCurvePresets.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae05f0dd1cf145e4e8e905c7971ee433 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector.meta new file mode 100644 index 0000000..1774e4e --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f68c7f7359094f045930a108c444e7a4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspector.cs new file mode 100644 index 0000000..f05cb29 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspector.cs @@ -0,0 +1,786 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Timeline; +using UnityObject = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + [CustomEditor(typeof(EditorClip)), CanEditMultipleObjects] + class ClipInspector : Editor + { + internal static class Styles + { + public static readonly GUIContent StartName = EditorGUIUtility.TrTextContent("Start", "The start time of the clip"); + public static readonly GUIContent DurationName = EditorGUIUtility.TrTextContent("Duration", "The length of the clip"); + public static readonly GUIContent EndName = EditorGUIUtility.TrTextContent("End", "The end time of the clip"); + public static readonly GUIContent EaseInDurationName = EditorGUIUtility.TrTextContent("Ease In Duration", "The length of the blend in"); + public static readonly GUIContent EaseOutDurationName = EditorGUIUtility.TrTextContent("Ease Out Duration", "The length of the blend out"); + public static readonly GUIContent ClipInName = EditorGUIUtility.TrTextContent("Clip In", "Start the clip at this local time"); + public static readonly GUIContent TimeScaleName = EditorGUIUtility.TrTextContent("Speed Multiplier", "Time scale of the playback speed"); + public static readonly GUIContent PreExtrapolateLabel = EditorGUIUtility.TrTextContent("Pre-Extrapolate", "Extrapolation used prior to the first clip"); + public static readonly GUIContent PostExtrapolateLabel = EditorGUIUtility.TrTextContent("Post-Extrapolate", "Extrapolation used after a clip ends"); + public static readonly GUIContent BlendInCurveName = EditorGUIUtility.TrTextContent("In", "Blend In Curve"); + public static readonly GUIContent BlendOutCurveName = EditorGUIUtility.TrTextContent("Out", "Blend Out Curve"); + public static readonly GUIContent PreviewTitle = EditorGUIUtility.TrTextContent("Curve Editor"); + public static readonly GUIContent ClipTimingTitle = EditorGUIUtility.TrTextContent("Clip Timing"); + public static readonly GUIContent AnimationExtrapolationTitle = EditorGUIUtility.TrTextContent("Animation Extrapolation"); + public static readonly GUIContent BlendCurvesTitle = EditorGUIUtility.TrTextContent("Blend Curves"); + public static readonly GUIContent GroupTimingTitle = EditorGUIUtility.TrTextContent("Multiple Clip Timing"); + public static readonly GUIContent MultipleClipsSelectedIncompatibleCapabilitiesWarning = EditorGUIUtility.TrTextContent("Multiple clips selected. Only common properties are shown."); + public static readonly GUIContent MultipleSelectionTitle = EditorGUIUtility.TrTextContent("Timeline Clips"); + public static readonly GUIContent MultipleClipStartName = EditorGUIUtility.TrTextContent("Start", "The start time of the clip group"); + public static readonly GUIContent MultipleClipEndName = EditorGUIUtility.TrTextContent("End", "The end time of the clip group"); + public static readonly GUIContent TimelineClipFG = DirectorStyles.IconContent("TimelineClipFG"); + public static readonly GUIContent TimelineClipBG = DirectorStyles.IconContent("TimelineClipBG"); + } + + class EditorClipSelection : ICurvesOwnerInspectorWrapper + { + public EditorClip editorClip { get; } + + public TimelineClip clip + { + get { return editorClip == null ? null : editorClip.clip; } + } + + public SerializedObject serializedPlayableAsset { get; } + + public ICurvesOwner curvesOwner + { + get { return clip; } + } + + public int lastCurveVersion { get; set; } + public double lastEvalTime { get; set; } + + public EditorClipSelection(EditorClip anEditorClip) + { + editorClip = anEditorClip; + lastCurveVersion = -1; + lastEvalTime = -1; + + var so = new SerializedObject(editorClip); + var playableAssetProperty = so.FindProperty("m_Clip.m_Asset"); + if (playableAssetProperty != null) + { + var asset = playableAssetProperty.objectReferenceValue as UnityEngine.Playables.PlayableAsset; + if (asset != null) + serializedPlayableAsset = new SerializedObject(asset); + } + } + + public double ToLocalTime(double time) + { + return clip == null ? time : clip.ToLocalTime(time); + } + } + + SerializedProperty m_DisplayNameProperty; + SerializedProperty m_BlendInDurationProperty; + SerializedProperty m_BlendOutDurationProperty; + SerializedProperty m_EaseInDurationProperty; + SerializedProperty m_EaseOutDurationProperty; + SerializedProperty m_ClipInProperty; + SerializedProperty m_TimeScaleProperty; + SerializedProperty m_PostExtrapolationModeProperty; + SerializedProperty m_PreExtrapolationModeProperty; + SerializedProperty m_PostExtrapolationTimeProperty; + SerializedProperty m_PreExtrapolationTimeProperty; + SerializedProperty m_MixInCurveProperty; + SerializedProperty m_MixOutCurveProperty; + SerializedProperty m_BlendInCurveModeProperty; + SerializedProperty m_BlendOutCurveModeProperty; + + void InitializeProperties() + { + m_DisplayNameProperty = serializedObject.FindProperty("m_Clip.m_DisplayName"); + m_BlendInDurationProperty = serializedObject.FindProperty("m_Clip.m_BlendInDuration"); + m_BlendOutDurationProperty = serializedObject.FindProperty("m_Clip.m_BlendOutDuration"); + m_EaseInDurationProperty = serializedObject.FindProperty("m_Clip.m_EaseInDuration"); + m_EaseOutDurationProperty = serializedObject.FindProperty("m_Clip.m_EaseOutDuration"); + m_ClipInProperty = serializedObject.FindProperty("m_Clip.m_ClipIn"); + m_TimeScaleProperty = serializedObject.FindProperty("m_Clip.m_TimeScale"); + m_PostExtrapolationModeProperty = serializedObject.FindProperty("m_Clip.m_PostExtrapolationMode"); + m_PreExtrapolationModeProperty = serializedObject.FindProperty("m_Clip.m_PreExtrapolationMode"); + m_PostExtrapolationTimeProperty = serializedObject.FindProperty("m_Clip.m_PostExtrapolationTime"); + m_PreExtrapolationTimeProperty = serializedObject.FindProperty("m_Clip.m_PreExtrapolationTime"); + m_MixInCurveProperty = serializedObject.FindProperty("m_Clip.m_MixInCurve"); + m_MixOutCurveProperty = serializedObject.FindProperty("m_Clip.m_MixOutCurve"); + m_BlendInCurveModeProperty = serializedObject.FindProperty("m_Clip.m_BlendInCurveMode"); + m_BlendOutCurveModeProperty = serializedObject.FindProperty("m_Clip.m_BlendOutCurveMode"); + } + + TimelineAsset m_TimelineAsset; + + List<EditorClipSelection> m_SelectionCache; + Editor m_SelectedPlayableAssetsInspector; + + ClipInspectorCurveEditor m_ClipCurveEditor; + AnimationCurve[] m_PreviewCurves; // the curves we are currently previewing. + CurvePresetLibrary m_CurvePresets; + + bool m_IsClipAssetInspectorExpanded = true; + GUIContent m_ClipAssetTitle = new GUIContent(); + string m_MultiselectionHeaderTitle; + + ClipInspectorSelectionInfo m_SelectionInfo; + + const double k_TimeScaleSensitivity = 0.003; + + bool hasMultipleSelection + { + get { return targets.Length > 1; } + } + + float currentFrameRate + { + get { return m_TimelineAsset != null ? m_TimelineAsset.editorSettings.fps : TimelineAsset.EditorSettings.kDefaultFps; } + } + + bool selectionHasIncompatibleCapabilities + { + get + { + return !(m_SelectionInfo.supportsBlending + && m_SelectionInfo.supportsClipIn + && m_SelectionInfo.supportsExtrapolation + && m_SelectionInfo.supportsSpeedMultiplier); + } + } + + public override bool RequiresConstantRepaint() + { + return base.RequiresConstantRepaint() || (m_SelectedPlayableAssetsInspector != null && m_SelectedPlayableAssetsInspector.RequiresConstantRepaint()); + } + + internal override void OnHeaderTitleGUI(Rect titleRect, string header) + { + if (hasMultipleSelection) + { + base.OnHeaderTitleGUI(titleRect, m_MultiselectionHeaderTitle); + return; + } + + if (m_DisplayNameProperty != null) + { + using (new EditorGUI.DisabledScope(!IsEnabled())) + { + serializedObject.Update(); + if (IsLocked()) + { + base.OnHeaderTitleGUI(titleRect, m_DisplayNameProperty.stringValue); + } + else + { + EditorGUI.BeginChangeCheck(); + EditorGUI.DelayedTextField(titleRect, m_DisplayNameProperty, GUIContent.none); + if (EditorGUI.EndChangeCheck()) + { + ApplyModifiedProperties(); + TimelineWindow.RepaintIfEditingTimelineAsset(m_TimelineAsset); + } + } + } + } + } + + internal override Rect DrawHeaderHelpAndSettingsGUI(Rect r) + { + using (new EditorGUI.DisabledScope(IsLocked())) + { + var helpSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon); + const int kTopMargin = 5; + // Show Editor Header Items. + return EditorGUIUtility.DrawEditorHeaderItems(new Rect(r.xMax - helpSize.x, r.y + kTopMargin, helpSize.x, helpSize.y), targets); + } + } + + internal override void OnHeaderIconGUI(Rect iconRect) + { + using (new EditorGUI.DisabledScope(IsLocked())) + { + var bgColor = Color.white; + if (!EditorGUIUtility.isProSkin) + bgColor.a = 0.55f; + using (new GUIColorOverride(bgColor)) + { + GUI.Label(iconRect, Styles.TimelineClipBG); + } + + var fgColor = Color.white; + if (m_SelectionInfo != null && m_SelectionInfo.uniqueParentTracks.Count == 1) + fgColor = TrackResourceCache.GetTrackColor(m_SelectionInfo.uniqueParentTracks.First()); + + using (new GUIColorOverride(fgColor)) + { + GUI.Label(iconRect, Styles.TimelineClipFG); + } + } + } + + public void OnEnable() + { + m_ClipCurveEditor = new ClipInspectorCurveEditor(); + + m_SelectionCache = new List<EditorClipSelection>(); + var selectedClips = new List<TimelineClip>(); + foreach (var editorClipObject in targets) + { + var editorClip = editorClipObject as EditorClip; + if (editorClip != null) + { + //all selected clips should have the same TimelineAsset + if (!IsTimelineAssetValidForEditorClip(editorClip)) + { + m_SelectionCache.Clear(); + return; + } + m_SelectionCache.Add(new EditorClipSelection(editorClip)); + selectedClips.Add(editorClip.clip); + } + } + + InitializeProperties(); + m_SelectionInfo = new ClipInspectorSelectionInfo(selectedClips); + + if (m_SelectionInfo.selectedAssetTypesAreHomogeneous) + { + var selectedAssets = m_SelectionCache.Select(e => e.clip.asset).ToArray(); + m_SelectedPlayableAssetsInspector = TimelineInspectorUtility.GetInspectorForObjects(selectedAssets); + } + + m_MultiselectionHeaderTitle = m_SelectionCache.Count + " " + Styles.MultipleSelectionTitle.text; + m_ClipAssetTitle.text = PlayableAssetSectionTitle(); + } + + void DrawClipProperties() + { + var dirtyEditorClipSelection = m_SelectionCache.Where(s => s.editorClip.GetHashCode() != s.editorClip.lastHash); + UnselectCurves(); + + EditorGUI.BeginChangeCheck(); + + //Group Selection + if (hasMultipleSelection) + { + GUILayout.Label(Styles.GroupTimingTitle); + EditorGUI.indentLevel++; + DrawGroupSelectionProperties(); + EditorGUI.indentLevel--; + EditorGUILayout.Space(); + } + + //Draw clip timing + GUILayout.Label(Styles.ClipTimingTitle); + + if (hasMultipleSelection && selectionHasIncompatibleCapabilities) + { + GUILayout.Label(Styles.MultipleClipsSelectedIncompatibleCapabilitiesWarning, EditorStyles.helpBox); + } + + EditorGUI.indentLevel++; + + if (!m_SelectionInfo.containsAtLeastTwoClipsOnTheSameTrack) + { + DrawStartTimeField(); + DrawEndTimeField(); + } + + if (!hasMultipleSelection) + { + DrawDurationProperty(); + } + + if (m_SelectionInfo.supportsBlending) + { + EditorGUILayout.Space(); + DrawBlendingProperties(); + } + + if (m_SelectionInfo.supportsClipIn) + { + EditorGUILayout.Space(); + DrawClipInProperty(); + } + + if (!hasMultipleSelection && m_SelectionInfo.supportsSpeedMultiplier) + { + EditorGUILayout.Space(); + DrawTimeScale(); + } + + EditorGUI.indentLevel--; + + bool hasDirtyEditorClips = false; + foreach (var editorClipSelection in dirtyEditorClipSelection) + { + EditorUtility.SetDirty(editorClipSelection.editorClip); + hasDirtyEditorClips = true; + } + + //Re-evaluate the graph in case of a change in properties + bool propertiesHaveChanged = false; + if (EditorGUI.EndChangeCheck() || hasDirtyEditorClips) + { + if (TimelineWindow.IsEditingTimelineAsset(m_TimelineAsset) && TimelineWindow.instance.state != null) + { + TimelineWindow.instance.state.Evaluate(); + TimelineWindow.instance.Repaint(); + } + propertiesHaveChanged = true; + } + + //Draw Animation Extrapolation + if (m_SelectionInfo.supportsExtrapolation) + { + EditorGUILayout.Space(); + GUILayout.Label(Styles.AnimationExtrapolationTitle); + EditorGUI.indentLevel++; + DrawExtrapolationOptions(); + EditorGUI.indentLevel--; + } + + //Blend curves + if (m_SelectionInfo.supportsBlending) + { + EditorGUILayout.Space(); + GUILayout.Label(Styles.BlendCurvesTitle); + EditorGUI.indentLevel++; + DrawBlendOptions(); + EditorGUI.indentLevel--; + } + + EditorGUILayout.Space(); + + if (CanShowPlayableAssetInspector()) + { + DrawClipAssetGui(); + } + + if (propertiesHaveChanged) + { + foreach (var item in m_SelectionCache) + item.editorClip.lastHash = item.editorClip.GetHashCode(); + m_SelectionInfo.Update(); + } + } + + public override void OnInspectorGUI() + { + if (TimelineWindow.instance == null || m_TimelineAsset == null) + return; + + using (new EditorGUI.DisabledScope(IsLocked())) + { + EditMode.HandleModeClutch(); + + serializedObject.Update(); + DrawClipProperties(); + ApplyModifiedProperties(); + } + } + + internal override bool IsEnabled() + { + if (!TimelineUtility.IsCurrentSequenceValid() || IsCurrentSequenceReadOnly()) + return false; + + if (m_TimelineAsset != TimelineWindow.instance.state.editSequence.asset) + return false; + return base.IsEnabled(); + } + + void DrawTimeScale() + { + var inputEvent = InputEvent.None; + var newEndTime = m_SelectionInfo.end; + var oldTimeScale = m_TimeScaleProperty.doubleValue; + + EditorGUI.BeginChangeCheck(); + var newTimeScale = TimelineInspectorUtility.DelayedAndDraggableDoubleField(Styles.TimeScaleName, oldTimeScale, ref inputEvent, k_TimeScaleSensitivity); + + if (EditorGUI.EndChangeCheck()) + { + newTimeScale = newTimeScale.Clamp(TimelineClip.kTimeScaleMin, TimelineClip.kTimeScaleMax); + newEndTime = m_SelectionInfo.start + (m_SelectionInfo.duration * oldTimeScale / newTimeScale); + } + EditMode.inputHandler.ProcessTrim(inputEvent, newEndTime, true); + } + + void DrawStartTimeField() + { + var inputEvent = InputEvent.None; + var newStart = TimelineInspectorUtility.TimeFieldUsingTimeReference(Styles.StartName, m_SelectionInfo.multipleClipStart, false, m_SelectionInfo.hasMultipleStartValues, currentFrameRate, 0.0, TimelineClip.kMaxTimeValue, ref inputEvent); + + if (inputEvent.InputHasBegun() && m_SelectionInfo.hasMultipleStartValues) + { + var items = ItemsUtils.ToItems(m_SelectionInfo.clips); + EditMode.inputHandler.SetValueForEdge(items, AttractedEdge.Left, newStart); //if the field has multiple values, set the same start on all selected clips + m_SelectionInfo.Update(); //clips could have moved relative to each other, recalculate + } + + EditMode.inputHandler.ProcessMove(inputEvent, newStart); + } + + void DrawEndTimeField() + { + var inputEvent = InputEvent.None; + var newEndTime = TimelineInspectorUtility.TimeFieldUsingTimeReference(Styles.EndName, m_SelectionInfo.multipleClipEnd, false, m_SelectionInfo.hasMultipleEndValues, currentFrameRate, 0, TimelineClip.kMaxTimeValue, ref inputEvent); + + if (inputEvent.InputHasBegun() && m_SelectionInfo.hasMultipleEndValues) + { + var items = ItemsUtils.ToItems(m_SelectionInfo.clips); + EditMode.inputHandler.SetValueForEdge(items, AttractedEdge.Right, newEndTime); //if the field has multiple value, set the same end on all selected clips + m_SelectionInfo.Update(); //clips could have moved relative to each other, recalculate + } + + var newStartValue = m_SelectionInfo.multipleClipStart + (newEndTime - m_SelectionInfo.multipleClipEnd); + EditMode.inputHandler.ProcessMove(inputEvent, newStartValue); + } + + void DrawClipAssetGui() + { + const float labelIndent = 34; + if (m_SelectedPlayableAssetsInspector == null) + return; + + var rect = GUILayoutUtility.GetRect(GUIContent.none, EditorStyles.inspectorTitlebar); + var oldWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = rect.width - labelIndent; + m_IsClipAssetInspectorExpanded = EditorGUI.FoldoutTitlebar(rect, m_ClipAssetTitle, m_IsClipAssetInspectorExpanded, false); + EditorGUIUtility.labelWidth = oldWidth; + if (m_IsClipAssetInspectorExpanded) + { + EditorGUILayout.Space(); + EditorGUI.indentLevel++; + ShowPlayableAssetInspector(); + EditorGUI.indentLevel--; + } + } + + void DrawExtrapolationOptions() + { + EditorGUI.BeginChangeCheck(); + + // PreExtrapolation + var preExtrapolationTime = m_PreExtrapolationTimeProperty.doubleValue; + bool hasPreExtrap = preExtrapolationTime > 0.0; + if (hasPreExtrap) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_PreExtrapolationModeProperty, Styles.PreExtrapolateLabel); + using (new GUIMixedValueScope(m_PreExtrapolationTimeProperty.hasMultipleDifferentValues)) + EditorGUILayout.DoubleField(preExtrapolationTime, EditorStyles.label); + EditorGUILayout.EndHorizontal(); + } + + // PostExtrapolation + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(m_PostExtrapolationModeProperty, Styles.PostExtrapolateLabel); + using (new GUIMixedValueScope(m_PostExtrapolationTimeProperty.hasMultipleDifferentValues)) + EditorGUILayout.DoubleField(m_PostExtrapolationTimeProperty.doubleValue, EditorStyles.label); + EditorGUILayout.EndHorizontal(); + } + + if (EditorGUI.EndChangeCheck()) + { + // if these options change the interval tree may need to be rebuilt. + if (TimelineWindow.IsEditingTimelineAsset(m_TimelineAsset) && TimelineWindow.instance.state != null) + { + TimelineWindow.instance.state.Refresh(); + } + } + } + + void OnDestroy() + { + DestroyImmediate(m_SelectedPlayableAssetsInspector); + } + + public override GUIContent GetPreviewTitle() + { + return Styles.PreviewTitle; + } + + public override bool HasPreviewGUI() + { + return m_PreviewCurves != null; + } + + public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) + { + if (m_PreviewCurves != null && m_ClipCurveEditor != null) + { + SetCurveEditorTrackHead(); + m_ClipCurveEditor.OnGUI(r, m_CurvePresets); + } + } + + void SetCurveEditorTrackHead() + { + if (TimelineWindow.instance == null || TimelineWindow.instance.state == null) + return; + + if (hasMultipleSelection) + return; + + var editorClip = target as EditorClip; + if (editorClip == null) + return; + + var director = TimelineWindow.instance.state.editSequence.director; + + if (director == null) + return; + + m_ClipCurveEditor.trackTime = ClipInspectorCurveEditor.kDisableTrackTime; + } + + void UnselectCurves() + { + if (Event.current.type == EventType.MouseDown) + { + m_PreviewCurves = null; + if (m_ClipCurveEditor != null) + m_ClipCurveEditor.SetUpdateCurveCallback(null); + } + } + + // Callback when the mixin/mixout properties are clicked on + void OnMixCurveSelected(string title, CurvePresetLibrary library, SerializedProperty curveSelected, bool easeIn) + { + m_CurvePresets = library; + m_PreviewCurves = new[] { curveSelected.animationCurveValue }; + m_ClipCurveEditor.headerString = title; + m_ClipCurveEditor.SetCurves(m_PreviewCurves, null); + m_ClipCurveEditor.SetSelected(curveSelected.animationCurveValue); + if (easeIn) + m_ClipCurveEditor.SetUpdateCurveCallback(MixInCurveUpdated); + else + m_ClipCurveEditor.SetUpdateCurveCallback(MixOutCurveUpdated); + Repaint(); + } + + // callback when the mix property is updated + void MixInCurveUpdated(AnimationCurve curve, EditorCurveBinding binding) + { + curve.keys = CurveEditUtility.SanitizeCurveKeys(curve.keys, true); + m_MixInCurveProperty.animationCurveValue = curve; + serializedObject.ApplyModifiedProperties(); + var editorClip = target as EditorClip; + if (editorClip != null) + editorClip.lastHash = editorClip.GetHashCode(); + RefreshCurves(); + } + + void MixOutCurveUpdated(AnimationCurve curve, EditorCurveBinding binding) + { + curve.keys = CurveEditUtility.SanitizeCurveKeys(curve.keys, false); + m_MixOutCurveProperty.animationCurveValue = curve; + serializedObject.ApplyModifiedProperties(); + var editorClip = target as EditorClip; + if (editorClip != null) + editorClip.lastHash = editorClip.GetHashCode(); + RefreshCurves(); + } + + void RefreshCurves() + { + AnimationCurvePreviewCache.ClearCache(); + TimelineWindow.RepaintIfEditingTimelineAsset(m_TimelineAsset); + Repaint(); + } + + void DrawBlendCurve(GUIContent title, SerializedProperty modeProperty, SerializedProperty curveProperty, Action<SerializedProperty> onCurveClick) + { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField(modeProperty, title); + if (hasMultipleSelection) + { + GUILayout.FlexibleSpace(); + } + else + { + using (new EditorGUI.DisabledScope(modeProperty.intValue != (int)TimelineClip.BlendCurveMode.Manual)) + { + ClipInspectorCurveEditor.CurveField(GUIContent.none, curveProperty, onCurveClick); + } + } + + EditorGUILayout.EndHorizontal(); + } + + void ShowPlayableAssetInspector() + { + if (!m_SelectionInfo.selectedAssetTypesAreHomogeneous) + return; + + if (m_SelectedPlayableAssetsInspector != null) + { + foreach (var selectedItem in m_SelectionCache) + CurvesOwnerInspectorHelper.PreparePlayableAsset(selectedItem); + + EditorGUI.BeginChangeCheck(); + using (new EditorGUI.DisabledScope(IsLocked())) + { + m_SelectedPlayableAssetsInspector.OnInspectorGUI(); + } + if (EditorGUI.EndChangeCheck()) + { + MarkClipsDirty(); + if (TimelineWindow.IsEditingTimelineAsset(m_TimelineAsset) && TimelineWindow.instance.state != null) + { + var basicInspector = m_SelectedPlayableAssetsInspector as BasicAssetInspector; + if (basicInspector != null) + basicInspector.ApplyChanges(); + else + TimelineEditor.Refresh(RefreshReason.ContentsModified); + } + } + } + } + + void ApplyModifiedProperties() + { + // case 926861 - we need to force the track to be dirty since modifying the clip does not + // automatically mark the track asset as dirty + if (serializedObject.ApplyModifiedProperties()) + { + foreach (var obj in serializedObject.targetObjects) + { + var editorClip = obj as EditorClip; + if (editorClip != null && editorClip.clip != null && editorClip.clip.parentTrack != null) + { + editorClip.clip.MarkDirty(); + EditorUtility.SetDirty(editorClip.clip.parentTrack); + } + } + } + } + + void MarkClipsDirty() + { + foreach (var obj in targets) + { + var editorClip = obj as EditorClip; + if (editorClip != null && editorClip.clip != null) + { + editorClip.clip.MarkDirty(); + } + } + } + + string PlayableAssetSectionTitle() + { + var firstSelectedClipAsset = m_SelectionCache.Any() ? m_SelectionCache.First().clip.asset : null; + return firstSelectedClipAsset != null + ? ObjectNames.NicifyVariableName(firstSelectedClipAsset.GetType().Name) + : string.Empty; + } + + bool IsTimelineAssetValidForEditorClip(EditorClip editorClip) + { + var trackAsset = editorClip.clip.parentTrack; + if (trackAsset == null) + return false; + + var clipTimelineAsset = trackAsset.timelineAsset; + if (m_TimelineAsset == null) + m_TimelineAsset = clipTimelineAsset; + else if (clipTimelineAsset != m_TimelineAsset) + { + m_TimelineAsset = null; + return false; + } + return true; + } + + bool CanShowPlayableAssetInspector() + { + if (hasMultipleSelection) + return m_SelectedPlayableAssetsInspector != null && + m_SelectedPlayableAssetsInspector.canEditMultipleObjects && + m_SelectionInfo.selectedAssetTypesAreHomogeneous; + else + return true; + } + + void DrawDurationProperty() + { + var minDuration = 1.0 / 30.0; + if (currentFrameRate > float.Epsilon) + { + minDuration = 1.0 / currentFrameRate; + } + + var inputEvent = InputEvent.None; + var newDuration = TimelineInspectorUtility.DurationFieldUsingTimeReference( + Styles.DurationName, m_SelectionInfo.start, m_SelectionInfo.end, false, m_SelectionInfo.hasMultipleDurationValues, currentFrameRate, minDuration, TimelineClip.kMaxTimeValue, ref inputEvent); + EditMode.inputHandler.ProcessTrim(inputEvent, m_SelectionInfo.start + newDuration, false); + } + + void DrawBlendingProperties() + { + var useBlendIn = m_SelectionInfo.hasBlendIn; + var maxBlendDuration = m_SelectionInfo.smallestDuration * 0.49; + var blendMax = useBlendIn ? TimelineClip.kMaxTimeValue : maxBlendDuration; + var inputEvent = InputEvent.None; + + TimelineInspectorUtility.TimeField(useBlendIn + ? m_BlendInDurationProperty + : m_EaseInDurationProperty, Styles.EaseInDurationName, useBlendIn, currentFrameRate, 0, blendMax, ref inputEvent); + + var useBlendOut = m_SelectionInfo.hasBlendOut; + blendMax = useBlendOut ? TimelineClip.kMaxTimeValue : maxBlendDuration; + TimelineInspectorUtility.TimeField(useBlendOut + ? m_BlendOutDurationProperty + : m_EaseOutDurationProperty, Styles.EaseOutDurationName, useBlendOut, currentFrameRate, 0, blendMax, ref inputEvent); + } + + void DrawClipInProperty() + { + var action = InputEvent.None; + TimelineInspectorUtility.TimeField(m_ClipInProperty, Styles.ClipInName, false, currentFrameRate, 0, TimelineClip.kMaxTimeValue, ref action); + } + + void DrawBlendOptions() + { + EditorGUI.BeginChangeCheck(); + + DrawBlendCurve(Styles.BlendInCurveName, m_BlendInCurveModeProperty, m_MixInCurveProperty, x => OnMixCurveSelected("Blend In", BuiltInPresets.blendInPresets, x, true)); + DrawBlendCurve(Styles.BlendOutCurveName, m_BlendOutCurveModeProperty, m_MixOutCurveProperty, x => OnMixCurveSelected("Blend Out", BuiltInPresets.blendOutPresets, x, false)); + + if (EditorGUI.EndChangeCheck()) + TimelineWindow.RepaintIfEditingTimelineAsset(m_TimelineAsset); + } + + void DrawGroupSelectionProperties() + { + var inputEvent = InputEvent.None; + var newStartTime = TimelineInspectorUtility.TimeField(Styles.MultipleClipStartName, m_SelectionInfo.multipleClipStart, false, false, currentFrameRate, 0, TimelineClip.kMaxTimeValue, ref inputEvent); + EditMode.inputHandler.ProcessMove(inputEvent, newStartTime); + + inputEvent = InputEvent.None; + var newEndTime = TimelineInspectorUtility.TimeField(Styles.MultipleClipEndName, m_SelectionInfo.multipleClipEnd, false, false, currentFrameRate, 0, TimelineClip.kMaxTimeValue, ref inputEvent); + var newStartValue = newStartTime + (newEndTime - m_SelectionInfo.multipleClipEnd); + EditMode.inputHandler.ProcessMove(inputEvent, newStartValue); + } + + bool IsLocked() + { + if (!TimelineUtility.IsCurrentSequenceValid() || IsCurrentSequenceReadOnly()) + return true; + + return targets.OfType<EditorClip>().Any(t => t.clip.parentTrack != null && t.clip.parentTrack.lockedInHierarchy); + } + + static bool IsCurrentSequenceReadOnly() + { + return TimelineWindow.instance.state.editSequence.isReadOnly; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspector.cs.meta new file mode 100644 index 0000000..165a3ea --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dff73c4907c95264c8fc095a81f9d51e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorCurveEditor.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorCurveEditor.cs new file mode 100644 index 0000000..e4c5ca5 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorCurveEditor.cs @@ -0,0 +1,348 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditorInternal; +using UnityEngine; + +namespace UnityEditor.Timeline +{ + class ClipInspectorCurveEditor + { + CurveEditor m_CurveEditor; + + AnimationCurve[] m_Curves; + CurveWrapper[] m_CurveWrappers; + + const float k_HeaderHeight = 30; + const float k_PresetHeight = 30; + + Action<AnimationCurve, EditorCurveBinding> m_CurveUpdatedCallback; + GUIContent m_TextContent = new GUIContent(); + + GUIStyle m_LabelStyle; + GUIStyle m_LegendStyle; + + // Track time. controls the position of the track head + public static readonly double kDisableTrackTime = double.NaN; + double m_trackTime = kDisableTrackTime; + public double trackTime { get { return m_trackTime; } set { m_trackTime = value; } } + + public string headerString { get; set; } + + public ClipInspectorCurveEditor() + { + var curveEditorSettings = new CurveEditorSettings + { + allowDeleteLastKeyInCurve = false, + allowDraggingCurvesAndRegions = true, + hTickLabelOffset = 0.1f, + showAxisLabels = true, + useFocusColors = false, + wrapColor = new EditorGUIUtility.SkinnedColor(Color.black), + hSlider = false, + hRangeMin = 0.0f, + vRangeMin = 0.0F, + vRangeMax = 1.0f, + hRangeMax = 1.0F, + vSlider = false, + hRangeLocked = false, + vRangeLocked = false, + + hTickStyle = new TickStyle + { + tickColor = new EditorGUIUtility.SkinnedColor(new Color(0.0f, 0.0f, 0.0f, 0.2f)), + distLabel = 30, + stubs = false, + centerLabel = true + }, + + vTickStyle = new TickStyle + { + tickColor = new EditorGUIUtility.SkinnedColor(new Color(1.0f, 0.0f, 0.0f, 0.2f)), + distLabel = 20, + stubs = false, + centerLabel = true + } + }; + + m_CurveEditor = new CurveEditor(new Rect(0, 0, 1000, 100), new CurveWrapper[0], true) + { + settings = curveEditorSettings, + ignoreScrollWheelUntilClicked = true + }; + } + + internal bool InitStyles() + { + if (EditorStyles.s_Current == null) + return false; + + if (m_LabelStyle == null) + { + m_LabelStyle = new GUIStyle(EditorStyles.whiteLargeLabel); + m_LegendStyle = new GUIStyle(EditorStyles.miniBoldLabel); + + m_LabelStyle.alignment = TextAnchor.MiddleCenter; + m_LegendStyle.alignment = TextAnchor.MiddleCenter; + } + return true; + } + + internal void OnGUI(Rect clientRect, CurvePresetLibrary presets) + { + const float presetPad = 30.0f; + + if (!InitStyles()) + return; + + if (m_Curves == null || m_Curves.Length == 0) + return; + + // regions + var headerRect = new Rect(clientRect.x, clientRect.y, clientRect.width, k_HeaderHeight); + var curveRect = new Rect(clientRect.x, clientRect.y + headerRect.height, clientRect.width, clientRect.height - k_HeaderHeight - k_PresetHeight); + var presetRect = new Rect(clientRect.x + presetPad, clientRect.y + curveRect.height + k_HeaderHeight, clientRect.width - presetPad, k_PresetHeight); + + GUI.Box(headerRect, headerString, m_LabelStyle); + + //Case 1201474 : Force to update only when Repaint event is called as the new rect provided on other event create a wrong curve editor computation. + if (Event.current.type == EventType.Repaint) + { + m_CurveEditor.rect = curveRect; + m_CurveEditor.shownAreaInsideMargins = new Rect(0, 0, 1, 1); + } + m_CurveEditor.animationCurves = m_CurveWrappers; + UpdateSelectionColors(); + + DrawTrackHead(curveRect); + + EditorGUI.BeginChangeCheck(); + + m_CurveEditor.OnGUI(); + DrawPresets(presetRect, presets); + + bool hasChanged = EditorGUI.EndChangeCheck(); + + if (presets == null) + DrawLegend(presetRect); + + if (hasChanged) + ProcessUpdates(); + } + + void DrawPresets(Rect position, PresetLibrary curveLibrary) + { + if (curveLibrary == null || curveLibrary.Count() == 0) + return; + + const int maxNumPresets = 9; + int numPresets = curveLibrary.Count(); + int showNumPresets = Mathf.Min(numPresets, maxNumPresets); + + const float swatchWidth = 30; + const float swatchHeight = 15; + const float spaceBetweenSwatches = 10; + float presetButtonsWidth = showNumPresets * swatchWidth + (showNumPresets - 1) * spaceBetweenSwatches; + float flexWidth = (position.width - presetButtonsWidth) * 0.5f; + + // Preset swatch area + float curY = (position.height - swatchHeight) * 0.5f; + float curX = 3.0f; + if (flexWidth > 0) + curX = flexWidth; + + GUI.BeginGroup(position); + + for (int i = 0; i < showNumPresets; i++) + { + if (i > 0) + curX += spaceBetweenSwatches; + + var swatchRect = new Rect(curX, curY, swatchWidth, swatchHeight); + m_TextContent.tooltip = curveLibrary.GetName(i); + if (GUI.Button(swatchRect, m_TextContent, GUIStyle.none)) + { + // if there is only 1, no need to specify + IEnumerable<CurveWrapper> wrappers = m_CurveWrappers; + if (m_CurveWrappers.Length > 1) + wrappers = m_CurveWrappers.Where(x => x.selected == CurveWrapper.SelectionMode.Selected); + + foreach (var wrapper in wrappers) + { + var presetCurve = (AnimationCurve)curveLibrary.GetPreset(i); + wrapper.curve.keys = (Keyframe[])presetCurve.keys.Clone(); + wrapper.changed = true; + } + } + + if (Event.current.type == EventType.Repaint) + curveLibrary.Draw(swatchRect, i); + + curX += swatchWidth; + } + + GUI.EndGroup(); + } + + // draw a line representing where in the current clip we are + void DrawTrackHead(Rect clientRect) + { + DirectorStyles styles = TimelineWindow.styles; + if (styles == null) + return; + + if (!double.IsNaN(m_trackTime)) + { + float x = m_CurveEditor.TimeToPixel((float)m_trackTime, clientRect); + x = Mathf.Clamp(x, clientRect.xMin, clientRect.xMax); + var p1 = new Vector2(x, clientRect.yMin); + var p2 = new Vector2(x, clientRect.yMax); + Graphics.DrawLine(p1, p2, DirectorStyles.Instance.customSkin.colorPlayhead); + } + } + + // Draws a legend for the displayed curves + void DrawLegend(Rect r) + { + if (m_CurveWrappers == null || m_CurveWrappers.Length == 0) + return; + + Color c = GUI.color; + float boxWidth = r.width / m_CurveWrappers.Length; + for (int i = 0; i < m_CurveWrappers.Length; i++) + { + CurveWrapper cw = m_CurveWrappers[i]; + if (cw != null) + { + var pos = new Rect(r.x + i * boxWidth, r.y, boxWidth, r.height); + var textColor = cw.color; + textColor.a = 1; + GUI.color = textColor; + string name = LabelName(cw.binding.propertyName); + EditorGUI.LabelField(pos, name, m_LegendStyle); + } + } + GUI.color = c; + } + + // Helper for making label name appropriately small + static char[] s_LabelMarkers = { '_' }; + + static string LabelName(string propertyName) + { + propertyName = AnimationWindowUtility.GetPropertyDisplayName(propertyName); + int index = propertyName.LastIndexOfAny(s_LabelMarkers); + if (index >= 0) + propertyName = propertyName.Substring(index); + return propertyName; + } + + public void SetCurves(AnimationCurve[] curves, EditorCurveBinding[] bindings) + { + m_Curves = curves; + if (m_Curves != null && m_Curves.Length > 0) + { + m_CurveWrappers = new CurveWrapper[m_Curves.Length]; + for (int i = 0; i < m_Curves.Length; i++) + { + var cw = new CurveWrapper + { + renderer = new NormalCurveRenderer(m_Curves[i]), + readOnly = false, + color = EditorGUI.kCurveColor, + id = curves[i].GetHashCode(), + hidden = false, + regionId = -1 + }; + + cw.renderer.SetWrap(WrapMode.Clamp, WrapMode.Clamp); + cw.renderer.SetCustomRange(0, 1); + + if (bindings != null) + { + cw.binding = bindings[i]; + cw.color = CurveUtility.GetPropertyColor(bindings[i].propertyName); + cw.id = bindings[i].GetHashCode(); + } + + m_CurveWrappers[i] = cw; + } + + UpdateSelectionColors(); + m_CurveEditor.animationCurves = m_CurveWrappers; + } + } + + internal void SetUpdateCurveCallback(Action<AnimationCurve, EditorCurveBinding> callback) + { + m_CurveUpdatedCallback = callback; + } + + void ProcessUpdates() + { + foreach (var cw in m_CurveWrappers) + { + if (cw.changed) + { + cw.changed = false; + + if (m_CurveUpdatedCallback != null) + m_CurveUpdatedCallback(cw.curve, cw.binding); + } + } + } + + public void SetSelected(AnimationCurve curve) + { + m_CurveEditor.SelectNone(); + for (int i = 0; i < m_Curves.Length; i++) + { + if (curve == m_Curves[i]) + { + m_CurveWrappers[i].selected = CurveWrapper.SelectionMode.Selected; + m_CurveEditor.AddSelection(new CurveSelection(m_CurveWrappers[i].id, 0)); + } + } + + UpdateSelectionColors(); + } + + void UpdateSelectionColors() + { + if (m_CurveWrappers == null) + return; + + // manually manage selection colors + foreach (var cw in m_CurveWrappers) + { + Color c = cw.color; + if (cw.readOnly) + c.a = 0.75f; + else if (cw.selected != CurveWrapper.SelectionMode.None) + c.a = 1.0f; + else + c.a = 0.5f; + cw.color = c; + } + } + + public static void CurveField(GUIContent title, SerializedProperty property, Action<SerializedProperty> onClick) + { + Rect controlRect = EditorGUILayout.GetControlRect(GUILayout.MinWidth(20)); + EditorGUI.BeginProperty(controlRect, title, property); + DrawCurve(controlRect, property, onClick, EditorGUI.kCurveColor, EditorGUI.kCurveBGColor); + EditorGUI.EndProperty(); + } + + static Rect DrawCurve(Rect controlRect, SerializedProperty property, Action<SerializedProperty> onClick, Color fgColor, Color bgColor) + { + if (GUI.Button(controlRect, GUIContent.none)) + { + if (onClick != null) + onClick(property); + } + EditorGUIUtility.DrawCurveSwatch(controlRect, null, property, fgColor, bgColor); + return controlRect; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorCurveEditor.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorCurveEditor.cs.meta new file mode 100644 index 0000000..1d16576 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorCurveEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3d14fa8f6934e14d92e37279e40e89b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorSelectionInfo.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorSelectionInfo.cs new file mode 100644 index 0000000..7c2d088 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorSelectionInfo.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + class ClipInspectorSelectionInfo + { + public double start, end, duration; + public double multipleClipStart, multipleClipEnd; + public double smallestDuration; + + public bool hasMultipleStartValues, hasMultipleEndValues, hasMultipleDurationValues; + public bool supportsExtrapolation, supportsClipIn, supportsSpeedMultiplier, supportsBlending; + public bool hasBlendIn, hasBlendOut; + public bool selectedAssetTypesAreHomogeneous; + public bool containsAtLeastTwoClipsOnTheSameTrack; + + public HashSet<TrackAsset> uniqueParentTracks = new HashSet<TrackAsset>(); + public ICollection<TimelineClip> clips { get; private set; } + + public ClipInspectorSelectionInfo(ICollection<TimelineClip> selectedClips) + { + supportsBlending = supportsClipIn = supportsExtrapolation = supportsSpeedMultiplier = true; + hasBlendIn = hasBlendOut = true; + selectedAssetTypesAreHomogeneous = true; + smallestDuration = TimelineClip.kMaxTimeValue; + start = end = duration = 0; + multipleClipStart = multipleClipEnd = 0; + hasMultipleStartValues = hasMultipleEndValues = hasMultipleDurationValues = false; + containsAtLeastTwoClipsOnTheSameTrack = false; + + clips = selectedClips; + Build(); + } + + void Build() + { + if (!clips.Any()) return; + + var firstSelectedClip = clips.First(); + if (firstSelectedClip == null) return; + + var firstSelectedClipAssetType = firstSelectedClip.asset != null ? firstSelectedClip.asset.GetType() : null; + + smallestDuration = TimelineClip.kMaxTimeValue; + InitSelectionBounds(firstSelectedClip); + InitMultipleClipBounds(firstSelectedClip); + + foreach (var clip in clips) + { + if (clip == null) continue; + + uniqueParentTracks.Add(clip.parentTrack); + selectedAssetTypesAreHomogeneous &= clip.asset.GetType() == firstSelectedClipAssetType; + + UpdateClipCaps(clip); + UpdateBlends(clip); + UpdateSmallestDuration(clip); + UpdateMultipleValues(clip); + UpdateMultipleValues(clip); + } + containsAtLeastTwoClipsOnTheSameTrack = uniqueParentTracks.Count != clips.Count; + } + + public void Update() + { + var firstSelectedClip = clips.First(); + if (firstSelectedClip == null) return; + + hasBlendIn = hasBlendOut = true; + hasMultipleStartValues = hasMultipleDurationValues = hasMultipleEndValues = false; + smallestDuration = TimelineClip.kMaxTimeValue; + InitSelectionBounds(firstSelectedClip); + InitMultipleClipBounds(firstSelectedClip); + + foreach (var clip in clips) + { + if (clip == null) continue; + + UpdateBlends(clip); + UpdateSmallestDuration(clip); + UpdateMultipleValues(clip); + } + } + + void InitSelectionBounds(TimelineClip clip) + { + start = clip.start; + duration = clip.duration; + end = clip.start + clip.duration; + } + + void InitMultipleClipBounds(TimelineClip firstSelectedClip) + { + multipleClipStart = firstSelectedClip.start; + multipleClipEnd = end; + } + + void UpdateSmallestDuration(TimelineClip clip) + { + smallestDuration = Math.Min(smallestDuration, clip.duration); + } + + void UpdateClipCaps(TimelineClip clip) + { + supportsBlending &= clip.SupportsBlending(); + supportsClipIn &= clip.SupportsClipIn(); + supportsExtrapolation &= clip.SupportsExtrapolation(); + supportsSpeedMultiplier &= clip.SupportsSpeedMultiplier(); + } + + void UpdateMultipleValues(TimelineClip clip) + { + hasMultipleStartValues |= !Mathf.Approximately((float)clip.start, (float)start); + hasMultipleDurationValues |= !Mathf.Approximately((float)clip.duration, (float)duration); + var clipEnd = clip.start + clip.duration; + hasMultipleEndValues |= !Mathf.Approximately((float)clipEnd, (float)end); + + multipleClipStart = Math.Min(multipleClipStart, clip.start); + multipleClipEnd = Math.Max(multipleClipEnd, clip.end); + } + + void UpdateBlends(TimelineClip clip) + { + hasBlendIn &= clip.hasBlendIn; + hasBlendOut &= clip.hasBlendOut; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorSelectionInfo.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorSelectionInfo.cs.meta new file mode 100644 index 0000000..bd8f85e --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/ClipInspector/ClipInspectorSelectionInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57a39be2178cca94ab21e15c082e3ab6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner.meta new file mode 100644 index 0000000..309cb0a --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 86cacab070a0a46e99aedb596a32c4fe +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/CurvesOwnerInspectorHelper.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/CurvesOwnerInspectorHelper.cs new file mode 100644 index 0000000..c5c4405 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/CurvesOwnerInspectorHelper.cs @@ -0,0 +1,109 @@ +using System; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + static class CurvesOwnerInspectorHelper + { + // Because what is animated is not the asset, but the instanced playable, + // we apply the animation clip here to preview what is being shown + // This could be improved doing something more inline with animation mode, + // and reverting values that aren't be recorded later to avoid dirtying the asset + public static void PreparePlayableAsset(ICurvesOwnerInspectorWrapper wrapper) + { + if (Event.current.type != EventType.Repaint) + return; + + if (wrapper.serializedPlayableAsset == null) + return; + + var curvesOwner = wrapper.curvesOwner; + if (curvesOwner == null || curvesOwner.curves == null) + return; + + var timelineWindow = TimelineWindow.instance; + if (timelineWindow == null || timelineWindow.state == null) + return; + + // requires preview mode. reset the eval time so previous value is correct value is displayed while toggling + if (!timelineWindow.state.previewMode) + { + wrapper.lastEvalTime = -1; + return; + } + + var time = wrapper.ToLocalTime(timelineWindow.state.editSequence.time); + + // detect if the time has changed, or if the curves have changed + if (Math.Abs(wrapper.lastEvalTime - time) < TimeUtility.kTimeEpsilon) + { + int curveVersion = AnimationClipCurveCache.Instance.GetCurveInfo(curvesOwner.curves).version; + if (curveVersion == wrapper.lastCurveVersion) + return; + + wrapper.lastCurveVersion = curveVersion; + } + + wrapper.lastEvalTime = time; + + var clipInfo = AnimationClipCurveCache.Instance.GetCurveInfo(curvesOwner.curves); + int count = clipInfo.bindings.Length; + if (count == 0) + return; + + wrapper.serializedPlayableAsset.Update(); + + var prop = wrapper.serializedPlayableAsset.GetIterator(); + while (prop.NextVisible(true)) + { + if (curvesOwner.IsParameterAnimated(prop.propertyPath)) + { + var curve = curvesOwner.GetAnimatedParameter(prop.propertyPath); + switch (prop.propertyType) + { + case SerializedPropertyType.Boolean: + prop.boolValue = curve.Evaluate((float)time) > 0; + break; + case SerializedPropertyType.Float: + prop.floatValue = curve.Evaluate((float)time); + break; + case SerializedPropertyType.Integer: + prop.intValue = Mathf.FloorToInt(curve.Evaluate((float)time)); + break; + case SerializedPropertyType.Color: + SetAnimatedValue(curvesOwner, prop, "r", time); + SetAnimatedValue(curvesOwner, prop, "g", time); + SetAnimatedValue(curvesOwner, prop, "b", time); + SetAnimatedValue(curvesOwner, prop, "a", time); + break; + case SerializedPropertyType.Quaternion: + case SerializedPropertyType.Vector4: + SetAnimatedValue(curvesOwner, prop, "w", time); + goto case SerializedPropertyType.Vector3; + case SerializedPropertyType.Vector3: + SetAnimatedValue(curvesOwner, prop, "z", time); + goto case SerializedPropertyType.Vector2; + case SerializedPropertyType.Vector2: + SetAnimatedValue(curvesOwner, prop, "x", time); + SetAnimatedValue(curvesOwner, prop, "y", time); + break; + } + } + } + + wrapper.serializedPlayableAsset.ApplyModifiedPropertiesWithoutUndo(); + } + + static void SetAnimatedValue(ICurvesOwner clip, SerializedProperty property, string path, double localTime) + { + var prop = property.FindPropertyRelative(path); + if (prop != null) + { + var curve = clip.GetAnimatedParameter(prop.propertyPath); + if (curve != null) + prop.floatValue = curve.Evaluate((float)localTime); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/CurvesOwnerInspectorHelper.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/CurvesOwnerInspectorHelper.cs.meta new file mode 100644 index 0000000..17e8bb3 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/CurvesOwnerInspectorHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a371bcbba2084dd0a8ebc6826aa8794 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/ICurvesOwnerInspectorWrapper.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/ICurvesOwnerInspectorWrapper.cs new file mode 100644 index 0000000..0ce6f58 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/ICurvesOwnerInspectorWrapper.cs @@ -0,0 +1,14 @@ +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + interface ICurvesOwnerInspectorWrapper + { + ICurvesOwner curvesOwner { get; } + SerializedObject serializedPlayableAsset { get; } + int lastCurveVersion { get; set; } + double lastEvalTime { get; set; } + + double ToLocalTime(double time); + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/ICurvesOwnerInspectorWrapper.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/ICurvesOwnerInspectorWrapper.cs.meta new file mode 100644 index 0000000..746e970 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/CurvesOwner/ICurvesOwnerInspectorWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 926a61ff0dec44a5aab649acb411e9ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/DirectorNamedColorInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/DirectorNamedColorInspector.cs new file mode 100644 index 0000000..5646870 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/DirectorNamedColorInspector.cs @@ -0,0 +1,27 @@ +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + /// <summary> + /// Internally used Inspector + /// </summary> + [CustomEditor(typeof(DirectorNamedColor))] + class DirectorNamedColorInspector : Editor + { + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + if (GUILayout.Button("ToTextAsset")) + { + DirectorStyles.Instance.ExportSkinToFile(); + } + + if (GUILayout.Button("Reload From File")) + { + DirectorStyles.Instance.ReloadSkin(); + UnityEditor.Selection.activeObject = DirectorStyles.Instance.customSkin; + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/DirectorNamedColorInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/DirectorNamedColorInspector.cs.meta new file mode 100644 index 0000000..250f3d4 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/DirectorNamedColorInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c8ceb9efacb4974bb3b7e2a87137b07 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClip.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClip.cs new file mode 100644 index 0000000..edd3d9d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClip.cs @@ -0,0 +1,24 @@ +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [ExcludeFromPreset] + class EditorClip : ScriptableObject + { + [SerializeField] TimelineClip m_Clip; + + public TimelineClip clip + { + get { return m_Clip; } + set { m_Clip = value; } + } + + public int lastHash { get; set; } + + public override int GetHashCode() + { + return clip.Hash(); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClip.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClip.cs.meta new file mode 100644 index 0000000..1887ce2 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClip.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 197c1114eb793d24c8ef31120a134e88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClipFactory.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClipFactory.cs new file mode 100644 index 0000000..d065b37 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClipFactory.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Timeline; +using UnityObject = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + static class EditorClipFactory + { + static Dictionary<TimelineClip, EditorClip> s_EditorCache = new Dictionary<TimelineClip, EditorClip>(); + + public static EditorClip GetEditorClip(TimelineClip clip) + { + if (clip == null) + throw new ArgumentException("parameter cannot be null"); + + if (s_EditorCache.ContainsKey(clip)) + { + var editorClip = s_EditorCache[clip]; + if (editorClip != null) + return editorClip; + } + + var editor = ScriptableObject.CreateInstance<EditorClip>(); + editor.hideFlags |= HideFlags.HideInHierarchy | HideFlags.DontSaveInEditor; + editor.lastHash = -1; + editor.clip = clip; + s_EditorCache[clip] = editor; + + return editor; + } + + public static void RemoveEditorClip(TimelineClip clip) + { + if (clip == null) + return; + + if (s_EditorCache.ContainsKey(clip)) + { + var obj = s_EditorCache[clip]; + if (obj != null) + UnityObject.DestroyImmediate(obj); + s_EditorCache.Remove(clip); + } + } + + public static bool Contains(TimelineClip clip) + { + return clip != null && s_EditorCache.ContainsKey(clip); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClipFactory.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClipFactory.cs.meta new file mode 100644 index 0000000..3681c42 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/EditorClipFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6ba30c492ac73742bc0cfee6817045a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/GroupTrackInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/GroupTrackInspector.cs new file mode 100644 index 0000000..5791e51 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/GroupTrackInspector.cs @@ -0,0 +1,107 @@ +//#define PERF_PROFILE + +using System.Linq; +using UnityEditorInternal; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [CustomEditor(typeof(GroupTrack)), CanEditMultipleObjects] + class GroupTrackInspector : TrackAssetInspector + { + static class Styles + { + public static readonly GUIContent GroupSubTrackHeaderName = EditorGUIUtility.TrTextContent("Name"); + public static readonly GUIContent GroupSubTrackHeaderType = EditorGUIUtility.TrTextContent("Type"); + public static readonly GUIContent GroupSubTrackHeaderDuration = EditorGUIUtility.TrTextContent("Duration"); + public static readonly GUIContent GroupSubTrackHeaderFrames = EditorGUIUtility.TrTextContent("Frames"); + public static readonly GUIContent GroupInvalidTrack = EditorGUIUtility.TrTextContent("Invalid Track"); + } + + ReorderableList m_SubTracks; + + public override void OnInspectorGUI() + { + foreach (var group in targets) + { + var groupTrack = group as GroupTrack; + if (groupTrack == null) return; + + var childrenTracks = groupTrack.GetChildTracks(); + var groupTrackName = groupTrack.name; + + GUILayout.Label(childrenTracks.Count() > 0 + ? groupTrackName + " (" + childrenTracks.Count() + ")" + : groupTrackName, EditorStyles.boldLabel); + GUILayout.Space(3.0f); + + // the subTrackObjects is used because it's the internal list + m_SubTracks.list = groupTrack.subTracksObjects; + m_SubTracks.DoLayoutList(); + m_SubTracks.index = -1; + } + } + + public override void OnEnable() + { + base.OnEnable(); + + m_SubTracks = new ReorderableList(new string[] {}, typeof(string), false, true, false, false) + { + drawElementCallback = OnDrawSubTrack, + drawHeaderCallback = OnDrawHeader, + showDefaultBackground = true, + index = 0, + elementHeight = 20 + }; + } + + static void OnDrawHeader(Rect rect) + { + int sections = 4; + float sectionWidth = rect.width / sections; + + rect.width = sectionWidth; + GUI.Label(rect, Styles.GroupSubTrackHeaderName, EditorStyles.label); + rect.x += sectionWidth; + GUI.Label(rect, Styles.GroupSubTrackHeaderType, EditorStyles.label); + rect.x += sectionWidth; + GUI.Label(rect, Styles.GroupSubTrackHeaderDuration, EditorStyles.label); + rect.x += sectionWidth; + GUI.Label(rect, Styles.GroupSubTrackHeaderFrames, EditorStyles.label); + } + + void OnDrawSubTrack(Rect rect, int index, bool selected, bool focused) + { + int sections = 4; + float sectionWidth = rect.width / sections; + + var childrenTrack = m_SubTracks.list[index] as TrackAsset; + if (childrenTrack == null) + { + object o = m_SubTracks.list[index]; + rect.width = sectionWidth; + if (o != null) // track is loaded, but has broken script + { + string name = ((UnityEngine.Object)m_SubTracks.list[index]).name; + GUI.Label(rect, name, EditorStyles.label); + } + rect.x += sectionWidth; + using (new GUIColorOverride(DirectorStyles.kClipErrorColor)) + GUI.Label(rect, Styles.GroupInvalidTrack.text, EditorStyles.label); + return; + } + + rect.width = sectionWidth; + GUI.Label(rect, childrenTrack.name, EditorStyles.label); + rect.x += sectionWidth; + GUI.Label(rect, childrenTrack.GetType().Name, EditorStyles.label); + rect.x += sectionWidth; + GUI.Label(rect, childrenTrack.duration.ToString(), EditorStyles.label); + rect.x += sectionWidth; + double exactFrames = TimeUtility.ToExactFrames(childrenTrack.duration, TimelineWindow.instance.state.referenceSequence.frameRate); + GUI.Label(rect, exactFrames.ToString(), EditorStyles.label); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/GroupTrackInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/GroupTrackInspector.cs.meta new file mode 100644 index 0000000..2730aef --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/GroupTrackInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41dcdc094b311464c8d6cb614548d89b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/MarkerInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/MarkerInspector.cs new file mode 100644 index 0000000..e8dea73 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/MarkerInspector.cs @@ -0,0 +1,69 @@ +using System; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [CustomEditor(typeof(Marker), true)] + [CanEditMultipleObjects] + class MarkerInspector : BasicAssetInspector + { + static class Styles + { + public static readonly string MultipleMarkerSelectionTitle = L10n.Tr("{0} Markers"); + public static readonly string UndoCommand = L10n.Tr("Rename marker"); + } + + internal override bool IsEnabled() + { + if (!TimelineUtility.IsCurrentSequenceValid() || IsCurrentSequenceReadOnly()) + return false; + var marker = target as Marker; + if (marker != null) + { + if (!marker.parent.GetShowMarkers()) + return false; + } + return base.IsEnabled(); + } + + internal override void OnHeaderTitleGUI(Rect titleRect, string header) + { + if (targets.Length > 1) + { + var multiSelectTitle = string.Format(Styles.MultipleMarkerSelectionTitle, targets.Length); + base.OnHeaderTitleGUI(titleRect, multiSelectTitle); + return; + } + + var marker = target as Marker; + if (marker != null) + { + if (marker.parent.GetShowMarkers() && TimelineUtility.IsCurrentSequenceValid() && !IsCurrentSequenceReadOnly()) + { + EditorGUI.BeginChangeCheck(); + var newName = EditorGUI.DelayedTextField(titleRect, marker.name); + if (EditorGUI.EndChangeCheck()) + { + TimelineUndo.PushUndo(marker, Styles.UndoCommand); + marker.name = newName; + } + } + else + { + base.OnHeaderTitleGUI(titleRect, marker.name); + } + } + else + { + var typeName = TypeUtility.GetDisplayName(target.GetType()); + EditorGUILayout.LabelField(typeName); + } + } + + static bool IsCurrentSequenceReadOnly() + { + return TimelineWindow.instance.state.editSequence.isReadOnly; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/MarkerInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/MarkerInspector.cs.meta new file mode 100644 index 0000000..9f6e901 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/MarkerInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb461734117c80c43ab595d699f801eb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimeFieldDrawer.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimeFieldDrawer.cs new file mode 100644 index 0000000..622f5b4 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimeFieldDrawer.cs @@ -0,0 +1,69 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [CustomPropertyDrawer(typeof(TimeFieldAttribute), true)] + class TimeFieldDrawer : PropertyDrawer + { + static WindowState state + { + get { return TimelineWindow.instance != null ? TimelineWindow.instance.state : null; } + } + + static float currentFrameRate + { + get { return state != null ? TimelineWindow.instance.state.referenceSequence.frameRate : 0.0f; } + } + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + if (property.propertyType != SerializedPropertyType.Float) + { + GUILayout.Label("TimeField only works on floating point types"); + return; + } + + var timeFieldAttribute = attribute as TimeFieldAttribute; + if (timeFieldAttribute == null) + return; + + var rect = EditorGUILayout.s_LastRect; + EditorGUI.BeginChangeCheck(); + + if (timeFieldAttribute.useEditMode == TimeFieldAttribute.UseEditMode.ApplyEditMode) + TimeFieldWithEditMode(rect, property, label); + else + TimeField(rect, property, label); + + if (EditorGUI.EndChangeCheck()) + { + if (state != null) + state.Refresh(); + } + } + + static void TimeField(Rect rect, SerializedProperty property, GUIContent label) + { + var evt1 = InputEvent.None; + TimelineInspectorUtility.TimeField(rect, property, label, false, currentFrameRate, 0, float.MaxValue, ref evt1); + } + + static void TimeFieldWithEditMode(Rect rect, SerializedProperty property, GUIContent label) + { + double minStartTime; + if (property.hasMultipleDifferentValues) + minStartTime = SelectionManager.SelectedItems().Min(i => i.start); + else + minStartTime = property.doubleValue; + + var evt = InputEvent.None; + var newValue = TimelineInspectorUtility.TimeField( + rect, label, minStartTime, false, property.hasMultipleDifferentValues, currentFrameRate, 0.0, float.MaxValue, ref evt); + + EditMode.inputHandler.ProcessMove(evt, newValue); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimeFieldDrawer.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimeFieldDrawer.cs.meta new file mode 100644 index 0000000..89749e8 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimeFieldDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0c73ea1c5ff95e43806e9002c155070 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineAssetInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineAssetInspector.cs new file mode 100644 index 0000000..9229464 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineAssetInspector.cs @@ -0,0 +1,78 @@ +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [CustomEditor(typeof(TimelineAsset)), CanEditMultipleObjects] + class TimelineAssetInspector : Editor + { + static class Styles + { + public static readonly GUIContent FrameRate = EditorGUIUtility.TrTextContent("Frame Rate", "The frame rate at which this sequence updates"); + public static readonly GUIContent DurationMode = EditorGUIUtility.TrTextContent("Duration Mode", "Specified how the duration of the sequence is calculated"); + public static readonly GUIContent Duration = EditorGUIUtility.TrTextContent("Duration", "The length of the sequence"); + public static readonly GUIContent HeaderTitleMultiselection = EditorGUIUtility.TrTextContent("Timeline Assets"); + } + + SerializedProperty m_FrameRateProperty; + SerializedProperty m_DurationModeProperty; + SerializedProperty m_FixedDurationProperty; + + void InitializeProperties() + { + m_FrameRateProperty = serializedObject.FindProperty("m_EditorSettings").FindPropertyRelative("m_Framerate"); + m_DurationModeProperty = serializedObject.FindProperty("m_DurationMode"); + m_FixedDurationProperty = serializedObject.FindProperty("m_FixedDuration"); + } + + public void OnEnable() + { + InitializeProperties(); + } + + internal override bool IsEnabled() + { + return !FileUtil.HasReadOnly(targets) && base.IsEnabled(); + } + + protected override void OnHeaderGUI() + { + string headerTitle; + if (targets.Length == 1) + headerTitle = target.name; + else + headerTitle = targets.Length.ToString() + " " + Styles.HeaderTitleMultiselection.text; + + DrawHeaderGUI(this, headerTitle, 0); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + EditorGUI.BeginChangeCheck(); + + EditorGUILayout.PropertyField(m_FrameRateProperty, Styles.FrameRate, GUILayout.MinWidth(140)); + var frameRate = m_FrameRateProperty.doubleValue; + + EditorGUILayout.PropertyField(m_DurationModeProperty, Styles.DurationMode, GUILayout.MinWidth(140)); + + var durationMode = (TimelineAsset.DurationMode)m_DurationModeProperty.enumValueIndex; + var inputEvent = InputEvent.None; + if (durationMode == TimelineAsset.DurationMode.FixedLength) + TimelineInspectorUtility.TimeField(m_FixedDurationProperty, Styles.Duration, false, frameRate, double.Epsilon, TimelineClip.kMaxTimeValue * 2, ref inputEvent); + else + { + var isMixed = targets.Length > 1; + TimelineInspectorUtility.TimeField(Styles.Duration, ((TimelineAsset)target).duration, true, isMixed, frameRate, double.MinValue, double.MaxValue, ref inputEvent); + } + + bool changed = EditorGUI.EndChangeCheck(); + + serializedObject.ApplyModifiedProperties(); + + if (changed) + TimelineWindow.RepaintIfEditingTimelineAsset((TimelineAsset)target); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineAssetInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineAssetInspector.cs.meta new file mode 100644 index 0000000..1ba0620 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineAssetInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e00a5dea786950546a21b0e2d817e466 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineInspectorUtility.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineInspectorUtility.cs new file mode 100644 index 0000000..f1c9d4a --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineInspectorUtility.cs @@ -0,0 +1,353 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [Flags] + enum InputEvent + { + None = 0, + DragEnter = 1, + DragExit = 2, + Drag = 4, + KeyboardInput = 8 + } + + static class InputEventMethods + { + public static bool InputHasBegun(this InputEvent evt) + { + return evt == InputEvent.DragEnter || evt == InputEvent.KeyboardInput; + } + } + + static class TimelineInspectorUtility + { + internal static class Styles + { + public static readonly GUIContent SecondsPrefix = EditorGUIUtility.TrTextContent("s", "Seconds"); + public static readonly GUIContent FramesPrefix = EditorGUIUtility.TrTextContent("f", "Frames"); + } + + public static void TimeField(SerializedProperty property, GUIContent label, bool readOnly, double frameRate, double minValue, double maxValue, ref InputEvent inputEvent) + { + var rect = EditorGUILayout.GetControlRect(); + TimeField(rect, property, label, readOnly, frameRate, minValue, maxValue, ref inputEvent); + } + + // Display Time related properties in frames and seconds + public static void TimeField(Rect rect, SerializedProperty property, GUIContent label, bool readOnly, double frameRate, double minValue, double maxValue, ref InputEvent inputEvent) + { + GUIContent title = EditorGUI.BeginProperty(rect, label, property); + rect = EditorGUI.PrefixLabel(rect, title); + + int indentLevel = EditorGUI.indentLevel; + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUI.indentLevel = 0; + EditorGUIUtility.labelWidth = (int)EditorGUI.kMiniLabelW; + using (new GUIMixedValueScope(property.hasMultipleDifferentValues)) + { + var secondsRect = new Rect(rect.xMin, rect.yMin, rect.width / 2 - EditorGUI.kSpacingSubLabel, rect.height); + var framesRect = new Rect(rect.xMin + rect.width / 2, rect.yMin, rect.width / 2, rect.height); + + if (readOnly) + { + EditorGUI.FloatField(secondsRect, Styles.SecondsPrefix, (float)property.doubleValue, EditorStyles.label); + } + else + { + EditorGUI.BeginChangeCheck(); + DelayedAndDraggableDoubleField(secondsRect, Styles.SecondsPrefix, property, ref inputEvent); + if (EditorGUI.EndChangeCheck()) + { + property.doubleValue = Clamp(property.doubleValue, minValue, maxValue); + } + } + + if (frameRate > TimeUtility.kTimeEpsilon) + { + EditorGUI.BeginChangeCheck(); + + double time = property.doubleValue; + int frames = TimeUtility.ToFrames(time, frameRate); + double exactFrames = TimeUtility.ToExactFrames(time, frameRate); + bool useIntField = TimeUtility.OnFrameBoundary(time, frameRate); + + if (readOnly) + { + if (useIntField) + EditorGUI.IntField(framesRect, Styles.FramesPrefix, frames, EditorStyles.label); + else + EditorGUI.DoubleField(framesRect, Styles.FramesPrefix, exactFrames, EditorStyles.label); + } + else + { + if (useIntField) + { + int newFrames = DelayedAndDraggableIntField(framesRect, Styles.FramesPrefix, frames, ref inputEvent); + time = Math.Max(0, TimeUtility.FromFrames(newFrames, frameRate)); + } + else + { + double newExactFrames = DelayedAndDraggableDoubleField(framesRect, Styles.FramesPrefix, exactFrames, ref inputEvent); + time = Math.Max(0, TimeUtility.FromFrames((int)Math.Floor(newExactFrames), frameRate)); + } + } + + if (EditorGUI.EndChangeCheck()) + { + property.doubleValue = Clamp(time, minValue, maxValue); + } + } + + EditorGUI.indentLevel = indentLevel; + EditorGUIUtility.labelWidth = labelWidth; + EditorGUI.EndProperty(); + } + } + + public static double TimeFieldUsingTimeReference( + GUIContent label, double time, bool readOnly, bool showMixed, double frameRate, double minValue, + double maxValue, ref InputEvent inputEvent) + { + var state = TimelineWindow.instance.state; + var needsTimeConversion = state != null && state.timeReferenceMode == TimeReferenceMode.Global; + + if (needsTimeConversion) + time = state.editSequence.ToGlobalTime(time); + + var t = TimeField(label, time, readOnly, showMixed, frameRate, minValue, maxValue, ref inputEvent); + + if (needsTimeConversion) + t = state.editSequence.ToLocalTime(t); + + return t; + } + + public static double DurationFieldUsingTimeReference( + GUIContent label, double start, double end, bool readOnly, bool showMixed, double frameRate, + double minValue, double maxValue, ref InputEvent inputEvent) + { + var state = TimelineWindow.instance.state; + var needsTimeConversion = state != null && state.timeReferenceMode == TimeReferenceMode.Global; + + if (needsTimeConversion) + { + start = state.editSequence.ToGlobalTime(start); + end = state.editSequence.ToGlobalTime(end); + } + + var duration = end - start; + + var t = TimeField(label, duration, readOnly, showMixed, frameRate, minValue, maxValue, ref inputEvent); + + end = start + t; + + if (needsTimeConversion) + { + start = state.editSequence.ToLocalTime(start); + end = state.editSequence.ToLocalTime(end); + } + + return end - start; + } + + public static double TimeField(Rect rect, GUIContent label, double time, bool readOnly, bool showMixed, double frameRate, double minValue, double maxValue, ref InputEvent inputEvent) + { + EditorGUILayout.BeginHorizontal(label, GUIStyle.none); + rect = EditorGUI.PrefixLabel(rect, label); + + int indentLevel = EditorGUI.indentLevel; + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUI.indentLevel = 0; + EditorGUIUtility.labelWidth = (int)EditorGUI.kMiniLabelW; + using (new GUIMixedValueScope(showMixed)) + { + var secondsRect = new Rect(rect.xMin, rect.yMin, rect.width / 2 - EditorGUI.kSpacingSubLabel, rect.height); + var framesRect = new Rect(rect.xMin + rect.width / 2, rect.yMin, rect.width / 2, rect.height); + + if (readOnly) + { + EditorGUI.FloatField(secondsRect, Styles.SecondsPrefix, (float)time, EditorStyles.label); + } + else + { + time = DelayedAndDraggableDoubleField(secondsRect, Styles.SecondsPrefix, time, ref inputEvent); + } + + if (frameRate > TimeUtility.kTimeEpsilon) + { + int frames = TimeUtility.ToFrames(time, frameRate); + double exactFrames = TimeUtility.ToExactFrames(time, frameRate); + bool useIntField = TimeUtility.OnFrameBoundary(time, frameRate); + if (readOnly) + { + if (useIntField) + EditorGUI.IntField(framesRect, Styles.FramesPrefix, frames, EditorStyles.label); + else + EditorGUI.FloatField(framesRect, Styles.FramesPrefix, (float)exactFrames, EditorStyles.label); + } + else + { + double newTime; + EditorGUI.BeginChangeCheck(); + if (useIntField) + { + int newFrames = DelayedAndDraggableIntField(framesRect, Styles.FramesPrefix, frames, ref inputEvent); + newTime = Math.Max(0, TimeUtility.FromFrames(newFrames, frameRate)); + } + else + { + double newExactFrames = DelayedAndDraggableDoubleField(framesRect, Styles.FramesPrefix, exactFrames, ref inputEvent); + newTime = Math.Max(0, TimeUtility.FromFrames((int)Math.Floor(newExactFrames), frameRate)); + } + + if (EditorGUI.EndChangeCheck()) + { + time = newTime; + } + } + } + + EditorGUILayout.EndHorizontal(); + EditorGUI.indentLevel = indentLevel; + EditorGUIUtility.labelWidth = labelWidth; + } + + return Clamp(time, minValue, maxValue); + } + + public static double TimeField(GUIContent label, double time, bool readOnly, bool showMixed, double frameRate, double minValue, double maxValue, ref InputEvent inputEvent) + { + var rect = EditorGUILayout.GetControlRect(); + return TimeField(rect, label, time, readOnly, showMixed, frameRate, minValue, maxValue, ref inputEvent); + } + + static InputEvent InputEventType(Rect rect, int id) + { + var evt = Event.current; + switch (evt.GetTypeForControl(id)) + { + case EventType.MouseDown: + if (rect.Contains(evt.mousePosition) && evt.button == 0) + { + return InputEvent.DragEnter; + } + break; + case EventType.MouseUp: + if (GUIUtility.hotControl == id) + { + return InputEvent.DragExit; + } + break; + case EventType.MouseDrag: + if (GUIUtility.hotControl == id) + { + return InputEvent.Drag; + } + break; + case EventType.KeyDown: + if (GUIUtility.hotControl == id && evt.keyCode == KeyCode.Escape) + { + return InputEvent.DragExit; + } + break; + } + return InputEvent.None; + } + + static double DelayedAndDraggableDoubleField(Rect rect, GUIContent label, double value, ref InputEvent inputEvent, double dragSensitivity) + { + var id = GUIUtility.GetControlID(FocusType.Keyboard); + var fieldRect = EditorGUI.PrefixLabel(rect, id, label); + rect.xMax = fieldRect.x; + + double refValue = value; + long dummy = 0; + + inputEvent |= InputEventType(rect, id); + + EditorGUI.DragNumberValue(rect, id, true, ref refValue, ref dummy, dragSensitivity); + + EditorGUI.BeginChangeCheck(); + var result = EditorGUI.DelayedDoubleFieldInternal(fieldRect, GUIContent.none, refValue, EditorStyles.numberField); + if (EditorGUI.EndChangeCheck()) + inputEvent |= InputEvent.KeyboardInput; + + return result; + } + + static int DelayedAndDraggableIntField(Rect rect, GUIContent label, int value, ref InputEvent inputEvent, long dragSensitivity) + { + var id = GUIUtility.GetControlID(FocusType.Keyboard); + var fieldRect = EditorGUI.PrefixLabel(rect, id, label); + rect.xMax = fieldRect.x; + + double dummy = 0.0; + long refValue = value; + + inputEvent |= InputEventType(rect, id); + + EditorGUI.DragNumberValue(rect, id, false, ref dummy, ref refValue, dragSensitivity); + + EditorGUI.BeginChangeCheck(); + var result = EditorGUI.DelayedIntFieldInternal(fieldRect, GUIContent.none, (int)refValue, EditorStyles.numberField); + if (EditorGUI.EndChangeCheck()) + inputEvent |= InputEvent.KeyboardInput; + + return result; + } + + internal static double DelayedAndDraggableDoubleField(GUIContent label, double value, ref InputEvent action, double dragSensitivity) + { + var r = EditorGUILayout.s_LastRect = EditorGUILayout.GetControlRect(false, EditorGUI.kSingleLineHeight); + return DelayedAndDraggableDoubleField(r, label, value, ref action, dragSensitivity); + } + + static void DelayedAndDraggableDoubleField(Rect rect, GUIContent label, SerializedProperty property, ref InputEvent inputEvent) + { + EditorGUI.BeginChangeCheck(); + var newValue = DelayedAndDraggableDoubleField(rect, label, property.doubleValue, ref inputEvent); + if (EditorGUI.EndChangeCheck()) + property.doubleValue = newValue; + } + + static double DelayedAndDraggableDoubleField(Rect rect, GUIContent label, double value, ref InputEvent inputEvent) + { + var dragSensitivity = NumericFieldDraggerUtility.CalculateFloatDragSensitivity(value); + return DelayedAndDraggableDoubleField(rect, label, value, ref inputEvent, dragSensitivity); + } + + static int DelayedAndDraggableIntField(Rect rect, GUIContent label, int value, ref InputEvent inputEvent) + { + var dragSensitivity = NumericFieldDraggerUtility.CalculateIntDragSensitivity(value); + return DelayedAndDraggableIntField(rect, label, value, ref inputEvent, dragSensitivity); + } + + internal static T Clamp<T>(this T val, T min, T max) where T : IComparable<T> + { + if (val.CompareTo(min) < 0) return min; + if (val.CompareTo(max) > 0) return max; + return val; + } + + public static Editor GetInspectorForObjects(UnityEngine.Object[] objects) + { + // create cached editor throws on assembly reload... + try + { + if (objects.Any(x => x != null)) + { + var director = TimelineWindow.instance.state.editSequence.director; + return Editor.CreateEditorWithContext(objects, director, null); + } + } + catch (Exception) + {} + + return null; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineInspectorUtility.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineInspectorUtility.cs.meta new file mode 100644 index 0000000..808a29d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TimelineInspectorUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3387717991705ce4e8ef033a0e543a06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TrackAssetInspector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TrackAssetInspector.cs new file mode 100644 index 0000000..91e83e1 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TrackAssetInspector.cs @@ -0,0 +1,203 @@ +//#define PERF_PROFILE + +using System.Linq; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + [CustomEditor(typeof(TrackAsset), true, isFallback = true)] + [CanEditMultipleObjects] + class TrackAssetInspector : Editor + { + class TrackCurvesWrapper : ICurvesOwnerInspectorWrapper + { + public ICurvesOwner curvesOwner { get; } + public SerializedObject serializedPlayableAsset { get; } + + public int lastCurveVersion { get; set; } + public double lastEvalTime { get; set; } + + public TrackCurvesWrapper(TrackAsset track) + { + lastCurveVersion = -1; + lastEvalTime = -1; + + if (track != null) + { + curvesOwner = track; + serializedPlayableAsset = new SerializedObject(track); + } + } + + public double ToLocalTime(double time) + { + return time; + } + } + + TrackCurvesWrapper m_TrackCurvesWrapper; + + SerializedProperty m_Name; + bool m_IsBuiltInType; + + Texture m_HeaderIcon; + + + protected TimelineWindow timelineWindow + { + get + { + return TimelineWindow.instance; + } + } + + protected bool IsTrackLocked() + { + if (!TimelineUtility.IsCurrentSequenceValid() || IsCurrentSequenceReadOnly()) + return true; + + return targets.Any(track => ((TrackAsset)track).lockedInHierarchy); + } + + public override void OnInspectorGUI() + { + using (new EditorGUI.DisabledScope(IsTrackLocked())) + { + DrawInspector(); + } + } + + internal override bool IsEnabled() + { + return TimelineUtility.IsCurrentSequenceValid() && !IsCurrentSequenceReadOnly() && base.IsEnabled(); + } + + internal override void OnHeaderTitleGUI(Rect titleRect, string header) + { + serializedObject.Update(); + + var textFieldRect = titleRect; + using (new GUIMixedValueScope(m_Name.hasMultipleDifferentValues)) + { + var seqWindow = TimelineWindow.instance; + + if (IsTrackLocked()) + { + base.OnHeaderTitleGUI(titleRect, m_Name.stringValue); + } + else + { + EditorGUI.BeginChangeCheck(); + string newName = EditorGUI.DelayedTextField(textFieldRect, m_Name.stringValue, EditorStyles.textField); + if (EditorGUI.EndChangeCheck() && !string.IsNullOrEmpty(newName)) + { + for (int c = 0; c < targets.Length; c++) + { + ObjectNames.SetNameSmart(targets[c], newName); + } + + if (seqWindow != null) + seqWindow.Repaint(); + } + + serializedObject.ApplyModifiedProperties(); + } + } + } + + internal override void OnHeaderIconGUI(Rect iconRect) + { + if (TimelineWindow.instance == null) + return; + using (new EditorGUI.DisabledScope(IsTrackLocked())) + { + if (m_HeaderIcon != null) + GUI.Label(iconRect, GUIContent.Temp(m_HeaderIcon)); + } + } + + internal override Rect DrawHeaderHelpAndSettingsGUI(Rect r) + { + using (new EditorGUI.DisabledScope(IsTrackLocked())) + { + var helpSize = EditorStyles.iconButton.CalcSize(EditorGUI.GUIContents.helpIcon); + const int kTopMargin = 5; + + // Show Editor Header Items. + return EditorGUIUtility.DrawEditorHeaderItems(new Rect(r.xMax - helpSize.x, r.y + kTopMargin, helpSize.x, helpSize.y), targets); + } + } + + public virtual void OnEnable() + { + m_IsBuiltInType = target != null && target.GetType().Assembly == typeof(TrackAsset).Assembly; + m_Name = serializedObject.FindProperty("m_Name"); + m_TrackCurvesWrapper = new TrackCurvesWrapper(target as TrackAsset); + m_HeaderIcon = TrackResourceCache.s_DefaultIcon.image; + + // only worry about the first track. if types are different, a different inspector is used. + var track = target as TrackAsset; + if (track != null) + { + var drawer = CustomTimelineEditorCache.GetTrackEditor(track); + UnityEngine.Object binding = null; + var director = m_Context as PlayableDirector; + if (director != null) + binding = director.GetGenericBinding(track); + + var options = drawer.GetTrackOptions(track, binding); + if (options.icon != null) + m_HeaderIcon = options.icon; + else + m_HeaderIcon = TrackResourceCache.GetTrackIcon(track).image; + } + } + + void DrawInspector() + { + if (serializedObject == null) + return; + + CurvesOwnerInspectorHelper.PreparePlayableAsset(m_TrackCurvesWrapper); + serializedObject.Update(); + + using (var changeScope = new EditorGUI.ChangeCheckScope()) + { + DrawTrackProperties(); + + if (changeScope.changed) + { + serializedObject.ApplyModifiedProperties(); + ApplyChanges(); + } + } + } + + protected virtual void DrawTrackProperties() + { + var property = serializedObject.GetIterator(); + var expanded = true; + while (property.NextVisible(expanded)) + { + // Don't draw script field for built-in types + if (m_IsBuiltInType && "m_Script" == property.propertyPath) + continue; + + EditorGUILayout.PropertyField(property, !expanded); + expanded = false; + } + } + + protected virtual void ApplyChanges() + { + TimelineEditor.Refresh(RefreshReason.ContentsModified); + } + + static bool IsCurrentSequenceReadOnly() + { + return TimelineWindow.instance.state.editSequence.isReadOnly; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TrackAssetInspector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TrackAssetInspector.cs.meta new file mode 100644 index 0000000..922b049 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/inspectors/TrackAssetInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8795e0dd0041d2f44b1fe1959fc9fb53 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |
