diff --git a/assets/README.md b/assets/README.md new file mode 100644 index 0000000..b71ffb7 --- /dev/null +++ b/assets/README.md @@ -0,0 +1,7 @@ +# Notes for `claws.blend` + +This is the source file for `resources/img/claws.png`. To generate the image, the animation in `claws.blend` is rendered to 256 PNG files and then combined using this command: + +```bash +convert *.png -average claws.png +``` \ No newline at end of file diff --git a/assets/claws.blend b/assets/claws.blend new file mode 100644 index 0000000..ee3bb06 Binary files /dev/null and b/assets/claws.blend differ diff --git a/docs/changelog.md b/docs/changelog.md index f001f32..60612ae 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -6,6 +6,7 @@ #### New Features +* Added a new ridiculous close-animation: the T-Rex-Attack! * Added a new simple close-animation: the TV-Effect! #### Other Enhancements diff --git a/extension.js b/extension.js index 531a85e..f186385 100644 --- a/extension.js +++ b/extension.js @@ -25,6 +25,7 @@ const utils = Me.imports.src.common.utils; const FireShader = Me.imports.src.extension.FireShader.FireShader; const MatrixShader = Me.imports.src.extension.MatrixShader.MatrixShader; const TVEffectShader = Me.imports.src.extension.TVEffectShader.TVEffectShader; +const TRexShader = Me.imports.src.extension.TRexShader.TRexShader; ////////////////////////////////////////////////////////////////////////////////////////// // This extensions modifies the window-close animation to look like the window was set // @@ -158,6 +159,12 @@ class Extension { } else if (mode == 3) { shader = new TVEffectShader(this._settings); tweakTransition('scale-y', 0.5); + } else if (mode == 4) { + shader = new TRexShader(this._settings); + + const warp = 0.5 * this._settings.get_double('claw-scratch-warp'); + tweakTransition('scale-x', 1.0 + warp); + tweakTransition('scale-y', 1.0 + warp); } if (shader) { diff --git a/prefs.js b/prefs.js index 562b30c..ec05e87 100644 --- a/prefs.js +++ b/prefs.js @@ -58,8 +58,12 @@ var PreferencesDialog = class PreferencesDialog { this._bindColorButton('matrix-trail-color'); this._bindColorButton('matrix-tip-color'); this._bindColorButton('tv-effect-color'); + this._bindColorButton('claw-scratch-color'); + this._bindAdjustment('claw-scratch-scale'); + this._bindAdjustment('claw-scratch-count'); + this._bindAdjustment('claw-scratch-warp'); - // The fire-gradient-reset button needs to by bound explicitly. + // The fire-gradient-reset button needs to be bound explicitly. this._builder.get_object('reset-fire-colors').connect('clicked', () => { this._settings.reset('fire-color-1'); this._settings.reset('fire-color-2'); diff --git a/resources/img/claws.png b/resources/img/claws.png new file mode 100644 index 0000000..9a21cac Binary files /dev/null and b/resources/img/claws.png differ diff --git a/resources/ui/gtk4.ui b/resources/ui/gtk4.ui index dbcc828..f0fefb9 100644 --- a/resources/ui/gtk4.ui +++ b/resources/ui/gtk4.ui @@ -20,6 +20,10 @@ TV Effect tv + + T-Rex Attack + trex + @@ -574,6 +578,211 @@ + + + 30 + 10 + + + T-Rex Attack Options + 0 + 1 + + + + + + + + + + + none + 1 + + + + + 0 + + + + + Claw Scratch Scale + 0 + start + center + 1 + + + + + end + center + 1 + 1 + left + 300 + + + 10 + 0.1 + 0.1 + 1 + + + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + 0 + + + + + Claw Scratch Count + 0 + start + center + 1 + + + + + end + center + 1 + 0 + left + 300 + + + 50 + 1 + 1 + 10 + + + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + 0 + + + + + Warp Effect + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + + + 1 + 0 + 0.01 + 0.1 + + + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + 0 + + + + + Flash Color + 0 + start + center + 1 + + + + + 1 + 1 + + + + + edit-clear-symbolic + Reset to Default Value + + + + + + + + + + + + + + 30 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 ec84354..08e45c5 100644 --- a/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml +++ b/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml @@ -5,6 +5,7 @@ + @@ -95,6 +96,7 @@ The color matrix trails. + "rgb(255, 255, 255)" TV Effect Color @@ -102,6 +104,31 @@ + + "rgb(170, 0, 0)" + Claw Scratch Color + The color of the claw scratches. + + + + 1.0 + Claw Scratch Scale + Size of the claw scratches. + + + + 0.15 + Claw Scratch Warp + Intensity of the claw scratch warp effect. + + + + 5 + Claw Scratch Count + Number of claw scratches drawn on top of each other. + + + \ No newline at end of file diff --git a/src/extension/TRexShader.js b/src/extension/TRexShader.js new file mode 100644 index 0000000..6ae0db6 --- /dev/null +++ b/src/extension/TRexShader.js @@ -0,0 +1,157 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ) ( // +// ( /( ( ( ) ( ( ( ( )\ ) ( ( // +// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( // +// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ // +// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) // +// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< // +// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ // +// |__/ // +// Copyright (c) 2021 Simon Schneegans // +// Released under the GPLv3 or later. See LICENSE file for details. // +////////////////////////////////////////////////////////////////////////////////////////// + +'use strict'; + +const {Clutter, GObject, GdkPixbuf, Cogl} = imports.gi; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = imports.misc.extensionUtils.getCurrentExtension(); +const shaderSnippets = Me.imports.src.extension.shaderSnippets; + +////////////////////////////////////////////////////////////////////////////////////////// +// This effect tears your windows apart with a series of violent scratches! // +// This effect is not available on GNOME 3.3x, due to the limitation described in the // +// documentation of vfunc_paint_target further down in this file. // +////////////////////////////////////////////////////////////////////////////////////////// + +var TRexShader = GObject.registerClass({Properties: {}, Signals: {}}, + class TRexShader extends Clutter.ShaderEffect { + _init(settings) { + super._init({shader_type: Clutter.ShaderType.FRAGMENT_SHADER}); + + // Load the claw texture. As the shader is re-created for each window animation, this + // texture is also re-created each time. This could be improved in the future! + // See assets/README.md for how this texture was created. + const clawData = GdkPixbuf.Pixbuf.new_from_resource('/img/claws.png'); + this._clawTexture = new Clutter.Image(); + this._clawTexture.set_data( + clawData.get_pixels(), Cogl.PixelFormat.RGB_888, clawData.width, clawData.height, + clawData.rowstride); + + const color = Clutter.Color.from_string(settings.get_string('claw-scratch-color'))[1]; + + this.set_shader_source(` + + // Inject some common shader snippets. + ${shaderSnippets.standardUniforms()} + ${shaderSnippets.noise()} + + // See assets/README.md for how this texture was created. + uniform sampler2D uClawTexture; + + const vec2 SEED = vec2(${Math.random()}, ${Math.random()}); + const float CLAW_SIZE = ${settings.get_double('claw-scratch-scale')}; + const float NUM_CLAWS = ${settings.get_int('claw-scratch-count')}; + const float WARP_INTENSITY = 1.0 + ${settings.get_double('claw-scratch-warp')}; + const float FLASH_INTENSITY = 0.1; + const float MAX_SPAWN_TIME = 0.5; // Scratches will only start in the first half of the animation. + const float FF_TIME = 0.5; // Relative time for the final fade to transparency. + + // This method generates a grid of randomly rotated, slightly shifted and scaled + // UV squares. It returns the texture coords of the UV square at the given actor + // coordinates. If these do not fall into one of the UV grids, the coordinates of + // the closest UV grid will be clamped and returned. + vec2 getClawUV(vec2 texCoords, float gridScale, vec2 seed) { + + // Shift coordinates by a random offset and make sure the have a 1:1 aspect ratio. + vec2 coords = texCoords + rand2(seed); + coords *= uSizeX < uSizeY ? vec2(1.0, 1.0 * uSizeY / uSizeX) : vec2(1.0 * uSizeX / uSizeY, 1.0); + + // Apply global scale. + coords *= gridScale; + + // Get grid cell coordinates in [0..1]. + vec2 cellUV = mod(coords, vec2(1)); + + // This is unique for each cell. + vec2 cellID = coords-cellUV + vec2(362.456); + + // Add random rotation, scale and offset to each grid cell. + float scale = mix(0.8, 1.0, rand(cellID*seed*134.451)); + float offsetX = mix(0.0, 1.0 - scale, rand(cellID*seed*54.4129)); + float offsetY = mix(0.0, 1.0 - scale, rand(cellID*seed*25.3089)); + float rotation = mix(0.0, 2.0 * 3.141, rand(cellID*seed*2.99837)); + + cellUV -= vec2(offsetX, offsetY); + cellUV /= scale; + + cellUV -= 0.5; + cellUV = vec2(cellUV.x * cos(rotation) - cellUV.y * sin(rotation), + cellUV.x * sin(rotation) + cellUV.y * cos(rotation)); + cellUV += 0.5; + + // Clamp resulting coordinates. + return clamp(cellUV, vec2(0), vec2(1)); + } + + void main() { + + // Warp the texture coordinates to create a blow-up effect. + vec2 coords = cogl_tex_coord_in[0].st * 2.0 - 1.0; + float dist = length(coords); + coords = (coords/dist * pow(dist, WARP_INTENSITY)) * 0.5 + 0.5; + coords = mix(cogl_tex_coord_in[0].st, coords, uProgress); + + // Accumulate several random scratches. The color in the scratch map refers to the + // relative time when the respective part will become invisible. Therefore we can + // add a value to make the scratch appear later. + float scratchMap = 1.0; + for (int i=0; i uProgress ? 1 : 0); + + // Add colorful flashes. + float flashIntensity = 1.0 / FLASH_INTENSITY * (scratchMap - uProgress) + 1; + if (flashIntensity < 0 || flashIntensity >= 1) { + flashIntensity = 0; + } + + vec3 flashColor = vec3(${color.red / 255}, + ${color.green / 255}, + ${color.blue / 255}) * ${color.alpha / 255}; + + cogl_color_out.rgb += flashIntensity * mix(flashColor, vec3(0), uProgress); + + // Fade out the remaining shards. + float fade = smoothstep(0, 1, 1 - clamp((uProgress - 1.0 + FF_TIME)/FF_TIME, 0, 1)); + cogl_color_out *= fade; + + // These are pretty useful for understanding how this works. + // cogl_color_out = vec4(vec3(flashIntensity), 1); + // cogl_color_out = vec4(vec3(scratchMap), 1); + } + `); + }; + + // This is overridden to bind the claw texture for drawing. Sadly, this seems to be + // impossible under GNOME 3.3x as this.get_pipeline() is not available. It was called + // get_target() back then but this is not wrapped in GJS. + // https://gitlab.gnome.org/GNOME/mutter/-/blob/gnome-3-36/clutter/clutter/clutter-offscreen-effect.c#L598 + vfunc_paint_target(node, paint_context) { + const pipeline = this.get_pipeline(); + pipeline.set_layer_texture(1, this._clawTexture.get_texture()); + this.set_uniform_value('uClawTexture', 1); + super.vfunc_paint_target(node, paint_context); + } +}); \ No newline at end of file