Ejemplo n.º 1
0
        private void DoLoopCounterGUI(ref Rect area, float length)
        {
            if (_LoopCounterCache == null)
            {
                _LoopCounterCache = new ConversionCache <int, string>((x) => "x" + x);
            }

            string label;
            var    normalizedTime = Target.Time / length;

            if (float.IsNaN(normalizedTime))
            {
                label = "NaN";
            }
            else
            {
                var loops = (int)Math.Abs(Target.Time / length);
                label = _LoopCounterCache.Convert(loops);
            }

            var width = AnimancerGUI.CalculateLabelWidth(label);

            var labelArea = AnimancerGUI.StealFromRight(ref area, width);

            GUI.Label(labelArea, label);
        }
Ejemplo n.º 2
0
            /// <summary>Draws two float fields.</summary>
            public static float DoTwinFloatFieldGUI(Rect area, GUIContent label, float value, float normalizeMultiplier, bool isNormalized)
            {
                if (_PixelSuffixCache == null)
                {
                    _PixelSuffixCache      = new ConversionCache <float, string>((s) => s + "px");
                    _NormalizedSuffixCache = new ConversionCache <float, string>((x) => x + "x");
                }

                var split          = (area.width - EditorGUIUtility.labelWidth - AnimancerGUI.StandardSpacing) * 0.5f;
                var normalizedArea = AnimancerGUI.StealFromRight(ref area, Mathf.Floor(split), AnimancerGUI.StandardSpacing);

                var pixels     = isNormalized ? value / normalizeMultiplier : value;
                var normalized = isNormalized ? value : value * normalizeMultiplier;

                EditorGUI.BeginChangeCheck();
                pixels = AnimancerGUI.DoSpecialFloatField(area, label, pixels, _PixelSuffixCache);
                if (EditorGUI.EndChangeCheck())
                {
                    value = isNormalized ? pixels * normalizeMultiplier : pixels;
                }

                EditorGUI.BeginChangeCheck();
                normalized = AnimancerGUI.DoSpecialFloatField(normalizedArea, null, normalized, _NormalizedSuffixCache);
                if (EditorGUI.EndChangeCheck())
                {
                    value = isNormalized ? normalized : normalized / normalizeMultiplier;
                }

                return(value);
            }
Ejemplo n.º 3
0
        /// <summary>
        /// Draws a label showing the `weight` aligned to the right side of the `area` and reduces its
        /// <see cref="Rect.width"/> to remove that label from its area.
        /// </summary>
        public static void DoWeightLabel(ref Rect area, float weight)
        {
            string label;

            if (weight < 0)
            {
                label = "-?";
            }
            else
            {
                if (_F1Cache == null)
                {
                    _F1Cache = new ConversionCache <float, string>((value) => value.ToString("F1"));
                }

                label = _F1Cache.Convert(weight);
            }

            var style = ObjectPool.GetCachedResult(() => new GUIStyle(GUI.skin.label));

            if (_WeightValueWidth < 0)
            {
                _WeightValueWidth = style.CalculateWidth("0.0");
            }

            style.normal.textColor = Color.Lerp(Color.grey, TextColor, weight);
            style.fontStyle        = Mathf.Approximately(weight * 10, (int)(weight * 10)) ?
                                     FontStyle.Normal : FontStyle.Italic;

            var weightArea = StealFromRight(ref area, _WeightValueWidth);

            GUI.Label(weightArea, label, style);
        }
Ejemplo n.º 4
0
        /// <summary>[Animancer Extension]
        /// Calls <see cref="Gather(ICollection{AnimationClip}, AnimationClip)"/> for each clip in the `asset`.
        /// </summary>
        public static void GatherFromAsset(this ICollection <AnimationClip> clips, PlayableAsset asset)
        {
            if (asset == null)
            {
                return;
            }

            // We want to get the tracks out of a TimelineAsset without actually referencing that class directly
            // because it comes from an optional package and Animancer does not need to depend on that package.
            if (_TypeToGetRootTracks == null)
            {
                _TypeToGetRootTracks = new Editor.ConversionCache <Type, MethodInfo>((type) =>
                {
                    var method = type.GetMethod("GetRootTracks");
                    if (method != null &&
                        typeof(IEnumerable).IsAssignableFrom(method.ReturnType) &&
                        method.GetParameters().Length == 0)
                    {
                        return(method);
                    }
                    else
                    {
                        return(null);
                    }
                });
            }

            var getRootTracks = _TypeToGetRootTracks.Convert(asset.GetType());

            if (getRootTracks != null)
            {
                var rootTracks = getRootTracks.Invoke(asset, null);
                GatherAnimationClips(rootTracks as IEnumerable, clips);
            }
        }
