From 91afdf7f13fb6c75ce25a5fcc2b5bcb7a8f0f667 Mon Sep 17 00:00:00 2001 From: LemmyCook Date: Fri, 29 Aug 2025 21:40:20 -0400 Subject: [PATCH] Wallpaper: added disc transition --- Modules/Background/Background.qml | 30 +++++++++++++++-- Services/WallpaperService.qml | 4 +++ Shaders/frag/wp_disc.frag | 52 ++++++++++++++++++++++++++++++ Shaders/frag/wp_wipe.frag | 2 +- Shaders/qsb/wp_disc.frag.qsb | Bin 0 -> 2398 bytes 5 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 Shaders/frag/wp_disc.frag create mode 100644 Shaders/qsb/wp_disc.frag.qsb 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 0000000000000000000000000000000000000000..485186eb3b9d20a42aabf0e0bd11c919b0f55384 GIT binary patch literal 2398 zcmV-k38D4?04eu)ob6iccN51Izu2-3!aNe5d6Z7#CXpSX$g0W1LO@~@Ac2}-hv2C0 zcD-833(~IGoi!rFJ?ZJ`*M96@(m$?WdfIbmeJialAg&nb$z`6S7uP`S-&Rm0)BHG{3J!xQOhA|hx{RzZjTc> zO*Tc;C6^qMbVo(ZqX1$X{*%ciUC*I^SsYAz8eG9 z;n~TFxfyonFdd{nfcpwfC%R87G8MHa~$cWVm zno$0{MU%=0{(YJzl}L{83<;{~8@q zF`UjwTur}0lk^H=&GN7Ib1AXMG_NliG_NN=rzl6iz+CuwAGDr7>-#1AVIR&?PQ~g7 z{5?m9RBYeIc-Dt?{K{C@D(H8>V;|my4+r1_)9)Gb1z@KQAB!nGZ}Lfl{s=xY&2m@O zjDEPR$G=6sXnNaN!w|ZTz+a}Llzv@`Kcp!or)v^p{!SB0cNO_?$XI_~-(xBIj6pO0 z%@kcWXkL$MioTqpZ>8vs6up_E?G){St|7l?k+YX*Qq5%+W1M3rkzX2n3iJJjrd0e+ z19J-U$H3F_uOT0`{Oc+CH-LE^@@K&Nl%|xg0{C;#F^&B#fZ^PkN4~vhU>3mtGfg3{ z61fFK_j%|p8geD@Z_||W_XEh5;NP3zY1?iQA44#hnMdX{NYsj}*no;^LAv^t1ZpD!MJVW<2@c#t4>)7Mh47nQ__PzjL+xrr-Ul?<~i8&YG&zG3I|K6-_}ce7@ck>phjqh;HDK6>TNu;2zQ+F7^j++Kz5d?-!~9vARv3NE`wZi( zcLRLwcO8CzYv}$h_!_g75#Qf|ujgSI^SFv}9sA!yrv)E2!PEL3=-)Q(vJ4fr06yWc-vL0WiLS>7tg;(m_Q( zM64EJBLIed^f1n{To)z!hNffm6|H+0b^JEXsPRYOnIE>xV?Ed{L2nE^+l?@;*W^2_ z$z#LT6Y#Y!-=kmt1vPvRyeEcE=KX^X(8tM1CWkZZ0W1xUH@Uyf?Yd#)1-@7;m-F4w zbv#Awc&(kTXto1eR!7*LFRS@{B*WN|Vmof;pX7xQqGQV?@laZ~Y#DmJs^TdP%v|f* zjwc_R+-?}OLN|&`p5yw`4eyPzHceL42?Dv}r)2G@>pJp|Exn+c->c^HvF|m5u){8j zcsp(ytYjjQ-RZX7u(B$mAPyaOvHA=^rJB$0+Tml*Z;4&ksqoA;+}=tMgpD$f1ztmN zs0;H5ibBP^qLzYUY)LplI|vs=O-Q#Vl zttaJkUE0zW7El(7s)>#mJx*_BNblkpy_HP8jLt{WmY$PLGhMgMvEky4p0?wuMxU(ZvKl#>fW!>7F2<^VE?beIid)jW; z9cey^y7I@R;u@m?&ai!H&Q1=B<+@KdHh@N+M#MuGZCeXO+4822_wUFq9IU3 z0x~%zGXO?yQ*F?dapm#Zj@+=&4jg|V&Z;}EZ0>_NsAa@qvl>h($ literal 0 HcmV?d00001