@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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.34",
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.34",
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 ${TTHEME_CONFIG:h}/ttheme.conf; do
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#*=}// /}
@@ -8,4 +8,4 @@ if [[ ${TTHEME_TAB_PALETTE:-off} != off ]]; then
8
8
  export TTHEME_SPEC=$REPLY
9
9
  fi
10
10
 
11
- exec /bin/zsh -l
11
+ exec ${SHELL:-/bin/zsh} -l
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 || return 0
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=
@@ -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
@@ -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
- }