diff options
Diffstat (limited to 'Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities')
58 files changed, 3870 insertions, 0 deletions
diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterCache.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterCache.cs new file mode 100644 index 0000000..d5f091f --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterCache.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace UnityEditor.Timeline +{ + static class AnimatedParameterCache + { + static readonly Dictionary<Type, FieldInfo[]> k_ScriptPlayableFieldsCache = new Dictionary<Type, FieldInfo[]>(); + static readonly Dictionary<PropertyKey, FieldInfo> k_PropertyFieldInfoCache = new Dictionary<PropertyKey, FieldInfo>(); + static readonly Dictionary<PropertyKey, bool> k_PropertyIsAnimatableCache = new Dictionary<PropertyKey, bool>(); + static readonly Dictionary<PropertyKey, string> k_BindingNameCache = new Dictionary<PropertyKey, string>(); + + public static bool TryGetScriptPlayableFields(Type type, out FieldInfo[] scriptPlayableFields) + { + return k_ScriptPlayableFieldsCache.TryGetValue(type, out scriptPlayableFields); + } + + public static void SetScriptPlayableFields(Type type, FieldInfo[] scriptPlayableFields) + { + k_ScriptPlayableFieldsCache[type] = scriptPlayableFields; + } + + public static bool TryGetFieldInfoForProperty(SerializedProperty property, out FieldInfo fieldInfo) + { + return k_PropertyFieldInfoCache.TryGetValue(new PropertyKey(property), out fieldInfo); + } + + public static void SetFieldInfoForProperty(SerializedProperty property, FieldInfo fieldInfo) + { + k_PropertyFieldInfoCache[new PropertyKey(property)] = fieldInfo; + } + + public static bool TryGetIsPropertyAnimatable(SerializedProperty property, out bool isAnimatable) + { + return k_PropertyIsAnimatableCache.TryGetValue(new PropertyKey(property), out isAnimatable); + } + + public static void SetIsPropertyAnimatable(SerializedProperty property, bool isAnimatable) + { + k_PropertyIsAnimatableCache[new PropertyKey(property)] = isAnimatable; + } + + public static bool TryGetBindingName(Type type, string path, out string bindingName) + { + return k_BindingNameCache.TryGetValue(new PropertyKey(type, path), out bindingName); + } + + public static void SetBindingName(Type type, string path, string bindingName) + { + k_BindingNameCache[new PropertyKey(type, path)] = bindingName; + } + } + + struct PropertyKey : IEquatable<PropertyKey> + { + readonly Type m_Type; + readonly string m_Path; + + public PropertyKey(SerializedProperty property) + { + m_Type = property.serializedObject.targetObject.GetType(); + m_Path = property.propertyPath; + } + + public PropertyKey(Type type, string path) + { + m_Type = type; + m_Path = path; + } + + public bool Equals(PropertyKey other) + { + return m_Type == other.m_Type && string.Equals(m_Path, other.m_Path); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is PropertyKey && Equals((PropertyKey)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((m_Type != null ? m_Type.GetHashCode() : 0) * 397) ^ (m_Path != null ? m_Path.GetHashCode() : 0); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterCache.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterCache.cs.meta new file mode 100644 index 0000000..19831f1 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1fe0f539450e54dbc85bfb2fa6b466fb +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/Utilities/AnimatedParameterUtility.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterUtility.cs new file mode 100644 index 0000000..53542e3 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterUtility.cs @@ -0,0 +1,358 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; +using UnityObject = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + static class AnimatedParameterUtility + { + static readonly Type k_DefaultAnimationType = typeof(TimelineAsset); + static SerializedObject s_CachedObject; + + public static ICurvesOwner ToCurvesOwner(IPlayableAsset playableAsset, TimelineAsset timeline) + { + if (playableAsset == null) + return null; + + var curvesOwner = playableAsset as ICurvesOwner; + if (curvesOwner == null) + { + // If the asset is not directly an ICurvesOwner, it might be the asset for a TimelineClip + curvesOwner = TimelineRecording.FindClipWithAsset(timeline, playableAsset); + } + + return curvesOwner; + } + + public static bool TryGetSerializedPlayableAsset(UnityObject asset, out SerializedObject serializedObject) + { + serializedObject = null; + if (asset == null || Attribute.IsDefined(asset.GetType(), typeof(NotKeyableAttribute)) || !HasScriptPlayable(asset)) + return false; + + serializedObject = GetSerializedPlayableAsset(asset); + return serializedObject != null; + } + + public static SerializedObject GetSerializedPlayableAsset(UnityObject asset) + { + if (!(asset is IPlayableAsset)) + return null; + + var scriptObject = asset as ScriptableObject; + if (scriptObject == null) + return null; + + if (s_CachedObject == null || s_CachedObject.targetObject != asset) + { + s_CachedObject = new SerializedObject(scriptObject); + } + + return s_CachedObject; + } + + public static void UpdateSerializedPlayableAsset(UnityObject asset) + { + var so = GetSerializedPlayableAsset(asset); + if (so != null) + so.UpdateIfRequiredOrScript(); + } + + public static bool HasScriptPlayable(UnityObject asset) + { + if (asset == null) + return false; + + var scriptPlayable = asset as IPlayableBehaviour; + return scriptPlayable != null || GetScriptPlayableFields(asset as IPlayableAsset).Any(); + } + + public static FieldInfo[] GetScriptPlayableFields(IPlayableAsset asset) + { + if (asset == null) + return new FieldInfo[0]; + + FieldInfo[] scriptPlayableFields; + if (!AnimatedParameterCache.TryGetScriptPlayableFields(asset.GetType(), out scriptPlayableFields)) + { + scriptPlayableFields = GetScriptPlayableFields_Internal(asset); + AnimatedParameterCache.SetScriptPlayableFields(asset.GetType(), scriptPlayableFields); + } + + return scriptPlayableFields; + } + + static FieldInfo[] GetScriptPlayableFields_Internal(IPlayableAsset asset) + { + return asset.GetType() + .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where( + f => typeof(IPlayableBehaviour).IsAssignableFrom(f.FieldType) && // The field is an IPlayableBehaviour + (f.IsPublic || f.GetCustomAttributes(typeof(SerializeField), false).Any()) && // The field is either public or marked with [SerializeField] + !f.GetCustomAttributes(typeof(NotKeyableAttribute), false).Any() && // The field is not marked with [NotKeyable] + !f.GetCustomAttributes(typeof(HideInInspector), false).Any() && // The field is not marked with [HideInInspector] + !f.FieldType.GetCustomAttributes(typeof(NotKeyableAttribute), false).Any()) // The field is not of a type marked with [NotKeyable] + .ToArray(); + } + + public static bool HasAnyAnimatableParameters(UnityObject asset) + { + return GetAllAnimatableParameters(asset).Any(); + } + + public static IEnumerable<SerializedProperty> GetAllAnimatableParameters(UnityObject asset) + { + SerializedObject serializedObject; + if (!TryGetSerializedPlayableAsset(asset, out serializedObject)) + yield break; + + var prop = serializedObject.GetIterator(); + + // We need to keep this variable because prop starts invalid + var outOfBounds = false; + while (!outOfBounds && prop.NextVisible(true)) + { + foreach (var property in SelectAnimatableProperty(prop)) + yield return property; + + // We can become out of bounds by calling SelectAnimatableProperty, if the last iterated property is a color. + outOfBounds = !prop.isValid; + } + } + + static IEnumerable<SerializedProperty> SelectAnimatableProperty(SerializedProperty prop) + { + // We're only interested by animatable leaf parameters + if (!prop.hasChildren && IsParameterAnimatable(prop)) + yield return prop.Copy(); + + // Color type is not considered "visible" when iterating + if (prop.propertyType == SerializedPropertyType.Color) + { + var end = prop.GetEndProperty(); + + // For some reasons, if the last 2+ serialized properties are of type Color, prop becomes invalid and + // Next() throws an exception. This is not the case when only the last serialized property is a Color. + while (!SerializedProperty.EqualContents(prop, end) && prop.isValid && prop.Next(true)) + { + foreach (var property in SelectAnimatableProperty(prop)) + yield return property; + } + } + } + + public static bool IsParameterAnimatable(UnityObject asset, string parameterName) + { + SerializedObject serializedObject; + if (!TryGetSerializedPlayableAsset(asset, out serializedObject)) + return false; + + var prop = serializedObject.FindProperty(parameterName); + return IsParameterAnimatable(prop); + } + + public static bool IsParameterAnimatable(SerializedProperty property) + { + if (property == null) + return false; + + bool isAnimatable; + if (!AnimatedParameterCache.TryGetIsPropertyAnimatable(property, out isAnimatable)) + { + isAnimatable = IsParameterAnimatable_Internal(property); + AnimatedParameterCache.SetIsPropertyAnimatable(property, isAnimatable); + } + + return isAnimatable; + } + + static bool IsParameterAnimatable_Internal(SerializedProperty property) + { + if (property == null) + return false; + + var asset = property.serializedObject.targetObject; + + // Currently not supported + if (asset is AnimationTrack) + return false; + + if (IsParameterKeyable(property)) + return asset is IPlayableBehaviour || IsParameterAtPathAnimatable(asset, property.propertyPath); + + return false; + } + + static bool IsParameterKeyable(SerializedProperty property) + { + return IsTypeAnimatable(property.propertyType) && IsKeyableInHierarchy(property); + } + + static bool IsKeyableInHierarchy(SerializedProperty property) + { + const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + var pathSegments = property.propertyPath.Split('.'); + var type = property.serializedObject.targetObject.GetType(); + foreach (var segment in pathSegments) + { + if (type.GetCustomAttributes(typeof(NotKeyableAttribute), false).Any()) + { + return false; + } + + if (type.IsArray) + { + if (segment != "Array") + type = type.GetElementType(); + continue; + } + + var fieldInfo = type.GetField(segment, bindingFlags); + + if (fieldInfo == null || + fieldInfo.GetCustomAttributes(typeof(NotKeyableAttribute), false).Any() || + fieldInfo.GetCustomAttributes(typeof(HideInInspector), false).Any()) + { + return false; + } + + type = fieldInfo.FieldType; + } + + return true; + } + + static bool IsParameterAtPathAnimatable(UnityObject asset, string path) + { + if (asset == null) + return false; + + return GetScriptPlayableFields(asset as IPlayableAsset) + .Any( + f => path.StartsWith(f.Name, StringComparison.Ordinal) && + path.Length > f.Name.Length && + path[f.Name.Length] == '.'); + } + + public static bool IsTypeAnimatable(SerializedPropertyType type) + { + // Note: Integer is not currently supported by the animated property system + switch (type) + { + case SerializedPropertyType.Boolean: + case SerializedPropertyType.Float: + case SerializedPropertyType.Vector2: + case SerializedPropertyType.Vector3: + case SerializedPropertyType.Color: + case SerializedPropertyType.Quaternion: + case SerializedPropertyType.Vector4: + return true; + default: + return false; + } + } + + public static bool IsParameterAnimated(UnityObject asset, AnimationClip animationData, string parameterName) + { + if (asset == null || animationData == null) + return false; + + var binding = GetCurveBinding(asset, parameterName); + var bindings = AnimationClipCurveCache.Instance.GetCurveInfo(animationData).bindings; + return bindings.Any(x => BindingMatchesParameterName(x, binding.propertyName)); + } + + // Retrieve an animated parameter curve. parameter name is required to include the appropriate field for vectors + // e.g.: position + public static AnimationCurve GetAnimatedParameter(UnityObject asset, AnimationClip animationData, string parameterName) + { + if (!(asset is ScriptableObject) || animationData == null) + return null; + + var binding = GetCurveBinding(asset, parameterName); + return AnimationUtility.GetEditorCurve(animationData, binding); + } + + // get an animatable curve binding for this parameter + public static EditorCurveBinding GetCurveBinding(UnityObject asset, string parameterName) + { + var animationName = GetAnimatedParameterBindingName(asset, parameterName); + return EditorCurveBinding.FloatCurve(string.Empty, GetValidAnimationType(asset), animationName); + } + + public static string GetAnimatedParameterBindingName(UnityObject asset, string parameterName) + { + if (asset == null) + return parameterName; + + string bindingName; + if (!AnimatedParameterCache.TryGetBindingName(asset.GetType(), parameterName, out bindingName)) + { + bindingName = GetAnimatedParameterBindingName_Internal(asset, parameterName); + AnimatedParameterCache.SetBindingName(asset.GetType(), parameterName, bindingName); + } + + return bindingName; + } + + static string GetAnimatedParameterBindingName_Internal(UnityObject asset, string parameterName) + { + if (asset is IPlayableBehaviour) + return parameterName; + + // strip the IScript playable field name + var fields = GetScriptPlayableFields(asset as IPlayableAsset); + foreach (var f in fields) + { + if (parameterName.StartsWith(f.Name, StringComparison.Ordinal)) + { + if (parameterName.Length > f.Name.Length && parameterName[f.Name.Length] == '.') + return parameterName.Substring(f.Name.Length + 1); + } + } + + return parameterName; + } + + public static bool BindingMatchesParameterName(EditorCurveBinding binding, string parameterName) + { + if (binding.propertyName == parameterName) + return true; + + var indexOfDot = binding.propertyName.IndexOf('.'); + return indexOfDot > 0 && parameterName.Length == indexOfDot && + binding.propertyName.StartsWith(parameterName, StringComparison.Ordinal); + } + + // the animated type must be a non-abstract instantiable object. + public static Type GetValidAnimationType(UnityObject asset) + { + return asset != null ? asset.GetType() : k_DefaultAnimationType; + } + + public static FieldInfo GetFieldInfoForProperty(SerializedProperty property) + { + FieldInfo fieldInfo; + + if (!AnimatedParameterCache.TryGetFieldInfoForProperty(property, out fieldInfo)) + { + Type _; + fieldInfo = ScriptAttributeUtility.GetFieldInfoFromProperty(property, out _); + AnimatedParameterCache.SetFieldInfoForProperty(property, fieldInfo); + } + + return fieldInfo; + } + + public static T GetAttributeForProperty<T>(SerializedProperty property) where T : Attribute + { + var fieldInfo = GetFieldInfoForProperty(property); + return fieldInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault() as T; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterUtility.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterUtility.cs.meta new file mode 100644 index 0000000..695849f --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/AnimatedParameterUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 84d86c98104d94063ad70bc591530f65 +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/Utilities/BindingUtility.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BindingUtility.cs new file mode 100644 index 0000000..5565817 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BindingUtility.cs @@ -0,0 +1,58 @@ +using System; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + static class BindingUtility + { + public static Type GetRequiredBindingType(PlayableBinding binding) + { + return binding.outputTargetType; + } + + public static void Bind(PlayableDirector director, TrackAsset bindTo, Object objectToBind) + { + if (director == null || bindTo == null || TimelineWindow.instance == null) + return; + + TimelineWindow.instance.state.previewMode = false; // returns all objects to previous state + TimelineUndo.PushUndo(director, "PlayableDirector Binding"); + director.SetGenericBinding(bindTo, objectToBind); + TimelineWindow.instance.state.rebuildGraph = true; + } + + public static BindingAction GetBindingAction(Type requiredBindingType, Object objectToBind) + { + if (requiredBindingType == null || objectToBind == null) + return BindingAction.DoNotBind; + + // prevent drag and drop of prefab assets + if (PrefabUtility.IsPartOfPrefabAsset(objectToBind)) + return BindingAction.DoNotBind; + + if (requiredBindingType.IsInstanceOfType(objectToBind)) + return BindingAction.BindDirectly; + + var draggedGameObject = objectToBind as GameObject; + + if (!typeof(Component).IsAssignableFrom(requiredBindingType) || draggedGameObject == null) + return BindingAction.DoNotBind; + + if (draggedGameObject.GetComponent(requiredBindingType) == null) + return BindingAction.BindToMissingComponent; + + return BindingAction.BindToExistingComponent; + } + } + + enum BindingAction + { + DoNotBind, + BindDirectly, + BindToExistingComponent, + BindToMissingComponent + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BindingUtility.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BindingUtility.cs.meta new file mode 100644 index 0000000..c528748 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BindingUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef5fa6e2005defb4ab5142723827b58e +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/Utilities/BreadcrumbDrawer.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BreadcrumbDrawer.cs new file mode 100644 index 0000000..a3276bf --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BreadcrumbDrawer.cs @@ -0,0 +1,235 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + enum TitleMode + { + None, + DisabledComponent, + Prefab, + PrefabOutOfContext, + Asset, + GameObject + } + + struct BreadCrumbTitle + { + public string name; + public TitleMode mode; + } + + class BreadcrumbDrawer + { + static readonly GUIContent s_TextContent = new GUIContent(); + static readonly string k_DisabledComponentText = L10n.Tr("The PlayableDirector is disabled"); + static readonly string k_PrefabOutOfContext = L10n.Tr("Prefab Isolation not enabled. Click to Enable."); + + static readonly GUIStyle k_BreadCrumbLeft; + static readonly GUIStyle k_BreadCrumbMid; + static readonly GUIStyle k_BreadCrumbLeftBg; + static readonly GUIStyle k_BreadCrumbMidBg; + static readonly GUIStyle k_BreadCrumbMidSelected; + static readonly GUIStyle k_BreadCrumbMidBgSelected; + + static readonly Texture k_TimelineIcon; + + const string k_Elipsis = "…"; + + static BreadcrumbDrawer() + { + k_BreadCrumbLeft = new GUIStyle("GUIEditor.BreadcrumbLeft"); + k_BreadCrumbMid = new GUIStyle("GUIEditor.BreadcrumbMid"); + k_BreadCrumbLeftBg = new GUIStyle("GUIEditor.BreadcrumbLeftBackground"); + k_BreadCrumbMidBg = new GUIStyle("GUIEditor.BreadcrumbMidBackground"); + + k_BreadCrumbMidSelected = new GUIStyle(k_BreadCrumbMid); + k_BreadCrumbMidSelected.normal = k_BreadCrumbMidSelected.onNormal; + + k_BreadCrumbMidBgSelected = new GUIStyle(k_BreadCrumbMidBg); + k_BreadCrumbMidBgSelected.normal = k_BreadCrumbMidBgSelected.onNormal; + k_TimelineIcon = EditorGUIUtility.IconContent("TimelineAsset Icon").image; + } + + static string FitTextInArea(float areaWidth, string text, GUIStyle style) + { + var borderWidth = style.border.left + style.border.right; + var textWidth = style.CalcSize(EditorGUIUtility.TextContent(text)).x; + + if (borderWidth + textWidth < areaWidth) + return text; + + // Need to truncate the text to fit in the areaWidth + var textAreaWidth = areaWidth - borderWidth; + var pixByChar = textWidth / text.Length; + var charNeeded = (int)Mathf.Floor(textAreaWidth / pixByChar); + charNeeded -= k_Elipsis.Length; + + if (charNeeded <= 0) + return k_Elipsis; + + if (charNeeded <= text.Length) + return k_Elipsis + " " + text.Substring(text.Length - charNeeded); + + return k_Elipsis; + } + + public static void Draw(float breadcrumbAreaWidth, List<BreadCrumbTitle> labels, Action<int> navigateToBreadcrumbIndex) + { + GUILayout.BeginHorizontal(GUILayout.Width(breadcrumbAreaWidth)); + { + var labelWidth = (int)(breadcrumbAreaWidth / labels.Count); + + for (var i = 0; i < labels.Count; i++) + { + var label = labels[i]; + + var style = i == 0 ? k_BreadCrumbLeft : k_BreadCrumbMid; + var backgroundStyle = i == 0 ? k_BreadCrumbLeftBg : k_BreadCrumbMidBg; + + if (i == labels.Count - 1) + { + if (i > 0) + { + // Only tint last breadcrumb if we are dug-in + DrawBreadcrumbAsSelectedSubSequence(labelWidth, label, k_BreadCrumbMidSelected, k_BreadCrumbMidBgSelected); + } + else + { + DrawActiveBreadcrumb(labelWidth, label, style, backgroundStyle); + } + } + else + { + var previousContentColor = GUI.contentColor; + + GUI.contentColor = new Color(previousContentColor.r, + previousContentColor.g, + previousContentColor.b, + previousContentColor.a * 0.6f); + var content = GetTextContent(labelWidth, label, style); + var rect = GetBreadcrumbLayoutRect(content, style); + + if (Event.current.type == EventType.Repaint) + { + backgroundStyle.Draw(rect, GUIContent.none, 0); + } + + if (GUI.Button(rect, content, style)) + { + navigateToBreadcrumbIndex.Invoke(i); + } + GUI.contentColor = previousContentColor; + } + } + } + GUILayout.EndHorizontal(); + } + + static GUIContent GetTextContent(int width, BreadCrumbTitle text, GUIStyle style) + { + s_TextContent.tooltip = string.Empty; + s_TextContent.image = null; + if (text.mode == TitleMode.DisabledComponent) + { + s_TextContent.tooltip = k_DisabledComponentText; + s_TextContent.image = EditorGUIUtility.GetHelpIcon(MessageType.Warning); + } + else if (text.mode == TitleMode.Prefab) + s_TextContent.image = PrefabUtility.GameObjectStyles.prefabIcon; + else if (text.mode == TitleMode.GameObject) + s_TextContent.image = PrefabUtility.GameObjectStyles.gameObjectIcon; + else if (text.mode == TitleMode.Asset) + s_TextContent.image = k_TimelineIcon; + else if (text.mode == TitleMode.PrefabOutOfContext) + { + s_TextContent.image = PrefabUtility.GameObjectStyles.prefabIcon; + if (!TimelineWindow.instance.locked) + s_TextContent.tooltip = k_PrefabOutOfContext; + } + + if (s_TextContent.image != null) + width = Math.Max(0, width - s_TextContent.image.width); + s_TextContent.text = FitTextInArea(width, text.name, style); + + return s_TextContent; + } + + static void DrawBreadcrumbAsSelectedSubSequence(int width, BreadCrumbTitle label, GUIStyle style, GUIStyle backgroundStyle) + { + var rect = DrawActiveBreadcrumb(width, label, style, backgroundStyle); + const float underlineThickness = 2.0f; + const float underlineVerticalOffset = 0.0f; + var underlineHorizontalOffset = backgroundStyle.border.right * 0.333f; + var underlineRect = Rect.MinMaxRect( + rect.xMin - underlineHorizontalOffset, + rect.yMax - underlineThickness - underlineVerticalOffset, + rect.xMax - underlineHorizontalOffset, + rect.yMax - underlineVerticalOffset); + + EditorGUI.DrawRect(underlineRect, DirectorStyles.Instance.customSkin.colorSubSequenceDurationLine); + } + + static Rect GetBreadcrumbLayoutRect(GUIContent content, GUIStyle style) + { + // the image makes the button far too big compared to non-image versions + var image = content.image; + content.image = null; + var size = style.CalcSizeWithConstraints(content, Vector2.zero); + content.image = image; + if (image != null) + size.x += size.y; // assumes square image, constrained by height + + return GUILayoutUtility.GetRect(content, style, GUILayout.MaxWidth(size.x)); + } + + static Rect DrawActiveBreadcrumb(int width, BreadCrumbTitle label, GUIStyle style, GUIStyle backgroundStyle) + { + var content = GetTextContent(width, label, style); + var rect = GetBreadcrumbLayoutRect(content, style); + + if (Event.current.type == EventType.Repaint) + { + backgroundStyle.Draw(rect, GUIContent.none, 0); + } + + if (GUI.Button(rect, content, style)) + { + UnityEngine.Object target = TimelineEditor.inspectedDirector; + if (target == null) + target = TimelineEditor.inspectedAsset; + if (target != null) + { + bool ping = true; + if (label.mode == TitleMode.PrefabOutOfContext) + { + var gameObject = PrefabUtility.GetRootGameObject(target); + if (gameObject != null) + { + target = gameObject; // ping the prefab root if it's locked. + if (!TimelineWindow.instance.locked) + { + var assetPath = AssetDatabase.GetAssetPath(gameObject); + if (!string.IsNullOrEmpty(assetPath)) + { + var stage = UnityEditor.Experimental.SceneManagement.PrefabStageUtility.OpenPrefab(assetPath); + if (stage != null) + ping = false; + } + } + } + } + + if (ping) + { + EditorGUIUtility.PingObject(target); + } + } + } + + return rect; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BreadcrumbDrawer.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BreadcrumbDrawer.cs.meta new file mode 100644 index 0000000..b17803a --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/BreadcrumbDrawer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 526f285e8d4fb8140b4cdfeb9102d8cb +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/Utilities/ClipModifier.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ClipModifier.cs new file mode 100644 index 0000000..8c54f4d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ClipModifier.cs @@ -0,0 +1,386 @@ +using System; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; +using UnityEngine.Playables; + +namespace UnityEditor.Timeline +{ + static class ClipModifier + { + public static bool Delete(TimelineAsset timeline, TimelineClip clip) + { + return timeline.DeleteClip(clip); + } + + public static bool Tile(TimelineClip[] clips) + { + if (clips.Length < 2) + return false; + + var clipsByTracks = clips.GroupBy(x => x.parentTrack) + .Select(track => new {track.Key, Items = track.OrderBy(c => c.start)}); + + foreach (var track in clipsByTracks) + { + TimelineUndo.PushUndo(track.Key, "Tile"); + } + + foreach (var track in clipsByTracks) + { + double newStart = track.Items.First().start; + foreach (var c in track.Items) + { + c.start = newStart; + newStart += c.duration; + } + } + + return true; + } + + public static bool TrimStart(TimelineClip[] clips, double trimTime) + { + var result = false; + + foreach (var clip in clips) + result |= TrimStart(clip, trimTime); + + return result; + } + + public static bool TrimStart(TimelineClip clip, double trimTime) + { + if (clip.asset == null) + return false; + + if (clip.start > trimTime) + return false; + + if (clip.end < trimTime) + return false; + + TimelineUndo.PushUndo(clip.parentTrack, "Trim Clip Start"); + + // Note: We are NOT using edit modes in this case because we want the same result + // regardless of the selected EditMode: split at cursor and delete left part + SetStart(clip, trimTime); + + return true; + } + + public static bool TrimEnd(TimelineClip[] clips, double trimTime) + { + var result = false; + + foreach (var clip in clips) + result |= TrimEnd(clip, trimTime); + + return result; + } + + public static bool TrimEnd(TimelineClip clip, double trimTime) + { + if (clip.asset == null) + return false; + + if (clip.start > trimTime) + return false; + + if (clip.end < trimTime) + return false; + + TimelineUndo.PushUndo(clip.parentTrack, "Trim Clip End"); + TrimClipWithEditMode(clip, TrimEdge.End, trimTime); + + return true; + } + + public static bool MatchDuration(TimelineClip[] clips) + { + double referenceDuration = clips[0].duration; + foreach (var clip in clips) + { + TimelineUndo.PushUndo(clip.parentTrack, "Match Clip Duration"); + + var newEnd = clip.start + referenceDuration; + TrimClipWithEditMode(clip, TrimEdge.End, newEnd); + } + + return true; + } + + public static bool Split(TimelineClip[] clips, double splitTime, PlayableDirector director) + { + var result = false; + + foreach (var clip in clips) + { + if (clip.start >= splitTime) + continue; + + if (clip.end <= splitTime) + continue; + + TimelineUndo.PushUndo(clip.parentTrack, "Split Clip"); + + TimelineClip newClip = TimelineHelpers.Clone(clip, director, director, clip.start); + + SetStart(clip, splitTime); + SetEnd(newClip, splitTime, false); + + // Sort produced by cloning clips on top of each other is unpredictable (it varies between mono runtimes) + clip.parentTrack.SortClips(); + + result = true; + } + + return result; + } + + public static void SetStart(TimelineClip clip, double time) + { + var supportsClipIn = clip.SupportsClipIn(); + var supportsPadding = TimelineUtility.IsRecordableAnimationClip(clip); + + // treat empty recordable clips as not supporting clip in (there are no keys to modify) + if (supportsPadding && (clip.animationClip == null || clip.animationClip.empty)) + { + supportsClipIn = false; + } + + if (supportsClipIn && !supportsPadding) + { + var minStart = clip.FromLocalTimeUnbound(0.0); + if (time < minStart) + time = minStart; + } + + var maxStart = clip.end - TimelineClip.kMinDuration; + if (time > maxStart) + time = maxStart; + + var timeOffset = time - clip.start; + var duration = clip.duration - timeOffset; + + if (supportsClipIn) + { + if (supportsPadding) + { + double clipInGlobal = clip.clipIn / clip.timeScale; + double keyShift = -timeOffset; + if (timeOffset < 0) // left drag, eliminate clipIn before shifting + { + double clipInDelta = Math.Max(-clipInGlobal, timeOffset); + keyShift = -Math.Min(0, timeOffset - clipInDelta); + clip.clipIn += clipInDelta * clip.timeScale; + } + else if (timeOffset > 0) // right drag, elimate padding in animation clip before adding clip in + { + var clipInfo = AnimationClipCurveCache.Instance.GetCurveInfo(clip.animationClip); + double keyDelta = clip.FromLocalTimeUnbound(clipInfo.keyTimes.Min()) - clip.start; + keyShift = -Math.Max(0, Math.Min(timeOffset, keyDelta)); + clip.clipIn += Math.Max(timeOffset + keyShift, 0) * clip.timeScale; + } + if (keyShift != 0) + { + AnimationTrackRecorder.ShiftAnimationClip(clip.animationClip, (float)(keyShift * clip.timeScale)); + } + } + else + { + clip.clipIn += timeOffset * clip.timeScale; + } + } + + clip.start = time; + clip.duration = duration; + } + + public static void SetEnd(TimelineClip clip, double time, bool affectTimeScale) + { + var duration = Math.Max(time - clip.start, TimelineClip.kMinDuration); + + if (affectTimeScale && clip.SupportsSpeedMultiplier()) + { + var f = clip.duration / duration; + clip.timeScale *= f; + } + + clip.duration = duration; + } + + public static bool ResetEditing(TimelineClip[] clips) + { + var result = false; + + foreach (var clip in clips) + result = result || ResetEditing(clip); + + return result; + } + + public static bool ResetEditing(TimelineClip clip) + { + if (clip.asset == null) + return false; + + TimelineUndo.PushUndo(clip.parentTrack, "Reset Clip Editing"); + + clip.clipIn = 0.0; + + if (clip.clipAssetDuration < double.MaxValue) + { + var duration = clip.clipAssetDuration / clip.timeScale; + TrimClipWithEditMode(clip, TrimEdge.End, clip.start + duration); + } + + return true; + } + + public static bool MatchContent(TimelineClip[] clips) + { + var result = false; + + foreach (var clip in clips) + result = result || MatchContent(clip); + + return result; + } + + public static bool MatchContent(TimelineClip clip) + { + if (clip.asset == null) + return false; + + TimelineUndo.PushUndo(clip.parentTrack, "Match Clip Content"); + + var newStartCandidate = clip.start - clip.clipIn / clip.timeScale; + var newStart = newStartCandidate < 0.0 ? 0.0 : newStartCandidate; + + TrimClipWithEditMode(clip, TrimEdge.Start, newStart); + + // In case resetting the start was blocked by edit mode or timeline start, we do the best we can + clip.clipIn = (clip.start - newStartCandidate) * clip.timeScale; + if (clip.clipAssetDuration > 0 && TimelineHelpers.HasUsableAssetDuration(clip)) + { + var duration = TimelineHelpers.GetLoopDuration(clip); + var offset = (clip.clipIn / clip.timeScale) % duration; + TrimClipWithEditMode(clip, TrimEdge.End, clip.start - offset + duration); + } + + return true; + } + + public static void TrimClipWithEditMode(TimelineClip clip, TrimEdge edge, double time) + { + var clipItem = ItemsUtils.ToItem(clip); + EditMode.BeginTrim(clipItem, edge); + if (edge == TrimEdge.Start) + EditMode.TrimStart(clipItem, time); + else + EditMode.TrimEnd(clipItem, time, false); + EditMode.FinishTrim(); + } + + public static bool CompleteLastLoop(TimelineClip[] clips) + { + foreach (var clip in clips) + { + CompleteLastLoop(clip); + } + + return true; + } + + public static void CompleteLastLoop(TimelineClip clip) + { + FixLoops(clip, true); + } + + public static bool TrimLastLoop(TimelineClip[] clips) + { + foreach (var clip in clips) + { + TrimLastLoop(clip); + } + + return true; + } + + public static void TrimLastLoop(TimelineClip clip) + { + FixLoops(clip, false); + } + + static void FixLoops(TimelineClip clip, bool completeLastLoop) + { + if (!TimelineHelpers.HasUsableAssetDuration(clip)) + return; + + var loopDuration = TimelineHelpers.GetLoopDuration(clip); + var firstLoopDuration = loopDuration - clip.clipIn * (1.0 / clip.timeScale); + + // Making sure we don't trim to zero + if (!completeLastLoop && firstLoopDuration > clip.duration) + return; + + var numLoops = (clip.duration - firstLoopDuration) / loopDuration; + var numCompletedLoops = Math.Floor(numLoops); + + if (!(numCompletedLoops < numLoops)) + return; + + if (completeLastLoop) + numCompletedLoops += 1; + + var newEnd = clip.start + firstLoopDuration + loopDuration * numCompletedLoops; + + TimelineUndo.PushUndo(clip.parentTrack, "Trim Clip Last Loop"); + + TrimClipWithEditMode(clip, TrimEdge.End, newEnd); + } + + public static bool DoubleSpeed(TimelineClip[] clips) + { + foreach (var clip in clips) + { + if (clip.SupportsSpeedMultiplier()) + { + TimelineUndo.PushUndo(clip.parentTrack, "Double Clip Speed"); + clip.timeScale = clip.timeScale * 2.0f; + } + } + + return true; + } + + public static bool HalfSpeed(TimelineClip[] clips) + { + foreach (var clip in clips) + { + if (clip.SupportsSpeedMultiplier()) + { + TimelineUndo.PushUndo(clip.parentTrack, "Half Clip Speed"); + clip.timeScale = clip.timeScale * 0.5f; + } + } + + return true; + } + + public static bool ResetSpeed(TimelineClip[] clips) + { + foreach (var clip in clips) + { + if (clip.timeScale != 1.0) + { + TimelineUndo.PushUndo(clip.parentTrack, "Reset Clip Speed"); + clip.timeScale = 1.0; + } + } + + return true; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ClipModifier.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ClipModifier.cs.meta new file mode 100644 index 0000000..3fa03b9 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ClipModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0eeee3cdfa56734abca5c1a4e7989ba +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/Utilities/Clipboard.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Clipboard.cs new file mode 100644 index 0000000..7ed3952 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Clipboard.cs @@ -0,0 +1,142 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + class Clipboard + { + class ExposedReferenceTable : IExposedPropertyTable + { + Dictionary<PropertyName, Object> m_ReferenceTable = new Dictionary<PropertyName, Object>(); + public void SetReferenceValue(PropertyName id, Object value) + { + m_ReferenceTable[id] = value; + } + + public Object GetReferenceValue(PropertyName id, out bool idValid) + { + Object reference; + idValid = m_ReferenceTable.TryGetValue(id, out reference); + return reference; + } + + public void ClearReferenceValue(PropertyName id) + { + m_ReferenceTable.Remove(id); + } + + public void Clear() + { + m_ReferenceTable.Clear(); + } + } + + public struct ClipboardTrackEntry + { + public TrackAsset item; + public TrackAsset parent; + } + + static readonly int kListInitialSize = 10; + + readonly List<ItemsPerTrack> m_ItemsData = new List<ItemsPerTrack>(kListInitialSize); + readonly List<ClipboardTrackEntry> m_trackData = new List<ClipboardTrackEntry>(kListInitialSize); + TimelineAsset rootTimeline; + + public readonly IExposedPropertyTable exposedPropertyTable = new ExposedReferenceTable(); + + public Clipboard() + { + rootTimeline = CreateTimeline(); + + EditorApplication.playModeStateChanged += OnPlayModeChanged; + } + + public void CopyItems(IEnumerable<ITimelineItem> items) + { + using (new TimelineUndo.DisableUndoGuard(true)) + { + var itemsByParent = items.ToLookup(i => i.parentTrack); + foreach (var itemsGroup in itemsByParent) + { + var parent = itemsGroup.Key; + var itemsList = new List<ITimelineItem>(); + foreach (var item in itemsGroup) + { + if (item is ClipItem) + itemsList.Add(CopyItem((ClipItem)item)); + else if (item is MarkerItem) + itemsList.Add(CopyItem((MarkerItem)item)); + } + m_ItemsData.Add(new ItemsPerTrack(parent, itemsList)); + } + } + } + + ClipItem CopyItem(ClipItem clipItem) + { + var newClip = TimelineHelpers.Clone(clipItem.clip, TimelineWindow.instance.state.editSequence.director, exposedPropertyTable, rootTimeline); + return new ClipItem(newClip); + } + + static MarkerItem CopyItem(MarkerItem markerItem) + { + var markerObject = markerItem.marker as Object; + if (markerObject != null) + { + var newMarker = Object.Instantiate(markerObject); + newMarker.name = markerObject.name; + return new MarkerItem((IMarker)newMarker); + } + + return null; + } + + public void CopyTracks(IEnumerable<TrackAsset> tracks) + { + using (new TimelineUndo.DisableUndoGuard(true)) + { + foreach (var track in TrackExtensions.FilterTracks(tracks)) + { + var newTrack = track.Duplicate(TimelineEditor.inspectedDirector, TimelineEditor.clipboard.exposedPropertyTable, rootTimeline); + m_trackData.Add(new ClipboardTrackEntry {item = newTrack, parent = track.parent as TrackAsset}); + } + } + } + + public IEnumerable<ClipboardTrackEntry> GetTracks() + { + return m_trackData; + } + + public IEnumerable<ItemsPerTrack> GetCopiedItems() + { + return m_ItemsData; + } + + public void Clear() + { + m_ItemsData.Clear(); + m_trackData.Clear(); + rootTimeline = CreateTimeline(); + ((ExposedReferenceTable)exposedPropertyTable).Clear(); + } + + private void OnPlayModeChanged(PlayModeStateChange state) + { + if (state == PlayModeStateChange.EnteredEditMode || state == PlayModeStateChange.EnteredPlayMode) + Clear(); + } + + static TimelineAsset CreateTimeline() + { + var timeline = ScriptableObject.CreateInstance<TimelineAsset>(); + timeline.hideFlags |= HideFlags.DontSave; + timeline.name = "Clipboard"; + + return timeline; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Clipboard.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Clipboard.cs.meta new file mode 100644 index 0000000..af5870a --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Clipboard.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b57629d89799e004182564256307b0cc +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/Utilities/ControlPlayableUtility.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ControlPlayableUtility.cs new file mode 100644 index 0000000..d7023e4 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ControlPlayableUtility.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using UnityEngine.Playables; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + static class ControlPlayableUtility + { + public static bool DetectCycle( + ControlPlayableAsset asset, PlayableDirector director, HashSet<PlayableDirector> set = null) + { + if (director == null || asset == null || !asset.updateDirector) + return false; + + if (set == null) + set = new HashSet<PlayableDirector>(); + + if (set.Contains(director)) + return true; + + var gameObject = asset.sourceGameObject.Resolve(director); + if (gameObject == null) + return false; + + set.Add(director); + + foreach (var subDirector in asset.GetComponent<PlayableDirector>(gameObject)) + { + foreach (var childAsset in GetPlayableAssets(subDirector)) + { + if (DetectCycle(childAsset, subDirector, set)) + return true; + } + } + + set.Remove(director); + + return false; + } + + public static IEnumerable<ControlPlayableAsset> GetPlayableAssets(PlayableDirector director) + { + var timeline = director != null ? (director.playableAsset as TimelineAsset) : null; + if (timeline != null) + { + foreach (var t in timeline.GetOutputTracks()) + { + var controlTrack = t as ControlTrack; + if (controlTrack != null) + { + foreach (var c in t.GetClips()) + { + var asset = c.asset as ControlPlayableAsset; + if (asset != null) + yield return asset; + } + } + } + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ControlPlayableUtility.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ControlPlayableUtility.cs.meta new file mode 100644 index 0000000..ab502a1 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ControlPlayableUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e801faa3b0dd2478dbe801a2441b679e +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/Utilities/CustomTrackDrawerAttribute.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/CustomTrackDrawerAttribute.cs new file mode 100644 index 0000000..021a635 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/CustomTrackDrawerAttribute.cs @@ -0,0 +1,47 @@ +using System; + +namespace UnityEditor.Timeline +{ + // Tells a custom [[TrackDrawer]] which [[TrackAsset]] it's a drawer for. + sealed class CustomTrackDrawerAttribute : Attribute + { + public Type assetType; + public CustomTrackDrawerAttribute(Type type) + { + assetType = type; + } + } + + /// <summary> + /// Attribute that specifies a class as an editor for an extended Timeline type. + /// </summary> + /// <remarks> + /// Use this attribute on a class that extends ClipEditor, TrackEditor, or MarkerEditor to specify either the PlayableAsset, Marker, or TrackAsset derived classes for associated customization. + /// </remarks> + /// <example> + /// [CustomTimelineEditor(typeof(LightControlClip))] + /// class LightControlClipEditor : ClipEditor + /// { + /// } + /// </example> + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] + public sealed class CustomTimelineEditorAttribute : Attribute + { + /// <summary> + /// The type that that this editor applies to. + /// </summary> + public Type classToEdit { get; private set; } + + /// <summary> + /// Constructor. + /// </summary> + /// <param name="type"> The type that that this editor applies to.</param> + /// <exception cref="ArgumentNullException">Thrown if type is null</exception> + public CustomTimelineEditorAttribute(Type type) + { + if (type == null) + throw new System.ArgumentNullException(nameof(type)); + classToEdit = type; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/CustomTrackDrawerAttribute.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/CustomTrackDrawerAttribute.cs.meta new file mode 100644 index 0000000..1738611 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/CustomTrackDrawerAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e1e957d39ca70834f9212a1289b6a0d5 +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/Utilities/DisplayNameHelper.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/DisplayNameHelper.cs new file mode 100644 index 0000000..f228c4c --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/DisplayNameHelper.cs @@ -0,0 +1,33 @@ +using System.Text; +using UnityEngine.Playables; + +namespace UnityEditor.Timeline +{ + static class DisplayNameHelper + { + static readonly string k_NoAssetDisplayName = L10n.Tr("<No Asset>"); + static readonly string k_ReadOnlyDisplayName = L10n.Tr("[Read Only]"); + static readonly StringBuilder k_StringBuilder = new StringBuilder(); + + public static string GetDisplayName(ISequenceState sequence) + { + string displayName = sequence.director != null ? GetDisplayName(sequence.director) : GetDisplayName(sequence.asset); + if (sequence.asset != null && sequence.isReadOnly) + displayName += " " + k_ReadOnlyDisplayName; + return displayName; + } + + public static string GetDisplayName(PlayableAsset asset) + { + return asset != null ? asset.name : k_NoAssetDisplayName; + } + + public static string GetDisplayName(PlayableDirector director) + { + k_StringBuilder.Length = 0; + k_StringBuilder.Append(GetDisplayName(director.playableAsset)); + k_StringBuilder.Append(" (").Append(director.name).Append(')'); + return k_StringBuilder.ToString(); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/DisplayNameHelper.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/DisplayNameHelper.cs.meta new file mode 100644 index 0000000..cb233c8 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/DisplayNameHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7fc2147e42d71644aad0eaf9a3526249 +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/Utilities/GUIColorOverride.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIColorOverride.cs new file mode 100644 index 0000000..47815cd --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIColorOverride.cs @@ -0,0 +1,21 @@ +using System; +using UnityEngine; + +namespace UnityEditor.Timeline +{ + struct GUIColorOverride : IDisposable + { + readonly Color m_OldColor; + + public GUIColorOverride(Color newColor) + { + m_OldColor = GUI.color; + GUI.color = newColor; + } + + public void Dispose() + { + GUI.color = m_OldColor; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIColorOverride.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIColorOverride.cs.meta new file mode 100644 index 0000000..1d338af --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIColorOverride.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44507a833d0ca8a42aaec1c3d752eb5f +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/Utilities/GUIGroupScope.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIGroupScope.cs new file mode 100644 index 0000000..e8f0413 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIGroupScope.cs @@ -0,0 +1,18 @@ +using System; +using UnityEngine; + +namespace UnityEditor +{ + struct GUIGroupScope : IDisposable + { + public GUIGroupScope(Rect position) + { + GUI.BeginGroup(position); + } + + public void Dispose() + { + GUI.EndGroup(); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIGroupScope.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIGroupScope.cs.meta new file mode 100644 index 0000000..d0a2d09 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIGroupScope.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0bee8aba5e8a40446b7098666c5314d9 +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/Utilities/GUIMixedValueScope.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIMixedValueScope.cs new file mode 100644 index 0000000..f3da9f3 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIMixedValueScope.cs @@ -0,0 +1,20 @@ +using System; +using UnityEngine; + +namespace UnityEditor +{ + struct GUIMixedValueScope : IDisposable + { + readonly bool m_PrevValue; + public GUIMixedValueScope(bool newValue) + { + m_PrevValue = EditorGUI.showMixedValue; + EditorGUI.showMixedValue = newValue; + } + + public void Dispose() + { + EditorGUI.showMixedValue = m_PrevValue; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIMixedValueScope.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIMixedValueScope.cs.meta new file mode 100644 index 0000000..94ff586 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIMixedValueScope.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d59cefc45e3c31d4a90563364e7258fa +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/Utilities/GUIViewportScope.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIViewportScope.cs new file mode 100644 index 0000000..7999ffd --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIViewportScope.cs @@ -0,0 +1,34 @@ +using System; +using UnityEngine; + +namespace UnityEditor +{ + // Special Clip Scope that only effects painting, and keeps the coordinate system identical + struct GUIViewportScope : IDisposable + { + bool m_open; + public GUIViewportScope(Rect position) + { + m_open = false; + if (Event.current.type == EventType.Repaint || Event.current.type == EventType.Layout) + { + GUI.BeginClip(position, -position.min, Vector2.zero, false); + m_open = true; + } + } + + public void Dispose() + { + CloseScope(); + } + + void CloseScope() + { + if (m_open) + { + GUI.EndClip(); + m_open = false; + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIViewportScope.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIViewportScope.cs.meta new file mode 100644 index 0000000..1c3a2f0 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/GUIViewportScope.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af84cf39b8fa0654badd9278cbd00d77 +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/Utilities/Graphics.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Graphics.cs new file mode 100644 index 0000000..cc9addf --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Graphics.cs @@ -0,0 +1,109 @@ +using UnityEngine; + +namespace UnityEditor.Timeline +{ + static class Graphics + { + public static void ShadowLabel(Rect rect, string text, GUIStyle style, Color textColor, Color shadowColor) + { + ShadowLabel(rect, GUIContent.Temp(text), style, textColor, shadowColor); + } + + public static void ShadowLabel(Rect rect, GUIContent content, GUIStyle style, Color textColor, Color shadowColor) + { + var shadowRect = rect; + shadowRect.xMin += 2.0f; + shadowRect.yMin += 2.0f; + style.normal.textColor = Color.black; + GUI.Label(shadowRect, content, style); + + style.normal.textColor = textColor; + GUI.Label(rect, content, style); + } + + public static void DrawLine(Vector3 p1, Vector3 p2, Color color) + { + var c = Handles.color; + Handles.color = color; + Handles.DrawLine(p1, p2); + Handles.color = c; + } + + public static void DrawPolygonAA(Color color, Vector3[] vertices) + { + var prevColor = Handles.color; + Handles.color = color; + Handles.DrawAAConvexPolygon(vertices); + Handles.color = prevColor; + } + + public static void DrawDottedLine(Vector3 p1, Vector3 p2, float segmentsLength, Color col) + { + HandleUtility.ApplyWireMaterial(); + + GL.Begin(GL.LINES); + GL.Color(col); + + var length = Vector3.Distance(p1, p2); // ignore z component + var count = Mathf.CeilToInt(length / segmentsLength); + for (var i = 0; i < count; i += 2) + { + GL.Vertex((Vector3.Lerp(p1, p2, i * segmentsLength / length))); + GL.Vertex((Vector3.Lerp(p1, p2, (i + 1) * segmentsLength / length))); + } + + GL.End(); + } + + public static void DrawLineAtTime(WindowState state, double time, Color color, bool dotted = false) + { + var t = state.TimeToPixel(time); + + var p0 = new Vector3(t, state.timeAreaRect.yMax); + var p1 = new Vector3(t, state.timeAreaRect.yMax + state.windowHeight - WindowConstants.sliderWidth); + + if (dotted) + DrawDottedLine(p0, p1, 4.0f, color); + else + DrawLine(p0, p1, color); + } + + public static void DrawTextureRepeated(Rect area, Texture texture) + { + if (texture == null || Event.current.type != EventType.Repaint) + return; + + GUI.BeginClip(area); + int w = Mathf.CeilToInt(area.width / texture.width); + int h = Mathf.CeilToInt(area.height / texture.height); + for (int x = 0; x < w; x++) + { + for (int y = 0; y < h; y++) + { + GUI.DrawTexture(new Rect(x * texture.width, y * texture.height, texture.width, texture.height), texture); + } + } + + GUI.EndClip(); + } + + public static void DrawShadow(Rect clientRect) + { + var rect = clientRect; + rect.height = WindowConstants.shadowUnderTimelineHeight; + GUI.Box(rect, GUIContent.none, DirectorStyles.Instance.bottomShadow); + } + + public static void DrawBackgroundRect(WindowState state, Rect rect, bool subSequenceMode = false) + { + Color c = subSequenceMode ? DirectorStyles.Instance.customSkin.colorSubSequenceBackground : DirectorStyles.Instance.customSkin.colorSequenceBackground; + EditorGUI.DrawRect(rect, c); + if (state.IsEditingAPrefabAsset()) + { + c = SceneView.kSceneViewPrefabBackground.Color; + c.a = 0.5f; + EditorGUI.DrawRect(rect, c); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Graphics.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Graphics.cs.meta new file mode 100644 index 0000000..72bcc8d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Graphics.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4545bb65ccebf8040ac212d5792979b5 +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/Utilities/KeyTraverser.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/KeyTraverser.cs new file mode 100644 index 0000000..2f64868 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/KeyTraverser.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline.Utilities +{ + class KeyTraverser + { + float[] m_KeyCache; + int m_DirtyStamp = -1; + int m_LastHash = -1; + readonly TimelineAsset m_Asset; + readonly float m_Epsilon; + int m_LastIndex = -1; + + public int lastIndex + { + get { return m_LastIndex; } + } + + public static IEnumerable<float> GetClipKeyTimes(TimelineClip clip) + { + if (clip == null || clip.animationClip == null || clip.animationClip.empty) + return new float[0]; + + return AnimationClipCurveCache.Instance.GetCurveInfo(clip.animationClip).keyTimes. + Select(k => (float)clip.FromLocalTimeUnbound(k)). // convert to sequence time + Where(k => k >= clip.start && k <= clip.end); // remove non visible keys + } + + public static IEnumerable<float> GetTrackKeyTimes(AnimationTrack track) + { + if (track != null) + { + if (track.inClipMode) + return track.clips.Where(c => c.recordable). + SelectMany(x => GetClipKeyTimes(x)); + if (track.infiniteClip != null && !track.infiniteClip.empty) + return AnimationClipCurveCache.Instance.GetCurveInfo(track.infiniteClip).keyTimes; + } + return new float[0]; + } + + static int CalcAnimClipHash(TrackAsset asset) + { + int hash = 0; + if (asset != null) + { + AnimationTrack animTrack = asset as AnimationTrack; + if (animTrack != null) + { + for (var i = 0; i != animTrack.clips.Length; ++i) + { + hash ^= (animTrack.clips[i]).Hash(); + } + } + foreach (var subTrack in asset.GetChildTracks()) + { + if (subTrack != null) + hash ^= CalcAnimClipHash(subTrack); + } + } + return hash; + } + + internal static int CalcAnimClipHash(TimelineAsset asset) + { + int hash = 0; + foreach (var t in asset.GetRootTracks()) + { + if (t != null) + hash ^= CalcAnimClipHash(t); + } + return hash; + } + + void RebuildKeyCache() + { + m_KeyCache = m_Asset.flattenedTracks.Where(x => (x as AnimationTrack) != null) + .Cast<AnimationTrack>() + .SelectMany(t => GetTrackKeyTimes(t)). + OrderBy(x => x).ToArray(); + + if (m_KeyCache.Length > 0) + { + float[] unique = new float[m_KeyCache.Length]; + unique[0] = m_KeyCache[0]; + int index = 0; + for (int i = 1; i < m_KeyCache.Length; i++) + { + if (m_KeyCache[i] - unique[index] > m_Epsilon) + { + index++; + unique[index] = m_KeyCache[i]; + } + } + m_KeyCache = unique; + Array.Resize(ref m_KeyCache, index + 1); + } + } + + public KeyTraverser(TimelineAsset timeline, float epsilon) + { + m_Asset = timeline; + m_Epsilon = epsilon; + } + + void CheckCache(int dirtyStamp) + { + int hash = CalcAnimClipHash(m_Asset); + if (dirtyStamp != m_DirtyStamp || hash != m_LastHash) + { + RebuildKeyCache(); + m_DirtyStamp = dirtyStamp; + m_LastHash = hash; + } + } + + public float GetNextKey(float key, int dirtyStamp) + { + CheckCache(dirtyStamp); + if (m_KeyCache.Length > 0) + { + if (key < m_KeyCache.Last() - m_Epsilon) + { + if (key > m_KeyCache[0] - m_Epsilon) + { + float t = key + m_Epsilon; + // binary search + int max = m_KeyCache.Length - 1; + int min = 0; + while (max - min > 1) + { + int imid = (min + max) / 2; + if (t > m_KeyCache[imid]) + min = imid; + else + max = imid; + } + m_LastIndex = max; + return m_KeyCache[max]; + } + + m_LastIndex = 0; + return m_KeyCache[0]; + } + if (key < m_KeyCache.Last() + m_Epsilon) + { + m_LastIndex = m_KeyCache.Length - 1; + return Mathf.Max(key, m_KeyCache.Last()); + } + } + m_LastIndex = -1; + return key; + } + + public float GetPrevKey(float key, int dirtyStamp) + { + CheckCache(dirtyStamp); + if (m_KeyCache.Length > 0) + { + if (key > m_KeyCache[0] + m_Epsilon) + { + if (key < m_KeyCache.Last() + m_Epsilon) + { + float t = key - m_Epsilon; + + // binary search + int max = m_KeyCache.Length - 1; + int min = 0; + while (max - min > 1) + { + int imid = (min + max) / 2; + if (t < m_KeyCache[imid]) + max = imid; + else + min = imid; + } + m_LastIndex = min; + return m_KeyCache[min]; + } + m_LastIndex = m_KeyCache.Length - 1; + return m_KeyCache.Last(); + } + if (key >= m_KeyCache[0] - m_Epsilon) + { + m_LastIndex = 0; + return Mathf.Min(key, m_KeyCache[0]); + } + } + m_LastIndex = -1; + return key; + } + + public int GetKeyCount(int dirtyStamp) + { + CheckCache(dirtyStamp); + return m_KeyCache.Length; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/KeyTraverser.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/KeyTraverser.cs.meta new file mode 100644 index 0000000..5ce97aa --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/KeyTraverser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b57f909f22642d469a39e9628535312 +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/Utilities/MarkerModifier.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/MarkerModifier.cs new file mode 100644 index 0000000..9da5277 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/MarkerModifier.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + static class MarkerModifier + { + public static void DeleteMarker(IMarker marker) + { + var trackAsset = marker.parent; + if (trackAsset != null) + { + SelectionManager.Remove(marker); + trackAsset.DeleteMarker(marker); + } + } + + public static IEnumerable<IMarker> CloneMarkersToParent(IEnumerable<IMarker> markers, TrackAsset parent) + { + if (!markers.Any()) return Enumerable.Empty<IMarker>(); + var clonedMarkers = new List<IMarker>(); + foreach (var marker in markers) + clonedMarkers.Add(CloneMarkerToParent(marker, parent)); + return clonedMarkers; + } + + public static IMarker CloneMarkerToParent(IMarker marker, TrackAsset parent) + { + var markerObject = marker as ScriptableObject; + if (markerObject == null) return null; + + var newMarkerObject = Object.Instantiate(markerObject); + AddMarkerToParent(newMarkerObject, parent); + + newMarkerObject.name = markerObject.name; + try + { + CustomTimelineEditorCache.GetMarkerEditor((IMarker)newMarkerObject).OnCreate((IMarker)newMarkerObject, marker); + } + catch (Exception e) + { + Debug.LogException(e); + } + + + return (IMarker)newMarkerObject; + } + + static void AddMarkerToParent(ScriptableObject marker, TrackAsset parent) + { + TimelineCreateUtilities.SaveAssetIntoObject(marker, parent); + TimelineUndo.RegisterCreatedObjectUndo(marker, "Duplicate Marker"); + TimelineUndo.PushUndo(parent, "Duplicate Marker"); + + if (parent != null) + { + parent.AddMarker(marker); + ((IMarker)marker).Initialize(parent); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/MarkerModifier.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/MarkerModifier.cs.meta new file mode 100644 index 0000000..b16c6f5 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/MarkerModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7cfaad4e53832d94c9421d2dd1ad82f7 +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/Utilities/ObjectExtension.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectExtension.cs new file mode 100644 index 0000000..863500d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectExtension.cs @@ -0,0 +1,28 @@ +using UnityEngine; +using UnityEditor; + +namespace UnityEditor.Timeline +{ + static class ObjectExtension + { + public static bool IsSceneObject(this Object obj) + { + if (obj == null) + return false; + + bool isSceneType = obj is GameObject || obj is Component; + if (!isSceneType) + return false; + + return !PrefabUtility.IsPartOfPrefabAsset(obj); + } + + public static bool IsPrefab(this Object obj) + { + if (obj == null) + return false; + + return PrefabUtility.IsPartOfPrefabAsset(obj); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectExtension.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectExtension.cs.meta new file mode 100644 index 0000000..b1ff382 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectExtension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4722a1362908a1843ab03a055c5c3fa0 +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/Utilities/ObjectReferenceField.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectReferenceField.cs new file mode 100644 index 0000000..3ace197 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectReferenceField.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using UnityEngine.Timeline; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine.Playables; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + // Describes the object references on a ScriptableObject, ignoring script fields + struct ObjectReferenceField + { + public string propertyPath; + public bool isSceneReference; + public System.Type type; + + private readonly static ObjectReferenceField[] None = new ObjectReferenceField[0]; + private readonly static Dictionary<System.Type, ObjectReferenceField[]> s_Cache = new Dictionary<System.Type, ObjectReferenceField[]>(); + + public static ObjectReferenceField[] FindObjectReferences(System.Type type) + { + if (type == null) + return None; + + if (type.IsAbstract || type.IsInterface) + return None; + + if (!typeof(ScriptableObject).IsAssignableFrom(type)) + return None; + + ObjectReferenceField[] result = null; + if (s_Cache.TryGetValue(type, out result)) + return result; + + result = SearchForFields(type); + s_Cache[type] = result; + return result; + } + + public static ObjectReferenceField[] FindObjectReferences<T>() where T : ScriptableObject, new() + { + return FindObjectReferences(typeof(T)); + } + + private static ObjectReferenceField[] SearchForFields(System.Type t) + { + Object instance = ScriptableObject.CreateInstance(t); + var list = new List<ObjectReferenceField>(); + + var serializableObject = new SerializedObject(instance); + var prop = serializableObject.GetIterator(); + bool enterChildren = true; + while (prop.NextVisible(enterChildren)) + { + enterChildren = true; + var ppath = prop.propertyPath; + if (ppath == "m_Script") + { + enterChildren = false; + } + else if (prop.propertyType == SerializedPropertyType.ObjectReference || prop.propertyType == SerializedPropertyType.ExposedReference) + { + enterChildren = false; + var exposedType = GetTypeFromPath(t, prop.propertyPath); + if (exposedType != null && typeof(Object).IsAssignableFrom(exposedType)) + { + bool isSceneRef = prop.propertyType == SerializedPropertyType.ExposedReference; + list.Add( + new ObjectReferenceField() {propertyPath = prop.propertyPath, isSceneReference = isSceneRef, type = exposedType} + ); + } + } + } + + Object.DestroyImmediate(instance); + if (list.Count == 0) + return None; + return list.ToArray(); + } + + private static System.Type GetTypeFromPath(System.Type baseType, string path) + { + if (string.IsNullOrEmpty(path)) + return null; + + System.Type parentType = baseType; + FieldInfo field = null; + var pathTo = path.Split(new char[] {'.'}, StringSplitOptions.RemoveEmptyEntries); + var flags = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Instance; + foreach (string s in pathTo) + { + field = parentType.GetField(s, flags); + while (field == null) + { + if (parentType.BaseType == null) + return null; // Should not happen really. Means SerializedObject got the property, but the reflection missed it + parentType = parentType.BaseType; + field = parentType.GetField(s, flags); + } + + parentType = field.FieldType; + } + + // dig out exposed reference types + if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(ExposedReference<Object>).GetGenericTypeDefinition()) + { + return field.FieldType.GetGenericArguments()[0]; + } + + return field.FieldType; + } + + public Object Find(ScriptableObject sourceObject, Object context = null) + { + if (sourceObject == null) + return null; + + SerializedObject obj = new SerializedObject(sourceObject, context); + var prop = obj.FindProperty(propertyPath); + if (prop == null) + throw new InvalidOperationException("sourceObject is not of the proper type. It does not contain a path to " + propertyPath); + + Object result = null; + if (isSceneReference) + { + if (prop.propertyType != SerializedPropertyType.ExposedReference) + throw new InvalidOperationException(propertyPath + " is marked as a Scene Reference, but is not an exposed reference type"); + if (context == null) + Debug.LogWarning("ObjectReferenceField.Find " + " is called on a scene reference without a context, will always be null"); + + result = prop.exposedReferenceValue; + } + else + { + if (prop.propertyType != SerializedPropertyType.ObjectReference) + throw new InvalidOperationException(propertyPath + "is marked as an asset reference, but is not an object reference type"); + result = prop.objectReferenceValue; + } + + return result; + } + + /// <summary> + /// Check if an Object satisfies this field, including components + /// </summary> + public bool IsAssignable(Object obj) + { + if (obj == null) + return false; + + // types match + bool potentialMatch = type.IsAssignableFrom(obj.GetType()); + + // field is component, and it exists on the gameObject + if (!potentialMatch && typeof(Component).IsAssignableFrom(type) && obj is GameObject) + potentialMatch = ((GameObject)obj).GetComponent(type) != null; + + return potentialMatch && isSceneReference == obj.IsSceneObject(); + } + + /// <summary> + /// Assigns a value to the field + /// </summary> + public bool Assign(ScriptableObject scriptableObject, Object value, IExposedPropertyTable exposedTable = null) + { + var serializedObject = new SerializedObject(scriptableObject, exposedTable as Object); + var property = serializedObject.FindProperty(propertyPath); + if (property == null) + return false; + + // if the value is a game object, but the field is a component + if (value is GameObject && typeof(Component).IsAssignableFrom(type)) + value = ((GameObject)value).GetComponent(type); + + if (isSceneReference) + { + property.exposedReferenceValue = value; + + // the object gets dirtied, but not the scene which is where the reference is stored + var component = exposedTable as Component; + if (component != null && !EditorApplication.isPlaying) + EditorSceneManager.MarkSceneDirty(component.gameObject.scene); + } + else + property.objectReferenceValue = value; + + serializedObject.ApplyModifiedProperties(); + return true; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectReferenceField.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectReferenceField.cs.meta new file mode 100644 index 0000000..c0655c7 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/ObjectReferenceField.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29bf1d4ec1012bc45967ce95b729b8b3 +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/Utilities/PropertyCollector.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/PropertyCollector.cs new file mode 100644 index 0000000..f19300d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/PropertyCollector.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + class PropertyCollector : IPropertyCollector + { + readonly Stack<GameObject> m_ObjectStack = new Stack<GameObject>(); + + // Call immediately before use + public void Reset() + { + m_ObjectStack.Clear(); + } + + // call to reset caches. should be called when switching master timelines + public void Clear() + { + m_ObjectStack.Clear(); + AnimationPreviewUtilities.ClearCaches(); + } + + public void PushActiveGameObject(GameObject gameObject) + { + m_ObjectStack.Push(gameObject); + } + + public void PopActiveGameObject() + { + m_ObjectStack.Pop(); + } + + public void AddFromClip(AnimationClip clip) + { + var go = m_ObjectStack.Peek(); // allow it to throw if empty + if (go != null && clip != null) // null game object is allowed for calls to be ignored + AddFromClip(go, clip); + } + + public void AddFromClips(IEnumerable<AnimationClip> clips) + { + var go = m_ObjectStack.Peek(); + if (go != null) + AddFromClips(go, clips); + } + + public void AddFromName<T>(string name) where T : Component + { + var go = m_ObjectStack.Peek(); // allow it to throw if empty + if (go != null) // null game object is allowed for calls to be ignored + AddFromName<T>(go, name); + } + + public void AddFromName(string name) + { + var go = m_ObjectStack.Peek(); // allow it to throw if empty + if (go != null) // null game object is allowed for calls to be ignored + AddFromName(go, name); + } + + public void AddFromClip(GameObject obj, AnimationClip clip) + { + if (!Application.isPlaying) + AddPropertiesFromClip(obj, clip); + } + + public void AddFromClips(GameObject animatorRoot, IEnumerable<AnimationClip> clips) + { + if (Application.isPlaying) + return; + + AnimationPreviewUtilities.PreviewFromCurves(animatorRoot, AnimationPreviewUtilities.GetBindings(animatorRoot, clips)); + } + + public void AddFromName<T>(GameObject obj, string name) where T : Component + { + if (!Application.isPlaying) + AddPropertiesFromName(obj, typeof(T), name); + } + + public void AddFromName(GameObject obj, string name) + { + if (!Application.isPlaying) + AddPropertiesFromName(obj, name); + } + + public void AddFromName(Component component, string name) + { + if (!Application.isPlaying) + AddPropertyModification(component, name); + } + + public void AddFromComponent(GameObject obj, Component component) + { + if (Application.isPlaying) + return; + + if (obj == null || component == null) + return; + + var serializedObject = new SerializedObject(component); + SerializedProperty property = serializedObject.GetIterator(); + + while (property.NextVisible(true)) + { + if (property.hasVisibleChildren || !AnimatedParameterUtility.IsTypeAnimatable(property.propertyType)) + continue; + + AddPropertyModification(component, property.propertyPath); + } + } + + void AddPropertiesFromClip(GameObject go, AnimationClip clip) + { + if (go != null && clip != null) + { + AnimationMode.InitializePropertyModificationForGameObject(go, clip); + } + } + + static void AddPropertiesFromName(GameObject go, string property) + { + if (go == null) + return; + + AddPropertyModification(go, property); + } + + static void AddPropertiesFromName(GameObject go, Type compType, string property) + { + if (go == null) + return; + var comp = go.GetComponent(compType); + if (comp == null) + return; + + AddPropertyModification(comp, property); + } + + public void AddObjectProperties(Object obj, AnimationClip clip) + { + if (obj == null || clip == null) + return; + + IPlayableAsset asset = obj as IPlayableAsset; + IPlayableBehaviour playable = obj as IPlayableBehaviour; + + // special case for assets that contain animated script playables. + // The paths in the clip start from the field with the templated playable + if (asset != null) + { + if (playable == null) + { + AddSerializedPlayableModifications(asset, clip); + } + else + { + // in this case the asset is the playable. The clip applies directly + AnimationMode.InitializePropertyModificationForObject(obj, clip); + } + } + } + + void AddSerializedPlayableModifications(IPlayableAsset asset, AnimationClip clip) + { + var obj = asset as Object; + if (obj == null) + return; + + var driver = WindowState.previewDriver; + if (driver == null || !AnimationMode.InAnimationMode(driver)) + return; + + var serializedObj = new SerializedObject(obj); + var bindings = AnimationClipCurveCache.Instance.GetCurveInfo(clip).bindings; + var fields = AnimatedParameterUtility.GetScriptPlayableFields(asset); + + // go through each binding and offset using the field name + // so the modification system can find the particle object using the asset as a root + foreach (var b in bindings) + { + foreach (var f in fields) + { + var propertyPath = f.Name + "." + b.propertyName; + if (serializedObj.FindProperty(propertyPath) != null) + { + DrivenPropertyManager.RegisterProperty(driver, obj, propertyPath); + break; + } + } + } + } + + private static void AddPropertyModification(GameObject obj, string propertyName) + { + var driver = WindowState.previewDriver; + if (driver == null || !AnimationMode.InAnimationMode(driver)) + return; + + DrivenPropertyManager.RegisterProperty(driver, obj, propertyName); + } + + private static void AddPropertyModification(Component comp, string name) + { + if (comp == null) + return; + + var driver = WindowState.previewDriver; + if (driver == null || !AnimationMode.InAnimationMode(driver)) + return; + + // Register Property will display an error if a property doesn't exist (wanted behaviour) + // However, it also displays an error on Monobehaviour m_Script property, since it can't be driven. (not wanted behaviour) + // case 967026 + if (name == "m_Script" && (comp as MonoBehaviour) != null) + return; + + DrivenPropertyManager.RegisterProperty(driver, comp, name); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/PropertyCollector.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/PropertyCollector.cs.meta new file mode 100644 index 0000000..3e8f486 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/PropertyCollector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f3a562675833b4448299e4f627b0cec +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/Utilities/Range.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Range.cs new file mode 100644 index 0000000..745e742 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Range.cs @@ -0,0 +1,49 @@ +using System; +using UnityEngine; + +namespace UnityEditor.Timeline +{ + struct Range + { + public double start; + public double end; + public double length { get { return end - start; } } + + public static Range Union(Range lhs, Range rhs) + { + return new Range + { + start = Math.Min(lhs.start, rhs.start), + end = Math.Max(lhs.end, rhs.end) + }; + } + + public static Range Intersection(Range lhs, Range rhs) + { + var s = Math.Max(lhs.start, rhs.start); + var e = Math.Min(lhs.end, rhs.end); + + if (s > e) + { + // No intersection returns a 0-length range from 0 to 0 + return new Range(); + } + + return new Range + { + start = s, + end = e + }; + } + + public override string ToString() + { + return ToString("F3"); + } + + public string ToString(string format) + { + return UnityString.Format("({0}, {1})", start.ToString(format), end.ToString(format)); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Range.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Range.cs.meta new file mode 100644 index 0000000..22005c4 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/Range.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d31dfeaa131921f4eae00783cc48146f +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/Utilities/SequenceSelectorNameFormater.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SequenceSelectorNameFormater.cs new file mode 100644 index 0000000..654eecb --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SequenceSelectorNameFormater.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace UnityEditor.Timeline +{ + // Class used for uniquely format names used in the GenericMenu. We can't add duplicate MenuItem in GenericMenu + // so that's why we need to keep information about the text we want to uniquely format. + class SequenceMenuNameFormater + { + Dictionary<int, int> m_UniqueItem = new Dictionary<int, int>(); + + public string Format(string text) + { + var key = text.GetHashCode(); + var index = 0; + + if (m_UniqueItem.ContainsKey(key)) + { + index = m_UniqueItem[key]; + index++; + m_UniqueItem[key] = index; + } + else + { + m_UniqueItem.Add(key, index); + return text; + } + + return $"{text}{index}"; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SequenceSelectorNameFormater.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SequenceSelectorNameFormater.cs.meta new file mode 100644 index 0000000..9fe16bd --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SequenceSelectorNameFormater.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1861286ba69badd439188a65bebf3cda +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/Utilities/SpacePartitioner.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SpacePartitioner.cs new file mode 100644 index 0000000..1539a1d --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SpacePartitioner.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + interface IBounds + { + Rect boundingRect { get; } + } + + class SpacePartitioner + { + internal class CachedList<T> + { + public static readonly List<T> Instance = new List<T>(1000); + } + + struct Entry : IInterval + { + public object item { get; set; } + public long intervalStart { get; set; } + public long intervalEnd { get; set; } + public Rect bounds { get; set; } + + private const float kPrecision = 100.0f; + private const float kMaxFloat = (float)long.MaxValue; + private const float kMinFloat = (float)long.MinValue; + + static public Int64 FromFloat(float f) + { + if (Single.IsPositiveInfinity(f)) + return long.MaxValue; + if (Single.IsNegativeInfinity(f)) + return long.MinValue; + + f = Mathf.Clamp(f, kMinFloat, kMaxFloat); // prevent overflow of floats + f = Mathf.Clamp(f * kPrecision, kMinFloat, kMaxFloat); // clamp to 'long' range + return (long)(f); + } + } + + const EventType k_GuiEventLock = EventType.Repaint; + + IntervalTree<Entry> m_Tree = new IntervalTree<Entry>(); + List<Entry> m_CacheList = new List<Entry>(); + + public void Clear() + { + m_Tree.Clear(); + } + + public void AddBounds(IBounds bounds) + { + AddBounds(bounds, bounds.boundingRect); + } + + public void AddBounds(object item, Rect rect) + { + if (item == null) + throw new ArgumentNullException("item"); + + m_Tree.Add(new Entry() + { + intervalStart = Entry.FromFloat(rect.yMin), + intervalEnd = Entry.FromFloat(rect.yMax), + bounds = rect, + item = item + } + ); + } + + /// <summary> + /// Get items of type T at a given position + /// </summary> + /// <param name="position"></param> + /// <param name="inClipSpace"></param> + /// <typeparam name="T"></typeparam> + /// <remarks> + /// Uses a (1,1) sized box + /// Use .ToList() or .ToArray() when not enumerating the result immediately + /// </remarks> + /// <returns></returns> + public IEnumerable<T> GetItemsAtPosition<T>(Vector2 position) + { + return GetItemsInArea<T>(new Rect(position.x, position.y, 1, 1)); + } + + /// <summary> + /// + /// </summary> + /// <param name="area"></param> + /// <param name="inClipSpace"></param> + /// <typeparam name="T"></typeparam> + /// <returns></returns> + public IEnumerable<T> GetItemsInArea<T>(Rect area) + { + m_CacheList.Clear(); + m_Tree.IntersectsWithRange(long.MinValue, long.MaxValue, m_CacheList); + + var list = CachedList<T>.Instance; + list.Clear(); + foreach (var i in m_CacheList) + { + if (i.item is T && i.bounds.Overlaps(area)) + list.Add((T)i.item); + } + return list; + } + + public void DebugDraw() + { + var kFillColor = new Color(1.0f, 1.0f, 1.0f, 0.1f); + var kOutlineColor = Color.yellow; + + m_CacheList.Clear(); + m_Tree.IntersectsWithRange(long.MinValue, long.MaxValue, m_CacheList); + HandleUtility.ApplyWireMaterial(); + + foreach (var item in m_CacheList) + { + Handles.DrawSolidRectangleWithOutline(item.bounds, kFillColor, kOutlineColor); + } + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SpacePartitioner.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SpacePartitioner.cs.meta new file mode 100644 index 0000000..2359cae --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/SpacePartitioner.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2fa2cf7de51b0d34d9dce3747b72e49d +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/Utilities/StyleManager.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleManager.cs new file mode 100644 index 0000000..794fc68 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleManager.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.Experimental; +using UnityEditor.StyleSheets; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + static class StyleManager + { + static readonly StyleState[] k_StyleStates = { StyleState.any }; + static readonly string k_ErrorCannotFindStyle = L10n.Tr("Cannot find style {0} for {1}"); + + static Dictionary<Type, GUIStyle> s_CustomStyles = new Dictionary<Type, GUIStyle>(); + static GUISkin s_CurrentSkin; + + public static GUIStyle UssStyleForType(Type type) + { + ClearCacheIfInvalid(); + + GUIStyle cachedStyle; + if (s_CustomStyles.TryGetValue(type, out cachedStyle)) + return cachedStyle; + + var style = DirectorStyles.GetGUIStyle(DirectorStyles.markerDefaultStyle); + + var customStyleForType = CustomStyleForType(type); + if (customStyleForType != null) + { + if (IsStyleValid(customStyleForType)) + style = DirectorStyles.GetGUIStyle(customStyleForType); + else + Debug.LogWarningFormat(k_ErrorCannotFindStyle, customStyleForType, type.Name); + } + + s_CustomStyles.Add(type, style); + return style; + } + + static string CustomStyleForType(Type type) + { + var attr = (CustomStyleAttribute)type.GetCustomAttributes(typeof(CustomStyleAttribute), true).FirstOrDefault(); + return attr != null ? attr.ussStyle : null; + } + + static bool IsStyleValid(string ussStyle) + { + return GUISkin.current.FindStyle(ussStyle) != null || EditorResources.styleCatalog.GetStyle(ussStyle, k_StyleStates).IsValid(); + } + + static void ClearCacheIfInvalid() + { + if (s_CurrentSkin != GUISkin.current) + s_CustomStyles.Clear(); + s_CurrentSkin = GUISkin.current; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleManager.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleManager.cs.meta new file mode 100644 index 0000000..bba0d35 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5f31f28cc64c91042976555c016ffd5f +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/Utilities/StyleNormalColorOverride.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleNormalColorOverride.cs new file mode 100644 index 0000000..24016ca --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleNormalColorOverride.cs @@ -0,0 +1,23 @@ +using System; +using UnityEngine; + +namespace UnityEditor.Timeline +{ + struct StyleNormalColorOverride : IDisposable + { + readonly GUIStyle m_Style; + readonly Color m_OldColor; + + public StyleNormalColorOverride(GUIStyle style, Color newColor) + { + m_Style = style; + m_OldColor = style.normal.textColor; + style.normal.textColor = newColor; + } + + public void Dispose() + { + m_Style.normal.textColor = m_OldColor; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleNormalColorOverride.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleNormalColorOverride.cs.meta new file mode 100644 index 0000000..b969311 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/StyleNormalColorOverride.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2bd3ca1fde4b154448ef972b0f9d292e +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/Utilities/TimeReferenceUtility.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimeReferenceUtility.cs new file mode 100644 index 0000000..4e456f8 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimeReferenceUtility.cs @@ -0,0 +1,57 @@ +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + static class TimeReferenceUtility + { + static WindowState state { get { return TimelineWindow.instance.state; } } + + public static double SnapToFrame(double time) + { + if (state.timeReferenceMode == TimeReferenceMode.Global) + { + time = state.editSequence.ToGlobalTime(time); + time = TimeUtility.RoundToFrame(time, state.referenceSequence.frameRate); + return state.editSequence.ToLocalTime(time); + } + + return TimeUtility.RoundToFrame(time, state.referenceSequence.frameRate); + } + + public static string ToTimeString(double time, string format = "F2") + { + if (state.timeReferenceMode == TimeReferenceMode.Global) + time = state.editSequence.ToGlobalTime(time); + + return state.editSequence.viewModel.timeInFrames ? + TimeUtility.TimeAsFrames(time, state.referenceSequence.frameRate, format) : + TimeUtility.TimeAsTimeCode(time, state.referenceSequence.frameRate, format); + } + + public static double FromTimeString(string timeString) + { + double newTime; + + if (state.timeInFrames) + { + double newFrameDouble; + if (double.TryParse(timeString, out newFrameDouble)) + newTime = TimeUtility.FromFrames(newFrameDouble, state.referenceSequence.frameRate); + else + newTime = state.editSequence.time; + } + else + { + newTime = TimeUtility.ParseTimeCode(timeString, state.referenceSequence.frameRate, -1); + } + + if (newTime >= 0.0) + { + return state.timeReferenceMode == TimeReferenceMode.Global ? + state.editSequence.ToLocalTime(newTime) : newTime; + } + + return state.editSequence.time; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimeReferenceUtility.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimeReferenceUtility.cs.meta new file mode 100644 index 0000000..1da1a4a --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimeReferenceUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6bb32665bcc91b41a7177fd6af08ad6 +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/Utilities/TimelineKeyboardNavigation.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimelineKeyboardNavigation.cs new file mode 100644 index 0000000..3cd18d8 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimelineKeyboardNavigation.cs @@ -0,0 +1,387 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor.IMGUI.Controls; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + static class KeyboardNavigation + { + public static void FrameTrackHeader(TreeViewItem treeItem = null) + { + if (TrackHeadActive()) + treeItem = treeItem ?? SelectionManager.SelectedTrackGUI().Last(); + else + { + var item = GetVisibleSelectedItems().LastOrDefault(); + treeItem = TimelineWindow.instance.allTracks.FirstOrDefault( + x => item != null && x.track == item.parentTrack); + } + + if (treeItem != null) + TimelineWindow.instance.treeView.FrameItem(treeItem); + } + + public static bool TrackHeadActive() + { + return SelectionManager.SelectedTracks().Any(x => x.IsVisibleRecursive()) && !ClipAreaActive(); + } + + public static bool ClipAreaActive() + { + return GetVisibleSelectedItems().Any(); + } + + public static IEnumerable<ITimelineItem> GetVisibleSelectedItems() + { + return SelectionManager.SelectedItems().Where(x => x.parentTrack.IsVisibleRecursive()); + } + + public static IEnumerable<TimelineTrackBaseGUI> GetVisibleTracks() + { + return TimelineWindow.instance.allTracks.Where(x => x.track.IsVisibleRecursive()); + } + + static TrackAsset PreviousTrack(this TrackAsset track) + { + var uiOrderTracks = GetVisibleTracks().Select(t => t.track).ToList(); + var selIdx = uiOrderTracks.IndexOf(track); + return selIdx > 0 ? uiOrderTracks[selIdx - 1] : null; + } + + static TrackAsset NextTrack(this TrackAsset track) + { + var uiOrderTracks = GetVisibleTracks().Select(t => t.track).ToList(); + var selIdx = uiOrderTracks.IndexOf(track); + return selIdx < uiOrderTracks.Count - 1 && selIdx != -1 ? uiOrderTracks[selIdx + 1] : null; + } + + static ITimelineItem PreviousItem(this ITimelineItem item, bool clipOnly) + { + var items = item.parentTrack.GetItems().ToArray(); + if (clipOnly) + { + items = items.Where(x => x is ClipItem).ToArray(); + } + else + { + items = items.Where(x => x is MarkerItem).ToArray(); + } + + var idx = Array.IndexOf(items, item); + return idx > 0 ? items[idx - 1] : null; + } + + static ITimelineItem NextItem(this ITimelineItem item, bool clipOnly) + { + var items = item.parentTrack.GetItems().ToArray(); + if (clipOnly) + { + items = items.Where(x => x is ClipItem).ToArray(); + } + else + { + items = items.Where(x => x is MarkerItem).ToArray(); + } + + var idx = Array.IndexOf(items, item); + return idx < items.Length - 1 ? items[idx + 1] : null; + } + + static bool FilterItems(ref List<ITimelineItem> items) + { + var clipOnly = false; + if (items.Any(x => x is ClipItem)) + { + items = items.Where(x => x is ClipItem).ToList(); + clipOnly = true; + } + + return clipOnly; + } + + static ITimelineItem GetClosestItem(TrackAsset track, ITimelineItem refItem) + { + var start = refItem.start; + var end = refItem.end; + var items = track.GetItems().ToList(); + + if (refItem is ClipItem) + { + items = items.Where(x => x is ClipItem).ToList(); + } + else + { + items = items.Where(x => x is MarkerItem).ToList(); + } + + if (!items.Any()) + return null; + ITimelineItem ret = null; + var scoreToBeat = double.NegativeInfinity; + + foreach (var item in items) + { + // test for overlap + var low = Math.Max(item.start, start); + var high = Math.Min(item.end, end); + if (low <= high) + { + var score = high - low; + if (score >= scoreToBeat) + { + scoreToBeat = score; + ret = item; + } + } + } + + return ret; + } + + public static bool FocusFirstVisibleItem(WindowState state, + IEnumerable<TrackAsset> focusTracks = null) + { + var timeRange = state.timeAreaShownRange; + + var tracks = focusTracks ?? TimelineWindow.instance.treeView.visibleTracks.Where(x => x.IsVisibleRecursive() && x.GetItems().Any()); + var items = tracks.SelectMany(t => t.GetItems().OfType<ClipItem>().Where(x => x.end >= timeRange.x && x.end <= timeRange.y || + x.start >= timeRange.x && x.start <= timeRange.y)).ToList(); + var itemFullyInView = items.Where(x => x.end >= timeRange.x && x.end <= timeRange.y && + x.start >= timeRange.x && x.start <= timeRange.y); + var itemToSelect = itemFullyInView.FirstOrDefault() ?? items.FirstOrDefault(); + if (itemToSelect != null) + { + SelectionManager.SelectOnly(itemToSelect); + return true; + } + return false; + } + + public static bool CollapseGroup(WindowState state) + { + if (TrackHeadActive()) + { + var quit = false; + foreach (var track in SelectionManager.SelectedTracks()) + { + if (!track.GetChildTracks().Any()) + continue; + if (!quit && !track.GetCollapsed()) + quit = true; + track.SetCollapsed(true); + } + if (quit) + { + state.Refresh(); + return true; + } + + var selectedTrack = SelectionManager.SelectedTracks().LastOrDefault(); + var parent = selectedTrack != null ? selectedTrack.parent as TrackAsset : null; + if (parent) + { + SelectionManager.SelectOnly(parent); + FrameTrackHeader(GetVisibleTracks().First(x => x.track == parent)); + return true; + } + } + return false; + } + + public static bool SelectLeftItem(WindowState state, bool shift = false) + { + if (ClipAreaActive()) + { + var items = SelectionManager.SelectedItems().ToList(); + var clipOnly = FilterItems(ref items); + + var item = items.Last(); + var prev = item.PreviousItem(clipOnly); + if (prev != null) + { + if (shift) + { + if (SelectionManager.Contains(prev)) + SelectionManager.Remove(item); + SelectionManager.Add(prev); + } + else + SelectionManager.SelectOnly(prev); + TimelineHelpers.FrameItems(state, new[] {prev}); + } + else if (item != null && !shift && item.parentTrack != state.editSequence.asset.markerTrack) + SelectionManager.SelectOnly(item.parentTrack); + return true; + } + return false; + } + + public static bool SelectRightItem(WindowState state, bool shift = false) + { + if (ClipAreaActive()) + { + var items = SelectionManager.SelectedItems().ToList(); + var clipOnly = FilterItems(ref items); + + var item = items.Last(); + var next = item.NextItem(clipOnly); + if (next != null) + { + if (shift) + { + if (SelectionManager.Contains(next)) + SelectionManager.Remove(item); + SelectionManager.Add(next); + } + else + SelectionManager.SelectOnly(next); + TimelineHelpers.FrameItems(state, new[] {next}); + return true; + } + } + return false; + } + + public static bool UnCollapseGroup(WindowState state) + { + if (TrackHeadActive()) + { + var quit = false; + foreach (var track in SelectionManager.SelectedTracks()) + { + if (!track.GetChildTracks().Any()) continue; + + if (!quit && track.GetCollapsed()) + quit = true; + track.SetCollapsed(false); + } + + if (quit) + { + state.Refresh(); + return true; + } + + // Transition to Clip area + var visibleTracks = GetVisibleTracks().Select(x => x.track).ToList(); + var idx = visibleTracks.IndexOf(SelectionManager.SelectedTracks().Last()); + ITimelineItem item = null; + for (var i = idx; i < visibleTracks.Count; ++i) + { + var items = visibleTracks[i].GetItems().OfType<ClipItem>(); + if (!items.Any()) + continue; + item = items.First(); + break; + } + + if (item != null) + { + SelectionManager.SelectOnly(item); + TimelineHelpers.FrameItems(state, new[] {item}); + return true; + } + } + return false; + } + + public static bool SelectUpTrack(bool shift = false) + { + if (TrackHeadActive()) + { + var prevTrack = PreviousTrack(SelectionManager.SelectedTracks().Last()); + if (prevTrack != null) + { + if (shift) + { + if (SelectionManager.Contains(prevTrack)) + SelectionManager.Remove(SelectionManager.SelectedTracks().Last()); + SelectionManager.Add(prevTrack); + } + else + SelectionManager.SelectOnly(prevTrack); + FrameTrackHeader(GetVisibleTracks().First(x => x.track == prevTrack)); + } + return true; + } + return false; + } + + public static bool SelectUpItem(WindowState state) + { + if (ClipAreaActive()) + { + var refItem = SelectionManager.SelectedItems().Last(); + var prevTrack = refItem.parentTrack.PreviousTrack(); + while (prevTrack != null) + { + var selectionItem = GetClosestItem(prevTrack, refItem); + if (selectionItem == null) + { + prevTrack = prevTrack.PreviousTrack(); + continue; + } + + SelectionManager.SelectOnly(selectionItem); + TimelineHelpers.FrameItems(state, new[] {selectionItem}); + FrameTrackHeader(GetVisibleTracks().First(x => x.track == selectionItem.parentTrack)); + break; + } + return true; + } + + return false; + } + + public static bool SelectDownTrack(bool shift = false) + { + if (TrackHeadActive()) + { + var nextTrack = SelectionManager.SelectedTracks().Last().NextTrack(); + if (nextTrack != null) + { + if (shift) + { + if (SelectionManager.Contains(nextTrack)) + SelectionManager.Remove(SelectionManager.SelectedTracks().Last()); + SelectionManager.Add(nextTrack); + } + else + SelectionManager.SelectOnly(nextTrack); + + FrameTrackHeader(GetVisibleTracks().First(x => x.track == nextTrack)); + } + return true; + } + + return false; + } + + public static bool SelectDownItem(WindowState state) + { + if (ClipAreaActive()) + { + var refItem = SelectionManager.SelectedItems().Last(); + var nextTrack = refItem.parentTrack.NextTrack(); + while (nextTrack != null) + { + var selectionItem = GetClosestItem(nextTrack, refItem); + if (selectionItem == null) + { + nextTrack = nextTrack.NextTrack(); + continue; + } + + SelectionManager.SelectOnly(selectionItem); + TimelineHelpers.FrameItems(state, new[] {selectionItem}); + FrameTrackHeader(GetVisibleTracks().First(x => x.track == selectionItem.parentTrack)); + break; + } + return true; + } + return false; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimelineKeyboardNavigation.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimelineKeyboardNavigation.cs.meta new file mode 100644 index 0000000..7fb6aea --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TimelineKeyboardNavigation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9be6112c2b1c3ae44927680ba7b36e10 +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/Utilities/TrackModifier.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackModifier.cs new file mode 100644 index 0000000..5afeb52 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackModifier.cs @@ -0,0 +1,21 @@ +using UnityEngine; +using UnityEditor; +using UnityEngine.Timeline; +using UnityEngine.Playables; + +namespace UnityEditor.Timeline +{ + static class TrackModifier + { + public static bool DeleteTrack(TimelineAsset timeline, TrackAsset track) + { + if (TimelineEditor.inspectedDirector != null) + { + TimelineUndo.PushUndo(TimelineEditor.inspectedDirector, "Delete Track"); + TimelineEditor.inspectedDirector.ClearGenericBinding(track); + } + + return timeline.DeleteTrack(track); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackModifier.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackModifier.cs.meta new file mode 100644 index 0000000..f221e10 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackModifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 411b7c7ffc0960249b35a2a247b66ff7 +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/Utilities/TrackResourceCache.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackResourceCache.cs new file mode 100644 index 0000000..8eda6fe --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackResourceCache.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEngine.Timeline; + +namespace UnityEditor.Timeline +{ + static class TrackResourceCache + { + private static Dictionary<System.Type, GUIContent> s_TrackIconCache = new Dictionary<Type, GUIContent>(10); + private static Dictionary<System.Type, Color> s_TrackColorCache = new Dictionary<Type, Color>(10); + public static GUIContent s_DefaultIcon = EditorGUIUtility.IconContent("UnityEngine/ScriptableObject Icon"); + + public static GUIContent GetTrackIcon(TrackAsset track) + { + if (track == null) + return s_DefaultIcon; + + GUIContent content = null; + if (!s_TrackIconCache.TryGetValue(track.GetType(), out content)) + { + content = FindTrackIcon(track); + s_TrackIconCache[track.GetType()] = content; + } + return content; + } + + public static Color GetTrackColor(TrackAsset track) + { + if (track == null) + return Color.white; + + // Try to ensure DirectorStyles is initialized first + // Note: GUISkin.current must exist to be able do so + if (!DirectorStyles.IsInitialized && GUISkin.current != null) + DirectorStyles.ReloadStylesIfNeeded(); + + Color color; + if (!s_TrackColorCache.TryGetValue(track.GetType(), out color)) + { + var attr = track.GetType().GetCustomAttributes(typeof(TrackColorAttribute), true); + if (attr.Length > 0) + { + color = ((TrackColorAttribute)attr[0]).color; + } + else + { + // case 1141958 + // There was an error initializing DirectorStyles + if (!DirectorStyles.IsInitialized) + return Color.white; + + color = DirectorStyles.Instance.customSkin.colorDefaultTrackDrawer; + } + + s_TrackColorCache[track.GetType()] = color; + } + return color; + } + + public static void ClearTrackIconCache() + { + s_TrackIconCache.Clear(); + } + + public static void SetTrackIcon<T>(GUIContent content) where T : TrackAsset + { + s_TrackIconCache[typeof(T)] = content; + } + + public static void ClearTrackColorCache() + { + s_TrackColorCache.Clear(); + } + + public static void SetTrackColor<T>(Color c) where T : TrackAsset + { + s_TrackColorCache[typeof(T)] = c; + } + + private static GUIContent FindTrackIcon(TrackAsset track) + { + // backwards compatible -- try to load from Gizmos folder + Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Gizmos/" + track.GetType().Name + ".png"); + if (texture != null) + return new GUIContent(texture); + + // try to load based on the binding type + var binding = track.outputs.FirstOrDefault(); + if (binding.outputTargetType != null) + { + // Type calls don't properly handle monobehaviours, because an instance is required to + // get the monoscript icons + if (typeof(MonoBehaviour).IsAssignableFrom(binding.outputTargetType)) + { + texture = null; + var scripts = UnityEngine.Resources.FindObjectsOfTypeAll<MonoScript>(); + foreach (var script in scripts) + { + if (script.GetClass() == binding.outputTargetType) + { + texture = AssetPreview.GetMiniThumbnail(script); + break; + } + } + } + else + { + texture = EditorGUIUtility.FindTexture(binding.outputTargetType); + } + + if (texture != null) + return new GUIContent(texture); + } + + // default to the scriptable object icon + return s_DefaultIcon; + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackResourceCache.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackResourceCache.cs.meta new file mode 100644 index 0000000..be2a519 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TrackResourceCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 63f2caa33e79582448112b2e286d576d +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/Utilities/TypeUtility.cs b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TypeUtility.cs new file mode 100644 index 0000000..2c28266 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TypeUtility.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using UnityEngine; +using UnityEngine.Playables; +using UnityEngine.Timeline; +using Component = UnityEngine.Component; +using Object = UnityEngine.Object; + +namespace UnityEditor.Timeline +{ + static class TypeUtility + { + private static Type[] s_AllTrackTypes; + private static Type[] s_AllClipTypes; + private static Type[] s_MarkerTypes; + private static Dictionary<Type, Type[]> s_TrackTypeToVisibleClipType = new Dictionary<Type, Type[]>(); + private static Dictionary<Type, Type[]> s_TrackTypeToAllClipType = new Dictionary<Type, Type[]>(); + private static Dictionary<Type, TrackBindingTypeAttribute> s_TrackToBindingCache = new Dictionary<Type, TrackBindingTypeAttribute>(); + + public static bool IsConcretePlayableAsset(Type t) + { + return typeof(IPlayableAsset).IsAssignableFrom(t) + && IsConcreteAsset(t); + } + + private static bool IsConcreteAsset(Type t) + { + return typeof(ScriptableObject).IsAssignableFrom(t) + && !t.IsAbstract + && !t.IsGenericType + && !t.IsInterface + && !typeof(TrackAsset).IsAssignableFrom(t) + && !typeof(TimelineAsset).IsAssignableFrom(t); + } + + /// <summary> + /// List of all PlayableAssets + /// </summary> + public static IEnumerable<Type> AllClipTypes() + { + if (s_AllClipTypes == null) + { + s_AllClipTypes = TypeCache.GetTypesDerivedFrom<IPlayableAsset>(). + Where(t => IsConcreteAsset(t)). + ToArray(); + } + return s_AllClipTypes; + } + + public static IEnumerable<Type> AllTrackTypes() + { + if (s_AllTrackTypes == null) + { + s_AllTrackTypes = TypeCache.GetTypesDerivedFrom<TrackAsset>() + .Where(x => !x.IsAbstract) + .ToArray(); + } + + return s_AllTrackTypes; + } + + public static IEnumerable<Type> GetVisiblePlayableAssetsHandledByTrack(Type trackType) + { + if (trackType == null || !typeof(TrackAsset).IsAssignableFrom(trackType)) + return Enumerable.Empty<Type>(); + + Type[] types; + if (s_TrackTypeToVisibleClipType.TryGetValue(trackType, out types)) + { + return types; + } + + // special case -- the playable track handles all types not handled by other tracks + if (trackType == typeof(PlayableTrack)) + { + types = GetUnhandledClipTypes().ToArray(); + s_TrackTypeToVisibleClipType[trackType] = types; + return types; + } + + var attributes = trackType.GetCustomAttributes(typeof(TrackClipTypeAttribute), true); + var baseClasses = attributes. + OfType<TrackClipTypeAttribute>(). + Where(t => t.allowAutoCreate). + Select(a => a.inspectedType); + + types = AllClipTypes().Where(t => baseClasses.Any(x => x.IsAssignableFrom(t))).ToArray(); + s_TrackTypeToVisibleClipType[trackType] = types; + return types; + } + + public static IEnumerable<Type> GetPlayableAssetsHandledByTrack(Type trackType) + { + if (trackType == null || !typeof(TrackAsset).IsAssignableFrom(trackType)) + return Enumerable.Empty<Type>(); + + Type[] types; + if (s_TrackTypeToAllClipType.TryGetValue(trackType, out types)) + { + return types; + } + + // special case -- the playable track handles all types not handled by other tracks + if (trackType == typeof(PlayableTrack)) + { + types = GetUnhandledClipTypes().ToArray(); + s_TrackTypeToAllClipType[trackType] = types; + return types; + } + + var attributes = trackType.GetCustomAttributes(typeof(TrackClipTypeAttribute), true); + var baseClasses = attributes. + OfType<TrackClipTypeAttribute>(). + Select(a => a.inspectedType); + + types = AllClipTypes().Where(t => baseClasses.Any(x => x.IsAssignableFrom(t))).ToArray(); + s_TrackTypeToAllClipType[trackType] = types; + return types; + } + + /// <summary> + /// Returns the binding attribute attrached to the track + /// </summary> + public static TrackBindingTypeAttribute GetTrackBindingAttribute(Type trackType) + { + if (trackType == null || !typeof(TrackAsset).IsAssignableFrom(trackType)) + return null; + + TrackBindingTypeAttribute attribute = null; + if (!s_TrackToBindingCache.TryGetValue(trackType, out attribute)) + { + attribute = (TrackBindingTypeAttribute)Attribute.GetCustomAttribute(trackType, typeof(TrackBindingTypeAttribute)); + s_TrackToBindingCache.Add(trackType, attribute); + } + + return attribute; + } + + /// <summary> + /// True if the given track has a clip type that handles the given object + /// </summary> + public static bool TrackHasClipForObject(Type trackType, Object obj) + { + return GetPlayableAssetsHandledByTrack(trackType) + .Any(c => ObjectReferenceField.FindObjectReferences(c).Any(o => o.IsAssignable(obj))); + } + + /// <summary> + /// Get the list of markers that have fields for the object + /// </summary> + public static IEnumerable<Type> MarkerTypesWithFieldForObject(Object obj) + { + return GetAllMarkerTypes().Where( + c => ObjectReferenceField.FindObjectReferences(c).Any(o => o.IsAssignable(obj)) + ); + } + + /// <summary> + /// Get the list of tracks that can handle this object as clips + /// </summary> + public static IEnumerable<Type> GetTrackTypesForObject(Object obj) + { + if (obj == null) + return Enumerable.Empty<Type>(); + + return AllTrackTypes().Where(t => TrackHasClipForObject(t, obj)); + } + + /// <summary> + /// Given a trackType and an object, does the binding type match + /// Takes into account whether creating a missing component is permitted + /// </summary> + public static bool IsTrackCreatableFromObject(Object obj, Type trackType) + { + if (obj == null || obj.IsPrefab()) + return false; + + var attribute = GetTrackBindingAttribute(trackType); + if (attribute == null || attribute.type == null) + return false; + + if (attribute.type.IsAssignableFrom(obj.GetType())) + return true; + + var gameObject = obj as GameObject; + if (gameObject != null && typeof(Component).IsAssignableFrom(attribute.type)) + { + return gameObject.GetComponent(attribute.type) != null || + (attribute.flags & TrackBindingFlags.AllowCreateComponent) != 0; + } + + return false; + } + + /// <summary> + /// Given an object, get the list of track that are creatable from it. Takes + /// binding flags into account + /// </summary> + public static IEnumerable<Type> GetTracksCreatableFromObject(Object obj) + { + if (obj == null) + return Enumerable.Empty<Type>(); + + return AllTrackTypes().Where(t => !IsHiddenInMenu(t) && IsTrackCreatableFromObject(obj, t)); + } + + /// <summary> + /// Get the list of playable assets that can handle an object for a particular track + /// </summary> + /// <param name="trackType">The type of the track</param> + /// <param name="obj">The object to handle</param> + /// <returns></returns> + public static IEnumerable<Type> GetAssetTypesForObject(Type trackType, Object obj) + { + if (obj == null) + return Enumerable.Empty<Type>(); + + return GetPlayableAssetsHandledByTrack(trackType).Where( + c => ObjectReferenceField.FindObjectReferences(c).Any(o => o.IsAssignable(obj)) + ); + } + + // get the track types for a track from it's attributes + private static IEnumerable<Type> GetTrackClipTypesFromAttributes(Type trackType) + { + if (trackType == null || !typeof(TrackAsset).IsAssignableFrom(trackType)) + return Enumerable.Empty<Type>(); + + var attributes = trackType.GetCustomAttributes(typeof(TrackClipTypeAttribute), true); + var baseClasses = attributes. + OfType<TrackClipTypeAttribute>(). + Select(a => a.inspectedType); + + return AllClipTypes().Where(t => baseClasses.Any(x => x.IsAssignableFrom(t))); + } + + // find the playable asset types that are unhandled + private static IEnumerable<Type> GetUnhandledClipTypes() + { + var typesHandledByTrack = AllTrackTypes().SelectMany(t => GetTrackClipTypesFromAttributes(t)); + + // exclude anything in the timeline assembly, handled by tracks, has a hide in menu attribute + // or is explicity ignored + return AllClipTypes() + .Except(typesHandledByTrack) + .Where(t => !TypeUtility.IsBuiltIn(t)) // exclude built-in + .Where(t => !typeof(TrackAsset).IsAssignableFrom(t)) // exclude track types (they are playable assets) + .Where(t => !t.IsDefined(typeof(HideInMenuAttribute), false) && !t.IsDefined(typeof(IgnoreOnPlayableTrackAttribute), true)) + .Distinct(); + } + + public static IEnumerable<Type> GetAllMarkerTypes() + { + if (s_MarkerTypes == null) + { + s_MarkerTypes = TypeCache.GetTypesDerivedFrom<IMarker>() + .Where(x => + typeof(ScriptableObject).IsAssignableFrom(x) + && !x.IsAbstract + && !x.IsGenericType + && !x.IsInterface) + .ToArray(); + } + return s_MarkerTypes; + } + + public static IEnumerable<Type> GetUserMarkerTypes() + { + return GetAllMarkerTypes().Where(x => !IsBuiltIn(x) && !IsHiddenInMenu(x)); + } + + public static IEnumerable<Type> GetBuiltInMarkerTypes() + { + return GetAllMarkerTypes().Where(TypeUtility.IsBuiltIn); + } + + public static bool DoesTrackSupportMarkerType(TrackAsset track, Type type) + { + if (track.supportsNotifications) + { + return true; + } + + return !typeof(INotification).IsAssignableFrom(type); + } + + internal static string GetDisplayName(Type t) + { + var displayName = ObjectNames.NicifyVariableName(t.Name); + var attr = Attribute.GetCustomAttribute(t, typeof(DisplayNameAttribute)) as DisplayNameAttribute; + if (attr != null) + displayName = attr.DisplayName; + return displayName; + } + + public static bool IsHiddenInMenu(Type type) + { + var attr = type.GetCustomAttributes(typeof(HideInMenuAttribute), false); + return attr.Length > 0; + } + + public struct ObjectReference + { + public Type type; + public bool isSceneReference; + } + + public static IEnumerable<ObjectReference> ObjectReferencesForType(Type type) + { + var objectReferences = ObjectReferenceField.FindObjectReferences(type); + var uniqueTypes = objectReferences.Select(objRef => objRef.type).Distinct(); + foreach (var refType in uniqueTypes) + { + var isSceneReference = objectReferences.Any(objRef => objRef.type == refType && objRef.isSceneReference); + yield return new ObjectReference { type = refType, isSceneReference = isSceneReference }; + } + } + + /// <summary> + /// Checks whether a type has an overridden method with a specific name. This method also checks overridden members in parent classes. + /// </summary> + public static bool HasOverrideMethod(System.Type t, string name) + { + const MethodAttributes mask = MethodAttributes.Virtual | MethodAttributes.NewSlot; + const MethodAttributes expectedResult = MethodAttributes.Virtual; + + var method = t.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + return method != null && (method.Attributes & mask) == expectedResult; + } + + /// <summary> + /// Returns whether the given type resides in the timeline assembly + /// </summary> + public static bool IsBuiltIn(System.Type t) + { + return t != null && t.Assembly.Equals(typeof(TimelineAsset).Assembly); + } + } +} diff --git a/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TypeUtility.cs.meta b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TypeUtility.cs.meta new file mode 100644 index 0000000..e73d461 --- /dev/null +++ b/Library/PackageCache/com.unity.timeline@1.2.13/Editor/Utilities/TypeUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c1821c1816c6fa44967b8ecb79ea7e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |
