🔀 Merge pull request #64 from Schneegans/feature/broken-glass

This commit is contained in:
Simon Schneegans
2022-01-22 12:45:03 +01:00
committed by GitHub
19 changed files with 711 additions and 161 deletions
+3
View File
@@ -1,5 +1,8 @@
*~
*.zip
*.blend1
*.blend2
*.blend3
/schemas/gschemas.compiled
/resources/burn-my-windows.gresource
/resources/burn-my-windows.gresource.xml
+1
View File
@@ -12,6 +12,7 @@ For a list of things changed in previous releases, you can have a look at the [c
Effect | Preview
-----|--------
**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! <br><br> _Only available in GNOME Shell 40+_ | <img src ="docs/pics/glass.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" />
**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" />
Binary file not shown.
+8
View File
@@ -1,5 +1,13 @@
# Changelog of the Burn-My-Windows Extension
## [Burn My Window 10](https://github.com/schneegans/Burn-My-Windows/releases/tag/v10)
**Release Date:** TBD
#### New Features
* **New Effect: Broken Glass.** Shatter your windows into a shower sharp shards! This effect can be configured so that the shards fly away from your mouse pointer position!
## [Burn My Window 9](https://github.com/schneegans/Burn-My-Windows/releases/tag/v9)
**Release Date:** 2022-01-18
+8 -19
View File
@@ -121,7 +121,8 @@ var SimpleFade = class SimpleFade {
// 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. the '*-close-effect').
// effect is enabled currently (e.g. '*-close-effect'), and its animation time
// (e.g. '*-animation-time').
static getNick() {
return 'simple-fade';
}
@@ -144,28 +145,16 @@ var SimpleFade = class SimpleFade {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('simple-fade-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// We re-target these transitions so that the window is neither scaled nor faded.
tweakTransition('opacity', 255);
tweakTransition('scale-x', 1);
tweakTransition('scale-y', 1);
// GNOME Shell. For each property, you can set a "from", "to", and a "mode". For this
// effect, windows should neither be scaled nor faded.
static getCloseTransition(actor, settings) {
return {'opacity': {to: 255}, 'scale-x': {to: 1.0}, 'scale-y': {to: 1.0}};
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

+95 -5
View File
@@ -36,6 +36,7 @@ const ALL_EFFECTS = [
Me.imports.src.EnergizeB.EnergizeB,
Me.imports.src.Fire.Fire,
Me.imports.src.Matrix.Matrix,
Me.imports.src.BrokenGlass.BrokenGlass,
Me.imports.src.TRexAttack.TRexAttack,
Me.imports.src.TVEffect.TVEffect,
Me.imports.src.Wisps.Wisps,
@@ -66,6 +67,10 @@ class Extension {
// Store a reference to the settings object.
this._settings = ExtensionUtils.getSettings();
// This will store an item of ALL_EFFECTS which was used the last time a window was
// closed.
this._effect = 0;
// We will monkey-patch these three methods. Let's store the original ones.
this._origWindowRemoved = Workspace.prototype._windowRemoved;
this._origDoRemoveWindow = Workspace.prototype._doRemoveWindow;
@@ -80,11 +85,57 @@ class Extension {
// the WorkspacesView.
const extensionThis = this;
// Do not attempt to close windows twice. Due to the animation in the overview, the
// close button can be clicked twice which normally would lead to a crash.
// This class is only available in GNOME Shell 3.38+. So no transition tweaking in
// GNOME Shell 3.36, but this is not used by any effect available there anyways for
// now...
if (WindowPreview) {
this._origDeleteAll = WindowPreview.prototype._deleteAll;
this._origRestack = WindowPreview.prototype._restack;
this._origInit = WindowPreview.prototype._init;
// This is required, else WindowPreview's _restack() which is called by the
// "this.overlayEnabled = false", sometimes tries to access an already delete
// WindowPreview.
WindowPreview.prototype._restack = function() {
if (!this._closeRequested) {
// Call the original method.
extensionThis._origRestack.apply(this);
}
};
// When a window is removed from the overview, we need adjust the transitions of the
// window clone according to the chosen effect. We do this in the 'unmanaged' signal
// of the WindowPreview's Meta.Window. This is not ideal, as it does not work for
// dialogs which close themselves... Maybe there's a better way?
WindowPreview.prototype._init = function(...params) {
// Call the original method.
extensionThis._origInit.apply(this, params);
// When the user clicks the X in the overview, the window is not deleted
// immediately. However, as soon as the window is really deleted, we need to
// adjust the transition of its clone.
const connectionID = this.metaWindow.connect('unmanaged', () => {
if (this.window_container) {
// Hide the window's icon, name, and close button.
this.overlayEnabled = false;
this._icon.visible = false;
const transitionConfig = extensionThis._effect.getCloseTransition(
this.window_container, extensionThis._settings);
extensionThis._tweakTransitions(this.window_container, transitionConfig);
}
});
// Make sure to not call the callback above if the Meta.Window was not unmanaged
// before leaving the overview.
this.connect('destroy', () => {
this.metaWindow.disconnect(connectionID);
});
};
// The _deleteAll is called when the user clicks the X in the overview. We should
// not attempt to close windows twice. Due to the animation in the overview, the
// close button can be clicked twice which normally would lead to a crash.
WindowPreview.prototype._deleteAll = function() {
if (!this._closeRequested) {
extensionThis._origDeleteAll.apply(this);
@@ -175,13 +226,14 @@ class Extension {
}
// Choose a random effect.
const Effect = enabledEffects[Math.floor(Math.random() * enabledEffects.length)];
this._effect = enabledEffects[Math.floor(Math.random() * enabledEffects.length)];
// The effect usually will choose to override the present transitions on the actor.
Effect.tweakTransitions(actor, this._settings);
const transitionConfig = this._effect.getCloseTransition(actor, this._settings);
this._tweakTransitions(actor, transitionConfig);
// Add a cool shader to our window actor!
const shader = Effect.createShader(this._settings);
const shader = this._effect.createShader(actor, this._settings);
if (shader) {
actor.add_effect(shader);
@@ -231,6 +283,8 @@ class Extension {
if (WindowPreview) {
WindowPreview.prototype._deleteAll = this._origDeleteAll;
WindowPreview.prototype._restack = this._origRestack;
WindowPreview.prototype._init = this._origInit;
}
this._settings = null;
@@ -255,6 +309,42 @@ class Extension {
return false;
}
// This is used to tweak the ongoing transitions of a window actor. This is either the
// actual actor of the Meta.Window or a clone in the overview. Usually windows are faded
// to transparency and scaled down slightly by GNOME Shell. Here, we allow modifications
// to this behavior by the effects.
_tweakTransitions(actor, config) {
const duration = this._settings.get_int(this._effect.getNick() + '-animation-time');
for (const property in config) {
const from = config[property].from;
const to = config[property].to;
const mode = config[property].mode;
const transition = actor.get_transition(property);
if (transition) {
transition.set_duration(duration);
if (to != undefined) transition.set_to(to);
if (from != undefined) transition.set_from(from);
if (mode != undefined) transition.set_progress_mode(mode);
} else {
if (from != undefined) actor[property] = from;
if (to != undefined) {
actor.save_easing_state();
actor.set_easing_duration(duration)
if (mode != undefined) actor.set_easing_mode(mode);
actor[property] = to;
actor.restore_easing_state();
}
}
}
}
}
// This function is called once when the extension is loaded, not enabled.
+1
View File
@@ -25,6 +25,7 @@ const ALL_EFFECTS = [
Me.imports.src.EnergizeB.EnergizeB,
Me.imports.src.Fire.Fire,
Me.imports.src.Matrix.Matrix,
Me.imports.src.BrokenGlass.BrokenGlass,
Me.imports.src.TRexAttack.TRexAttack,
Me.imports.src.TVEffect.TVEffect,
Me.imports.src.Wisps.Wisps,
Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

+266
View File
@@ -0,0 +1,266 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkBox" id="broken-glass-prefs">
<property name="orientation">vertical</property>
<property name="margin-start">60</property>
<property name="margin-end">60</property>
<property name="margin-top">60</property>
<property name="margin-bottom">60</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="broken-glass-animation-time">
<property name="upper">10000</property>
<property name="lower">500</property>
<property name="step-increment">10</property>
<property name="page-increment">100</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-broken-glass-animation-time">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">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">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="broken-glass-scale">
<property name="upper">5</property>
<property name="lower">0.2</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.1</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-broken-glass-scale">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">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">Gravity</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="broken-glass-gravity">
<property name="upper">2.0</property>
<property name="lower">-2.0</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.1</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-broken-glass-gravity">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">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">Blow Force</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="broken-glass-blow-force">
<property name="upper">2.0</property>
<property name="lower">-2.0</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.1</property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-broken-glass-blow-force">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">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="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Shatter From Pointer Location</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="GtkLabel">
<property name="label" translatable="yes">The shards will fly away from where your mouse pointer was when closing the window.</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="valign">center</property>
<property name="hexpand">1</property>
<style>
<class name="dim-label" />
<class name="caption" />
</style>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSwitch" id="broken-glass-use-pointer">
<property name="halign">end</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-broken-glass-use-pointer">
<property name="icon-name">edit-clear-symbolic</property>
<property name="tooltip-text">Reset to Default Value</property>
<style>
<class name="flat" />
</style>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>
@@ -263,6 +263,46 @@
<description>The color of the wisps effect.</description>
</key>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Broken Glass Effect Options -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<key name="broken-glass-close-effect" type="b">
<default>false</default>
<summary>Broken Glass Close Effect</summary>
<description>Use the broken glass effect for window closing.</description>
</key>
<key name="broken-glass-animation-time" type="i">
<default>1500</default>
<summary>Broken Glass Animation Time</summary>
<description>The time the broken glass effect takes.</description>
</key>
<key name="broken-glass-scale" type="d">
<default>1.0</default>
<summary>Broken Glass Scale</summary>
<description>The size of the broken glass effect.</description>
</key>
<key name="broken-glass-gravity" type="d">
<default>-1.0</default>
<summary>Broken Glass Gravity</summary>
<description>The gravity of the broken glass effect.</description>
</key>
<key name="broken-glass-blow-force" type="d">
<default>0.5</default>
<summary>Broken Glass Blow Force</summary>
<description>The blow force of the broken glass effect.</description>
</key>
<key name="broken-glass-use-pointer" type="b">
<default>false</default>
<summary>Broken Glass Use Pointer</summary>
<description>Use the pointer location for the broken glass effect.</description>
</key>
</schema>
</schemalist>
+233
View File
@@ -0,0 +1,233 @@
//////////////////////////////////////////////////////////////////////////////////////////
// ) ( //
// ( /( ( ( ) ( ( ( ( )\ ) ( ( //
// )\()) ))\ )( ( ( )\ ) )\))( )\ ( (()/( ( )\))( ( //
// ((_)\ /((_|()\ )\ ) )\ '(()/( ((_)()((_) )\ ) ((_)))\((_)()\ )\ //
// | |(_|_))( ((_)_(_/( _((_)) )(_)) _(()((_|_)_(_/( _| |((_)(()((_|(_) //
// | '_ \ || | '_| ' \)) | ' \()| || | \ 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 ExtensionUtils = imports.misc.extensionUtils;
const Me = imports.misc.extensionUtils.getCurrentExtension();
const utils = Me.imports.src.utils;
//////////////////////////////////////////////////////////////////////////////////////////
// This effect shatters the window into pieces. For an explanation how this works, look //
// further down in this file into the documentation of the Shader class. 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. //
//////////////////////////////////////////////////////////////////////////////////////////
// The shader class for this effect is registered further down in this file.
let Shader = null;
// The effect class is completely static. It 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 BrokenGlass = class BrokenGlass {
// ---------------------------------------------------------------------------- metadata
// This effect is only available on GNOME Shell 40+.
static getMinShellVersion() {
return [40, 0];
}
// 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').
static getNick() {
return 'broken-glass';
}
// 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.
static getLabel() {
return 'Broken Glass';
}
// -------------------------------------------------------------------- API for prefs.js
// This is called by the preferences dialog. It loads the settings page for this effect,
// binds all properties to the settings and appends the page to the main stack of the
// preferences dialog.
static initPreferences(dialog) {
// Add the settings page to the builder.
dialog.getBuilder().add_from_resource('/ui/gtk4/BrokenGlass.ui');
// Bind all properties.
dialog.bindAdjustment('broken-glass-animation-time');
dialog.bindAdjustment('broken-glass-scale');
dialog.bindAdjustment('broken-glass-gravity');
dialog.bindAdjustment('broken-glass-blow-force');
dialog.bindSwitch('broken-glass-use-pointer');
// Finally, append the settings page to the main stack.
const stack = dialog.getBuilder().get_object('main-stack');
stack.add_titled(
dialog.getBuilder().get_object('broken-glass-prefs'), BrokenGlass.getNick(),
BrokenGlass.getLabel());
}
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(actor, settings) {
return new Shader(actor, settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. For this effect, windows are set to twice their original size, so that
// we have some space to draw the shards. We also set the animation mode to "Linear".
static getCloseTransition(actor, settings) {
return {
'opacity': {to: 255, mode: 1},
'scale-x': {from: 2.0, to: 2.0, mode: 1},
'scale-y': {from: 2.0, to: 2.0, mode: 1}
};
}
}
//////////////////////////////////////////////////////////////////////////////////////////
// The shader class for this effect will only be registered in GNOME Shell's process //
// (not in the preferences process). It's done this way as Clutter may not be installed //
// on the system and therefore the preferences would crash. //
//////////////////////////////////////////////////////////////////////////////////////////
if (utils.isInShellProcess()) {
const {Clutter, GdkPixbuf, Cogl} = imports.gi;
const shaderSnippets = Me.imports.src.shaderSnippets;
// This shader creates a complex-looking effect with rather simple means. Here is how it
// works: The window is drawn five times on top of each other (see the SHARD_LAYERS
// constant in the GLSL code). Each layer only draws some of the shards, all layers
// combined make up the entire window. The layers are then scaled, rotated, and moved
// independently from each other - this creates the impression that all shards are
// moving independently. In reality, there are only five groups of shards! Which shard
// belongs to which layer is defined by the green channel of the texture
// resources/img/shards.png. The red channel of the texture contains the distance to the
// shard edges. This information is used to fade out the shards.
Shader = GObject.registerClass({}, class Shader extends Clutter.ShaderEffect {
_init(actor, settings) {
super._init({shader_type: Clutter.ShaderType.FRAGMENT_SHADER});
// Load the shards 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!
const shardData = GdkPixbuf.Pixbuf.new_from_resource('/img/shards.png');
this._shardTexture = new Clutter.Image();
this._shardTexture.set_data(
shardData.get_pixels(), Cogl.PixelFormat.RGB_888, shardData.width,
shardData.height, shardData.rowstride);
// Usually, the shards fly away from the center of the window.
let epicenterX = 0.5;
let epicenterY = 0.5;
// However, if this option is set, we use the mouse pointer position.
if (settings.get_boolean('broken-glass-use-pointer')) {
const [x, y] = global.get_pointer();
const [ok, localX, localY] = actor.transform_stage_point(x, y);
epicenterX = localX / actor.width;
epicenterY = localY / actor.height;
}
this.set_shader_source(`
// Inject some common shader snippets.
${shaderSnippets.standardUniforms()}
uniform sampler2D uShardTexture;
const vec2 SEED = vec2(${Math.random()}, ${Math.random()});
const float SHARD_SCALE = ${settings.get_double('broken-glass-scale')};
const float SHARD_LAYERS = 5;
const float GRAVITY = ${settings.get_double('broken-glass-gravity')};
const float BLOW_FORCE = ${settings.get_double('broken-glass-blow-force')};
const float ACTOR_SCALE = 2.0;
const float PADDING = ACTOR_SCALE / 2.0 - 0.5;
const vec2 EPICENTER = vec2(${epicenterX}, ${epicenterY});
void main() {
cogl_color_out = vec4(0, 0, 0, 0);
// Draw the individual shard layers.
for (float i=0; i<SHARD_LAYERS; ++i) {
// To enable drawing shards outside of the window bounds, the actor was scaled
// by ACTOR_SCALE. Here we scale and move the texture coordinates so that the
// window gets drawn at the correct position again.
vec2 coords = cogl_tex_coord_in[0].st * ACTOR_SCALE - PADDING;
// Scale and rotate around our epicenter.
coords -= EPICENTER;
// Scale each layer a bit differently.
coords /= mix(1.0, 1.0 + BLOW_FORCE*(i+2)/SHARD_LAYERS, uProgress);
// Rotate each layer a bit differently.
float rotation = (mod(i, 2.0)-0.5)*0.2*uProgress;
coords = vec2(coords.x * cos(rotation) - coords.y * sin(rotation),
coords.x * sin(rotation) + coords.y * cos(rotation));
// Move down each layer a bit.
float gravity = GRAVITY*0.1*(i+1)*uProgress*uProgress;
coords += vec2(0, gravity);
// Restore correct position.
coords += EPICENTER;
// Retrieve information from the shard texture for our layer.
vec2 shardCoords = (coords + SEED) * vec2(uSizeX, uSizeY) / SHARD_SCALE / 500.0;
vec2 shardMap = texture2D(uShardTexture, shardCoords).rg;
// The green channel contains a random value in [0..1] for each shard. We
// discretize this into SHARD_LAYERS bins and check if our layer falls into
// the bin of the current shard.
float shardGroup = floor(shardMap.g * SHARD_LAYERS * 0.999);
if (shardGroup == i) {
vec4 windowColor = texture2D(uTexture, coords);
// Dissolve the shard by using distance information from the red channel.
float dissolve = (shardMap.x - pow(uProgress+0.1, 2)) > 0 ? 1: 0;
cogl_color_out = mix(cogl_color_out, windowColor, dissolve);
}
}
}
`);
};
// This is overridden to bind the shard 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();
// Use linear filtering for the window texture.
pipeline.set_layer_filters(
0, Cogl.PipelineFilter.LINEAR, Cogl.PipelineFilter.LINEAR);
// Bind the shard texture.
pipeline.set_layer_texture(1, this._shardTexture.get_texture());
pipeline.set_layer_wrap_mode(1, Cogl.PipelineWrapMode.REPEAT);
this.set_uniform_value('uShardTexture', 1);
super.vfunc_paint_target(node, paint_context);
}
});
}
+7 -19
View File
@@ -40,7 +40,8 @@ var EnergizeA = class EnergizeA {
// 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. the '*-close-effect').
// effect is enabled currently (e.g. '*-close-effect'), and its animation time
// (e.g. '*-animation-time').
static getNick() {
return 'energize-a';
}
@@ -76,28 +77,15 @@ var EnergizeA = class EnergizeA {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('energize-a-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// We re-target these transitions so that the window is neither scaled nor faded.
tweakTransition('opacity', 255);
tweakTransition('scale-x', 1);
tweakTransition('scale-y', 1);
// GNOME Shell. For this effect, windows should neither be scaled nor faded.
static getCloseTransition(actor, settings) {
return {'opacity': {to: 255}, 'scale-x': {to: 1.0}, 'scale-y': {to: 1.0}};
}
}
+7 -19
View File
@@ -40,7 +40,8 @@ var EnergizeB = class EnergizeB {
// 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. the '*-close-effect').
// effect is enabled currently (e.g. '*-close-effect'), and its animation time
// (e.g. '*-animation-time').
static getNick() {
return 'energize-b';
}
@@ -76,28 +77,15 @@ var EnergizeB = class EnergizeB {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('energize-b-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// We re-target these transitions so that the window is neither scaled nor faded.
tweakTransition('opacity', 255);
tweakTransition('scale-x', 1);
tweakTransition('scale-y', 1);
// GNOME Shell. For this effect, windows should neither be scaled nor faded.
static getCloseTransition(actor, settings) {
return {'opacity': {to: 255}, 'scale-x': {to: 1.0}, 'scale-y': {to: 1.0}};
}
}
+7 -19
View File
@@ -44,7 +44,8 @@ var Fire = class Fire {
// 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. the '*-close-effect').
// effect is enabled currently (e.g. '*-close-effect'), and its animation time
// (e.g. '*-animation-time').
static getNick() {
return 'fire';
}
@@ -97,28 +98,15 @@ var Fire = class Fire {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('fire-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// We re-target these transitions so that the window is neither scaled nor faded.
tweakTransition('opacity', 255);
tweakTransition('scale-x', 1);
tweakTransition('scale-y', 1);
// GNOME Shell. For this effect, windows should neither be scaled nor faded.
static getCloseTransition(actor, settings) {
return {'opacity': {to: 255}, 'scale-x': {to: 1.0}, 'scale-y': {to: 1.0}};
}
// ----------------------------------------------------------------------- private stuff
+7 -19
View File
@@ -44,7 +44,8 @@ var Matrix = class Matrix {
// 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. the '*-close-effect').
// effect is enabled currently (e.g. '*-close-effect'), and its animation time
// (e.g. '*-animation-time').
static getNick() {
return 'matrix';
}
@@ -82,28 +83,15 @@ var Matrix = class Matrix {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('matrix-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// We re-target these transitions so that the window is neither scaled nor faded.
tweakTransition('opacity', 255);
tweakTransition('scale-x', 1);
tweakTransition('scale-y', 1);
// GNOME Shell. For this effect, windows should neither be scaled nor faded.
static getCloseTransition(actor, settings) {
return {'opacity': {to: 255}, 'scale-x': {to: 1.0}, 'scale-y': {to: 1.0}};
}
}
+12 -20
View File
@@ -42,7 +42,8 @@ var TRexAttack = class TRexAttack {
// 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. the '*-close-effect').
// effect is enabled currently (e.g. '*-close-effect'), and its animation time
// (e.g. '*-animation-time').
static getNick() {
return 'trex';
}
@@ -80,30 +81,21 @@ var TRexAttack = class TRexAttack {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('trex-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// For this effect, we slightly increase the window's scale as part of the warp
// effect.
// GNOME Shell. For this effect, we slightly increase the window's scale as part of the
// warp effect.
static getCloseTransition(actor, settings) {
const warp = 0.5 * settings.get_double('claw-scratch-warp');
tweakTransition('opacity', 255);
tweakTransition('scale-x', 1.0 + warp);
tweakTransition('scale-y', 1.0 + warp);
return {
'opacity': {to: 255},
'scale-x': {to: 1.0 + warp},
'scale-y': {to: 1.0 + warp}
};
}
}
+7 -19
View File
@@ -42,7 +42,8 @@ var TVEffect = class TVEffect {
// 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. the '*-close-effect').
// effect is enabled currently (e.g. '*-close-effect'), and its animation time
// (e.g. '*-animation-time').
static getNick() {
return 'tv';
}
@@ -77,28 +78,15 @@ var TVEffect = class TVEffect {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('tv-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// For this effect, we scale the window only vertically.
tweakTransition('opacity', 255);
tweakTransition('scale-x', 1);
tweakTransition('scale-y', 0.5);
// GNOME Shell. For this effect, windows are scaled down vertically.
static getCloseTransition(actor, settings) {
return {'opacity': {to: 255}, 'scale-x': {to: 1.0}, 'scale-y': {to: 0.5}};
}
}
+9 -22
View File
@@ -27,9 +27,10 @@ const utils = Me.imports.src.utils;
// The shader class for this effect is registered further down in this file.
let Shader = null;
// The effect class is completely static. It 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.
// 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').
var Wisps = class Wisps {
// ---------------------------------------------------------------------------- metadata
@@ -76,29 +77,15 @@ var Wisps = class Wisps {
// ---------------------------------------------------------------- API for extension.js
// This is called from extension.js whenever a window is closed with this effect.
static createShader(settings) {
static createShader(actor, settings) {
return new Shader(settings);
}
// This is also called from extension.js. It is used to tweak the ongoing transitions of
// This is also called from extension.js. It is used to tweak the ongoing transition of
// the actor - usually windows are faded to transparency and scaled down slightly by
// GNOME Shell. Here, we modify this behavior as well as the transition duration.
static tweakTransitions(actor, settings) {
const animationTime = settings.get_int('wisps-animation-time');
const tweakTransition = (property, value) => {
const transition = actor.get_transition(property);
if (transition) {
transition.set_to(value);
transition.set_duration(animationTime);
}
};
// We re-target these transitions so that the window is not faded but scaled down a
// tiny bit.
tweakTransition('opacity', 255);
tweakTransition('scale-x', 0.9);
tweakTransition('scale-y', 0.9);
// GNOME Shell. For this effect, windows should be scaled down slightly but not faded.
static getCloseTransition(actor, settings) {
return {'opacity': {to: 255}, 'scale-x': {to: 0.9}, 'scale-y': {to: 0.9}};
}
}