Demos/AnimationShowcase/Sections/AnimatorSection.cs
using Goo;
using Goo.Animation;
using Sandbox.UI;
using static Sandbox.DemoTokens;

namespace Sandbox.AnimationShowcase;

public class AnimatorSection
{
    const float BarW = 480f;
    const float BarH = 24f;

    Animator _animator = new Animator(
        new Tween( Easing.EaseInOut, duration: 2f ).PingPong().Loop() );

    public void Update( float dt ) => _animator.Update( dt );

    public Container Build() => Section.Build(
        "animator - pause / resume / seek / restart",
        new Container
        {
            FlexDirection = FlexDirection.Column,
            Gap           = Space3,
            AlignItems    = Align.FlexStart,
            Children =
            {
                ProgressBar.Build( BarW, BarH, _animator.Value, Accent ),
                new Container
                {
                    FlexDirection = FlexDirection.Row,
                    Gap           = Space2,
                    Children =
                    {
                        CtrlButton.Build( _animator.Paused ? "resume" : "pause", _ => Toggle() ),
                        CtrlButton.Build( "restart",      _ => _animator.Restart() ),
                        // Seek by half the cycle duration so EaseInOut PingPong lands at the
                        // visual midpoint. _animator.Tween.Duration (not the literal 0.5f) is
                        // the source of truth for the cycle length.
                        CtrlButton.Build( "seek halfway", _ => _animator.Seek( _animator.Tween.Duration / 2f ) ),
                    },
                },
            },
        } );

    void Toggle()
    {
        if ( _animator.Paused ) _animator.Resume();
        else _animator.Pause();
    }
}