diff --git a/Assets/Matugen/Matugen.qml b/Assets/Matugen/Matugen.qml index b6e2d2c..0d5c2b6 100644 --- a/Assets/Matugen/Matugen.qml +++ b/Assets/Matugen/Matugen.qml @@ -50,7 +50,8 @@ Singleton { lines.push("\n[templates.ghostty]") lines.push('input_path = "' + Quickshell.shellDir + '/Assets/Matugen/templates/ghostty.conf"') lines.push('output_path = "~/.config/ghostty/themes/noctalia"') - lines.push("post_hook = \"grep -q '^theme *= *' ~/.config/ghostty/config; and sed -i 's/^theme *= *.*/theme = noctalia/' ~/.config/ghostty/config; or echo 'theme = noctalia' >> ~/.config/ghostty/config\"") + lines.push( + "post_hook = \"grep -q '^theme *= *' ~/.config/ghostty/config; and sed -i 's/^theme *= *.*/theme = noctalia/' ~/.config/ghostty/config; or echo 'theme = noctalia' >> ~/.config/ghostty/config\"") } return lines.join("\n") + "\n" diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 1911f34..3d2c058 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -18,9 +18,13 @@ Variants { id: root // Internal state management - property bool transitioning: false - property real fadeValue: 0.0 property bool firstWallpaper: true + property bool transitioning: false + property real transitionProgress: 0.0 + + // Swipe direction: 0=left, 1=right, 2=up, 3=down + property real swipeDirection: 0 + property real swipeSmoothness: 0.05 // External state management property string servicedWallpaper: WallpaperService.getWallpaper(modelData.name) @@ -34,10 +38,29 @@ Variants { return } - if (Settings.data.wallpaper.transitionType === 'fade') { - setWallpaperWithTransition(servicedWallpaper) - } else { - setWallpaperImmediate(servicedWallpaper) + switch (Settings.data.wallpaper.transitionType) { + case "none": + setWallpaperImmediate(servicedWallpaper) + break + case "swipe_left": + swipeDirection = 0 + setWallpaperWithTransition(servicedWallpaper) + break + case "swipe_right": + swipeDirection = 1 + setWallpaperWithTransition(servicedWallpaper) + break + case "swipe_up": + swipeDirection = 2 + setWallpaperWithTransition(servicedWallpaper) + break + case "swipe_down": + swipeDirection = 3 + setWallpaperWithTransition(servicedWallpaper) + break + default: + setWallpaperWithTransition(servicedWallpaper) + break } } } @@ -77,30 +100,52 @@ Variants { visible: false } + // Fade transition shader ShaderEffect { - id: shaderEffect + id: fadeShader anchors.fill: parent + visible: Settings.data.wallpaper.transitionType === 'fade' property variant source1: currentWallpaper property variant source2: nextWallpaper - property real fade: fadeValue - fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/mix_images.frag.qsb") + property real fade: transitionProgress + fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/wp_fade.frag.qsb") } - // Animation for the fade value + // Swipe transition shader + ShaderEffect { + id: swipeShader + anchors.fill: parent + visible: Settings.data.wallpaper.transitionType.startsWith('swipe_') + + property variant source1: currentWallpaper + property variant source2: nextWallpaper + property real progress: transitionProgress + property real direction: swipeDirection + property real smoothness: swipeSmoothness + fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/wp_swipe.frag.qsb") + } + + // Animation for the transition progress NumberAnimation { - id: fadeAnimation + id: transitionAnimation target: root - property: "fadeValue" + property: "transitionProgress" from: 0.0 to: 1.0 - duration: Settings.data.wallpaper.transitionDuration - easing.type: Easing.InOutQuad + duration: Settings.data.wallpaper.transitionDuration ?? 1000 + easing.type: { + const transitionType = Settings.data.wallpaper.transitionType ?? 'fade' + if (transitionType.startsWith('swipe_')) { + return Easing.InOutCubic + } + return Easing.InOutCubic + } onFinished: { // Swap images after transition completes currentWallpaper.source = nextWallpaper.source - fadeValue = 0.0 + transitionProgress = 0.0 transitioning = false } } @@ -108,14 +153,14 @@ Variants { function startTransition() { if (!transitioning && nextWallpaper.source != currentWallpaper.source) { transitioning = true - fadeAnimation.start() + transitionAnimation.start() } } function setWallpaperImmediate(source) { currentWallpaper.source = source nextWallpaper.source = source - fadeValue = 0.0 + transitionProgress = 0.0 transitioning = false } @@ -123,13 +168,10 @@ Variants { if (source != currentWallpaper.source) { if (transitioning) { - // we are interupting a transition - if (fadeValue >= 0.5) { - - } + // We are interrupting a transition currentWallpaper.source = nextWallpaper.source - fadeAnimation.stop() - fadeValue = 0 + transitionAnimation.stop() + transitionProgress = 0 transitioning = false } diff --git a/Services/WallpaperService.qml b/Services/WallpaperService.qml index ea3a594..e12a273 100644 --- a/Services/WallpaperService.qml +++ b/Services/WallpaperService.qml @@ -23,6 +23,22 @@ Singleton { key: "fade" name: "Fade" } + ListElement { + key: "swipe_left" + name: "Swipe Left" + } + ListElement { + key: "swipe_right" + name: "Swipe Right" + } + ListElement { + key: "swipe_up" + name: "Swipe Up" + } + ListElement { + key: "swipe_down" + name: "Swipe Down" + } } property var wallpaperLists: ({}) diff --git a/Shaders/frag/mix_images.frag b/Shaders/frag/wp_fade.frag similarity index 100% rename from Shaders/frag/mix_images.frag rename to Shaders/frag/wp_fade.frag diff --git a/Shaders/frag/wp_swipe.frag b/Shaders/frag/wp_swipe.frag new file mode 100644 index 0000000..caa1ebc --- /dev/null +++ b/Shaders/frag/wp_swipe.frag @@ -0,0 +1,57 @@ +#version 440 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(binding = 1) uniform sampler2D source1; // Current wallpaper +layout(binding = 2) uniform sampler2D source2; // Next wallpaper + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + float qt_Opacity; + float progress; // Transition progress (0.0 to 1.0) + float direction; // 0=left, 1=right, 2=up, 3=down + float smoothness; // Edge smoothness (0.01 to 0.5, default 0.05) +} ubuf; + +void main() { + vec2 uv = qt_TexCoord0; + vec4 color1 = texture(source1, uv); // Current (old) wallpaper + vec4 color2 = texture(source2, uv); // Next (new) wallpaper + + float edge = 0.0; + float factor = 0.0; + + // Extend the progress range to account for smoothness + // This ensures the transition completes fully at the edges + float extendedProgress = ubuf.progress * (1.0 + 2.0 * ubuf.smoothness) - ubuf.smoothness; + + // Calculate edge position based on direction + // As progress goes from 0 to 1, we reveal source2 (new wallpaper) + if (ubuf.direction < 0.5) { + // Swipe from right to left (new image enters from right) + edge = 1.0 - extendedProgress; + factor = smoothstep(edge - ubuf.smoothness, edge + ubuf.smoothness, uv.x); + fragColor = mix(color1, color2, factor); + } + else if (ubuf.direction < 1.5) { + // Swipe from left to right (new image enters from left) + edge = extendedProgress; + factor = smoothstep(edge - ubuf.smoothness, edge + ubuf.smoothness, uv.x); + fragColor = mix(color2, color1, factor); + } + else if (ubuf.direction < 2.5) { + // Swipe from bottom to top (new image enters from bottom) + edge = 1.0 - extendedProgress; + factor = smoothstep(edge - ubuf.smoothness, edge + ubuf.smoothness, uv.y); + fragColor = mix(color1, color2, factor); + } + else { + // Swipe from top to bottom (new image enters from top) + edge = extendedProgress; + factor = smoothstep(edge - ubuf.smoothness, edge + ubuf.smoothness, uv.y); + fragColor = mix(color2, color1, factor); + } + + fragColor *= ubuf.qt_Opacity; +} \ No newline at end of file diff --git a/Shaders/qsb/mix_images.frag.qsb b/Shaders/qsb/wp_fade.frag.qsb similarity index 100% rename from Shaders/qsb/mix_images.frag.qsb rename to Shaders/qsb/wp_fade.frag.qsb diff --git a/Shaders/qsb/wp_swipe.frag.qsb b/Shaders/qsb/wp_swipe.frag.qsb new file mode 100644 index 0000000..e1977ce Binary files /dev/null and b/Shaders/qsb/wp_swipe.frag.qsb differ