@kecan0406/ttheme 1.0.34 → 1.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -28
- package/bin/ttheme.js +125 -125
- package/bin/ttheme.js.map +1 -1
- package/dist/manifest.json +1 -16
- package/package.json +2 -4
- package/shell/adapters/ghostty.zsh +1 -1
- package/shell/launch-tab.zsh +1 -1
- package/shell/ttheme.zsh +16 -1
- package/dist/ghostty/ttheme.conf +0 -9
- package/ghostty/shaders/LICENSE +0 -21
- package/ghostty/shaders/README.md +0 -31
- package/ghostty/shaders/cursor_tail.glsl +0 -243
- package/ghostty/shaders/ripple_cursor.glsl +0 -141
package/dist/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.0.
|
|
2
|
+
"version": "1.0.35",
|
|
3
3
|
"gate": [
|
|
4
4
|
{
|
|
5
5
|
"rule": "foreground",
|
|
@@ -46,21 +46,6 @@
|
|
|
46
46
|
"margin": 0.03,
|
|
47
47
|
"stands": 12
|
|
48
48
|
},
|
|
49
|
-
"font": {
|
|
50
|
-
"family": "JetBrainsMono Nerd Font",
|
|
51
|
-
"size": 14,
|
|
52
|
-
"codepointMap": [
|
|
53
|
-
{
|
|
54
|
-
"range": "U+AC00-U+D7A3",
|
|
55
|
-
"family": "D2Coding"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
"range": "U+3130-U+318F",
|
|
59
|
-
"family": "D2Coding"
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
},
|
|
63
|
-
"shader": "cursor_tail.glsl",
|
|
64
49
|
"palettes": [
|
|
65
50
|
{
|
|
66
51
|
"name": "neutral",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kecan0406/ttheme",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.35",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ttheme": "bin/ttheme.js"
|
|
@@ -8,10 +8,8 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"bin",
|
|
10
10
|
"dist/manifest.json",
|
|
11
|
-
"dist/ghostty/ttheme.conf",
|
|
12
11
|
"shell",
|
|
13
|
-
"!shell/check.zsh"
|
|
14
|
-
"ghostty/shaders"
|
|
12
|
+
"!shell/check.zsh"
|
|
15
13
|
],
|
|
16
14
|
"description": "Character terminal palettes for Ghostty, kitty, Alacritty, WezTerm, iTerm2, Windows Terminal and Warp",
|
|
17
15
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@ __tt_shown() {
|
|
|
30
30
|
__tt_bg_cells() {
|
|
31
31
|
local fd saved resp="" line c v f
|
|
32
32
|
local -i px=2 py=2 fs=0 sc=2
|
|
33
|
-
for f in ${XDG_CONFIG_HOME:-$HOME/.config}/ghostty/config
|
|
33
|
+
for f in ${XDG_CONFIG_HOME:-$HOME/.config}/ghostty/config; do
|
|
34
34
|
[[ -r $f ]] || continue
|
|
35
35
|
for line in "${(@f)$(<$f)}"; do
|
|
36
36
|
v=${${line#*=}// /}
|
package/shell/launch-tab.zsh
CHANGED
package/shell/ttheme.zsh
CHANGED
|
@@ -13,12 +13,27 @@ __tt_palettes_load() {
|
|
|
13
13
|
__tt_fresh() {
|
|
14
14
|
local -a at
|
|
15
15
|
local was=$TTHEME_STARTUP
|
|
16
|
-
zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/palettes.zsh 2>/dev/null
|
|
16
|
+
if ! zstat -F %s.%N -A at +mtime -- $TTHEME_HOME/palettes.zsh 2>/dev/null; then
|
|
17
|
+
[[ -e $TTHEME_HOME ]] || __tt_gone
|
|
18
|
+
return 0
|
|
19
|
+
fi
|
|
17
20
|
[[ $at[1] == "$TTHEME_PALETTES_AT" ]] && return 0
|
|
18
21
|
__tt_palettes_load && __tt_reloaded
|
|
19
22
|
[[ -n $was && -z $TTHEME_STARTUP && -n $TTHEME_SPEC ]] && __tt_active && __tt_off_here
|
|
20
23
|
}
|
|
21
24
|
|
|
25
|
+
__tt_gone() {
|
|
26
|
+
local bg=${TTHEME_SPEC%% *} hook
|
|
27
|
+
TTHEME_SPEC=
|
|
28
|
+
__tt_reload
|
|
29
|
+
__tt_reset_reloaded $bg
|
|
30
|
+
print -n $'\e[?1004l'
|
|
31
|
+
for hook in precmd:__tt_fresh precmd:__tt_precmd precmd:__tt_unmux preexec:__tt_preexec preexec:__tt_mux chpwd:__tt_chpwd; do
|
|
32
|
+
add-zsh-hook -d ${hook%%:*} ${hook#*:}
|
|
33
|
+
done
|
|
34
|
+
unfunction ttheme
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
__tt_off_here() {
|
|
23
38
|
local bg=${TTHEME_SPEC%% *}
|
|
24
39
|
TTHEME_SPEC=
|
package/dist/ghostty/ttheme.conf
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# ttheme — shared font and shader, identical for every palette.
|
|
2
|
-
# Pick colors with: theme = <palette>
|
|
3
|
-
font-family = JetBrainsMono Nerd Font
|
|
4
|
-
font-size = 14
|
|
5
|
-
font-codepoint-map = U+AC00-U+D7A3=D2Coding
|
|
6
|
-
font-codepoint-map = U+3130-U+318F=D2Coding
|
|
7
|
-
|
|
8
|
-
custom-shader = ~/.config/ghostty/shaders/cursor_tail.glsl
|
|
9
|
-
custom-shader-animation = true
|
package/ghostty/shaders/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Sahaj Bhatt
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# Shaders
|
|
2
|
-
|
|
3
|
-
Ghostty is the only Tier-1 terminal that runs GLSL, so nothing here applies to
|
|
4
|
-
kitty, Alacritty, WezTerm or iTerm2. A theme picks one with `[ghostty] shader`
|
|
5
|
-
in its TOML; the built config wires it up as `custom-shader`.
|
|
6
|
-
|
|
7
|
-
Shaders apply to the whole Ghostty instance, not per tab — so switching a tab's
|
|
8
|
-
palette does not switch its shader.
|
|
9
|
-
|
|
10
|
-
## Included
|
|
11
|
-
|
|
12
|
-
Both come from [sahaj-b/ghostty-cursor-shaders][sahaj] (MIT — see `LICENSE`).
|
|
13
|
-
|
|
14
|
-
| File | Effect | Local change |
|
|
15
|
-
|---|---|---|
|
|
16
|
-
| `cursor_tail.glsl` | comet trail behind the cursor | `DURATION` 0.09 → 0.05 (shorter tail) |
|
|
17
|
-
| `ripple_cursor.glsl` | expanding ring on cursor move | fixed `COLOR` → theme cursor via `iCurrentCursorColor` |
|
|
18
|
-
|
|
19
|
-
Trail length lives in `DURATION` and `MAX_TRAIL_LENGTH` inside the file.
|
|
20
|
-
|
|
21
|
-
## Not included
|
|
22
|
-
|
|
23
|
-
These are in use locally but ship no license, so they are not redistributed
|
|
24
|
-
here. Drop them into this directory yourself if you want them:
|
|
25
|
-
|
|
26
|
-
- `bloom.glsl`, `bloom-subtle.glsl` — [qwerasd205's gist][bloom]
|
|
27
|
-
- `gradient-background.glsl`, `animated-gradient-shader.glsl` — [unkn0wncode][unk]
|
|
28
|
-
|
|
29
|
-
[sahaj]: https://github.com/sahaj-b/ghostty-cursor-shaders
|
|
30
|
-
[bloom]: https://gist.github.com/qwerasd205/c3da6c610c8ffe17d6d2d3cc7068f17f
|
|
31
|
-
[unk]: https://github.com/unkn0wncode
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
// cursor_tail.glsl — from sahaj-b/ghostty-cursor-shaders (MIT).
|
|
2
|
-
// https://github.com/sahaj-b/ghostty-cursor-shaders
|
|
3
|
-
// See LICENSE in this directory. Local change: DURATION tuned.
|
|
4
|
-
|
|
5
|
-
// sRGB -> Linear conversion (needed because Ghostty passes sRGB values but the shader pipeline operates in linear color space)
|
|
6
|
-
vec3 sRGBToLinear(vec3 c) {
|
|
7
|
-
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), c));
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// --- CONFIGURATION ---
|
|
11
|
-
vec4 TRAIL_COLOR = vec4(sRGBToLinear(iCurrentCursorColor.rgb), iCurrentCursorColor.a); // for custom color: vec4(0.2, 0.6, 1.0, 0.5); (wrap in sRGBToLinear for correct brightness)
|
|
12
|
-
const float DURATION = 0.05; // in seconds
|
|
13
|
-
const float MAX_TRAIL_LENGTH = 0.2;
|
|
14
|
-
const float THRESHOLD_MIN_DISTANCE = 1.5; // min distance to show trail (units of cursor width)
|
|
15
|
-
const float BLUR = 2.0; // blur size in pixels (for antialiasing)
|
|
16
|
-
|
|
17
|
-
// --- CONSTANTS for easing functions ---
|
|
18
|
-
const float PI = 3.14159265359;
|
|
19
|
-
const float C1_BACK = 1.70158;
|
|
20
|
-
const float C2_BACK = C1_BACK * 1.525;
|
|
21
|
-
const float C3_BACK = C1_BACK + 1.0;
|
|
22
|
-
const float C4_ELASTIC = (2.0 * PI) / 3.0;
|
|
23
|
-
const float C5_ELASTIC = (2.0 * PI) / 4.5;
|
|
24
|
-
const float SPRING_STIFFNESS = 9.0;
|
|
25
|
-
const float SPRING_DAMPING = 0.9;
|
|
26
|
-
|
|
27
|
-
// --- EASING FUNCTIONS ---
|
|
28
|
-
|
|
29
|
-
// // Linear
|
|
30
|
-
// float ease(float x) {
|
|
31
|
-
// return x;
|
|
32
|
-
// }
|
|
33
|
-
|
|
34
|
-
// // EaseOutQuad
|
|
35
|
-
// float ease(float x) {
|
|
36
|
-
// return 1.0 - (1.0 - x) * (1.0 - x);
|
|
37
|
-
// }
|
|
38
|
-
|
|
39
|
-
// // EaseOutCubic
|
|
40
|
-
// float ease(float x) {
|
|
41
|
-
// return 1.0 - pow(1.0 - x, 3.0);
|
|
42
|
-
// }
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// // EaseOutQuart
|
|
46
|
-
// float ease(float x) {
|
|
47
|
-
// return 1.0 - pow(1.0 - x, 4.0);
|
|
48
|
-
// }
|
|
49
|
-
|
|
50
|
-
// // EaseOutQuint
|
|
51
|
-
// float ease(float x) {
|
|
52
|
-
// return 1.0 - pow(1.0 - x, 5.0);
|
|
53
|
-
// }
|
|
54
|
-
|
|
55
|
-
// // EaseOutSine
|
|
56
|
-
// float ease(float x) {
|
|
57
|
-
// return sin((x * PI) / 2.0);
|
|
58
|
-
// }
|
|
59
|
-
|
|
60
|
-
// // EaseOutExpo
|
|
61
|
-
// float ease(float x) {
|
|
62
|
-
// return x == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * x);
|
|
63
|
-
// }
|
|
64
|
-
|
|
65
|
-
// EaseOutCirc
|
|
66
|
-
float ease(float x) {
|
|
67
|
-
return sqrt(1.0 - pow(x - 1.0, 2.0));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// // EaseOutBack
|
|
71
|
-
// float ease(float x) {
|
|
72
|
-
// return 1.0 + C3_BACK * pow(x - 1.0, 3.0) + C1_BACK * pow(x - 1.0, 2.0);
|
|
73
|
-
// }
|
|
74
|
-
|
|
75
|
-
// // EaseOutElastic
|
|
76
|
-
// float ease(float x) {
|
|
77
|
-
// return x == 0.0 ? 0.0
|
|
78
|
-
// : x == 1.0 ? 1.0
|
|
79
|
-
// : pow(2.0, -10.0 * x) * sin((x * 10.0 - 0.75) * C4_ELASTIC) + 1.0;
|
|
80
|
-
// }
|
|
81
|
-
|
|
82
|
-
// Parametric Spring
|
|
83
|
-
// float ease(float x) {
|
|
84
|
-
// x = clamp(x, 0.0, 1.0);
|
|
85
|
-
// float decay = exp(-SPRING_DAMPING * SPRING_STIFFNESS * x);
|
|
86
|
-
// float freq = sqrt(SPRING_STIFFNESS * (1.0 - SPRING_DAMPING * SPRING_DAMPING));
|
|
87
|
-
// float osc = cos(freq * 6.283185 * x) + (SPRING_DAMPING * sqrt(SPRING_STIFFNESS) / freq) * sin(freq * 6.283185 * x);
|
|
88
|
-
// return 1.0 - decay * osc;
|
|
89
|
-
// }
|
|
90
|
-
|
|
91
|
-
float getSdfRectangle(in vec2 p, in vec2 xy, in vec2 b)
|
|
92
|
-
{
|
|
93
|
-
vec2 d = abs(p - xy) - b;
|
|
94
|
-
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Based on Inigo Quilez's 2D distance functions article: https://iquilezles.org/articles/distfunctions2d/
|
|
98
|
-
// Potencially optimized by eliminating conditionals and loops to enhance performance and reduce branching
|
|
99
|
-
|
|
100
|
-
float seg(in vec2 p, in vec2 a, in vec2 b, inout float s, float d) {
|
|
101
|
-
vec2 e = b - a;
|
|
102
|
-
vec2 w = p - a;
|
|
103
|
-
vec2 proj = a + e * clamp(dot(w, e) / dot(e, e), 0.0, 1.0);
|
|
104
|
-
float segd = dot(p - proj, p - proj);
|
|
105
|
-
d = min(d, segd);
|
|
106
|
-
|
|
107
|
-
float c0 = step(0.0, p.y - a.y);
|
|
108
|
-
float c1 = 1.0 - step(0.0, p.y - b.y);
|
|
109
|
-
float c2 = 1.0 - step(0.0, e.x * w.y - e.y * w.x);
|
|
110
|
-
float allCond = c0 * c1 * c2;
|
|
111
|
-
float noneCond = (1.0 - c0) * (1.0 - c1) * (1.0 - c2);
|
|
112
|
-
float flip = mix(1.0, -1.0, step(0.5, allCond + noneCond));
|
|
113
|
-
s *= flip;
|
|
114
|
-
return d;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
float getSdfParallelogram(in vec2 p, in vec2 v0, in vec2 v1, in vec2 v2, in vec2 v3) {
|
|
118
|
-
float s = 1.0;
|
|
119
|
-
float d = dot(p - v0, p - v0);
|
|
120
|
-
|
|
121
|
-
d = seg(p, v0, v3, s, d);
|
|
122
|
-
d = seg(p, v1, v0, s, d);
|
|
123
|
-
d = seg(p, v2, v1, s, d);
|
|
124
|
-
d = seg(p, v3, v2, s, d);
|
|
125
|
-
|
|
126
|
-
return s * sqrt(d);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
vec2 normalize(vec2 value, float isPosition) {
|
|
130
|
-
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
float antialising(float distance) {
|
|
134
|
-
return 1. - smoothstep(0., normalize(vec2(BLUR, BLUR), 0.).x, distance);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
float determineIfTopRightIsLeading(vec2 a, vec2 b) {
|
|
138
|
-
float condition1 = step(b.x, a.x) * step(a.y, b.y); // a.x < b.x && a.y > b.y
|
|
139
|
-
float condition2 = step(a.x, b.x) * step(b.y, a.y); // a.x > b.x && a.y < b.y
|
|
140
|
-
|
|
141
|
-
// if neither condition is met, return 1 (else case)
|
|
142
|
-
return 1.0 - max(condition1, condition2);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
vec2 getRectangleCenter(vec4 rectangle) {
|
|
146
|
-
return vec2(rectangle.x + (rectangle.z / 2.), rectangle.y - (rectangle.w / 2.));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
|
151
|
-
#if !defined(WEB)
|
|
152
|
-
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
|
153
|
-
#endif
|
|
154
|
-
|
|
155
|
-
// normalization & setup(-1, 1 coords)
|
|
156
|
-
vec2 vu = normalize(fragCoord, 1.);
|
|
157
|
-
vec2 offsetFactor = vec2(-.5, 0.5);
|
|
158
|
-
|
|
159
|
-
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
|
160
|
-
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
|
161
|
-
|
|
162
|
-
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
|
163
|
-
vec2 centerCP = previousCursor.xy - (previousCursor.zw * offsetFactor);
|
|
164
|
-
|
|
165
|
-
vec2 delta = centerCP - centerCC;
|
|
166
|
-
float lineLength = length(delta);
|
|
167
|
-
|
|
168
|
-
float sdfCurrentCursor = getSdfRectangle(vu, centerCC, currentCursor.zw * 0.5);
|
|
169
|
-
|
|
170
|
-
vec4 newColor = vec4(fragColor);
|
|
171
|
-
|
|
172
|
-
float minDist = currentCursor.w * THRESHOLD_MIN_DISTANCE;
|
|
173
|
-
float progress = clamp((iTime - iTimeCursorChange) / DURATION, 0.0, 1.0);
|
|
174
|
-
if (lineLength > minDist) {
|
|
175
|
-
// ANIMATION logic
|
|
176
|
-
|
|
177
|
-
float head_eased = 0.0;
|
|
178
|
-
float tail_eased = 0.0;
|
|
179
|
-
|
|
180
|
-
float tail_delay_factor = MAX_TRAIL_LENGTH / lineLength;
|
|
181
|
-
|
|
182
|
-
float isLongMove = step(MAX_TRAIL_LENGTH, lineLength);
|
|
183
|
-
|
|
184
|
-
float head_eased_short = ease(progress);
|
|
185
|
-
float tail_eased_short = ease(smoothstep(tail_delay_factor, 1.0, progress));
|
|
186
|
-
float head_eased_long = 1.0;
|
|
187
|
-
float tail_eased_long = ease(progress);
|
|
188
|
-
|
|
189
|
-
head_eased = mix(head_eased_long, head_eased_short, isLongMove);
|
|
190
|
-
tail_eased = mix(tail_eased_long, tail_eased_short, isLongMove);
|
|
191
|
-
|
|
192
|
-
// detect straight moves
|
|
193
|
-
vec2 delta_abs = abs(centerCC - centerCP);
|
|
194
|
-
float threshold = 0.001;
|
|
195
|
-
float isHorizontal = step(delta_abs.y, threshold);
|
|
196
|
-
float isVertical = step(delta_abs.x, threshold);
|
|
197
|
-
float isStraightMove = max(isHorizontal, isVertical);
|
|
198
|
-
|
|
199
|
-
// -- Making the parallelogram sdf (diagonal move) --
|
|
200
|
-
|
|
201
|
-
// animate the TOP-LEFT corners
|
|
202
|
-
vec2 head_pos_tl = mix(previousCursor.xy, currentCursor.xy, head_eased);
|
|
203
|
-
vec2 tail_pos_tl = mix(previousCursor.xy, currentCursor.xy, tail_eased);
|
|
204
|
-
|
|
205
|
-
float isTopRightLeading = determineIfTopRightIsLeading(currentCursor.xy, previousCursor.xy);
|
|
206
|
-
float isBottomLeftLeading = 1.0 - isTopRightLeading;
|
|
207
|
-
|
|
208
|
-
// v0, v1 : "front" of the trail (head)
|
|
209
|
-
vec2 v0 = vec2(head_pos_tl.x + currentCursor.z * isTopRightLeading, head_pos_tl.y - currentCursor.w);
|
|
210
|
-
vec2 v1 = vec2(head_pos_tl.x + currentCursor.z * isBottomLeftLeading, head_pos_tl.y);
|
|
211
|
-
|
|
212
|
-
// v2, v3: "back" of the trail (tail)
|
|
213
|
-
vec2 v2 = vec2(tail_pos_tl.x + currentCursor.z * isBottomLeftLeading, tail_pos_tl.y);
|
|
214
|
-
vec2 v3 = vec2(tail_pos_tl.x + currentCursor.z * isTopRightLeading, tail_pos_tl.y - previousCursor.w);
|
|
215
|
-
|
|
216
|
-
float sdfTrail_diag = getSdfParallelogram(vu, v0, v1, v2, v3);
|
|
217
|
-
|
|
218
|
-
// -- Making the rectangle sdf (straight move) --
|
|
219
|
-
|
|
220
|
-
vec2 head_center = mix(centerCP, centerCC, head_eased);
|
|
221
|
-
vec2 tail_center = mix(centerCP, centerCC, tail_eased);
|
|
222
|
-
|
|
223
|
-
vec2 min_center = min(head_center, tail_center);
|
|
224
|
-
vec2 max_center = max(head_center, tail_center);
|
|
225
|
-
|
|
226
|
-
vec2 box_size = (max_center - min_center) + currentCursor.zw;
|
|
227
|
-
vec2 box_center = (min_center + max_center) * 0.5;
|
|
228
|
-
|
|
229
|
-
float sdfTrail_rect = getSdfRectangle(vu, box_center, box_size * 0.5);
|
|
230
|
-
|
|
231
|
-
// -- FINAL SELECTING AND DRAWING --
|
|
232
|
-
float sdfTrail = mix(sdfTrail_diag, sdfTrail_rect, isStraightMove);
|
|
233
|
-
|
|
234
|
-
vec4 trail = TRAIL_COLOR;
|
|
235
|
-
float trailAlpha = antialising(sdfTrail);
|
|
236
|
-
newColor = mix(newColor, trail, trailAlpha);
|
|
237
|
-
|
|
238
|
-
// punch hole
|
|
239
|
-
newColor = mix(newColor, fragColor, step(sdfCurrentCursor, 0.));
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
fragColor = newColor;
|
|
243
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
// ripple_cursor.glsl — from sahaj-b/ghostty-cursor-shaders (MIT).
|
|
2
|
-
// https://github.com/sahaj-b/ghostty-cursor-shaders
|
|
3
|
-
// See LICENSE in this directory. Local change: COLOR follows the theme cursor.
|
|
4
|
-
|
|
5
|
-
// sRGB -> Linear conversion (needed because Ghostty passes sRGB values but the shader pipeline operates in linear color space)
|
|
6
|
-
vec3 sRGBToLinear(vec3 c) {
|
|
7
|
-
return mix(c / 12.92, pow((c + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), c));
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// CONFIGURATION
|
|
11
|
-
const float DURATION = 0.15; // How long the ripple animates (seconds)
|
|
12
|
-
const float MAX_RADIUS = 0.05; // Max radius in normalized coords (0.5 = 1/4 screen height)
|
|
13
|
-
const float RING_THICKNESS = 0.02; // Ring width in normalized coords
|
|
14
|
-
const float CURSOR_WIDTH_CHANGE_THRESHOLD = 0.5; // Triggers ripple if cursor width changes by this fraction
|
|
15
|
-
vec4 COLOR = vec4(sRGBToLinear(iCurrentCursorColor.rgb), 1.0); // for custom color: vec4(0.35, 0.36, 0.44, 1.0)
|
|
16
|
-
const float BLUR = 3.0; // Blur level in pixels
|
|
17
|
-
const float ANIMATION_START_OFFSET = 0.0; // Start the ripple slightly progressed (0.0 - 1.0)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// Easing functions
|
|
21
|
-
float easeOutQuad(float t) {
|
|
22
|
-
return 1.0 - (1.0 - t) * (1.0 - t);
|
|
23
|
-
}
|
|
24
|
-
float easeInOutQuad(float t) {
|
|
25
|
-
return t < 0.5 ? 2.0 * t * t : 1.0 - pow(-2.0 * t + 2.0, 2.0) / 2.0;
|
|
26
|
-
}
|
|
27
|
-
float easeOutCubic(float t) {
|
|
28
|
-
return 1.0 - pow(1.0 - t, 3.0);
|
|
29
|
-
}
|
|
30
|
-
float easeOutQuart(float t) {
|
|
31
|
-
return 1.0 - pow(1.0 - t, 4.0);
|
|
32
|
-
}
|
|
33
|
-
float easeOutQuint(float t) {
|
|
34
|
-
return 1.0 - pow(1.0 - t, 5.0);
|
|
35
|
-
}
|
|
36
|
-
float easeOutExpo(float t) {
|
|
37
|
-
return t == 1.0 ? 1.0 : 1.0 - pow(2.0, -10.0 * t);
|
|
38
|
-
}
|
|
39
|
-
float easeOutCirc(float t) {
|
|
40
|
-
return sqrt(1.0 - pow(t - 1.0, 2.0));
|
|
41
|
-
}
|
|
42
|
-
float easeOutSine(float t) {
|
|
43
|
-
return sin((t * 3.1415916) / 2.0);
|
|
44
|
-
}
|
|
45
|
-
float easeOutElastic(float t) {
|
|
46
|
-
const float c4 = (2.0 * 3.1415916) / 3.0;
|
|
47
|
-
return t == 0.0 ? 0.0 : t == 1.0 ? 1.0 : pow(2.0, -10.0 * t) * sin((t * 10.0 - 0.75) * c4) + 1.0;
|
|
48
|
-
}
|
|
49
|
-
float easeOutBounce(float t) {
|
|
50
|
-
const float n1 = 7.5625;
|
|
51
|
-
const float d1 = 2.75;
|
|
52
|
-
if (t < 1.0 / d1) {
|
|
53
|
-
return n1 * t * t;
|
|
54
|
-
} else if (t < 2.0 / d1) {
|
|
55
|
-
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
|
56
|
-
} else if (t < 2.5 / d1) {
|
|
57
|
-
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
|
58
|
-
} else {
|
|
59
|
-
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
float easeOutBack(float t) {
|
|
63
|
-
const float c1 = 1.70158;
|
|
64
|
-
const float c3 = c1 + 1.0;
|
|
65
|
-
return 1.0 + c3 * pow(t - 1.0, 3.0) + c1 * pow(t - 1.0, 2.0);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Pulse fade functions
|
|
69
|
-
float easeOutPulse(float t) {
|
|
70
|
-
return t * (2.0 - t);
|
|
71
|
-
}
|
|
72
|
-
float exponentialDecayPulse(float t) {
|
|
73
|
-
return exp(-3.0 * t) * sin(t * 3.1415916);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
vec2 normalize(vec2 value, float isPosition) {
|
|
77
|
-
return (value * 2.0 - (iResolution.xy * isPosition)) / iResolution.y;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
void mainImage(out vec4 fragColor, in vec2 fragCoord){
|
|
81
|
-
#if !defined(WEB)
|
|
82
|
-
fragColor = texture(iChannel0, fragCoord.xy / iResolution.xy);
|
|
83
|
-
#endif
|
|
84
|
-
|
|
85
|
-
// Normalization & setup (-1 to 1 coords)
|
|
86
|
-
vec2 vu = normalize(fragCoord, 1.);
|
|
87
|
-
vec2 offsetFactor = vec2(-.5, 0.5);
|
|
88
|
-
|
|
89
|
-
vec4 currentCursor = vec4(normalize(iCurrentCursor.xy, 1.), normalize(iCurrentCursor.zw, 0.));
|
|
90
|
-
vec4 previousCursor = vec4(normalize(iPreviousCursor.xy, 1.), normalize(iPreviousCursor.zw, 0.));
|
|
91
|
-
|
|
92
|
-
vec2 centerCC = currentCursor.xy - (currentCursor.zw * offsetFactor);
|
|
93
|
-
|
|
94
|
-
float cellWidth = max(currentCursor.z, previousCursor.z); // width of the 'block' cursor
|
|
95
|
-
|
|
96
|
-
// check for significant width change
|
|
97
|
-
float widthChange = abs(currentCursor.z - previousCursor.z);
|
|
98
|
-
float widthThresholdNorm = cellWidth * CURSOR_WIDTH_CHANGE_THRESHOLD;
|
|
99
|
-
float isModeChange = step(widthThresholdNorm, widthChange);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
// ANIMATION
|
|
103
|
-
float rippleProgress = (iTime - iTimeCursorChange) / DURATION + ANIMATION_START_OFFSET;
|
|
104
|
-
// don't clamp yet; we need to know if it's > 1.0 (finished)
|
|
105
|
-
float isAnimating = 1.0 - step(1.0, rippleProgress); // progress < 1.0 ? 1.0: 0.0
|
|
106
|
-
|
|
107
|
-
if (isModeChange > 0.0 && isAnimating > 0.0) {
|
|
108
|
-
// Apply easing to progress
|
|
109
|
-
// float easedProgress = rippleProgress;
|
|
110
|
-
// float easedProgress = easeOutQuad(rippleProgress);
|
|
111
|
-
// float easedProgress = easeInOutQuad(rippleProgress);
|
|
112
|
-
// float easedProgress = easeOutCubic(rippleProgress);
|
|
113
|
-
// float easedProgress = easeOutQuart(rippleProgress);
|
|
114
|
-
// float easedProgress = easeOutQuint(rippleProgress);
|
|
115
|
-
// float easedProgress = easeOutExpo(rippleProgress);
|
|
116
|
-
float easedProgress = easeOutCirc(rippleProgress);
|
|
117
|
-
// float easedProgress = easeOutSine(rippleProgress);
|
|
118
|
-
// float easedProgress = easeOutBack(rippleProgress);
|
|
119
|
-
|
|
120
|
-
// RIPPLE CALCULATION
|
|
121
|
-
float rippleRadius = easedProgress * MAX_RADIUS;
|
|
122
|
-
|
|
123
|
-
// float fade = 1.0; // no fade
|
|
124
|
-
// float fade = 1.0 - easedProgress; // linear fade
|
|
125
|
-
float fade = 1.0 - easeOutPulse(rippleProgress);
|
|
126
|
-
// float fade = 1.0 - exponentialDecayPulse(rippleProgress);
|
|
127
|
-
|
|
128
|
-
// Calculate distance from frag to cursor center
|
|
129
|
-
float dist = distance(vu, centerCC);
|
|
130
|
-
|
|
131
|
-
float sdfRing = abs(dist - rippleRadius) - RING_THICKNESS * 0.5;
|
|
132
|
-
|
|
133
|
-
// Antialias (1-pixel width in normalized coords)
|
|
134
|
-
float antiAliasSize = normalize(vec2(BLUR, BLUR), 0.0).x;
|
|
135
|
-
float ripple = (1.0 - smoothstep(-antiAliasSize, antiAliasSize, sdfRing)) * fade;
|
|
136
|
-
|
|
137
|
-
// Apply ripple effect
|
|
138
|
-
fragColor = mix(fragColor, COLOR, ripple * COLOR.a);
|
|
139
|
-
}
|
|
140
|
-
// else: do nothing, keep original fragColor
|
|
141
|
-
}
|