#pragma once #include "modern-qt/utility/animation/state/accessor.hh" #include "modern-qt/utility/animation/transition.hh" #include #include #include #include #include #include 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(); 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>> ripples; Animatable& animatable; double speed; }; }