Ejemplo n.º 5
0
        private static void GetEventLabels(int index, Context context, out GUIContent timeLabel, out string callbackLabel,
                                           out float defaultTime, out bool isEndEvent)
        {
            if (index >= context.TimeCount - 1)
            {
                timeLabel = AnimancerGUI.TempContent("End Time",
                                                     Strings.ProOnlyTag + "The time when the end callback will be triggered");

                callbackLabel = "End Callback";

                defaultTime = AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(
                    context.TransitionContext.Transition.Speed);
                isEndEvent = true;
            }
            else
            {
                if (_CallbackLabelCache == null)
                {
                    _CallbackLabelCache = new ConversionCache <int, string>((i) => "Event " + i + " Callback");
                    _TimeLabelCache     = new ConversionCache <int, string>((i) => "Event " + i + " Time");
                }

                timeLabel = AnimancerGUI.TempContent(_TimeLabelCache.Convert(index),
                                                     Strings.ProOnlyTag + "The time when the callback will be triggered");

                callbackLabel = _CallbackLabelCache.Convert(index);

                defaultTime = 0;
                isEndEvent  = false;
            }
        }
Ejemplo n.º 6
0
        private static void GetEventLabels(int index, Context context,
                                           out string nameLabel, out string timeLabel, out string callbackLabel, out float defaultTime, out bool isEndEvent)
        {
            if (index >= context.Times.Count - 1)
            {
                nameLabel     = null;
                timeLabel     = "End Time";
                callbackLabel = "End Callback";

                defaultTime = AnimancerEvent.Sequence.GetDefaultNormalizedEndTime(
                    context.TransitionContext?.Transition?.Speed ?? 1);
                isEndEvent = true;
            }
            else
            {
                if (_NameLabelCache == null)
                {
                    _NameLabelCache     = new ConversionCache <int, string>((i) => $"Event {i} Name");
                    _TimeLabelCache     = new ConversionCache <int, string>((i) => $"Event {i} Time");
                    _CallbackLabelCache = new ConversionCache <int, string>((i) => $"Event {i} Callback");
                }

                nameLabel     = _NameLabelCache.Convert(index);
                timeLabel     = _TimeLabelCache.Convert(index);
                callbackLabel = _CallbackLabelCache.Convert(index);

                defaultTime = 0;
                isEndEvent  = false;
            }
        }
        /************************************************************************************************************************/

        /// <summary>Creates and returns a cache for the specified `characterCount`.</summary>
        private ConversionCache <float, string> GetCache(int characterCount)
        {
            while (Caches.Count <= characterCount)
            {
                Caches.Add(null);
            }

            var cache = Caches[characterCount];

            if (cache == null)
            {
                if (characterCount == 0)
                {
                    cache = new ConversionCache <float, string>((value) =>
                    {
                        return(value.ToStringCached() + Suffix);
                    });
                }
                else
                {
                    cache = new ConversionCache <float, string>((value) =>
                    {
                        var valueString = value.ToStringCached();

                        if (value > LargeExponentialThreshold ||
                            value < -LargeExponentialThreshold)
                        {
                            goto IsExponential;
                        }

                        if (_DecimalSeparator == null)
                        {
                            _DecimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
                        }

                        var decimalIndex = valueString.IndexOf(_DecimalSeparator);
                        if (decimalIndex < 0 || decimalIndex > characterCount)
                        {
                            goto IsExponential;
                        }

                        // Not exponential.
                        return(valueString.Substring(0, characterCount) + ApproximateSuffix);

                        IsExponential:
                        var digits  = Math.Max(0, characterCount - ApproximateSuffix.Length - 1);
                        var format  = GetExponentialFormat(digits);
                        valueString = value.ToString(format);
                        TrimExponential(ref valueString);
                        return(valueString + Suffix);
                    });
                }

                Caches[characterCount] = cache;
            }

            return(cache);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Calls <see cref="GUIStyle.CalcMinMaxWidth"/> using <see cref="GUISkin.label"/> and returns the max
        /// width. The result is cached for efficient reuse.
        /// <para></para>
        /// This method uses the <see cref="TempContent(string, string, bool)"/>.
        /// </summary>
        public static float CalculateLabelWidth(string text)
        {
            if (_LabelWidthCache == null)
            {
                _LabelWidthCache = CreateWidthCache(GUI.skin.label);
            }

            return(_LabelWidthCache.Convert(text));
        }
Ejemplo n.º 9
0
        private static void DrawSpriteFrames(AnimationClip clip)
        {
            var keyframes = GetSpriteReferences(clip);

            if (keyframes == null)
            {
                return;
            }

            for (int i = 0; i < keyframes.Length; i++)
            {
                var keyframe = keyframes[i];
                var sprite   = keyframe.value as Sprite;
                if (sprite != null)
                {
                    if (_FrameCache == null)
                    {
                        _FrameCache = new ConversionCache <int, string>(
                            (value) => $"Frame: {value}");

                        _TimeCache = new ConversionCache <float, string>(
                            (value) => $"Time: {value}s");
                    }

                    var texture = sprite.texture;

                    var area  = GUILayoutUtility.GetRect(0, AnimancerGUI.LineHeight * 4);
                    var width = area.width;

                    var rect = sprite.rect;
                    area.width = area.height * rect.width / rect.height;

                    rect.x      /= texture.width;
                    rect.y      /= texture.height;
                    rect.width  /= texture.width;
                    rect.height /= texture.height;

                    GUI.DrawTextureWithTexCoords(area, texture, rect);

                    var offset = area.width + AnimancerGUI.StandardSpacing;
                    area.x     += offset;
                    area.width  = width - offset;
                    area.height = AnimancerGUI.LineHeight;
                    area.y     += Mathf.Round(area.height * 0.5f);

                    GUI.Label(area, _FrameCache.Convert(i));

                    AnimancerGUI.NextVerticalArea(ref area);
                    GUI.Label(area, _TimeCache.Convert(keyframe.time));

                    AnimancerGUI.NextVerticalArea(ref area);
                    GUI.Label(area, sprite.name);
                }
            }
        }
Ejemplo n.º 10
0
        private void DoRulerLabelGUI(ref Rect previousArea, float time)
        {
            if (_RulerLabelStyle == null)
            {
                _RulerLabelStyle = new GUIStyle(GUI.skin.label)
                {
                    padding       = new RectOffset(),
                    contentOffset = new Vector2(0, -2),
                    alignment     = TextAnchor.UpperLeft,
                    fontSize      = Mathf.CeilToInt(AnimancerGUI.LineHeight * 0.6f),
                }
            }
            ;

            var text = G2Cache.Convert(time);

            if (_TimeLabelWidthCache == null)
            {
                _TimeLabelWidthCache = AnimancerGUI.CreateWidthCache(_RulerLabelStyle);
            }

            var area = new Rect(
                SecondsToPixels(time),
                _Area.y,
                _TimeLabelWidthCache.Convert(text),
                _Area.height);

            if (area.x > _Area.x)
            {
                var tickY = _Area.yMax - TickHeight;
                EditorGUI.DrawRect(new Rect(area.x, tickY, 1, TickHeight), AnimancerGUI.TextColor);
            }

            if (area.xMax > _Area.xMax)
            {
                area.x = _Area.xMax - area.width;
            }
            if (area.x < 0)
            {
                area.x = 0;
            }

            if (area.x > previousArea.xMax + 2)
            {
                GUI.Label(area, text, _RulerLabelStyle);

                previousArea = area;
            }
        }

        /************************************************************************************************************************/
        #endregion
        /************************************************************************************************************************/
    }
