From df8eed957662a6cff9e31cc59387933cb587f501 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 29 Nov 2020 03:19:22 +0300 Subject: [PATCH] Added implementation of blobs painter. --- CMakeLists.txt | 2 ++ ui/effects/animation_value.h | 46 ++++++++++++++++++++++++++ ui/paint/blobs.cpp | 63 ++++++++++++++++++++++++++++++++++++ ui/paint/blobs.h | 50 ++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+) create mode 100644 ui/paint/blobs.cpp create mode 100644 ui/paint/blobs.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d0597b..47285df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,8 @@ PRIVATE ui/layers/layer_widget.h ui/paint/blob.cpp ui/paint/blob.h + ui/paint/blobs.cpp + ui/paint/blobs.h ui/platform/linux/ui_window_linux.cpp ui/platform/linux/ui_window_linux.h ui/platform/linux/ui_utility_linux.cpp diff --git a/ui/effects/animation_value.h b/ui/effects/animation_value.h index dc5d530..93110ce 100644 --- a/ui/effects/animation_value.h +++ b/ui/effects/animation_value.h @@ -404,4 +404,50 @@ private: }; +class continuous_value { +public: + continuous_value() = default; + continuous_value(float64 duration) : _duration(duration) { + } + void start(float64 to, float64 duration) { + _to = to; + _delta = (_to - _cur) / duration; + } + void start(float64 to) { + start(to, _duration); + } + void reset() { + _to = _cur = _delta = 0.; + } + + float64 current() const { + return _cur; + } + float64 to() const { + return _to; + } + float64 delta() const { + return _delta; + } + void update(crl::time dt, Fn &&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.; + +}; + } // namespace anim diff --git a/ui/paint/blobs.cpp b/ui/paint/blobs.cpp new file mode 100644 index 0000000..a235725 --- /dev/null +++ b/ui/paint/blobs.cpp @@ -0,0 +1,63 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#include "ui/paint/blobs.h" + +#include "ui/painter.h" + +namespace Ui::Paint { + +Blobs::Blobs( + std::vector blobDatas, + float levelDuration, + float maxLevel) +: _maxLevel(maxLevel) +, _blobDatas(blobDatas) +, _levelValue(levelDuration) { + init(); +} + +void Blobs::init() { + for (const auto &data : _blobDatas) { + auto blob = Paint::BlobBezier(data.segmentsCount, data.minScale); + blob.setRadius(data.minRadius, data.maxRadius); + _blobs.push_back(std::move(blob)); + } +} + +float Blobs::maxRadius() const { + const auto maxOfRadiuses = [](const BlobData data) { + return std::max(data.maxRadius, data.minRadius); + }; + const auto max = *ranges::max_element( + _blobDatas, + std::less<>(), + maxOfRadiuses); + return maxOfRadiuses(max); +} + +void Blobs::setLevel(float value) { + const auto to = std::min(_maxLevel, value) / _maxLevel; + _levelValue.start(to); +} + +void Blobs::paint(Painter &p, const QBrush &brush) { + const auto dt = crl::now() - _lastUpdateTime; + _levelValue.update((dt > 20) ? 17 : dt); + + const auto opacity = p.opacity(); + for (auto i = 0; i < _blobs.size(); i++) { + _blobs[i].update(_levelValue.current(), _blobDatas[i].speedScale); + const auto alpha = _blobDatas[i].alpha; + if (alpha != 1.) { + p.setOpacity(opacity * alpha); + } + _blobs[i].paint(p, brush); + } + _lastUpdateTime = crl::now(); +} + +} // namespace Ui::Paint diff --git a/ui/paint/blobs.h b/ui/paint/blobs.h new file mode 100644 index 0000000..6d53eab --- /dev/null +++ b/ui/paint/blobs.h @@ -0,0 +1,50 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#pragma once + +#include "ui/effects/animation_value.h" +#include "ui/paint/blob.h" + +class Painter; + +namespace Ui::Paint { + +class Blobs final { +public: + struct BlobData { + int segmentsCount = 0; + float minScale = 0; + float minRadius = 0; + float maxRadius = 0; + float speedScale = 0; + float alpha = 0; + }; + + Blobs( + std::vector blobDatas, + float levelDuration, + float maxLevel); + + void setLevel(float value); + void paint(Painter &p, const QBrush &brush); + + [[nodiscard]] float maxRadius() const; + +private: + void init(); + + const float _maxLevel; + + std::vector _blobDatas; + std::vector _blobs; + + crl::time _lastUpdateTime = 0; + anim::continuous_value _levelValue; + +}; + +} // namespace Ui::Paint