📝 Update effect creation guide

This commit is contained in:
Simon Schneegans
2023-08-19 08:00:54 +02:00
parent 44ce1a4825
commit a8466a16f7
+28 -289
View File
@@ -103,13 +103,14 @@ Please study this code carefully, all of it is explained with inline comments.
// The content from common.glsl is automatically prepended to each shader effect. This // The content from common.glsl is automatically prepended to each shader effect. This
// provides the standard input: // provides the standard input:
// vec2 iTexCoord: Texture coordinates for retrieving the window input color. // vec2 iTexCoord: Texture coordinates for retrieving the window input color.
// bool uForOpening: True if a window-open animation is ongoing, false otherwise. // bool uIsFullscreen: True if the window is maximized or in fullscreen mode.
// float uProgress: A value which transitions from 0 to 1 during the animation. // bool uForOpening: True if a window-open animation is ongoing, false otherwise.
// float uDuration: The duration of the current animation in seconds. // float uProgress: A value which transitions from 0 to 1 during the animation.
// vec2 uSize: The size of uTexture in pixels. // float uDuration: The duration of the current animation in seconds.
// float uPadding: The empty area around the actual window (e.g. where the shadow // vec2 uSize: The size of uTexture in pixels.
// is drawn). For now, this will only be set on GNOME. // float uPadding: The empty area around the actual window (e.g. where the shadow
// is drawn). For now, this will only be set on GNOME.
// Furthermore, there are two global methods for reading the window input color and // Furthermore, there are two global methods for reading the window input color and
// setting the shader output color. Both methods assume straight alpha: // setting the shader output color. Both methods assume straight alpha:
@@ -162,16 +163,13 @@ void main() {
// SPDX-FileCopyrightText: Your Name <your@email.com> // SPDX-FileCopyrightText: Your Name <your@email.com>
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
'use strict'; "use strict";
const GObject = imports.gi.GObject; const GObject = imports.gi.GObject;
const _ = imports.gettext.domain('burn-my-windows').gettext; const _ = imports.gettext.domain("burn-my-windows").gettext;
const ExtensionUtils = imports.misc.extensionUtils; import { ShaderFactory } from "../ShaderFactory.js";
const Me = imports.misc.extensionUtils.getCurrentExtension();
const utils = Me.imports.src.utils;
const ShaderFactory = Me.imports.src.ShaderFactory.ShaderFactory;
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// This effect ... // // This effect ... //
@@ -181,21 +179,21 @@ const ShaderFactory = Me.imports.src.ShaderFactory.ShaderFactory;
// The effect class can be used to get some metadata (like the effect's name or supported // 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 // GNOME Shell versions), to initialize the respective page of the settings dialog, as
// well as to create the actual shader for the effect. // well as to create the actual shader for the effect.
var SimpleFade = class { export default class Effect {
// The constructor creates a ShaderFactory which will be used by extension.js to create // 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 // 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 // GLSL file in resources/shaders/<nick>.glsl. The callback will be called for each
// newly created shader instance. // newly created shader instance.
constructor() { constructor() {
this.shaderFactory = new ShaderFactory(this.getNick(), (shader) => { this.shaderFactory = new ShaderFactory(this.getNick(), (shader) => {
// Store uniform locations of newly created shaders. // Store uniform locations of newly created shaders.
shader._uFadeWidth = shader.get_uniform_location('uFadeWidth'); shader._uFadeWidth = shader.get_uniform_location("uFadeWidth");
// Write all uniform values at the start of each animation. // Write all uniform values at the start of each animation.
shader.connect('begin-animation', (shader, settings) => { shader.connect("begin-animation", (shader, settings) => {
shader.set_uniform_float(shader._uFadeWidth, 1, [settings.get_double('simple-fade-width')]); shader.set_uniform_float(shader._uFadeWidth, 1, [
settings.get_double("simple-fade-width"),
]);
}); });
}); });
} }
@@ -213,13 +211,13 @@ var SimpleFade = class {
// (e.g. '*-animation-time'). Also, the shader file and the settings UI files should be // (e.g. '*-animation-time'). Also, the shader file and the settings UI files should be
// named likes this. // named likes this.
getNick() { getNick() {
return 'simple-fade'; return "simple-fade";
} }
// This will be shown in the sidebar of the preferences dialog as well as in the // 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. // drop-down menus where the user can choose the effect.
getLabel() { getLabel() {
return _('Simple Fade Effect'); return _("Simple Fade Effect");
} }
// -------------------------------------------------------------------- API for prefs.js // -------------------------------------------------------------------- API for prefs.js
@@ -236,7 +234,7 @@ var SimpleFade = class {
// animation. This is useful if the effect requires drawing something beyond the usual // animation. This is useful if the effect requires drawing something beyond the usual
// bounds of the actor. This only works for GNOME 3.38+. // bounds of the actor. This only works for GNOME 3.38+.
getActorScale(settings) { getActorScale(settings) {
return {x: 1.0, y: 1.0}; return { x: 1.0, y: 1.0 };
} }
} }
``` ```
@@ -250,15 +248,17 @@ Both, [`extension.js`](../extension.js) and [`prefs.js`](../prefs.js) define an
Like this: Like this:
```javascript ```javascript
import SimpleFade from './src/effects/SimpleFade.js';
...
const ALL_EFFECTS = [ const ALL_EFFECTS = [
... ...
new Me.imports.src.effects.SimpleFade.SimpleFade(), new SimpleFade(),
... ...
]; ];
``` ```
### Testing your Effect ### Testing your Effect
Now you can call `make install` and restart GNOME Shell with <kbd>Alt</kbd> + <kbd>F2</kbd>, <kbd>r</kbd> + <kbd>Enter</kbd>. Now you can call `make install` and restart GNOME Shell with <kbd>Alt</kbd> + <kbd>F2</kbd>, <kbd>r</kbd> + <kbd>Enter</kbd>.
@@ -274,272 +274,11 @@ gnome-extensions prefs burn-my-windows@schneegans.github.com
## Adding a Preferences Page ## Adding a Preferences Page
There should be two sliders in this example: The animation duration and the width of the fading gradient. There should be two sliders in this example: The animation duration and the width of the fading gradient.
Just save the code below to `resources/ui/adw/simple-fade.ui`.
If your effect supports GNOME Shell 3.3x _and_ GNOME Shell 40+, you will have to provide three `*.ui` files for this.
This is because starting with GNOME Shell 40, the preference dialog uses GTK4, before it used to use GTK3.
Starting with GNOME Shell 42, it uses `libadwaita` which requires different UI files again.
_:information_source: If you do not have the means to test your effect on different versions of GNOME, feel free to submit a pull request for one GNOME version only, I may then port your effect to other GNOME versions!_
Just save the code below to `resources/ui/gtk3/simple-fade.ui`, `resources/ui/gtk4/simple-fade.ui`, and `resources/ui/adw/simple-fade.ui` respectively.
Remember to replace any occurrence of `simple-fade` with your effect's nick-name! Remember to replace any occurrence of `simple-fade` with your effect's nick-name!
<details> <details>
<summary>Expand this to show the GTK3 code.</summary> <summary>Expand this to show the UI code.</summary>
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-FileCopyrightText: Your Name <your@email.com>
SPDX-License-Identifier: GPL-3.0-or-later
-->
<interface domain="burn-my-windows">
<object class="GtkAdjustment" id="simple-fade-animation-time">
<property name="upper">5000</property>
<property name="lower">100</property>
<property name="step-increment">10</property>
<property name="page-increment">100</property>
</object>
<object class="GtkAdjustment" id="simple-fade-width">
<property name="upper">1</property>
<property name="lower">0</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.1</property>
</object>
<object class="GtkRevealer" id="simple-fade-prefs">
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<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">simple-fade-animation-time</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-simple-fade-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="activatable">0</property>
<child>
<object class="GtkBox">
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">Fade Width</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">simple-fade-width</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-simple-fade-width">
<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>
</interface>
```
</details>
<details>
<summary>Expand this to show the GTK4 code.</summary>
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
SPDX-FileCopyrightText: Your Name <your@email.com>
SPDX-License-Identifier: GPL-3.0-or-later
-->
<interface domain="burn-my-windows">
<object class="GtkAdjustment" id="simple-fade-animation-time">
<property name="upper">5000</property>
<property name="lower">100</property>
<property name="step-increment">10</property>
<property name="page-increment">100</property>
</object>
<object class="GtkAdjustment" id="simple-fade-width">
<property name="upper">1</property>
<property name="lower">0</property>
<property name="step-increment">0.01</property>
<property name="page-increment">0.1</property>
</object>
<object class="GtkRevealer" id="simple-fade-prefs">
<child>
<object class="GtkListBox">
<property name="selection-mode">none</property>
<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">simple-fade-animation-time</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-simple-fade-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">Fade Width</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">simple-fade-width</property>
</object>
</child>
<child>
<object class="GtkButton" id="reset-simple-fade-width">
<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>
</interface>
```
</details>
<details>
<summary>Expand this to show the libadwaita code.</summary>
```xml ```xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
@@ -628,7 +367,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
### Loading the Preferences Page ### Loading the Preferences Page
In order to load the above `*.ui` files, add the following code to your effect's `bindPreferences()` method. In order to load the above `*.ui` file, add the following code to your effect's `bindPreferences()` method.
```javascript ```javascript
bindPreferences(dialog) { bindPreferences(dialog) {