/// <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 footer of the child list.</summary> protected virtual void DoChildListFooterGUI(Rect area) { ReorderableList.defaultBehaviours.DrawFooter(area, _CurrentChildList); EditorGUI.BeginChangeCheck(); area.xMax = EditorGUIUtility.labelWidth + AnimancerGUI.IndentSize; area.y++; area.height = AnimancerGUI.LineHeight; using (ObjectPool.Disposable.AcquireContent(out var label, "Count")) { var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; var labelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = AnimancerGUI.CalculateLabelWidth(label.text); var count = EditorGUI.DelayedIntField(area, label, _CurrentChildList.count); if (EditorGUI.EndChangeCheck()) { ResizeList(count); } EditorGUIUtility.labelWidth = labelWidth; EditorGUI.indentLevel = indentLevel; } }
/// <summary>Splits the specified `area` into separate sections.</summary> protected static void SplitListRect(Rect area, bool isHeader, out Rect animation, out Rect speed, out Rect sync) { if (_SpeedLabelWidth == 0) { _SpeedLabelWidth = AnimancerGUI.CalculateWidth(EditorStyles.popup, "Speed"); } if (_SyncLabelWidth == 0) { _SyncLabelWidth = AnimancerGUI.CalculateWidth(EditorStyles.popup, "Sync"); } var spacing = AnimancerGUI.StandardSpacing; var syncWidth = isHeader ? _SyncLabelWidth : AnimancerGUI.ToggleWidth - spacing; var speedWidth = _SpeedLabelWidth + _SyncLabelWidth - syncWidth; if (!isHeader) { // Don't use Clamp because the max might be smaller than the min. var max = Math.Max(area.height, area.width * 0.25f - 30); speedWidth = Math.Min(speedWidth, max); } area.width += spacing; sync = AnimancerGUI.StealFromRight(ref area, syncWidth, spacing); speed = AnimancerGUI.StealFromRight(ref area, speedWidth, spacing); animation = area; }
/************************************************************************************************************************/ private void DoOptionalAfterGUI(bool isOptional, Rect area, ref float value, float defaultValue, bool guiWasEnabled, float previousLabelWidth) { GUI.enabled = guiWasEnabled; EditorGUIUtility.labelWidth = previousLabelWidth; if (!isOptional) { return; } area.x += AnimancerGUI.StandardSpacing; var wasEnabled = !float.IsNaN(value); // Use the EditorGUI method instead to properly handle EditorGUI.showMixedValue. //var isEnabled = GUI.Toggle(area, wasEnabled, GUIContent.none); var indentLevel = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; var isEnabled = EditorGUI.Toggle(area, wasEnabled); EditorGUI.indentLevel = indentLevel; if (isEnabled != wasEnabled) { value = isEnabled ? defaultValue : float.NaN; AnimancerGUI.Deselect(); } }
/// <summary>[Editor-Only] Ends a GUI property block started by <see cref="BeginProperty"/>.</summary> protected static void EndProperty(Rect area, SerializedProperty property, ref float value) { if (AnimancerGUI.TryUseClickEvent(area, 2)) { DefaultValueAttribute.SetToDefault(ref value, property); } if (EditorGUI.EndChangeCheck()) { property.floatValue = value; } EditorGUI.EndProperty(); }
/************************************************************************************************************************/ /// <summary>[Editor-Only] Draws this attribute's fields.</summary> protected void DoFieldGUI(Rect area, GUIContent label, ref float value) { var isMultiLine = area.height > LineHeight; area.height = LineHeight; DoOptionalBeforeGUI(IsOptional, area, out var toggleArea, out var guiWasEnabled, out var previousLabelWidth); Rect allFieldArea; if (isMultiLine) { EditorGUI.LabelField(area, label); label = null; AnimancerGUI.NextVerticalArea(ref area); EditorGUI.indentLevel++; allFieldArea = EditorGUI.IndentedRect(area); EditorGUI.indentLevel--; } else { var labelXMax = area.x + EditorGUIUtility.labelWidth; allFieldArea = new Rect(labelXMax, area.y, area.xMax - labelXMax, area.height); } // Count the number of active fields. var count = 0; var last = 0; for (int i = 0; i < Multipliers.Length; i++) { if (!float.IsNaN(Multipliers[i])) { count++; last = i; } } var width = (allFieldArea.width - StandardSpacing * (count - 1)) / count; var fieldArea = new Rect(allFieldArea.x, allFieldArea.y, width, allFieldArea.height); var displayValue = GetDisplayValue(value, DefaultValue); // Draw the active fields. for (int i = 0; i < Multipliers.Length; i++) { var multiplier = Multipliers[i]; if (float.IsNaN(multiplier)) { continue; } if (label != null) { fieldArea.xMin = area.xMin; } else if (i < last) { fieldArea.width = width; fieldArea.xMax = AnimancerUtilities.Round(fieldArea.xMax); } else { fieldArea.xMax = area.xMax; } EditorGUI.BeginChangeCheck(); var fieldValue = displayValue * multiplier; fieldValue = DoSpecialFloatField(fieldArea, label, fieldValue, DisplayConverters[i]); label = null; if (EditorGUI.EndChangeCheck()) { value = fieldValue / multiplier; } fieldArea.x += fieldArea.width + StandardSpacing; } DoOptionalAfterGUI(IsOptional, toggleArea, ref value, DefaultValue, guiWasEnabled, previousLabelWidth); Validate.ValueRule(ref value, Rule); }