Files
screensaver/modules/Polygon/Polygon.cpp

112 lines
2.6 KiB
C++

#include "Polygon.hpp"
#include <cairo/cairo.h>
#include <libsccolor.hpp>
#include <libscscreensaver.hpp>
#include <vector>
struct Point {
double x;
double y;
double speed_x;
double speed_y;
};
class Polygon : public ScreensaverPlugin {
public:
Polygon() = default;
~Polygon() = default;
void configure() override;
void update() override;
void render() override;
std::string version() const override;
void size_changed() override;
private:
int _num_points {};
double _min_speed {0.2};
double _max_speed {2.0};
double _stroke_width {1.0};
Color _stroke_color {"#FFFFFF"};
Color _fill_color {"#606060"};
std::vector<Point> _points;
double _hue;
};
ScreensaverPlugin *create_instance() { return new Polygon; }
void Polygon::configure() {
_num_points = _j["num-points"];
_min_speed = _j["min-speed"];
_max_speed = _j["max-speed"];
_stroke_width = _j["stroke-width"];
for (int i = 0; i < _num_points; ++i) {
Point p;
p.x = random_x();
p.y = random_y();
p.speed_x = random_between(_min_speed, _max_speed);
p.speed_x *= random_bool() ? 1 : -1;
p.speed_y = random_between(_min_speed, _max_speed);
p.speed_y *= random_bool() ? 1 : -1;
_points.push_back(p);
}
_hue = random_between(0.0, 360.0);
}
void Polygon::size_changed() {
for (Point &p : _points) {
p.x = random_x();
p.y = random_y();
}
}
std::string Polygon::version() const { return "1.1.0"; }
void Polygon::update() {
// update points
for (Point& p : _points) {
p.x += p.speed_x;
if (p.x < 0 || p.x > _r.width) {
p.speed_x *= -1;
p.x += p.speed_x;
}
p.y += p.speed_y;
if (p.y < 0 || p.y > _r.height) {
p.speed_y *= -1;
p.y += p.speed_y;
}
}
// update hue
_hue += 0.5;
if (_hue >= 360.0) {
_hue -= 360.0;
}
// construct stroke and fill colors
HSB hsb;
hsb.h = _hue;
hsb.s = 1.0;
hsb.b = 0.1;
_fill_color = hsb;
hsb.b = 0.7;
_stroke_color = hsb;
}
void Polygon::render() {
make_black();
Point first = _points[0];
cairo_new_path(_c);
cairo_move_to(_c, first.x, first.y);
for (size_t i = 1; i < _points.size(); ++i) {
Point& p = _points[i];
cairo_line_to(_c, p.x, p.y);
}
cairo_close_path(_c);
RGB c = RGB(_stroke_color);
cairo_set_source_rgb(_c, c.r, c.g, c.b);
cairo_set_line_width(_c, _stroke_width);
cairo_stroke_preserve(_c);
RGB f = RGB(_fill_color);
cairo_set_source_rgb(_c, f.r, f.g, f.b);
cairo_fill(_c);
}