mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 22:28:24 +02:00
Implement simple easing curves
This commit is contained in:
37
kitty/animation.c
Normal file
37
kitty/animation.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* animation.c
|
||||
* Copyright (C) 2024 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#include "animation.h"
|
||||
#include <stdbool.h>
|
||||
#include "data-types.h"
|
||||
|
||||
static double
|
||||
unit_value(double x) { return MAX(0., MIN(x, 1.)); }
|
||||
|
||||
double
|
||||
linear_easing_curve(easing_curve_parameters p, double val) {
|
||||
for (size_t i = p.count - 1; i-- > 0;) if (p.positions[i] <= val) return p.params[i];
|
||||
return p.params[0];
|
||||
}
|
||||
|
||||
double
|
||||
cubic_bezier_easing_curve(easing_curve_parameters p, double t) {
|
||||
const double u = 1. - t, uu = u * u, uuu = uu * u, tt = t * t, ttt = tt * t;
|
||||
// p0 is start, p3 is end. p1, p2 are control points
|
||||
return uuu * p.params[0] + 3 * uu * t * p.params[1] + 3 * u * tt * p.params[2] + ttt * p.params[3];
|
||||
}
|
||||
|
||||
double
|
||||
apply_easing_curve(const Animation *a, double val) {
|
||||
if (a->first_half.curve) {
|
||||
if (a->second_half.curve) {
|
||||
if (val <= 0.5) return unit_value(a->first_half.curve(a->first_half.params, 2 * val));
|
||||
return unit_value(a->second_half.curve(a->second_half.params, 2 * (val - 0.5)));
|
||||
} else return unit_value(a->first_half.curve(a->first_half.params, val));
|
||||
} else return (val <= 0.5) ? 1. : 0.;
|
||||
}
|
||||
|
||||
28
kitty/animation.h
Normal file
28
kitty/animation.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* animation.h
|
||||
* Copyright (C) 2024 Kovid Goyal <kovid at kovidgoyal.net>
|
||||
*
|
||||
* Distributed under terms of the GPL3 license.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct easing_curve_parameters {
|
||||
size_t count;
|
||||
const double *params, *positions;
|
||||
} easing_curve_parameters;
|
||||
|
||||
typedef double(*easing_curve)(easing_curve_parameters, double);
|
||||
|
||||
typedef struct Animation {
|
||||
struct {
|
||||
easing_curve_parameters params;
|
||||
easing_curve curve;
|
||||
} first_half, second_half;
|
||||
} Animation;
|
||||
|
||||
double linear_easing_curve(easing_curve_parameters, double);
|
||||
double cubic_bezier_easing_curve(easing_curve_parameters, double);
|
||||
double apply_easing_curve(const Animation *a, double t /* must be between 0 and 1*/);
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "screen.h"
|
||||
#include "fonts.h"
|
||||
#include "monotonic.h"
|
||||
#include "animation.h"
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@@ -673,18 +674,20 @@ collect_cursor_info(CursorRenderInfo *ans, Window *w, monotonic_t now, OSWindow
|
||||
if (rd->screen->scrolled_by || !screen_is_cursor_visible(rd->screen)) return cursor_needs_render(w);
|
||||
monotonic_t time_since_start_blink = now - os_window->cursor_blink_zero_time;
|
||||
bool cursor_blinking = OPT(cursor_blink_interval) > 0 && !cursor->non_blinking && os_window->is_focused && (OPT(cursor_stop_blinking_after) == 0 || time_since_start_blink <= OPT(cursor_stop_blinking_after));
|
||||
bool do_draw_cursor = true;
|
||||
if (cursor_blinking) {
|
||||
int t = monotonic_t_to_ms(time_since_start_blink);
|
||||
int d = monotonic_t_to_ms(OPT(cursor_blink_interval));
|
||||
int n = t / d;
|
||||
do_draw_cursor = n % 2 == 0 ? true : false;
|
||||
monotonic_t bucket = ms_to_monotonic_t((monotonic_t)(n + 1) * d);
|
||||
monotonic_t delay = bucket - time_since_start_blink;
|
||||
set_maximum_wait(delay);
|
||||
}
|
||||
if (!do_draw_cursor) { ans->opacity = 0; return cursor_needs_render(w); }
|
||||
ans->opacity = 1;
|
||||
if (cursor_blinking) {
|
||||
if (OPT(animation.cursor).first_half.curve) {
|
||||
monotonic_t den = OPT(cursor_blink_interval) * 2;
|
||||
monotonic_t time_into_cycle = time_since_start_blink % den;
|
||||
double frac_into_cycle = (double)time_into_cycle / (double)den;
|
||||
ans->opacity = (float)apply_easing_curve(&OPT(animation.cursor), frac_into_cycle);
|
||||
set_maximum_wait(ms_to_monotonic_t(75));
|
||||
} else {
|
||||
monotonic_t n = time_since_start_blink / OPT(cursor_blink_interval);
|
||||
ans->opacity = n % 2 == 0 ? 1 : 0;
|
||||
set_maximum_wait((n + 1) * OPT(cursor_blink_interval) - time_since_start_blink);
|
||||
}
|
||||
}
|
||||
ans->shape = cursor->shape ? cursor->shape : OPT(cursor_shape);
|
||||
ans->is_focused = os_window->is_focused;
|
||||
return cursor_needs_render(w);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "data-types.h"
|
||||
#include "animation.h"
|
||||
#include "screen.h"
|
||||
#include "monotonic.h"
|
||||
#include "window_logo.h"
|
||||
@@ -118,6 +118,7 @@ typedef struct {
|
||||
hb_feature_t *features;
|
||||
} *entries;
|
||||
} font_features;
|
||||
struct { Animation cursor; } animation;
|
||||
} Options;
|
||||
|
||||
typedef struct WindowLogoRenderData {
|
||||
|
||||
Reference in New Issue
Block a user