diff --git a/extension.js b/extension.js index c8c0b5d..dc77ebd 100644 --- a/extension.js +++ b/extension.js @@ -58,6 +58,7 @@ class Extension { new Me.imports.src.EnergizeB.EnergizeB(), new Me.imports.src.Fire.Fire(), new Me.imports.src.Glide.Glide(), + new Me.imports.src.Glitch.Glitch(), new Me.imports.src.Hexagon.Hexagon(), new Me.imports.src.Incinerate.Incinerate(), new Me.imports.src.Matrix.Matrix(), diff --git a/prefs.js b/prefs.js index 0cf131a..7612e01 100644 --- a/prefs.js +++ b/prefs.js @@ -54,6 +54,7 @@ var PreferencesDialog = class PreferencesDialog { new Me.imports.src.EnergizeB.EnergizeB(), new Me.imports.src.Fire.Fire(), new Me.imports.src.Glide.Glide(), + new Me.imports.src.Glitch.Glitch(), new Me.imports.src.Hexagon.Hexagon(), new Me.imports.src.Incinerate.Incinerate(), new Me.imports.src.Matrix.Matrix(), diff --git a/resources/shaders/glitch.frag b/resources/shaders/glitch.frag new file mode 100644 index 0000000..fbe8228 --- /dev/null +++ b/resources/shaders/glitch.frag @@ -0,0 +1,62 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ) ( // +// ( /( ( ( ) ( ( ( ( )\ ) ( ( // +// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( // +// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ // +// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) // +// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< // +// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ // +// |__/ // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +// The content from common.glsl is automatically prepended to each shader effect. + +uniform vec3 uColor; +uniform float uScale; +uniform float uStrength; +uniform float uSpeed; + +// Somewhat inspired by https://www.shadertoy.com/view/XtK3W3 +void main() { + float progress = (uForOpening ? 1.0 - uProgress : uProgress); + float time = 7.5 * progress * uDuration * uSpeed; + float strength = uStrength * progress; + float displace = 750.0 * strength / uSize.x; + float yPos = uScale * uSize.y * iTexCoord.y; + + // Create large, incidental noise waves. + float noise = clamp(simplex2D(vec2(time, yPos * 0.002)) - 0.3, 0.0, 1.0); + + // Offset by smaller, constant noise waves. + noise = noise + (simplex2D(vec2(time * 10.0, yPos * 0.05)) - 0.5) * 0.15; + + // Apply the noise as x displacement for every line. + float xPos = clamp(iTexCoord.x - displace * noise * noise, 0.0, 1.0); + vec4 oColor = getInputColor(vec2(xPos, iTexCoord.y)); + + // Mix in some random interference lines. + vec3 interference = uColor * hash12(vec2(yPos * time)); + float interferenceStrength = noise * min(strength, 1.0); + oColor.rgb = mix(oColor.rgb, interference, interferenceStrength); + + // Apply a line pattern every 4 pixels. + if (floor(mod(yPos * 0.25, 2.0)) == 0.0) { + oColor.rgb = mix(uColor, oColor.rgb, 1.0 - (0.15 * noise)); + } + + // Shift green/blue channels. + oColor.g = mix(oColor.g, + getInputColor(vec2(xPos + noise * 0.1 * displace, iTexCoord.y)).g, 0.25); + oColor.b = mix(oColor.b, + getInputColor(vec2(xPos - noise * 0.1 * displace, iTexCoord.y)).b, 0.25); + + // Dissolve the window. + if (progress > mix(1.0 - noise, max(max(oColor.r, oColor.g), oColor.b), 0.5)) { + oColor.a = 0.0; + } + + setOutputColor(oColor); +} \ No newline at end of file diff --git a/resources/ui/adw/Glitch.ui b/resources/ui/adw/Glitch.ui new file mode 100644 index 0000000..23775d2 --- /dev/null +++ b/resources/ui/adw/Glitch.ui @@ -0,0 +1,171 @@ + + + + + + + + + + + Animation Time [ms] + + + center + 1 + 0 + left + 300 + + + 2000 + 100 + 1 + 100 + + + + + + + edit-clear-symbolic + center + Reset to Default Value + + + + + + + + + Scale + + + center + 1 + 2 + left + 300 + + + 10 + 0.1 + 0.01 + 0.1 + + + + + + + edit-clear-symbolic + center + Reset to Default Value + + + + + + + + + Strength + + + center + 1 + 2 + left + 300 + + + 10 + 0.1 + 0.01 + 0.1 + + + + + + + edit-clear-symbolic + center + Reset to Default Value + + + + + + + + + Speed + + + center + 1 + 2 + left + 300 + + + 10 + 0.1 + 0.01 + 0.1 + + + + + + + edit-clear-symbolic + center + Reset to Default Value + + + + + + + + + Color + glitch-color + + + center + 250 + 0 + 1 + + + + + edit-clear-symbolic + center + Reset to Default Value + + + + + + + + + \ No newline at end of file diff --git a/resources/ui/gtk3/Glitch.ui b/resources/ui/gtk3/Glitch.ui new file mode 100644 index 0000000..79fb5b3 --- /dev/null +++ b/resources/ui/gtk3/Glitch.ui @@ -0,0 +1,297 @@ + + + + + + + + 2000 + 100 + 1 + 100 + + + + 10 + 0.1 + 0.01 + 0.1 + + + + 10 + 0.1 + 0.01 + 0.1 + + + + 10 + 0.1 + 0.01 + 0.1 + + + + vertical + + + + + + none + + + + + 10 + 10 + 10 + 10 + 0 + + + 8 + + + Animation Time [ms] + 0 + start + center + 1 + + + + + end + center + 1 + 0 + left + 300 + glitch-animation-time + + + + + + + edit-clear-symbolic + 1 + + + Reset to Default Value + + + + + + + + + + + 10 + 10 + 10 + 10 + 0 + + + 8 + + + Scale + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + glitch-scale + + + + + + + edit-clear-symbolic + 1 + + + Reset to Default Value + + + + + + + + + + + 10 + 10 + 10 + 10 + 0 + + + 8 + + + Strength + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + glitch-strength + + + + + + + edit-clear-symbolic + 1 + + + Reset to Default Value + + + + + + + + + + + 10 + 10 + 10 + 10 + 0 + + + 8 + + + Speed + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + glitch-speed + + + + + + + edit-clear-symbolic + 1 + + + Reset to Default Value + + + + + + + + + + + 10 + 10 + 10 + 10 + 0 + + + + + Color + 0 + start + center + 1 + + + + + 0 + 1 + + + + + + + edit-clear-symbolic + 1 + + + Reset to Default Value + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/ui/gtk4/Glitch.ui b/resources/ui/gtk4/Glitch.ui new file mode 100644 index 0000000..ade6471 --- /dev/null +++ b/resources/ui/gtk4/Glitch.ui @@ -0,0 +1,249 @@ + + + + + + + + vertical + + + + + + none + 1 + + + + + 0 + + + + + Animation Time [ms] + 0 + start + center + 1 + + + + + end + center + 1 + 0 + left + 300 + + + 2000 + 100 + 1 + 100 + + + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + 0 + + + + + Scale + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + + + 10 + 0.1 + 0.01 + 0.1 + + + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + 0 + + + + + Strength + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + + + 10 + 0.1 + 0.01 + 0.1 + + + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + 0 + + + + + Speed + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + + + 10 + 0.1 + 0.01 + 0.1 + + + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + 0 + + + + + Color + 0 + start + center + 1 + + + + + 0 + 1 + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml b/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml index be44e36..3911d4c 100644 --- a/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml +++ b/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml @@ -635,6 +635,53 @@ SPDX-License-Identifier: CC0-1.0 The color of the effect. + + + + + + + false + Glitch Close Effect + Use the Glitch effect for window closing. + + + + false + Glitch Open Effect + Use the Glitch effect for window opening. + + + + 750 + Glitch Animation Time + The time the Glitch effect takes. + + + + 1.0 + Glitch Scale + The size of the effect. + + + + 1.0 + Glitch Strength + The intensity of the effect. + + + + 1.0 + Glitch Speed + The speed of the effect. + + + + "rgb(255, 200, 50)" + Glitch Color + The color of the effect. + + diff --git a/src/Glitch.js b/src/Glitch.js new file mode 100644 index 0000000..01f645a --- /dev/null +++ b/src/Glitch.js @@ -0,0 +1,114 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ) ( // +// ( /( ( ( ) ( ( ( ( )\ ) ( ( // +// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( // +// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ // +// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) // +// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< // +// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ // +// |__/ // +////////////////////////////////////////////////////////////////////////////////////////// + +// SPDX-FileCopyrightText: Simon Schneegans +// SPDX-License-Identifier: GPL-3.0-or-later + +'use strict'; + +const GObject = imports.gi.GObject; + +const _ = imports.gettext.domain('burn-my-windows').gettext; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const utils = Me.imports.src.utils; +const ShaderFactory = Me.imports.src.ShaderFactory.ShaderFactory; + +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// + +// The effect class can be used to get some metadata (like the effect's name or supported +// GNOME Shell versions), to initialize the respective page of the settings dialog, as +// well as to create the actual shader for the effect. +var Glitch = class { + + // The constructor creates a ShaderFactory which will be used by extension.js to create + // shader instances for this effect. The shaders will be automagically created using the + // GLSL file in resources/shaders/.glsl. The callback will be called for each + // newly created shader instance. + constructor() { + this.shaderFactory = new ShaderFactory(this.getNick(), (shader) => { + // We import Clutter in this function as it is not available in the preferences + // process. This creator function of the ShaderFactory is only called within GNOME + // Shell's process. + const Clutter = imports.gi.Clutter; + + // Store uniform locations of newly created shaders. + shader._uColor = shader.get_uniform_location('uColor'); + shader._uScale = shader.get_uniform_location('uScale'); + shader._uStrength = shader.get_uniform_location('uStrength'); + shader._uSpeed = shader.get_uniform_location('uSpeed'); + + // Write all uniform values at the start of each animation. + shader.connect('begin-animation', (shader, settings) => { + const c = Clutter.Color.from_string(settings.get_string('glitch-color'))[1]; + + // clang-format off + shader.set_uniform_float(shader._uColor, 3, [c.red / 255, c.green / 255, c.blue / 255]); + shader.set_uniform_float(shader._uScale, 1, [settings.get_double('glitch-scale')]); + shader.set_uniform_float(shader._uStrength, 1, [settings.get_double('glitch-strength')]); + shader.set_uniform_float(shader._uSpeed, 1, [settings.get_double('glitch-speed')]); + // clang-format on + }); + }); + } + + // ---------------------------------------------------------------------------- metadata + + // The effect is available on all GNOME Shell versions supported by this extension. + getMinShellVersion() { + return [3, 36]; + } + + // This will be called in various places where a unique identifier for this effect is + // required. It should match the prefix of the settings keys which store whether the + // effect is enabled currently (e.g. '*-close-effect'), and its animation time + // (e.g. '*-animation-time'). + getNick() { + return 'glitch'; + } + + // This will be shown in the sidebar of the preferences dialog as well as in the + // drop-down menus where the user can choose the effect. + getLabel() { + return _('Glitch'); + } + + // -------------------------------------------------------------------- API for prefs.js + + // This is called by the preferences dialog. It loads the settings page for this effect, + // and binds all properties to the settings. + getPreferences(dialog) { + + // Add the settings page to the builder. + dialog.getBuilder().add_from_resource(`/ui/${utils.getUIDir()}/Glitch.ui`); + + // Bind all properties. + dialog.bindAdjustment('glitch-animation-time'); + dialog.bindAdjustment('glitch-scale'); + dialog.bindAdjustment('glitch-speed'); + dialog.bindAdjustment('glitch-strength'); + dialog.bindColorButton('glitch-color'); + + // Finally, return the new settings page. + return dialog.getBuilder().get_object('glitch-prefs'); + } + + // ---------------------------------------------------------------- API for extension.js + + // The getActorScale() is called from extension.js to adjust the actor's size during the + // animation. This is useful if the effect requires drawing something beyond the usual + // bounds of the actor. This only works for GNOME 3.38+. + getActorScale(settings) { + return {x: 1.0, y: 1.0}; + } +} \ No newline at end of file diff --git a/tests/generate-references.sh b/tests/generate-references.sh index 81a3210..45fdfbd 100755 --- a/tests/generate-references.sh +++ b/tests/generate-references.sh @@ -182,6 +182,7 @@ capture_effect "energize-a" capture_effect "energize-b" capture_effect "fire" capture_effect "glide" +capture_effect "glitch" capture_effect "hexagon" capture_effect "incinerate" capture_effect "pixelate" diff --git a/tests/run-test.sh b/tests/run-test.sh index 177ea53..d570a57 100755 --- a/tests/run-test.sh +++ b/tests/run-test.sh @@ -207,6 +207,7 @@ test_effect "energize-a" test_effect "energize-b" test_effect "fire" test_effect "glide" +test_effect "glitch" test_effect "hexagon" test_effect "incinerate" test_effect "pixelate"