Add base gnome extensions
This commit is contained in:
@ -0,0 +1,13 @@
|
||||
uniform sampler2D tex;
|
||||
uniform float red;
|
||||
uniform float green;
|
||||
uniform float blue;
|
||||
uniform float blend;
|
||||
|
||||
void main() {
|
||||
vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);
|
||||
vec3 pix_color = c.xyz;
|
||||
vec3 color = vec3(red, green, blue);
|
||||
|
||||
cogl_color_out = vec4(mix(pix_color, color, blend), 1.);
|
||||
}
|
||||
@ -0,0 +1,181 @@
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Clutter from 'gi://Clutter';
|
||||
import Shell from 'gi://Shell';
|
||||
|
||||
|
||||
const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'color_effect.glsl', GLib.UriFlags.NONE))[0];
|
||||
|
||||
|
||||
const get_shader_source = _ => {
|
||||
try {
|
||||
return Shell.get_file_contents_utf8_sync(SHADER_PATH);
|
||||
} catch (e) {
|
||||
console.warn(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/// New Clutter Shader Effect that simply mixes a color in, the class applies
|
||||
/// the GLSL shader programmed into vfunc_get_static_shader_source and applies
|
||||
/// it to an Actor.
|
||||
///
|
||||
/// Clutter Shader Source Code:
|
||||
/// https://github.com/GNOME/clutter/blob/master/clutter/clutter-shader-effect.c
|
||||
///
|
||||
/// GJS Doc:
|
||||
/// https://gjs-docs.gnome.org/clutter10~10_api/clutter.shadereffect
|
||||
export const ColorEffect = new GObject.registerClass({
|
||||
GTypeName: "ColorEffect",
|
||||
Properties: {
|
||||
'red': GObject.ParamSpec.double(
|
||||
`red`,
|
||||
`Red`,
|
||||
`Red value in shader`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'green': GObject.ParamSpec.double(
|
||||
`green`,
|
||||
`Green`,
|
||||
`Green value in shader`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'blue': GObject.ParamSpec.double(
|
||||
`blue`,
|
||||
`Blue`,
|
||||
`Blue value in shader`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'blend': GObject.ParamSpec.double(
|
||||
`blend`,
|
||||
`Blend`,
|
||||
`Amount of blending between the colors`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
}
|
||||
}, class ColorShader extends Clutter.ShaderEffect {
|
||||
constructor(params, settings) {
|
||||
// initialize without color as a parameter
|
||||
let _color = params.color;
|
||||
delete params.color;
|
||||
|
||||
super(params);
|
||||
|
||||
this._red = null;
|
||||
this._green = null;
|
||||
this._blue = null;
|
||||
this._blend = null;
|
||||
|
||||
this._static = true;
|
||||
this._settings = settings;
|
||||
|
||||
// set shader source
|
||||
this._source = get_shader_source();
|
||||
if (this._source)
|
||||
this.set_shader_source(this._source);
|
||||
|
||||
// set shader color
|
||||
if (_color)
|
||||
this.color = _color;
|
||||
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
get red() {
|
||||
return this._red;
|
||||
}
|
||||
|
||||
set red(value) {
|
||||
if (this._red !== value) {
|
||||
this._red = value;
|
||||
|
||||
this.set_uniform_value('red', parseFloat(this._red - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
get green() {
|
||||
return this._green;
|
||||
}
|
||||
|
||||
set green(value) {
|
||||
if (this._green !== value) {
|
||||
this._green = value;
|
||||
|
||||
this.set_uniform_value('green', parseFloat(this._green - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
get blue() {
|
||||
return this._blue;
|
||||
}
|
||||
|
||||
set blue(value) {
|
||||
if (this._blue !== value) {
|
||||
this._blue = value;
|
||||
|
||||
this.set_uniform_value('blue', parseFloat(this._blue - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
get blend() {
|
||||
return this._blend;
|
||||
}
|
||||
|
||||
set blend(value) {
|
||||
if (this._blend !== value) {
|
||||
this._blend = value;
|
||||
|
||||
this.set_uniform_value('blend', parseFloat(this._blend - 1e-6));
|
||||
}
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
set color(rgba) {
|
||||
let [r, g, b, a] = rgba;
|
||||
this.red = r;
|
||||
this.green = g;
|
||||
this.blue = b;
|
||||
this.blend = a;
|
||||
}
|
||||
|
||||
get color() {
|
||||
return [this.red, this.green, this.blue, this.blend];
|
||||
}
|
||||
|
||||
/// False set function, only cares about the color. Too hard to change.
|
||||
set(params) {
|
||||
this.color = params.color;
|
||||
}
|
||||
|
||||
update_enabled() {
|
||||
// don't anything if this._settings is undefined (when calling super)
|
||||
if (this._settings === undefined)
|
||||
return;
|
||||
|
||||
this.set_enabled(
|
||||
this.blend > 0 &&
|
||||
this._settings.COLOR_AND_NOISE &&
|
||||
this._static
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
vfunc_paint_target(paint_node = null, paint_context = null) {
|
||||
this.set_uniform_value("tex", 0);
|
||||
|
||||
if (paint_node && paint_context)
|
||||
super.vfunc_paint_target(paint_node, paint_context);
|
||||
else if (paint_node)
|
||||
super.vfunc_paint_target(paint_node);
|
||||
else
|
||||
super.vfunc_paint_target();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,20 @@
|
||||
uniform sampler2D tex;
|
||||
uniform float noise;
|
||||
uniform float lightness;
|
||||
|
||||
float PHI = 1.61803398874989484820459;
|
||||
float SEED = 24;
|
||||
|
||||
float noise_gen(in vec2 xy) {
|
||||
float r = fract(tan(distance(xy * PHI, xy) * SEED) * xy.x);
|
||||
r = r != r ? 0.0 : r;
|
||||
return r;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 c = texture2D(tex, cogl_tex_coord_in[0].st);
|
||||
vec3 pix_color = c.xyz;
|
||||
float blend = noise * (1. - noise_gen(gl_FragCoord.xy));
|
||||
|
||||
cogl_color_out = vec4(mix(pix_color, lightness * pix_color, blend), 1.);
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
import GLib from 'gi://GLib';
|
||||
import GObject from 'gi://GObject';
|
||||
import Clutter from 'gi://Clutter';
|
||||
import Shell from 'gi://Shell';
|
||||
|
||||
|
||||
const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'noise_effect.glsl', GLib.UriFlags.NONE))[0];
|
||||
|
||||
const get_shader_source = _ => {
|
||||
try {
|
||||
return Shell.get_file_contents_utf8_sync(SHADER_PATH);
|
||||
} catch (e) {
|
||||
console.warn(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const NoiseEffect = new GObject.registerClass({
|
||||
GTypeName: "NoiseEffect",
|
||||
Properties: {
|
||||
'noise': GObject.ParamSpec.double(
|
||||
`noise`,
|
||||
`Noise`,
|
||||
`Amount of noise integrated with the image`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 1.0,
|
||||
0.4,
|
||||
),
|
||||
'lightness': GObject.ParamSpec.double(
|
||||
`lightness`,
|
||||
`Lightness`,
|
||||
`Lightness of the grey used for the noise`,
|
||||
GObject.ParamFlags.READWRITE,
|
||||
0.0, 2.0,
|
||||
0.4,
|
||||
),
|
||||
}
|
||||
}, class NoiseShader extends Clutter.ShaderEffect {
|
||||
constructor(params, settings) {
|
||||
super(params);
|
||||
|
||||
this._noise = null;
|
||||
this._lightness = null;
|
||||
|
||||
this._static = true;
|
||||
this._settings = settings;
|
||||
|
||||
if (params.noise)
|
||||
this.noise = params.noise;
|
||||
if (params.lightness)
|
||||
this.lightness = params.lightness;
|
||||
|
||||
// set shader source
|
||||
this._source = get_shader_source();
|
||||
if (this._source)
|
||||
this.set_shader_source(this._source);
|
||||
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
get noise() {
|
||||
return this._noise;
|
||||
}
|
||||
|
||||
set noise(value) {
|
||||
if (this._noise !== value) {
|
||||
this._noise = value;
|
||||
|
||||
this.set_uniform_value('noise', parseFloat(this._noise - 1e-6));
|
||||
}
|
||||
this.update_enabled();
|
||||
}
|
||||
|
||||
get lightness() {
|
||||
return this._lightness;
|
||||
}
|
||||
|
||||
set lightness(value) {
|
||||
if (this._lightness !== value) {
|
||||
this._lightness = value;
|
||||
|
||||
this.set_uniform_value('lightness', parseFloat(this._lightness - 1e-6));
|
||||
}
|
||||
}
|
||||
|
||||
update_enabled() {
|
||||
// don't anything if this._settings is undefined (when calling super)
|
||||
if (this._settings === undefined)
|
||||
return;
|
||||
|
||||
this.set_enabled(
|
||||
this.noise > 0 &&
|
||||
this._settings.COLOR_AND_NOISE &&
|
||||
this._static
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
vfunc_paint_target(paint_node = null, paint_context = null) {
|
||||
this.set_uniform_value("tex", 0);
|
||||
|
||||
if (paint_node && paint_context)
|
||||
super.vfunc_paint_target(paint_node, paint_context);
|
||||
else if (paint_node)
|
||||
super.vfunc_paint_target(paint_node);
|
||||
else
|
||||
super.vfunc_paint_target();
|
||||
}
|
||||
});
|
||||
@ -0,0 +1,89 @@
|
||||
import GObject from 'gi://GObject';
|
||||
import Clutter from 'gi://Clutter';
|
||||
|
||||
|
||||
export const PaintSignals = class PaintSignals {
|
||||
constructor(connections) {
|
||||
this.buffer = [];
|
||||
this.connections = connections;
|
||||
}
|
||||
|
||||
connect(actor, blur_effect) {
|
||||
let paint_effect = new EmitPaintSignal();
|
||||
let infos = {
|
||||
actor: actor,
|
||||
paint_effect: paint_effect
|
||||
};
|
||||
let counter = 0;
|
||||
|
||||
actor.add_effect(paint_effect);
|
||||
this.connections.connect(paint_effect, 'update-blur', () => {
|
||||
try {
|
||||
// checking if blur_effect.queue_repaint() has been recently called
|
||||
if (counter === 0) {
|
||||
counter = 2;
|
||||
blur_effect.queue_repaint();
|
||||
}
|
||||
else counter--;
|
||||
} catch (e) { }
|
||||
});
|
||||
|
||||
// remove the actor from buffer when it is destroyed
|
||||
if (
|
||||
actor.connect &&
|
||||
(
|
||||
!(actor instanceof GObject.Object) ||
|
||||
GObject.signal_lookup('destroy', actor)
|
||||
)
|
||||
)
|
||||
this.connections.connect(actor, 'destroy', () => {
|
||||
this.buffer.forEach(infos => {
|
||||
if (infos.actor === actor) {
|
||||
// remove from buffer
|
||||
let index = this.buffer.indexOf(infos);
|
||||
this.buffer.splice(index, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.buffer.push(infos);
|
||||
}
|
||||
|
||||
disconnect_all_for_actor(actor) {
|
||||
this.buffer.forEach(infos => {
|
||||
if (infos.actor === actor) {
|
||||
this.connections.disconnect_all_for(infos.paint_effect);
|
||||
infos.actor.remove_effect(infos.paint_effect);
|
||||
|
||||
// remove from buffer
|
||||
let index = this.buffer.indexOf(infos);
|
||||
this.buffer.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
disconnect_all() {
|
||||
this.buffer.forEach(infos => {
|
||||
this.connections.disconnect_all_for(infos.paint_effect);
|
||||
infos.actor.remove_effect(infos.paint_effect);
|
||||
});
|
||||
|
||||
this.buffer = [];
|
||||
}
|
||||
};
|
||||
|
||||
export const EmitPaintSignal = GObject.registerClass({
|
||||
GTypeName: 'EmitPaintSignal',
|
||||
Signals: {
|
||||
'update-blur': {
|
||||
param_types: []
|
||||
},
|
||||
}
|
||||
},
|
||||
class EmitPaintSignal extends Clutter.Effect {
|
||||
vfunc_paint(node, paint_context, paint_flags) {
|
||||
this.emit("update-blur");
|
||||
super.vfunc_paint(node, paint_context, paint_flags);
|
||||
}
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user