/// <summary>Determines the <see cref="AnimationType"/> of the specified `clip`.</summary> public static AnimationType GetAnimationType(AnimationClip clip) { if (clip == null) { return(AnimationType.None); } if (clip.isHumanMotion) { return(AnimationType.Humanoid); } AnimancerEditorUtilities.InitialiseCleanDictionary(ref _ClipToIsSprite); if (!_ClipToIsSprite.TryGetValue(clip, out var isSprite)) { var bindings = AnimationUtility.GetObjectReferenceCurveBindings(clip); for (int i = 0; i < bindings.Length; i++) { var binding = bindings[i]; if (binding.type == typeof(SpriteRenderer) && binding.propertyName == "m_Sprite") { isSprite = true; break; } } _ClipToIsSprite.Add(clip, isSprite); } return(isSprite ? AnimationType.Sprite : AnimationType.Generic); }
/// <summary>Returns a cached <see cref="BindingData"/> representing the specified `gameObject`.</summary> /// <remarks>Note that the cache is cleared by <see cref="EditorApplication.hierarchyChanged"/>.</remarks> public static BindingData GetBindings(GameObject gameObject) { if (AnimancerEditorUtilities.InitialiseCleanDictionary(ref _ObjectToBindings)) { EditorApplication.hierarchyChanged += _ObjectToBindings.Clear; } if (!_ObjectToBindings.TryGetValue(gameObject, out var bindings)) { bindings = new BindingData(gameObject); _ObjectToBindings.Add(gameObject, bindings); } return(bindings); }
/// <summary>Returns a cached array of all properties animated by the specified `clip`.</summary> public static EditorCurveBinding[] GetBindings(AnimationClip clip) { AnimancerEditorUtilities.InitialiseCleanDictionary(ref _ClipToBindings); if (!_ClipToBindings.TryGetValue(clip, out var bindings)) { var curveBindings = AnimationUtility.GetCurveBindings(clip); var objectBindings = AnimationUtility.GetObjectReferenceCurveBindings(clip); bindings = new EditorCurveBinding[curveBindings.Length + objectBindings.Length]; Array.Copy(curveBindings, bindings, curveBindings.Length); Array.Copy(objectBindings, 0, bindings, curveBindings.Length, objectBindings.Length); _ClipToBindings.Add(clip, bindings); } return(bindings); }
/// <summary> /// Determines the <see cref="MatchType"/> representing the properties animated by the `clip` in /// comparison to the properties that actually exist on the target <see cref="GameObject"/> and its /// children. /// <para></para> /// Also compiles a `message` explaining the differences if that paraneter is not null. /// </summary> public MatchType GetMatchType(AnimationClip clip, StringBuilder message, Dictionary <EditorCurveBinding, bool> bindingsInMessage, ref int existingBindings, bool forceGather = true) { AnimancerEditorUtilities.InitialiseCleanDictionary(ref _BindingMatches); if (_BindingMatches.TryGetValue(clip, out var match)) { if (bindingsInMessage == null) { return(match); } } else if (!forceGather && !CanGatherBindings()) { return(MatchType.Unknown); } var objectType = ObjectType; var clipType = GetAnimationType(clip); if (clipType != objectType) { if (message != null) { message.AppendLine() .Append($"{LinePrefix}This message does not necessarily mean anything is wrong," + $" but if something is wrong then this might help you identify the problem."); message.AppendLine() .Append($"{LinePrefix}The {nameof(AnimationType)} of the '") .Append(clip.name) .Append("' animation is ") .Append(clipType) .Append(" while the '") .Append(GameObject.name) .Append("' Rig is ") .Append(objectType) .Append(". See the documentation for more information about Animation Types:" + $" {Strings.DocsURLs.Inspector}#animation-types"); } switch (clipType) { default: case AnimationType.None: case AnimationType.Humanoid: match = MatchType.Error; if (message == null) { goto SetMatch; } else { break; } case AnimationType.Generic: case AnimationType.Sprite: match = MatchType.Warning; break; } } var bindingMatch = GetMatchType(GetBindings(clip), bindingsInMessage, ref existingBindings); if (match < bindingMatch) { match = bindingMatch; } SetMatch: _BindingMatches[clip] = match; return(match); }
/// <summary> /// Determines the <see cref="MatchType"/> representing the properties animated by the `clip` in /// comparison to the properties that actually exist on the target <see cref="GameObject"/> and its /// children. /// <para></para> /// Also compiles a `message` explaining the differences if that paraneter is not null. /// </summary> public MatchType GetMatchType(AnimationClip clip, StringBuilder message, Dictionary <EditorCurveBinding, bool> bindingsInMessage, ref int existingBindings) { AnimancerEditorUtilities.InitialiseCleanDictionary(ref _BindingMatches); if (_BindingMatches.TryGetValue(clip, out var match) && bindingsInMessage == null) { return(match); } var objectType = ObjectType; var clipType = GetAnimationType(clip); if (clipType != objectType) { if (message != null) { message.AppendLine() .Append($"{LinePrefix}The {nameof(AnimationType)} of the '") .Append(clip.name) .Append("' animation is ") .Append(clipType) .Append(" while the '") .Append(GameObject.name) .Append("' Rig is ") .Append(objectType) .Append("."); } switch (clipType) { default: case AnimationType.None: case AnimationType.Humanoid: match = MatchType.Error; if (message == null) { goto SetMatch; } else { break; } case AnimationType.Generic: case AnimationType.Sprite: match = MatchType.Warning; break; } } var bindingMatch = GetMatchType(GetBindings(clip), bindingsInMessage, ref existingBindings); if (match < bindingMatch) { match = bindingMatch; } SetMatch: _BindingMatches[clip] = match; return(match); }