Ejemplo n.º 11
0
        /// <summary>
        /// Draw a <see cref="EditorGUI.FloatField(Rect, GUIContent, float)"/> with an alternate cached string when it
        /// is not selected (for example, "1" might become "1s" to indicate "seconds").
        /// </summary>
        public static void DoFloatFieldWithSuffix(Rect area, GUIContent label, SerializedProperty property,
                                                  ConversionCache <float, string> toString)
        {
            label = EditorGUI.BeginProperty(area, label, property);
            EditorGUI.BeginChangeCheck();
            var value = DoSpecialFloatField(area, label, property.floatValue, toString);

            if (EditorGUI.EndChangeCheck())
            {
                property.floatValue = value;
            }
            EditorGUI.EndProperty();
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Returns the `text` without any spaces if <see cref="EditorGUIUtility.wideMode"/> is false.
        /// Otherwise simply returns the `text` without any changes.
        /// </summary>
        public static string GetNarrowText(string text)
        {
            if (EditorGUIUtility.wideMode ||
                string.IsNullOrEmpty(text))
            {
                return(text);
            }

            if (_NarrowTextCache == null)
            {
                _NarrowTextCache = new ConversionCache <string, string>((str) => str.Replace(" ", ""));
            }

            return(_NarrowTextCache.Convert(text));
        }
        /************************************************************************************************************************/

        /// <summary>Calculate the index of the cache to use for the given parameters.</summary>
        private int CalculateCacheIndex(float value, float width)
        {
            //if (value > LargeExponentialThreshold ||
            //    value < -LargeExponentialThreshold)
            //    return 0;

            var valueString = value.ToStringCached();

            // It the approximated string wouldn't be shorter than the original, don't approximate.
            if (valueString.Length < 2 + ApproximateSuffix.Length)
            {
                return(0);
            }

            if (_SuffixWidth == 0)
            {
                if (_WidthCache == null)
                {
                    _WidthCache             = AnimancerGUI.CreateWidthCache(EditorStyles.numberField);
                    _FieldPadding           = EditorStyles.numberField.padding.horizontal;
                    _ApproximateSymbolWidth = _WidthCache.Convert("~") - _FieldPadding;
                }

                _SuffixWidth = _WidthCache.Convert(Suffix);
            }

            // If the field is wide enough to fit the full value, don't approximate.
            width -= _FieldPadding + _ApproximateSymbolWidth * 0.75f;
            var valueWidth = _WidthCache.Convert(valueString) + _SuffixWidth;

            if (valueWidth <= width)
            {
                return(0);
            }

            // If the number of allowed characters would include the full value, don't approximate.
            var suffixedLength    = valueString.Length + Suffix.Length;
            var allowedCharacters = (int)(suffixedLength * width / valueWidth);

            if (allowedCharacters + 2 >= suffixedLength)
            {
                return(0);
            }

            return(allowedCharacters);
        }
Ejemplo n.º 14
0
        /// <summary>Draws the GUI for the `animancerEvent`.</summary>
        public static void Draw(ref Rect area, string name, AnimancerEvent animancerEvent)
        {
            area.height = AnimancerGUI.LineHeight;

            if (_EventTimeCache == null)
            {
                _EventTimeCache = new ConversionCache <float, string>((time)
                                                                      => float.IsNaN(time) ? "Time = Auto" : $"Time = {time.ToStringCached()}x");
            }

            EditorGUI.LabelField(area, name, _EventTimeCache.Convert(animancerEvent.normalizedTime));

            AnimancerGUI.NextVerticalArea(ref area);

            EditorGUI.indentLevel++;
            DrawInvocationList(ref area, animancerEvent.callback);
            EditorGUI.indentLevel--;
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Draws a label showing the `weight` aligned to the right side of the `area` and reduces its
        /// <see cref="Rect.width"/> to remove that label from its area.
        /// </summary>
        public static void DoWeightLabel(ref Rect area, float weight)
        {
            if (_F1Cache == null)
            {
                _F1Cache          = new ConversionCache <float, string>((value) => value.ToString("F1"));
                _WeightLabelStyle = new GUIStyle(GUI.skin.label);
                _WeightValueWidth = _WeightLabelStyle.CalculateWidth("0.0");
            }

            var weightArea = StealFromRight(ref area, _WeightValueWidth);

            var label = _F1Cache.Convert(weight);

            _WeightLabelStyle.normal.textColor = Color.Lerp(Color.grey, TextColor, weight);
            _WeightLabelStyle.fontStyle        = Mathf.Approximately(weight * 10, (int)(weight * 10)) ?
                                                 FontStyle.Normal : FontStyle.Italic;

            GUI.Label(weightArea, label, _WeightLabelStyle);
        }
Ejemplo n.º 16
0
        private void DoRulerLabelGUI(ref Rect previousArea, float time)
        {
            var text = G2Cache.Convert(time);

            if (_TimeLabelWidthCache == null)
            {
                _TimeLabelWidthCache = AnimancerGUI.CreateWidthCache(Styles.TimeLabel);
            }

            var area = new Rect(
                SecondsToPixels(time),
                _Area.y,
                _TimeLabelWidthCache.Convert(text),
                _Area.height);

            if (area.x > _Area.x)
            {
                var tickHeight = _Area.height * TickHeight;
                var tickY      = _Area.yMax - tickHeight;

                EditorGUI.DrawRect(new Rect(area.x, tickY, 1, tickHeight), AnimancerGUI.TextColor);
            }

            if (area.xMax > _Area.xMax)
            {
                area.x = _Area.xMax - area.width;
            }
            if (area.x < 0)
            {
                area.x = 0;
            }

            if (area.x > previousArea.xMax + 2)
            {
                GUI.Label(area, text, Styles.TimeLabel);

                previousArea = area;
            }
        }
Ejemplo n.º 17
0
        /// <summary>Gathers all the animations in the `tracks`.</summary>
        private static void GatherAnimationClips(IEnumerable tracks, ICollection <AnimationClip> clips)
        {
            if (tracks == null)
            {
                return;
            }

            if (_TrackAssetToGetClips == null)
            {
                _TrackAssetToGetClips = new Editor.ConversionCache <Type, MethodInfo>((type) =>
                {
                    var method = type.GetMethod("GetClips");
                    if (method != null &&
                        typeof(IEnumerable).IsAssignableFrom(method.ReturnType) &&
                        method.GetParameters().Length == 0)
                    {
                        return(method);
                    }
                    else
                    {
                        return(null);
                    }
                });

                _TimelineClipToAnimationClip = new Editor.ConversionCache <Type, MethodInfo>((type) =>
                {
                    var property = type.GetProperty("animationClip");
                    if (property != null &&
                        property.PropertyType == typeof(AnimationClip))
                    {
                        return(property.GetGetMethod());
                    }
                    else
                    {
                        return(null);
                    }
                });

                _TrackAssetToGetChildTracks = new Editor.ConversionCache <Type, MethodInfo>((type) =>
                {
                    var method = type.GetMethod("GetChildTracks");
                    if (method != null &&
                        typeof(IEnumerable).IsAssignableFrom(method.ReturnType) &&
                        method.GetParameters().Length == 0)
                    {
                        return(method);
                    }
                    else
                    {
                        return(null);
                    }
                });
            }

            foreach (var track in tracks)
            {
                if (track == null)
                {
                    continue;
                }

                var trackType = track.GetType();

                var getClips = _TrackAssetToGetClips.Convert(trackType);
                if (getClips != null)
                {
                    var trackClips = getClips.Invoke(track, null) as IEnumerable;
                    if (trackClips != null)
                    {
                        foreach (var clip in trackClips)
                        {
                            var getClip = _TimelineClipToAnimationClip.Convert(clip.GetType());
                            if (getClip != null)
                            {
                                clips.Gather(getClip.Invoke(clip, null) as AnimationClip);
                            }
                        }
                    }
                }

                var getChildTracks = _TrackAssetToGetChildTracks.Convert(trackType);
                if (getChildTracks != null)
                {
                    var childTracks = getChildTracks.Invoke(track, null);
                    GatherAnimationClips(childTracks as IEnumerable, clips);
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Draw a <see cref="GUI.Toggle(Rect, bool, GUIContent)"/> which sets the value to <see cref="float.NaN"/>
        /// when disabled followed by two float fields to display the `time` both normalized and in seconds.
        /// </summary>
        public static float DoOptionalTimeField(ref Rect area, GUIContent label, float time, bool timeIsNormalized,
                                                float length, float defaultValue = 0, bool isOptional = true)
        {
            if (_XSuffixCache == null)
            {
                _XSuffixCache = new ConversionCache <float, string>((x) => x + "x");
                _SSuffixCache = new ConversionCache <float, string>((s) => s + "s");
            }

            area.height = LineHeight;

            bool showNormalized, showSeconds;

            if (length > 0)
            {
                showNormalized = showSeconds = true;
            }
            else
            {
                showNormalized = timeIsNormalized;
                showSeconds    = !timeIsNormalized;
            }

            var labelWidth = EditorGUIUtility.labelWidth;
            var enabled    = GUI.enabled;

            var toggleArea = area;

            if (isOptional)
            {
                toggleArea.x += EditorGUIUtility.labelWidth;

                toggleArea.width             = ToggleWidth;
                EditorGUIUtility.labelWidth += toggleArea.width;

                EditorGUIUtility.AddCursorRect(toggleArea, MouseCursor.Arrow);

                // We need to draw the toggle after everything else to it goes on top of the label. But we want it to
                // get priority for input events, so we disable the other controls during those events in its area.
                var currentEvent = Event.current;
                if (enabled && toggleArea.Contains(currentEvent.mousePosition))
                {
                    switch (currentEvent.type)
                    {
                    case EventType.Repaint:
                    case EventType.Layout:
                        break;

                    default:
                        GUI.enabled = false;
                        break;
                    }
                }
            }
            else if (float.IsNaN(time))
            {
                time = defaultValue;
            }

            var displayTime = float.IsNaN(time) ? defaultValue : time;

            var normalizedArea = area;
            var secondsArea    = area;

            if (showNormalized)
            {
                if (showSeconds)
                {
                    var split = (EditorGUIUtility.labelWidth + normalizedArea.xMax - StandardSpacing) * 0.5f;
                    normalizedArea.xMax = split;
                    secondsArea.xMin    = split + StandardSpacing;
                }

                var normalizedTime = timeIsNormalized ? displayTime : displayTime / length;

                EditorGUI.BeginChangeCheck();
                normalizedTime = DoSpecialFloatField(normalizedArea, label, normalizedTime, _XSuffixCache);
                if (EditorGUI.EndChangeCheck())
                {
                    time = timeIsNormalized ? normalizedTime : normalizedTime * length;
                }
            }

            EditorGUIUtility.labelWidth = labelWidth;

            if (showSeconds)
            {
                var rawTime = timeIsNormalized ? displayTime * length : displayTime;

                if (showNormalized)
                {
                    label = null;
                }

                EditorGUI.BeginChangeCheck();
                rawTime = DoSpecialFloatField(secondsArea, label, rawTime, _SSuffixCache);
                if (EditorGUI.EndChangeCheck())
                {
                    if (timeIsNormalized)
                    {
                        if (length != 0)
                        {
                            time = rawTime / length;
                        }
                    }
                    else
                    {
                        time = rawTime;
                    }
                }
            }

            GUI.enabled = enabled;

            if (isOptional)
            {
                DoOptionalTimeToggle(toggleArea, ref time, defaultValue);
            }

            return(time);
        }
Ejemplo n.º 19
0
        /************************************************************************************************************************/
        #endregion
        /************************************************************************************************************************/
        #region Fields
        /************************************************************************************************************************/

        /// <summary>
        /// Draw a <see cref="EditorGUI.FloatField(Rect, GUIContent, float)"/> with an alternate cached string when it
        /// is not selected (for example, "1" might become "1s" to indicate "seconds").
        /// </summary>
        public static float DoSpecialFloatField(Rect area, GUIContent label, float value, ConversionCache <float, string> toString)
        {
            // Treat most events normally, but when repainting show a text field with the cached string.

            if (label != null)
            {
                if (Event.current.type != EventType.Repaint)
                {
                    return(EditorGUI.FloatField(area, label, value));
                }

                var dragArea = new Rect(area.x, area.y, EditorGUIUtility.labelWidth, area.height);
                EditorGUIUtility.AddCursorRect(dragArea, MouseCursor.SlideArrow);

                EditorGUI.TextField(area, label, toString.Convert(value));
            }
            else
            {
                var indentLevel = EditorGUI.indentLevel;
                EditorGUI.indentLevel = 0;

                if (Event.current.type != EventType.Repaint)
                {
                    value = EditorGUI.FloatField(area, value);
                }
                else
                {
                    EditorGUI.TextField(area, toString.Convert(value));
                }

                EditorGUI.indentLevel = indentLevel;
            }

            return(value);
        }
Ejemplo n.º 20
0
        /// <summary>Returns a string which approximates the `weight` into no more than 3 digits.</summary>
        private static string WeightToShortString(float weight, out bool isExact)
        {
            isExact = true;

            if (weight == 0)
            {
                return("0.0");
            }
            if (weight == 1)
            {
                return("1.0");
            }

            isExact = false;

            if (weight >= -0.5f && weight < 0.05f)
            {
                return("~0.");
            }
            if (weight >= 0.95f && weight < 1.05f)
            {
                return("~1.");
            }

            if (weight <= -99.5f)
            {
                return("-??");
            }
            if (weight >= 999.5f)
            {
                return("???");
            }

            if (_ShortWeightCache == null)
            {
                _ShortWeightCache = new ConversionCache <float, string>((value) =>
                {
                    if (value < -9.5f)
                    {
                        return($"{value:F0}");
                    }
                    if (value < -0.5f)
                    {
                        return($"{value:F0}.");
                    }
                    if (value < 9.5f)
                    {
                        return($"{value:F1}");
                    }
                    if (value < 99.5f)
                    {
                        return($"{value:F0}.");
                    }
                    return($"{value:F0}");
                });
            }

            var rounded = weight > 0 ? Mathf.Floor(weight * 10) : Mathf.Ceil(weight * 10);

            isExact = Mathf.Approximately(weight * 10, rounded);

            return(_ShortWeightCache.Convert(weight));
        }
Ejemplo n.º 21
0
        /************************************************************************************************************************/

        /// <summary>Draws the GUI for the `events`.</summary>
        public void Draw(ref Rect area, Sequence events, GUIContent label)
        {
            if (events == null)
            {
                return;
            }

            area.height = AnimancerGUI.LineHeight;

            var headerArea = area;

            const string LogLabel = "Log";

            if (float.IsNaN(_LogButtonWidth))
            {
                _LogButtonWidth = EditorStyles.miniButton.CalculateWidth(LogLabel);
            }
            var logArea = AnimancerGUI.StealFromRight(ref headerArea, _LogButtonWidth);

            if (GUI.Button(logArea, LogLabel, EditorStyles.miniButton))
            {
                Debug.Log(events.DeepToString());
            }

            _IsExpanded = EditorGUI.Foldout(headerArea, _IsExpanded, GUIContent.none, true);
            using (ObjectPool.Disposable.AcquireContent(out var summary, GetSummary(events)))
                EditorGUI.LabelField(headerArea, label, summary);

            AnimancerGUI.NextVerticalArea(ref area);

            if (!_IsExpanded)
            {
                return;
            }

            var enabled = GUI.enabled;

            GUI.enabled = false;

            EditorGUI.indentLevel++;

            for (int i = 0; i < events.Count; i++)
            {
                var name = events.GetName(i);
                if (string.IsNullOrEmpty(name))
                {
                    if (_EventNumberCache == null)
                    {
                        _EventNumberCache = new ConversionCache <int, string>((index) => $"Event {index}");
                    }

                    name = _EventNumberCache.Convert(i);
                }

                Draw(ref area, name, events[i]);
            }

            Draw(ref area, "End Event", events.endEvent);

            EditorGUI.indentLevel--;

            GUI.enabled = enabled;
        }