diff --git a/resources/shaders/aura-glow.frag b/resources/shaders/aura-glow.frag index 2302592..6c9d4bb 100644 --- a/resources/shaders/aura-glow.frag +++ b/resources/shaders/aura-glow.frag @@ -10,6 +10,7 @@ ////////////////////////////////////////////////////////////////////////////////////////// // SPDX-FileCopyrightText: Justin Garza +// SPDX-FileCopyrightText: Simon Schneegans // SPDX-License-Identifier: GPL-3.0-or-later // The content from common.glsl is automatically prepended to each shader effect. This @@ -30,121 +31,87 @@ // vec4 getInputColor(vec2 coords) // void setOutputColor(vec4 outColor) -// The width of the fading effect is loaded from the settings. uniform float uColorSpeed; uniform bool uRandomColorOffset; uniform float uColorOffset; uniform float uColorSaturation; -uniform float uFadeOut; uniform float uBlur; uniform vec2 uSeed; - -/* -this controls the end shape --5.0 large Star --3.0 Star -1.0 Dimond -2.0 Circle -3.0 Squircle -5.0 Square -*/ -uniform float uEdgeShape; - -// the size of the edge color uniform float uEdgeSize; - -// soft <--> hard uniform float uEdgeHardness; void main() { - // This gradually dissolves from [1..0] from the outside to the center. We - // switch the direction for opening and closing. + // We simply inverse the progress for opening windows. float progress = uForOpening ? uProgress : 1.0 - uProgress; - // adjusting for Gnome - if (uPadding > 0.0) { - progress = remap(progress, 0.0, ((uSize.x - (uPadding * 2.0)) / uSize.x), 0.0, 1.0); + // Map UV to window content (without the shadow padding). + vec2 uv = (iTexCoord.st - 0.5) * uSize / (vec2(1.0) - vec2(uPadding * 2.0) / uSize); + uv = uv / uSize + 0.5; + + // We want the shapes of the masks at the end of the animation to have a 1:1 aspect + // ratio. For this, we scale the UV coordinates based on the aspect ratio of the window + // and later blend between the original UV and the 1:1 UV based on the progress. + vec2 oneToOneUV = uv; + oneToOneUV -= 0.5; + + if (uSize.x > uSize.y) { + oneToOneUV.y *= uSize.y / uSize.x; + } else { + oneToOneUV.x *= uSize.x / uSize.y; } - // Get the color from the window texture. - vec4 oColor = getInputColor(iTexCoord.st); + oneToOneUV += 0.5; - // Calculate the aspect ratio of the render area - float aspect = uSize.x / uSize.y; + uv = mix(oneToOneUV, uv, progress); - // standard uv - vec2 uv = iTexCoord.st; + // This blends between a square-shaped gradient towards the window edges and a circular + // gradient. + float shape = mix(2.0, 100.0, pow(progress, 5.0)); + float gradient = pow(abs(uv.x - 0.5) * 2.0, shape) + pow(abs(uv.y - 0.5) * 2.0, shape); + gradient += simplex2D((iTexCoord + uSeed)) * 0.5; - // tuv is for when progress is near 0 - vec2 tuv = uv; - tuv -= 0.5; // Shift UV coordinates to center (from [-0.5 to 0.5]) - tuv.x *= aspect; // Scale x-coordinate to match aspect ratio - tuv += 0.5; // Shift UV coordinates back (from [0 to 1]) + // This mask is used for the color overlay. + float glowMask = (progress - gradient) / mix(uEdgeSize, 0.5, progress); + glowMask = 1.0 - clamp(glowMask - progress, 0.0, 1.0); - // mixing the UVs - uv = mix(tuv, uv, easeOutExpo(progress)); + // Quickly fade out the glow mask at the end of the animation. + glowMask *= easeOutSine(min(1.0, (1.0 - progress) * 4.0)); - // this controls the shape - // -1.0 would be a diamond-ish - // 0.0 would be a rounded diamond - // 1.0 would be a circle - // 2.0 will be sqircle - // 1000.0 will be very square - float p = mix(uEdgeShape, 1000.0, easeInExpo(progress)); - - // this will be used later to make a mask - float m = - mix(0.0, 1.0, - clamp(pow(abs(uv.x - 0.5) * 2.0, p) + pow(abs(uv.y - 0.5) * 2.0, p), 0.0, 1.0)); - - // this calculates the edge of the effect - float edge = abs(m - progress); - float e = mix(0.0, uEdgeSize, 1.0 - progress); - edge = remap(edge, 0.0, e, 0.0, 1.0); - edge = clamp(edge, 0.0, 1.0); - edge = 1.0 - edge; - - // this is the mask - float mask = (m > progress) ? 0.0 : 1.0; - - // we need two of these - float mask0 = mix(mask, mask + edge, 1.0 - uEdgeHardness); - float mask1 = mix(edge, edge * mask, uEdgeHardness); - - // calculate color - vec3 color = cos(progress * uColorSpeed + uv.xyx + vec3(0, 2, 4)).xyz; - // coloroffset - float colorOffset = (uRandomColorOffset) ? hash12(uSeed) : uColorOffset; - color = offsetHue(color, colorOffset + 0.10); - // clamp and saturate - color = clamp(color * uColorSaturation, vec3(0.0), vec3(1.0)); - - // save this for later - float oColorAlpha = oColor.a; - - // blur-ify + // Get the color from the window texture. We gradually blur the input color based on + // the progress of the animation. We also slightly scale the UV coordinates to make + // the window scale up during the animation. + vec2 windowUV = (iTexCoord.st - 0.5) * mix(1.1, 1.0, easeOutCubic(progress)) + 0.5; + vec4 windowColor; if (uBlur > 0.0) { - // used for blur later ... - // calculate this before saturating it - float b = (color.r + color.g + color.b) / 3.0; - - oColor = getBlurredInputColor(iTexCoord.st, b * uBlur * mask1, 7.0); + windowColor = getBlurredInputColor(windowUV, (1.0 - progress) * uBlur, 3.0); + } else { + windowColor = getInputColor(windowUV); } + glowMask *= windowColor.a; - // apply masks and colors - oColor.a *= mask0; + vec3 glowColor = cos(progress * uColorSpeed + uv.xyx + vec3(0, 2, 4)).xyz; + float colorOffset = (uRandomColorOffset) ? hash12(uSeed) : uColorOffset; + glowColor = offsetHue(glowColor, colorOffset + 0.1); + glowColor = clamp(glowColor * uColorSaturation, vec3(0.0), vec3(1.0)); - oColor += mask1 * vec4(color.rgb, 1.0); - oColor.a *= oColorAlpha; + windowColor.rgb += glowColor * glowMask; - // i want to fade out the last ~10% of the animation - float lastfade = remap(progress, 0.0, uFadeOut, 0.0, 1.0); - lastfade = clamp(lastfade, 0.0, 1.0); - lastfade = easeInSine(lastfade); + // To make this look better on light themes, we also add some color non-additively. + windowColor = alphaOver(windowColor, vec4(glowColor, glowMask * 0.2)); - // apply the lastfade - oColor.a *= lastfade; + // A mask which will crop the window gradually into a circle. + float softCrop = 1.0 - smoothstep(progress - 0.5, progress + 0.5, gradient); + float hardCrop = 1.0 - smoothstep(progress - 0.05, progress + 0.05, gradient); + float cropMask = mix(softCrop, hardCrop, uEdgeHardness); - setOutputColor(oColor); + // Quickly fade in the alpha mask at the beginning of the animation. + cropMask *= easeInSine(min(1.0, progress * 2.0)); + + // Quickly fade out the alpha mask at the end of the animation. + cropMask = max(cropMask, 1.0 - easeOutSine(min(1.0, (1.0 - progress) * 4.0))); + + windowColor.a *= cropMask; + + setOutputColor(windowColor); } \ No newline at end of file diff --git a/resources/ui/adw/aura-glow.ui b/resources/ui/adw/aura-glow.ui index 240f31c..e96a5b2 100644 --- a/resources/ui/adw/aura-glow.ui +++ b/resources/ui/adw/aura-glow.ui @@ -40,7 +40,7 @@ SPDX-License-Identifier: GPL-3.0-or-later - + @@ -53,7 +53,7 @@ SPDX-License-Identifier: GPL-3.0-or-later - edit-clear-symbolic + edit-clear-symbolic center Reset to Default Value - - - - --> - Edge Size @@ -204,12 +175,12 @@ SPDX-License-Identifier: GPL-3.0-or-later left 300 - - 1.0 - 0.0 - 0.05 - 0.10 - + + 1.0 + 0.0 + 0.05 + 0.10 + @@ -226,44 +197,9 @@ SPDX-License-Identifier: GPL-3.0-or-later - - - Edge Shape - -1.0 (Star-ish) to 2.0 (Square) - - - center - 1 - 2 - left - 300 - - - 2.0 - -1.0 - 0.10 - 0.25 - - - - - - - edit-clear-symbolic - center - Reset to Default Value - - - - - - Edge Hardness - 0.0 (soft/blurry) to 1.0 (sharp/hard) center @@ -272,12 +208,12 @@ SPDX-License-Identifier: GPL-3.0-or-later left 300 - - 1.0 - 0.0 - 0.10 - 0.25 - + + 1.0 + 0.0 + 0.10 + 0.25 + @@ -297,7 +233,6 @@ SPDX-License-Identifier: GPL-3.0-or-later Blur Amount - 0 is Off center @@ -307,7 +242,7 @@ SPDX-License-Identifier: GPL-3.0-or-later 300 - 100.0 + 30.0 0.0 0.50 1.00 @@ -328,39 +263,6 @@ SPDX-License-Identifier: GPL-3.0-or-later - - - Fade Out - - - center - 1 - 2 - left - 300 - - - 0.75 - 0.0 - 0.10 - 0.25 - - - - - - - edit-clear-symbolic - center - Reset to Default Value - - - - - - \ No newline at end of file diff --git a/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml b/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml index b40cc93..b7b4b8f 100644 --- a/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml +++ b/schemas/org.gnome.shell.extensions.burn-my-windows-profile.gschema.xml @@ -968,7 +968,7 @@ SPDX-License-Identifier: CC0-1.0 - 1500 + 750 Aura Glow Animation Time The time the Aura Glow effect takes. @@ -986,53 +986,35 @@ SPDX-License-Identifier: CC0-1.0 - 5.0 + 2.5 Aura Glow Color Speed The Speed at which the color changes - 0.5 + 0.75 Aura Glow Color Saturation Amount of color in the effect - - - 1.0 + 0.75 Aura Glow Size of the Color Edge Size of the Color Edge - - -1.0 - Aura Glow Edge Shape - The Shape at the end of the animation - - - 0.0 + 0.25 Aura Glow Edge Hardness The Hardness of the Edge - 50.0 + 15.0 Aura Glow Blur Changes the Blue Amount - - 0.0 - Aura Glow Fade Out - The Percent at which the window will fade out - - diff --git a/src/effects/AuraGlow.js b/src/effects/AuraGlow.js index a6028ba..b3e772b 100644 --- a/src/effects/AuraGlow.js +++ b/src/effects/AuraGlow.js @@ -10,6 +10,7 @@ ////////////////////////////////////////////////////////////////////////////////////////// // SPDX-FileCopyrightText: Justin Garza +// SPDX-FileCopyrightText: Simon Schneegans // SPDX-License-Identifier: GPL-3.0-or-later 'use strict'; @@ -36,7 +37,6 @@ export default class Effect { // GLSL file in resources/shaders/.glsl. The callback will be called for each // newly created shader instance. - constructor() { this.shaderFactory = new ShaderFactory(Effect.getNick(), (shader) => { // Store uniform locations of newly created shaders. @@ -44,58 +44,22 @@ export default class Effect { shader._uRandomColorOffset = shader.get_uniform_location('uRandomColorOffset'); shader._uColorOffset = shader.get_uniform_location('uColorOffset'); shader._uColorSaturation = shader.get_uniform_location('uColorSaturation'); - - shader._uEdgeSize = shader.get_uniform_location('uEdgeSize'); - shader._uEdgeShape = shader.get_uniform_location('uEdgeShape'); - shader._uEdgeHardness = shader.get_uniform_location('uEdgeHardness'); - - shader._uBlur = shader.get_uniform_location('uBlur'); - shader._uFadeOut = shader.get_uniform_location('uFadeOut'); - shader._uSeed = shader.get_uniform_location('uSeed'); - + shader._uEdgeSize = shader.get_uniform_location('uEdgeSize'); + shader._uEdgeHardness = shader.get_uniform_location('uEdgeHardness'); + shader._uBlur = shader.get_uniform_location('uBlur'); + shader._uSeed = shader.get_uniform_location('uSeed'); // Write all uniform values at the start of each animation. shader.connect('begin-animation', (shader, settings) => { - shader.set_uniform_float(shader._uColorSpeed, 1, [ - settings.get_double('aura-glow-color-speed'), - ]); - - shader.set_uniform_float(shader._uRandomColorOffset, 1, - [settings.get_boolean('aura-glow-random-color')]); - - shader.set_uniform_float(shader._uColorOffset, 1, [ - settings.get_double('aura-glow-color-offset'), - ]); - - shader.set_uniform_float(shader._uColorSaturation, 1, [ - settings.get_double('aura-glow-color-saturation'), - ]); - - shader.set_uniform_float(shader._uEdgeSize, 1, [ - settings.get_double('aura-glow-edge-size'), - ]); - shader.set_uniform_float(shader._uEdgeShape, 1, [ - settings.get_double('aura-glow-edge-shape'), - ]); - shader.set_uniform_float(shader._uEdgeHardness, 1, [ - settings.get_double('aura-glow-edge-hardness'), - ]); - - shader.set_uniform_float(shader._uBlur, 1, [ - settings.get_double('aura-glow-blur'), - ]); - - shader.set_uniform_float(shader._uFadeOut, 1, [ - settings.get_double('aura-glow-fade-out'), - ]); - - // shader.set_uniform_float(shader._uLightTheme, 1, [ - // Effect.getCurrentThemeMode(), - // ]); - - // this will be used with a has function to get a random number // clang-format off - shader.set_uniform_float(shader._uSeed, 2, [Math.random(), Math.random()]); + shader.set_uniform_float(shader._uColorSpeed, 1, [settings.get_double('aura-glow-color-speed')]); + shader.set_uniform_float(shader._uRandomColorOffset, 1, [settings.get_boolean('aura-glow-random-color')]); + shader.set_uniform_float(shader._uColorOffset, 1, [settings.get_double('aura-glow-color-offset')]); + shader.set_uniform_float(shader._uColorSaturation, 1, [settings.get_double('aura-glow-color-saturation')]); + shader.set_uniform_float(shader._uEdgeSize, 1, [settings.get_double('aura-glow-edge-size')]); + shader.set_uniform_float(shader._uEdgeHardness, 1, [settings.get_double('aura-glow-edge-hardness')]); + shader.set_uniform_float(shader._uBlur, 1, [settings.get_double('aura-glow-blur')]); + shader.set_uniform_float(shader._uSeed, 2, [Math.random(), Math.random()]); // clang-format on }); }); @@ -130,117 +94,35 @@ export default class Effect { // This is called by the preferences dialog whenever a new effect profile is loaded. It // binds all user interface elements to the respective settings keys of the profile. static bindPreferences(dialog) { - // Empty for now... Code is added here later in the tutorial! dialog.bindAdjustment('aura-glow-animation-time'); dialog.bindAdjustment('aura-glow-color-speed'); dialog.bindSwitch('aura-glow-random-color'); dialog.bindAdjustment('aura-glow-color-offset'); dialog.bindAdjustment('aura-glow-color-saturation'); - dialog.bindAdjustment('aura-glow-edge-size'); - dialog.bindAdjustment('aura-glow-edge-shape'); dialog.bindAdjustment('aura-glow-edge-hardness'); - dialog.bindAdjustment('aura-glow-blur'); - dialog.bindAdjustment('aura-glow-fade-out'); // enable and disable the one slider - function EnableDisablePref(dialog, state) { + function enableDisablePref(dialog, state) { dialog.getBuilder() .get_object('aura-glow-color-offset-scale') .set_sensitive(!state); } - // if we use a checkbox instead of a switch - /* - const randColor = dialog.getBuilder().get_object('aura-glow-random-color'); - if (randColor) { - // Connect to the "toggled" signal to update preferences dynamically - randColor.connect('toggled', (widget) => { - const state = widget.get_active(); // Retrieve the state directly - EnableDisablePref(dialog, state); // Update sensitivity when the state changes - }); - - // Manually call the update function on startup, using the initial state of the - // switch - const initialState = - randColor.get_active(); // Get the initial state of the check button - EnableDisablePref(dialog, initialState); - } else { - // Log an error if the switch widget is not found in the UI - log('Error: \'aura-glow-random-color\' switch widget not found.'); - } - */ - - // if we use a switch instead of a checkbox - const switchWidget = dialog.getBuilder().get_object('aura-glow-random-color'); - if (switchWidget) { - // Connect to the "state-set" signal to update preferences dynamically based on - // the switch state. - switchWidget.connect('state-set', (widget, state) => { - EnableDisablePref(dialog, state); // Update sensitivity when the state changes. - }); - // Manually call the update function on startup, using the initial state of the - // switch. - const initialState = - switchWidget.get_active(); // Get the current state of the switch. - EnableDisablePref(dialog, initialState); - } else { - // Log an error if the switch widget is not found in the UI. - log('Error: \'aura-glow-random-color\' switch widget not found.'); - } + // Connect to the "state-set" signal to update preferences dynamically based on + // the switch state. + switchWidget.connect('state-set', (widget, state) => { + enableDisablePref(dialog, state); // Update sensitivity when the state changes. + }); - - // Retrieve the necessary objects - const colorOffset = dialog.getBuilder().get_object('aura-glow-color-offset-scale'); - const actionRow = dialog.getBuilder().get_object('aura-glow-action-row'); - - if (colorOffset == null) { - log('colorOffset is null'); - } - - - // Define an array of color names based on the slider value - const colorNames = [ - 'Red', // 0.00 - 'Reddish-Orange', // 0.05 - 'Orange', // 0.10 - 'Yellow-Orange', // 0.15 - 'Yellow-Green', // 0.20 - 'Lime Green', // 0.25 - 'Green', // 0.30 - 'Greenish-Cyan', // 0.35 - 'Aqua', // 0.40 - 'Light Cyan', // 0.45 - 'Cyan', // 0.50 - 'Sky Cyan', // 0.55 - 'Sky Blue', // 0.60 - 'Light Blue', // 0.65 - 'Blue', // 0.70 - 'Indigo', // 0.75 - 'Purple', // 0.80 - 'Magenta', // 0.85 - 'Pinkish-Red', // 0.90 - 'Crimson', // 0.95 - 'Red' // 1.00 (wraps around) - ]; - - // Function to update the subtitle based on the slider value - const updateSubtitle = () => { - const value = colorOffset.get_value(); // Get the current slider value - const index = Math.round(value * 20); // Map value [0.0, 1.0] to index [0, 10] - actionRow.set_subtitle( - colorNames[index]); // Update subtitle with the corresponding color - }; - - // Connect the value-changed signal to the updateSubtitle function - // Connect the value-changed signal to the updateSubtitle function - colorOffset.connect('value-changed', updateSubtitle); - - // Initialize the subtitle on load - updateSubtitle(); + // Manually call the update function on startup, using the initial state of the + // switch. + const initialState = + switchWidget.get_active(); // Get the current state of the switch. + enableDisablePref(dialog, initialState); } // ---------------------------------------------------------------- API for extension.js