72 lines
2.0 KiB
C++
72 lines
2.0 KiB
C++
#pragma once
|
|
|
|
#include "modern-qt/utility/animation/state/accessor.hh"
|
|
#include "modern-qt/utility/animation/transition.hh"
|
|
|
|
#include <QColor>
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QPointF>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
namespace creeper {
|
|
|
|
struct WaterRippleState : public NormalAccessor {
|
|
using ValueT = double;
|
|
|
|
QPointF origin;
|
|
double value = 0.0;
|
|
double target = 0.0;
|
|
double speed = 1.0;
|
|
|
|
auto update() noexcept -> bool {
|
|
value += speed;
|
|
return value < target;
|
|
}
|
|
};
|
|
|
|
class WaterRippleRenderer {
|
|
public:
|
|
explicit WaterRippleRenderer(Animatable& core, double speed)
|
|
: animatable { core }
|
|
, speed { speed } { }
|
|
|
|
auto clicked(const QPointF& origin, double max_distance) noexcept -> void {
|
|
auto state = std::make_shared<WaterRippleState>();
|
|
state->origin = origin;
|
|
state->speed = speed;
|
|
state->target = max_distance;
|
|
|
|
auto ripple = make_transition(animatable, state);
|
|
ripple->transition_to(max_distance);
|
|
ripples.push_back(std::move(ripple));
|
|
}
|
|
|
|
auto renderer(const QPainterPath& clip_path, const QColor& water_color) noexcept {
|
|
return [&, this](QPainter& painter) {
|
|
std::erase_if(ripples, [&](const auto& ripple) {
|
|
const auto& state = ripple->get_state();
|
|
const auto opacity = 1.0 - state.value / state.target;
|
|
|
|
painter.setRenderHint(QPainter::Antialiasing);
|
|
painter.setClipPath(clip_path);
|
|
painter.setOpacity(opacity);
|
|
painter.setPen(Qt::NoPen);
|
|
painter.setBrush(water_color);
|
|
painter.drawEllipse(state.origin, state.value, state.value);
|
|
painter.setOpacity(1.0);
|
|
|
|
return state.value >= state.target;
|
|
});
|
|
};
|
|
}
|
|
|
|
private:
|
|
std::vector<std::unique_ptr<TransitionValue<WaterRippleState>>> ripples;
|
|
Animatable& animatable;
|
|
double speed;
|
|
};
|
|
|
|
}
|