mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-08 08:04:08 +02:00
Replaced raw variables for animations in VoiceRecordButton.
This commit is contained in:
parent
ce1ae5ba12
commit
71e8bda7bb
1 changed files with 85 additions and 60 deletions
|
@ -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();
|
||||||
|
|
Loading…
Add table
Reference in a new issue