Demos/AnimationShowcase/Sections/MouseFollowSection.cs
using System;
using Goo;
using Goo.Animation;
using Sandbox.UI;
using static Sandbox.DemoTokens;
namespace Sandbox.AnimationShowcase;
public class MouseFollowSection
{
const float PadW = 480f;
const float PadH = 320f;
const float DotSize = 18f;
SmoothVector2 _smooth = new( initial: new Vector2( PadW / 2f, PadH / 2f ), smoothTime: 0.20f );
DecayVector2 _decay = new( initial: new Vector2( PadW / 2f, PadH / 2f ), halflife: 0.12f );
SpringVector2 _spring = new( initial: new Vector2( PadW / 2f, PadH / 2f ), frequency: 6f, damping: 0.35f );
public void Update( float dt )
{
_smooth.Update( dt );
_decay.Update( dt );
_spring.Update( dt );
}
public Container Build() => Section.Build(
"vector2 dampers - move the cursor inside the pad",
new Container
{
FlexDirection = FlexDirection.Row,
Gap = Space4,
AlignItems = Align.FlexStart,
Children =
{
Pad(),
Legend.Build(
( "SmoothVector2", "velocity-tracked", Accent ),
( "DecayVector2", "exponential, no overshoot", AccentGreen ),
( "SpringVector2", "oscillates", AccentOrange )
),
},
} );
Container Pad()
{
var pad = new Container
{
Width = PadW,
Height = PadH,
BackgroundColor = BgCard,
BorderRadius = Radius2,
Position = PositionMode.Relative,
PointerEvents = PointerEvents.All,
// LocalPosition is in rendered pixels; normalize via Box.Rect into authored coords.
OnMouseMove = e =>
{
float rectW = e.Target?.Box.Rect.Width ?? 0f;
float rectH = e.Target?.Box.Rect.Height ?? 0f;
if ( rectW <= 0f || rectH <= 0f ) return;
float ax = Math.Clamp( e.LocalPosition.x / rectW, 0f, 1f ) * PadW;
float ay = Math.Clamp( e.LocalPosition.y / rectH, 0f, 1f ) * PadH;
var target = new Vector2( ax, ay );
_smooth.Target = target;
_decay.Target = target;
_spring.Target = target;
},
};
pad.Children.Add( Dot.AtCenter( _smooth.Current, DotSize, Accent ) );
pad.Children.Add( Dot.AtCenter( _decay.Current, DotSize, AccentGreen ) );
pad.Children.Add( Dot.AtCenter( _spring.Current, DotSize, AccentOrange ) );
return pad;
}
}