diff options
Diffstat (limited to 'desktop/modules/appearance')
| -rw-r--r-- | desktop/modules/appearance/WallShader.qml | 27 | ||||
| -rw-r--r-- | desktop/modules/appearance/WallpaperSpread.qml | 38 | ||||
| -rw-r--r-- | desktop/modules/appearance/Wallpapers.qml | 9 | ||||
| -rw-r--r-- | desktop/modules/appearance/burn.frag | 4 | ||||
| -rw-r--r-- | desktop/modules/appearance/burn.frag.qsb | bin | 3983 -> 4027 bytes |
5 files changed, 56 insertions, 22 deletions
diff --git a/desktop/modules/appearance/WallShader.qml b/desktop/modules/appearance/WallShader.qml new file mode 100644 index 0000000..19826ac --- /dev/null +++ b/desktop/modules/appearance/WallShader.qml @@ -0,0 +1,27 @@ +// Copyright (C) 2026 Danilo M. <danix@danix.xyz> +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +import QtQuick + +// One transition, by name, for the cover and the settings page's thumbnails. +// Goes in the old picture's layer.effect, which fills in source. Every shader +// draws the old picture at progress 0 and the new one at 1, and picks what it +// needs from these properties. target must be an item with a layer: an Image +// sampled directly gives the whole picture, not its PreserveAspectCrop crop. +ShaderEffect { + property string name: "burn" + property var source + property var target + property real progress: 0 + property real aspect: 1 + property point origin: Qt.point(0.5, 0.5) + fragmentShader: Qt.resolvedUrl(name + ".frag.qsb") +} diff --git a/desktop/modules/appearance/WallpaperSpread.qml b/desktop/modules/appearance/WallpaperSpread.qml index 02e5f94..f9e484b 100644 --- a/desktop/modules/appearance/WallpaperSpread.qml +++ b/desktop/modules/appearance/WallpaperSpread.qml @@ -16,8 +16,8 @@ import QtQuick // The transition when Apply sets a wallpaper. swaybg has none: wallp kills // the old one and starts a new one, which can show a frame of nothing. A // surface on the bottom layer, above swaybg and below every window, covers -// the swap: the old picture burns away over the new one, and the -// surface goes once wallp has finished, by when the new swaybg is drawing +// the swap: the old picture gives way to the new one, through the transition +// Transitions picked, and the surface goes once wallp has finished, by when the new swaybg is drawing // the same picture underneath. Sets from a terminal get no transition: by // the time wall_h changes, swaybg has already swapped. Scope { @@ -34,6 +34,7 @@ Scope { property bool running: false property bool done: false property real progress: 0 + property string effect: "burn" property point origin: Qt.point(0.5, 0.5) visible: running @@ -47,12 +48,12 @@ Scope { Connections { target: Wallpapers - function onSwapping(which, from, to) { + function onSwapping(which, from, to, effect) { if (which !== win.modelData.which || !win.screen) return; anim.stop(); - // Behind the char band, so no pixel starts out scorched. - win.progress = -0.05; - // A different place each time the fire starts. + win.effect = effect; + win.progress = 0; + // A different place each time it starts. win.origin = Qt.point(Math.random(), Math.random()); win.done = false; oldImg.source = from; @@ -69,7 +70,7 @@ Scope { } } - // Both decoded before the first block drops, or the old one + // Both decoded before anything moves, or the old one // would pop in late over a half-drawn screen. readonly property bool ready: running && oldImg.status === Image.Ready && newImg.status === Image.Ready @@ -88,7 +89,7 @@ Scope { // -m fill is a centred crop, which is what PreserveAspectCrop does. // Both hidden until both are decoded: the new one usually lands // first, and drawn under an old one still loading it flashed - // the new picture before the burn. Until then the surface is + // the new picture before the transition. Until then the surface is // clear and swaybg shows the old picture itself. Image { id: newImg @@ -98,6 +99,8 @@ Scope { sourceSize: Qt.size(win.width, win.height) asynchronous: true cache: false + // A layer, so the shaders that read it get the crop. + layer.enabled: win.running } Image { @@ -109,11 +112,12 @@ Scope { asynchronous: true cache: false layer.enabled: win.running - layer.effect: ShaderEffect { - property real progress: win.progress - property real aspect: win.width / Math.max(1, win.height) - property point origin: win.origin - fragmentShader: Qt.resolvedUrl("burn.frag.qsb") + layer.effect: WallShader { + name: win.effect + target: newImg + progress: win.progress + aspect: win.width / Math.max(1, win.height) + origin: win.origin } } @@ -121,10 +125,10 @@ Scope { id: anim target: win property: "progress" - // Past 1: fbm can push a threshold a little over it. Linear, - // since an ease spends its slow ends where nothing burns. - to: 1.05 - duration: 3500 + // Linear, since an ease spends its slow ends where nothing + // happens. + to: 1 + duration: Transitions.duration easing.type: Easing.Linear onFinished: if (win.done) win.running = false } diff --git a/desktop/modules/appearance/Wallpapers.qml b/desktop/modules/appearance/Wallpapers.qml index 582fb22..2b8faf7 100644 --- a/desktop/modules/appearance/Wallpapers.qml +++ b/desktop/modules/appearance/Wallpapers.qml @@ -59,7 +59,7 @@ Singleton { signal applied(bool ok, string message) // Sent before wallp runs, while current still names the old picture, so // WallpaperSpread can cover the swap with it. - signal swapping(string which, string from, string to) + signal swapping(string which, string from, string to, string effect) // Every run's end, Apply's or the engine's. applied is Apply's alone: it // reports to the save bar and closes the window. signal finished(bool ok) @@ -333,8 +333,9 @@ Singleton { applying = true; root.kind = kind; let covers = 0; - if (h !== "" && currentH !== "" && h !== currentH) { covers++; swapping("H", currentH, h); } - if (v !== "" && currentV !== "" && v !== currentV) { covers++; swapping("V", currentV, v); } + const effect = Transitions.next(); + if (h !== "" && currentH !== "" && h !== currentH) { covers++; swapping("H", currentH, h, effect); } + if (v !== "" && currentV !== "" && v !== currentV) { covers++; swapping("V", currentV, v, effect); } const args = []; if (h !== "") args.push(`H=${JSON.stringify(h)}`); if (v !== "") args.push(`V=${JSON.stringify(v)}`); @@ -349,7 +350,7 @@ Singleton { // Covers still to come up before wallp may swap swaybg under them. The // cover decodes its pictures asynchronously, and starting wallp with // swapping showed the new picture through the still empty cover for a - // moment, then the old one over it, then the burn. WallpaperSpread + // moment, then the old one over it, then the transition. WallpaperSpread // calls covered() once it is drawing; a cover that never comes (a // screen missing, a picture that fails to load) is waited out. property int uncovered: 0 diff --git a/desktop/modules/appearance/burn.frag b/desktop/modules/appearance/burn.frag index a5cb9c3..4f91a81 100644 --- a/desktop/modules/appearance/burn.frag +++ b/desktop/modules/appearance/burn.frag @@ -45,7 +45,9 @@ void main() { vec2 asp = vec2(aspect, 1.0); float d = length((qt_TexCoord0 - origin) * asp) / length(max(origin, 1.0 - origin) * asp); float t = mix(d, fbm(qt_TexCoord0 * asp * 5.0), 0.5); - float e = t - progress; + // Starts behind the char band, so no pixel starts out scorched, and ends + // past 1, since fbm can push a threshold a little over it. + float e = t - (progress * 1.1 - 0.05); if (e <= 0.0) { fragColor = vec4(0.0); return; } // Front to intact paper: flame, then char, then the picture. diff --git a/desktop/modules/appearance/burn.frag.qsb b/desktop/modules/appearance/burn.frag.qsb Binary files differindex 599a911..5344661 100644 --- a/desktop/modules/appearance/burn.frag.qsb +++ b/desktop/modules/appearance/burn.frag.qsb |
