/// <summary>Draws the GUI of the state at the specified `index`.</summary> protected void DoElementGUI(Rect animationArea, Rect speedArea, Rect syncArea, int index, SerializedProperty state, SerializedProperty speed) { DoAnimationField(animationArea, state); if (speed != null) { EditorGUI.PropertyField(speedArea, speed, GUIContent.none); } else// If this element doesn't have its own speed property, just show 1. { EditorGUI.BeginProperty(speedArea, GUIContent.none, CurrentSpeeds); var value = Units.UnitsAttribute.DoSpecialFloatField( speedArea, null, 1, Units.AnimationSpeedAttribute.DisplayConverters[0]); // Middle Click toggles from 1 to -1. if (AnimancerGUI.TryUseClickEvent(speedArea, 2)) { value = -1; } if (value != 1) { CurrentSpeeds.InsertArrayElementAtIndex(0); CurrentSpeeds.GetArrayElementAtIndex(0).floatValue = 1; CurrentSpeeds.arraySize = CurrentAnimations.arraySize; CurrentSpeeds.GetArrayElementAtIndex(index).floatValue = value; } EditorGUI.EndProperty(); } DoSyncToggleGUI(syncArea, index); }
/// <summary>Draws the GUI of the state at the specified `index`.</summary> protected void DoElementGUI(Rect animationArea, Rect speedArea, Rect syncArea, int index, SerializedProperty clip, SerializedProperty speed) { EditorGUI.PropertyField(animationArea, clip, GUIContent.none); if (speed != null) { EditorGUI.PropertyField(speedArea, speed, GUIContent.none); } else { EditorGUI.BeginProperty(speedArea, GUIContent.none, CurrentSpeeds); var value = EditorGUI.FloatField(speedArea, 1); if (value != 1) { CurrentSpeeds.InsertArrayElementAtIndex(0); CurrentSpeeds.GetArrayElementAtIndex(0).floatValue = 1; CurrentSpeeds.arraySize = CurrentClips.arraySize; CurrentSpeeds.GetArrayElementAtIndex(index).floatValue = value; } EditorGUI.EndProperty(); } DoSyncToggleGUI(syncArea, index); }
/************************************************************************************************************************/ #region Speeds /************************************************************************************************************************/ /// <summary> /// Initialises every element in the <see cref="CurrentSpeeds"/> array from the `start` to the end of /// the array to contain a value of 1. /// </summary> public static void InitialiseSpeeds(int start) { var count = CurrentSpeeds.arraySize; while (start < count) { CurrentSpeeds.GetArrayElementAtIndex(start++).floatValue = 1; } }
/************************************************************************************************************************/ /// <summary> /// Recalculates the <see cref="CurrentSpeeds"/> depending on the <see cref="AnimationClip.length"/> of /// their animations so that they all take the same amount of time to play fully. /// </summary> private static void NormalizeDurations(SerializedProperty property) { var speedCount = CurrentSpeeds.arraySize; var lengths = new float[CurrentAnimations.arraySize]; if (lengths.Length <= 1) { return; } int nonZeroLengths = 0; float totalLength = 0; float totalSpeed = 0; for (int i = 0; i < lengths.Length; i++) { var state = CurrentAnimations.GetArrayElementAtIndex(i).objectReferenceValue; if (AnimancerUtilities.TryGetLength(state, out var length) && length > 0) { nonZeroLengths++; totalLength += length; lengths[i] = length; if (speedCount > 0) { totalSpeed += CurrentSpeeds.GetArrayElementAtIndex(i).floatValue; } } } if (nonZeroLengths == 0) { return; } var averageLength = totalLength / nonZeroLengths; var averageSpeed = speedCount > 0 ? totalSpeed / nonZeroLengths : 1; CurrentSpeeds.arraySize = lengths.Length; InitializeSpeeds(speedCount); for (int i = 0; i < lengths.Length; i++) { if (lengths[i] == 0) { continue; } CurrentSpeeds.GetArrayElementAtIndex(i).floatValue = averageSpeed * lengths[i] / averageLength; } TryCollapseArrays(); }
/************************************************************************************************************************/ /// <summary>Draws the GUI of the state at the specified `index`.</summary> private void DoElementGUI(Rect area, int index, bool isActive, bool isFocused) { if (index < 0 || index > CurrentClips.arraySize) { return; } var clip = CurrentClips.GetArrayElementAtIndex(index); var speed = CurrentSpeeds.arraySize > 0 ? CurrentSpeeds.GetArrayElementAtIndex(index) : null; DoElementGUI(area, index, clip, speed); }
/************************************************************************************************************************/ /// <summary>Draws the GUI of the state at the specified `index`.</summary> private void DoElementGUI(Rect area, int index, bool isActive, bool isFocused) { if (index < 0 || index > CurrentAnimations.arraySize) { return; } area.height = AnimancerGUI.LineHeight; var state = CurrentAnimations.GetArrayElementAtIndex(index); var speed = CurrentSpeeds.arraySize > 0 ? CurrentSpeeds.GetArrayElementAtIndex(index) : null; DoElementGUI(area, index, state, speed); }
/************************************************************************************************************************/ /// <summary> /// If every element in the <see cref="CurrentSpeeds"/> array is 1, this method sets the array size to 0. /// </summary> public static void TryCollapseSpeeds() { var speedCount = CurrentSpeeds.arraySize; if (speedCount <= 0) { return; } for (int i = 0; i < speedCount; i++) { if (CurrentSpeeds.GetArrayElementAtIndex(i).floatValue != 1) { return; } } CurrentSpeeds.arraySize = 0; }