🔀 Merge pull request #206 from Schneegans/feature/doom

This commit is contained in:
Simon Schneegans
2022-09-01 20:17:45 +02:00
committed by GitHub
271 changed files with 1049 additions and 45 deletions
+26 -11
View File
@@ -68,9 +68,29 @@ jobs:
run: | run: |
find $GITHUB_WORKSPACE -type f -and \( -name "*.sh" \) | xargs shellcheck find $GITHUB_WORKSPACE -type f -and \( -name "*.sh" \) | xargs shellcheck
references:
name: Generate References
runs-on: ubuntu-22.04
if: >
github.event_name == 'push' && contains(github.event.head_commit.message, '[generate-references]')
steps:
- uses: actions/checkout@v2
- name: Download Dependencies
run: |
sudo apt update -qq
sudo apt install gettext -qq
- name: Build Burn-My-Windows
run: make
- name: Generate References
run: sudo make references
- uses: actions/upload-artifact@v3
with:
name: references
path: tests/references/
build: build:
name: Run Tests name: Run Tests
runs-on: ubuntu-latest runs-on: ubuntu-22.04
if: > if: >
github.event_name == 'pull_request' || github.event_name == 'pull_request' ||
( contains(github.ref, 'main') && !contains(github.event.head_commit.message, '[no-ci]') ) || ( contains(github.ref, 'main') && !contains(github.event.head_commit.message, '[no-ci]') ) ||
@@ -86,25 +106,20 @@ jobs:
- '35' - '35'
- '36' - '36'
session: session:
#- 'gnome-xsession' Disabled for now as it miraculously fails on GitHub. Locally, all tests pass... - 'gnome-xsession'
- 'gnome-wayland-nested' - 'gnome-wayland-nested'
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Download Dependencies - name: Download Dependencies
run: | run: |
sudo apt update -qq sudo apt update -qq
sudo apt install gettext -qq sudo apt install gettext imagemagick -qq
- name: Build Burn-My-Windows - name: Build Burn-My-Windows
run: make run: make
- name: Test Burn-My-Windows - name: Test Burn-My-Windows
run: sudo $GITHUB_WORKSPACE/tests/run-test.sh -v ${{ matrix.version }} -s ${{ matrix.session }} run: sudo $GITHUB_WORKSPACE/tests/run-test.sh -v ${{ matrix.version }} -s ${{ matrix.session }}
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v3
if: failure() if: failure()
with: with:
name: log_${{ matrix.version }}_${{ matrix.session }} name: result_${{ matrix.version }}_${{ matrix.session }}
path: fail.log path: tests/output/
- uses: actions/upload-artifact@v2
if: failure()
with:
name: screen_${{ matrix.version }}_${{ matrix.session }}
path: fail.png
+2
View File
@@ -24,6 +24,7 @@ Effect | Preview
-----|-------- -----|--------
**Apparition** <br> This effect hides your windows by violently sucking them into the void of magic! | <img src ="docs/pics/apparition.gif" /> **Apparition** <br> This effect hides your windows by violently sucking them into the void of magic! | <img src ="docs/pics/apparition.gif" />
**Broken Glass** <br> Shatter your windows into a shower sharp shards! This effect can be configured so that the shards fly away from your mouse pointer position!| <img src ="docs/pics/glass.gif" /> **Broken Glass** <br> Shatter your windows into a shower sharp shards! This effect can be configured so that the shards fly away from your mouse pointer position!| <img src ="docs/pics/glass.gif" />
**Doom** <br> Melt your windows. Inspired by the legendary screen transitions of the original Doom. | <img src ="docs/pics/doom.gif" />
**Energize A** <br> Beam your windows away! | <img src ="docs/pics/energizeA.gif" /> **Energize A** <br> Beam your windows away! | <img src ="docs/pics/energizeA.gif" />
**Energize B** <br> Using different transporter technology results in an alternative visual effect. | <img src ="docs/pics/energizeB.gif" /> **Energize B** <br> Using different transporter technology results in an alternative visual effect. | <img src ="docs/pics/energizeB.gif" />
**Fire** <br> 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. | <img src ="docs/pics/fire.gif" /> **Fire** <br> 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. | <img src ="docs/pics/fire.gif" />
@@ -51,6 +52,7 @@ Below is a table which summarizes the current availability for all effects.
<tr><td></td> <td>3.36</td><td>3.38</td><td>40</td><td>41</td><td>42</td><td>5.25.0</td></tr> <tr><td></td> <td>3.36</td><td>3.38</td><td>40</td><td>41</td><td>42</td><td>5.25.0</td></tr>
<tr><td>Apparition</td> <td> </td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td> </td> </tr> <tr><td>Apparition</td> <td> </td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td> </td> </tr>
<tr><td>Broken Glass</td> <td> </td> <td> </td> <td>✅</td><td>✅</td><td>✅</td><td> </td> </tr> <tr><td>Broken Glass</td> <td> </td> <td> </td> <td>✅</td><td>✅</td><td>✅</td><td> </td> </tr>
<tr><td>Doom</td> <td> </td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td>✅</td> </tr>
<tr><td>Energize A</td> <td>✅</td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td>✅</td> </tr> <tr><td>Energize A</td> <td>✅</td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td>✅</td> </tr>
<tr><td>Energize B</td> <td>✅</td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td>✅</td> </tr> <tr><td>Energize B</td> <td>✅</td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td>✅</td> </tr>
<tr><td>Fire</td> <td>✅</td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td>✅</td> </tr> <tr><td>Fire</td> <td>✅</td> <td>✅</td> <td>✅</td><td>✅</td><td>✅</td><td>✅</td> </tr>
+3
View File
@@ -6,11 +6,14 @@
#### New Features #### New Features
* **New Effect: Doom.** Melt your windows. Inspired by the legendary screen transitions of the original Doom.
* **New Effect: Pixelate.** Pixelate your windows and randomly hide pixels until the entire window is gone. * **New Effect: Pixelate.** Pixelate your windows and randomly hide pixels until the entire window is gone.
#### Enhancements #### Enhancements
* Under KWin, the effects now use the same names as in the KDE store. * Under KWin, the effects now use the same names as in the KDE store.
* The continuous integration tests now use a fuzzy search for the images targets. This way, the test work again on X11 and Wayland.
* A new GitHub Actions workflow has been added which is executed whenever a commit message includes the `[generate-references]` tag. This workflow re-creates all reference images for the continuous integration test.
## [Burn My Windows 19](https://github.com/schneegans/Burn-My-Windows/releases/tag/v19) ## [Burn My Windows 19](https://github.com/schneegans/Burn-My-Windows/releases/tag/v19)
Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB

