diff --git a/Makefile b/Makefile index 4931975..b0618eb 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ZIP_NAME := $(NAME)@$(DOMAIN).zip # Some of the recipes below depend on some of these files. JS_FILES = $(shell find -type f -and \( -name "*.js" \)) -UI_FILES = $(shell find -type f -and \( -name "*.ui" \)) +UI_FILES = $(shell find resources -type f -and \( -name "*.ui" \)) RESOURCE_FILES = $(shell find resources -mindepth 2 -type f) LOCALES_PO = $(wildcard po/*.po) LOCALES_MO = $(patsubst po/%.po,locale/%/LC_MESSAGES/$(NAME).mo,$(LOCALES_PO)) diff --git a/README.md b/README.md index acea9fc..e541b71 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ Effect | Preview **Energize B**
Using different transporter technology results in an alternative visual effect. | **Fire**
The classic effect inspired by Compiz. However, this is implemented using a GLSL shader and not with a particle system like in the old days. | **Hexagon**
With glowing lines and hexagon-shaped tiles, this effect looks very sci-fi. | +**Incinerate**
A less snappy but definitely more fancy take on the fire effect. | **Matrix**
Turn your windows into a shower of green letters! The color is actually configurable.| **Snap of Disintegration**
Dissolve your windows into a cloud of dust.| **T-Rex Attack**
Destroy your windows with a series of violent slashes!| @@ -46,18 +47,19 @@ Below is a table which summarizes the current availability for all effects. GNOME KWin - 3.363.384041425.25 -Apparition ✅ ✅✅✅ -Broken Glass ✅✅✅ -Energize A ✅ ✅ ✅✅✅✅ -Energize B ✅ ✅ ✅✅✅✅ -Fire ✅ ✅ ✅✅✅✅ -Hexagon ✅ ✅ ✅✅✅✅ -Matrix ✅✅✅ -Snap of Disintegration ✅✅✅ -T-Rex Attack ✅✅✅ -TV-Effect ✅ ✅ ✅✅✅✅ -Wisps ✅ ✅ ✅✅✅✅ + 3.363.384041425.25.0 +Apparition ✅ ✅✅✅ +Broken Glass ✅✅✅ +Energize A ✅ ✅ ✅✅✅✅ +Energize B ✅ ✅ ✅✅✅✅ +Fire ✅ ✅ ✅✅✅✅ +Hexagon ✅ ✅ ✅✅✅✅ +Incinerate ✅ ✅ ✅✅✅✅ +Matrix ✅✅✅ +Snap of Disintegration ✅✅✅ +T-Rex Attack ✅✅✅ +TV-Effect ✅ ✅ ✅✅✅✅ +Wisps ✅ ✅ ✅✅✅✅ @@ -85,6 +87,7 @@ While [coding new features](docs/how-to-create-new-effects.md) or [translating t

🏅 Previous Sponsors and One-Time Donators

+ @wolfyrion
@MrTomRod
Pouhiou
DAPREMONT Christophe
diff --git a/docs/changelog.md b/docs/changelog.md index fba0b60..b82a883 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -6,6 +6,7 @@ #### New Features +* **New Effect: Incinerate.** This is a completely new take on the fire effect. It is a bit more demanding in terms of GPU power, but at the same time it looks much more awesome! * **Initial KDE Support.** Thanks to the [awesome work](https://invent.kde.org/plasma/kwin/-/merge_requests/2227) of Martin Flöser, it has become possible to port some of its effects to KDE Plasma! For now, only the most simple effects can be ported, but hopefully this list can be improved in the future. * An option has been added which allows to automatically disable all effects if running on battery power. diff --git a/docs/pics/incinerate.gif b/docs/pics/incinerate.gif new file mode 100644 index 0000000..fe78260 Binary files /dev/null and b/docs/pics/incinerate.gif differ diff --git a/extension.js b/extension.js index f11aba8..067ab2e 100644 --- a/extension.js +++ b/extension.js @@ -56,6 +56,7 @@ class Extension { new Me.imports.src.EnergizeB.EnergizeB(), new Me.imports.src.Fire.Fire(), new Me.imports.src.Hexagon.Hexagon(), + new Me.imports.src.Incinerate.Incinerate(), new Me.imports.src.Matrix.Matrix(), new Me.imports.src.SnapOfDisintegration.SnapOfDisintegration(), new Me.imports.src.TRexAttack.TRexAttack(), diff --git a/kwin/build.sh b/kwin/build.sh index 316e54e..4153729 100755 --- a/kwin/build.sh +++ b/kwin/build.sh @@ -128,6 +128,7 @@ generate "energize-a" "[BMW] Energize A" "Beam your windows away" generate "energize-b" "[BMW] Energize B" "Using different transporter technology results in an alternative visual effect" generate "fire" "[BMW] Fire" "The classic effect inspired by Compiz" generate "hexagon" "[BMW] Hexagon" "With glowing lines and hexagon-shaped tiles, this effect looks very sci-fi" +generate "incinerate" "[BMW] Incinerate" "A less snappy but definitely more fancy take on the fire effect" generate "tv" "[BMW] TV Effect" "Make windows close like turning off a TV" generate "wisps" "[BMW] Wisps" "Let your windows be carried away to the realm of dreams by these little fairies" diff --git a/kwin/incinerate/config.ui b/kwin/incinerate/config.ui new file mode 100755 index 0000000..b745eb1 --- /dev/null +++ b/kwin/incinerate/config.ui @@ -0,0 +1,117 @@ + + + BMWConfigForm + + + + 0 + 0 + 562 + 365 + + + + + + + true + + + + + + + 0.100000000000000 + + + 10.000000000000000 + + + 0.1 + + + + + + + milliseconds + + + 100 + + + 9999 + + + 100 + + + + + + + Duration: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Color: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_Color + + + + + + + Scale: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + kcfg_Color + + + + + + + Turbulence: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 1.000000000000000 + + + 0.1 + + + + + + + + KColorButton + QPushButton +

kcolorbutton.h
+ + + + + \ No newline at end of file diff --git a/kwin/incinerate/main.xml b/kwin/incinerate/main.xml new file mode 100755 index 0000000..8f8e8f0 --- /dev/null +++ b/kwin/incinerate/main.xml @@ -0,0 +1,19 @@ + + + + + + 2000 + + + 1 + + + 0.3 + + + #ffb47f + + + \ No newline at end of file diff --git a/kwin/incinerate/onSettingsChanged.js b/kwin/incinerate/onSettingsChanged.js new file mode 100644 index 0000000..8437459 --- /dev/null +++ b/kwin/incinerate/onSettingsChanged.js @@ -0,0 +1,9 @@ +// This part is automatically included in the effect's source during the build process. +// The code below is called whenever the user changes something in the configuration of +// the effect. + +effect.setUniform(this.shader, 'uSeed', [Math.random(), Math.random()]); +effect.setUniform(this.shader, 'uDuration', this.duration * 0.001); +effect.setUniform(this.shader, 'uColor', this.readRGBConfig('Color')); +effect.setUniform(this.shader, 'uScale', effect.readConfig('Scale', 1.0)); +effect.setUniform(this.shader, 'uTurbulence', effect.readConfig('Turbulence', 1.0)); \ No newline at end of file diff --git a/po/burn-my-windows.pot b/po/burn-my-windows.pot index a93f228..c4da0d2 100644 --- a/po/burn-my-windows.pot +++ b/po/burn-my-windows.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: burn-my-windows\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-05-25 12:59+0200\n" +"POT-Creation-Date: 2022-06-25 05:04+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,41 +17,41 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: prefs.js:113 +#: prefs.js:114 msgid "Effect Options" msgstr "" -#: prefs.js:141 +#: prefs.js:142 msgid "Go Back" msgstr "" -#: prefs.js:183 +#: prefs.js:184 msgid "General Options" msgstr "" -#: prefs.js:277 +#: prefs.js:278 msgid "Gold Sponsors" msgstr "" -#: prefs.js:280 +#: prefs.js:281 msgid "Silver Sponsors" msgstr "" -#: prefs.js:283 +#: prefs.js:284 msgid "Bronze Sponsors" msgstr "" -#: prefs.js:286 +#: prefs.js:287 msgid "Past Sponsors" msgstr "" #. Translators: %s will be replaced by the effect's name. -#: prefs.js:509 +#: prefs.js:510 #, javascript-format msgid "Preview for %s" msgstr "" -#: prefs.js:531 +#: prefs.js:532 msgid "Close this Window to Preview the Effect!" msgstr "" @@ -71,6 +71,10 @@ msgstr "" msgid "Snap of Disintegration" msgstr "" +#: src/Incinerate.js:87 +msgid "Incinerate" +msgstr "" + #: src/Wisps.js:85 msgid "Wisps" msgstr "" @@ -148,15 +152,15 @@ msgid "About Burn-My-Windows" msgstr "" #: resources/ui/gtk4/Matrix.ui:24 resources/ui/gtk4/BrokenGlass.ui:24 -#: resources/ui/gtk4/Wisps.ui:24 resources/ui/gtk4/Fire.ui:49 -#: resources/ui/gtk4/SnapOfDisintegration.ui:24 +#: resources/ui/gtk4/Incinerate.ui:24 resources/ui/gtk4/Wisps.ui:24 +#: resources/ui/gtk4/Fire.ui:49 resources/ui/gtk4/SnapOfDisintegration.ui:24 #: resources/ui/gtk4/TRexAttack.ui:24 resources/ui/gtk4/TVEffect.ui:24 #: resources/ui/gtk4/EnergizeA.ui:24 resources/ui/gtk4/Hexagon.ui:24 #: resources/ui/gtk4/EnergizeB.ui:24 resources/ui/gtk4/Apparition.ui:24 -#: resources/ui/gtk3/Wisps.ui:42 resources/ui/gtk3/Fire.ui:93 -#: resources/ui/gtk3/TVEffect.ui:35 resources/ui/gtk3/EnergizeA.ui:42 -#: resources/ui/gtk3/Hexagon.ui:49 resources/ui/gtk3/EnergizeB.ui:42 -#: resources/ui/gtk3/Apparition.ui:63 +#: resources/ui/gtk3/Incinerate.ui:49 resources/ui/gtk3/Wisps.ui:42 +#: resources/ui/gtk3/Fire.ui:93 resources/ui/gtk3/TVEffect.ui:35 +#: resources/ui/gtk3/EnergizeA.ui:42 resources/ui/gtk3/Hexagon.ui:49 +#: resources/ui/gtk3/EnergizeB.ui:42 resources/ui/gtk3/Apparition.ui:63 msgid "Animation Time [ms]" msgstr "" @@ -165,7 +169,9 @@ msgstr "" #: resources/ui/gtk4/Matrix.ui:224 resources/ui/gtk4/Matrix.ui:258 #: resources/ui/gtk4/BrokenGlass.ui:52 resources/ui/gtk4/BrokenGlass.ui:98 #: resources/ui/gtk4/BrokenGlass.ui:144 resources/ui/gtk4/BrokenGlass.ui:190 -#: resources/ui/gtk4/BrokenGlass.ui:244 resources/ui/gtk4/Wisps.ui:52 +#: resources/ui/gtk4/BrokenGlass.ui:244 resources/ui/gtk4/Incinerate.ui:52 +#: resources/ui/gtk4/Incinerate.ui:98 resources/ui/gtk4/Incinerate.ui:144 +#: resources/ui/gtk4/Incinerate.ui:178 resources/ui/gtk4/Wisps.ui:52 #: resources/ui/gtk4/Wisps.ui:98 resources/ui/gtk4/Wisps.ui:132 #: resources/ui/gtk4/Fire.ui:77 resources/ui/gtk4/Fire.ui:123 #: resources/ui/gtk4/Fire.ui:169 resources/ui/gtk4/Fire.ui:222 @@ -182,7 +188,9 @@ msgstr "" #: resources/ui/gtk4/prefs.ui:166 resources/ui/gtk4/prefs.ui:200 #: resources/ui/gtk4/Apparition.ui:52 resources/ui/gtk4/Apparition.ui:98 #: resources/ui/gtk4/Apparition.ui:144 resources/ui/gtk4/Apparition.ui:190 -#: resources/ui/gtk4/Apparition.ui:236 resources/ui/gtk3/Wisps.ui:68 +#: resources/ui/gtk4/Apparition.ui:236 resources/ui/gtk3/Incinerate.ui:75 +#: resources/ui/gtk3/Incinerate.ui:124 resources/ui/gtk3/Incinerate.ui:173 +#: resources/ui/gtk3/Incinerate.ui:216 resources/ui/gtk3/Wisps.ui:68 #: resources/ui/gtk3/Wisps.ui:117 resources/ui/gtk3/Wisps.ui:160 #: resources/ui/gtk3/Fire.ui:119 resources/ui/gtk3/Fire.ui:167 #: resources/ui/gtk3/Fire.ui:215 resources/ui/gtk3/Fire.ui:277 @@ -201,12 +209,13 @@ msgid "Reset to Default Value" msgstr "" #: resources/ui/gtk4/Matrix.ui:70 resources/ui/gtk4/BrokenGlass.ui:70 -#: resources/ui/gtk4/Wisps.ui:70 resources/ui/gtk4/Fire.ui:95 -#: resources/ui/gtk4/SnapOfDisintegration.ui:70 +#: resources/ui/gtk4/Incinerate.ui:70 resources/ui/gtk4/Wisps.ui:70 +#: resources/ui/gtk4/Fire.ui:95 resources/ui/gtk4/SnapOfDisintegration.ui:70 #: resources/ui/gtk4/EnergizeA.ui:70 resources/ui/gtk4/Hexagon.ui:70 -#: resources/ui/gtk4/EnergizeB.ui:70 resources/ui/gtk3/Wisps.ui:91 -#: resources/ui/gtk3/Fire.ui:141 resources/ui/gtk3/EnergizeA.ui:91 -#: resources/ui/gtk3/Hexagon.ui:98 resources/ui/gtk3/EnergizeB.ui:91 +#: resources/ui/gtk4/EnergizeB.ui:70 resources/ui/gtk3/Incinerate.ui:98 +#: resources/ui/gtk3/Wisps.ui:91 resources/ui/gtk3/Fire.ui:141 +#: resources/ui/gtk3/EnergizeA.ui:91 resources/ui/gtk3/Hexagon.ui:98 +#: resources/ui/gtk3/EnergizeB.ui:91 msgid "Scale" msgstr "" @@ -245,11 +254,16 @@ msgid "" "window." msgstr "" -#: resources/ui/gtk4/Wisps.ui:116 resources/ui/gtk4/SnapOfDisintegration.ui:116 +#: resources/ui/gtk4/Incinerate.ui:116 resources/ui/gtk3/Incinerate.ui:147 +msgid "Turbulence" +msgstr "" + +#: resources/ui/gtk4/Incinerate.ui:162 resources/ui/gtk4/Wisps.ui:116 +#: resources/ui/gtk4/SnapOfDisintegration.ui:116 #: resources/ui/gtk4/TVEffect.ui:70 resources/ui/gtk4/EnergizeA.ui:116 -#: resources/ui/gtk4/EnergizeB.ui:116 resources/ui/gtk3/Wisps.ui:139 -#: resources/ui/gtk3/TVEffect.ui:83 resources/ui/gtk3/EnergizeA.ui:139 -#: resources/ui/gtk3/EnergizeB.ui:139 +#: resources/ui/gtk4/EnergizeB.ui:116 resources/ui/gtk3/Incinerate.ui:195 +#: resources/ui/gtk3/Wisps.ui:139 resources/ui/gtk3/TVEffect.ui:83 +#: resources/ui/gtk3/EnergizeA.ui:139 resources/ui/gtk3/EnergizeB.ui:139 msgid "Color" msgstr "" diff --git a/prefs.js b/prefs.js index ef0a373..3bc0863 100644 --- a/prefs.js +++ b/prefs.js @@ -52,6 +52,7 @@ var PreferencesDialog = class PreferencesDialog { new Me.imports.src.EnergizeB.EnergizeB(), new Me.imports.src.Fire.Fire(), new Me.imports.src.Hexagon.Hexagon(), + new Me.imports.src.Incinerate.Incinerate(), new Me.imports.src.Matrix.Matrix(), new Me.imports.src.SnapOfDisintegration.SnapOfDisintegration(), new Me.imports.src.TRexAttack.TRexAttack(), diff --git a/resources/credits/sponsors.json b/resources/credits/sponsors.json index f79ec6c..705464f 100644 --- a/resources/credits/sponsors.json +++ b/resources/credits/sponsors.json @@ -12,6 +12,7 @@ "Angel Brielez" ], "past": [ + "@wolfyrion", "@MrTomRod", "Pouhiou", "DAPREMONT Christophe", diff --git a/resources/shaders/common.glsl b/resources/shaders/common.glsl index 80894b7..98507b1 100644 --- a/resources/shaders/common.glsl +++ b/resources/shaders/common.glsl @@ -98,7 +98,7 @@ uniform vec2 uSize; uniform float uPadding; // On GNOME, we set iTexCoord to be an alias for the cogl variables. -#define iTexCoord cogl_tex_coord_in[0] +vec2 iTexCoord = cogl_tex_coord_in[0].st; // Shell.GLSLEffect uses straight alpha. So we have to convert from premultiplied. vec4 getInputColor(vec2 coords) { @@ -124,6 +124,17 @@ vec4 alphaOver(vec4 under, vec4 over) { return vec4((over.rgb * over.a + under.rgb * under.a * (1.0 - over.a)) / alpha, alpha); } +// ------------------------------------------------------------------------- color helpers + +// Maps the given value from [0..1] to the given colors. +vec3 tritone(float val, vec3 shadows, vec3 midtones, vec3 highlights) { + if (val < 0.5) { + return mix(shadows, midtones, smoothstep(0.0, 1.0, val * 2.0)); + } + + return mix(midtones, highlights, smoothstep(0.0, 1.0, val * 2.0 - 1.0)); +} + // ---------------------------------------------------------------------- easing functions // Here are some basic easing function. More can be added if required! diff --git a/resources/shaders/incinerate.frag b/resources/shaders/incinerate.frag new file mode 100644 index 0000000..c33da41 --- /dev/null +++ b/resources/shaders/incinerate.frag @@ -0,0 +1,158 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ) ( // +// ( /( ( ( ) ( ( ( ( )\ ) ( ( // +// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( // +// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ // +// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) // +// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< // +// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ // +// |__/ // +// Copyright (c) 2021 Simon Schneegans // +// Released under the GPLv3 or later. See LICENSE file for details. // +////////////////////////////////////////////////////////////////////////////////////////// + +// The content from common.glsl is automatically prepended to each shader effect. + +uniform vec2 uSeed; +uniform vec3 uColor; +uniform float uScale; +uniform float uTurbulence; + +// This maps a given value in [0..1] to a color from the rgba color ramp +// [transparent black ... semi-transparent uColor ... opaque white]. +vec4 getFireColor(float val) { + return vec4(tritone(val, vec3(0.0), uColor, vec3(1.0)), val); +} + +void main() { + + // The burning fire edge is composed of multiple regions. The width of all regions is + // defined below. If a window is closed and the burning direction happens to be from top + // to bottom, the different zones are arragned like this: + // + // . . . . ^ + // . : .: . | smokeRange: In this zone, smoke and little ember + // . : : .. : : . | particles are drawn. + // : . .:.: .: :.. | + // ...:: ..: :: : . .. | + // :: ) .. : : ..: : . | ^ + // ( /( ( ( . .::. | | flameRange: Flames are drawn in this zone. + // )\()) ))\ )( . ( . | | + // ((_)\ /((_|()\ )\ ) | | ^ + // | |(_|_))( ((_)_(_/( v v | burnRange: In + // ///////////////////// <- hideThreshold: From here on, | this zone, a + // | / / / / / / / / / | ^ the window is hidden. | firery edge is + // | / / / / / / | | v drawn. + // | / / / / / | v scorchRange: The window becomes + // | | brownish and a subtle + // | | heat distortion effect + // | | kicks in. + // | | + // \___________________/ + // + // If a window is opened, the window texture is visible on the other side of the + // hideThreshold and the scorchRange is also flipped to the other side (so it is drawn + // below the flames and the smoke). + + // All widths depend on the configured scale of the effect. + float SCORCH_WIDTH = 0.2 * uScale; + float BURN_WIDTH = 0.03 * uScale; + float SMOKE_WIDTH = 0.9 * uScale; + float FLAME_WIDTH = 0.2 * uScale; + + // During the animation, the hideThreshold transitions from a small value to a larger + // value, so that all the above ranges are covered. + float hideThreshold = + mix(uForOpening ? 0.0 : -SCORCH_WIDTH, 1.0 + SMOKE_WIDTH, uProgress); + + // The individual ranges are now given by the current hideThreshold and the widths of + // the zones. + vec2 scorchRange = uForOpening ? vec2(hideThreshold - SCORCH_WIDTH, hideThreshold) + : vec2(hideThreshold, hideThreshold + SCORCH_WIDTH); + vec2 burnRange = vec2(hideThreshold - BURN_WIDTH, hideThreshold + BURN_WIDTH); + vec2 flameRange = vec2(hideThreshold - FLAME_WIDTH, hideThreshold); + vec2 smokeRange = vec2(hideThreshold - SMOKE_WIDTH, hideThreshold); + + // Now we compute a 2D gradient in [0..1] which covers the entire window. The dark + // regions will be burned first, the bright regions in the end. We mix a radial gradient + // with some noise. The center of the radial gradient is positioned somewhere at the + // window boundary. + vec2 center = uSeed.x > uSeed.y ? vec2(uSeed.x, floor(uSeed.y + 0.5)) + : vec2(floor(uSeed.x + 0.5), uSeed.y); + float circle = length(iTexCoord - center); + + vec2 uv = iTexCoord / uScale * uSize / 1.5; + float smokeNoise = + simplex2DFractal(uv * 0.01 + uSeed + uProgress * vec2(0.0, 0.3 * uDuration)); + + float gradient = + mix(circle, smokeNoise, 200.0 * uTurbulence * uScale / max(uSize.x, uSize.y)); + + // Now, based on the gradient and the ranges, we can compute masks for the individual + // zones. + float smokeMask = smoothstep(0.0, 1.0, (gradient - smokeRange.x) / SMOKE_WIDTH) * + getAbsoluteEdgeMask(100.0, 0.3); + float flameMask = smoothstep(0.0, 1.0, (gradient - flameRange.x) / FLAME_WIDTH) * + getAbsoluteEdgeMask(20.0, 0.0); + float fireMask = smoothstep(1.0, 0.0, abs(gradient - hideThreshold) / BURN_WIDTH); + float scorchMask = smoothstep(1.0, 0.0, (gradient - scorchRange.x) / SCORCH_WIDTH); + + if (uForOpening) { + scorchMask = 1.0 - scorchMask; + } + + // Now we retrieve the window color. We only show the window when the burning edge has + // passed. + vec4 oColor = vec4(0.0); + + if ((!uForOpening && gradient > hideThreshold) || + (uForOpening && gradient < hideThreshold)) { + + // We add some distortion in the scorch zone + vec2 distort = vec2(0.0); + + if (scorchRange.x < gradient && gradient < scorchRange.y) { + distort = vec2(dFdx(gradient), dFdy(gradient)) * scorchMask * 5.0; + } + + oColor = getInputColor(iTexCoord + distort); + } + + // Add smoke and embers. + if (smokeRange.x < gradient && gradient < smokeRange.y) { + float smoke = smokeMask * smokeNoise; + oColor = alphaOver(oColor, vec4(0.5 * vec3(smoke), smoke)); + + float emberNoise = simplex2DFractal( + uv * 0.05 + uSeed - smokeNoise * vec2(0.0, 0.3 * smokeMask * uDuration)); + float embers = clamp(pow(emberNoise + 0.3, 100.0), 0.0, 2.0) * smoke; + oColor += getFireColor(embers); + } + + // Add scorch effect. + if (scorchRange.x < gradient && gradient < scorchRange.y) { + oColor.rgb = mix(oColor.rgb, mix(oColor.rgb, vec3(0.1, 0.05, 0.02), 0.4), scorchMask); + } + + // Add trailing flames. + if (min(burnRange.x, flameRange.x) < gradient && + gradient < max(burnRange.y, flameRange.y)) { + float flameNoise = + simplex2DFractal(uv * 0.02 + uSeed + smokeNoise * vec2(0.0, 1.0 * uDuration) + + vec2(0.0, uProgress * uDuration)); + + if (flameRange.x < gradient && gradient < flameRange.y) { + float flame = clamp(pow(flameNoise + 0.3, 20.0), 0.0, 2.0) * flameMask; + flame += clamp(pow(flameNoise + 0.4, 10.0), 0.0, 2.0) * flameMask * flameMask * 0.1; + oColor += getFireColor(flame); + } + + // Add burning edge. + if (burnRange.x < gradient && gradient < burnRange.y) { + float fire = fireMask * pow(flameNoise + 0.4, 4.0) * oColor.a; + oColor += getFireColor(fire); + } + } + + setOutputColor(oColor); +} \ No newline at end of file diff --git a/resources/ui/gtk3/Incinerate.ui b/resources/ui/gtk3/Incinerate.ui new file mode 100644 index 0000000..808eba4 --- /dev/null +++ b/resources/ui/gtk3/Incinerate.ui @@ -0,0 +1,235 @@ + + + + + 10000 + 100 + 1 + 100 + + + + 10 + 0.1 + 0.01 + 0.1 + + + + 1 + 0 + 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 + incinerate-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 + incinerate-scale + + + + + + + edit-clear-symbolic + 1 + + + Reset to Default Value + + + + + + + + + + + 10 + 10 + 10 + 10 + 0 + + + 8 + + + Turbulence + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + incinerate-turbulence + + + + + + + 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/Incinerate.ui b/resources/ui/gtk4/Incinerate.ui new file mode 100644 index 0000000..958cd5e --- /dev/null +++ b/resources/ui/gtk4/Incinerate.ui @@ -0,0 +1,197 @@ + + + + + vertical + + + + + + none + 1 + + + + + 0 + + + + + Animation Time [ms] + 0 + start + center + 1 + + + + + end + center + 1 + 0 + left + 300 + + + 10000 + 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 + + + + + Turbulence + 0 + start + center + 1 + + + + + end + center + 1 + 2 + left + 300 + + + 1 + 0 + 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 7444661..50f69e0 100644 --- a/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml +++ b/schemas/org.gnome.shell.extensions.burn-my-windows.gschema.xml @@ -331,6 +331,46 @@ Use additive blending for the line and the glow. + + + + + + false + Incinerate Close Effect + Use the Incinerate effect for window closing. + + + + false + Incinerate Open Effect + Use the Incinerate effect for window opening. + + + + 2000 + Incinerate Animation Time + The time the Incinerate effect takes. + + + + 1.0 + Incinerate Scale + The scale of the effect. + + + + 0.3 + Incinerate Turbulence + The turbulence of the effect. + + + + "rgb(255, 180, 127)" + Incinerate Color + The color of the effect. + + diff --git a/src/Incinerate.js b/src/Incinerate.js new file mode 100644 index 0000000..dd3e777 --- /dev/null +++ b/src/Incinerate.js @@ -0,0 +1,117 @@ +////////////////////////////////////////////////////////////////////////////////////////// +// ) ( // +// ( /( ( ( ) ( ( ( ( )\ ) ( ( // +// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( // +// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ // +// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) // +// | '_ \ || | '_| ' \)) | ' \()| || | \ V V / | ' \)) _` / _ \ V V (_-< // +// |_.__/\_,_|_| |_||_| |_|_|_| \_, | \_/\_/|_|_||_|\__,_\___/\_/\_//__/ // +// |__/ // +// Copyright (c) 2021 Simon Schneegans // +// Released under the GPLv3 or later. See LICENSE file for details. // +////////////////////////////////////////////////////////////////////////////////////////// + +'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; + +////////////////////////////////////////////////////////////////////////////////////////// +// This effect burns windows to ashes. The fire starts at a random position at the // +// window's boundary and then burns through the window in a circular shape. // +////////////////////////////////////////////////////////////////////////////////////////// + +// 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 Incinerate = 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 these modules in this function as they are not available in the + // preferences process. This callback is only called within GNOME Shell's process. + const {Clutter} = imports.gi; + + // Store uniform locations of newly created shaders. + shader._uSeed = shader.get_uniform_location('uSeed'); + shader._uColor = shader.get_uniform_location('uColor'); + shader._uScale = shader.get_uniform_location('uScale'); + shader._uTurbulence = shader.get_uniform_location('uTurbulence'); + + // 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('incinerate-color'))[1]; + + // If we are currently performing integration test, the animation uses a fixed + // seed. + const testMode = settings.get_boolean('test-mode'); + + // clang-format off + shader.set_uniform_float(shader._uSeed, 2, [testMode ? 0 : Math.random(), testMode ? 0 : Math.random()]); + 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('incinerate-scale')]); + shader.set_uniform_float(shader._uTurbulence, 1, [settings.get_double('incinerate-turbulence')]); + // clang-format on + }); + }); + } + + // ---------------------------------------------------------------------------- metadata + + // This effect is available on all supported GNOME Shell versions. + 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 'incinerate'; + } + + // 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 _('Incinerate'); + } + + // -------------------------------------------------------------------- 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.getGTKString()}/Incinerate.ui`); + + // Bind all properties. + dialog.bindAdjustment('incinerate-animation-time'); + dialog.bindAdjustment('incinerate-scale'); + dialog.bindAdjustment('incinerate-turbulence'); + dialog.bindColorButton('incinerate-color'); + + // Finally, return the new settings page. + return dialog.getBuilder().get_object('incinerate-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 32416d7..45f26d4 100755 --- a/tests/generate-references.sh +++ b/tests/generate-references.sh @@ -170,6 +170,7 @@ capture_effect "energize-a" capture_effect "energize-b" capture_effect "fire" capture_effect "hexagon" +capture_effect "incinerate" capture_effect "tv" capture_effect "wisps" diff --git a/tests/references/incinerate-close-gnome-wayland-nested-32.png b/tests/references/incinerate-close-gnome-wayland-nested-32.png new file mode 100644 index 0000000..e509e00 Binary files /dev/null and b/tests/references/incinerate-close-gnome-wayland-nested-32.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-33.png b/tests/references/incinerate-close-gnome-wayland-nested-33.png new file mode 100644 index 0000000..5073673 Binary files /dev/null and b/tests/references/incinerate-close-gnome-wayland-nested-33.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-34.png b/tests/references/incinerate-close-gnome-wayland-nested-34.png new file mode 100644 index 0000000..902ffcb Binary files /dev/null and b/tests/references/incinerate-close-gnome-wayland-nested-34.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-35.png b/tests/references/incinerate-close-gnome-wayland-nested-35.png new file mode 100644 index 0000000..902ffcb Binary files /dev/null and b/tests/references/incinerate-close-gnome-wayland-nested-35.png differ diff --git a/tests/references/incinerate-close-gnome-wayland-nested-36.png b/tests/references/incinerate-close-gnome-wayland-nested-36.png new file mode 100644 index 0000000..9684afe Binary files /dev/null and b/tests/references/incinerate-close-gnome-wayland-nested-36.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-32.png b/tests/references/incinerate-close-gnome-xsession-32.png new file mode 100644 index 0000000..e509e00 Binary files /dev/null and b/tests/references/incinerate-close-gnome-xsession-32.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-33.png b/tests/references/incinerate-close-gnome-xsession-33.png new file mode 100644 index 0000000..5073673 Binary files /dev/null and b/tests/references/incinerate-close-gnome-xsession-33.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-34.png b/tests/references/incinerate-close-gnome-xsession-34.png new file mode 100644 index 0000000..22febf8 Binary files /dev/null and b/tests/references/incinerate-close-gnome-xsession-34.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-35.png b/tests/references/incinerate-close-gnome-xsession-35.png new file mode 100644 index 0000000..22febf8 Binary files /dev/null and b/tests/references/incinerate-close-gnome-xsession-35.png differ diff --git a/tests/references/incinerate-close-gnome-xsession-36.png b/tests/references/incinerate-close-gnome-xsession-36.png new file mode 100644 index 0000000..bf4760d Binary files /dev/null and b/tests/references/incinerate-close-gnome-xsession-36.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-32.png b/tests/references/incinerate-open-gnome-wayland-nested-32.png new file mode 100644 index 0000000..04aa1f7 Binary files /dev/null and b/tests/references/incinerate-open-gnome-wayland-nested-32.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-33.png b/tests/references/incinerate-open-gnome-wayland-nested-33.png new file mode 100644 index 0000000..4faa883 Binary files /dev/null and b/tests/references/incinerate-open-gnome-wayland-nested-33.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-34.png b/tests/references/incinerate-open-gnome-wayland-nested-34.png new file mode 100644 index 0000000..306d54a Binary files /dev/null and b/tests/references/incinerate-open-gnome-wayland-nested-34.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-35.png b/tests/references/incinerate-open-gnome-wayland-nested-35.png new file mode 100644 index 0000000..306d54a Binary files /dev/null and b/tests/references/incinerate-open-gnome-wayland-nested-35.png differ diff --git a/tests/references/incinerate-open-gnome-wayland-nested-36.png b/tests/references/incinerate-open-gnome-wayland-nested-36.png new file mode 100644 index 0000000..d5ef62d Binary files /dev/null and b/tests/references/incinerate-open-gnome-wayland-nested-36.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-32.png b/tests/references/incinerate-open-gnome-xsession-32.png new file mode 100644 index 0000000..04aa1f7 Binary files /dev/null and b/tests/references/incinerate-open-gnome-xsession-32.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-33.png b/tests/references/incinerate-open-gnome-xsession-33.png new file mode 100644 index 0000000..4faa883 Binary files /dev/null and b/tests/references/incinerate-open-gnome-xsession-33.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-34.png b/tests/references/incinerate-open-gnome-xsession-34.png new file mode 100644 index 0000000..0e7557b Binary files /dev/null and b/tests/references/incinerate-open-gnome-xsession-34.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-35.png b/tests/references/incinerate-open-gnome-xsession-35.png new file mode 100644 index 0000000..0e7557b Binary files /dev/null and b/tests/references/incinerate-open-gnome-xsession-35.png differ diff --git a/tests/references/incinerate-open-gnome-xsession-36.png b/tests/references/incinerate-open-gnome-xsession-36.png new file mode 100644 index 0000000..410b154 Binary files /dev/null and b/tests/references/incinerate-open-gnome-xsession-36.png differ diff --git a/tests/run-test.sh b/tests/run-test.sh index bca773f..38c9dd4 100755 --- a/tests/run-test.sh +++ b/tests/run-test.sh @@ -199,6 +199,7 @@ test_effect "energize-a" test_effect "energize-b" test_effect "fire" test_effect "hexagon" +test_effect "incinerate" test_effect "tv" test_effect "wisps"