diff --git a/Modules/Background/Background.qml b/Modules/Background/Background.qml index 198c94c..5a163f4 100644 --- a/Modules/Background/Background.qml +++ b/Modules/Background/Background.qml @@ -28,6 +28,11 @@ Variants { property real wipeDirection: 0 property real wipeSmoothness: 0.05 + // Disc + property real discCenterX: 0.5 + property real discCenterY: 0.5 + property real discSmoothness: 0.05 + // External state management property string servicedWallpaper: WallpaperService.getWallpaper(modelData.name) onServicedWallpaperChanged: { @@ -75,6 +80,11 @@ Variants { wipeDirection = 3 setWallpaperWithTransition(servicedWallpaper) break + case "disc": + discCenterX = Math.random() + discCenterY = Math.random() + setWallpaperWithTransition(servicedWallpaper) + break default: setWallpaperWithTransition(servicedWallpaper) break @@ -117,7 +127,7 @@ Variants { cache: false } - // Fade transition shader + // Fade or None transition shader ShaderEffect { id: fadeShader anchors.fill: parent @@ -143,6 +153,22 @@ Variants { fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/wp_wipe.frag.qsb") } + // Disc reveal transition shader + ShaderEffect { + id: discShader + anchors.fill: parent + visible: transitionType === 'disc' + + property variant source1: currentWallpaper + property variant source2: nextWallpaper + property real progress: transitionProgress + property real centerX: discCenterX + property real centerY: discCenterY + property real smoothness: discSmoothness + property real aspectRatio: width / height + fragmentShader: Qt.resolvedUrl("../../Shaders/qsb/wp_disc.frag.qsb") + } + // Animation for the transition progress NumberAnimation { id: transitionAnimation @@ -151,7 +177,7 @@ Variants { from: 0.0 to: 1.0 duration: Settings.data.wallpaper.transitionDuration ?? 1000 - easing.type: transitionType.startsWith('wipe_') ? Easing.InOutCubic : Easing.InOutCubic + easing.type: transitionType.startsWith('wipe_') ? Easing.InOutCubic : Easing.OutQuad onFinished: { // Swap images after transition completes currentWallpaper.source = nextWallpaper.source diff --git a/Services/WallpaperService.qml b/Services/WallpaperService.qml index 83c2a60..472e317 100644 --- a/Services/WallpaperService.qml +++ b/Services/WallpaperService.qml @@ -27,6 +27,10 @@ Singleton { key: "fade" name: "Fade" } + ListElement { + key: "disc" + name: "Disc" + } ListElement { key: "wipe_left" name: "Wipe Left" diff --git a/Shaders/frag/wp_disc.frag b/Shaders/frag/wp_disc.frag new file mode 100644 index 0000000..292ce59 --- /dev/null +++ b/Shaders/frag/wp_disc.frag @@ -0,0 +1,52 @@ +#version 450 + +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 centerX; // X coordinate of disc center (0.0 to 1.0) + float centerY; // Y coordinate of disc center (0.0 to 1.0) + float smoothness; // Edge smoothness (0.01 to 0.5, default 0.05) + float aspectRatio; // Width / Height of the screen +} ubuf; + +void main() { + vec2 uv = qt_TexCoord0; + vec4 color1 = texture(source1, uv); // Current (old) wallpaper + vec4 color2 = texture(source2, uv); // Next (new) wallpaper + + // Adjust UV coordinates to compensate for aspect ratio + // This makes distances circular instead of elliptical + vec2 adjustedUV = vec2(uv.x * ubuf.aspectRatio, uv.y); + vec2 adjustedCenter = vec2(ubuf.centerX * ubuf.aspectRatio, ubuf.centerY); + + // Calculate distance in aspect-corrected space + float dist = distance(adjustedUV, adjustedCenter); + + // Calculate the maximum possible distance (corner to corner) + // This ensures the disc can cover the entire screen + float maxDistX = max(ubuf.centerX * ubuf.aspectRatio, + (1.0 - ubuf.centerX) * ubuf.aspectRatio); + float maxDistY = max(ubuf.centerY, 1.0 - ubuf.centerY); + float maxDist = length(vec2(maxDistX, maxDistY)); + + // Scale progress to cover the maximum distance + // Add extra range for smoothness to ensure complete coverage + // Adjust smoothness for aspect ratio to maintain consistent visual appearance + float adjustedSmoothness = ubuf.smoothness * max(1.0, ubuf.aspectRatio); + float radius = ubuf.progress * (maxDist + adjustedSmoothness); + + // Use smoothstep for a smooth edge transition + float factor = smoothstep(radius - adjustedSmoothness, radius + adjustedSmoothness, dist); + + // Mix the textures (factor = 0 inside disc, 1 outside) + fragColor = mix(color2, color1, factor); + + fragColor *= ubuf.qt_Opacity; +} \ No newline at end of file diff --git a/Shaders/frag/wp_wipe.frag b/Shaders/frag/wp_wipe.frag index ab36dd5..f6db80e 100644 --- a/Shaders/frag/wp_wipe.frag +++ b/Shaders/frag/wp_wipe.frag @@ -1,4 +1,4 @@ -#version 440 +#version 450 layout(location = 0) in vec2 qt_TexCoord0; layout(location = 0) out vec4 fragColor; diff --git a/Shaders/qsb/wp_disc.frag.qsb b/Shaders/qsb/wp_disc.frag.qsb new file mode 100644 index 0000000..485186e Binary files /dev/null and b/Shaders/qsb/wp_disc.frag.qsb differ