+2 -1
View File
@@ -52,6 +52,7 @@ class Extension {
this._ALL_EFFECTS = [ this._ALL_EFFECTS = [
new Me.imports.src.Apparition.Apparition(), new Me.imports.src.Apparition.Apparition(),
new Me.imports.src.BrokenGlass.BrokenGlass(), new Me.imports.src.BrokenGlass.BrokenGlass(),
new Me.imports.src.Doom.Doom(),
new Me.imports.src.EnergizeA.EnergizeA(), new Me.imports.src.EnergizeA.EnergizeA(),
new Me.imports.src.EnergizeB.EnergizeB(), new Me.imports.src.EnergizeB.EnergizeB(),
new Me.imports.src.Fire.Fire(), new Me.imports.src.Fire.Fire(),
@@ -434,7 +435,7 @@ class Extension {
// windows are faded in / out scaled up / down slightly by GNOME Shell. Here, we tweak // windows are faded in / out scaled up / down slightly by GNOME Shell. Here, we tweak
// the transitions so that nothing changes. The window stays opaque and is scaled to // the transitions so that nothing changes. The window stays opaque and is scaled to
// actorScale. // actorScale.
const actorScale = effect.getActorScale(this._settings); const actorScale = effect.getActorScale(this._settings, forOpening, actor);
// To make things deterministic during testing, we set the effect duration to 5 // To make things deterministic during testing, we set the effect duration to 5
// seconds. // seconds.
+1
View File
@@ -130,6 +130,7 @@ generate() {
generate "energize-a" "Energize A [Burn-My-Windows]" "Beam your windows away" generate "energize-a" "Energize A [Burn-My-Windows]" "Beam your windows away"
generate "energize-b" "Energize B [Burn-My-Windows]" "Using different transporter technology results in an alternative visual effect" generate "energize-b" "Energize B [Burn-My-Windows]" "Using different transporter technology results in an alternative visual effect"
generate "doom" "Doom [Burn-My-Windows]" "Melt your windows"
generate "fire" "Fire [Burn-My-Windows]" "The classic effect inspired by Compiz" generate "fire" "Fire [Burn-My-Windows]" "The classic effect inspired by Compiz"
generate "hexagon" "Hexagon [Burn-My-Windows]" "With glowing lines and hexagon-shaped tiles, this effect looks very sci-fi" generate "hexagon" "Hexagon [Burn-My-Windows]" "With glowing lines and hexagon-shaped tiles, this effect looks very sci-fi"
generate "incinerate" "Incinerate [Burn-My-Windows]" "A less snappy but definitely more fancy take on the fire effect" generate "incinerate" "Incinerate [Burn-My-Windows]" "A less snappy but definitely more fancy take on the fire effect"
+113
View File
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>BMWConfigForm</class>
<widget class="QWidget" name="BMWConfigForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>562</width>
<height>365</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="kcfg_HorizontalScale">
<property name="decimals">
<number>0</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>200.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Duration:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Horizontal Scale</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Pixel Size</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="kcfg_Duration">
<property name="suffix">
<string> milliseconds</string>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>9999</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="kcfg_PixelSize">
<property name="decimals">
<number>0</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>50.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="kcfg_VerticalScale">
<property name="decimals">
<number>0</number>
</property>
<property name="minimum">
<double>1.000000000000000</double>
</property>
<property name="maximum">
<double>200.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Vertical Scale</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
<kcfgfile name="" />
<group name="">
<entry name="Duration" type="UInt">
<default>500</default>
</entry>
<entry name="HorizontalScale" type="UInt">
<default>10</default>
</entry>
<entry name="VerticalScale" type="UInt">
<default>50</default>
</entry>
<entry name="PixelSize" type="UInt">
<default>10</default>
</entry>
</group>
</kcfg>
+12
View File
@@ -0,0 +1,12 @@
// 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.
// I have not yet found a way to scaling the actor canvas on KWin. So this effect cannot
// look as good as on GNOME.
effect.setUniform(this.shader, 'uActorScale', 1.0);
effect.setUniform(this.shader, 'uHorizontalScale',
effect.readConfig('HorizontalScale', 1.0));
effect.setUniform(this.shader, 'uVerticalScale', effect.readConfig('VerticalScale', 1.0));
effect.setUniform(this.shader, 'uPixelSize', effect.readConfig('PixelSize', 1.0));
+1 -1
View File
@@ -50,7 +50,7 @@
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Randomness</string> <string>Noise</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+1
View File
@@ -48,6 +48,7 @@ var PreferencesDialog = class PreferencesDialog {
this._ALL_EFFECTS = [ this._ALL_EFFECTS = [
new Me.imports.src.Apparition.Apparition(), new Me.imports.src.Apparition.Apparition(),
new Me.imports.src.BrokenGlass.BrokenGlass(), new Me.imports.src.BrokenGlass.BrokenGlass(),
new Me.imports.src.Doom.Doom(),
new Me.imports.src.EnergizeA.EnergizeA(), new Me.imports.src.EnergizeA.EnergizeA(),
new Me.imports.src.EnergizeB.EnergizeB(), new Me.imports.src.EnergizeB.EnergizeB(),
new Me.imports.src.Fire.Fire(), new Me.imports.src.Fire.Fire(),
+65
View File
@@ -0,0 +1,65 @@
//////////////////////////////////////////////////////////////////////////////////////////
// ) ( //
// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
// | '_ \ || | '_| ' \)) | ' \()| || | \ 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 float uActorScale;
uniform float uHorizontalScale;
uniform float uVerticalScale;
uniform float uPixelSize;
// This method returns a mask which smoothly transitions towards zero when approaching
// the window's top or bottom border.
float getEdgeMask(vec2 uv, float fadeWidth) {
float mask = 1.0;
mask *= smoothstep(0.0, 1.0, clamp(uv.y / fadeWidth, 0.0, 1.0));
mask *= smoothstep(0.0, 1.0, clamp((1.0 - uv.y) / fadeWidth, 0.0, 1.0));
return mask;
}
void main() {
// We simply inverse the pixelation progress for opening windows.
float pixelateProgress = uForOpening ? 0.9 - uProgress : uProgress;
float pixelSize = max(1.0, ceil(uPixelSize * pixelateProgress + 1.0));
vec2 pixelGrid = vec2(pixelSize) / uSize;
// Snap texcoords to pixel grid.
vec2 texcoord = iTexCoord.st;
texcoord.y = texcoord.y * uActorScale + 0.5 - uActorScale * 0.5;
texcoord -= mod(iTexCoord.st, pixelGrid);
texcoord += pixelGrid * 0.5;
// The pixel columns move vertically. The offset is generated with a random noise
// function.
float hScale = uHorizontalScale * uSize.x * 0.001;
float noise = simplex2DFractal(texcoord.xx * hScale) * 2.0 - 0.5;
// Shift the pixel columns vertically over time.
float vScale = uVerticalScale * uSize.y * 0.00002 * uActorScale;
float shiftProgress = uForOpening ? mix(-vScale - 1.0, 0.0, uProgress)
: mix(-vScale, 1.0 + vScale, uProgress);
float shift = noise * vScale + shiftProgress;
if (uForOpening) {
texcoord.y -= 0.5 * uActorScale * min(shift, 0.0);
} else {
texcoord.y -= 0.5 * uActorScale * max(shift, 0.0);
}
vec4 oColor = getInputColor(texcoord);
// Fade window texture at the top and bottom.
oColor.a *= getEdgeMask(iTexCoord.st, 0.1);
setOutputColor(oColor);
}
+248
View File
@@ -0,0 +1,248 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="burn-my-windows">
<object class="GtkAdjustment" id="doom-animation-time">
<property name="upper">10000</property>
<property name="lower">100</property>
<property name="step-increment">1</property>
<property name="page-increment">100</property>
</object>
<object class="GtkAdjustment" id="doom-horizontal-scale">
<property name="upper">50</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="doom-vertical-scale">
<property name="upper">50</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="doom-pixel-size">
<property name="upper">50</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkBox" id="doom-prefs">
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame">
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<style>
<class name="rich-list" />
</style>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Animation Time [ms]</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">0</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">doom-animation-time</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-animation-time">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Horizontal Scale</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">2</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">doom-horizontal-scale</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-horizontal-scale">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Vertical Scale</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">2</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">doom-vertical-scale</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-vertical-scale">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
<property name="margin-top">10</property>
<property name="margin-bottom">10</property>
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<property name="spacing">8</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Pixel Size</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">0</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">doom-pixel-size</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-pixel-size">
<child>
<object class="GtkImage">
<property name="icon-name">edit-clear-symbolic</property>
<property name="icon-size">1</property>
</object>
</child>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
+1 -1
View File
@@ -95,7 +95,7 @@
<property name="spacing">8</property> <property name="spacing">8</property>
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Scale</property> <property name="label" translatable="yes">Noise</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="halign">start</property> <property name="halign">start</property>
<property name="valign">center</property> <property name="valign">center</property>
+209
View File
@@ -0,0 +1,209 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface domain="burn-my-windows">
<object class="GtkBox" id="doom-prefs">
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame">
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<property name="show-separators">1</property>
<style>
<class name="rich-list" />
</style>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Animation Time [ms]</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">0</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">
<object class="GtkAdjustment" id="doom-animation-time">
<property name="upper">10000</property>
<property name="lower">100</property>
<property name="step-increment">1</property>
<property name="page-increment">100</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-animation-time">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Horizontal Scale</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">2</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">
<object class="GtkAdjustment" id="doom-horizontal-scale">
<property name="upper">50</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-horizontal-scale">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Vertical Scale</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">2</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">
<object class="GtkAdjustment" id="doom-vertical-scale">
<property name="upper">50</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-vertical-scale">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow">
<property name="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Pixel Size</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
</object>
</child>
<child>
<object class="GtkScale">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="draw-value">1</property>
<property name="digits">0</property>
<property name="value-pos">left</property>
<property name="width-request">300</property>
<property name="adjustment">
<object class="GtkAdjustment" id="doom-pixel-size">
<property name="upper">50</property>
<property name="lower">1</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-doom-pixel-size">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text" translatable="yes">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
+1 -1
View File
@@ -67,7 +67,7 @@
<object class="GtkBox"> <object class="GtkBox">
<child> <child>
<object class="GtkLabel"> <object class="GtkLabel">
<property name="label" translatable="yes">Randomness</property> <property name="label" translatable="yes">Noise</property>
<property name="xalign">0</property> <property name="xalign">0</property>
<property name="halign">start</property> <property name="halign">start</property>
<property name="valign">center</property> <property name="valign">center</property>
@@ -118,6 +118,46 @@
<description>The size of the maximum pixelation.</description> <description>The size of the maximum pixelation.</description>
</key> </key>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Doom Options -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<key name="doom-close-effect" type="b">
<default>false</default>
<summary>Doom Close Effect</summary>
<description>Use the Doom effect for window closing.</description>
</key>
<key name="doom-open-effect" type="b">
<default>false</default>
<summary>Doom Open Effect</summary>
<description>Use the Doom effect for window opening.</description>
</key>
<key name="doom-animation-time" type="i">
<default>1000</default>
<summary>Doom Animation Time</summary>
<description>The time the Doom effect takes.</description>
</key>
<key name="doom-horizontal-scale" type="d">
<default>10.0</default>
<summary>Doom Horizontal Scale</summary>
<description>The X scale of the effect.</description>
</key>
<key name="doom-vertical-scale" type="d">
<default>10.0</default>
<summary>Doom Vertical Scale</summary>
<description>The Y scale of the effect.</description>
</key>
<key name="doom-pixel-size" type="d">
<default>10</default>
<summary>Doom Pixel Size</summary>
<description>The size of the maximum pixelation.</description>
</key>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Fire Options --> <!-- Fire Options -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+120
View File
@@ -0,0 +1,120 @@
//////////////////////////////////////////////////////////////////////////////////////////
// ) ( //
// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
// | '_ \ || | '_| ' \)) | ' \()| || | \ 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 melts your windows. Inspired by the legendary screen transitions of the //
// original Doom. //
//////////////////////////////////////////////////////////////////////////////////////////
// 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 Doom = 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/<nick>.glsl. The callback will be called for each
// newly created shader instance.
constructor() {
this.shaderFactory = new ShaderFactory(this.getNick(), (shader) => {
// Store uniform locations of newly created shaders.
shader._uActorScale = shader.get_uniform_location('uActorScale');
shader._uHorizontalScale = shader.get_uniform_location('uHorizontalScale');
shader._uVerticalScale = shader.get_uniform_location('uVerticalScale');
shader._uPixelSize = shader.get_uniform_location('uPixelSize');
// Write all uniform values at the start of each animation.
shader.connect('begin-animation', (shader, settings, forOpening, actor) => {
// For this effect, we scale the actor vertically so that it covers the entire
// screen. This ensures that the melted window will not be cut off.
let actorScale = 2.0 * Math.max(1.0, global.stage.height / actor.height);
// If we are currently performing integration test, nothing will be visible in the
// test images as the animation has passed the center of the window already. To
// fix this, we set the actor scale to a fixed low value when performing tests.
const testMode = settings.get_boolean('test-mode');
// clang-format off
shader.set_uniform_float(shader._uActorScale, 1, [testMode ? 1.0 : actorScale]);
shader.set_uniform_float(shader._uHorizontalScale, 1, [testMode ? 50.0 :settings.get_double('doom-horizontal-scale')]);
shader.set_uniform_float(shader._uVerticalScale, 1, [testMode ? 150.0 : settings.get_double('doom-vertical-scale')]);
shader.set_uniform_float(shader._uPixelSize, 1, [settings.get_int('doom-pixel-size')]);
// clang-format on
});
});
}
// ---------------------------------------------------------------------------- metadata
// The effect is not available on GNOME Shell 3.36 as it requires scaling of the window
// actor.
getMinShellVersion() {
return [3, 38];
}
// 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 'doom';
}
// 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 _('Doom');
}
// -------------------------------------------------------------------- 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()}/Doom.ui`);
// Bind all properties.
dialog.bindAdjustment('doom-animation-time');
dialog.bindAdjustment('doom-horizontal-scale');
dialog.bindAdjustment('doom-vertical-scale');
dialog.bindAdjustment('doom-pixel-size');
// Finally, return the new settings page.
return dialog.getBuilder().get_object('doom-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+.
// For this effect, we scale the actor vertically so that it covers the entire screen.
// This ensures that the melted window will not be cut off.
getActorScale(settings, forOpening, actor) {
let actorScale = 2.0 * Math.max(1.0, global.stage.height / actor.height);
return {x: 1.0, y: actorScale};
}
}
+124
View File
@@ -0,0 +1,124 @@
#!/bin/bash
# -------------------------------------------------------------------------------------- #
# This script searches for a given image on the screen and prints the coordinates of the #
# upper left corner to STDOUT if it's found. If the image is not found, an exit code #
# of 1 is returned. #
# #
# -s scale_factor: In order to optimize the performance, both, the target image and the #
# screen capture is scaled down by 1 / scale_factor. Lower numbers can #
# help finding difficult targets but will also increase the calculation #
# time. Reasonable values are [1...10], default is 4. #
# -f fuzziness: A mean-squared-error threshold under which a location is considered #
# to be a match. Default is 0.01. Increase this to make finding a #
# target more likely but also increase the possibility of false #
# positives. #
# -------------------------------------------------------------------------------------- #
usage() {
echo "Usage: $0 -s scale_factor -f fuzziness screen.png target.png" >&2
}
SCALE_FACTOR=4
FUZZINESS=0.01
while getopts "s:f:h" opt; do
case $opt in
s) SCALE_FACTOR="${OPTARG}";;
f) FUZZINESS="${OPTARG}";;
h) usage; exit 0;;
*) usage; exit 1;;
esac
done
shift $((OPTIND-1))
SCREEN=$1
TARGET=$2
# Make sure the screen image is given.
if [[ -z "${SCREEN}" ]]; then
usage
exit 1
fi
# Make sure the target image is given.
if [[ -z "${TARGET}" ]]; then
usage
exit 1
fi
# Create a temporary directory.
WORK_DIR=$(mktemp -d)
if [[ ! "${WORK_DIR}" || ! -d "${WORK_DIR}" ]]; then
echo "Failed to create tmp directory!" >&2
exit 1
fi
# Deletes the temp directory on exit.
function cleanup {
rm -r "${WORK_DIR}"
}
trap cleanup EXIT
# Reduce the size of the screen capture and the target to optimize the search performance.
convert "${SCREEN}" -resize $((100 / SCALE_FACTOR))% "${WORK_DIR}/screen_small.png"
convert "${TARGET}" -resize $((100 / SCALE_FACTOR))% "${WORK_DIR}/target_small.png"
# Make a search on the reduced images.
RESULT=$(compare -metric MSE -subimage-search \
"${WORK_DIR}/screen_small.png" "${WORK_DIR}/target_small.png" "${WORK_DIR}/out.png" 2>&1)
if [[ $RESULT == *"error"* ]]; then
echo "Failed to find the target: ${RESULT}" >&2
exit 1
fi
# We use the position of match to crop the original screen capture tightly around the
# match. Some padding is added to make sure that the target is contained in the cropped
# screen capture. We then search one more in the full resolution to get the exact pixel
# location.
# Here we extract the pixel location of the match in the scaled-down version.
CROP_X=$(echo "${RESULT}" | awk -F[\,\ ] '{print $4}')
CROP_Y=$(echo "${RESULT}" | awk -F[\,\ ] '{print $5}')
# We add more padding if the images are more scaled down.
PADDING=$SCALE_FACTOR
CROP_X=$((CROP_X * SCALE_FACTOR - PADDING))
CROP_Y=$((CROP_Y * SCALE_FACTOR - PADDING))
# Clamp the result.
CROP_X=$((CROP_X < 0 ? 0 : CROP_X))
CROP_Y=$((CROP_Y < 0 ? 0 : CROP_Y))
# The crop size depends on the target image size.
TARGET_WIDTH=$(identify -format "%[fx:w]" "${TARGET}")
TARGET_HEIGHT=$(identify -format "%[fx:h]" "${TARGET}")
CROP_WIDTH=$((TARGET_WIDTH + 2*PADDING))
CROP_HEIGHT=$((TARGET_HEIGHT + 2*PADDING))
# Perform the crop.
convert "${SCREEN}" -crop ${CROP_WIDTH}x${CROP_HEIGHT}+${CROP_X}+${CROP_Y} \
+repage "${WORK_DIR}/screen_cropped.png"
# Search again on the full resolution.
RESULT=$(compare -metric MSE -dissimilarity-threshold "${FUZZINESS}" -subimage-search \
"${WORK_DIR}/screen_cropped.png" "${TARGET}" "${WORK_DIR}/out.png" 2>&1)
if [[ $RESULT == *"error"* ]]; then
echo "Failed to find the target: ${RESULT}" >&2
exit 1
fi
# Extract the pixel location from the result. This is now relative to the crop position.
POS_X=$(echo "${RESULT}" | awk -F[\,\ ] '{print $4}')
POS_Y=$(echo "${RESULT}" | awk -F[\,\ ] '{print $5}')
# Therefore we have to add the crop position to the result.
POS_X=$((POS_X + CROP_X))
POS_Y=$((POS_Y + CROP_Y))
# Finally print our result.
echo "$POS_X $POS_Y"
+19 -3
View File
@@ -57,7 +57,7 @@ EXTENSION="burn-my-windows@schneegans.github.com"
# All references images of the effects are captured at & cropped to this region # All references images of the effects are captured at & cropped to this region
# in the center of the screen. This is kind of arbitrary, but has been choosen so that # in the center of the screen. This is kind of arbitrary, but has been choosen so that
# something is visible from each effect. # something is visible from each effect.
CROP="100x100+910+480" CROP="100x100+900+500"
# Run the container. For more info, visit https://github.com/Schneegans/gnome-shell-pod. # Run the container. For more info, visit https://github.com/Schneegans/gnome-shell-pod.
POD=$(podman run --rm --cap-add=SYS_NICE --cap-add=IPC_LOCK -td "${IMAGE}") POD=$(podman run --rm --cap-add=SYS_NICE --cap-add=IPC_LOCK -td "${IMAGE}")
@@ -110,7 +110,8 @@ capture_effect() {
set_setting "open-preview-effect" "${1}" set_setting "open-preview-effect" "${1}"
set_setting "close-preview-effect" "${1}" set_setting "close-preview-effect" "${1}"
do_in_pod gnome-extensions prefs "${EXTENSION}" sleep 1
do_in_pod gnome-terminal
sleep 3 sleep 3
capture "tests/references/${1}-open-${SESSION}-${FEDORA_VERSION}.png" capture "tests/references/${1}-open-${SESSION}-${FEDORA_VERSION}.png"
send_keystroke "Alt+F4" send_keystroke "Alt+F4"
@@ -132,6 +133,11 @@ podman cp "${EXTENSION}.zip" "${POD}:/home/gnomeshell"
do_in_pod gnome-extensions install "${EXTENSION}.zip" do_in_pod gnome-extensions install "${EXTENSION}.zip"
# ----------------------- install gnome-terminal (this is used for testing the animations)
do_in_pod sudo dnf install -y gnome-terminal
# ---------------------------------------------------------------------- start GNOME Shell # ---------------------------------------------------------------------- start GNOME Shell
# Starting with GNOME 40, there is a "Welcome Tour" dialog popping up at first launch. # Starting with GNOME 40, there is a "Welcome Tour" dialog popping up at first launch.
@@ -141,6 +147,9 @@ if [[ "${FEDORA_VERSION}" -gt 33 ]]; then
do_in_pod gsettings set org.gnome.shell welcome-dialog-last-shown-version "999" || true do_in_pod gsettings set org.gnome.shell welcome-dialog-last-shown-version "999" || true
fi fi
# Make sure that new windows are opened in the center.
do_in_pod gsettings set org.gnome.mutter center-new-windows true
echo "Starting $(do_in_pod gnome-shell --version)." echo "Starting $(do_in_pod gnome-shell --version)."
do_in_pod systemctl --user start "${SESSION}@:99" do_in_pod systemctl --user start "${SESSION}@:99"
sleep 10 sleep 10
@@ -161,10 +170,16 @@ sleep 3
# --------------------------------------------------------------------- capture the images # --------------------------------------------------------------------- capture the images
# First we open the preferences and capture a portion of the dialog
echo "Opening Preferences."
do_in_pod gnome-extensions prefs "${EXTENSION}"
sleep 3
capture "tests/references/preferences-${SESSION}-${FEDORA_VERSION}.png"
send_keystroke "Alt+F4"
# The test mode ensures that the animations are "frozen" and do not change in time. # The test mode ensures that the animations are "frozen" and do not change in time.
echo "Entering test mode." echo "Entering test mode."
set_setting "test-mode" true set_setting "test-mode" true
do_in_pod gsettings set org.gnome.mutter center-new-windows true
capture_effect "energize-a" capture_effect "energize-a"
capture_effect "energize-b" capture_effect "energize-b"
@@ -177,6 +192,7 @@ capture_effect "wisps"
if [[ "${FEDORA_VERSION}" -gt 32 ]]; then if [[ "${FEDORA_VERSION}" -gt 32 ]]; then
capture_effect "apparition" capture_effect "apparition"
capture_effect "doom"
fi fi
if [[ "${FEDORA_VERSION}" -gt 33 ]]; then if [[ "${FEDORA_VERSION}" -gt 33 ]]; then
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1021 B

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 625 B

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1021 B

After

Width:  |  Height:  |  Size: 917 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Some files were not shown because too many files have changed in this diff Show More