quickshell: fling the worm when a panel pops out on top of him
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
25819bd901
commit
bdb3ab0c75
1 changed files with 43 additions and 26 deletions
|
|
@ -1029,7 +1029,7 @@ in
|
|||
// Snapshot last, so a rect is always compared against
|
||||
// where it was exactly one tick ago. vector4d is a
|
||||
// value type, so this copies numbers, not handles.
|
||||
prevRects = pushers.slice();
|
||||
prevRects = pushers.map(p => p.rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1060,12 +1060,18 @@ in
|
|||
}
|
||||
|
||||
// ── Shoved by the panels ────────────────────────────────
|
||||
// Bound to the very rects the frame shader melts into the
|
||||
// chrome (cx, cy, hw, hh; hw <= 0 means "not on screen"), so
|
||||
// what sweeps him aside is the panel outline you can actually
|
||||
// see growing, not the cards riding inside it.
|
||||
// Each pusher is { rect, push }: `rect` is the very vector4d
|
||||
// the frame shader melts into the chrome (cx, cy, hw, hh;
|
||||
// hw <= 0 means "not on screen"), so what sweeps him aside is
|
||||
// the panel outline you can actually see. `push` is the unit
|
||||
// direction that panel slides out in — a constant of the
|
||||
// design, and not something worth deriving: the morph is
|
||||
// 280ms of OutExpo, nearly all of it landing inside a single
|
||||
// 33ms tick, so there is rarely a partly-grown rect to read a
|
||||
// direction off of.
|
||||
property var pushers: []
|
||||
property var prevRects: []
|
||||
readonly property real shoveSpeed: 18
|
||||
|
||||
function inRect(p, r) {
|
||||
return Math.abs(p.x - r.x) <= r.z + 6 && Math.abs(p.y - r.y) <= r.w + 6;
|
||||
|
|
@ -1074,16 +1080,28 @@ in
|
|||
function checkShove() {
|
||||
let head = body[0], tail = body[segments - 1];
|
||||
for (let i = 0; i < pushers.length; i++) {
|
||||
let r = pushers[i], q = prevRects[i];
|
||||
let r = pushers[i].rect, q = prevRects[i];
|
||||
if (!r || r.z < 0.5) continue;
|
||||
if (!inRect(head, r)) continue;
|
||||
if (!q || q.z < 0.5) { q = r; } // appeared already overlapping him
|
||||
// Only an edge that is travelling outward carries him,
|
||||
// and it carries him the way it is going: the dropdown
|
||||
// grows rightward out of the bar, the launcher grows
|
||||
// up out of the floor. A panel closing just lets go.
|
||||
let dx = Math.max(0, (r.x + r.z) - (q.x + q.z)) + Math.min(0, (r.x - r.z) - (q.x - q.z));
|
||||
let dy = Math.max(0, (r.y + r.w) - (q.y + q.w)) + Math.min(0, (r.y - r.w) - (q.y - q.w));
|
||||
// Any part of him in the way is enough to be swept;
|
||||
// only the head decides a turn-around.
|
||||
let touched = false;
|
||||
for (let s = 0; s < body.length && !touched; s++)
|
||||
touched = inRect(body[s], r);
|
||||
if (!touched) continue;
|
||||
// Either it was not there a tick ago — the pop-out,
|
||||
// and the usual case given how fast the morph is — or
|
||||
// an edge has swept outward over him since. Both mean
|
||||
// the panel arrived where he was standing.
|
||||
let appeared = !q || q.z < 0.5;
|
||||
let grew = !appeared && (
|
||||
(r.x + r.z) - (q.x + q.z) > 1 || (q.x - q.z) - (r.x - r.z) > 1
|
||||
|| (r.y + r.w) - (q.y + q.w) > 1 || (q.y - q.w) - (r.y - r.w) > 1);
|
||||
if (appeared || grew) {
|
||||
worm.loose = true;
|
||||
worm.vx = pushers[i].push.x * shoveSpeed;
|
||||
worm.vy = pushers[i].push.y * shoveSpeed - 3; // -3: a little air
|
||||
return;
|
||||
}
|
||||
// Sitting still, it is simply solid: he walks into the
|
||||
// panel and turns around rather than crawling through
|
||||
// it, which is what made an open dropdown feel like it
|
||||
|
|
@ -1092,15 +1110,7 @@ in
|
|||
// inside (he landed there) means walking on is the way
|
||||
// out, and reversing on that would just buzz him in
|
||||
// place against both edges.
|
||||
if (Math.abs(dx) < 1 && Math.abs(dy) < 1) {
|
||||
if (!inRect(tail, r)) reverse();
|
||||
return;
|
||||
}
|
||||
worm.loose = true;
|
||||
// Clamped: the panel's first frame of OutExpo covers
|
||||
// most of its width, which would fire him off screen.
|
||||
worm.vx = Math.max(-22, Math.min(22, dx * 1.4));
|
||||
worm.vy = Math.max(-22, Math.min(22, dy * 1.4)) - 3; // -3: a little air
|
||||
if (inRect(head, r) && !inRect(tail, r)) reverse();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -6752,9 +6762,16 @@ in
|
|||
|
||||
// Last child, so he crawls over the panels rather than under
|
||||
// them. Purely decorative, see Weird.qml. The pushers are the
|
||||
// same rects the frame shader draws, so what shoves him is the
|
||||
// panel outline itself as it grows.
|
||||
Weird { pushers: [chromeSdf.panel, chromeSdf.launcher] }
|
||||
// same rects the frame shader draws, paired with the way each
|
||||
// one slides out: dropdowns and toasts rightward out of the
|
||||
// bar column, the launcher up out of the bottom frame band.
|
||||
Weird {
|
||||
pushers: [
|
||||
{ rect: chromeSdf.panel, push: Qt.point(1, 0) },
|
||||
{ rect: chromeSdf.toast, push: Qt.point(1, 0) },
|
||||
{ rect: chromeSdf.launcher, push: Qt.point(0, -1) }
|
||||
]
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue