Files
UnrealEngine/Engine/Source/Runtime/Slate/Private/Framework/Layout/InertialScrollManager.cpp
2025-05-18 13:04:45 +08:00

83 lines
2.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Framework/Layout/InertialScrollManager.h"
#include "HAL/IConsoleManager.h"
float FrictionCoefficient = 2.0f;
FAutoConsoleVariableRef CVarFrictionCoefficient(
TEXT("Slate.InertialScroll.FrictionCoefficient"),
FrictionCoefficient,
TEXT("This is the percentage of velocity loss per second."),
ECVF_Default);
float StaticVelocityDrag = 100;
FAutoConsoleVariableRef CVarStaticVelocityDrag(
TEXT("Slate.InertialScroll.StaticVelocityDrag"),
StaticVelocityDrag,
TEXT("This is a constant amount of velocity lost per second."),
ECVF_Default);
FInertialScrollManager::FInertialScrollManager(double InSampleTimeout)
: ScrollVelocity(0.f)
, SampleTimeout(InSampleTimeout)
{
}
void FInertialScrollManager::AddScrollSample(float Delta, double CurrentTime)
{
ScrollSamples.Emplace(Delta, CurrentTime);
float Total = 0;
double OldestTime = 0;
for ( int32 VelIdx = ScrollSamples.Num() - 1; VelIdx >= 0; --VelIdx )
{
const double SampleTime = ScrollSamples[VelIdx].Time;
const float SampleDelta = ScrollSamples[VelIdx].Delta;
if ( CurrentTime - SampleTime > SampleTimeout )
{
ScrollSamples.RemoveAt(VelIdx);
}
else
{
if ( SampleTime < OldestTime || OldestTime == 0 )
{
OldestTime = SampleTime;
}
Total += SampleDelta;
}
}
// Set the current velocity to the average of the previous recent samples
const double Duration = (OldestTime > 0) ? (CurrentTime - OldestTime) : 0;
if ( Duration > 0 )
{
ScrollVelocity = Total / Duration;
}
else
{
ScrollVelocity = 0;
}
}
void FInertialScrollManager::UpdateScrollVelocity(const float InDeltaTime)
{
const float VelocityLostPerSecond = ScrollVelocity > 0 ? StaticVelocityDrag : -StaticVelocityDrag;
const float DeltaVelocity = FrictionCoefficient * ScrollVelocity * InDeltaTime + VelocityLostPerSecond * InDeltaTime;
if ( ScrollVelocity > 0 )
{
ScrollVelocity = FMath::Max<float>(0.f, ScrollVelocity - DeltaVelocity);
}
else if ( ScrollVelocity < 0 )
{
ScrollVelocity = FMath::Min<float>(0.f, ScrollVelocity - DeltaVelocity);
}
}
void FInertialScrollManager::ClearScrollVelocity(bool bInShouldStopScrollNow)
{
bShouldStopScrollNow = ScrollVelocity != 0 ? bInShouldStopScrollNow : false;
ScrollVelocity = 0;
}