Replaced raw variables for animations in VoiceRecordButton.

This commit is contained in:
23rd 2020-10-29 17:25:36 +03:00 committed by John Preston
parent ce1ae5ba12
commit 71e8bda7bb

View file

@ -66,12 +66,6 @@ constexpr auto kMaxAmplitude = 1800.;
constexpr auto kZeroPoint = QPointF(0, 0); constexpr auto kZeroPoint = QPointF(0, 0);
void ApplyTo(float64 &value, const float64 &to, const float64 &diff) {
if ((value != to) && ((diff > 0) == (value > to))) {
value = to;
}
}
template <typename Number> template <typename Number>
void Normalize(Number &value, Number right) { void Normalize(Number &value, Number right) {
if (value >= right) { if (value >= right) {
@ -120,6 +114,49 @@ void PerformAnimation(
} // namespace } // namespace
class ContinuousValue {
public:
ContinuousValue() = default;
ContinuousValue(float64 duration) : _duration(duration) {
}
void start(float64 to, float64 duration) {
_to = to;
_delta = (_to - _cur) / duration;
}
void start(float64 to) {
start(to, _duration);
}
float64 current() const {
return _cur;
}
float64 to() const {
return _to;
}
float64 delta() const {
return _delta;
}
void update(crl::time dt, Fn<void(float64 &)> &&callback = nullptr) {
if (_to != _cur) {
_cur += _delta * dt;
if ((_to != _cur) && ((_delta > 0) == (_cur > _to))) {
_cur = _to;
}
if (callback) {
callback(_cur);
}
}
}
private:
float64 _duration = 0.;
float64 _to = 0.;
float64 _cur = 0.;
float64 _delta = 0.;
};
class CircleBezier final { class CircleBezier final {
public: public:
CircleBezier(int n); CircleBezier(int n);
@ -162,8 +199,8 @@ public:
float64 amplitudeDiffFactor, float64 amplitudeDiffFactor,
bool isDirectionClockwise); bool isDirectionClockwise);
void setValue(float64 value); void setValue(float64 to);
void tick(float64 circleRadius, crl::time lastUpdateTime); void tick(float64 circleRadius, crl::time dt);
void paint(Painter &p, QColor c); void paint(Painter &p, QColor c);
@ -185,16 +222,13 @@ private:
const int _flingDistanceFactor; const int _flingDistanceFactor;
const int _flingInAnimationDuration; const int _flingInAnimationDuration;
const int _flingOutAnimationDuration; const int _flingOutAnimationDuration;
const float64 _amplitudeDiffSpeed; const float64 _amplitudeInAnimationDuration;
const float64 _amplitudeDiffFactor; const float64 _amplitudeOutAnimationDuration;
const int _directionClockwise; const int _directionClockwise;
bool _incRandomAdditionals = false; bool _incRandomAdditionals = false;
bool _isIdle = true; bool _isIdle = true;
bool _wasFling = false; bool _wasFling = false;
float64 _amplitude = 0.;
float64 _animateAmplitudeDiff = 0.;
float64 _animateToAmplitude = 0.;
float64 _flingRadius = 0.; float64 _flingRadius = 0.;
float64 _idleRadius = 0.; float64 _idleRadius = 0.;
float64 _idleRotation = 0.; float64 _idleRotation = 0.;
@ -203,6 +237,7 @@ private:
float64 _sineAngleMax = 0.; float64 _sineAngleMax = 0.;
float64 _waveAngle = 0.; float64 _waveAngle = 0.;
float64 _waveDiff = 0.; float64 _waveDiff = 0.;
ContinuousValue _levelValue;
rpl::event_stream<float64> _flingAnimationRequests; rpl::event_stream<float64> _flingAnimationRequests;
rpl::event_stream<> _enterIdleAnimationRequests; rpl::event_stream<> _enterIdleAnimationRequests;
@ -223,13 +258,8 @@ private:
const std::unique_ptr<Wave> _majorWave; const std::unique_ptr<Wave> _majorWave;
const std::unique_ptr<Wave> _minorWave; const std::unique_ptr<Wave> _minorWave;
float64 _amplitude = 0.;
float64 _animateToAmplitude = 0.;
float64 _animateAmplitudeDiff = 0.;
crl::time _lastUpdateTime = 0; crl::time _lastUpdateTime = 0;
ContinuousValue _levelValue;
rpl::lifetime _animationLifetime;
rpl::lifetime _lifetime;
}; };
@ -320,25 +350,23 @@ Wave::Wave(
, _flingDistanceFactor(flingDistanceFactor) , _flingDistanceFactor(flingDistanceFactor)
, _flingInAnimationDuration(flingInAnimationDuration) , _flingInAnimationDuration(flingInAnimationDuration)
, _flingOutAnimationDuration(flingOutAnimationDuration) , _flingOutAnimationDuration(flingOutAnimationDuration)
, _amplitudeDiffSpeed(amplitudeDiffSpeed) , _amplitudeInAnimationDuration(kMinDivider
, _amplitudeDiffFactor(amplitudeDiffFactor) + amplitudeDiffFactor * amplitudeDiffSpeed)
, _amplitudeOutAnimationDuration(kMinDivider
+ kAmplitudeDiffFactorMax * amplitudeDiffSpeed)
, _directionClockwise(isDirectionClockwise ? 1 : -1) , _directionClockwise(isDirectionClockwise ? 1 : -1)
, _rotation(rotationOffset) { , _rotation(rotationOffset) {
initEnterIdleAnimation(rpl::duplicate(animationTicked)); initEnterIdleAnimation(rpl::duplicate(animationTicked));
initFlingAnimation(std::move(animationTicked)); initFlingAnimation(std::move(animationTicked));
} }
void Wave::setValue(float64 value) { void Wave::setValue(float64 to) {
_animateToAmplitude = value; const auto duration = (to <= _levelValue.current())
? _amplitudeOutAnimationDuration
: _amplitudeInAnimationDuration;
_levelValue.start(to, duration);
const auto amplitudeDelta = (_animateToAmplitude - _amplitude); const auto idle = to < 0.1;
const auto factor = (_animateToAmplitude <= _amplitude)
? kAmplitudeDiffFactorMax
: _amplitudeDiffFactor;
_animateAmplitudeDiff = amplitudeDelta
/ (kMinDivider + factor * _amplitudeDiffSpeed);
const auto idle = value < 0.1;
if (_isIdle != idle && idle) { if (_isIdle != idle && idle) {
_enterIdleAnimationRequests.fire({}); _enterIdleAnimationRequests.fire({});
} }
@ -414,30 +442,28 @@ void Wave::initFlingAnimation(rpl::producer<crl::time> animationTicked) {
}, _lifetime); }, _lifetime);
} }
void Wave::tick(float64 circleRadius, crl::time lastUpdateTime) { void Wave::tick(float64 circleRadius, crl::time dt) {
const auto dt = (crl::now() - lastUpdateTime);
if (_animateToAmplitude != _amplitude) { auto amplitudeCallback = [&](float64 &value) {
_amplitude += _animateAmplitudeDiff * dt; if (std::abs(value - _levelValue.to()) * _amplitudeRadius
ApplyTo(_amplitude, _animateToAmplitude, _animateAmplitudeDiff);
if (std::abs(_amplitude - _animateToAmplitude) * _amplitudeRadius
< (st::historyRecordRandomAddition / 2)) { < (st::historyRecordRandomAddition / 2)) {
if (!_wasFling) { if (!_wasFling) {
_flingAnimationRequests.fire_copy(_animateAmplitudeDiff); _flingAnimationRequests.fire_copy(_levelValue.delta());
_wasFling = true; _wasFling = true;
} }
} else { } else {
_wasFling = false; _wasFling = false;
} }
} };
_levelValue.update(dt, std::move(amplitudeCallback));
_idleRadius = circleRadius * kIdleRadiusFactor; _idleRadius = circleRadius * kIdleRadiusFactor;
{ {
const auto delta = (_sineAngleMax - _animateToAmplitude); const auto to = _levelValue.to();
const auto delta = (_sineAngleMax - to);
if (std::abs(delta) - 0.25 < 0) { if (std::abs(delta) - 0.25 < 0) {
_sineAngleMax = _animateToAmplitude; _sineAngleMax = to;
} else { } else {
_sineAngleMax -= 0.25 * ((delta < 0) ? -1 : 1); _sineAngleMax -= 0.25 * ((delta < 0) ? -1 : 1);
} }
@ -445,7 +471,7 @@ void Wave::tick(float64 circleRadius, crl::time lastUpdateTime) {
if (!_isIdle) { if (!_isIdle) {
_rotation += dt _rotation += dt
* (kRotationSpeed * 4. * (_amplitude > 0.5 ? 1 : _amplitude / 0.5) * (kRotationSpeed * 4. * std::min(_levelValue.current() / .5, 1.)
+ kRotationSpeed * 0.5); + kRotationSpeed * 0.5);
Normalize(_rotation, 360.); Normalize(_rotation, 360.);
} else { } else {
@ -468,13 +494,14 @@ void Wave::tick(float64 circleRadius, crl::time lastUpdateTime) {
void Wave::paint(Painter &p, QColor c) { void Wave::paint(Painter &p, QColor c) {
const auto waveAmplitude = _amplitude < 0.3 ? _amplitude / 0.3 : 1.; const auto amplitude = _levelValue.current();
const auto waveAmplitude = std::min(amplitude / .3, 1.);
const auto radiusDiff = st::historyRecordRadiusDiffMin const auto radiusDiff = st::historyRecordRadiusDiffMin
+ st::historyRecordRadiusDiff * kWaveAngle * _animateToAmplitude; + st::historyRecordRadiusDiff * kWaveAngle * _levelValue.to();
const auto diffFactor = 0.35 * waveAmplitude * _waveDiff; const auto diffFactor = 0.35 * waveAmplitude * _waveDiff;
const auto radius = (_lastRadius + _amplitudeRadius * _amplitude) const auto radius = (_lastRadius + _amplitudeRadius * amplitude)
+ _idleGlobalRadius + _idleGlobalRadius
+ (_flingRadius * waveAmplitude); + (_flingRadius * waveAmplitude);
@ -527,30 +554,28 @@ RecordCircle::RecordCircle(rpl::producer<crl::time> animationTicked)
kFlingOutAnimationDurationMinor, kFlingOutAnimationDurationMinor,
kAnimationSpeedMinor, kAnimationSpeedMinor,
kAmplitudeDiffFactorMinor, kAmplitudeDiffFactorMinor,
false)) { false))
, _levelValue(kMinDivider
+ kAmplitudeDiffFactorMax * kAnimationSpeedCircle) {
} }
void RecordCircle::setAmplitude(float64 value) { void RecordCircle::setAmplitude(float64 value) {
_animateToAmplitude = std::min(kMaxAmplitude, value) / kMaxAmplitude; const auto to = std::min(kMaxAmplitude, value) / kMaxAmplitude;
_majorWave->setValue(_animateToAmplitude); _levelValue.start(to);
_minorWave->setValue(_animateToAmplitude); _majorWave->setValue(to);
_animateAmplitudeDiff = (_animateToAmplitude - _amplitude) _minorWave->setValue(to);
/ (kMinDivider + kAmplitudeDiffFactorMax * kAnimationSpeedCircle);
} }
void RecordCircle::paint(Painter &p, QColor c) { void RecordCircle::paint(Painter &p, QColor c) {
const auto dt = (crl::now() - _lastUpdateTime); const auto dt = crl::now() - _lastUpdateTime;
if (_animateToAmplitude != _amplitude) { _levelValue.update(dt);
_amplitude += _animateAmplitudeDiff * dt;
ApplyTo(_amplitude, _animateToAmplitude, _animateAmplitudeDiff);
}
const auto radius = (st::historyRecordLevelMainRadius const auto radius = (st::historyRecordLevelMainRadius
+ st::historyRecordLevelMainRadiusAmplitude * _amplitude); + st::historyRecordLevelMainRadiusAmplitude * _levelValue.current());
_majorWave->tick(radius, _lastUpdateTime); _majorWave->tick(radius, dt);
_minorWave->tick(radius, _lastUpdateTime); _minorWave->tick(radius, dt);
_lastUpdateTime = crl::now(); _lastUpdateTime = crl::now();
const auto opacity = p.opacity(); const auto opacity = p.opacity();