aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-09-12 01:29:32 +0200
committerFederico Angelilli <code@fedang.net>2024-09-12 01:29:32 +0200
commitbd8dbe03ead6c73f28df517f8873675108277bf5 (patch)
tree3a63ef377a599d7b9cddc4e2e3184f8defe29756
parent2907d743760f74a01a77dca91c4f74ac849517b5 (diff)
Add effects
-rw-r--r--comet.conf6
-rw-r--r--src/block.c2
-rw-r--r--src/block.h1
-rw-r--r--src/comet.c2
-rw-r--r--src/effect.c52
-rw-r--r--src/effect.h29
-rw-r--r--src/event.c5
-rw-r--r--src/layout.c25
-rw-r--r--src/util.c47
-rw-r--r--src/util.h10
10 files changed, 169 insertions, 10 deletions
diff --git a/comet.conf b/comet.conf
index 2d6a6d5..a405f74 100644
--- a/comet.conf
+++ b/comet.conf
@@ -20,10 +20,10 @@
[block.try]
type = text
text-color = #a123fc
- text = ""
+ text = "a"
color = #fff
- ;x-padding = 10
- y-padding = 10
+ x-padding = 2
+ y-padding = 2
[block.perf]
type = group
diff --git a/src/block.c b/src/block.c
index d0b66c9..29a8394 100644
--- a/src/block.c
+++ b/src/block.c
@@ -9,7 +9,7 @@ void block_update(block_t *block)
if (block->update_cb != NULL) {
struct timespec now, diff;
timespec_get(&now, TIME_UTC);
- diff = timespec_diff(block->update_last, now);
+ diff = timespec_diff(now, block->update_last);
if (timespec_greater(diff, block->update_interval)) {
log_value_trace("Updating block",
diff --git a/src/block.h b/src/block.h
index 4254355..6eeb0c0 100644
--- a/src/block.h
+++ b/src/block.h
@@ -52,6 +52,7 @@ struct block {
block_update_t update_cb;
block_event_t event_cb;
block_finalize_t finalize_cb;
+ struct effect *effect;
color_t color;
color_t line_color;
unsigned int line_width;
diff --git a/src/comet.c b/src/comet.c
index 6fccb3d..a539015 100644
--- a/src/comet.c
+++ b/src/comet.c
@@ -124,7 +124,7 @@ int main(int argc, char **argv)
layout_free(&layout);
timespec_get(&end, TIME_UTC);
- diff = timespec_diff(timespec_diff(end, start), rate);
+ diff = timespec_diff(rate, timespec_diff(end, start));
nanosleep(&diff, NULL);
}
diff --git a/src/effect.c b/src/effect.c
new file mode 100644
index 0000000..ae44c68
--- /dev/null
+++ b/src/effect.c
@@ -0,0 +1,52 @@
+#include <math.h>
+
+#include "effect.h"
+#include "any_log.h"
+
+double cubic_bezier(double x, double a, double b, double c, double d)
+{
+ const double t = 1 - x;
+ return a * (t * t * t) + 3 * b * (t * t * x) + 3 * c * (t * x * x) + d * (x * x * x);
+}
+
+static void effect_pulse_pre(effect_t *effect, layout_t *layout, cairo_t *cr)
+{
+ struct timespec now;
+ timespec_get(&now, TIME_UTC);
+
+ // After half the duration we invert direction
+ struct timespec midpoint = timespec_div(effect->duration, 2);
+ struct timespec diff = timespec_diff(now, effect->start);
+
+ double t = timespec_greater(midpoint, diff)
+ ? (double)timespec_to_ms(diff) / timespec_to_ms(midpoint)
+ : 1.0 - (double)timespec_to_ms(timespec_diff(diff, midpoint)) / timespec_to_ms(midpoint);
+
+ // Make it customizable
+ double s = cubic_bezier(t, 0.19, 1.0, 0.22, 1.0);
+
+ // Make it a parameter
+ const double amplitude = 0.12;
+
+ // FIXME: The intent was to scale the animation for long blocks, but it needs more love
+ //
+ int x_max = amplitude * (layout->height + (layout->width / (double)layout->height) - 1);
+ int y_max = amplitude * layout->height;
+
+ layout->x_padding = layout->block->x_padding + x_max * s;
+ layout->y_padding = layout->block->y_padding + y_max * s;
+}
+
+effect_t *effect_pulse(struct timespec duration)
+{
+ effect_t *effect = calloc(1, sizeof(effect_t));
+ effect->type = EFFECT_PULSE;
+ effect->duration = duration;
+ effect->pre = effect_pulse_pre;
+ return effect;
+}
+
+void effect_free(effect_t *effect)
+{
+ free(effect);
+}
diff --git a/src/effect.h b/src/effect.h
new file mode 100644
index 0000000..b6c6282
--- /dev/null
+++ b/src/effect.h
@@ -0,0 +1,29 @@
+#ifndef COMET_EFFECT_H
+#define COMET_EFFECT_H
+
+#include <cairo.h>
+
+#include "util.h"
+#include "layout.h"
+
+typedef enum {
+ EFFECT_PULSE,
+} effect_type_t;
+
+typedef struct effect effect_t;
+
+typedef void (*effect_render_t)(effect_t *effect, layout_t *layout, cairo_t *cr);
+
+struct effect {
+ effect_type_t type;
+ struct timespec start;
+ struct timespec duration;
+ effect_render_t pre;
+ effect_render_t post;
+};
+
+effect_t *effect_pulse(struct timespec duration);
+
+void effect_free(effect_t *effect);
+
+#endif
diff --git a/src/event.c b/src/event.c
index 0942fa1..a433fba 100644
--- a/src/event.c
+++ b/src/event.c
@@ -3,6 +3,7 @@
#include "util.h"
#include "layout.h"
#include "event.h"
+#include "effect.h"
#include "any_log.h"
const char *even_type_to_string(event_type_t type)
@@ -31,6 +32,10 @@ static bool event_click(layout_t *layout, event_t event)
return true;
}
+ if (layout->block->effect == NULL) {
+ layout->block->effect = effect_pulse(timespec_from_ms(200));
+ }
+
block_event_t event_cb = layout->block->event_cb;
log_value_debug("Block was clicked",
"s:type", even_type_to_string(event.type),
diff --git a/src/layout.c b/src/layout.c
index 92e6469..3ebbcce 100644
--- a/src/layout.c
+++ b/src/layout.c
@@ -5,6 +5,7 @@
#include "any_log.h"
#include "layout.h"
+#include "effect.h"
void layout_init(layout_t *layout, block_t *block, layout_info_t info)
{
@@ -73,6 +74,22 @@ void layout_init(layout_t *layout, block_t *block, layout_info_t info)
void layout_render(layout_t *layout, cairo_t *cr)
{
+ effect_t *effect = layout->block->effect;
+ if (effect != NULL) {
+ struct timespec now;
+ timespec_get(&now, TIME_UTC);
+
+ if (timespec_zero(effect->start))
+ effect->start = now;
+ else if (timespec_greater(now, timespec_add(effect->start, effect->duration)))
+ layout->block->effect = NULL;
+ }
+
+ // Pre-processing effects
+ if (effect != NULL && effect->pre != NULL) {
+ effect->pre(effect, layout, cr);
+ }
+
double degree = M_PI / 180.0;
int radius = layout->height / 2 - layout->y_padding;
int line_radius = radius - layout->block->line_width / 2;
@@ -117,6 +134,14 @@ void layout_render(layout_t *layout, cairo_t *cr)
pango_cairo_update_layout(cr, layout->pl);
pango_cairo_show_layout(cr, layout->pl);
}
+
+ // Post-processing effects
+ if (effect != NULL && effect->post != NULL) {
+ effect->post(effect, layout, cr);
+ }
+
+ if (layout->block->effect == NULL && effect != NULL)
+ effect_free(effect);
}
void layout_free(layout_t *layout)
diff --git a/src/util.c b/src/util.c
index 805d397..301222a 100644
--- a/src/util.c
+++ b/src/util.c
@@ -28,14 +28,46 @@ void color_print(FILE *stream, color_t *color)
fprintf(stream, "#%02x%02x%02x%02x", r, g, b, a);
}
+struct timespec timespec_from_ms(long ms)
+{
+ struct timespec ts = {
+ .tv_sec = ms / 1000,
+ .tv_nsec = (ms % 1000) * 1000000ul,
+ };
+ return ts;
+}
+
+long timespec_to_ms(struct timespec ts)
+{
+ return (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000ul);
+}
+
struct timespec timespec_diff(struct timespec a, struct timespec b)
{
- bool over = (b.tv_nsec - a.tv_nsec) < 0;
- struct timespec diff = {
- .tv_sec = b.tv_sec - a.tv_sec - over,
- .tv_nsec = b.tv_nsec - a.tv_nsec + over * 1000000000ul,
+ bool over = (a.tv_nsec - b.tv_nsec) < 0;
+ struct timespec ts = {
+ .tv_sec = a.tv_sec - b.tv_sec - over,
+ .tv_nsec = a.tv_nsec - b.tv_nsec + over * 1000000000ul,
};
- return diff;
+ return ts;
+}
+
+struct timespec timespec_add(struct timespec a, struct timespec b)
+{
+ bool over = (a.tv_nsec + b.tv_nsec) > 1000000000ul;
+ struct timespec ts = {
+ .tv_sec = a.tv_sec + b.tv_sec + over,
+ .tv_nsec = a.tv_nsec + b.tv_nsec - over * 1000000000ul,
+ };
+ return ts;
+}
+
+struct timespec timespec_div(struct timespec ts, int n)
+{
+ ts.tv_nsec /= n;
+ ts.tv_nsec += ((ts.tv_sec % n) * 1000000000ul) / n;
+ ts.tv_sec /= n;
+ return ts;
}
bool timespec_greater(struct timespec a, struct timespec b)
@@ -44,6 +76,11 @@ bool timespec_greater(struct timespec a, struct timespec b)
|| (a.tv_sec == b.tv_sec && a.tv_nsec > b.tv_nsec);
}
+bool timespec_zero(struct timespec ts)
+{
+ return ts.tv_sec == 0 && ts.tv_nsec == 0;
+}
+
void timespec_print(FILE *stream, struct timespec *ts)
{
fprintf(stream, "%ld.%.9ld", ts->tv_sec, ts->tv_nsec);
diff --git a/src/util.h b/src/util.h
index 770790d..0e28006 100644
--- a/src/util.h
+++ b/src/util.h
@@ -29,10 +29,20 @@ char *color_to_string(color_t *color);
void color_print(FILE *stream, color_t *color);
+struct timespec timespec_from_ms(long ms);
+
+long timespec_to_ms(struct timespec ts);
+
struct timespec timespec_diff(struct timespec a, struct timespec b);
+struct timespec timespec_add(struct timespec a, struct timespec b);
+
+struct timespec timespec_div(struct timespec ts, int n);
+
bool timespec_greater(struct timespec a, struct timespec b);
+bool timespec_zero(struct timespec ts);
+
void timespec_print(FILE *stream, struct timespec *ts);
// Check if point (px, py) is inside a rectangle in (x, y), (x+w, y), (x, y+h) and (w+h, y+h)