您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
178 行
6.1 KiB
178 行
6.1 KiB
using System;
|
|
using Unity.UIWidgets.foundation;
|
|
using Unity.UIWidgets.physics;
|
|
using Unity.UIWidgets.ui;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.UIWidgets.widgets {
|
|
public class BouncingScrollSimulation : Simulation {
|
|
public BouncingScrollSimulation(
|
|
float position,
|
|
float velocity,
|
|
float leadingExtent,
|
|
float trailingExtent,
|
|
SpringDescription spring,
|
|
Tolerance tolerance = null
|
|
) : base(tolerance: tolerance) {
|
|
D.assert(leadingExtent <= trailingExtent);
|
|
D.assert(spring != null);
|
|
|
|
this.leadingExtent = leadingExtent;
|
|
this.trailingExtent = trailingExtent;
|
|
this.spring = spring;
|
|
|
|
if (position < leadingExtent) {
|
|
_springSimulation = _underscrollSimulation(position, velocity);
|
|
_springTime = float.NegativeInfinity;
|
|
}
|
|
else if (position > trailingExtent) {
|
|
_springSimulation = _overscrollSimulation(position, velocity);
|
|
_springTime = float.NegativeInfinity;
|
|
}
|
|
else {
|
|
_frictionSimulation = new FrictionSimulation(0.135f, position, velocity);
|
|
float finalX = _frictionSimulation.finalX;
|
|
if (velocity > 0.0f && finalX > trailingExtent) {
|
|
_springTime = _frictionSimulation.timeAtX(trailingExtent);
|
|
_springSimulation = _overscrollSimulation(
|
|
trailingExtent,
|
|
Mathf.Min(_frictionSimulation.dx(_springTime),
|
|
maxSpringTransferVelocity)
|
|
);
|
|
D.assert(_springTime.isFinite());
|
|
}
|
|
else if (velocity < 0.0f && finalX < leadingExtent) {
|
|
_springTime = _frictionSimulation.timeAtX(leadingExtent);
|
|
_springSimulation = _underscrollSimulation(
|
|
leadingExtent,
|
|
Mathf.Min(_frictionSimulation.dx(_springTime),
|
|
maxSpringTransferVelocity)
|
|
);
|
|
D.assert(_springTime.isFinite());
|
|
}
|
|
else {
|
|
_springTime = float.PositiveInfinity;
|
|
}
|
|
}
|
|
}
|
|
|
|
const float maxSpringTransferVelocity = 5000.0f;
|
|
|
|
public readonly float leadingExtent;
|
|
|
|
public readonly float trailingExtent;
|
|
|
|
public readonly SpringDescription spring;
|
|
|
|
readonly FrictionSimulation _frictionSimulation;
|
|
readonly Simulation _springSimulation;
|
|
readonly float _springTime;
|
|
float _timeOffset = 0.0f;
|
|
|
|
Simulation _underscrollSimulation(float x, float dx) {
|
|
return new ScrollSpringSimulation(spring, x, leadingExtent, dx);
|
|
}
|
|
|
|
Simulation _overscrollSimulation(float x, float dx) {
|
|
return new ScrollSpringSimulation(spring, x, trailingExtent, dx);
|
|
}
|
|
|
|
Simulation _simulation(float time) {
|
|
Simulation simulation;
|
|
if (time > _springTime) {
|
|
_timeOffset = _springTime.isFinite() ? _springTime : 0.0f;
|
|
simulation = _springSimulation;
|
|
}
|
|
else {
|
|
_timeOffset = 0.0f;
|
|
simulation = _frictionSimulation;
|
|
}
|
|
|
|
simulation.tolerance = tolerance;
|
|
return simulation;
|
|
}
|
|
|
|
public override float x(float time) {
|
|
return _simulation(time).x(time - _timeOffset);
|
|
}
|
|
|
|
public override float dx(float time) {
|
|
return _simulation(time).dx(time - _timeOffset);
|
|
}
|
|
|
|
public override bool isDone(float time) {
|
|
return _simulation(time).isDone(time - _timeOffset);
|
|
}
|
|
|
|
public override string ToString() {
|
|
return $"{GetType()}(leadingExtent: {leadingExtent}, trailingExtent: {trailingExtent})";
|
|
}
|
|
}
|
|
|
|
public class ClampingScrollSimulation : Simulation {
|
|
public ClampingScrollSimulation(
|
|
float position,
|
|
float velocity,
|
|
float friction = 0.015f,
|
|
Tolerance tolerance = null
|
|
) : base(tolerance: tolerance) {
|
|
D.assert(_flingVelocityPenetration(0.0f) == _initialVelocityPenetration);
|
|
this.position = position;
|
|
this.velocity = velocity;
|
|
this.friction = friction;
|
|
|
|
_duration = _flingDuration(velocity);
|
|
_distance = (velocity * _duration / _initialVelocityPenetration).abs();
|
|
}
|
|
|
|
public readonly float position;
|
|
|
|
public readonly float velocity;
|
|
|
|
public readonly float friction;
|
|
|
|
readonly float _duration;
|
|
|
|
readonly float _distance;
|
|
|
|
static readonly float _kDecelerationRate = Mathf.Log(0.78f) / Mathf.Log(0.9f);
|
|
|
|
static float _decelerationForFriction(float friction) {
|
|
return friction * 61774.04968f;
|
|
}
|
|
|
|
float _flingDuration(float velocity) {
|
|
float scaledFriction = friction * _decelerationForFriction(0.84f);
|
|
|
|
float deceleration = Mathf.Log(0.35f * velocity.abs() / scaledFriction);
|
|
|
|
return Mathf.Exp(deceleration / (_kDecelerationRate - 1.0f));
|
|
}
|
|
|
|
const float _initialVelocityPenetration = 3.065f;
|
|
|
|
static float _flingDistancePenetration(float t) {
|
|
return (1.2f * t * t * t) - (3.27f * t * t) + (_initialVelocityPenetration * t);
|
|
}
|
|
|
|
static float _flingVelocityPenetration(float t) {
|
|
return (3.6f * t * t) - (6.54f * t) + _initialVelocityPenetration;
|
|
}
|
|
|
|
public override float x(float time) {
|
|
float t = (time / _duration).clamp(0.0f, 1.0f);
|
|
return (position + _distance * _flingDistancePenetration(t) *
|
|
velocity.sign());
|
|
}
|
|
|
|
public override float dx(float time) {
|
|
float t = (time / _duration).clamp(0.0f, 1.0f);
|
|
return (_distance * _flingVelocityPenetration(t) * velocity.sign() /
|
|
_duration);
|
|
}
|
|
|
|
public override bool isDone(float time) {
|
|
return time >= _duration;
|
|
}
|
|
}
|
|
}
|