diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml index 64f8c4e72..3aa345124 100644 --- a/dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml @@ -5,13 +5,13 @@ import qs.modules.common.functions import qs.modules.common.widgets QuickToggleModel { - name: Translation.tr("Anti-flashbang") - tooltipText: Translation.tr("Anti-flashbang") - icon: "flash_off" + name: HyprlandAntiFlashbangShader.enabled ? (HyprlandAntiFlashbangShader.weak ? Translation.tr("Anti-flash: Weak") : Translation.tr("Anti-flash: Strong")) : Translation.tr("Anti-flashbang") + tooltipText: `${Translation.tr("Anti-flashbang")}: ${HyprlandAntiFlashbangShader.enabled ? (HyprlandAntiFlashbangShader.weak ? Translation.tr("Weak") : Translation.tr("Strong")) : Translation.tr("Off")}` + icon: HyprlandAntiFlashbangShader.enabled ? (!HyprlandAntiFlashbangShader.weak ? "flash_off" : "sunny_snowing") : "flash_on" toggled: HyprlandAntiFlashbangShader.enabled mainAction: () => { - HyprlandAntiFlashbangShader.toggle() + HyprlandAntiFlashbangShader.cycle() } hasMenu: true } diff --git a/dots/.config/quickshell/ii/services/HyprlandAntiFlashbangShader.qml b/dots/.config/quickshell/ii/services/HyprlandAntiFlashbangShader.qml index eea2123b9..e8efb46d9 100644 --- a/dots/.config/quickshell/ii/services/HyprlandAntiFlashbangShader.qml +++ b/dots/.config/quickshell/ii/services/HyprlandAntiFlashbangShader.qml @@ -10,7 +10,9 @@ Singleton { id: root readonly property string shaderPath: Quickshell.shellPath("services/hyprlandAntiFlashbangShader/anti-flashbang.glsl") - property bool enabled: confOpt.value == shaderPath + readonly property string weakShaderPath: Quickshell.shellPath("services/hyprlandAntiFlashbangShader/anti-flashbang-weak.glsl") + property bool enabled: confOpt.value == shaderPath || weak + property bool weak: confOpt.value == weakShaderPath function enable() { HyprlandConfig.setMany({ @@ -19,6 +21,13 @@ Singleton { }); } + function enableWeak() { + HyprlandConfig.setMany({ + "decoration:screen_shader": root.weakShaderPath, + "debug:damage_tracking": 1, + }); + } + function disable() { HyprlandConfig.resetMany([ "decoration:screen_shader", @@ -30,6 +39,16 @@ Singleton { if (root.enabled) disable() else enable() } + + function cycle() { + if (!enabled) { + enableWeak(); + } else if (weak) { + enable(); + } else { + disable(); + } + } HyprlandConfigOption { id: confOpt diff --git a/dots/.config/quickshell/ii/services/hyprlandAntiFlashbangShader/anti-flashbang-weak.glsl b/dots/.config/quickshell/ii/services/hyprlandAntiFlashbangShader/anti-flashbang-weak.glsl new file mode 100644 index 000000000..6ab4a30fa --- /dev/null +++ b/dots/.config/quickshell/ii/services/hyprlandAntiFlashbangShader/anti-flashbang-weak.glsl @@ -0,0 +1,47 @@ +#version 300 es +precision highp float; + +in vec2 v_texcoord; +uniform sampler2D tex; +out vec4 fragColor; + +float overlayOpacityForBrightness(float x) { + // Note: range 0 to 1 + + // Will a fancy curve help?... I'll have to experiment more at night + // float y = pow(x, 2.0) * 0.75; + // float y = (1.0 - exp(-x))*1.19; + // float y = (1.0 - exp(-pow((x-0.15), 0.6)))*1.18; + + float y = x*0.42; + return min(max(y, 0.001), 1.0); +} + +void main() { + // 1. Get the current pixel color + vec4 pixColor = texture(tex, v_texcoord); + + // 2. Calculate average screen brightness + vec3 totalRGB = vec3(0.0); + float samples = 0.0; + + // We use a nested loop to create a 10x10 grid (100 samples) + // This is dense enough to catch small icons/text but light enough to run fast. + for(float x = 0.05; x < 1.0; x += 0.1) { + for(float y = 0.05; y < 1.0; y += 0.1) { + totalRGB += texture(tex, vec2(x, y)).rgb; + samples++; + } + } + + vec3 avgColor = totalRGB / samples; + float globalBrightness = dot(avgColor, vec3(0.2126, 0.7152, 0.0722)); + + // 3. Get the specific opacity for this brightness level + float opacity = overlayOpacityForBrightness(globalBrightness); + + // 4. Apply the "black overlay" effect + vec3 outColor = mix(pixColor.rgb, vec3(0.0), opacity); + + fragColor = vec4(outColor, pixColor.a); +}