Compare commits

..

57 Commits

Author SHA1 Message Date
a93761b042 update 2025-12-04 22:42:27 -08:00
a1ec1a54ba update 2025-12-03 22:49:24 -08:00
kyasuda
7b7fae9b91 update 2025-12-03 14:12:00 -08:00
d8a0e95bb5 bump versions 2025-12-02 18:49:10 -08:00
154f9e3ea6 update 2025-12-02 18:48:58 -08:00
4983623860 update mpv config 2025-12-02 18:48:51 -08:00
3628e70b72 update 2025-12-01 18:40:58 -08:00
31cfb8dd1c fux docs script 2025-12-01 18:09:32 -08:00
3fc0b32a9d update 2025-11-30 22:58:47 -08:00
4005e4650e move float center window rule down 2025-11-30 22:58:39 -08:00
3b87c06731 update rofi scripts 2025-11-30 22:57:56 -08:00
099d5e8ba6 update 2025-11-30 12:25:38 -08:00
21d6320cc1 update to new monitor 2025-11-30 12:25:25 -08:00
kyasuda
cb3641a9d9 send input directly to codecompanion inline command 2025-11-25 09:32:26 -08:00
b2cda94362 update window rules to new format 2025-11-20 12:26:07 -08:00
36d458c378 set sub-pos 2025-11-18 23:48:27 -08:00
5ec72352b8 update 2025-11-18 22:36:38 -08:00
7378fe9826 disable vrr on monitors 2025-11-16 20:54:53 -08:00
2006748e1d update keybindings 2025-11-14 10:24:20 -08:00
db9b3b65f1 update mpv config and remove osc.conf 2025-11-13 22:07:31 -08:00
a26255e83a update opacity rules and add keybind toggle 2025-11-12 11:30:48 -08:00
edec0e1b80 update 2025-11-12 11:27:51 -08:00
5e8bbf7f82 update 2025-10-24 23:21:58 -07:00
3f622c3298 update 2025-10-23 21:08:24 -07:00
918b5ccaec update keybindings 2025-10-23 21:08:07 -07:00
c36740a494 add codex 2025-10-22 22:34:09 -07:00
2688e2c488 add rofi-docs 2025-10-21 23:46:16 -07:00
db54fee30b fix stuff 2025-10-21 23:45:55 -07:00
c61bd04919 fix style 2025-10-21 23:08:39 -07:00
e5934fc174 fix border 2025-10-21 22:55:08 -07:00
cd370f70e6 add rmpv script 2025-10-20 18:23:44 -07:00
3bb7a5b0c7 remove lazy lock 2025-10-20 18:20:01 -07:00
kyasuda
2fc1896d89 update nvim 2025-10-20 09:36:39 -07:00
036e1b01dd remove cava 2025-10-16 22:21:12 -07:00
89732e90c5 update mpd config 2025-10-16 22:21:05 -07:00
7a1b814187 add center keybiding 2025-10-11 00:27:32 -07:00
9933e7a7f2 fix waybar 2025-10-11 00:27:21 -07:00
d8f8d4425b fix notification spacing when no notifications 2025-10-10 00:57:56 -07:00
7f963a9a6c fix waybar config and some other stuff 2025-10-09 23:56:49 -07:00
4c99d38f05 udpate 2025-10-03 14:52:42 -07:00
cebca89c32 udpate 2025-09-20 00:09:25 -07:00
kyasuda
356aac91db fix ruff config and linting 2025-09-19 11:42:29 -07:00
4589fc08b5 fix snacks indent 2025-09-14 01:29:17 -07:00
2c9749fa3d enable memory 2025-09-13 17:49:16 -07:00
102dc49fd0 update input.conf 2025-09-13 17:16:07 -07:00
5880b3093b add opencode 2025-09-12 00:42:11 -07:00
7f2e13e034 update nvim 2025-09-12 00:41:38 -07:00
f632c549d9 udpate 2025-09-10 01:17:20 -07:00
4d5bc435dc add submoudles symlink 2025-09-09 09:19:03 -07:00
63079f36bb update submodules 2025-09-09 09:18:34 -07:00
84071a8d37 remove old modules 2025-09-09 09:10:01 -07:00
574a880b5c update modules 2025-09-09 09:03:28 -07:00
77121f74de update script-opts config 2025-09-09 00:40:49 -07:00
7e3f8170bf Merge branch 'master' of github.com:ksyasuda/dotfiles 2025-09-09 00:33:47 -07:00
6f8ff08859 add mpv 2025-09-09 00:29:30 -07:00
kyasuda
73fed69cb7 update nvim 2025-09-05 11:04:16 -07:00
kyasuda
b8b8d6ef09 update nvim 2025-09-05 10:32:09 -07:00
113 changed files with 19079 additions and 589 deletions

View File

@@ -14,12 +14,34 @@
################ ################
# See https://wiki.hyprland.org/Configuring/Monitors/ # See https://wiki.hyprland.org/Configuring/Monitors/
monitor=DP-1,2560x1440@144,0x0,1, vrr, 1 # monitor=DP-1,2560x1440@144,0x0,1
monitor=DP-3,2560x1440@144,2560x0,1, vrr, 1 # monitor=DP-3,2560x1440@144,2560x0,1
# vrr 2 enables vrr if application is fullscreen
# vrr 3 enables vrr if application is fullscreen and video or game content
# monitor = DP-1, 3440x1440@240,0x0,1,vrr,3
monitorv2 {
output = DP-1
mode = 3440x1440@240
position = 0x0
scale = 1
vrr = 2
cm = srgb
# Optional HDR settings
# cm = hdr
# bitdepth = 10
# sdr_min_luminance = 0.005
# sdr_max_luminance = 200
# min_luminance = 0
# max_luminance = 1000
# max_avg_luminance = 200
# sdrbrightness = 1.2
# sdrsaturation = 0.98
}
source = ~/.config/hypr/keybindings.conf source = ~/.config/hypr/keybindings.conf
source = ~/.config/hypr/windowrules.conf
source = ~/.config/hypr/macchiato.conf source = ~/.config/hypr/macchiato.conf
# source = ~/.config/hypr/env.conf
# unscale XWayland # unscale XWayland
xwayland { xwayland {
force_zero_scaling = true force_zero_scaling = true
@@ -46,8 +68,8 @@ $notification_daemon = uwsm app -- swaync -c ~/.config/swaync/config.json
# Autostart necessary processes (like notifications daemons, status bars, etc.) # Autostart necessary processes (like notifications daemons, status bars, etc.)
# Or execute your favorite apps at launch like this: # Or execute your favorite apps at launch like this:
exec-once = uwsm app -sb -- hyprpm update -nn exec-once = uwsm app -sb -- hyprpm update -n
exec-once = uwsm app -sb -- hyprpm reload -nn exec-once = uwsm app -sb -- hyprpm reload -n
exec-once = $notification_daemon exec-once = $notification_daemon
exec-once = $terminal exec-once = $terminal
exec-once = uwsm app -sb -S both -t scope -- hyprpm update -nn exec-once = uwsm app -sb -S both -t scope -- hyprpm update -nn
@@ -55,7 +77,7 @@ exec-once = uwsm app -sb -S both -t scope -- hyprpm reload -nn
exec-once = uwsm app -sb -t service -- nm-applet exec-once = uwsm app -sb -t service -- nm-applet
exec-once = uwsm app -sb -t service -- waybar -c ~/.config/waybar/catppuccin-macchiato/config.jsonc -s ~/.config/waybar/catppuccin-macchiato/style.css exec-once = uwsm app -sb -t service -- waybar -c ~/.config/waybar/catppuccin-macchiato/config.jsonc -s ~/.config/waybar/catppuccin-macchiato/style.css
exec-once = uwsm app -sb -t service -- hyprsunset exec-once = uwsm app -sb -t service -- hyprsunset
exec-once = uwsm app -sb -t service -- polkit-kde-authentication-agent-1.desktop exec-once = uwsm app -sb -t service -- /usr/lib/polkit-kde-authentication-agent-1
exec-once = uwsm app -sb -t service -- variety exec-once = uwsm app -sb -t service -- variety
exec-once = ~/.local/bin/aria exec-once = ~/.local/bin/aria
# exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP
@@ -105,10 +127,10 @@ decoration {
rounding_power = 2 rounding_power = 2
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
# active_opacity = 0.88 active_opacity = 0.88
active_opacity = 1.0 # active_opacity = 1.0
# inactive_opacity = 0.88 inactive_opacity = 0.88
inactive_opacity = 1.0 # inactive_opacity = 1.0
shadow { shadow {
enabled = true enabled = true
@@ -166,10 +188,6 @@ animations {
# uncomment all if you wish to use that. # uncomment all if you wish to use that.
# workspace = w[tv1], gapsout:0, gapsin:0 # workspace = w[tv1], gapsout:0, gapsin:0
# workspace = f[1], gapsout:0, gapsin:0 # workspace = f[1], gapsout:0, gapsin:0
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
dwindle { dwindle {
@@ -212,7 +230,7 @@ input {
# https://wiki.hyprland.org/Configuring/Variables/#gestures # https://wiki.hyprland.org/Configuring/Variables/#gestures
gestures { gestures {
workspace_swipe = false # workspace_swipe = false
} }
# Example per-device config # Example per-device config
@@ -230,7 +248,8 @@ misc {
font_family = JetBrainsMono Nerd Font font_family = JetBrainsMono Nerd Font
} }
# {{{ WORKSPACES # {{{ WORKSPACES - HANDLED IN WAYBAR CONFIG
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
# workspace = name:,monitor:DP-1 # workspace = name:,monitor:DP-1
# workspace = 2,monitor:DP-1,defaultName: # workspace = 2,monitor:DP-1,defaultName:
# workspace = 2,monitor:DP-1,persistent:false # workspace = 2,monitor:DP-1,persistent:false
@@ -244,65 +263,9 @@ misc {
# workspace = 10,monitor:DP-3,persistent:false # workspace = 10,monitor:DP-3,persistent:false
# }}} # }}}
# windowrule = match:class my-window, border_size 10
############################## debug {
### WINDOWS AND WORKSPACES ### disable_logs = true
############################## enable_stdout_logs = false
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules
# Example windowrule v1
# windowrulev2 = float, class:com.mitchellh.ghostty
windowrule = float, class:discord
windowrule = float, class:mpv
windowrule = float, class:steam
windowrule = workspace 10 silent, class:discord
windowrule = workspace 9 silent, class:steam
# windowruv2 = opacity 0.88, class:.* fullscreen:0
windowrule = opacity 0.88, class:.* fullscreen:0
# windowruv2 = opacity 1, class:.* fullscreen:0
windowrule = opacity 1, class:mpv fullscreen:0
windowrule = opacity 1, class:anki fullscreen:0
windowrule = opacity 1, class:Thorium-browser title:(.*)asbplayer
windowrule = tile, class:Thorium-browser title:(.*)asbplayer
windowrule = opacity 1, class:^(remote-viewer)$
windowrule = opacity 1, class:com.obsproject.Studio
windowrule = opacity 1, title:(.*)(- YouTube(.*))
windowrule = opacity 1, class:zen, title:(.*)YouTube TV(.*)
# Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# Ignore maximize requests from apps. You'll probably like this.
windowrule = suppressevent maximize, class:.*
# Fix some dragging issues with XWayland
windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
# https://github.com/hyprwm/Hyprland/issues/3835#issuecomment-2004448245
windowrule = suppressevent maximize, class:^(zen)$
exec-once = $HOME/.local/bin/bitwarden-nofloat.sh
# ENABLE_HDR_WSI=1 mpv --vo=gpu-next --target-colorspace-hint --gpu-api=vulkan --gpu-context=waylandvk "filename"
# {{{ Screen sharing workaround: https://wiki.hyprland.org/Useful-Utilities/Screen-Sharing/#xwayland
windowrule = opacity 0.0 override, class:^(xwaylandvideobridge)$
windowrule = noanim, class:^(xwaylandvideobridge)$
windowrule = noinitialfocus, class:^(xwaylandvideobridge)$
windowrule = maxsize 1 1, class:^(xwaylandvideobridge)$
windowrule = noblur, class:^(xwaylandvideobridge)$
windowrule = nofocus, class:^(xwaylandvideobridge)$
# }}}
plugin {
split-monitor-workspaces {
count = 5
keep_focused = 1
enable_notifications = 1
enable_persistent_workspaces = 1
}
} }

View File

@@ -20,7 +20,7 @@ bind = $mainMod, d, exec, $menu
bind = $mainMod, P, pseudo, # dwindle bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, t, togglesplit, # dwindle bind = $mainMod, t, togglesplit, # dwindle
bind = $mainMod, f, fullscreen, bind = $mainMod, f, fullscreen,
bind = $mainMod, i, swapactiveworkspaces, DP-1 DP-3 bind = $mainMod, i, swapnext
# Move focus with mainMod + arrow keys # Move focus with mainMod + arrow keys
bind = $mainMod, h, movefocus, l bind = $mainMod, h, movefocus, l
@@ -32,6 +32,7 @@ bind = $mainMod SHIFT, j, movewindow, d
bind = $mainMod SHIFT, k, movewindow, u bind = $mainMod SHIFT, k, movewindow, u
bind = $mainMod SHIFT, h, movewindow, l bind = $mainMod SHIFT, h, movewindow, l
bind = $mainMod SHIFT, l, movewindow, r bind = $mainMod SHIFT, l, movewindow, r
bind = CTRL+SHIFT, c, centerwindow
# Move focus to next monitor # Move focus to next monitor
@@ -39,28 +40,28 @@ bind = CTRL+ALT, j, focusmonitor, r
bind = CTRL+ALT, k, focusmonitor, l bind = CTRL+ALT, k, focusmonitor, l
# Switch workspaces with mainMod + [0-9] # Switch workspaces with mainMod + [0-9]
bind = $mainMod, 1, split-workspace, 1 bind = $mainMod, 1, workspace, 1
bind = $mainMod, 2, split-workspace, 2 bind = $mainMod, 2, workspace, 2
bind = $mainMod, 3, split-workspace, 3 bind = $mainMod, 3, workspace, 3
bind = $mainMod, 4, split-workspace, 4 bind = $mainMod, 4, workspace, 4
bind = $mainMod, 5, split-workspace, 5 bind = $mainMod, 5, workspace, 5
bind = $mainMod, 6, split-workspace, 6 bind = $mainMod, 6, workspace, 6
bind = $mainMod, 7, split-workspace, 7 bind = $mainMod, 7, workspace, 7
bind = $mainMod, 8, split-workspace, 8 bind = $mainMod, 8, workspace, 8
bind = $mainMod, 9, split-workspace, 9 bind = $mainMod, 9, workspace, 9
bind = $mainMod, 0, split-workspace, 10 bind = $mainMod, 0, workspace, 10
# Move active window to a workspace with mainMod + SHIFT + [0-9] # Move active window to a workspace with mainMod + SHIFT + [0-9]
bind = $mainMod SHIFT, 1, split-movetoworkspacesilent, 1 bind = $mainMod SHIFT, 1, movetoworkspacesilent, 1
bind = $mainMod SHIFT, 2, split-movetoworkspacesilent, 2 bind = $mainMod SHIFT, 2, movetoworkspacesilent, 2
bind = $mainMod SHIFT, 3, split-movetoworkspacesilent, 3 bind = $mainMod SHIFT, 3, movetoworkspacesilent, 3
bind = $mainMod SHIFT, 4, split-movetoworkspacesilent, 4 bind = $mainMod SHIFT, 4, movetoworkspacesilent, 4
bind = $mainMod SHIFT, 5, split-movetoworkspacesilent, 5 bind = $mainMod SHIFT, 5, movetoworkspacesilent, 5
bind = $mainMod SHIFT, 6, split-movetoworkspacesilent, 6 bind = $mainMod SHIFT, 6, movetoworkspacesilent, 6
bind = $mainMod SHIFT, 7, split-movetoworkspacesilent, 7 bind = $mainMod SHIFT, 7, movetoworkspacesilent, 7
bind = $mainMod SHIFT, 8, split-movetoworkspacesilent, 8 bind = $mainMod SHIFT, 8, movetoworkspacesilent, 8
bind = $mainMod SHIFT, 9, split-movetoworkspacesilent, 9 bind = $mainMod SHIFT, 9, movetoworkspacesilent, 9
bind = $mainMod SHIFT, 0, split-movetoworkspacesilent, 10 bind = $mainMod SHIFT, 0, movetoworkspacesilent, 10
# Example special workspace (scratchpad) # Example special workspace (scratchpad)
bind = SUPER, S, togglespecialworkspace, magic bind = SUPER, S, togglespecialworkspace, magic
@@ -93,12 +94,13 @@ bindl = , XF86AudioPrev, exec, mpc prev
bind = $mainMod SHIFT, v, exec, uwsm app -sb -- rofi-rbw bind = $mainMod SHIFT, v, exec, uwsm app -sb -- rofi-rbw
bind = $mainMod, w, exec, rofi -show window -theme $HOME/.config/rofi/launchers/type-2/style-2.rasi -dpi 96 -theme-str 'window {width: 35%;}' bind = $mainMod, w, exec, rofi -show window -theme $HOME/.config/rofi/launchers/type-2/style-2.rasi -dpi 96 -theme-str 'window {width: 35%;}'
bind = $mainMod SHIFT, w, exec, $HOME/.config/rofi/scripts/rofi-wallpaper.sh bind = $mainMod SHIFT, w, exec, $HOME/.config/rofi/scripts/rofi-wallpaper.sh
bind = $mainMod SHIFT, d, exec, $HOME/.config/rofi/scripts/rofi-docs.sh
# ncmcppp # ncmcppp
bind = $mainMod, n, exec, uwsm app -sb -- ghostty --command=/usr/bin/ncmpcpp bind = $mainMod, n, exec, uwsm app -sb -- ghostty --command=/usr/bin/ncmpcpp
# notifications # notifications
bind = $mainMod SHIFT, n, exec, swaync-client -t bind = $mainMod SHIFT, n, exec, swaync-client -t
# mpv add # mpv add
bind = SUPER, m, exec, ~/.local/bin/mpv-add.sh bind = SUPER, m, exec, ~/.local/bin/mpv-add.sh
@@ -126,3 +128,14 @@ bind = $mainMod, z, exec, uwsm app -sb -- zen-browser
bind = $mainMod SHIFT, s, exec , rofi -show ssh -theme "$HOME/.config/rofi/launchers/type-2/style-2.rasi" -terminal -theme-str 'window{width: 25%;} listview {columns: 1; lines: 10;}' ghostty -ssh-command "ghostty --initial-command='TERM=kitty ssh {host}'" bind = $mainMod SHIFT, s, exec , rofi -show ssh -theme "$HOME/.config/rofi/launchers/type-2/style-2.rasi" -terminal -theme-str 'window{width: 25%;} listview {columns: 1; lines: 10;}' ghostty -ssh-command "ghostty --initial-command='TERM=kitty ssh {host}'"
# reload monitors
bind = $mainMod SHIFT, R, exec, hyprctl dispatch dpms off && sleep 1 && hyprctl dispatch dpms on
# Disable keybinds with one master keybind
# https://wiki.hypr.land/0.49.0/Configuring/Uncommon-tips--tricks/#disabling-keybinds-with-one-master-keybind
bind = $mainMod, code:117, submap, clean
submap = clean
bind = $mainMod, code:112, submap, reset
submap = reset
bind = SUPER, l, exec, hyprlock

View File

@@ -7,7 +7,7 @@ pid_file "~/.config/mpd/pid"
state_file "~/.config/mpd/mpdstate" state_file "~/.config/mpd/mpdstate"
playlist_directory "~/.config/mpd/playlists" playlist_directory "~/.config/mpd/playlists"
# music_directory "~/Music" # music_directory "~/Music"
music_directory "/jellyfin/music" music_directory "/truenas/jellyfin/music"
# music_directory "nfs://102.168.5.77:/nandury/jellyfin/music" # music_directory "nfs://102.168.5.77:/nandury/jellyfin/music"
database { database {
plugin "simple" plugin "simple"

6
.config/mpv/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
immersive-data
.ytdl_preload/
.ytdl-preload/
scripts/anilistUpdater/anilistToken.txt
.watch-later
state

2
.config/mpv/.prettierrc Normal file
View File

@@ -0,0 +1,2 @@
trailingComma: "es5"
singleQuote: true

Binary file not shown.

Binary file not shown.

285
.config/mpv/input.conf Normal file
View File

@@ -0,0 +1,285 @@
# mpv keybindings
#
# Location of user-defined bindings: ~/.config/mpv/input.conf
#
# Lines starting with # are comments. Use SHARP to assign the # key.
# Copy this file and uncomment and edit the bindings you want to change.
#
# List of commands and further details: DOCS/man/input.rst
# List of special keys: --input-keylist
# Keybindings testing mode: mpv --input-test --force-window --idle
#
# Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore').
#
# Strings need to be quoted and escaped:
# KEY show-text "This is a single backslash: \\ and a quote: \" !"
#
# You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with
# the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal).
#
# The default keybindings are hardcoded into the mpv binary.
# You can disable them completely with: --no-input-default-bindings
# Developer note:
# On compilation, this file is baked into the mpv binary, and all lines are
# uncommented (unless '#' is followed by a space) - thus this file defines the
# default key bindings.
# If this is enabled, treat all the following bindings as default.
#default-bindings start
#MBTN_LEFT ignore # don't do anything
#MBTN_LEFT_DBL cycle fullscreen # toggle fullscreen on/off
#MBTN_RIGHT cycle pause # toggle pause on/off
#MBTN_BACK playlist-prev
#MBTN_FORWARD playlist-next
# Mouse wheels, touchpad or other input devices that have axes
# if the input devices supports precise scrolling it will also scale the
# numeric value accordingly
#WHEEL_UP seek 10
#WHEEL_DOWN seek -10
#WHEEL_LEFT add volume -2
#WHEEL_RIGHT add volume 2
## Seek units are in seconds, but note that these are limited by keyframes
#RIGHT seek 5
#LEFT seek -5
#UP seek 60
#DOWN seek -60
# Do smaller, always exact (non-keyframe-limited), seeks with shift.
# Don't show them on the OSD (no-osd).
#Shift+RIGHT no-osd seek 1 exact
#Shift+LEFT no-osd seek -1 exact
#Shift+UP no-osd seek 5 exact
#Shift+DOWN no-osd seek -5 exact
# Skip to previous/next subtitle (subject to some restrictions; see manpage)
#Ctrl+LEFT no-osd sub-seek -1
#Ctrl+RIGHT no-osd sub-seek 1
# Adjust timing to previous/next subtitle
#Ctrl+Shift+LEFT sub-step -1
#Ctrl+Shift+RIGHT sub-step 1
# Move video rectangle
#Alt+left add video-pan-x 0.1
#Alt+right add video-pan-x -0.1
#Alt+up add video-pan-y 0.1
#Alt+down add video-pan-y -0.1
# Zoom/unzoom video
#Alt++ add video-zoom 0.1
#Alt+- add video-zoom -0.1
# Reset video zoom/pan settings
#Alt+BS set video-zoom 0 ; set video-pan-x 0 ; set video-pan-y 0
#PGUP add chapter 1 # skip to next chapter
#PGDWN add chapter -1 # skip to previous chapter
#Shift+PGUP seek 600
#Shift+PGDWN seek -600
[ add speed -0.05 # scale playback speed
] add speed 0.05
#{ multiply speed 0.5
#} multiply speed 2.0
#BS set speed 1.0 # reset speed to normal
#Shift+BS revert-seek # undo previous (or marked) seek
#Shift+Ctrl+BS revert-seek mark # mark position for revert-seek
#q quit
#Q quit-watch-later
#q {encode} quit 4
#ESC set fullscreen no
#ESC {encode} quit 4
#p cycle pause # toggle pause/playback mode
#. frame-step # advance one frame and pause
#, frame-back-step # go back by one frame and pause
#SPACE cycle pause
#> playlist-next # skip to next file
#ENTER playlist-next # skip to next file
#< playlist-prev # skip to previous file
#O no-osd cycle-values osd-level 3 1 # cycle through OSD mode
#o show-progress
#P show-progress
#i script-binding stats/display-stats
#I script-binding stats/display-stats-toggle
#` script-binding console/enable
#z add sub-delay -0.1 # subtract 100 ms delay from subs
#Z add sub-delay +0.1 # add
#x add sub-delay +0.1 # same as previous binding (discouraged)
#ctrl++ add audio-delay 0.100 # this changes audio/video sync
#ctrl+- add audio-delay -0.100
#Shift+g add sub-scale +0.1 # increase subtitle font size
#Shift+f add sub-scale -0.1 # decrease subtitle font size
9 add volume -5
#/ add volume -2
0 add volume 5
#* add volume 2
#m cycle mute
#1 add contrast -1
#2 add contrast 1
#3 add brightness -1
#4 add brightness 1
#5 add gamma -1
#6 add gamma 1
#7 add saturation -1
#8 add saturation 1
#Alt+0 set window-scale 0.5
#Alt+1 set window-scale 1.0
#Alt+2 set window-scale 2.0
# toggle deinterlacer (automatically inserts or removes required filter)
#d cycle deinterlace
#r add sub-pos -1 # move subtitles up
#R add sub-pos +1 # down
#t add sub-pos +1 # same as previous binding (discouraged)
#v cycle sub-visibility
# stretch SSA/ASS subtitles with anamorphic videos to match historical
#V cycle sub-ass-vsfilter-aspect-compat
# switch between applying no style overrides to SSA/ASS subtitles, and
# overriding them almost completely with the normal subtitle style
#u cycle-values sub-ass-override "force" "no"
#j cycle sub # cycle through subtitles
#J cycle sub down # ...backwards
#SHARP cycle audio # switch audio streams
#_ cycle video
#T cycle ontop # toggle video window ontop of other windows
#f cycle fullscreen # toggle fullscreen
#s screenshot # take a screenshot
#S screenshot video # ...without subtitles
#Ctrl+s screenshot window # ...with subtitles and OSD, and scaled
#Alt+s screenshot each-frame # automatically screenshot every frame
#w add panscan -0.1 # zoom out with -panscan 0 -fs
#W add panscan +0.1 # in
#e add panscan +0.1 # same as previous binding (discouraged)
# cycle video aspect ratios; "-1" is the container aspect
#A cycle-values video-aspect-override "16:9" "4:3" "2.35:1" "-1"
#POWER quit
#PLAY cycle pause
#PAUSE cycle pause
#PLAYPAUSE cycle pause
#PLAYONLY set pause no
#PAUSEONLY set pause yes
#STOP quit
#FORWARD seek 60
#REWIND seek -60
#NEXT playlist-next
#PREV playlist-prev
#VOLUME_UP add volume 2
#VOLUME_DOWN add volume -2
#MUTE cycle mute
#CLOSE_WIN quit
#CLOSE_WIN {encode} quit 4
#ctrl+w quit
#E cycle edition # next edition
#l ab-loop # Set/clear A-B loop points
#L cycle-values loop-file "inf" "no" # toggle infinite looping
#ctrl+c quit 4
#DEL script-binding osc/visibility # cycle OSC display
#ctrl+h cycle-values hwdec "auto" "no" # cycle hardware decoding
#F8 show_text ${playlist} # show playlist
#F9 show_text ${track-list} # show list of audio/sub streams
#
# Legacy bindings (may or may not be removed in the future)
#
#! add chapter -1 # skip to previous chapter
#@ add chapter 1 # next
#
# Not assigned by default
# (not an exhaustive list of unbound commands)
#
# ? cycle angle # switch DVD/Bluray angle
# ? cycle sub-forced-only # toggle DVD forced subs
# ? cycle program # cycle transport stream programs
# ? stop # stop playback (quit or enter idle mode)
# n cycle_values af loudnorm=I=-30 loudnorm=I=-15 anull
CTRL+1 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/FSR.glsl"; show-text "FSR"
CTRL+2 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/NVScaler.glsl"; show-text "NIS"
CTRL+3 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/CAS-scaled.glsl"; show-text "CAS"
CTRL+4 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/FSRCNNX.glsl"; show-text "FSRCNNX"
CTRL+5 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/ArtCNN_C4F32.glsl"; show-text "ArtCNN"
CTRL+6 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/ArtCNN_C4F16_DS.glsl"; show-text "ArtCNN"
CTRL+7 no-osd change-list glsl-shaders set "~/.config/mpv/shaders/ArtCNN_C4F16.glsl"; show-text "ArtCNN"
CTRL+0 no-osd change-list glsl-shaders clr ""; show-text "GLSL shaders cleared"
ctrl+K cycle-values keep-open "yes" "no"
ctrl+r script-binding reload-scripts
ctrl+s script_binding autosubsync-menu
# {{{ sponsorblock
ctrl+g script-binding sponsorblock/set_segment
ctrl+G script-binding sponsorblock/submit_segment
ctrl+< script-binding sponsorblock/upvote_setment
ctrl+> script-binding sponsorblock/downvote_segment
#}}}
# {{{ anilist
ctrl+A script-binding update_anilist
ctrl+B script-binding launch_anilist
ctrl+E script-binding open_folder
ctrl+V script-binding mpvacious-secondary-sid-toggle
# }}}
# {{{ mpvacious (subs2srs)
a script-binding mpvacious-menu-open
ctrl+g ignore # script-binding mpvacious-animated-snapshot-toggle
ctrl+N script-binding mpvacious-export-note
ctrl+b ignore # script-binding mpvacious-update-selected-note
ctrl+B ignore # script-binding mpvacious-overwrite-selected-note
ctrl+m ignore # script-binding mpvacious-update-last-note
ctrl+M ignore # script-binding mpvacious-overwrite-last-note
G script-binding mpvacious-quick-card-menu-open
alt+g script-binding mpvacious-quick-card-sel-menu-open
ctrl+c script-binding mpvacious-copy-primary-sub-to-clipboard
ctrl+C script-binding mpvacious-copy-secondary-sub-to-clipboard
ctrl+= script-binding mpvacious-autocopy-toggle
H script-binding mpvacious-sub-seek-back
L script-binding mpvacious-sub-seek-forward
alt+h script-binding mpvacious-sub-seek-back-pause
alt+l script-binding mpvacious-sub-seek-forward-pause
ctrl+h script-binding mpvacious-sub-rewind
ctrl+H script-binding mpvacious-sub-replay
ctrl+L script-binding mpvacious-sub-play-up-to-next
ctrl+V script-binding mpvacious-secondary-sid-toggle
ctrl+K script-binding mpvacious-secondary-sid-prev
ctrl+J script-binding mpvacious-secondary-sid-next
# }}}
# {{{ animecards
ctrl+v script-binding animecards/update-anki-card
# }}}
# {{{ mpv-youtube-queue
ctrl+a script-binding mpv_youtube_queue/add_to_queue
ctrl+n script-binding mpv_youtube_queue/play_next_in_queue
ctrl+p script-binding mpv_youtube_queue/play_previous_in_queue
ctrl+q script-binding mpv_youtube_queue/print_queue
ctrl+k script-binding mpv_youtube_queue/move_cursor_up
ctrl+j script-binding mpv_youtube_queue/move_cursor_down
ctrl+ENTER script-binding mpv_youtube_queue/play_selected_video
ctrl+o script-binding mpv_youtube_queue/open_video_in_browser
ctrl+P script-binding mpv_youtube_queue/print_current_video
ctrl+O script-binding mpv_youtube_queue/open_channel_in_browser
ctrl+d script-binding mpv_youtube_queue/download_current_video
ctrl+D script-binding mpv_youtube_queue/download_selected_video
ctrl+m script-binding mpv_youtube_queue/move_video
ctrl+x script-binding mpv_youtube_queue/delete_video
#}}}
#{{{ MPV SELECT
g ignore
g-a script-binding select/select-aid
g-b script-binding select/select-binding
g-c script-binding select/select-chapter
g-e script-binding select/select-edition
g-h script-binding select/select-watch-history
g-l script-binding select/select-subtitle-line
g-m script-binding select/menu
g-p script-binding select/select-playlist
g-r script-binding select/show-properties
g-s script-binding select/select-sid
g-S script-binding select/select-secondary-sid
g-t script-binding select/select-track
g-v script-binding select/select-vid
g-w script-binding select/select-watch-later
# }}}
# {{{ IMMERSION TRACKER
ctrl+t script-binding immersion_tracker/immersion_tracking
# }}}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/home/sudacode/.config/mpv/fonts</dir>
<include ignore_missing="yes">/etc/fonts/fonts.conf</include>
<include ignore_missing="yes">/etc/fonts/conf.d</include>
<alias>
<family>sans-serif</family>
<prefer>
<family>JetBrainsMono Nerd Font</family>
<family>Fluent System Icons</family>
<family>Noto Sans CJK JP</family>
<family>Noto Sans</family>
<family>Open Sans</family>
</prefer>
</alias>
</fontconfig>

View File

@@ -0,0 +1,174 @@
profile=high-quality
user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
glsl-shaders="" # Disable heavy shaders for regular content
# glsl-shaders="~~/shaders/ArtCNN_C4F32_DS.glsl"
# glsl-shaders="~~/shaders/ArtCNN_C4F32.glsl"
scale=spline36 # Faster than ewa_lanczos for high-res video when shaders are off
dither=fruit # Lighter dithering aimed at 8-bit or FRC panels
# --- Window & interface ---
ontop=yes
border=no
no-border
autofit=50% # Start at half of the screen to avoid oversized windows on UHD displays
osc=no
blend-subtitles=video # Keeps subtitles composited into the video plane
opengl-early-flush=no # Delay buffer flushes to reduce micro-stutter on some GPUs
# --- Subtitle defaults ---
sub-font="JetBrainsMono Nerd Font"
sub-font-size=45
sub-auto=fuzzy
slang=en,eng
subs-with-matching-audio=no
sub-fix-timing=yes
sub-ass-override=scale
sub-gauss=1.0
sub-gray=yes
sub-pos=100
# --- Audio chain ---
volume=75
ao=pipewire,pulse
audio-spdif=ac3,dts-hd,truehd
audio-stream-silence=yes # Keep the device primed to avoid startup pops
audio-wait-open=0.1 # Shorten audio device warm-up for snappier playback
# --- Networking & remote sources ---
ytdl-format=bestvideo+bestaudio/best
ytdl-raw-options=sub-langs=en.*,write-auto-subs=
ytdl-raw-options-append=sponsorblock-mark=all
ytdl-raw-options-append=sponsorblock-remove=sponsor,selfpromo,interaction
# --- Video output & decoding ---
vo=gpu-next
hwdec=nvdec
hwdec-codecs=all
gpu-api=vulkan
gpu-context=waylandvk
vulkan-queue-count=2
vulkan-async-compute=yes # Use independent compute queues for tone mapping/shaders
vulkan-async-transfer=yes # Parallelize frame uploads to free the graphics queue
vd-lavc-dr=yes # Direct rendering keeps frames resident on the GPU longer
vd-lavc-threads=0 # Let ffmpeg auto-pick the optimal thread count
video-sync=display-resample # Smoothly match video speed to the display refresh
# --- Scaling, interpolation, and dithering ---
scale=ewa_lanczossharp
dscale=catmull_rom
cscale=ewa_lanczos
tscale=oversample
interpolation=yes
interpolation-preserve=no
interpolation-threshold=0.5 # Only blend nearby frames to reduce SOE artifacts
sigmoid-upscaling=yes # Protect highlights when upscaling SDR video
temporal-dither=yes # Prefer temporal noise over spatial patterns on SDR panels
# Dithering presets reference:
# fruit -> 8-bit / 8-bit + FRC displays
# ordered -> True 10-bit / 12-bit displays
# error-diffusion -> High-end GPUs
dither=error-diffusion
dither-depth=auto
error-diffusion=sierra-lite # Balanced diffusion kernel for 8-bit panels
# --- Antiring controls ---
scale-antiring=0.5
dscale-antiring=0.5
cscale-antiring=0.5
# --- Post-processing ---
deband=yes
deband-iterations=2
deband-threshold=24
deband-range=16
deband-grain=4
# --- IPC & automation ---
input-ipc-server=/tmp/mpvsocket # Allows external tools (e.g., SVP) to control mpv
# --- Screenshot workflow ---
screenshot-format=webp
screenshot-webp-lossless=yes
screenshot-high-bit-depth=yes
screenshot-sw=no # Force GPU path so tone mapping stays consistent
screenshot-directory="/truenas/sudacode/pictures/mpv"
screenshot-template="%f-%wH.%wM.%wS.%wT-#%#00n"
# --- Session persistence ---
save-position-on-quit
watch-later-dir="~~/.watch-later"
resume-playback=yes
save-watch-history
watch-history-path="~~/state/watch_history.jsonl"
# --- HDR/SDR hints ---
target-colorspace-hint=yes
# --- Caching & buffers ---
cache=yes
demuxer-max-bytes=1GiB # Buffer up to 1 GiB for high-bitrate remuxes
demuxer-max-back-bytes=200MiB # Keep recent data handy for quick reverse seeks
cache-secs=30
demuxer-readahead-secs=30
[anime]
profile-desc="Anime upscaling with ArtCNN"
glsl-shaders="~~/shaders/ArtCNN_C4F32.glsl"
scale=ewa_lanczossharp
dither=error-diffusion
deband=yes # Crucial for anime gradients
[movies]
profile-desc="Movies and TV shows"
profile-cond=width >= 1920 and filename:match("mkv$|mp4$")
glsl-shaders=""
scale=ewa_lanczos
target-peak=800
[hdr]
target-colorspace-hint=yes
tone-mapping-param=0.5
tone-mapping-max-boost=2.0
allow-delayed-peak-detect=yes
# For SDR content on HDR display (or vice versa)
icc-profile-auto=yes
[svp]
interpolation=no
input-ipc-server=/tmp/mpvsocket
hr-seek-framedrop=no
resume-playback=no
[Idle]
profile-cond=p["idle-active"]
profile-restore=copy-equal
title=' '
keepaspect=no
[immersion]
cookies=yes
cookies-file=/truenas/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options=mark-watched=,write-auto-subs=,sub-langs=ja.*
ytdl-raw-options-append=cookies=/truenas/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options-append=sponsorblock-mark=all
ytdl-raw-options-append=sponsorblock-remove=sponsor,selfpromo,interaction
ytdl-format=bestvideo+bestaudio/best
sub-auto=fuzzy
alang=ja,jp,jpn,japanese,en,eng,english,English,enUS,en-US
slang=ja,jp,jpn,japanese,en,eng,english,English,enUS,en-US
vlang=ja,jpn
subs-with-matching-audio=yes
sub-font="Noto Sans CJK JP Regular"
glsl-shaders="~~/shaders/ArtCNN_C4F32.glsl"
scale=ewa_lanczossharp
dither=error-diffusion
deband=yes # Crucial for anime gradients
[anime-subs]
profile-cond=p["slang"] == "ja" or p["slang"] == "ja.hi"
sub-font="Noto Sans CJK JP Regular"
sub-font-size=42
sub-border-size=1.2
sub-shadow-color=0.0/0.0/0.0/0.6
sub-shadow-offset=3
sub-hinting=light

View File

@@ -0,0 +1,206 @@
user-agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36"
glsl-shaders=""
scale=spline36 # Fast, high-quality fallback
dither=fruit # Lightweight dithering
# Window & interface
ontop=yes
border=no
no-border
autofit=50% # Reasonable default size
# Audio (macOS-specific)
volume=75
ao=coreaudio # Native macOS audio
audio-stream-silence=no # FIXED: Prevents player behavior issues
audio-wait-open=0.1 # Faster audio startup
# Subtitle defaults
sub-font="JetBrainsMono Nerd Font"
sub-font-size=45
sub-auto=fuzzy
slang=en,eng
subs-with-matching-audio=no
sub-fix-timing=yes
sub-ass-override=scale
sub-gauss=1.0
sub-gray=yes
sub-pos=90
# Networking & streaming
ytdl-format=bestvideo+bestaudio/best
ytdl-raw-options=sub-langs=en.*,write-auto-subs=
ytdl-raw-options-append=sponsorblock-mark=all
ytdl-raw-options-append=sponsorblock-remove=sponsor,selfpromo,interaction
# Stats & UI colors (Catppuccin Macchiato)
background-color='#24273a'
osd-back-color='#181926'
osd-border-color='#181926'
osd-color='#cad3f5'
osd-shadow-color='#24273a'
script-opts-append=stats-border_color=30201e
script-opts-append=stats-font_color=f5d3ca
script-opts-append=stats-plot_bg_border_color=f8bdb7
script-opts-append=stats-plot_bg_color=30201e
script-opts-append=stats-plot_color=f8bdb7
##################
# Video/Graphics #
##################
vo=gpu-next
hwdec=videotoolbox # macOS hardware decoding
hwdec-codecs=all
gpu-api=vulkan
gpu-context=macvk # macOS-specific Vulkan context
# Vulkan optimizations (prevents crashes and memory leaks)
vulkan-queue-count=1 # FIXED: Prevents buffer overflow
vulkan-async-compute=no # FIXED: Improves stability
vulkan-async-transfer=no # FIXED: Reduces memory pressure
vulkan-swap-mode=fifo # Most compatible presentation mode
fbo-format=rgba8 # FIXED: Memory-safe format
# Video filtering & quality
vd-lavc-film-grain=cpu # FIXED: GPU grain not supported on macOS
vd-lavc-threads=0
vd-lavc-dr=yes # Keep frames on GPU
video-sync=display-resample # Smooth playback
# Scaling & interpolation
scale=ewa_lanczossharp
dscale=catmull_rom
cscale=ewa_lanczos
tscale=oversample
interpolation=yes
interpolation-threshold=0.5
sigmoid-upscaling=yes
temporal-dither=yes
# High-quality dithering
dither=error-diffusion
dither-depth=auto
error-diffusion=sierra-lite
# Antiring
scale-antiring=0.5
dscale-antiring=0.5
cscale-antiring=0.5
# Post-processing
deband=yes
deband-iterations=2
deband-threshold=24
deband-range=16
deband-grain=4
##################
# Screenshot #
##################
screenshot-format=webp
screenshot-webp-lossless=yes
screenshot-high-bit-depth=yes
screenshot-sw=no
screenshot-directory="/Volumes/sudacode/pictures/mpv"
screenshot-template="%f-%wH.%wM.%wS.%wT-#%#00n"
##################
# Session #
##################
save-position-on-quit
watch-later-dir="~~/.watch-later"
resume-playback=yes
save-watch-history
watch-history-path="~~/state/watch_history.jsonl"
input-ipc-server=/tmp/mpvsocket
##################
# Caching #
##################
cache=yes
demuxer-max-bytes=1GiB
demuxer-max-back-bytes=200MiB
cache-pause=no
cache-secs=30
demuxer-readahead-secs=30
############
# Profiles #
############
# Base high-quality preset (inherits above settings)
[base]
profile=gpu-hq
# Anime profile (ArtCNN is memory-heavy, use cautiously)
[anime]
profile-desc="Anime upscaling with ArtCNN"
profile-cond=filename:match("mkv$") and height <= 1080
glsl-shaders="~~/shaders/ArtCNN_C4F16.glsl" # Use F16 variant (lighter)
scale=ewa_lanczossharp
deband=yes
# Movies profile (no shaders, HDR support)
[movies]
profile-desc="Movies and TV shows"
profile-cond=width >= 1920 and filename:match("mkv$|mp4$")
glsl-shaders=""
scale=ewa_lanczos
target-peak=800
hdr-tone-mapping=bt.2390
# HDR profile
[hdr]
target-colorspace-hint=yes
tone-mapping-param=0.5
tone-mapping-max-boost=2.0
allow-delayed-peak-detect=yes
icc-profile-auto=yes
# SVP compatibility profile
[svp]
interpolation=no
input-ipc-server=/tmp/mpvsocket
hr-seek-framedrop=no
resume-playback=no
# Idle profile
[Idle]
profile-cond=p["idle-active"]
profile-restore=copy-equal
title=' '
keepaspect=no
# Japanese immersion profile
[immersion]
cookies=yes
cookies-file=/Volumes/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options=mark-watched=,write-auto-subs=,sub-langs=ja.*
ytdl-raw-options-append=cookies=/Volumes/sudacode/japanese/cookies.Japanese.txt
ytdl-raw-options-append=sponsorblock-mark=all
ytdl-raw-options-append=sponsorblock-remove=sponsor
ytdl-format=bestvideo+bestaudio/best
sub-auto=fuzzy
alang=ja,jp,jpn,japanese,en,eng,english,English,enUS,en-US
slang=ja,jp,jpn,japanese,en,eng,english,English,enUS,en-US
vlang=ja,jpn
subs-with-matching-audio=yes
sub-font="Noto Sans CJK JP Regular"
glsl-shaders="~~/shaders/ArtCNN_C4F32.glsl"
scale=ewa_lanczossharp
dither=error-diffusion
deband=yes # Crucial for anime gradients
# Anime subtitles profile
[anime-subs]
profile-cond=p["slang"] == "ja" or p["slang"] == "ja.hi"
sub-font="Noto Sans CJK JP"
sub-font-size=42
sub-border-size=1.2
sub-shadow-color=0.0/0.0/0.0/0.6
sub-shadow-offset=3

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,293 @@
local mp = require 'mp'
local scroll_list = {
global_style = [[]],
header_style = [[{\q2\fs35\c&00ccff&}]],
list_style = [[{\q2\fs25\c&Hffffff&}]],
wrapper_style = [[{\c&00ccff&\fs16}]],
cursor_style = [[{\c&00ccff&}]],
selected_style = [[{\c&Hfce788&}]],
cursor = [[➤\h]],
indent = [[\h\h\h\h]],
num_entries = 16,
wrap = false,
empty_text = "no entries"
}
--formats strings for ass handling
--this function is based on a similar function from https://github.com/mpv-player/mpv/blob/master/player/lua/console.lua#L110
function scroll_list.ass_escape(str, replace_newline)
if replace_newline == true then replace_newline = "\\\239\187\191n" end
--escape the invalid single characters
str = str:gsub('[\\{}\n]', {
-- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if
-- it isn't followed by a recognised character, so add a zero-width
-- non-breaking space
['\\'] = '\\\239\187\191',
['{'] = '\\{',
['}'] = '\\}',
-- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of
-- consecutive newlines
['\n'] = '\239\187\191\\N',
})
-- Turn leading spaces into hard spaces to prevent ASS from stripping them
str = str:gsub('\\N ', '\\N\\h')
str = str:gsub('^ ', '\\h')
if replace_newline then
str = str:gsub("\\N", replace_newline)
end
return str
end
--format and return the header string
function scroll_list:format_header_string(str)
return str
end
--appends the entered text to the overlay
function scroll_list:append(text)
if text == nil then return end
self.ass.data = self.ass.data .. text
end
--appends a newline character to the osd
function scroll_list:newline()
self.ass.data = self.ass.data .. '\\N'
end
--re-parses the list into an ass string
--if the list is closed then it flags an update on the next open
function scroll_list:update()
if self.hidden then self.flag_update = true
else self:update_ass() end
end
--prints the header to the overlay
function scroll_list:format_header()
self:append(self.header_style)
self:append(self:format_header_string(self.header))
self:newline()
end
--formats each line of the list and prints it to the overlay
function scroll_list:format_line(index, item)
self:append(self.list_style)
if index == self.selected then self:append(self.cursor_style..self.cursor..self.selected_style)
else self:append(self.indent) end
self:append(item.style)
self:append(item.ass)
self:newline()
end
--refreshes the ass text using the contents of the list
function scroll_list:update_ass()
self.ass.data = self.global_style
self:format_header()
if #self.list < 1 then
self:append(self.empty_text)
self.ass:update()
return
end
local start = 1
local finish = start+self.num_entries-1
--handling cursor positioning
local mid = math.ceil(self.num_entries/2)+1
if self.selected+mid > finish then
local offset = self.selected - finish + mid
--if we've overshot the end of the list then undo some of the offset
if finish + offset > #self.list then
offset = offset - ((finish+offset) - #self.list)
end
start = start + offset
finish = finish + offset
end
--making sure that we don't overstep the boundaries
if start < 1 then start = 1 end
local overflow = finish < #self.list
--this is necessary when the number of items in the dir is less than the max
if not overflow then finish = #self.list end
--adding a header to show there are items above in the list
if start > 1 then self:append(self.wrapper_style..(start-1)..' item(s) above\\N\\N') end
for i=start, finish do
self:format_line(i, self.list[i])
end
if overflow then self:append('\\N'..self.wrapper_style..#self.list-finish..' item(s) remaining') end
self.ass:update()
end
--moves the selector down the list
function scroll_list:scroll_down()
if self.selected < #self.list then
self.selected = self.selected + 1
self:update_ass()
elseif self.wrap then
self.selected = 1
self:update_ass()
end
end
--moves the selector up the list
function scroll_list:scroll_up()
if self.selected > 1 then
self.selected = self.selected - 1
self:update_ass()
elseif self.wrap then
self.selected = #self.list
self:update_ass()
end
end
--moves the selector to the list next page
function scroll_list:move_pagedown()
if #self.list > self.num_entries then
self.selected = self.selected + self.num_entries
if self.selected > #self.list then self.selected = #self.list end
self:update_ass()
end
end
--moves the selector to the list previous page
function scroll_list:move_pageup()
if #self.list > self.num_entries then
self.selected = self.selected - self.num_entries
if self.selected < 1 then self.selected = 1 end
self:update_ass()
end
end
--moves the selector to the list begin
function scroll_list:move_begin()
if #self.list > 1 then
self.selected = 1
self:update_ass()
end
end
--moves the selector to the list end
function scroll_list:move_end()
if #self.list > 1 then
self.selected = #self.list
self:update_ass()
end
end
--adds the forced keybinds
function scroll_list:add_keybinds()
for _,v in ipairs(self.keybinds) do
mp.add_forced_key_binding(v[1], 'dynamic/'..self.ass.id..'/'..v[2], v[3], v[4])
end
end
--removes the forced keybinds
function scroll_list:remove_keybinds()
for _,v in ipairs(self.keybinds) do
mp.remove_key_binding('dynamic/'..self.ass.id..'/'..v[2])
end
end
--opens the list and sets the hidden flag
function scroll_list:open_list()
self.hidden = false
if not self.flag_update then self.ass:update()
else self.flag_update = false ; self:update_ass() end
end
--closes the list and sets the hidden flag
function scroll_list:close_list()
self.hidden = true
self.ass:remove()
end
--modifiable function that opens the list
function scroll_list:open()
if self.hidden then self:add_keybinds() end
self:open_list()
end
--modifiable function that closes the list
function scroll_list:close()
self:remove_keybinds()
self:close_list()
end
--toggles the list
function scroll_list:toggle()
if self.hidden then self:open()
else self:close() end
end
--clears the list in-place
function scroll_list:clear()
local i = 1
while self.list[i] do
self.list[i] = nil
i = i + 1
end
end
--added alias for ipairs(list.list) for lua 5.1
function scroll_list:ipairs()
return ipairs(self.list)
end
--append item to the end of the list
function scroll_list:insert(item)
self.list[#self.list + 1] = item
end
local metatable = {
__index = function(t, key)
if scroll_list[key] ~= nil then return scroll_list[key]
elseif key == "__current" then return t.list[t.selected]
elseif type(key) == "number" then return t.list[key] end
end,
__newindex = function(t, key, value)
if type(key) == "number" then rawset(t.list, key, value)
else rawset(t, key, value) end
end,
__scroll_list = scroll_list,
__len = function(t) return #t.list end,
__ipairs = function(t) return ipairs(t.list) end
}
--creates a new list object
function scroll_list:new()
local vars
vars = {
ass = mp.create_osd_overlay('ass-events'),
hidden = true,
flag_update = true,
header = "header \\N ----------------------------------------------",
list = {},
selected = 1,
keybinds = {
{'DOWN', 'scroll_down', function() vars:scroll_down() end, {repeatable = true}},
{'UP', 'scroll_up', function() vars:scroll_up() end, {repeatable = true}},
{'PGDWN', 'move_pagedown', function() vars:move_pagedown() end, {}},
{'PGUP', 'move_pageup', function() vars:move_pageup() end, {}},
{'HOME', 'move_begin', function() vars:move_begin() end, {}},
{'END', 'move_end', function() vars:move_end() end, {}},
{'ESC', 'close_browser', function() vars:close() end, {}}
}
}
return setmetatable(vars, metatable)
end
return scroll_list:new()

View File

@@ -0,0 +1,11 @@
# Use 'yes' or 'no' for boolean options below
# Example for multiple directories (comma or semicolon separated):
# DIRECTORIES=D:/Torrents,D:/Anime
# or
# DIRECTORIES=D:/Torrents;D:/Anime
DIRECTORIES=/truenas/jellyfin/anime
UPDATE_PERCENTAGE=85
SET_COMPLETED_TO_REWATCHING_ON_FIRST_EPISODE=no
UPDATE_PROGRESS_WHEN_REWATCHING=yes
SET_TO_COMPLETED_AFTER_LAST_EPISODE_CURRENT=yes
SET_TO_COMPLETED_AFTER_LAST_EPISODE_REWATCHING=yes

View File

@@ -0,0 +1,11 @@
# Use 'yes' or 'no' for boolean options below
# Example for multiple directories (comma or semicolon separated):
# DIRECTORIES=D:/Torrents,D:/Anime
# or
# DIRECTORIES=D:/Torrents;D:/Anime
DIRECTORIES=/Volumes/jellyfin/anime
UPDATE_PERCENTAGE=85
SET_COMPLETED_TO_REWATCHING_ON_FIRST_EPISODE=no
UPDATE_PROGRESS_WHEN_REWATCHING=yes
SET_TO_COMPLETED_AFTER_LAST_EPISODE_CURRENT=yes
SET_TO_COMPLETED_AFTER_LAST_EPISODE_REWATCHING=yes

View File

@@ -0,0 +1,107 @@
# =================================================
# Anacreon Script (Animecards) Config for MPV
# =================================================
# ⚠ WARNING:
# Use only yes/no (not true/false) in boolean options
# =================================================
# Anki Field Names
# These must match the field names in your Anki note type
# =================================================
FRONT_FIELD=Expression
SENTENCE_FIELD=Sentence
IMAGE_FIELD=Picture
SENTENCE_AUDIO_FIELD=SentenceAudio
# =================================================
# Behavior Settings
# =================================================
# [Not recommended] Copy subtitles to clipboard enabled by default? (yes/no)
# The more modern and recommended alternative is to use the websocket.
ENABLE_SUBS_TO_CLIP=no
# Ask before overwriting existing cards? (yes/no)
# Recommended to set yes unless you know what you are doing
ASK_TO_OVERWRITE=yes
# [Dangerous] Max cards that can be overwritten at once (-1 = unlimited)
OVERWRITE_LIMIT=8
# Keep bold formatting added by yomitan? (yes/no)
HIGHLIGHT_WORD=no
# Use MPV's built-in clipboard API (requires v0.40+)? (yes/no)
# Alternative clipboard method that may reduce latency on Windows.
# Supported on macOS and Wayland as well. Not supported on X11.
USE_MPV_CLIPBOARD_API=no
# ==========================================================
# Audio Settings
# ==========================================================
# [Optional] Padding and fade settings in seconds. (0 = disable)
# Padding grabs extra audio around your selected subs.
# Fade does a volume fade in/out effect.
AUDIO_CLIP_PADDING=0.75
AUDIO_CLIP_FADE=0.2
# Always create mono audio? (yes/no)
AUDIO_MONO=yes
# [Optional] Use MPV's current volume for card audio? (yes/no)
USE_MPV_VOLUME=no
# [Optional] Play sentence audio after updating the card? (yes/no)
AUTOPLAY_AUDIO=no
# =================================================
# Image Settings
# =================================================
# Format of screenshots: png, jpg or webp
# ⚠ Use png or jpg for iOS/Mac compatibility
# (webp won't display on iOS/Mac)
IMAGE_FORMAT=png
# Resize image to this height (in pixels).
# Preserves aspect ratio. (0 = keep original resolution)
IMAGE_HEIGHT=480
# [JPG only] Quality: from 0 (worst) to 100 (best)
JPG_QUALITY=88
# =================================================
# Animated Image Settings
# =================================================
# Enable animated export for the selected subtitle segment (yes/no)
ANIMATED_IMAGE_ENABLED=yes
# Animated format: webp or avif
ANIMATED_IMAGE_FORMAT=avif
# Resize animated image to this height (in pixels). (0 = keep original)
ANIMATED_IMAGE_HEIGHT=480
# Frames per second for animated export (1-30)
ANIMATED_IMAGE_FPS=24
# Quality 0-100 (mapped to CRF for avif)
ANIMATED_IMAGE_QUALITY=69
# =================================================
# Misc Info - Extra metadata for cards
# =================================================
# [Optional] Save extra metadata (filename, timestamp, etc.) to a field
WRITE_MISCINFO=yes
# Field to store the extra info (only used if WRITE_MISCINFO=yes)
MISCINFO_FIELD=MiscInfo
# Pattern for the Misc Info content:
# %f = filename (without extension)
# %F = filename (with extension)
# %t = timestamp (HH:MM:SS)
# %T = timestamp with milliseconds (HH:MM:SS:MLS)
# <br> = Next line tag
# Examples:
# MISCINFO_PATTERN %f (%t)
# MISCINFO_PATTERN=File: %F<br>Timestamp: %T
MISCINFO_PATTERN=[Anacreon Script] %f (%t)

View File

@@ -0,0 +1,33 @@
# Absolute paths to the executables, if needed:
# 1. ffmpeg
ffmpeg_path=/usr/bin/ffmpeg
# 2. ffsubsync
ffsubsync_path=/usr/bin/ffsubsync
# 3. alass
alass_path=/usr/bin/alass
# Preferred retiming tool. Allowed options: 'ffsubsync', 'alass', 'ask'.
# If set to 'ask', the add-on will ask to choose the tool every time:
# 1. Preferred tool for syncing to audio.
# audio_subsync_tool=ask
audio_subsync_tool=ffsubsync
# audio_subsync_tool=alass
# 2. Preferred tool for syncing to another subtitle.
# altsub_subsync_tool=ask
# altsub_subsync_tool=ffsubsync
altsub_subsync_tool=alass
# Unload old subs (yes,no)
# After retiming, tell mpv to forget the original subtitle track.
unload_old_sub=yes
# unload_old_sub=no
# Overwrite the original subtitle file.
# Replace the old subtitle file with the retimed file.
# overwrite_old_sub=yes
overwrite_old_sub=no

View File

@@ -0,0 +1,33 @@
# Absolute paths to the executables, if needed:
# 1. ffmpeg
ffmpeg_path=/opt/homebrew/bin/ffmpeg
# 2. ffsubsync
ffsubsync_path=/Users/sudacode/.local/bin/ffsubsync
# 3. alass
alass_path=/Users/sudacode/.local/bin/alass-cli
# Preferred retiming tool. Allowed options: 'ffsubsync', 'alass', 'ask'.
# If set to 'ask', the add-on will ask to choose the tool every time:
# 1. Preferred tool for syncing to audio.
# audio_subsync_tool=ask
audio_subsync_tool=ffsubsync
# audio_subsync_tool=alass
# 2. Preferred tool for syncing to another subtitle.
# altsub_subsync_tool=ask
# altsub_subsync_tool=ffsubsync
altsub_subsync_tool=alass
# Unload old subs (yes,no)
# After retiming, tell mpv to forget the original subtitle track.
unload_old_sub=yes
# unload_old_sub=no
# Overwrite the original subtitle file.
# Replace the old subtitle file with the retimed file.
# overwrite_old_sub=yes
overwrite_old_sub=no

View File

@@ -0,0 +1,22 @@
start_tracking_key=ctrl+t
data_dir=/home/sudacode/.config/mpv/scripts/immersion-tracker/data
csv_file=/truenas/sudacode/japanese/immersion_tracker.csv
session_file=/home/sudacode/.config/mpv/scripts/immersion-tracker/data/current_session.json
min_session_duration=30
save_interval=10
enable_debug_logging=no
backup_sessions=no
max_backup_files=10
use_title=yes
use_filename=no
custom_prefix=[Immersion]
max_title_length = 100
export_csv=yes
export_json=no
export_html=no
backup_csv=yes
show_session_start=yes
show_session_end=yes
show_progress_milestones=no
milestone_percentages=25507590

View File

@@ -0,0 +1,22 @@
start_tracking_key=ctrl+t
data_dir=/Users/sudacode/.config/mpv/scripts/immersion-tracker/data
csv_file=/Volumes/sudacode/japanese/immersion_tracker.csv
session_file=/Users/sudacode/.config/mpv/scripts/immersion-tracker/data/current_session.json
min_session_duration=30
save_interval=10
enable_debug_logging=no
backup_sessions=no
max_backup_files=10
use_title=yes
use_filename=no
custom_prefix=[Immersion]
max_title_length = 100
export_csv=yes
export_json=no
export_html=no
backup_csv=yes
show_session_start=yes
show_session_end=yes
show_progress_milestones=no
milestone_percentages=25507590

View File

@@ -0,0 +1,378 @@
# Language and display
# set language (for available options, see: https://github.com/Samillion/ModernZ/blob/main/docs/TRANSLATIONS.md)
language=en
# font for the OSC (default: mpv-osd-symbols or the one set in mpv.conf)
font=mpv-osd-symbols
# show mpv logo when idle
idlescreen=yes
# show OSC window top bar: "auto", "yes", or "no" (borderless/fullscreen)
window_top_bar=auto
# show OSC when windowed
showwindowed=yes
# show OSC when fullscreen
showfullscreen=yes
# show OSC when paused
showonpause=yes
# disable OSC hide timeout when paused
keeponpause=yes
# disable Santa hat in December
greenandgrumpy=no
# OSC behaviour and scaling
# time (in ms) before OSC hides if no mouse movement
hidetimeout=1500
# if seeking should reset the hidetimeout
seek_resets_hidetimeout=yes
# fade-out duration (in ms), set to 0 for no fade
fadeduration=200
# whether to enable fade-in effect
fadein=no
# minimum mouse movement (in pixels) required to show OSC
minmousemove=0
# show OSC only when hovering at the bottom
bottomhover=yes
# height of hover zone for bottomhover (in pixels)
bottomhover_zone=130
# show OSC when seeking
osc_on_seek=no
# show OSC on start of every file
osc_on_start=no
# pause video while seeking with mouse move (on button hold)
mouse_seek_pause=yes
# force show seekbar tooltip on mouse drag, even if not hovering seekbar
force_seek_tooltip=no
# scale osc with the video
vidscale=auto
# osc scale factor when windowed
scalewindowed=1.0
# osc scale factor when fullscreen
scalefullscreen=1.0
# Elements display
# show title in the OSC (above seekbar)
show_title=yes
# title above seekbar format: "${media-title}" or "${filename}"
title=${media-title}
# font size of the title text (above seekbar)
title_font_size=24
# chapter title font size
chapter_title_font_size=14
# show cached time information
cache_info=no
# show cache speed per second
cache_info_speed=no
# font size of the cache information
cache_info_font_size=12
# show chapter title alongside timestamp (below seekbar)
show_chapter_title=yes
# format for chapter display on seekbar hover (set to "no" to disable)
chapter_fmt=%s
# show total time instead of remaining time
timetotal=yes
# show timecodes with milliseconds
timems=no
# use the Unicode minus sign in remaining time
unicodeminus=no
# "dynamic" or "fixed". dynamic shows MM:SS when possible, fixed always shows HH:MM:SS
time_format=dynamic
# font size of the time display
time_font_size=16
# tooltips font size
tooltip_font_size=14
# Title bar settings
# show window title in borderless/fullscreen mode
window_title=no
# show window controls (close, minimize, maximize) in borderless/fullscreen
window_controls=yes
# same as title but for window_top_bar
windowcontrols_title=${media-title}
# Subtitle display settings
# raise subtitles above the OSC when shown
raise_subtitles=yes
# amount by which subtitles are raised when the OSC is shown (in pixels)
raise_subtitle_amount=125
# Buttons display and functionality
# show the jump backward and forward buttons
jump_buttons=yes
# change the jump amount in seconds
jump_amount=1
# change the jump amount in seconds when right-clicking jump buttons and shift-clicking chapter skip buttons
jump_more_amount=5
# show different icon when jump_amount is set to 5, 10, or 30
jump_icon_number=yes
# seek mode for jump buttons
jump_mode=relative
# enable continuous jumping when holding down seek buttons
jump_softrepeat=yes
# show the chapter skip backward and forward buttons
chapter_skip_buttons=no
# enable continuous skipping when holding down chapter skip buttons
chapter_softrepeat=yes
# show next/previous playlist track buttons
track_nextprev_buttons=yes
# show mute button and volume slider
volume_control=yes
# volume scale type: "linear" or "logarithmic"
volume_control_type=linear
# show playlist button: Left-click for simple playlist, Right-click for interactive playlist
playlist_button=yes
# hide playlist button when no playlist exists
hide_empty_playlist_button=yes
# gray out the playlist button when no playlist exists
gray_empty_playlist_button=yes
# show download button on web videos (requires yt-dlp and ffmpeg)
download_button=yes
# default download directory for videos (https://mpv.io/manual/master/#paths)
download_path=~~desktop/mpv
# show screenshot button
screenshot_button=no
# flag for screenshot button: "subtitles", "video", "window", "each-frame"
screenshot_flag=subtitles
# show window on top button
ontop_button=yes
# show loop button
loop_button=no
# show speed control button
speed_button=no
# speed change amount per click
speed_button_click=1
# speed change amount on scroll
speed_button_scroll=0.25
# show info button
info_button=yes
# show fullscreen toggle button
fullscreen_button=yes
# enable looping by right-clicking pause
loop_in_pause=yes
# force buttons to always be active. can add: playlist_prev,playlist_next
buttons_always_active=none
# icon size for the play/pause button
playpause_size=28
# icon size for the middle buttons
midbuttons_size=24
# icon size for the side buttons
sidebuttons_size=24
# show zoom controls in image viewer mode
zoom_control=yes
# maximum zoom in value
zoom_in_max=4
# minimum zoom out value
zoom_out_min=-1
# Colors and style
# accent color of the OSC and title bar
osc_color=#181926
# color of the title in borderless/fullscreen mode
window_title_color=#A5ADCB
# color of the window controls (close, minimize, maximize) in borderless/fullscreen mode
window_controls_color=#A5ADCB
# color of close window control on hover
windowcontrols_close_hover=#ED8796
# color of maximize window controls on hover
windowcontrols_max_hover=#EED49F
# color of minimize window controls on hover
windowcontrols_min_hover=#A6DA95
# color of the title (above seekbar)
title_color=#CAD3F5
# color of the cache information
cache_info_color=#CAD3F5
# color of the seekbar progress and handle
seekbarfg_color=#C6A0F6
# color of the remaining seekbar
seekbarbg_color=#B7BDF8
# color of the cache ranges on the seekbar
seekbar_cache_color=#A5ADCB
# match volume bar color with seekbar color (ignores side_buttons_color)
volumebar_match_seek_color=no
# color of the timestamps (below seekbar)
time_color=#CAD3F5
# color of the chapter title next to timestamp (below seekbar)
chapter_title_color=#A5ADCB
# color of the side buttons (audio, subtitles, playlist, etc.)
side_buttons_color=#A5ADCB
# color of the middle buttons (skip, jump, chapter, etc.)
middle_buttons_color=#A5ADCB
# color of the play/pause button
playpause_color=#A5ADCB
# color of the element when held down (pressed)
held_element_color=#999999
# color of a hovered button when hover_effect includes "color"
hover_effect_color=#C6A0F6
# color of the border for thumbnails (with thumbfast)
thumbnail_border_color=#181926
# color of the border outline for thumbnails
thumbnail_border_outline=#363A4F
# alpha of the OSC background box
fade_alpha=130
# blur strength for the OSC alpha fade. caution: high values can take a lot of CPU time to render
fade_blur_strength=100
# alpha of the window title bar (0 to disable)
window_fade_alpha=100
# blur strength for the window title bar. caution: high values can take a lot of CPU time to render
window_fade_blur_strength=100
# width of the thumbnail border (for thumbfast)
thumbnail_border=3
# rounded corner radius for thumbnail border (0 to disable)
thumbnail_border_radius=3
# Button hover effects
# active button hover effects: "glow", "size", "color"; can use multiple separated by commas
hover_effect=size,glow,color
# relative size of a hovered button if "size" effect is active
hover_button_size=115
# glow intensity when "glow" hover effect is active
button_glow_amount=5
# apply hover size effect to slider handle
hover_effect_for_sliders=yes
# Tooltips and hints
# enable tooltips for disabled buttons and elements
tooltips_for_disabled_elements=yes
# enable text hints for info, loop, ontop, and screenshot buttons
tooltip_hints=yes
# Progress bar settings
# size ratio of the seekbar handle (range: 0 ~ 1)
seek_handle_size=0.8
# show seek range overlay
seekrange=yes
# transparency of the seek range
seekrangealpha=150
# update chapter markers on the seekbar when duration changes
livemarkers=yes
# use keyframes when dragging the seekbar
seekbarkeyframes=no
# top chapter nibbles above seekbar
nibbles_top=yes
# bottom chapter nibbles below seekbar
nibbles_bottom=yes
# chapter nibble style. "triangle", "bar" or "single-bar"
nibbles_style=triangle
# automatically set keyframes for the seekbar based on video length
automatickeyframemode=yes
# videos longer than this (in seconds) will have keyframes on the seekbar
automatickeyframelimit=600
# always show a small progress line at the bottom of the screen
persistentprogress=no
# height of the persistent progress bar
persistentprogressheight=17
# show buffer status on web videos in the persistent progress line
persistentbuffer=no
# Miscellaneous settings
# only used at init to set visibility_mode(...)
visibility=auto
# visibility modes to cycle through, modes are separated by _
visibility_modes=never_auto_always
# minimum interval between OSC redraws (in seconds)
tick_delay=0.03
# use display FPS as the minimum redraw interval
tick_delay_follow_display_fps=no
# Elements Position
# Useful when adjusting font size or type
# title height position above seekbar
title_height=96
# title height position if a chapter title is below it
title_with_chapter_height=108
# chapter title height position above seekbar
chapter_title_height=91
# time codes height position
time_codes_height=35
# time codes height position with portrait window
time_codes_centered_height=57
# tooltip height position offset
tooltip_height_offset=2
# if tooltip contains many characters, it is moved to the left by offset
tooltip_left_offset=5
# portrait window width trigger to move some elements
portrait_window_trigger=1000
# hide volume bar trigger window width
hide_volume_bar_trigger=1150
# osc height offset if title above seekbar is disabled
notitle_osc_h_offset=25
# osc height offset if chapter title is disabled or doesn't exist
nochapter_osc_h_offset=10
# seek hover timecodes tooltip height position offset
seek_hover_tooltip_h_offset=0
# osc height without offsets
osc_height=132
## Mouse commands
## details: https://github.com/Samillion/ModernZ#mouse-commands-user-options
# title above seekbar mouse actions
title_mbtn_left_command=script-binding stats/display-page-5
title_mbtn_mid_command=show-text ${filename}
title_mbtn_right_command=show-text ${path}
# playlist button mouse actions
playlist_mbtn_left_command=script-binding select/select-playlist; script-message-to modernz osc-hide
playlist_mbtn_right_command=show-text ${playlist} 3000
# volume mouse actions
vol_ctrl_mbtn_left_command=no-osd cycle mute
vol_ctrl_mbtn_right_command=script-binding select/select-audio-device; script-message-to modernz osc-hide
vol_ctrl_wheel_down_command=no-osd add volume -5
vol_ctrl_wheel_up_command=no-osd add volume 5
# audio button mouse actions
audio_track_mbtn_left_command=script-binding select/select-aid; script-message-to modernz osc-hide
audio_track_mbtn_mid_command=cycle audio down
audio_track_mbtn_right_command=cycle audio
audio_track_wheel_down_command=cycle audio
audio_track_wheel_up_command=cycle audio down
# subtitle button mouse actions
sub_track_mbtn_left_command=script-binding select/select-sid; script-message-to modernz osc-hide
sub_track_mbtn_mid_command=cycle sub down
sub_track_mbtn_right_command=cycle sub
sub_track_wheel_down_command=cycle sub
sub_track_wheel_up_command=cycle sub down
# chapter skip buttons mouse actions
chapter_prev_mbtn_left_command=add chapter -1
chapter_prev_mbtn_mid_command=show-text ${chapter-list} 3000
chapter_prev_mbtn_right_command=script-binding select/select-chapter; script-message-to modernz osc-hide
chapter_next_mbtn_left_command=add chapter 1
chapter_next_mbtn_mid_command=show-text ${chapter-list} 3000
chapter_next_mbtn_right_command=script-binding select/select-chapter; script-message-to modernz osc-hide
# chapter title (below seekbar) mouse actions
chapter_title_mbtn_left_command=script-binding select/select-chapter; script-message-to modernz osc-hide
chapter_title_mbtn_right_command=show-text ${chapter-list} 3000
# playlist skip buttons mouse actions
playlist_prev_mbtn_left_command=playlist-prev
playlist_prev_mbtn_mid_command=show-text ${playlist} 3000
playlist_prev_mbtn_right_command=script-binding select/select-playlist; script-message-to modernz osc-hide
playlist_next_mbtn_left_command=playlist-next
playlist_next_mbtn_mid_command=show-text ${playlist} 3000
playlist_next_mbtn_right_command=script-binding select/select-playlist; script-message-to modernz osc-hide
# fullscreen button mouse actions
fullscreen_mbtn_left_command=cycle fullscreen
fullscreen_mbtn_right_command=cycle window-maximized
# info button mouse actions
info_mbtn_left_command=script-binding stats/display-page-1-toggle

View File

@@ -0,0 +1,35 @@
add_to_queue=ctrl+a
default_save_method=unwatched
download_current_video=ctrl+d
download_selected_video=ctrl+D
move_cursor_down=ctrl+j
move_cursor_up=ctrl+k
load_queue=ctrl+l
move_video=ctrl+m
play_next_in_queue=ctrl+n
open_video_in_browser=ctrl+o
open_channel_in_browser=ctrl+O
play_previous_in_queue=ctrl+p
print_current_video=ctrl+P
print_queue=ctrl+q
save_queue=ctrl+s
save_full_queue=ctrl+S
remove_from_queue=ctrl+x
play_selected_video=ctrl+ENTER
browser=zen-browser
clipboard_command=wl-paste
cursor_icon=➤
display_limit=10
download_directory=~/videos/YouTube
download_quality=1080p
downloader=curl
font_name=JetBrainsMono NF
font_size=12
marked_icon=⇅
menu_timeout=5
show_errors=yes
ytdlp_file_format=mp4
ytdlp_output_template=%(uploader)s/%(title)s.%(ext)s
use_history_db=yes
backend_host=http://localhost
backend_port=42069

View File

@@ -0,0 +1,35 @@
add_to_queue=ctrl+a
default_save_method=unwatched
download_current_video=ctrl+d
download_selected_video=ctrl+D
move_cursor_down=ctrl+j
move_cursor_up=ctrl+k
load_queue=ctrl+l
move_video=ctrl+m
play_next_in_queue=ctrl+n
open_video_in_browser=ctrl+o
open_channel_in_browser=ctrl+O
play_previous_in_queue=ctrl+p
print_current_video=ctrl+P
print_queue=ctrl+q
save_queue=ctrl+s
save_full_queue=ctrl+S
remove_from_queue=ctrl+x
play_selected_video=ctrl+ENTER
browser=zen-browser
clipboard_command=pbpaste
cursor_icon=➤
display_limit=10
download_directory=~/videos/YouTube
download_quality=1080p
downloader=curl
font_name=JetBrainsMono NF
font_size=12
marked_icon=⇅
menu_timeout=5
show_errors=yes
ytdlp_file_format=mp4
ytdlp_output_template=%(uploader)s/%(title)s.%(ext)s
use_history_db=yes
backend_host=http://localhost
backend_port=42069

View File

@@ -0,0 +1,34 @@
# enable automatic reload on timeout
# when paused-for-cache event fired, we will wait
# paused_for_cache_timer_timeout sedonds and then reload the video
paused_for_cache_timer_enabled=yes
# checking paused_for_cache property interval in seconds,
# can not be less than 0.05 (50 ms)
paused_for_cache_timer_interval=1
# time in seconds to wait until reload
paused_for_cache_timer_timeout=10
# enable automatic reload based on demuxer cache
# if demuxer-cache-time property didn't change in demuxer_cache_timer_timeout
# time interval, the video will be reloaded as soon as demuxer cache depleated
demuxer_cache_timer_enabled=yes
# checking demuxer-cache-time property interval in seconds,
# can not be less than 0.05 (50 ms)
demuxer_cache_timer_interval=2
# if demuxer cache didn't receive any data during demuxer_cache_timer_timeout
# we decide that it has no progress and will reload the stream when
# paused_for_cache event happens
demuxer_cache_timer_timeout=20
# when the end-of-file is reached, reload the stream to check
# if there is more content available.
reload_eof_enabled=no
# keybinding to reload stream from current time position
# you can disable keybinding by setting it to empty value
# reload_key_binding=
reload_key_binding=Ctrl+r

View File

@@ -0,0 +1 @@
plot_tonemapping_lut=yes

View File

@@ -0,0 +1,331 @@
###
### Main mpvacious configuration file.
### Save this file to ~/.config/mpv/script-opts/subs2srs.conf
###
##
## General settings
##
# Anki deck for new cards. Subdecks are supported.
deck_name=Minecraft
# Model names are listed in `Tools -> Manage note types` menu in Anki.
# If you don't have a model for Japanese, get it from
# https://tatsumoto.neocities.org/blog/setting-up-anki.html#import-an-example-mining-deck
model_name=Lapis
# Field names as they appear in the selected note type.
# If you set `audio_field` or `image_field` empty,
# the corresponding media file will not be created.
audio_field=SentenceAudio
image_field=Picture
sentence_field=Expression
secondary_field=SelectionText
# The tag(s) added to new notes. Spaces separate multiple tags.
# Leave nothing after `=` to disable tagging completely.
# The following substitutions are supported:
# %n - the name of the video
# %t - timestamp
# %d - episode number (if none, returns nothing)
# %e - SUBS2SRS_TAGS environment variable (if you have it set)
# note_tag=subs2srs
note_tag=%n-E%d %t
#note_tag=
# Size and name of the font used in the menu
menu_font_size=24
menu_font_name=Noto Serif CJK JP
# AnkiConnect server address
# The default address for a server on the same device is http://127.0.0.1:8765.
# If Anki is running and AnkiConnect is installed, opening this URL should
# open a page showing the current version of AnkiConnect.
# Change this if you have changed webBindAddress in AnkiConnect's settings.
ankiconnect_url=127.0.0.1:8765
##
## Toggleables.
## Possible values: `yes` or `no`.
# Use FFmpeg encoder instead of mpv encoder
# If mpvacious encounters problems creating audio and images for Anki cards,
# setting this to `yes` should fix them.
#
# You need to install ffmpeg and add it to the PATH first.
# https://wiki.archlinux.org/title/FFmpeg
# https://www.ffmpeg.org/download.html
#
# FFmpeg encoder is unable to create audio and images from remote content (like YouTube videos).
use_ffmpeg=yes
# Automatically create the deck for new cards (see deck_name option)
create_deck=no
# Allow making notes with the same sentence field.
allow_duplicates=no
# When mpv starts, automatically copy subs to the clipboard as they appear on screen.
# This option can be also toggled in the addon's OSD menu.
autoclip=no
# Possible options:
# "disabled" - autocopy is disabled
# "clipboard" - copy to the system clipboard (e.g. uses xclip)
# "goldendict" - send the subtitle string to goldendict (goldendict-ng).
# "custom_command" - run any custom command specified in `autoclip_custom_args`.
autoclip_method=custom_command
# Command to run when autoclip is enabled and set to "custom_command".
# If empty, nothing will be done.
# If set, calls the external program.
# The following substitutions are supported:
# %MPV_PRIMARY% - primary subtitle line
# %MPV_SECONDARY% - secondary subtitle line
autoclip_custom_args=wl-copy %MPV_PRIMARY%
# Remove all spaces from the primary subtitle text.
# Set this to "yes" for languages without spaces like Japanese.
# However, if mpvacious detects any latin characters in the string, spaces will not be removed.
nuke_spaces=yes
# if set to `yes`, the volume of the outputted audio file
# depends on the volume of the player at the time of export
tie_volumes=no
# This is used when selecting cards in Anki to update, it wont let you
# overwrite more than the value specified below
# Just remember that having multiple cards with the same sentence
# and the same audio recording is usually bad practice.
card_overwrite_safeguard = 1
# Remove text in parentheses and leading/trailing spaces or
# newlines that may interfere with Rikaitan before copying
# subtitles to the clipboard
clipboard_trim_enabled=yes
# Add media to fields before or after existing data
append_media=yes
# Remove text in brackets before substituting %n into tag
tag_nuke_brackets=yes
# Remove text in parentheses before substituting %n into tag
tag_nuke_parentheses=no
# Remove the episode number before substituting %n into tag
tag_del_episode_num=yes
# Remove everything after the episode number before substituting %n into tag
# Does nothing if the previous option tag_del_episode_num is disabled.
tag_del_after_episode_num=yes
# Convert filename to lowercase for tagging.
tag_filename_lowercase=no
# Lets you disable anki browser manipulation by mpvacious.
disable_gui_browse=no
# Play audio clip automatically in background
# after note creation (or note update) to ensure that the audio is correctly cut.
preview_audio=no
# When selecting subtitle lines, print them on the screen.
show_selected_text=yes
# For convenience, read config file from disk before a card is made.
# Useful if you change your config often since you won't have to restart mpv every time,
# but reading from disk takes some time.
reload_config_before_card_creation=yes
##
## Image settings
##
# Snapshot format.
# Do not switch to `jpg` unless your computer doesn't support `webp` or `avif`.
snapshot_format=avif
# snapshot_format=webp
#snapshot_format=jpg
# Quality of produced image files. 0 = lowest, 100=highest.
snapshot_quality=88
# Image dimensions
# If either (but not both) of the width or height parameters is -2,
# the value will be calculated preserving the aspect-ratio.
snapshot_width=-2
snapshot_height=400
# Screenshot (yes, no)
# Usually not required.
# When making Anki cards, create a screenshot (by calling 'screenshot-to-file') instead of a snapshot.
# If set to yes, image dimensions and quality cannot be controlled due to mpv limitations.
# 'snapshot_format' is still respected.
# When using this, a custom sync server is recommended, e.g. https://github.com/ankicommunity/anki-sync-server
screenshot=yes
# The exact image template used when exporting to Anki's image field.
# Adding data-editor-shrink="true" makes the image smaller by default within the Anki viewer
# on versions 2.1.53+ (equivalent of double-clicking on the image).
# You likely would not want to change this unless you know what you are doing.
image_template=<img alt="snapshot" src="%s">
#image_template=<img alt="snapshot" data-editor-shrink="true" src="%s">
# Similar to image_template but with audio.
# Normally, the user doesn't need to change this setting,
# but it may be needed for audio files to be playable on AnkiWeb.
audio_template=[sound:%s]
#audio_template=<audio controls="" src="%s"></audio>
##
## Animated snapshots
## Animated snapshots will capture the video from the start to the end times selected when using mpvacious.
##
# If enabled, generates animated snapshots (something like GIFs) instead of static snapshots.
animated_snapshot_enabled=yes
# Animated snapshot format. Like "snapshot_format" but for animated images. Can be either avif or webp.
animated_snapshot_format=avif
# animated_snapshot_format=webp
# Number of frame per seconds, a value between 0 and 30 (30 included)
# Higher values will increase both quality and file size, lower values will do the opposite
animated_snapshot_fps=24
# Animated snapshot dimensions
# If either (but not both) of the width or height parameters is -2,
# the value will be calculated preserving the aspect-ratio.
animated_snapshot_width=-2
animated_snapshot_height=400
# Quality of the produced animation, 0 = lowest, 100 = highest
animated_snapshot_quality=69
##
## Audio settings
##
# Audio format.
# Opus is the recommended format.
audio_format=opus
# audio_format=mp3
# Container for opus files.
# It may be required to use a different container for Opus.
# This is the case on certain computers or devices
# which are running proprietary operating systems, e.g. AnkiMobile. Using them is discouraged.
# ・ Ogg/Opus play everywhere except AnkiWeb in Safari and AnkiMobile.
# ・ M4A (iOS 17.2 and probably even earlier) and WEBM (since iOS 17.4) play everywhere.
# ・ Opus in CAF can be used with older iOS. CAF plays only on Anki Desktop, Safari and AnkiMobile.
# ・ (iOS Lockdown Mode disables Opus support completely,
# though you may try to add an exception for AnkiMobile.)
# opus_container=ogg
#opus_container=opus
opus_container=m4a
# opus_container=webm
#opus_container=caf
# Sane values are 16k-32k for opus, 64k-128k for mp3.
audio_bitrate=32k
# Set a pad to the dialog timings. 0.5 = half a second.
# Pads are never applied to manually set timings.
audio_padding=0.0
#audio_padding=0.5
##
## Forvo support (Rikaitan users only)
##
# yes - fetch audio from Forvo if Rikaitan couldn't find the audio (default)
# always - always fetch audio from Forvo and replace the audio added by Rikaitan
# no - never use Forvo
use_forvo=yes
# Vocab field should be equal to {expression} field in Rikaitan
vocab_field=Expression
# Vocab Audio field should be equal to {audio} field in Rikaitan
vocab_audio_field=ExpressionAudio
##
## Misc info
## Various context information that can be written on your cards in a specified field.
##
# yes to enable or no to disable.
miscinfo_enable=yes
# Field name
miscinfo_field=ExtraInfo
# Format string used to fill the misc info field.
# It supports the same substitutions as `note_tag`. HTML is supported.
miscinfo_format=%n EP%d (%t)
#miscinfo_format=From <b>mpvacious</b> %n at %t.
##
## Secondary subtitles
## Mpvacious can try automatically loading secondary subtitles that will appear at the top.
## For example, you may want to load English subs alongside Japanese subs.
##
## Secondary subtitles should be present in the container.
## But if you manually set secondary sid from the command line, mpvacious won't change it.
##
# Load secondary subtitle track automatically when a file is opened.
secondary_sub_auto_load=yes
# Language of secondary subs. This is your native language or a language you know well.
# If you leave this parameter empty, secondary subs will NOT be automatically loaded.
secondary_sub_lang=eng,en
#secondary_sub_lang=
# Hover area.
# Proportion of the top part of the mpv window where the secondary subtitles are visible when hovered over.
# Possible values: from 0.0 to 1.0
secondary_sub_area=0.15
# Visibility state
# Can be set to: 'auto', 'never', 'always'.
# If set to 'never' or 'always', secondary_sub_area has no effect.
# If set to 'auto', visibility behaves according to the value of secondary_sub_area.
# Default binding to cycle this value: Ctrl+v.
secondary_sub_visibility=auto
# Perform two-pass loudness normalization.
# Parameter explanation can be found e.g. at:
# https://auphonic.com/blog/2013/01/07/loudness-targets-mobile-audio-podcasts-radio-tv/
# https://auphonic.com/blog/2019/08/19/dynamic-range-processing/
# MAKE SURE TO REMOVE loudnorm FROM CUSTOM ARGS BEFORE ENABLING.
loudnorm=no
loudnorm_target=-16
loudnorm_range=11
loudnorm_peak=-1.5
##
## Custom audio encoding arguments
## These arguments are added to the command line.
## `mpv` and `ffmpeg` accept slightly different parameters.
## Feel free to experiment for yourself, but be careful or media creation might stop working.
##
# loudnorm IN CUSTOM ARGS IS LEFT FOR BACKWARD COMPATIBILITY.
# MAKE SURE TO REMOVE ALL MENTIONS OF loudnorm FROM CUSTOM ARGS
# (E.G. SET TO EMPTY STRINGS) BEFORE ENABLING TWO-PASS loudnorm.
# ENABLING loudnorm BOTH THROUGH THE SWITCH AND THROUGH CUSTOM ARGS
# CAN LEAD TO UNPREDICTABLE RESULTS.
# Ffmpeg
ffmpeg_audio_args=-af loudnorm=I=-16:TP=-1.5:LRA=11:dual_mono=true
#ffmpeg_audio_args=
#ffmpeg_audio_args=-af silenceremove=1:0:-50dB
# mpv
# mpv accepts each filter as a separate argument, e.g. --af-append=1 --af-append=2
mpv_audio_args=--af-append=loudnorm=I=-16:TP=-1.5:LRA=11:dual_mono=true
#mpv_audio_args=
#mpv_audio_args=--af-append=silenceremove=1:0:-50dB

View File

@@ -0,0 +1,30 @@
# Socket path (leave empty for auto)
socket=
# Thumbnail path (leave empty for auto)
thumbnail=
# Maximum thumbnail size in pixels (scaled down to fit)
# Values are scaled when hidpi is enabled
max_height=400
max_width=400
# Overlay id
overlay_id=42
# Spawn thumbnailer on file load for faster initial thumbnails
spawn_first=yes
# Enable on network playback
network=yes
# Enable on audio playback
audio=no
# Enable hardware decoding
hwdec=yes
# Windows only: use native Windows API to write to pipe (requires LuaJIT)
direct_io=no
mpv_path=mpv

View File

@@ -0,0 +1,91 @@
# KEY BINDINGS
append_binding=ctrl+SPACE
# invoke or dismiss the quality menu
toggle_menu_binding=ctrl+u
# move the menu cursor up
up_binding=ctrl+k
# move the menu cursor down
down_binding=ctrl+j
# select menu entry
select_binding=ctrl+ENTER
# auto fetch recommended videos when opening a url
fetch_on_start=no
# auto load and add the "upnext" video to the playlist
auto_add=no
# formatting / cursors
cursor_selected=●
cursor_unselected=○
cursor_appended=▷
cursor_appended_selected=▶
# font size scales by window, if false requires larger font and padding sizes
scale_playlist_by_window=yes
# playlist ass style overrides inside curly brackets, \keyvalue is one field, extra \ for escape in lua
# example {\\fnUbuntu\\fs10\\b0\\bord1} equals: font=Ubuntu, size=10, bold=no, border=1
# read http://docs.aegisub.org/3.2/ASS_Tags/ for reference of tags
# undeclared tags will use default osd settings
# these styles will be used for the whole playlist. More specific styling will need to be hacked in
#
# (a monospaced font is recommended but not required)
style_ass_tags={\\fnJetBrainsMono Nerd Font\\fs12}
# paddings for top left corner
text_padding_x=5
text_padding_y=5
# Screen dim when menu is open 0.0 - 1.0 (0 is no dim, 1 is black)
curtain_opacity=0.7
# how many seconds until the quality menu times out
menu_timeout=10
# base url for loading new urls, %s will be replaced with video id
youtube_url=https://www.youtube.com/watch?v=%s
# Fallback Invidious instance. Used if "upnext" could not be retrieved from the normal youtube website
# See https://api.invidious.io/ for alternatives
invidious_instance=https://inv.tux.pizza
# Keep the width of the window the same when the next video is played
restore_window_width=no
# On Windows wget.exe may not be able to check SSL certificates for HTTPS, so you can disable it here
check_certificate=yes
# Use a cookies file
# Same as youtube-dl --cookies or wget --load-cookies
# If you don't set this, the script may create a cookie file for you
# For example "C:\\Users\\Username\\cookies.txt"
# Or "C:/Users/Username/cookies.txt"
#cookies=cookies.txt
# When a video is selected from the menu, the new video can be appended to the playlist
# or the playlist can be cleared and replaced with only the selected video.
# If yes, the video will be appended to the playlist. If no, the playlist will be cleared.
keep_playlist_on_select=yes
# What should happen if a video recommendation in uosc menu is clicked? Options are:
# submenu --> show a submenu with play/upnext/append option
# append --> append the video to the playlist
# insert --> play the video after the current video
# play --> append the video to the playlist and play it
# replace --> play the video and clear the playlist
uosc_entry_action=submenu
# Should the uosc menu stay open after clicking a video recommendation?
uosc_keep_menu_open=no
# Don't play/append videos that are shorter than this time. Format is "HH:MM:SS" or "MM:SS"
#skip_shorter_than=00:30
# Don't play/append videos that are longer than this time. Format is "HH:MM:SS" or "MM:SS"
#skip_longer_than=07:00
# Also don't show the videos in the menu that are too short or too long
#hide_skipped_videos=yes

View File

@@ -0,0 +1 @@
temp=/tmp/ytdl-preload

View File

@@ -0,0 +1 @@
../../submodules/mpv-anilist-updater/anilistUpdater/anilistUpdater.py

View File

@@ -0,0 +1 @@
../../submodules/mpv-anilist-updater/anilistUpdater/main.lua

View File

@@ -0,0 +1 @@
../submodules/animecards/animecards

View File

@@ -0,0 +1 @@
../submodules/autosubsync-mpv

View File

@@ -0,0 +1 @@
../submodules/immersion-tracker

View File

@@ -0,0 +1,388 @@
// Go to https://jimaku.cc/login and create a new account.
// Then go to https://jimaku.cc/account and click the `Generate` button to create a new API key
// Click the `Copy` button and paste it below
var API_KEY = "";
// Configuration options
var CONFIG = {
// Filter the response to only have the specified episode
prompt_episode: true,
// Subtitle suffix (e.g., ".JA" for Japanese subtitles)
subtitle_suffix: ".JA",
// Preferred subtitle format (order matters, first is most preferred)
preferred_formats: ["ass", "srt", "vtt"],
// Automatically load the subtitle after download
auto_load: true,
// Default subtitle delay in seconds (can be positive or negative)
default_delay: 0,
// Default subtitle font size
default_font_size: 16,
// Automatically rename the subtitle file after download
auto_rename: true,
// Automatically run autosubsync-mpv after downloading the subtitle
run_auto_subsync: true
};
// Keybindings
// var MANUAL_SEARCH_KEY = "g";
var FILENAME_AUTO_SEARCH_KEY = "ctrl+J";
var PARENT_FOLDER_AUTO_SEARCH_KEY = "n";
function api(url, extraArgs) {
var baseArgs = [
"curl",
"-s",
"--url",
url,
"--header",
"Authorization: " + API_KEY
];
var args = Array.prototype.concat.apply(baseArgs, extraArgs);
var res = mp.command_native({
name: "subprocess",
playback_only: false,
capture_stdout: true,
capture_stderr: true,
args: args
});
if (res.stdout) return JSON.parse(res.stdout);
}
function downloadSub(sub) {
return api(sub.url, ["--output", sub.name]);
}
function showMessage(message, persist) {
var ass_start = mp.get_property_osd("osd-ass-cc/0");
var ass_stop = mp.get_property_osd("osd-ass-cc/1");
mp.osd_message(
ass_start + "{\\fs16}" + message + ass_stop,
persist ? 999 : 2
);
}
// The timeout is neccessary due to a weird bug in mpv
function inputGet(args) {
mp.input.terminate();
setTimeout(function () {
mp.input.get(args);
}, 1);
}
// The timeout is neccessary due to a weird bug in mpv
function inputSelect(args) {
mp.input.terminate();
setTimeout(function () {
mp.input.select(args);
}, 1);
}
// Taken from mpv-subversive
// https://github.com/nairyosangha/mpv-subversive/blob/master/backend/backend.lua#L146
function sanitize(text) {
var subPatterns = [
/\.[a-zA-Z]+$/, // extension
/\./g,
/-/g,
/_/g,
/\[[^\]]+\]/g, // [] bracket
/\([^\)]+\)/g, // () bracket
/720[pP]/g,
/480[pP]/g,
/1080[pP]/g,
/[xX]26[45]/g,
/[bB]lu[-]?[rR]ay/g,
/^[\s]*/,
/[\s]*$/,
/1920x1080/g,
/1920X1080/g,
/Hi10P/g,
/FLAC/g,
/AAC/g
];
var result = text;
subPatterns.forEach(function (subPattern) {
var newResult = result.replace(subPattern, " ");
if (newResult.length > 0) {
result = newResult;
}
});
return result;
}
// Adapted from mpv-subversive
// https://github.com/nairyosangha/mpv-subversive/blob/master/backend/backend.lua#L164
function extractTitle(text) {
var matchers = [
{ regex: /^([\w\s\d]+)[Ss]\d+[Ee]?\d+/, group: 1 },
{ regex: /^([\w\s\d]+)-[\s]*\d+[\s]*[^\w]*$/, group: 1 },
{ regex: /^([\w\s\d]+)[Ee]?[Pp]?[\s]+\d+$/, group: 1 },
{ regex: /^([\w\s\d]+)[\s]\d+.*$/, group: 1 },
{ regex: /^\d+[\s]*(.+)$/, group: 1 }
];
for (var i = 0; i < matchers.length; i++) {
var matcher = matchers[i];
var match = text.match(matcher.regex);
if (match) {
return match[matcher.group].trim();
}
}
return text;
}
function getNames(results) {
return results.map(function (item) {
return item.name;
});
}
function runAutoSubSyncMPV() {
try {
mp.command_native(["script-binding", "autosubsync-menu"]);
} catch (e) {
showMessage("autosubsync-mpv not installed");
return;
}
}
function selectSub(selectedSub) {
showMessage("Downloading: " + selectedSub.name);
try {
downloadSub(selectedSub);
// Get current video filename without extension
var videoPath = mp.get_property("path");
if (!videoPath) {
throw new Error("No video file is currently playing");
}
var videoName = videoPath.substring(0, videoPath.lastIndexOf("."));
// Get subtitle extension
var subExt = selectedSub.name.substring(selectedSub.name.lastIndexOf("."));
var newSubName = selectedSub.name;
if (CONFIG.auto_rename) {
// Create new subtitle filename
newSubName = videoName + CONFIG.subtitle_suffix + subExt;
// Rename the downloaded subtitle file
var renameResult = mp.command_native({
name: "subprocess",
playback_only: false,
args: ["mv", selectedSub.name, newSubName]
});
if (renameResult.error) {
throw new Error(
"Failed to rename subtitle file: " + renameResult.error
);
}
showMessage(newSubName + " downloaded and renamed");
} else {
showMessage(newSubName + " downloaded");
}
if (CONFIG.auto_load) {
mp.commandv("sub_add", newSubName);
showMessage(newSubName + " added");
// Apply subtitle settings if configured
if (CONFIG.default_delay !== 0) {
mp.commandv("sub_delay", CONFIG.default_delay);
}
if (CONFIG.default_font_size !== 16) {
mp.commandv("sub_font_size", CONFIG.default_font_size);
}
}
if (CONFIG.run_auto_subsync) {
runAutoSubSyncMPV();
}
mp.set_property("pause", "no");
} catch (error) {
showMessage("Error: " + error.message, true);
mp.set_property("pause", "no");
}
}
function sortByPreferredFormat(files) {
return files.sort(function (a, b) {
var extA = a.name.substring(a.name.lastIndexOf(".") + 1).toLowerCase();
var extB = b.name.substring(b.name.lastIndexOf(".") + 1).toLowerCase();
var indexA = CONFIG.preferred_formats.indexOf(extA);
var indexB = CONFIG.preferred_formats.indexOf(extB);
if (indexA === -1) return 1;
if (indexB === -1) return -1;
return indexA - indexB;
});
}
function selectEpisode(anime, episode) {
mp.input.terminate();
var episodeResults;
if (episode) {
showMessage("Fetching subs for: " + anime.name + " episode " + episode);
episodeResults = api(
"https://jimaku.cc/api/entries/" + anime.id + "/files?episode=" + episode
);
} else {
showMessage("Fetching all subs for: " + anime.name);
episodeResults = api(
"https://jimaku.cc/api/entries/" + anime.id + "/files"
);
}
if (episodeResults.error) {
showMessage("Error: " + animeResults.error);
return;
}
if (episodeResults.length === 0) {
showMessage("No results found");
return;
}
// Sort results by preferred format
episodeResults = sortByPreferredFormat(episodeResults);
if (episodeResults.length === 1) {
var selectedEpisode = episodeResults[0];
selectSub(selectedEpisode);
return;
}
var items = getNames(episodeResults);
inputSelect({
prompt: "Select episode: ",
items: items,
submit: function (id) {
var selectedEpisode = episodeResults[id - 1];
selectSub(selectedEpisode);
}
});
}
function onAnimeSelected(anime) {
if (CONFIG.prompt_episode) {
inputGet({
prompt: "Episode (leave blank for all): ",
submit: function (episode) {
selectEpisode(anime, episode);
}
});
} else {
selectEpisode(anime);
}
}
function search(searchTerm, isAuto) {
mp.input.terminate();
showMessage('Searching for: "' + searchTerm + '"');
var animeResults = api(
encodeURI(
"https://jimaku.cc/api/entries/search?anime=true&query=" + searchTerm
)
);
if (animeResults.error) {
showMessage("Error: " + animeResults.error);
return;
}
if (animeResults.length === 0) {
showMessage("No results found");
if (isAuto) {
manualSearch(searchTerm);
}
return;
}
if (animeResults.length === 1) {
var selectedAnime = animeResults[0];
onAnimeSelected(selectedAnime);
return;
}
var items = getNames(animeResults);
inputSelect({
prompt: "Select anime: ",
items: items,
submit: function (id) {
var selectedAnime = animeResults[id - 1];
showMessage(selectedAnime.name, true);
onAnimeSelected(selectedAnime);
}
});
}
function manualSearch(defaultText) {
inputGet({
prompt: "Search term: ",
submit: search,
default_text: defaultText
});
mp.set_property("pause", "yes");
showMessage("Manual Jimaku Search", true);
}
function autoSearch() {
var filename = mp.get_property("filename");
var sanitizedFilename = sanitize(filename);
var currentAnime = extractTitle(sanitizedFilename);
mp.set_property("pause", "yes");
search(currentAnime, true);
}
function autoSearchParentFolder() {
var path = mp.get_property("stream-open-filename");
var pathSplit = path.split(path.indexOf("/") >= 0 ? "/" : "\\");
var filename =
pathSplit.length === 1 ? pathSplit[0] : pathSplit[pathSplit.length - 2];
var sanitizedFilename = sanitize(filename);
var currentAnime = extractTitle(sanitizedFilename);
mp.set_property("pause", "yes");
search(currentAnime, true);
}
// mp.add_key_binding(MANUAL_SEARCH_KEY, "jimaku-manual-search", manualSearch);
mp.add_key_binding(
FILENAME_AUTO_SEARCH_KEY,
"jimaku-filename-auto-search",
autoSearch
);
mp.add_key_binding(
PARENT_FOLDER_AUTO_SEARCH_KEY,
"jimaku-parent-folder-auto-search",
autoSearchParentFolder
);

View File

@@ -0,0 +1 @@
../submodules/ModernZ/modernz.lua

View File

@@ -0,0 +1 @@
../submodules/mpv-youtube-queue/mpv-youtube-queue.lua

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,416 @@
-- reload.lua
--
-- When an online video is stuck buffering or got very slow CDN
-- source, restarting often helps. This script provides automatic
-- reloading of videos that doesn't have buffering progress for some
-- time while keeping the current time position. It also adds `Ctrl+r`
-- keybinding to reload video manually.
--
-- SETTINGS
--
-- To override default setting put the `lua-settings/reload.conf` file in
-- mpv user folder, on linux it is `~/.config/mpv`. NOTE: config file
-- name should match the name of the script.
--
-- Default `reload.conf` settings:
--
-- ```
-- # enable automatic reload on timeout
-- # when paused-for-cache event fired, we will wait
-- # paused_for_cache_timer_timeout sedonds and then reload the video
-- paused_for_cache_timer_enabled=yes
--
-- # checking paused_for_cache property interval in seconds,
-- # can not be less than 0.05 (50 ms)
-- paused_for_cache_timer_interval=1
--
-- # time in seconds to wait until reload
-- paused_for_cache_timer_timeout=10
--
-- # enable automatic reload based on demuxer cache
-- # if demuxer-cache-time property didn't change in demuxer_cache_timer_timeout
-- # time interval, the video will be reloaded as soon as demuxer cache depleated
-- demuxer_cache_timer_enabled=yes
--
-- # checking demuxer-cache-time property interval in seconds,
-- # can not be less than 0.05 (50 ms)
-- demuxer_cache_timer_interval=2
--
-- # if demuxer cache didn't receive any data during demuxer_cache_timer_timeout
-- # we decide that it has no progress and will reload the stream when
-- # paused_for_cache event happens
-- demuxer_cache_timer_timeout=20
--
-- # when the end-of-file is reached, reload the stream to check
-- # if there is more content available.
-- reload_eof_enabled=no
--
-- # keybinding to reload stream from current time position
-- # you can disable keybinding by setting it to empty value
-- # reload_key_binding=
-- reload_key_binding=Ctrl+r
-- ```
--
-- DEBUGGING
--
-- Debug messages will be printed to stdout with mpv command line option
-- `--msg-level='reload=debug'`. You may also need to add the `--no-msg-color`
-- option to make the debug logs visible if you are using a dark colorscheme
-- in terminal.
local msg = require 'mp.msg'
local options = require 'mp.options'
local utils = require 'mp.utils'
local settings = {
paused_for_cache_timer_enabled = true,
paused_for_cache_timer_interval = 1,
paused_for_cache_timer_timeout = 10,
demuxer_cache_timer_enabled = true,
demuxer_cache_timer_interval = 2,
demuxer_cache_timer_timeout = 20,
reload_eof_enabled = false,
reload_key_binding = "Ctrl+r"
}
-- global state stores properties between reloads
local property_path = nil
local property_time_pos = 0
local property_keep_open = nil
-- FSM managing the demuxer cache.
--
-- States:
--
-- * fetch - fetching new data
-- * stale - unable to fetch new data for time < 'demuxer_cache_timer_timeout'
-- * stuck - unable to fetch new data for time >= 'demuxer_cache_timer_timeout'
--
-- State transitions:
--
-- +---------------------------+
-- v |
-- +-------+ +-------+ +-------+
-- + fetch +<--->+ stale +---->+ stuck |
-- +-------+ +-------+ +-------+
-- | ^ | ^ | ^
-- +---+ +---+ +---+
local demuxer_cache = {
timer = nil,
state = { name = 'uninitialized', demuxer_cache_time = 0, in_state_time = 0 },
events = {
continue_fetch = { name = 'continue_fetch', from = 'fetch', to = 'fetch' },
continue_stale = { name = 'continue_stale', from = 'stale', to = 'stale' },
continue_stuck = { name = 'continue_stuck', from = 'stuck', to = 'stuck' },
fetch_to_stale = { name = 'fetch_to_stale', from = 'fetch', to = 'stale' },
stale_to_fetch = { name = 'stale_to_fetch', from = 'stale', to = 'fetch' },
stale_to_stuck = { name = 'stale_to_stuck', from = 'stale', to = 'stuck' },
stuck_to_fetch = { name = 'stuck_to_fetch', from = 'stuck', to = 'fetch' }
}
}
-- Always start with 'fetch' state
function demuxer_cache.reset_state()
demuxer_cache.state = {
name = demuxer_cache.events.continue_fetch.to,
demuxer_cache_time = 0,
in_state_time = 0
}
end
-- Has 'demuxer_cache_time' changed
function demuxer_cache.has_progress_since(t)
return demuxer_cache.state.demuxer_cache_time ~= t
end
function demuxer_cache.is_state_fetch()
return demuxer_cache.state.name == demuxer_cache.events.continue_fetch.to
end
function demuxer_cache.is_state_stale()
return demuxer_cache.state.name == demuxer_cache.events.continue_stale.to
end
function demuxer_cache.is_state_stuck()
return demuxer_cache.state.name == demuxer_cache.events.continue_stuck.to
end
function demuxer_cache.transition(event)
if demuxer_cache.state.name == event.from then
-- state setup
demuxer_cache.state.demuxer_cache_time = event.demuxer_cache_time
if event.name == 'continue_fetch' then
demuxer_cache.state.in_state_time = demuxer_cache.state
.in_state_time +
event.interval
elseif event.name == 'continue_stale' then
demuxer_cache.state.in_state_time = demuxer_cache.state
.in_state_time +
event.interval
elseif event.name == 'continue_stuck' then
demuxer_cache.state.in_state_time = demuxer_cache.state
.in_state_time +
event.interval
elseif event.name == 'fetch_to_stale' then
demuxer_cache.state.in_state_time = 0
elseif event.name == 'stale_to_fetch' then
demuxer_cache.state.in_state_time = 0
elseif event.name == 'stale_to_stuck' then
demuxer_cache.state.in_state_time = 0
elseif event.name == 'stuck_to_fetch' then
demuxer_cache.state.in_state_time = 0
end
-- state transition
demuxer_cache.state.name = event.to
msg.debug('demuxer_cache.transition', event.name,
utils.to_string(demuxer_cache.state))
else
msg.error('demuxer_cache.transition', 'illegal transition', event.name,
'from state', demuxer_cache.state.name)
end
end
function demuxer_cache.initialize(demuxer_cache_timer_interval)
demuxer_cache.reset_state()
demuxer_cache.timer = mp.add_periodic_timer(demuxer_cache_timer_interval,
function()
demuxer_cache.demuxer_cache_timer_tick(
mp.get_property_native('demuxer-cache-time'),
demuxer_cache_timer_interval)
end)
end
-- If there is no progress of demuxer_cache_time in
-- settings.demuxer_cache_timer_timeout time interval switch state to
-- 'stuck' and switch back to 'fetch' as soon as any progress is made
function demuxer_cache.demuxer_cache_timer_tick(demuxer_cache_time,
demuxer_cache_timer_interval)
local event = nil
local cache_has_progress = demuxer_cache.has_progress_since(
demuxer_cache_time)
-- I miss pattern matching so much
if demuxer_cache.is_state_fetch() then
if cache_has_progress then
event = demuxer_cache.events.continue_fetch
else
event = demuxer_cache.events.fetch_to_stale
end
elseif demuxer_cache.is_state_stale() then
if cache_has_progress then
event = demuxer_cache.events.stale_to_fetch
elseif demuxer_cache.state.in_state_time <
settings.demuxer_cache_timer_timeout then
event = demuxer_cache.events.continue_stale
else
event = demuxer_cache.events.stale_to_stuck
end
elseif demuxer_cache.is_state_stuck() then
if cache_has_progress then
event = demuxer_cache.events.stuck_to_fetch
else
event = demuxer_cache.events.continue_stuck
end
end
event.demuxer_cache_time = demuxer_cache_time
event.interval = demuxer_cache_timer_interval
demuxer_cache.transition(event)
end
local paused_for_cache = { timer = nil, time = 0 }
function paused_for_cache.reset_timer()
msg.debug('paused_for_cache.reset_timer', paused_for_cache.time)
if paused_for_cache.timer then
paused_for_cache.timer:kill()
paused_for_cache.timer = nil
paused_for_cache.time = 0
end
end
function paused_for_cache.start_timer(interval_seconds, timeout_seconds)
msg.debug('paused_for_cache.start_timer', paused_for_cache.time)
if not paused_for_cache.timer then
paused_for_cache.timer = mp.add_periodic_timer(interval_seconds,
function()
paused_for_cache.time = paused_for_cache.time + interval_seconds
if paused_for_cache.time >= timeout_seconds then
paused_for_cache.reset_timer()
reload_resume()
end
msg.debug('paused_for_cache', 'tick', paused_for_cache.time)
end)
end
end
function paused_for_cache.handler(property, is_paused)
if is_paused then
if demuxer_cache.is_state_stuck() then
msg.info("demuxer cache has no progress")
-- reset demuxer state to avoid immediate reload if
-- paused_for_cache event triggered right after reload
demuxer_cache.reset_state()
reload_resume()
end
paused_for_cache.start_timer(settings.paused_for_cache_timer_interval,
settings.paused_for_cache_timer_timeout)
else
paused_for_cache.reset_timer()
end
end
function read_settings()
options.read_options(settings, mp.get_script_name())
msg.debug(utils.to_string(settings))
end
function reload(path, time_pos)
msg.debug("reload", path, time_pos)
if time_pos == nil then
mp.commandv("loadfile", path, "replace")
else
local success = mp.commandv("loadfile", path, "replace", -1,
"start=+" .. time_pos)
-- fallback to old syntax of loadfile for compatibility
if success == nil then
msg.warn(
"old loadfile syntax detected. falling back to using old syntax. update mpv to remove this warning")
mp.commandv("loadfile", path, "replace", "start=+" .. time_pos)
end
end
end
function reload_resume()
local path = mp.get_property("path", property_path)
local time_pos = mp.get_property("time-pos")
local reload_duration = mp.get_property_native("duration")
local playlist_count = mp.get_property_number("playlist/count")
local playlist_pos = mp.get_property_number("playlist-pos")
local playlist = {}
for i = 0, playlist_count - 1 do
playlist[i] = mp.get_property("playlist/" .. i .. "/filename")
end
-- Tries to determine live stream vs. pre-recordered VOD. VOD has non-zero
-- duration property. When reloading VOD, to keep the current time position
-- we should provide offset from the start. Stream doesn't have fixed start.
-- Decent choice would be to reload stream from it's current 'live' positon.
-- That's the reason we don't pass the offset when reloading streams.
if reload_duration and reload_duration > 0 then
msg.info("reloading video from", time_pos, "second")
reload(path, time_pos)
-- VODs get stuck when reload is called without a time_pos
-- this is most noticeable in youtube videos whenever download gets stuck in the first frames
-- video would stay paused without being actually paused
-- issue surfaced in mpv 0.33, afaik
elseif reload_duration and reload_duration == 0 then
msg.info("reloading video from", time_pos, "second")
reload(path, time_pos)
else
msg.info("reloading stream")
reload(path, nil)
end
msg.info("file", playlist_pos + 1, "of", playlist_count, "in playlist")
for i = 0, playlist_pos - 1 do
mp.commandv("loadfile", playlist[i], "append")
end
mp.commandv("playlist-move", 0, playlist_pos + 1)
for i = playlist_pos + 1, playlist_count - 1 do
mp.commandv("loadfile", playlist[i], "append")
end
end
function reload_eof(property, eof_reached)
msg.debug("reload_eof", property, eof_reached)
local time_pos = mp.get_property_number("time-pos")
local duration = mp.get_property_number("duration")
if eof_reached and round(time_pos) == round(duration) then
msg.debug("property_time_pos", property_time_pos, "time_pos", time_pos)
-- Check that playback time_pos made progress after the last reload. When
-- eof is reached we try to reload the video, in case there is more content
-- available. If time_pos stayed the same after reload, it means that the
-- video length stayed the same, and we can end the playback.
if round(property_time_pos) == round(time_pos) then
msg.info("eof reached, playback ended")
mp.set_property("keep-open", property_keep_open)
else
msg.info("eof reached, checking if more content available")
reload_resume()
mp.set_property_bool("pause", false)
property_time_pos = time_pos
end
end
end
function on_file_loaded(event)
local debug_info = {
event = event,
time_pos = mp.get_property("time-pos"),
stream_pos = mp.get_property("stream-pos"),
stream_end = mp.get_property("stream-end"),
duration = mp.get_property("duration"),
seekable = mp.get_property("seekable"),
pause = mp.get_property("pause"),
paused_for_cache = mp.get_property("paused-for-cache"),
cache_buffering_state = mp.get_property("cache-buffering-state")
}
msg.debug("debug_info", utils.to_string(debug_info))
-- When the video is reloaded after being paused for cache, it won't start
-- playing again while all properties looks fine:
-- `pause=no`, `paused-for-cache=no` and `cache-buffering-state=100`.
-- As a workaround, we cycle through the paused state by sending two SPACE
-- keypresses.
-- What didn't work:
-- - Cycling through the `pause` property.
-- - Run the `playlist-play-index current` command.
mp.commandv("keypress", 'SPACE')
mp.commandv("keypress", 'SPACE')
end
-- Round positive numbers.
function round(num) return math.floor(num + 0.5) end
-- main
read_settings()
if settings.reload_key_binding ~= "" then
mp.add_key_binding(settings.reload_key_binding, "reload_resume",
reload_resume)
end
if settings.paused_for_cache_timer_enabled then
mp.observe_property("paused-for-cache", "bool", paused_for_cache.handler)
end
if settings.demuxer_cache_timer_enabled then
demuxer_cache.initialize(settings.demuxer_cache_timer_interval)
end
if settings.reload_eof_enabled then
-- vo-configured == video output created && its configuration went ok
mp.observe_property("vo-configured", "bool", function(name, vo_configured)
msg.debug(name, vo_configured)
if vo_configured then
property_path = mp.get_property("path")
property_keep_open = mp.get_property("keep-open")
mp.set_property("keep-open", "yes")
mp.set_property("keep-open-pause", "no")
end
end)
mp.observe_property("eof-reached", "bool", reload_eof)
end
mp.register_event("file-loaded", on_file_loaded)

View File

@@ -0,0 +1,83 @@
-- mpv_websocket
-- https://github.com/kuroahna/mpv_websocket
local utils = require("mp.utils")
local platform = mp.get_property_native("platform")
local config_file_path = mp.find_config_file("mpv.conf")
local config_folder_path, config_file = utils.split_path(config_file_path)
local mpv_websocket_path =
utils.join_path(config_folder_path, platform == "windows" and "mpv_websocket.exe" or "mpv_websocket")
local initialised_websocket
local _, err = utils.file_info(config_file_path)
if err then
error("failed to open mpv config file `" .. config_file_path .. "`")
end
local _, err = utils.file_info(mpv_websocket_path)
if err then
error("failed to open mpv_websocket")
end
local function find_mpv_socket(config_file_path)
local file = io.open(config_file_path, "r")
if file == nil then
error("failed to read mpv config file `" .. config_file_path .. "`")
end
local mpv_socket
for line in file:lines() do
mpv_socket = line:match("^input%-ipc%-server%s*=%s*(%g+)%s*")
if mpv_socket then
break
end
end
file:close()
if not mpv_socket then
error("input-ipc-server option does not exist in `" .. config_file_path .. "`")
end
return mpv_socket
end
local mpv_socket = find_mpv_socket(config_file_path)
if platform == "windows" then
mpv_socket = "\\\\.\\pipe" .. mpv_socket:gsub("/", "\\")
end
local function start_websocket()
initialised_websocket = mp.command_native_async({
name = "subprocess",
playback_only = false,
capture_stdout = true,
capture_stderr = true,
args = {
mpv_websocket_path,
"-m",
mpv_socket,
"-w",
"6677",
},
})
end
local function end_websocket()
mp.abort_async_command(initialised_websocket)
initialised_websocket = nil
end
local function toggle_websocket()
local paused = mp.get_property_bool("pause")
if initialised_websocket and paused then
end_websocket()
elseif not initialised_websocket and not paused then
start_websocket()
end
end
mp.register_script_message("togglewebsocket", toggle_websocket)
start_websocket()

View File

@@ -0,0 +1,679 @@
-- sponsorblock.lua
--
-- This script skips sponsored segments of YouTube videos
-- using data from https://github.com/ajayyy/SponsorBlock
local ON_WINDOWS = package.config:sub(1, 1) ~= "/"
local options = {
server_address = "https://sponsor.ajay.app",
python_path = ON_WINDOWS and "python" or "python3",
-- Categories to fetch
categories = "sponsor,intro,outro,interaction,selfpromo,filler",
-- Categories to skip automatically
skip_categories = "sponsor",
-- If true, sponsored segments will only be skipped once
skip_once = true,
-- Note that sponsored segments may ocasionally be inaccurate if this is turned off
-- see https://blog.ajay.app/voting-and-pseudo-randomness-or-sponsorblock-or-youtube-sponsorship-segment-blocker
local_database = false,
-- Update database on first run, does nothing if local_database is false
auto_update = true,
-- How long to wait between local database updates
-- Format: "X[d,h,m]", leave blank to update on every mpv run
auto_update_interval = "6h",
-- User ID used to submit sponsored segments, leave blank for random
user_id = "",
-- Name to display on the stats page https://sponsor.ajay.app/stats/ leave blank to keep current name
display_name = "",
-- Tell the server when a skip happens
report_views = true,
-- Auto upvote skipped sponsors
auto_upvote = false,
-- Use sponsor times from server if they're more up to date than our local database
server_fallback = true,
-- Create chapters at sponsor boundaries for OSC display and manual skipping
make_chapters = true,
-- Minimum duration for sponsors (in seconds), segments under that threshold will be ignored
min_duration = 1,
-- Fade audio for smoother transitions
audio_fade = false,
-- Audio fade step, applied once every 100ms until cap is reached
audio_fade_step = 10,
-- Audio fade cap
audio_fade_cap = 0,
-- Fast forward through sponsors instead of skipping
fast_forward = false,
-- Playback speed modifier when fast forwarding, applied once every second until cap is reached
fast_forward_increase = 0.2,
-- Playback speed cap
fast_forward_cap = 2,
-- Length of the sha256 prefix (3-32) when querying server, 0 to disable
sha256_length = 4,
-- Pattern for video id in local files, ignored if blank
-- Recommended value for base youtube-dl is "-([%w-_]+)%.[mw][kpe][v4b]m?$"
local_pattern = "",
-- Legacy option, use skip_categories instead
skip = true,
}
mp.options = require("mp.options")
mp.options.read_options(options, "sponsorblock")
local legacy = mp.command_native_async == nil
--[[
if legacy then
options.local_database = false
end
--]]
options.local_database = false
local utils = require("mp.utils")
scripts_dir = mp.find_config_file("scripts")
local sponsorblock = utils.join_path(scripts_dir, "sponsorblock_shared/sponsorblock.py")
local uid_path = utils.join_path(scripts_dir, "sponsorblock_shared/sponsorblock.txt")
local database_file = options.local_database and utils.join_path(scripts_dir, "sponsorblock_shared/sponsorblock.db")
or ""
local youtube_id = nil
local ranges = {}
local init = false
local segment = { a = 0, b = 0, progress = 0, first = true }
local retrying = false
local last_skip = { uuid = "", dir = nil }
local speed_timer = nil
local fade_timer = nil
local fade_dir = nil
local volume_before = mp.get_property_number("volume")
local categories = {}
local all_categories =
{ "sponsor", "intro", "outro", "interaction", "selfpromo", "preview", "music_offtopic", "filler" }
local chapter_cache = {}
for category in string.gmatch(options.skip_categories, "([^,]+)") do
categories[category] = true
end
function file_exists(name)
local f = io.open(name, "r")
if f ~= nil then
io.close(f)
return true
else
return false
end
end
function t_count(t)
local count = 0
for _ in pairs(t) do
count = count + 1
end
return count
end
function time_sort(a, b)
if a.time == b.time then
return string.match(a.title, "segment end")
end
return a.time < b.time
end
function parse_update_interval()
local s = options.auto_update_interval
if s == "" then
return 0
end -- Interval Disabled
local num, mod = s:match("^(%d+)([hdm])$")
if num == nil or mod == nil then
mp.osd_message("[sponsorblock] auto_update_interval " .. s .. " is invalid", 5)
return nil
end
local time_table = {
m = 60,
h = 60 * 60,
d = 60 * 60 * 24,
}
return num * time_table[mod]
end
function clean_chapters()
local chapters = mp.get_property_native("chapter-list")
local new_chapters = {}
for _, chapter in pairs(chapters) do
if chapter.title ~= "Preview segment start" and chapter.title ~= "Preview segment end" then
table.insert(new_chapters, chapter)
end
end
mp.set_property_native("chapter-list", new_chapters)
end
function create_chapter(chapter_title, chapter_time)
local chapters = mp.get_property_native("chapter-list")
local duration = mp.get_property_native("duration")
table.insert(
chapters,
{ title = chapter_title, time = (duration == nil or duration > chapter_time) and chapter_time
or duration - 0.001 }
)
table.sort(chapters, time_sort)
mp.set_property_native("chapter-list", chapters)
end
function process(uuid, t, new_ranges)
start_time = tonumber(string.match(t, "[^,]+"))
end_time = tonumber(string.sub(string.match(t, ",[^,]+"), 2))
for o_uuid, o_t in pairs(ranges) do
if
(start_time >= o_t.start_time and start_time <= o_t.end_time)
or (o_t.start_time >= start_time and o_t.start_time <= end_time)
then
new_ranges[o_uuid] = o_t
return
end
end
category = string.match(t, "[^,]+$")
if categories[category] and end_time - start_time >= options.min_duration then
new_ranges[uuid] = {
start_time = start_time,
end_time = end_time,
category = category,
skipped = false,
}
end
if options.make_chapters and not chapter_cache[uuid] then
chapter_cache[uuid] = true
local category_title = (category:gsub("^%l", string.upper):gsub("_", " "))
create_chapter(category_title .. " segment start (" .. string.sub(uuid, 1, 6) .. ")", start_time)
create_chapter(category_title .. " segment end (" .. string.sub(uuid, 1, 6) .. ")", end_time)
end
end
function getranges(_, exists, db, more)
if type(exists) == "table" and exists["status"] == "1" then
if options.server_fallback then
mp.add_timeout(0, function()
getranges(true, true, "")
end)
else
return mp.osd_message("[sponsorblock] database update failed, gave up")
end
end
if db ~= "" and db ~= database_file then
db = database_file
end
if exists ~= true and not file_exists(db) then
if not retrying then
mp.osd_message("[sponsorblock] database update failed, retrying...")
retrying = true
end
return update()
end
if retrying then
mp.osd_message("[sponsorblock] database update succeeded")
retrying = false
end
local sponsors
local args = {
options.python_path,
sponsorblock,
"ranges",
db,
options.server_address,
youtube_id,
options.categories,
tostring(options.sha256_length),
}
if not legacy then
sponsors = mp.command_native({ name = "subprocess", capture_stdout = true, playback_only = false, args = args })
else
sponsors = utils.subprocess({ args = args })
end
mp.msg.debug("Got: " .. string.gsub(sponsors.stdout, "[\n\r]", ""))
if not string.match(sponsors.stdout, "^%s*(.*%S)") then
return
end
if string.match(sponsors.stdout, "error") then
return getranges(true, true)
end
local new_ranges = {}
local r_count = 0
if more then
r_count = -1
end
for t in string.gmatch(sponsors.stdout, "[^:%s]+") do
uuid = string.match(t, "([^,]+),[^,]+$")
if ranges[uuid] then
new_ranges[uuid] = ranges[uuid]
else
process(uuid, t, new_ranges)
end
r_count = r_count + 1
end
local c_count = t_count(ranges)
if c_count == 0 or r_count >= c_count then
ranges = new_ranges
end
end
function fast_forward()
if options.fast_forward and options.fast_forward == true then
speed_timer = nil
mp.set_property("speed", 1)
end
local last_speed = mp.get_property_number("speed")
local new_speed = math.min(last_speed + options.fast_forward_increase, options.fast_forward_cap)
if new_speed <= last_speed then
return
end
mp.set_property("speed", new_speed)
end
function fade_audio(step)
local last_volume = mp.get_property_number("volume")
local new_volume = math.max(options.audio_fade_cap, math.min(last_volume + step, volume_before))
if new_volume == last_volume then
if step >= 0 then
fade_dir = nil
end
if fade_timer ~= nil then
fade_timer:kill()
end
fade_timer = nil
return
end
mp.set_property("volume", new_volume)
end
function skip_ads(name, pos)
if pos == nil then
return
end
local sponsor_ahead = false
for uuid, t in pairs(ranges) do
if
(options.fast_forward == uuid or not options.skip_once or not t.skipped)
and t.start_time <= pos
and t.end_time > pos
then
if options.fast_forward == uuid then
return
end
if options.fast_forward == false then
mp.osd_message("[sponsorblock] " .. t.category .. " skipped")
mp.set_property("time-pos", t.end_time)
else
mp.osd_message("[sponsorblock] skipping " .. t.category)
end
t.skipped = true
last_skip = { uuid = uuid, dir = nil }
if options.report_views or options.auto_upvote then
local args = {
options.python_path,
sponsorblock,
"stats",
database_file,
options.server_address,
youtube_id,
uuid,
options.report_views and "1" or "",
uid_path,
options.user_id,
options.auto_upvote and "1" or "",
}
if not legacy then
mp.command_native_async({ name = "subprocess", playback_only = false, args = args }, function() end)
else
utils.subprocess_detached({ args = args })
end
end
if options.fast_forward ~= false then
options.fast_forward = uuid
if speed_timer ~= nil then
speed_timer:kill()
end
speed_timer = mp.add_periodic_timer(1, fast_forward)
end
return
elseif (not options.skip_once or not t.skipped) and t.start_time <= pos + 1 and t.end_time > pos + 1 then
sponsor_ahead = true
end
end
if options.audio_fade then
if sponsor_ahead then
if fade_dir ~= false then
if fade_dir == nil then
volume_before = mp.get_property_number("volume")
end
if fade_timer ~= nil then
fade_timer:kill()
end
fade_dir = false
fade_timer = mp.add_periodic_timer(0.1, function()
fade_audio(-options.audio_fade_step)
end)
end
elseif fade_dir == false then
fade_dir = true
if fade_timer ~= nil then
fade_timer:kill()
end
fade_timer = mp.add_periodic_timer(0.1, function()
fade_audio(options.audio_fade_step)
end)
end
end
if options.fast_forward and options.fast_forward ~= true then
options.fast_forward = true
speed_timer:kill()
speed_timer = nil
mp.set_property("speed", 1)
end
end
function vote(dir)
if last_skip.uuid == "" then
return mp.osd_message("[sponsorblock] no sponsors skipped, can't submit vote")
end
local updown = dir == "1" and "up" or "down"
if last_skip.dir == dir then
return mp.osd_message("[sponsorblock] " .. updown .. "vote already submitted")
end
last_skip.dir = dir
local args = {
options.python_path,
sponsorblock,
"stats",
database_file,
options.server_address,
youtube_id,
last_skip.uuid,
"",
uid_path,
options.user_id,
dir,
}
if not legacy then
mp.command_native_async({ name = "subprocess", playback_only = false, args = args }, function() end)
else
utils.subprocess({ args = args })
end
mp.osd_message("[sponsorblock] " .. updown .. "vote submitted")
end
function update()
mp.command_native_async(
{
name = "subprocess",
playback_only = false,
args = {
options.python_path,
sponsorblock,
"update",
database_file,
options.server_address,
},
},
getranges
)
end
function file_loaded()
local initialized = init
ranges = {}
segment = { a = 0, b = 0, progress = 0, first = true }
last_skip = { uuid = "", dir = nil }
chapter_cache = {}
local video_path = mp.get_property("path", "")
mp.msg.debug("Path: " .. video_path)
local video_referer = string.match(mp.get_property("http-header-fields", ""), "Referer:([^,]+)") or ""
mp.msg.debug("Referer: " .. video_referer)
local urls = {
"https?://youtu%.be/([%w-_]+).*",
"https?://w?w?w?%.?youtube%.com/v/([%w-_]+).*",
"/watch.*[?&]v=([%w-_]+).*",
"/embed/([%w-_]+).*",
}
youtube_id = nil
for i, url in ipairs(urls) do
youtube_id = youtube_id or string.match(video_path, url) or string.match(video_referer, url)
if youtube_id then
break
end
end
youtube_id = youtube_id or string.match(video_path, options.local_pattern)
if not youtube_id or string.len(youtube_id) < 11 or (local_pattern and string.len(youtube_id) ~= 11) then
return
end
youtube_id = string.sub(youtube_id, 1, 11)
mp.msg.debug("Found YouTube ID: " .. youtube_id)
init = true
if not options.local_database then
getranges(true, true)
else
local exists = file_exists(database_file)
if exists and options.server_fallback then
getranges(true, true)
mp.add_timeout(0, function()
getranges(true, true, "", true)
end)
elseif exists then
getranges(true, true)
elseif options.server_fallback then
mp.add_timeout(0, function()
getranges(true, true, "")
end)
end
end
if initialized then
return
end
if options.skip then
mp.observe_property("time-pos", "native", skip_ads)
end
if options.display_name ~= "" then
local args = {
options.python_path,
sponsorblock,
"username",
database_file,
options.server_address,
youtube_id,
"",
"",
uid_path,
options.user_id,
options.display_name,
}
if not legacy then
mp.command_native_async({ name = "subprocess", playback_only = false, args = args }, function() end)
else
utils.subprocess_detached({ args = args })
end
end
if not options.local_database or (not options.auto_update and file_exists(database_file)) then
return
end
if file_exists(database_file) then
local db_info = utils.file_info(database_file)
local cur_time = os.time(os.date("*t"))
local upd_interval = parse_update_interval()
if upd_interval == nil or os.difftime(cur_time, db_info.mtime) < upd_interval then
return
end
end
update()
end
function set_segment()
if not youtube_id then
return
end
local pos = mp.get_property_number("time-pos")
if pos == nil then
return
end
if segment.progress > 1 then
segment.progress = segment.progress - 2
end
if segment.progress == 1 then
segment.progress = 0
segment.b = pos
mp.osd_message("[sponsorblock] segment boundary B set, press again for boundary A", 3)
else
segment.progress = 1
segment.a = pos
mp.osd_message("[sponsorblock] segment boundary A set, press again for boundary B", 3)
end
if options.make_chapters and not segment.first then
local start_time = math.min(segment.a, segment.b)
local end_time = math.max(segment.a, segment.b)
if end_time - start_time ~= 0 and end_time ~= 0 then
clean_chapters()
create_chapter("Preview segment start", start_time)
create_chapter("Preview segment end", end_time)
end
end
segment.first = false
end
function select_category(selected)
for category in string.gmatch(options.categories, "([^,]+)") do
mp.remove_key_binding("select_category_" .. category)
mp.remove_key_binding("kp_select_category_" .. category)
end
submit_segment(selected)
end
function submit_segment(category)
if not youtube_id then
return
end
local start_time = math.min(segment.a, segment.b)
local end_time = math.max(segment.a, segment.b)
if end_time - start_time == 0 or end_time == 0 then
mp.osd_message("[sponsorblock] empty segment, not submitting")
elseif segment.progress <= 1 then
segment.progress = segment.progress + 2
local category_list = ""
for category_id, category in pairs(all_categories) do
local category_title = (category:gsub("^%l", string.upper):gsub("_", " "))
category_list = category_list .. category_id .. ": " .. category_title .. "\n"
mp.add_forced_key_binding(tostring(category_id), "select_category_" .. category, function()
select_category(category)
end)
mp.add_forced_key_binding("KP" .. tostring(category_id), "kp_select_category_" .. category, function()
select_category(category)
end)
end
mp.osd_message(
string.format(
"[sponsorblock] press a number to select category for segment: %.2d:%.2d:%.2d to %.2d:%.2d:%.2d\n\n"
.. category_list
.. "\nyou can press Shift+G again for default (Sponsor) or hide this message with g",
math.floor(start_time / (60 * 60)),
math.floor(start_time / 60 % 60),
math.floor(start_time % 60),
math.floor(end_time / (60 * 60)),
math.floor(end_time / 60 % 60),
math.floor(end_time % 60)
),
30
)
else
mp.osd_message("[sponsorblock] submitting segment...", 30)
local submit
local args = {
options.python_path,
sponsorblock,
"submit",
database_file,
options.server_address,
youtube_id,
tostring(start_time),
tostring(end_time),
uid_path,
options.user_id,
category or "sponsor",
}
if not legacy then
submit =
mp.command_native({ name = "subprocess", capture_stdout = true, playback_only = false, args = args })
else
submit = utils.subprocess({ args = args })
end
if string.match(submit.stdout, "success") then
segment = { a = 0, b = 0, progress = 0, first = true }
mp.osd_message("[sponsorblock] segment submitted")
if options.make_chapters then
clean_chapters()
create_chapter("Submitted segment start", start_time)
create_chapter("Submitted segment end", end_time)
end
elseif string.match(submit.stdout, "error") then
mp.osd_message("[sponsorblock] segment submission failed, server may be down. try again", 5)
elseif string.match(submit.stdout, "502") then
mp.osd_message("[sponsorblock] segment submission failed, server is down. try again", 5)
elseif string.match(submit.stdout, "400") then
mp.osd_message("[sponsorblock] segment submission failed, impossible inputs", 5)
segment = { a = 0, b = 0, progress = 0, first = true }
elseif string.match(submit.stdout, "429") then
mp.osd_message("[sponsorblock] segment submission failed, rate limited. try again", 5)
elseif string.match(submit.stdout, "409") then
mp.osd_message("[sponsorblock] segment already submitted", 3)
segment = { a = 0, b = 0, progress = 0, first = true }
else
mp.osd_message("[sponsorblock] segment submission failed", 5)
end
end
end
mp.register_event("file-loaded", file_loaded)
mp.add_key_binding("ctrl+g", "set_segment", set_segment)
mp.add_key_binding("ctrl+G", "submit_segment", submit_segment)
mp.add_key_binding("ctrl+h", "upvote_segment", function()
return vote("1")
end)
mp.add_key_binding("ctrl+H", "downvote_segment", function()
return vote("0")
end)
-- Bindings below are for backwards compatibility and could be removed at any time
mp.add_key_binding(nil, "sponsorblock_set_segment", set_segment)
mp.add_key_binding(nil, "sponsorblock_submit_segment", submit_segment)
mp.add_key_binding(nil, "sponsorblock_upvote", function()
return vote("1")
end)
mp.add_key_binding(nil, "sponsorblock_downvote", function()
return vote("0")
end)

View File

@@ -0,0 +1,3 @@
-- This is a dummy main.lua
-- required for mpv 0.33
-- do not delete

View File

@@ -0,0 +1,122 @@
import urllib.request
import urllib.parse
import hashlib
import sqlite3
import random
import string
import json
import sys
import os
if sys.argv[1] in ["submit", "stats", "username"]:
if not sys.argv[8]:
if os.path.isfile(sys.argv[7]):
with open(sys.argv[7]) as f:
uid = f.read()
else:
uid = "".join(random.choices(string.ascii_letters + string.digits, k=36))
with open(sys.argv[7], "w") as f:
f.write(uid)
else:
uid = sys.argv[8]
opener = urllib.request.build_opener()
opener.addheaders = [("User-Agent", "mpv_sponsorblock/1.0 (https://github.com/po5/mpv_sponsorblock)")]
urllib.request.install_opener(opener)
if sys.argv[1] == "ranges" and (not sys.argv[2] or not os.path.isfile(sys.argv[2])):
sha = None
if 3 <= int(sys.argv[6]) <= 32:
sha = hashlib.sha256(sys.argv[4].encode()).hexdigest()[:int(sys.argv[6])]
times = []
try:
response = urllib.request.urlopen(sys.argv[3] + "/api/skipSegments" + ("/" + sha + "?" if sha else "?videoID=" + sys.argv[4] + "&") + urllib.parse.urlencode([("categories", json.dumps(sys.argv[5].split(",")))]))
segments = json.load(response)
for segment in segments:
if sha and sys.argv[4] != segment["videoID"]:
continue
if sha:
for s in segment["segments"]:
times.append(str(s["segment"][0]) + "," + str(s["segment"][1]) + "," + s["UUID"] + "," + s["category"])
else:
times.append(str(segment["segment"][0]) + "," + str(segment["segment"][1]) + "," + segment["UUID"] + "," + segment["category"])
print(":".join(times))
except (TimeoutError, urllib.error.URLError) as e:
print("error")
except urllib.error.HTTPError as e:
if e.code == 404:
print("")
else:
print("error")
elif sys.argv[1] == "ranges":
conn = sqlite3.connect(sys.argv[2])
conn.row_factory = sqlite3.Row
c = conn.cursor()
times = []
for category in sys.argv[5].split(","):
c.execute("SELECT startTime, endTime, votes, UUID, category FROM sponsorTimes WHERE videoID = ? AND shadowHidden = 0 AND votes > -1 AND category = ?", (sys.argv[4], category))
sponsors = c.fetchall()
best = list(sponsors)
dealtwith = []
similar = []
for sponsor_a in sponsors:
for sponsor_b in sponsors:
if sponsor_a is not sponsor_b and sponsor_a["startTime"] >= sponsor_b["startTime"] and sponsor_a["startTime"] <= sponsor_b["endTime"]:
similar.append([sponsor_a, sponsor_b])
if sponsor_a in best:
best.remove(sponsor_a)
if sponsor_b in best:
best.remove(sponsor_b)
for sponsors_a in similar:
if sponsors_a in dealtwith:
continue
group = set(sponsors_a)
for sponsors_b in similar:
if sponsors_b[0] in group or sponsors_b[1] in group:
group.add(sponsors_b[0])
group.add(sponsors_b[1])
dealtwith.append(sponsors_b)
best.append(max(group, key=lambda x:x["votes"]))
for time in best:
times.append(str(time["startTime"]) + "," + str(time["endTime"]) + "," + time["UUID"] + "," + time["category"])
print(":".join(times))
elif sys.argv[1] == "update":
try:
urllib.request.urlretrieve(sys.argv[3] + "/database.db", sys.argv[2] + ".tmp")
os.replace(sys.argv[2] + ".tmp", sys.argv[2])
except PermissionError:
print("database update failed, file currently in use", file=sys.stderr)
sys.exit(1)
except ConnectionResetError:
print("database update failed, connection reset", file=sys.stderr)
sys.exit(1)
except TimeoutError:
print("database update failed, timed out", file=sys.stderr)
sys.exit(1)
except urllib.error.URLError:
print("database update failed", file=sys.stderr)
sys.exit(1)
elif sys.argv[1] == "submit":
try:
req = urllib.request.Request(sys.argv[3] + "/api/skipSegments", data=json.dumps({"videoID": sys.argv[4], "segments": [{"segment": [float(sys.argv[5]), float(sys.argv[6])], "category": sys.argv[9]}], "userID": uid}).encode(), headers={"Content-Type": "application/json"})
response = urllib.request.urlopen(req)
print("success")
except urllib.error.HTTPError as e:
print(e.code)
except:
print("error")
elif sys.argv[1] == "stats":
try:
if sys.argv[6]:
urllib.request.urlopen(sys.argv[3] + "/api/viewedVideoSponsorTime?UUID=" + sys.argv[5])
if sys.argv[9]:
urllib.request.urlopen(sys.argv[3] + "/api/voteOnSponsorTime?UUID=" + sys.argv[5] + "&userID=" + uid + "&type=" + sys.argv[9])
except:
pass
elif sys.argv[1] == "username":
try:
data = urllib.parse.urlencode({"userID": uid, "userName": sys.argv[9]}).encode()
req = urllib.request.Request(sys.argv[3] + "/api/setUsername", data=data)
urllib.request.urlopen(req)
except:
pass

View File

@@ -0,0 +1 @@
dFlkoCOSK3BQhXGGhUsXSNU0sPr7AV7avndk

View File

@@ -0,0 +1 @@
../submodules/mpvacious

View File

@@ -0,0 +1 @@
../submodules/thumbfast/thumbfast.lua

View File

@@ -0,0 +1 @@
../submodules/mpv-youtube-upnext/youtube-upnext.lua

View File

@@ -0,0 +1 @@
../submodules/ytdl-preload/ytdl-preload.lua

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,415 @@
// LICENSE
// =======
// Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved.
// -------
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// -------
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
// Software.
// -------
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// FidelityFX CAS v1.0.2 by AMD
// ported to mpv by agyild
// Changelog
// Optimized texture lookups for OpenGL 4.0+, DirectX 10+, and OpenGL ES 3.1+
// Changed rcp + mul operations to div for better clarity when CAS_GO_SLOWER is set to 1, since the compiler should automatically
// optimize those instructions anyway.
// Made it directly operate on LUMA plane, since the original shader was operating on LUMA by deriving it from RGB. This should
// cause a major increase in performance, especially on OpenGL 4.0+ renderers (4 texture lookups vs. 16)
// Removed transparency preservation mechanism since the alpha channel is a separate source plan than LUMA
// Added custom gamma curve support for relinearization
// Removed final blending between the original and the sharpened pixels since it was redundant
//
// Notes
// Per AMD's guidelines only upscales content up to 4x (e.g., 1080p -> 2160p, 720p -> 1440p etc.) and everything else in between,
// that means CAS will scale up to 4x at maximum, and any further scaling will be processed by mpv's scalers
//
// The filter is designed to run in linear light, and does have an optional relinerization and delinearization pass which
// assumes BT.1886 content by default. Do not forget to change SOURCE_TRC and TARGET_TRC variables depending
// on what kind of content the filter is running on. You might want to create seperate versions of the file with different
// colorspace values, and apply them via autoprofiles. Note that running in non-linear light will result in oversharpening.
//!HOOK LUMA
//!BIND HOOKED
//!DESC FidelityFX Upsampling and Sharpening v1.0.2 (Relinearization)
//!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 >
// User variables - Relinearization
// Compatibility
#define SOURCE_TRC 4 // Is needed to convert from source colorspace to linear light. 0 = None (Skip conversion), 1 = Rec709, 2 = PQ, 3 = sRGB, 4 = BT.1886, 5 = HLG, 6 = Custom
#define CUSTOM_GAMMA 2.2 // Custom power gamma curve to use if and when SOURCE_TRC is 6.
// Shader code
float From709(float rec709) {
return max(min(rec709 / float(4.5), float(0.081)), pow((rec709 + float(0.099)) / float(1.099), float(1.0 / 0.45)));
}
float FromPq(float pq) {
float p = pow(pq, float(0.0126833));
return (pow(clamp(p - float(0.835938), 0.0, 1.0) / (float(18.8516) - float(18.6875) * p), float(6.27739)));
}
float FromSrgb(float srgb) {
return max(min(srgb / 12.92, float(0.04045)), pow((srgb + float(0.055)) / float(1.055), float(2.4)));
}
float FromHlg(float hlg) {
const float a = 0.17883277;
const float b = 0.28466892;
const float c = 0.55991073;
float linear;
if (hlg >= 0.0 && hlg <= 0.5) {
linear = pow(hlg, 2.0) / 3.0;
} else {
linear = (exp((hlg - c) / a) + b) / 12.0;
}
return linear;
}
vec4 hook() {
vec4 col = HOOKED_tex(HOOKED_pos);
col.r = clamp(col.r, 0.0, 1.0);
#if (SOURCE_TRC == 1)
col.r = From709(col.r);
#elif (SOURCE_TRC == 2)
col.r = FromPq(col.r);
#elif (SOURCE_TRC == 3)
col.r = FromSrgb(col.r);
#elif (SOURCE_TRC == 4)
col.r = pow(col.r, float(2.4));
#elif (SOURCE_TRC == 5)
col.r = FromHlg(col.r);
#elif (SOURCE_TRC == 6)
col.r = pow(col.r, float(CUSTOM_GAMMA));
#endif
return col;
}
//!HOOK LUMA
//!BIND HOOKED
//!DESC FidelityFX Upsampling and Sharpening v1.0.2
//!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 >
//!WIDTH OUTPUT.w OUTPUT.w LUMA.w 2 * < * LUMA.w 2 * OUTPUT.w LUMA.w 2 * > * + OUTPUT.w OUTPUT.w LUMA.w 2 * = * +
//!HEIGHT OUTPUT.h OUTPUT.h LUMA.h 2 * < * LUMA.h 2 * OUTPUT.h LUMA.h 2 * > * + OUTPUT.h OUTPUT.h LUMA.h 2 * = * +
// User variables - Upsampling and Sharpening
// Intensity
#define SHARPENING 0.0 // Adjusts the range the shader adapts to high contrast (0 is not all the way off). Higher values = more high contrast sharpening. 0.0 to 1.0.
// Performance
#define CAS_BETTER_DIAGONALS 1 // If set to 0, drops certain math and texture lookup operations for better performance. This is only useful on pre-OpenGL 4.0 renderers and there is no need to disable it otherwise. 0 or 1.
#define CAS_GO_SLOWER 0 // If set to 1, disables the use of optimized approximate transcendental functions which might slightly increase accuracy in exchange of performance. 0 or 1.
// Compatibility
#define TARGET_TRC 4 // Is needed to convert from source colorspace to target colorspace. 0 = None (Skip conversion), 1 = Rec709, 2 = PQ, 3 = sRGB, 4 = BT.1886, 5 = HLG, 6 = Custom
#define CUSTOM_GAMMA 2.2 // Custom power gamma curve to use if and when TARGET_TRC is 6.
// Shader code
float To709(float linear) {
return max(min(linear * float(4.5), float(0.018)), float(1.099) * pow(linear, float(0.45)) - float(0.099));
}
float ToPq(float linear) {
float p = pow(linear, float(0.159302));
return pow((float(0.835938) + float(18.8516) * p) / (float(1.0) + float(18.6875) * p), float(78.8438));
}
float ToSrgb(float linear) {
return max(min(linear * float(12.92), float(0.0031308)), float(1.055) * pow(linear, float(0.41666)) - float(0.055));
}
float ToHlg(float linear) {
const float a = 0.17883277;
const float b = 0.28466892;
const float c = 0.55991073;
float hlg;
if (linear <= 1.0 / 12.0) {
hlg = sqrt(3.0 * linear);
} else {
hlg = a * log(12.0 * linear - b) + c;
}
return hlg;
}
#if (CAS_GO_SLOWER == 0)
float APrxLoSqrtF1(float a) {
return uintBitsToFloat((floatBitsToUint(a) >> uint(1)) + uint(0x1fbc4639));
}
float APrxLoRcpF1(float a) {
return uintBitsToFloat(uint(0x7ef07ebb) - floatBitsToUint(a));
}
float APrxMedRcpF1(float a) {
float b = uintBitsToFloat(uint(0x7ef19fff) - floatBitsToUint(a));
return b * (-b * a + float(2.0));
}
#endif
vec4 hook()
{
// Scaling algorithm adaptively interpolates between nearest 4 results of the non-scaling algorithm.
// a b c d
// e f g h
// i j k l
// m n o p
// Working these 4 results.
// +-----+-----+
// | | |
// | f..|..g |
// | . | . |
// +-----+-----+
// | . | . |
// | j..|..k |
// | | |
// +-----+-----+
vec2 pp = HOOKED_pos * HOOKED_size - 0.5;
vec2 fp = floor(pp);
pp -= fp;
#if (defined(HOOKED_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310)))
vec4 abef = HOOKED_gather(vec2((fp - vec2(0.5)) * HOOKED_pt), 0);
float b = abef.z;
float e = abef.x;
float f = abef.y;
vec4 cdgh = HOOKED_gather(vec2((fp + vec2(1.5, -0.5)) * HOOKED_pt), 0);
float c = cdgh.w;
float g = cdgh.x;
float h = cdgh.y;
vec4 ijmn = HOOKED_gather(vec2((fp + vec2(-0.5, 1.5)) * HOOKED_pt), 0);
float i = ijmn.w;
float j = ijmn.z;
float n = ijmn.y;
vec4 klop = HOOKED_gather(vec2((fp + vec2(1.5)) * HOOKED_pt), 0);
float k = klop.w;
float l = klop.z;
float o = klop.x;
#if (CAS_BETTER_DIAGONALS == 1)
float a = abef.w;
float d = cdgh.z;
float m = ijmn.x;
float p = klop.y;
#endif
#else
ivec2 sp = ivec2(fp);
#if (CAS_BETTER_DIAGONALS == 1)
float a = texelFetch(HOOKED_raw, sp + ivec2(-1, -1), 0).r * HOOKED_mul;
float d = texelFetch(HOOKED_raw, sp + ivec2( 2, -1), 0).r * HOOKED_mul;
float m = texelFetch(HOOKED_raw, sp + ivec2(-1, 2), 0).r * HOOKED_mul;
float p = texelFetch(HOOKED_raw, sp + ivec2( 2, 2), 0).r * HOOKED_mul;
#endif
float b = texelFetch(HOOKED_raw, sp + ivec2( 0, -1), 0).r * HOOKED_mul;
float e = texelFetch(HOOKED_raw, sp + ivec2(-1, 0), 0).r * HOOKED_mul;
float f = texelFetch(HOOKED_raw, sp , 0).r * HOOKED_mul;
float c = texelFetch(HOOKED_raw, sp + ivec2( 1, -1), 0).r * HOOKED_mul;
float g = texelFetch(HOOKED_raw, sp + ivec2( 1, 0), 0).r * HOOKED_mul;
float h = texelFetch(HOOKED_raw, sp + ivec2( 2, 0), 0).r * HOOKED_mul;
float i = texelFetch(HOOKED_raw, sp + ivec2(-1, 1), 0).r * HOOKED_mul;
float j = texelFetch(HOOKED_raw, sp + ivec2( 0, 1), 0).r * HOOKED_mul;
float n = texelFetch(HOOKED_raw, sp + ivec2( 0, 2), 0).r * HOOKED_mul;
float k = texelFetch(HOOKED_raw, sp + ivec2( 1, 1), 0).r * HOOKED_mul;
float l = texelFetch(HOOKED_raw, sp + ivec2( 2, 1), 0).r * HOOKED_mul;
float o = texelFetch(HOOKED_raw, sp + ivec2( 1, 2), 0).r * HOOKED_mul;
#endif
// Soft min and max.
// These are 2.0x bigger (factored out the extra multiply).
// a b c b
// e f g * 0.5 + e f g * 0.5 [F]
// i j k j
float mnfL = min(min(b, min(e, f)), min(g, j));
float mxfL = max(max(b, max(e, f)), max(g, j));
#if (CAS_BETTER_DIAGONALS == 1)
float mnfL2 = min(min(mnfL, min(a, c)), min(i, k));
mnfL += mnfL2;
float mxfL2 = max(max(mxfL, max(a, c)), max(i, k));
mxfL += mxfL2;
#endif
// b c d c
// f g h * 0.5 + f g h * 0.5 [G]
// j k l k
float mngL = min(min(c, min(f, g)), min(h, k));
float mxgL = max(max(c, max(f, g)), max(h, k));
#if (CAS_BETTER_DIAGONALS == 1)
float mngL2 = min(min(mngL, min(b, d)), min(j, l));
mngL += mngL2;
float mxgL2 = max(max(mxgL, max(b, d)), max(j, l));
mxgL += mxgL2;
#endif
// e f g f
// i j k * 0.5 + i j k * 0.5 [J]
// m n o n
float mnjL = min(min(f, min(i, j)), min(k, n));
float mxjL = max(max(f, max(i, j)), max(k, n));
#if (CAS_BETTER_DIAGONALS == 1)
float mnjL2 = min(min(mnjL, min(e, g)), min(m, o));
mnjL += mnjL2;
float mxjL2 = max(max(mxjL, max(e, g)), max(m, o));
mxjL += mxjL2;
#endif
// f g h g
// j k l * 0.5 + j k l * 0.5 [K]
// n o p o
float mnkL = min(min(g, min(j, k)), min(l, o));
float mxkL = max(max(g, max(j, k)), max(l, o));
#if (CAS_BETTER_DIAGONALS == 1)
float mnkL2 = min(min(mnkL, min(f, h)), min(n, p));
mnkL += mnkL2;
float mxkL2 = max(max(mxkL, max(f, h)), max(n, p));
mxkL += mxkL2;
#endif
// Smooth minimum distance to signal limit divided by smooth max.
const float bdval = bool(CAS_BETTER_DIAGONALS) ? 2.0 : 1.0;
#if (CAS_GO_SLOWER == 1)
float ampfL = clamp(min(mnfL, bdval - mxfL) / mxfL, 0.0, 1.0);
float ampgL = clamp(min(mngL, bdval - mxgL) / mxgL, 0.0, 1.0);
float ampjL = clamp(min(mnjL, bdval - mxjL) / mxjL, 0.0, 1.0);
float ampkL = clamp(min(mnkL, bdval - mxkL) / mxkL, 0.0, 1.0);
#else
float ampfL = clamp(min(mnfL, bdval - mxfL) * APrxLoRcpF1(mxfL), 0.0, 1.0);
float ampgL = clamp(min(mngL, bdval - mxgL) * APrxLoRcpF1(mxgL), 0.0, 1.0);
float ampjL = clamp(min(mnjL, bdval - mxjL) * APrxLoRcpF1(mxjL), 0.0, 1.0);
float ampkL = clamp(min(mnkL, bdval - mxkL) * APrxLoRcpF1(mxkL), 0.0, 1.0);
#endif
// Shaping amount of sharpening.
#if (CAS_GO_SLOWER == 1)
ampfL = sqrt(ampfL);
ampgL = sqrt(ampgL);
ampjL = sqrt(ampjL);
ampkL = sqrt(ampkL);
#else
ampfL = APrxLoSqrtF1(ampfL);
ampgL = APrxLoSqrtF1(ampgL);
ampjL = APrxLoSqrtF1(ampjL);
ampkL = APrxLoSqrtF1(ampkL);
#endif
// Filter shape.
// 0 w 0
// w 1 w
// 0 w 0
const float peak = -(mix(8.0, 5.0, clamp(SHARPENING, 0.0, 1.0)));
float wfL = ampfL / peak;
float wgL = ampgL / peak;
float wjL = ampjL / peak;
float wkL = ampkL / peak;
// Blend between 4 results.
// s t
// u v
float s = (1.0 - pp.x) * (1.0 - pp.y);
float t = pp.x * (1.0 - pp.y);
float u = (1.0 - pp.x) * pp.y;
float v = pp.x * pp.y;
// Thin edges to hide bilinear interpolation (helps diagonals).
const float thinB = 0.03125; // 1.0 / 32.0
#if (CAS_GO_SLOWER == 1)
s /= thinB + mxfL - mnfL;
t /= thinB + mxgL - mngL;
u /= thinB + mxjL - mnjL;
v /= thinB + mxkL - mnkL;
#else
s *= APrxLoRcpF1(thinB + mxfL - mnfL);
t *= APrxLoRcpF1(thinB + mxgL - mngL);
u *= APrxLoRcpF1(thinB + mxjL - mnjL);
v *= APrxLoRcpF1(thinB + mxkL - mnkL);
#endif
// Final weighting.
// b c
// e f g h
// i j k l
// n o
// _____ _____ _____ _____
// fs gt
//
// _____ _____ _____ _____
// fs s gt fs t gt
// ju kv
// _____ _____ _____ _____
// fs gt
// ju u kv ju v kv
// _____ _____ _____ _____
//
// ju kv
float qbeL = wfL * s;
float qchL = wgL * t;
float qfL = wgL * t + wjL * u + s;
float qgL = wfL * s + wkL * v + t;
float qjL = wfL * s + wkL * v + u;
float qkL = wgL * t + wjL * u + v;
float qinL = wjL * u;
float qloL = wkL * v;
// Filter.
vec4 pix = vec4(0.0, 0.0, 0.0, 1.0);
float W = 2.0 * qbeL + 2.0 * qchL + 2.0 * qinL + 2.0 * qloL + qfL + qgL + qjL + qkL;
pix.r = b * qbeL + e * qbeL + c * qchL + h * qchL + i * qinL + n * qinL + l * qloL + o * qloL + f * qfL + g * qgL + j * qjL + k * qkL;
#if (CAS_GO_SLOWER == 1)
pix.r /= W;
#else
pix.r *= APrxMedRcpF1(W);
#endif
pix.r = clamp(pix.r, 0.0, 1.0);
#if (TARGET_TRC == 1)
pix.r = To709(pix.r);
#elif (TARGET_TRC == 2)
pix.r = ToPq(pix.r);
#elif (TARGET_TRC == 3)
pix.r = ToSrgb(pix.r);
#elif (TARGET_TRC == 4)
pix.r = pow(pix.r, float(1.0 / 2.4));
#elif (TARGET_TRC == 5)
pix.r = ToHlg(pix.r);
#elif (TARGET_TRC == 6)
pix.r = pow(pix.r, float(1.0 / CUSTOM_GAMMA));
#endif
return pix;
}

View File

@@ -0,0 +1,453 @@
// Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// FidelityFX FSR v1.0.2 by AMD
// ported to mpv by agyild
// Changelog
// Made it compatible with pre-OpenGL 4.0 renderers
// Made it directly operate on LUMA plane, since the original shader was operating on LUMA by deriving it from RGB. This should cause a major increase in performance, especially on OpenGL 4.0+ renderers (4+2 texture lookups vs. 12+5)
// Removed transparency preservation mechanism since the alpha channel is a separate source plane than LUMA
// Added optional performance-saving lossy optimizations to EASU (Credit: atyuwen, https://atyuwen.github.io/posts/optimizing-fsr/)
//
// Notes
// Per AMD's guidelines only upscales content up to 4x (e.g., 1080p -> 2160p, 720p -> 1440p etc.) and everything else in between,
// that means FSR will scale up to 4x at maximum, and any further scaling will be processed by mpv's scalers
//!HOOK LUMA
//!BIND HOOKED
//!SAVE EASUTEX
//!DESC FidelityFX Super Resolution v1.0.2 (EASU)
//!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 >
//!WIDTH OUTPUT.w OUTPUT.w LUMA.w 2 * < * LUMA.w 2 * OUTPUT.w LUMA.w 2 * > * + OUTPUT.w OUTPUT.w LUMA.w 2 * = * +
//!HEIGHT OUTPUT.h OUTPUT.h LUMA.h 2 * < * LUMA.h 2 * OUTPUT.h LUMA.h 2 * > * + OUTPUT.h OUTPUT.h LUMA.h 2 * = * +
//!COMPONENTS 1
// User variables - EASU
#define FSR_PQ 0 // Whether the source content has PQ gamma or not. Needs to be set to the same value for both passes. 0 or 1.
#define FSR_EASU_DERING 1 // If set to 0, disables deringing for a small increase in performance. 0 or 1.
#define FSR_EASU_SIMPLE_ANALYSIS 0 // If set to 1, uses a simpler single-pass direction and length analysis for an increase in performance. 0 or 1.
#define FSR_EASU_QUIT_EARLY 0 // If set to 1, uses bilinear filtering for non-edge pixels and skips EASU on those regions for an increase in performance. 0 or 1.
// Shader code
#ifndef FSR_EASU_DIR_THRESHOLD
#if (FSR_EASU_QUIT_EARLY == 1)
#define FSR_EASU_DIR_THRESHOLD 64.0
#elif (FSR_EASU_QUIT_EARLY == 0)
#define FSR_EASU_DIR_THRESHOLD 32768.0
#endif
#endif
float APrxLoRcpF1(float a) {
return uintBitsToFloat(uint(0x7ef07ebb) - floatBitsToUint(a));
}
float APrxLoRsqF1(float a) {
return uintBitsToFloat(uint(0x5f347d74) - (floatBitsToUint(a) >> uint(1)));
}
float AMin3F1(float x, float y, float z) {
return min(x, min(y, z));
}
float AMax3F1(float x, float y, float z) {
return max(x, max(y, z));
}
#if (FSR_PQ == 1)
float ToGamma2(float a) {
return pow(a, 4.0);
}
#endif
// Filtering for a given tap for the scalar.
void FsrEasuTap(
inout float aC, // Accumulated color, with negative lobe.
inout float aW, // Accumulated weight.
vec2 off, // Pixel offset from resolve position to tap.
vec2 dir, // Gradient direction.
vec2 len, // Length.
float lob, // Negative lobe strength.
float clp, // Clipping point.
float c){ // Tap color.
// Rotate offset by direction.
vec2 v;
v.x = (off.x * ( dir.x)) + (off.y * dir.y);
v.y = (off.x * (-dir.y)) + (off.y * dir.x);
// Anisotropy.
v *= len;
// Compute distance^2.
float d2 = v.x * v.x + v.y * v.y;
// Limit to the window as at corner, 2 taps can easily be outside.
d2 = min(d2, clp);
// Approximation of lancos2 without sin() or rcp(), or sqrt() to get x.
// (25/16 * (2/5 * x^2 - 1)^2 - (25/16 - 1)) * (1/4 * x^2 - 1)^2
// |_______________________________________| |_______________|
// base window
// The general form of the 'base' is,
// (a*(b*x^2-1)^2-(a-1))
// Where 'a=1/(2*b-b^2)' and 'b' moves around the negative lobe.
float wB = float(2.0 / 5.0) * d2 + -1.0;
float wA = lob * d2 + -1.0;
wB *= wB;
wA *= wA;
wB = float(25.0 / 16.0) * wB + float(-(25.0 / 16.0 - 1.0));
float w = wB * wA;
// Do weighted average.
aC += c * w;
aW += w;
}
// Accumulate direction and length.
void FsrEasuSet(
inout vec2 dir,
inout float len,
vec2 pp,
#if (FSR_EASU_SIMPLE_ANALYSIS == 1)
float b, float c,
float i, float j, float f, float e,
float k, float l, float h, float g,
float o, float n
#elif (FSR_EASU_SIMPLE_ANALYSIS == 0)
bool biS, bool biT, bool biU, bool biV,
float lA, float lB, float lC, float lD, float lE
#endif
){
// Compute bilinear weight, branches factor out as predicates are compiler time immediates.
// s t
// u v
#if (FSR_EASU_SIMPLE_ANALYSIS == 1)
vec4 w = vec4(0.0);
w.x = (1.0 - pp.x) * (1.0 - pp.y);
w.y = pp.x * (1.0 - pp.y);
w.z = (1.0 - pp.x) * pp.y;
w.w = pp.x * pp.y;
float lA = dot(w, vec4(b, c, f, g));
float lB = dot(w, vec4(e, f, i, j));
float lC = dot(w, vec4(f, g, j, k));
float lD = dot(w, vec4(g, h, k, l));
float lE = dot(w, vec4(j, k, n, o));
#elif (FSR_EASU_SIMPLE_ANALYSIS == 0)
float w = 0.0;
if (biS)
w = (1.0 - pp.x) * (1.0 - pp.y);
if (biT)
w = pp.x * (1.0 - pp.y);
if (biU)
w = (1.0 - pp.x) * pp.y;
if (biV)
w = pp.x * pp.y;
#endif
// Direction is the '+' diff.
// a
// b c d
// e
// Then takes magnitude from abs average of both sides of 'c'.
// Length converts gradient reversal to 0, smoothly to non-reversal at 1, shaped, then adding horz and vert terms.
float dc = lD - lC;
float cb = lC - lB;
float lenX = max(abs(dc), abs(cb));
lenX = APrxLoRcpF1(lenX);
float dirX = lD - lB;
lenX = clamp(abs(dirX) * lenX, 0.0, 1.0);
lenX *= lenX;
// Repeat for the y axis.
float ec = lE - lC;
float ca = lC - lA;
float lenY = max(abs(ec), abs(ca));
lenY = APrxLoRcpF1(lenY);
float dirY = lE - lA;
lenY = clamp(abs(dirY) * lenY, 0.0, 1.0);
lenY *= lenY;
#if (FSR_EASU_SIMPLE_ANALYSIS == 1)
len = lenX + lenY;
dir = vec2(dirX, dirY);
#elif (FSR_EASU_SIMPLE_ANALYSIS == 0)
dir += vec2(dirX, dirY) * w;
len += dot(vec2(w), vec2(lenX, lenY));
#endif
}
vec4 hook() {
// Result
vec4 pix = vec4(0.0, 0.0, 0.0, 1.0);
//------------------------------------------------------------------------------------------------------------------------------
// +---+---+
// | | |
// +--(0)--+
// | b | c |
// +---F---+---+---+
// | e | f | g | h |
// +--(1)--+--(2)--+
// | i | j | k | l |
// +---+---+---+---+
// | n | o |
// +--(3)--+
// | | |
// +---+---+
// Get position of 'F'.
vec2 pp = HOOKED_pos * HOOKED_size - vec2(0.5);
vec2 fp = floor(pp);
pp -= fp;
//------------------------------------------------------------------------------------------------------------------------------
// 12-tap kernel.
// b c
// e f g h
// i j k l
// n o
// Gather 4 ordering.
// a b
// r g
// Allowing dead-code removal to remove the 'z's.
#if (defined(HOOKED_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310)))
vec4 bczzL = HOOKED_gather(vec2((fp + vec2(1.0, -1.0)) * HOOKED_pt), 0);
vec4 ijfeL = HOOKED_gather(vec2((fp + vec2(0.0, 1.0)) * HOOKED_pt), 0);
vec4 klhgL = HOOKED_gather(vec2((fp + vec2(2.0, 1.0)) * HOOKED_pt), 0);
vec4 zzonL = HOOKED_gather(vec2((fp + vec2(1.0, 3.0)) * HOOKED_pt), 0);
#else
// pre-OpenGL 4.0 compatibility
float b = HOOKED_tex(vec2((fp + vec2(0.5, -0.5)) * HOOKED_pt)).r;
float c = HOOKED_tex(vec2((fp + vec2(1.5, -0.5)) * HOOKED_pt)).r;
float e = HOOKED_tex(vec2((fp + vec2(-0.5, 0.5)) * HOOKED_pt)).r;
float f = HOOKED_tex(vec2((fp + vec2( 0.5, 0.5)) * HOOKED_pt)).r;
float g = HOOKED_tex(vec2((fp + vec2( 1.5, 0.5)) * HOOKED_pt)).r;
float h = HOOKED_tex(vec2((fp + vec2( 2.5, 0.5)) * HOOKED_pt)).r;
float i = HOOKED_tex(vec2((fp + vec2(-0.5, 1.5)) * HOOKED_pt)).r;
float j = HOOKED_tex(vec2((fp + vec2( 0.5, 1.5)) * HOOKED_pt)).r;
float k = HOOKED_tex(vec2((fp + vec2( 1.5, 1.5)) * HOOKED_pt)).r;
float l = HOOKED_tex(vec2((fp + vec2( 2.5, 1.5)) * HOOKED_pt)).r;
float n = HOOKED_tex(vec2((fp + vec2(0.5, 2.5) ) * HOOKED_pt)).r;
float o = HOOKED_tex(vec2((fp + vec2(1.5, 2.5) ) * HOOKED_pt)).r;
vec4 bczzL = vec4(b, c, 0.0, 0.0);
vec4 ijfeL = vec4(i, j, f, e);
vec4 klhgL = vec4(k, l, h, g);
vec4 zzonL = vec4(0.0, 0.0, o, n);
#endif
//------------------------------------------------------------------------------------------------------------------------------
// Rename.
float bL = bczzL.x;
float cL = bczzL.y;
float iL = ijfeL.x;
float jL = ijfeL.y;
float fL = ijfeL.z;
float eL = ijfeL.w;
float kL = klhgL.x;
float lL = klhgL.y;
float hL = klhgL.z;
float gL = klhgL.w;
float oL = zzonL.z;
float nL = zzonL.w;
#if (FSR_PQ == 1)
// Not the most performance-friendly solution, but should work until mpv adds proper gamma transformation functions for shaders
bL = ToGamma2(bL);
cL = ToGamma2(cL);
iL = ToGamma2(iL);
jL = ToGamma2(jL);
fL = ToGamma2(fL);
eL = ToGamma2(eL);
kL = ToGamma2(kL);
lL = ToGamma2(lL);
hL = ToGamma2(hL);
gL = ToGamma2(gL);
oL = ToGamma2(oL);
nL = ToGamma2(nL);
#endif
// Accumulate for bilinear interpolation.
vec2 dir = vec2(0.0);
float len = 0.0;
#if (FSR_EASU_SIMPLE_ANALYSIS == 1)
FsrEasuSet(dir, len, pp, bL, cL, iL, jL, fL, eL, kL, lL, hL, gL, oL, nL);
#elif (FSR_EASU_SIMPLE_ANALYSIS == 0)
FsrEasuSet(dir, len, pp, true, false, false, false, bL, eL, fL, gL, jL);
FsrEasuSet(dir, len, pp, false, true, false, false, cL, fL, gL, hL, kL);
FsrEasuSet(dir, len, pp, false, false, true, false, fL, iL, jL, kL, nL);
FsrEasuSet(dir, len, pp, false, false, false, true, gL, jL, kL, lL, oL);
#endif
//------------------------------------------------------------------------------------------------------------------------------
// Normalize with approximation, and cleanup close to zero.
vec2 dir2 = dir * dir;
float dirR = dir2.x + dir2.y;
bool zro = dirR < float(1.0 / FSR_EASU_DIR_THRESHOLD);
dirR = APrxLoRsqF1(dirR);
#if (FSR_EASU_QUIT_EARLY == 1)
if (zro) {
vec4 w = vec4(0.0);
w.x = (1.0 - pp.x) * (1.0 - pp.y);
w.y = pp.x * (1.0 - pp.y);
w.z = (1.0 - pp.x) * pp.y;
w.w = pp.x * pp.y;
pix.r = clamp(dot(w, vec4(fL, gL, jL, kL)), 0.0, 1.0);
return pix;
}
#elif (FSR_EASU_QUIT_EARLY == 0)
dirR = zro ? 1.0 : dirR;
dir.x = zro ? 1.0 : dir.x;
#endif
dir *= vec2(dirR);
// Transform from {0 to 2} to {0 to 1} range, and shape with square.
len = len * 0.5;
len *= len;
// Stretch kernel {1.0 vert|horz, to sqrt(2.0) on diagonal}.
float stretch = (dir.x * dir.x + dir.y * dir.y) * APrxLoRcpF1(max(abs(dir.x), abs(dir.y)));
// Anisotropic length after rotation,
// x := 1.0 lerp to 'stretch' on edges
// y := 1.0 lerp to 2x on edges
vec2 len2 = vec2(1.0 + (stretch - 1.0) * len, 1.0 + -0.5 * len);
// Based on the amount of 'edge',
// the window shifts from +/-{sqrt(2.0) to slightly beyond 2.0}.
float lob = 0.5 + float((1.0 / 4.0 - 0.04) - 0.5) * len;
// Set distance^2 clipping point to the end of the adjustable window.
float clp = APrxLoRcpF1(lob);
//------------------------------------------------------------------------------------------------------------------------------
// Accumulation
// b c
// e f g h
// i j k l
// n o
float aC = 0.0;
float aW = 0.0;
FsrEasuTap(aC, aW, vec2( 0.0,-1.0) - pp, dir, len2, lob, clp, bL); // b
FsrEasuTap(aC, aW, vec2( 1.0,-1.0) - pp, dir, len2, lob, clp, cL); // c
FsrEasuTap(aC, aW, vec2(-1.0, 1.0) - pp, dir, len2, lob, clp, iL); // i
FsrEasuTap(aC, aW, vec2( 0.0, 1.0) - pp, dir, len2, lob, clp, jL); // j
FsrEasuTap(aC, aW, vec2( 0.0, 0.0) - pp, dir, len2, lob, clp, fL); // f
FsrEasuTap(aC, aW, vec2(-1.0, 0.0) - pp, dir, len2, lob, clp, eL); // e
FsrEasuTap(aC, aW, vec2( 1.0, 1.0) - pp, dir, len2, lob, clp, kL); // k
FsrEasuTap(aC, aW, vec2( 2.0, 1.0) - pp, dir, len2, lob, clp, lL); // l
FsrEasuTap(aC, aW, vec2( 2.0, 0.0) - pp, dir, len2, lob, clp, hL); // h
FsrEasuTap(aC, aW, vec2( 1.0, 0.0) - pp, dir, len2, lob, clp, gL); // g
FsrEasuTap(aC, aW, vec2( 1.0, 2.0) - pp, dir, len2, lob, clp, oL); // o
FsrEasuTap(aC, aW, vec2( 0.0, 2.0) - pp, dir, len2, lob, clp, nL); // n
//------------------------------------------------------------------------------------------------------------------------------
// Normalize and dering.
pix.r = aC / aW;
#if (FSR_EASU_DERING == 1)
float min1 = min(AMin3F1(fL, gL, jL), kL);
float max1 = max(AMax3F1(fL, gL, jL), kL);
pix.r = clamp(pix.r, min1, max1);
#endif
pix.r = clamp(pix.r, 0.0, 1.0);
return pix;
}
//!HOOK LUMA
//!BIND EASUTEX
//!DESC FidelityFX Super Resolution v1.0.2 (RCAS)
//!WIDTH EASUTEX.w
//!HEIGHT EASUTEX.h
//!COMPONENTS 1
// User variables - RCAS
#define SHARPNESS 0.2 // Controls the amount of sharpening. The scale is {0.0 := maximum, to N>0, where N is the number of stops (halving) of the reduction of sharpness}. 0.0 to 2.0.
#define FSR_RCAS_DENOISE 1 // If set to 1, lessens the sharpening on noisy areas. Can be disabled for better performance. 0 or 1.
#define FSR_PQ 0 // Whether the source content has PQ gamma or not. Needs to be set to the same value for both passes. 0 or 1.
// Shader code
#define FSR_RCAS_LIMIT (0.25 - (1.0 / 16.0)) // This is set at the limit of providing unnatural results for sharpening.
float APrxMedRcpF1(float a) {
float b = uintBitsToFloat(uint(0x7ef19fff) - floatBitsToUint(a));
return b * (-b * a + 2.0);
}
float AMax3F1(float x, float y, float z) {
return max(x, max(y, z));
}
float AMin3F1(float x, float y, float z) {
return min(x, min(y, z));
}
#if (FSR_PQ == 1)
float FromGamma2(float a) {
return sqrt(sqrt(a));
}
#endif
vec4 hook() {
// Algorithm uses minimal 3x3 pixel neighborhood.
// b
// d e f
// h
#if (defined(EASUTEX_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310)))
vec3 bde = EASUTEX_gather(EASUTEX_pos + EASUTEX_pt * vec2(-0.5), 0).xyz;
float b = bde.z;
float d = bde.x;
float e = bde.y;
vec2 fh = EASUTEX_gather(EASUTEX_pos + EASUTEX_pt * vec2(0.5), 0).zx;
float f = fh.x;
float h = fh.y;
#else
float b = EASUTEX_texOff(vec2( 0.0, -1.0)).r;
float d = EASUTEX_texOff(vec2(-1.0, 0.0)).r;
float e = EASUTEX_tex(EASUTEX_pos).r;
float f = EASUTEX_texOff(vec2(1.0, 0.0)).r;
float h = EASUTEX_texOff(vec2(0.0, 1.0)).r;
#endif
// Min and max of ring.
float mn1L = min(AMin3F1(b, d, f), h);
float mx1L = max(AMax3F1(b, d, f), h);
// Immediate constants for peak range.
vec2 peakC = vec2(1.0, -1.0 * 4.0);
// Limiters, these need to be high precision RCPs.
float hitMinL = min(mn1L, e) / (4.0 * mx1L);
float hitMaxL = (peakC.x - max(mx1L, e)) / (4.0 * mn1L + peakC.y);
float lobeL = max(-hitMinL, hitMaxL);
float lobe = max(float(-FSR_RCAS_LIMIT), min(lobeL, 0.0)) * exp2(-clamp(float(SHARPNESS), 0.0, 2.0));
// Apply noise removal.
#if (FSR_RCAS_DENOISE == 1)
// Noise detection.
float nz = 0.25 * b + 0.25 * d + 0.25 * f + 0.25 * h - e;
nz = clamp(abs(nz) * APrxMedRcpF1(AMax3F1(AMax3F1(b, d, e), f, h) - AMin3F1(AMin3F1(b, d, e), f, h)), 0.0, 1.0);
nz = -0.5 * nz + 1.0;
lobe *= nz;
#endif
// Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes.
float rcpL = APrxMedRcpF1(4.0 * lobe + 1.0);
vec4 pix = vec4(0.0, 0.0, 0.0, 1.0);
pix.r = float((lobe * b + lobe * d + lobe * h + lobe * f + e) * rcpL);
#if (FSR_PQ == 1)
pix.r = FromGamma2(pix.r);
#endif
return pix;
}

View File

@@ -0,0 +1,426 @@
// Copyright (C) 2017-2021 igv
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3.0 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program. If not, see <https://www.gnu.org/licenses/>.
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC feature map 1
//!BIND LUMA
//!SAVE FEATURE1
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.1572492271661758,-0.0120896836742759,0.0061487639322877,-0.2852848768234253);
res += vec4(-0.0047900392673910,0.0537447109818459,-0.0000247144635068,0.0066653941757977) * float(LUMA_texOff(vec2(-2,-2)));
res += vec4(0.0073144687339664,-0.0309004038572311,-0.0109181385487318,-0.0092840325087309) * float(LUMA_texOff(vec2(-2,-1)));
res += vec4(0.0591700896620750,0.1974907070398331,-0.0197357516735792,-0.0546554848551750) * float(LUMA_texOff(vec2(-2,0)));
res += vec4(-0.0011764382943511,-0.0299451071768999,0.0229587312787771,0.0021908886265010) * float(LUMA_texOff(vec2(-2,1)));
res += vec4(0.0098101310431957,0.0080995410680771,-0.0030452020000666,-0.0132035519927740) * float(LUMA_texOff(vec2(-2,2)));
res += vec4(-0.0168330334126949,-0.0743711441755295,-0.0259261634200811,0.0234480481594801) * float(LUMA_texOff(vec2(-1,-2)));
res += vec4(0.0239933785051107,0.1896541714668274,0.0207756329327822,-0.0370332375168800) * float(LUMA_texOff(vec2(-1,-1)));
res += vec4(0.0094799501821399,-0.0652511194348335,-0.0004292793164495,-0.0726212188601494) * float(LUMA_texOff(vec2(-1,0)));
res += vec4(0.0297284796833992,-0.1210186630487442,-0.0202929321676493,-0.0574462898075581) * float(LUMA_texOff(vec2(-1,1)));
res += vec4(-0.0318185277283192,0.0840775370597839,0.0110451309010386,0.0415569432079792) * float(LUMA_texOff(vec2(-1,2)));
res += vec4(-0.0253141783177853,0.1168256178498268,0.1159729585051537,0.0963164269924164) * float(LUMA_texOff(vec2(0,-2)));
res += vec4(-0.1103615835309029,-0.0276833958923817,-0.4999594092369080,0.1053867191076279) * float(LUMA_texOff(vec2(0,-1)));
res += vec4(1.1100435256958008,0.0646764487028122,0.0154005717486143,0.8891586661338806) * float(LUMA_texOff(vec2(0,0)));
res += vec4(0.1229330673813820,0.1719468832015991,0.5730338096618652,-0.1645544171333313) * float(LUMA_texOff(vec2(0,1)));
res += vec4(-0.0090442728251219,-0.3023961782455444,-0.1589493155479431,0.0418574027717113) * float(LUMA_texOff(vec2(0,2)));
res += vec4(0.0031942036002874,-0.1310926079750061,0.0075543406419456,-0.0016449346439913) * float(LUMA_texOff(vec2(1,-2)));
res += vec4(-0.0995150282979012,-0.0701921209692955,-0.0130895879119635,0.1344170123338699) * float(LUMA_texOff(vec2(1,-1)));
res += vec4(0.0060519003309309,-0.1533465683460236,0.0114194005727768,0.0264683905988932) * float(LUMA_texOff(vec2(1,0)));
res += vec4(0.0244008023291826,0.1881769001483917,-0.0206351149827242,-0.0628309547901154) * float(LUMA_texOff(vec2(1,1)));
res += vec4(0.0075713125988841,0.0508594363927841,0.0430423170328140,-0.0124188791960478) * float(LUMA_texOff(vec2(1,2)));
res += vec4(-0.0166875869035721,-0.0047865519300103,0.0006719123339280,0.0316803231835365) * float(LUMA_texOff(vec2(2,-2)));
res += vec4(-0.0058461269363761,0.0990798473358154,-0.0177743826061487,-0.0066122291609645) * float(LUMA_texOff(vec2(2,-1)));
res += vec4(-0.0972401946783066,-0.0225446373224258,-0.0037693574558944,0.1953062713146210) * float(LUMA_texOff(vec2(2,0)));
res += vec4(-0.0216837190091610,-0.1824268400669098,0.0069816261529922,0.0283037684857845) * float(LUMA_texOff(vec2(2,1)));
res += vec4(-0.0025767991319299,0.0459827110171318,-0.0080216089263558,0.0084134787321091) * float(LUMA_texOff(vec2(2,2)));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC feature map 2
//!BIND LUMA
//!SAVE FEATURE2
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(0.0541447550058365,0.0088306749239564,-0.0112389577552676,-0.0127860950306058);
res += vec4(0.0142660010606050,0.0137931071221828,0.0061188107356429,-0.0104134222492576) * float(LUMA_texOff(vec2(-2,-2)));
res += vec4(0.0147292809560895,-0.0289912857115269,0.0266769435256720,0.0933856964111328) * float(LUMA_texOff(vec2(-2,-1)));
res += vec4(-0.1734338253736496,0.1116316691040993,-0.1973157376050949,-0.0581855811178684) * float(LUMA_texOff(vec2(-2,0)));
res += vec4(0.0347507223486900,-0.0341566652059555,0.0061667622067034,0.0075258882716298) * float(LUMA_texOff(vec2(-2,1)));
res += vec4(0.0069884369149804,-0.0194250214844942,0.0080830128863454,-0.0036874092184007) * float(LUMA_texOff(vec2(-2,2)));
res += vec4(0.0233764201402664,0.0344744995236397,0.0162145942449570,0.0979529991745949) * float(LUMA_texOff(vec2(-1,-2)));
res += vec4(0.1280796974897385,-0.1018339172005653,-0.0132977198809385,-0.0019474622095004) * float(LUMA_texOff(vec2(-1,-1)));
res += vec4(0.4286882579326630,0.1222677752375603,0.7046694159507751,0.0945475697517395) * float(LUMA_texOff(vec2(-1,0)));
res += vec4(0.1107441782951355,-0.0134433070197701,-0.0174900908023119,-0.1686445474624634) * float(LUMA_texOff(vec2(-1,1)));
res += vec4(0.0321478620171547,0.0065357843413949,0.0300805997103453,0.0420113280415535) * float(LUMA_texOff(vec2(-1,2)));
res += vec4(-0.1240341588854790,0.0950303301215172,-0.0129648456349969,-0.2681856453418732) * float(LUMA_texOff(vec2(0,-2)));
res += vec4(0.4846960902214050,0.0351924635469913,0.0223043337464333,-0.1273630708456039) * float(LUMA_texOff(vec2(0,-1)));
res += vec4(-1.9379507303237915,-0.2444442063570023,0.0291962660849094,-0.3835578560829163) * float(LUMA_texOff(vec2(0,0)));
res += vec4(0.6396278142929077,-0.0765938311815262,-0.0552659817039967,0.4393545985221863) * float(LUMA_texOff(vec2(0,1)));
res += vec4(-0.1969728022813797,-0.0607173256576061,0.0131113547831774,0.0542017817497253) * float(LUMA_texOff(vec2(0,2)));
res += vec4(0.0091696009039879,-0.0031533432193100,-0.0368777588009834,-0.0459998287260532) * float(LUMA_texOff(vec2(1,-2)));
res += vec4(0.1096992492675781,0.2597902715206146,0.0304869692772627,-0.0195200722664595) * float(LUMA_texOff(vec2(1,-1)));
res += vec4(0.2889648377895355,-0.4275591969490051,-0.7414156794548035,0.2695442438125610) * float(LUMA_texOff(vec2(1,0)));
res += vec4(0.0892018377780914,-0.0229137558490038,0.0244414471089840,-0.1926898956298828) * float(LUMA_texOff(vec2(1,1)));
res += vec4(0.0576358586549759,0.0027846973389387,-0.0036861505359411,-0.0253547113388777) * float(LUMA_texOff(vec2(1,2)));
res += vec4(0.0159624069929123,0.0319602824747562,0.0019470085389912,0.0089780492708087) * float(LUMA_texOff(vec2(2,-2)));
res += vec4(0.0552792511880398,0.0543054342269897,0.0134062822908163,0.0545728243887424) * float(LUMA_texOff(vec2(2,-1)));
res += vec4(-0.1170092225074768,0.1963327825069427,0.1503890156745911,0.1891828328371048) * float(LUMA_texOff(vec2(2,0)));
res += vec4(-0.0084421783685684,0.1297017931938171,-0.0330600887537003,-0.0942063704133034) * float(LUMA_texOff(vec2(2,1)));
res += vec4(0.0118440408259630,-0.0337875857949257,0.0055063469335437,0.0254479162395000) * float(LUMA_texOff(vec2(2,2)));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 1_1
//!BIND FEATURE1
//!BIND FEATURE2
//!SAVE MODEL21
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.0445119962096214,-0.7632357478141785,0.0156328510493040,-0.2424548566341400);
res += mat4(0.1279004216194153,-0.0275541823357344,0.2275633513927460,0.2241709381341934,0.0197204202413559,-0.0456816256046295,-0.1296672523021698,0.0564568229019642,-0.0241488646715879,-0.0237508192658424,-0.1899632662534714,0.4177669584751129,-0.1814560592174530,-0.0526473335921764,0.1154382973909378,-0.0715614855289459) * FEATURE1_texOff(vec2(-1,-1));
res += mat4(-0.0660311505198479,0.0416736751794815,0.3146112561225891,0.1472041457891464,-0.3456672728061676,-0.0055983816273510,0.0022350433282554,0.0819796621799469,0.0057485047727823,0.1532524228096008,0.0204557459801435,-0.2500547170639038,-0.0524359568953514,-0.1911625266075134,-0.1078366711735725,-0.1296254843473434) * FEATURE2_texOff(vec2(-1,-1));
res += mat4(0.0904538556933403,-0.0150672039017081,0.3322310745716095,0.0638923197984695,0.5975797176361084,-0.2452044337987900,-0.4947478473186493,-0.0783191770315170,0.5771877169609070,-0.0870653912425041,-0.8966570496559143,-0.2140965163707733,-0.0493861362338066,-0.0380848757922649,-0.1345319598913193,-0.0186063013970852) * FEATURE1_texOff(vec2(-1,0));
res += mat4(-0.2523841261863708,0.1387074738740921,0.7878478765487671,-0.2251627445220947,0.2277439534664154,0.5417668819427490,0.0866540968418121,-0.1707777529954910,-0.0598246827721596,-0.4717158675193787,-1.2242834568023682,0.0454643070697784,-0.3503442704677582,0.0573085807263851,0.2530198395252228,-0.0207283068448305) * FEATURE2_texOff(vec2(-1,0));
res += mat4(0.0168380383402109,-0.2142438590526581,-0.0207892972975969,0.3628533780574799,0.2431225180625916,0.3098322153091431,0.4073205888271332,-0.2762102782726288,-0.0197229012846947,0.1305596232414246,-0.5697882771492004,-0.2976251542568207,-0.0551432967185974,0.2614036500453949,-0.1410341411828995,-0.2906406223773956) * FEATURE1_texOff(vec2(-1,1));
res += mat4(-0.0498303361237049,0.0224859956651926,0.1952174901962280,-0.0311204437166452,0.2501715123653412,-0.5893352627754211,-1.0793941020965576,0.0160885509103537,0.5081620812416077,0.0482814386487007,0.0546359121799469,-0.0501569248735905,0.1400523334741592,-0.0106841633096337,-0.0940591320395470,-0.1791856139898300) * FEATURE2_texOff(vec2(-1,1));
res += mat4(0.0393299944698811,0.2232691347599030,-0.1055066883563995,-0.1607919186353683,-0.1567825973033905,-0.0042221010662615,-0.0548228211700916,0.2352052628993988,0.1483389288187027,0.7503526806831360,0.0797731876373291,-0.0049001369625330,-0.0242983382195234,-0.0308702979236841,0.0828925222158432,0.0561857633292675) * FEATURE1_texOff(vec2(0,-1));
res += mat4(0.0926392748951912,-0.0418718457221985,-0.3060409128665924,-0.1883587390184402,0.0284292586147785,-0.3584854304790497,-0.7909982800483704,-0.0187337957322598,-0.2496993243694305,-0.7520986795425415,0.3771523833274841,-0.0259053874760866,0.0337998159229755,0.2209153026342392,0.0708771497011185,-0.2814430892467499) * FEATURE2_texOff(vec2(0,-1));
res += mat4(-0.5287809371948242,0.5777525901794434,0.0880500450730324,-0.8452472090721130,-0.3393408954143524,-0.2273543328046799,-0.1298527419567108,0.4990308582782745,1.2613251209259033,-0.7636719942092896,1.5694186687469482,-0.4087363779544830,0.0874531939625740,0.7067158818244934,-0.3419588804244995,-0.3265531957149506) * FEATURE1_texOff(vec2(0,0));
res += mat4(0.8229957222938538,-0.1236215904355049,-0.1859253048896790,1.6684840917587280,0.2000777721405029,-0.1239093989133835,1.5623438358306885,0.1779983490705490,0.1017884835600853,-0.3707404434680939,1.0626678466796875,-0.3124029338359833,0.0659058541059494,-0.3585464656352997,-0.1866402775049210,0.6733445525169373) * FEATURE2_texOff(vec2(0,0));
res += mat4(-0.5544115900993347,-0.1892931908369064,0.2460739761590958,-0.1056193932890892,-0.4318082630634308,0.1257930994033813,-0.2672747671604156,-0.1690235435962677,0.0018221997888759,-0.4397548139095306,-0.3007801771163940,0.1068472340703011,0.3506655991077423,0.1143834441900253,0.1363849341869354,-0.1417382210493088) * FEATURE1_texOff(vec2(0,1));
res += mat4(-0.0505668744444847,0.1831464916467667,0.3957343697547913,-0.2295413911342621,-0.3892803490161896,0.5436951518058777,0.1217770799994469,0.0223295800387859,-0.4462866187095642,-0.4055982232093811,-0.3771279454231262,0.0807068347930908,0.2116729617118835,0.0281026475131512,-0.0229265503585339,0.2868605256080627) * FEATURE2_texOff(vec2(0,1));
res += mat4(0.1962712109088898,-0.2373334914445877,-2.5208437442779541,-0.1988540291786194,0.2224564403295517,-0.1783192902803421,-0.3962321281433105,-0.1685980409383774,0.1910390257835388,0.2554391324520111,0.4586416482925415,0.2779130041599274,-0.2002453953027725,-0.0061091855168343,1.3808131217956543,0.0434907525777817) * FEATURE1_texOff(vec2(1,-1));
res += mat4(-0.0307611189782619,-0.0524470545351505,-0.5897512435913086,-0.0816674903035164,0.4052906930446625,0.2542210817337036,-1.9041002988815308,0.0835462361574173,-0.2484460622072220,-0.0184739269316196,0.4510098397731781,0.2587619423866272,0.1537084281444550,0.1503131389617920,-0.0742949545383453,0.0613216012716293) * FEATURE2_texOff(vec2(1,-1));
res += mat4(0.1772638261318207,0.0948876664042473,0.0083848545327783,-0.2919732332229614,0.2566950321197510,0.0288751143962145,-0.4624863862991333,-0.0608786940574646,0.3310996592044830,-0.0104284398257732,0.6334818005561829,-0.0027201652992517,-0.0342350602149963,0.1938806027173996,-0.2464301586151123,0.0125883584842086) * FEATURE1_texOff(vec2(1,0));
res += mat4(0.4839433431625366,-0.0502159744501114,-1.1114163398742676,-0.3965759575366974,0.2117286175489426,0.0414481423795223,-0.1332397013902664,-0.0549883767962456,-0.1275007277727127,0.7844302654266357,-0.0095163453370333,0.0961041301488876,-0.4759134948253632,-0.4284025132656097,-0.2072399407625198,-0.3953579664230347) * FEATURE2_texOff(vec2(1,0));
res += mat4(0.1605869531631470,-0.1715892106294632,0.0865620598196983,-0.0464400537312031,-0.2688548862934113,0.1722514480352402,0.0167612321674824,-0.0032994034700096,-0.3451044559478760,-0.2280300110578537,-0.0029796555172652,-0.1597652435302734,0.0500137843191624,0.1023071259260178,-0.0407028235495090,0.2228624969720840) * FEATURE1_texOff(vec2(1,1));
res += mat4(0.6999920010566711,0.0839441940188408,0.0815469548106194,-0.1509176045656204,-0.0690853074193001,-0.3200871348381042,0.0780162736773491,-0.1449639797210693,0.2868815064430237,0.3962450027465820,-0.3439113497734070,0.2657423913478851,0.0988137871026993,0.3471299111843109,-0.2186402678489685,-0.0648017078638077) * FEATURE2_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(1.0311057567596436,0.1051208898425102,0.1158760935068130,0.0466635078191757) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 1_2
//!BIND FEATURE1
//!BIND FEATURE2
//!SAVE MODEL22
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(0.0713458731770515,-0.1403961777687073,-0.0019562745001167,0.0153338573873043);
res += mat4(-0.0950641855597496,-0.1496641039848328,-0.0653550028800964,0.0655386000871658,-0.0118882004171610,0.2012491524219513,-0.2844599783420563,-0.4794720113277435,0.1128025799989700,-0.0173030979931355,-0.0558849945664406,-0.2957552075386047,0.0128202112391591,0.0199047476053238,-0.0091027505695820,-0.0789640173316002) * FEATURE1_texOff(vec2(-1,-1));
res += mat4(0.1597457975149155,-0.0476507246494293,0.1466529071331024,0.0859163030982018,0.0797316282987595,-0.3380981683731079,0.2370245009660721,-0.1145931258797646,-0.0352988094091415,-0.0444888733327389,-0.2100716233253479,0.1305520236492157,-0.1359029710292816,0.1097442805767059,0.0449938289821148,-0.1155664771795273) * FEATURE2_texOff(vec2(-1,-1));
res += mat4(-0.0333916284143925,0.2415594160556793,0.0520512908697128,0.1228107511997223,-0.0491011217236519,0.4408806562423706,0.4631956815719604,0.2014560103416443,-0.3688595592975616,0.0367180295288563,0.2484581321477890,-0.1113442853093147,0.1283355057239532,0.0418004281818867,-0.0171243026852608,-0.1231943219900131) * FEATURE1_texOff(vec2(-1,0));
res += mat4(0.3493446409702301,0.4550022482872009,0.0368724688887596,0.0748724937438965,0.5001406073570251,0.0145555436611176,0.1236629858613014,0.3143120706081390,-0.1951988488435745,-0.0157914645969868,0.0937998965382576,-0.2233840376138687,0.5033411383628845,-0.3183194100856781,-0.2259195148944855,0.3639536798000336) * FEATURE2_texOff(vec2(-1,0));
res += mat4(-0.0742707476019859,-0.1287801116704941,-0.2533137500286102,0.0666435658931732,-0.0185621567070484,0.1427449285984039,-0.0724751204252243,-0.0781485065817833,-0.2270648330450058,-0.2314778864383698,0.3814929425716400,-0.1655400246381760,0.0408568829298019,-0.1139645278453827,0.1797397136688232,-0.0245632305741310) * FEATURE1_texOff(vec2(-1,1));
res += mat4(0.1184135973453522,0.0439366139471531,0.0225226897746325,-0.0038526873104274,0.1292685419321060,0.0629177838563919,0.3455114960670471,-0.1857204884290695,-0.4921502172946930,-0.1171003505587578,0.0188624169677496,-0.1101682260632515,0.0676844567060471,0.5154085755348206,-0.0898379907011986,0.3413280248641968) * FEATURE2_texOff(vec2(-1,1));
res += mat4(-0.2631838321685791,0.0215514600276947,0.3092688918113708,-0.0200904365628958,0.0678770467638969,0.1769931465387344,-0.3653681278228760,-0.3274513185024261,0.4608019888401031,-0.1544784456491470,0.1189439669251442,0.7015876173973083,0.2732816934585571,-0.0545057803392410,-0.3474545478820801,-0.0253226496279240) * FEATURE1_texOff(vec2(0,-1));
res += mat4(0.0994316861033440,0.0642566010355949,0.2031503319740295,0.2276959568262100,-0.1094077304005623,0.4463521838188171,0.0921792611479759,-0.3033096492290497,-0.0953373983502388,-0.1331395804882050,0.2615413069725037,-0.2874414622783661,-0.0389687754213810,0.0338272154331207,0.2804331183433533,-0.3443813025951385) * FEATURE2_texOff(vec2(0,-1));
res += mat4(-0.1806042939424515,-0.4840798676013947,0.4222546219825745,0.1238701492547989,0.0117481639608741,-0.5986865758895874,0.3057619929313660,0.1934896260499954,-0.7086342573165894,-0.8567376136779785,0.6944998502731323,-1.4599204063415527,0.0886754393577576,-0.4293498098850250,-0.1524195969104767,0.2418079674243927) * FEATURE1_texOff(vec2(0,0));
res += mat4(2.1706113815307617,0.3525652289390564,-0.7008359432220459,-0.4825965166091919,-0.3203429281711578,0.8500943183898926,-0.7993509769439697,0.4329842329025269,0.2106771767139435,1.1103280782699585,1.2092385292053223,1.4814503192901611,-0.4147390127182007,-0.7046836614608765,-0.1443170011043549,-0.6811133027076721) * FEATURE2_texOff(vec2(0,0));
res += mat4(-0.1489356607198715,0.1400019824504852,0.2425604313611984,-0.2098473459482193,-0.1580564379692078,0.1463224738836288,-0.2187854647636414,0.5174596905708313,-0.0143817225471139,-0.0362622961401939,-0.0068237944506109,0.4749472737312317,0.2914732992649078,-0.3306328952312469,-0.2444777786731720,-0.1171946674585342) * FEATURE1_texOff(vec2(0,1));
res += mat4(0.0455239675939083,0.3496046066284180,0.1297491937875748,-0.2541095912456512,0.3605501055717468,0.2339573651552200,-0.0188565086573362,-0.0526181310415268,0.1471424549818039,0.8212822079658508,0.0819099843502045,-0.0851665437221527,0.3739568293094635,0.1304695755243301,0.1481167376041412,-0.2134698331356049) * FEATURE2_texOff(vec2(0,1));
res += mat4(-0.2076720446348190,-0.0932599306106567,0.0648527294397354,-0.2374770641326904,-0.0927826911211014,0.1848200261592865,0.4131188094615936,0.3280069231987000,-0.2099185734987259,0.2130926996469498,-0.0362745784223080,0.0191331822425127,0.1590368449687958,0.0303016249090433,0.1207325309514999,0.2451425045728683) * FEATURE1_texOff(vec2(1,-1));
res += mat4(-0.0135009605437517,-0.0101303057745099,0.0752487555146217,0.0533373840153217,-0.0253537259995937,0.1318614929914474,-0.1263181120157242,0.0249524712562561,-0.1477261483669281,0.3236559033393860,0.0773291289806366,-0.1439673304557800,-0.2005890905857086,0.0892757251858711,0.0398719944059849,0.3675192892551422) * FEATURE2_texOff(vec2(1,-1));
res += mat4(-0.0193535499274731,-0.2256918102502823,0.0341436080634594,0.0795947611331940,0.1496857404708862,-0.2784725725650787,-0.0582313314080238,-0.2786065340042114,-0.1666128039360046,-0.6534121036529541,0.2695854306221008,-0.0179719906300306,0.0015976354479790,0.0139929885044694,-0.1706486046314240,-0.3274765610694885) * FEATURE1_texOff(vec2(1,0));
res += mat4(-0.7170836329460144,0.0868831276893616,0.1829078495502472,-0.0076045366004109,0.1525912433862686,-0.2558896839618683,0.0893209800124168,-0.3426039516925812,-0.2871107757091522,-0.2445062994956970,0.1676304638385773,0.2116415053606033,0.0883995518088341,-0.3880331516265869,0.2636835277080536,-0.2514505982398987) * FEATURE2_texOff(vec2(1,0));
res += mat4(-0.1861270815134048,0.2000686377286911,-0.1501186788082123,0.1525203883647919,0.1969228833913803,0.1174068301916122,-0.1281060427427292,-0.0854888409376144,0.0290613435208797,-0.0538076497614384,-0.0251582786440849,0.0692845508456230,0.0384319014847279,0.2888138592243195,0.1151804402470589,0.0990421250462532) * FEATURE1_texOff(vec2(1,1));
res += mat4(-0.0344385802745819,0.1270371377468109,0.0922426953911781,-0.0426749102771282,-0.1656492203474045,-0.3273328542709351,-0.0282224025577307,0.1099396124482155,-0.1113230437040329,0.2943290174007416,-0.2181112915277481,-0.3177657723426819,-0.1096536740660667,-0.0508293099701405,-0.0256164856255054,-0.0388228967785835) * FEATURE2_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(0.7142407894134521,0.0686190053820610,0.3999933302402496,-1.0247212648391724) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 2_1
//!BIND MODEL21
//!BIND MODEL22
//!SAVE MODEL1
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(0.0203563515096903,0.1902436912059784,-0.0757935121655464,0.0393617525696754);
res += mat4(-0.1080558672547340,-0.0400269515812397,0.1042881682515144,-0.1994346678256989,0.0172465778887272,-0.0829331055283546,-0.1278677284717560,-0.0762506872415543,-0.0593080408871174,-0.0305212251842022,0.1326192617416382,-0.3380933105945587,-0.0722763314843178,-0.1975518912076950,-0.0223602931946516,0.2251029163599014) * MODEL21_texOff(vec2(-1,-1));
res += mat4(0.1747678220272064,0.0297168865799904,0.1054855734109879,0.0803295820951462,-0.0338115766644478,-0.3885377943515778,-0.3540246784687042,-0.0719623491168022,-0.0656022280454636,-0.0469004511833191,0.1379419565200806,0.0319863893091679,0.0799935683608055,-0.0099127553403378,0.1698455959558487,-0.0108015276491642) * MODEL22_texOff(vec2(-1,-1));
res += mat4(0.1587898135185242,0.3995443880558014,-0.0333226583898067,0.2373267263174057,-0.1616930961608887,0.0659186244010925,0.0141129801049829,-0.0541022196412086,-0.5743742585182190,0.1121487766504288,0.4259817600250244,0.0280795227736235,-0.3721714317798615,-0.3496374189853668,0.0997273251414299,-0.0079920450225472) * MODEL21_texOff(vec2(-1,0));
res += mat4(0.0928084030747414,0.3107658624649048,0.1375299990177155,0.1550617516040802,-0.0780353918671608,-0.0102957757189870,-0.2056752145290375,-0.3927979469299316,-1.2112152576446533,0.0213295854628086,0.1396545022726059,0.0492016039788723,-0.0569122135639191,-0.1691886335611343,-0.1535325646400452,0.2800904810428619) * MODEL22_texOff(vec2(-1,0));
res += mat4(0.2494744062423706,-0.0363066755235195,0.0959179550409317,-0.0048101749271154,-0.0195793900638819,0.0451166369020939,0.1470773071050644,-0.0050059854984283,0.2886958122253418,-0.3221147954463959,-0.7062104344367981,0.1646659970283508,-0.0092520527541637,-0.1254461258649826,0.0217506736516953,-0.0678806379437447) * MODEL21_texOff(vec2(-1,1));
res += mat4(-0.0686557441949844,-0.0414490625262260,-0.1855954080820084,0.0264346338808537,-0.0296857114881277,-0.0431593284010887,0.0669397041201591,-0.0946076661348343,-0.2036914378404617,-0.1336101740598679,-0.2099903970956802,-0.1327936947345734,-0.1002155169844627,-0.0368575826287270,-0.1660962998867035,0.0728288888931274) * MODEL22_texOff(vec2(-1,1));
res += mat4(0.5504320859909058,0.2939232587814331,0.4704743027687073,0.2129514217376709,0.0843106731772423,-0.1978624463081360,-0.3298224806785583,0.1919094175100327,0.1980742365121841,-0.0644423812627792,0.0091170109808445,-0.2124856859445572,0.0804558470845222,-0.1130188927054405,-0.6276652812957764,0.1861163526773453) * MODEL21_texOff(vec2(0,-1));
res += mat4(-0.3357668519020081,0.2093413323163986,0.4355416595935822,0.1550502777099609,-0.6510964035987854,-0.1751857399940491,-0.2060168534517288,-0.1710205078125000,-0.1202360317111015,-0.2500316798686981,0.1074745431542397,-0.2418434321880341,0.0133954072371125,-0.0555886104702950,0.1514673978090286,0.2739115655422211) * MODEL22_texOff(vec2(0,-1));
res += mat4(-0.3006273508071899,-0.2699472010135651,-0.1982013583183289,-0.0032952548936009,0.0307833012193441,0.3671586215496063,-0.0966020002961159,-0.2836556434631348,0.4297264218330383,0.6171903610229492,0.6723483800888062,0.2705117464065552,-0.1438141316175461,-0.0873940736055374,-0.7001031041145325,-0.2052250355482101) * MODEL21_texOff(vec2(0,0));
res += mat4(-0.2875024676322937,-1.6230558156967163,-0.6733398437500000,-0.9642448425292969,-0.1964960694313049,0.2485812455415726,0.1236900389194489,-1.1423941850662231,-0.0412602946162224,0.3412002623081207,0.3962794244289398,-0.2490761876106262,-0.0058065578341484,-0.4578708708286285,-0.2418260127305984,0.5357795953750610) * MODEL22_texOff(vec2(0,0));
res += mat4(0.0062361713498831,0.1925230026245117,0.0824977159500122,0.0561275146901608,0.0929671525955200,0.0698546022176743,0.3816939592361450,0.0395248420536518,-0.0719512030482292,0.0564917400479317,-0.1297784000635147,0.1245511695742607,0.0012355837970972,-0.0990515723824501,0.4213519692420959,-0.1645816713571548) * MODEL21_texOff(vec2(0,1));
res += mat4(-0.0611936338245869,-0.0220258161425591,-0.0040935277938843,-0.1060328409075737,-0.0583154149353504,-0.0171997752040625,0.1058546081185341,0.2793170809745789,-0.2339317053556442,-0.1972009539604187,-0.0600687190890312,-0.0684379041194916,0.0243016034364700,-0.2111079394817352,-0.2042971849441528,0.0724857896566391) * MODEL22_texOff(vec2(0,1));
res += mat4(-0.0833447948098183,-0.0533220991492271,0.0767802372574806,0.1182348504662514,-0.0223299078643322,-0.0479344800114632,-0.0119727496057749,0.0524821877479553,-0.0334780365228653,0.0719002187252045,0.0439689308404922,0.0475181229412556,0.0764308497309685,0.0086713796481490,-0.1700707823038101,0.0657354295253754) * MODEL21_texOff(vec2(1,-1));
res += mat4(0.1391696482896805,0.0739523395895958,0.0565792545676231,-0.0430364646017551,0.0943084582686424,0.0102064209058881,0.0120795257389545,-0.0841303989291191,0.1573246121406555,0.0164279472082853,0.0988841354846954,-0.1430613398551941,-0.0572808869183064,-0.0844292491674423,0.0621565617620945,0.0923799052834511) * MODEL22_texOff(vec2(1,-1));
res += mat4(-0.1223107874393463,-0.2441930323839188,-0.2410650849342346,-0.0162935722619295,0.0695567727088928,-0.0028583710081875,-0.0059417244046926,0.0715164169669151,-0.0668491795659065,-0.1499572396278381,0.0869924053549767,0.0553652904927731,0.2729566097259521,0.1370039582252502,-0.1282183527946472,-0.1451860070228577) * MODEL21_texOff(vec2(1,0));
res += mat4(0.1331952214241028,0.0021079662255943,-0.1116734445095062,-0.4168601930141449,0.0534659475088120,0.0037860786542296,-0.0366065911948681,0.1047701835632324,0.1491260826587677,0.0782341659069061,0.0949895009398460,-0.1160908639431000,-0.1057133302092552,-0.2699718773365021,-0.1193305626511574,0.2142304331064224) * MODEL22_texOff(vec2(1,0));
res += mat4(0.0041565205901861,-0.1065499857068062,-0.0629659667611122,-0.1144768893718719,0.0318886637687683,-0.0562519319355488,0.0043422472663224,0.0226082988083363,-0.1456198990345001,-0.2398656159639359,-0.2625046670436859,-0.0710547044873238,0.0067904205061495,0.0018544088816270,0.1019348874688148,-0.0186133962124586) * MODEL21_texOff(vec2(1,1));
res += mat4(0.0732532218098640,0.1516859829425812,0.0580205544829369,0.1968977004289627,-0.0066619524732232,-0.1597842127084732,-0.0990600511431694,-0.1059188917279243,0.0718481168150902,-0.2222738713026047,-0.1675696671009064,-0.1500017195940018,-0.0568779110908508,-0.0582777932286263,-0.0844587534666061,-0.0263266414403915) * MODEL22_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(-0.2459529191255569,0.7563464641571045,-0.0705636814236641,-0.0094820559024811) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 2_2
//!BIND MODEL21
//!BIND MODEL22
//!SAVE MODEL2
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.0448397286236286,-0.1649267971515656,-0.1192543581128120,-0.0061073559336364);
res += mat4(0.0724840760231018,-0.0480341166257858,-0.1082391515374184,-0.1447021961212158,0.0723197236657143,0.0481830574572086,0.0009448126656935,0.0353565886616707,-0.0653375908732414,0.0029647622723132,-0.0016588598955423,-0.2075651884078979,0.0403469167649746,0.3929971158504486,0.0342363268136978,0.1427230089902878) * MODEL21_texOff(vec2(-1,-1));
res += mat4(-0.0743464827537537,0.1844420731067657,0.0256296340376139,-0.2808582782745361,0.0351609662175179,0.3277008235454559,-0.0205841138958931,-0.5355809330940247,0.0681906566023827,0.2058052271604538,-0.0479847639799118,-0.3735262751579285,-0.0261550359427929,-0.1148884072899818,-0.2329017966985703,0.0728458985686302) * MODEL22_texOff(vec2(-1,-1));
res += mat4(-0.1236097738146782,0.1251334398984909,-0.1339431256055832,0.0198749266564846,-0.1325920224189758,-2.2431972026824951,-0.0680834427475929,-0.5671764612197876,-0.3431925177574158,-0.0983135104179382,-0.2207138091325760,-0.2374879121780396,0.0127309206873178,1.3076044321060181,0.0848151743412018,-0.1928595900535583) * MODEL21_texOff(vec2(-1,0));
res += mat4(-0.0471093133091927,-0.1513628512620926,-0.0134263765066862,-0.1519252359867096,-0.5260242223739624,0.2291621714830399,0.4088975787162781,-0.4315340518951416,0.0933236032724380,-1.0386694669723511,0.0015958193689585,-0.2737887501716614,-0.0246253963559866,-0.2722961604595184,-0.1770633459091187,-0.2291279733181000) * MODEL22_texOff(vec2(-1,0));
res += mat4(-0.0017552347853780,0.1903935521841049,-0.0740704238414764,-0.0917679518461227,0.0323882810771465,-0.3029108047485352,0.0532565414905548,-0.0651542618870735,0.4868686199188232,0.8539272546768188,0.4151960313320160,0.2619662582874298,-0.0413270294666290,0.1404227763414383,0.1027320474386215,0.3274228572845459) * MODEL21_texOff(vec2(-1,1));
res += mat4(0.1828346252441406,0.0274682324379683,-0.1169882863759995,0.0327291004359722,0.1786244213581085,-0.6569546461105347,-0.0609031207859516,-0.1676601022481918,-0.1481092721223831,0.2889067530632019,0.1246089115738869,0.2203597426414490,-0.0366856977343559,0.1539470851421356,0.0069492300972342,-0.1544002443552017) * MODEL22_texOff(vec2(-1,1));
res += mat4(0.2073992937803268,-0.0717074573040009,-0.0196173377335072,-0.0956910699605942,0.0728898122906685,0.0484567955136299,0.3063069283962250,-0.3200540542602539,0.0291527546942234,-0.0265460256487131,0.1168476045131683,-0.2479970753192902,0.1224220171570778,0.0745823010802269,0.1868897676467896,-0.1958049237728119) * MODEL21_texOff(vec2(0,-1));
res += mat4(0.0019954447634518,-0.0225235987454653,0.0812198966741562,0.0295672398060560,-0.2016931176185608,-0.2239151000976562,-0.2481262385845184,-0.2381946444511414,-0.0520484372973442,-0.1200495883822441,0.2121954560279846,-0.1573531329631805,-0.0198472067713737,0.1001087054610252,-0.1084884032607079,-0.3126969039440155) * MODEL22_texOff(vec2(0,-1));
res += mat4(0.3838330209255219,0.1678779572248459,0.6496244072914124,0.3783606290817261,-0.2198582738637924,-0.2351343184709549,-0.2852248847484589,0.6310021877288818,0.8083020448684692,0.0039323624223471,-0.0901831910014153,0.0797894075512886,-0.2271467447280884,0.7082978487014771,0.1513756662607193,0.2188975960016251) * MODEL21_texOff(vec2(0,0));
res += mat4(-0.2871031761169434,0.2316448241472244,0.4947948157787323,0.3308620452880859,-0.0623455122113228,-0.1314185708761215,-0.2664661705493927,0.8725078701972961,0.4541083276271820,0.1433589160442352,-1.1269453763961792,0.6427971124649048,-0.1016561388969421,0.3418317139148712,-0.0991155728697777,-1.0508837699890137) * MODEL22_texOff(vec2(0,0));
res += mat4(-0.2179604172706604,0.1258949041366577,-0.1155700981616974,-0.0536149404942989,-0.0140614463016391,-0.0091438721865416,-0.0501774959266186,-0.3570724725723267,-0.5832386016845703,0.2004123181104660,0.2986239194869995,-0.8139168024063110,0.0142666567116976,0.0681498944759369,0.1293468028306961,-0.1001938357949257) * MODEL21_texOff(vec2(0,1));
res += mat4(0.1952836811542511,-0.3092494010925293,0.3063779771327972,0.1934849917888641,0.0746696740388870,-0.3533902466297150,-0.1269576102495193,-0.2237875163555145,0.2470717132091522,-0.2640363574028015,-0.2862776815891266,0.1740108281373978,-0.0963631942868233,0.2631850540637970,0.0400718413293362,-0.3590607047080994) * MODEL22_texOff(vec2(0,1));
res += mat4(-0.5299927592277527,0.0979989692568779,0.1666737496852875,-0.1547524333000183,-0.0043443185277283,0.1540203243494034,0.0594348423182964,-0.0167275425046682,-0.1043610796332359,0.0504250898957253,0.0456700921058655,0.2525034546852112,0.2241353541612625,-0.1678503304719925,0.1532667279243469,0.2901742458343506) * MODEL21_texOff(vec2(1,-1));
res += mat4(0.0998796448111534,0.0385462641716003,-0.0762400180101395,-0.1255892217159271,0.0281430184841156,-0.0304958485066891,-0.1440480053424835,-0.1001605167984962,-0.2257689833641052,0.2056092917919159,0.0248535349965096,-0.1383949518203735,-0.0951708629727364,0.0997417271137238,0.0275330394506454,-0.5728432536125183) * MODEL22_texOff(vec2(1,-1));
res += mat4(0.4256163835525513,0.1745115518569946,-0.2409395426511765,0.3139856457710266,-0.0036795330233872,0.1819283962249756,-0.0864531323313713,0.0102691333740950,-0.3397279977798462,0.1107075437903404,-0.0035228815395385,-0.2207705229520798,-0.1779139339923859,-0.2106117755174637,0.0352664291858673,0.3615589439868927) * MODEL21_texOff(vec2(1,0));
res += mat4(-0.0345224253833294,-0.0669926702976227,0.0907212942838669,-0.3758732676506042,-0.0452554710209370,-0.1134464666247368,-0.0358871109783649,-0.1858227252960205,-0.0233245138078928,-0.0495684742927551,0.1976234614849091,-0.1165761798620224,-0.0340447537600994,0.1095624342560768,0.0110175255686045,-0.8269239664077759) * MODEL22_texOff(vec2(1,0));
res += mat4(-0.1379280686378479,0.1004267781972885,0.0723998174071312,-0.1510958224534988,0.0610648579895496,0.0451720170676708,-0.0231927260756493,-0.0251553766429424,0.2306085377931595,0.1033207178115845,-0.1316205114126205,0.1130664870142937,-0.0458516106009483,-0.1152514070272446,-0.0088650323450565,-0.0214479379355907) * MODEL21_texOff(vec2(1,1));
res += mat4(-0.0545783303678036,-0.0620098188519478,0.0347074456512928,0.1096799224615097,0.0036664425861090,-0.0413107499480247,0.1443250179290771,-0.1161036714911461,-0.0061624986119568,-0.0252977479249239,0.3230019211769104,-0.2536626160144806,-0.0565439648926258,0.0827583819627762,-0.0071726376190782,-0.1983329951763153) * MODEL22_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(-0.6312188506126404,-0.1215368881821632,0.2487443536520004,0.4051703512668610) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 3_1
//!BIND MODEL1
//!BIND MODEL2
//!SAVE MODEL21
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.0410279631614685,-0.1111723631620407,-0.0406232848763466,-0.0939496159553528);
res += mat4(0.1221675798296928,0.0083215842023492,-0.0162804014980793,0.0316714197397232,-0.2205813378095627,0.1500435769557953,0.2109555304050446,0.2741867899894714,0.0956874340772629,-0.0896854698657990,-0.1657065600156784,-0.1349759399890900,0.0601499564945698,-0.1523845940828323,-0.1828087568283081,-0.2727653682231903) * MODEL1_texOff(vec2(-1,-1));
res += mat4(-0.0918163508176804,0.1564485579729080,0.1133174449205399,0.2215953171253204,-0.0623677000403404,-0.0497728772461414,-0.0372809022665024,-0.0258478187024593,-0.1364922970533371,0.1053884625434875,0.3292874991893768,0.2693256139755249,-0.0347631797194481,-0.1470523178577423,0.0096792401745915,-0.0542853325605392) * MODEL2_texOff(vec2(-1,-1));
res += mat4(0.1331177949905396,-0.0964357852935791,-0.0706946700811386,0.1593225002288818,-0.4815943241119385,0.1224092170596123,-0.0870430991053581,0.0005010276800022,-0.0242684502154589,-0.2256436049938202,0.1367238312959671,0.0474774017930031,0.6886650323867798,-0.0065326127223670,0.1841574758291245,-0.1354993879795074) * MODEL1_texOff(vec2(-1,0));
res += mat4(-0.1049591675400734,0.0515934228897095,0.1128631457686424,0.1688040047883987,-0.0084041170775890,-0.0006375144002959,-0.0598374009132385,0.1424416452646255,-0.0048398924991488,0.1832167655229568,0.0231959503144026,0.0816788375377655,-0.1321710795164108,0.0397678017616272,-0.0058345394209027,0.5784573554992676) * MODEL2_texOff(vec2(-1,0));
res += mat4(0.1438693851232529,-0.0694608166813850,-0.0428275354206562,0.1599996536970139,-0.1651254445314407,0.1388883888721466,-0.0895452573895454,0.2569831907749176,0.3150432109832764,-0.0910519883036613,0.0367441214621067,0.1903669685125351,0.2805841267108917,-0.0444608181715012,0.0059385276399553,-0.2585869431495667) * MODEL1_texOff(vec2(-1,1));
res += mat4(-0.1217494234442711,0.0191769022494555,-0.0065453462302685,0.1391217857599258,0.0998920649290085,-0.0162798929959536,0.0502282194793224,0.0370145924389362,0.0290782172232866,-0.0099554909393191,0.0142515478655696,0.1248661577701569,-0.0076912571676075,0.0251651499420404,0.2190572917461395,0.0020069130696356) * MODEL2_texOff(vec2(-1,1));
res += mat4(0.2666685581207275,-0.1625511497259140,-0.3938800692558289,-0.0253848694264889,0.0987015441060066,0.2033616453409195,0.3128099143505096,0.4608893990516663,0.0620003379881382,-0.1389972567558289,-0.3095863461494446,-0.4023511111736298,-0.1105777546763420,0.1115406602621078,0.3639950752258301,0.0645622834563255) * MODEL1_texOff(vec2(0,-1));
res += mat4(-0.2135885655879974,-0.1035343706607819,0.1795026361942291,0.1828210204839706,0.0780984908342361,0.0656728670001030,0.0033678691834211,0.1361345648765564,0.1712654232978821,-0.0172833092510700,-0.0502183400094509,0.2910411655902863,0.0691247656941414,0.1935720741748810,0.0652214139699936,0.1608240753412247) * MODEL2_texOff(vec2(0,-1));
res += mat4(0.8243460655212402,-0.0979344248771667,-0.0366373993456364,0.1692261099815369,0.5517869591712952,0.3282494544982910,-0.7905511856079102,-0.4462923705577850,-0.0803156569600105,0.1172509342432022,0.1864327639341354,0.1471016854047775,0.1296005547046661,-0.1004103720188141,0.3174172043800354,-0.1181766316294670) * MODEL1_texOff(vec2(0,0));
res += mat4(0.0259374529123306,-0.0934808850288391,0.3008874654769897,0.3957927823066711,-0.4048821926116943,0.1461934000253677,-0.1819096356630325,-0.1908810287714005,0.3193186521530151,-0.7438099980354309,0.1919509470462799,-0.2065188735723495,0.1752236187458038,-0.6840037107467651,0.1588519066572189,-0.3956064879894257) * MODEL2_texOff(vec2(0,0));
res += mat4(0.1574442386627197,-0.0114925103262067,-0.1208277940750122,0.2058266401290894,0.2879209220409393,-0.0419875606894493,-0.1902059614658356,-0.2723863720893860,-0.1086223348975182,-0.0870924964547157,0.8605937957763672,0.2656622231006622,-0.1653763055801392,0.0816384851932526,-0.0137870563194156,0.1433854848146439) * MODEL1_texOff(vec2(0,1));
res += mat4(-0.1565909236669540,-0.0307490080595016,-0.1055604666471481,0.2573592662811279,-0.1186821162700653,0.1141471788287163,-0.0272745657712221,-0.1049114838242531,0.2445316016674042,-0.0027864547446370,-0.1759569346904755,-0.1556979566812515,0.0550616309046745,0.1704383641481400,0.0853662937879562,0.3280856907367706) * MODEL2_texOff(vec2(0,1));
res += mat4(0.1460669338703156,0.4202052652835846,-0.3638312816619873,-0.0958623066544533,-0.0492525361478329,-0.3664234280586243,0.0794373303651810,0.0399017669260502,0.0629198029637337,0.1662959158420563,-0.1001493930816650,-0.0587460733950138,-0.0396478697657585,0.0017320754704997,0.0314909480512142,-0.0202700830996037) * MODEL1_texOff(vec2(1,-1));
res += mat4(-0.0964399129152298,0.0380319654941559,0.0396055467426777,0.0265473183244467,-0.0161637403070927,-0.1872924566268921,0.1670000404119492,0.0029466480482370,-0.1093841269612312,-0.3629201948642731,-0.0562992505729198,0.1792684197425842,-0.0203859098255634,0.0983991250395775,0.0058611719869077,0.1627455651760101) * MODEL2_texOff(vec2(1,-1));
res += mat4(-0.1117974221706390,0.7562329173088074,-0.2046248912811279,0.1677842289209366,-0.2063486129045486,-0.6023545265197754,-0.5739209651947021,0.5110496878623962,-0.0715268924832344,-0.1373793482780457,0.1251420378684998,-0.0477442294359207,0.4961377978324890,0.2688887119293213,0.3146316707134247,-0.5197153687477112) * MODEL1_texOff(vec2(1,0));
res += mat4(-0.1314805448055267,0.0746279135346413,0.3457699418067932,0.2564856410026550,0.0839370116591454,-0.6136511564254761,-0.4646295011043549,0.0612256154417992,-0.1910563558340073,-0.0935136750340462,-0.2426030039787292,0.2102959007024765,0.1575350016355515,0.6145061254501343,0.3368154168128967,-0.0974092856049538) * MODEL2_texOff(vec2(1,0));
res += mat4(0.0565315335988998,0.2393359094858170,-0.0932938233017921,0.1555283814668655,0.0123879108577967,-0.1247719228267670,-0.0564610138535500,-0.1125799044966698,-0.0104600470513105,0.0482629500329494,0.2316472232341766,0.1083717569708824,-0.0525921434164047,0.0643989592790604,-0.0525734610855579,-0.0503251366317272) * MODEL1_texOff(vec2(1,1));
res += mat4(-0.1835366338491440,0.0978360474109650,-0.1111819595098495,0.2109299153089523,0.0509372949600220,-0.1992686837911606,0.0677929744124413,-0.0870024710893631,-0.0412262082099915,-0.0697719156742096,-0.0967373847961426,0.0137308547273278,0.0195730421692133,0.0410240143537521,0.1157210171222687,0.2283479571342468) * MODEL2_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(0.1991519331932068,-0.1275756657123566,-0.0622864030301571,0.1586369574069977) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 3_2
//!BIND MODEL1
//!BIND MODEL2
//!SAVE MODEL22
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.0089084329083562,-0.0336172059178352,0.0177190825343132,0.0529975406825542);
res += mat4(-0.0275970958173275,0.0141968233510852,0.1181544512510300,-0.0572245270013809,0.1161347925662994,-0.1156444773077965,-0.2549640238285065,0.0882879272103310,-0.0715355500578880,0.0151285668835044,0.1079384386539459,0.0650847703218460,-0.1597152203321457,0.0669793561100960,0.2084401696920395,-0.0951152443885803) * MODEL1_texOff(vec2(-1,-1));
res += mat4(0.0404323227703571,-0.0206144321709871,-0.1080420613288879,-0.2038477361202240,0.0248847268521786,-0.0064681121148169,0.0389525443315506,0.0011026862775907,0.0885242074728012,0.0295896343886852,-0.3323790132999420,0.1935138553380966,-0.0466548874974251,0.1023886054754257,0.1257870644330978,-0.1541756242513657) * MODEL2_texOff(vec2(-1,-1));
res += mat4(-0.0076520540751517,0.0361139886081219,0.1749804913997650,-0.2051989138126373,0.0022692133206874,-0.0282937753945589,-0.2039019316434860,-0.2343468815088272,-0.0357327871024609,-0.0570764988660812,0.2925858795642853,-0.1988349705934525,-0.0584560707211494,-0.0341510921716690,0.1300961822271347,0.5184492468833923) * MODEL1_texOff(vec2(-1,0));
res += mat4(0.0884973928332329,0.0333527140319347,0.0180535931140184,-0.2655122876167297,0.0433661043643951,0.0104369185864925,0.0010909073753282,-0.0705273598432541,-0.0602585524320602,0.2420269846916199,-0.4731841087341309,-0.8040290474891663,0.3066828548908234,-0.2466925680637360,0.0938910692930222,-0.2002603262662888) * MODEL2_texOff(vec2(-1,0));
res += mat4(0.0549152903258801,0.0291299298405647,0.0946277007460594,-0.0581608228385448,0.0669180899858475,-0.0635575056076050,-0.2427970170974731,-0.2677550315856934,0.2226776182651520,0.1301570236682892,-0.1519709974527359,0.0671724304556847,-0.0526433289051056,0.1898351758718491,0.2383745312690735,0.2191711813211441) * MODEL1_texOff(vec2(-1,1));
res += mat4(-0.0234222635626793,0.0238620284944773,0.0427630320191383,-0.1080563366413116,0.0332126952707767,-0.0039051575586200,0.0293126031756401,0.0161924213171005,0.0453971028327942,0.0131999952718616,-0.0689036697149277,0.2349009960889816,0.1013344153761864,0.2706570029258728,0.1191426888108253,-0.2830821871757507) * MODEL2_texOff(vec2(-1,1));
res += mat4(0.0181465242058039,-0.0571886636316776,0.4875229001045227,-0.4244020283222198,0.4331104159355164,0.1066712513566017,-0.5277034044265747,0.1110567077994347,-0.1179447323083878,-0.0273578558117151,0.1798476576805115,-0.2829602360725403,0.1012385115027428,-0.2528488039970398,0.1697608679533005,0.1121710017323494) * MODEL1_texOff(vec2(0,-1));
res += mat4(-0.1404130905866623,-0.0984055623412132,-0.0279541295021772,-0.1321212500333786,-0.0841855704784393,0.1336171030998230,-0.1458790600299835,-0.0044095455668867,0.2203754037618637,0.1455714553594589,-0.2362042963504791,-0.0329121425747871,-0.1683547794818878,0.0289597529917955,0.3424547612667084,0.0143845872953534) * MODEL2_texOff(vec2(0,-1));
res += mat4(0.0287246014922857,0.1948280781507492,0.5998955368995667,0.1192114129662514,-0.6269109249114990,0.8724324703216553,-0.6399638652801514,-0.4201497733592987,-0.3355066180229187,-0.1566904038190842,-0.4396412074565887,0.1525828838348389,0.5573399066925049,0.2324324846267700,0.2762884795665741,0.0406046211719513) * MODEL1_texOff(vec2(0,0));
res += mat4(0.3890096545219421,-0.0574061162769794,-0.1468243300914764,-0.5953360199928284,-0.1363215148448944,-0.2224670499563217,-0.2237723320722580,0.2738097012042999,-0.4868114292621613,-0.5029351711273193,-0.3570256233215332,-0.1776263266801834,-0.0176672954112291,-0.4318660795688629,1.0395888090133667,0.1728395074605942) * MODEL2_texOff(vec2(0,0));
res += mat4(0.1337304115295410,-0.0809440389275551,0.1600498855113983,-0.1108811497688293,-0.2376178801059723,-0.1532768607139587,-0.0447455830872059,0.2515332102775574,0.4848278462886810,-0.0915748402476311,-0.0336527302861214,-0.2141884714365005,0.2125129699707031,0.3237875998020172,0.0022272330243140,-0.0167857185006142) * MODEL1_texOff(vec2(0,1));
res += mat4(0.0457934997975826,0.0510537698864937,-0.0519523508846760,-0.4506326615810394,-0.1029204949736595,0.0116113182157278,-0.1750748157501221,-0.0048758201301098,0.1506977379322052,0.0633068457245827,-0.1628549993038177,-0.0144928665831685,0.1408756822347641,0.2896180152893066,0.0803691521286964,-0.4930096566677094) * MODEL2_texOff(vec2(0,1));
res += mat4(-0.0484248884022236,0.1371297985315323,-0.1235475391149521,-0.2618594765663147,-0.0280395895242691,0.0248795989900827,0.1204105168581009,0.3246576189994812,0.0426272377371788,-0.0520061068236828,0.0575957447290421,-0.2613646090030670,0.1165295541286469,-0.0390013493597507,-0.0470846109092236,-0.0014663023175672) * MODEL1_texOff(vec2(1,-1));
res += mat4(-0.1066762879490852,-0.0869804695248604,-0.0099332248792052,-0.1355892717838287,-0.0760413780808449,0.1377770304679871,-0.0263407956808805,0.0880135521292686,0.1496269851922989,-0.0487459264695644,0.1286851912736893,0.2218491584062576,0.1723349541425705,-0.0165541302412748,-0.0690477639436722,-0.2388458102941513) * MODEL2_texOff(vec2(1,-1));
res += mat4(-0.4236431121826172,0.0465179122984409,-0.1526456624269485,0.1426440477371216,0.5913932919502258,-0.1082349196076393,0.2731275856494904,-0.2687640488147736,-0.4628683030605316,-0.0537119321525097,-0.1597615629434586,0.0528527684509754,-0.3485085070133209,0.1395110934972763,0.0642972290515900,0.0323829315602779) * MODEL1_texOff(vec2(1,0));
res += mat4(0.0066713397391140,-0.0482029877603054,-0.1707276403903961,-0.1001396998763084,0.0539822019636631,-0.1624453216791153,0.4913550019264221,0.3687861263751984,0.0491421781480312,0.1311376541852951,0.0992425829172134,-0.4636098444461823,-0.3415873646736145,-0.0153833786025643,-0.0270162131637335,-0.0935514941811562) * MODEL2_texOff(vec2(1,0));
res += mat4(-0.1738258153200150,0.0458541549742222,-0.0653749182820320,-0.0156540926545858,-0.0357586294412613,-0.1486178338527679,0.1798035055398941,-0.1310307979583740,0.0783249065279961,-0.0261360015720129,-0.1047066971659660,0.3385537564754486,-0.0339452810585499,0.2299628853797913,-0.1408322304487228,-0.0352708548307419) * MODEL1_texOff(vec2(1,1));
res += mat4(0.0463018082082272,0.0565674640238285,-0.0538956597447395,-0.2354862987995148,0.0297824125736952,0.0307939313352108,0.1271791011095047,-0.1025698855519295,0.1060482114553452,-0.0703211054205894,-0.0083062350749969,0.0474255047738552,0.0442508421838284,0.1569559425115585,-0.0442709513008595,-0.1188704669475555) * MODEL2_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(0.7366524934768677,1.0013850927352905,-0.0276311747729778,0.0734841898083687) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 4_1
//!BIND MODEL21
//!BIND MODEL22
//!SAVE MODEL1
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.1306160986423492,-0.0808217376470566,-0.2880123555660248,0.0099629526957870);
res += mat4(-0.1033539846539497,0.0541300140321255,-0.0804840475320816,-0.0334571413695812,-0.0264753755182028,0.1118840202689171,0.1186013221740723,-0.0127575425431132,0.2236593365669250,0.0025286162272096,0.0985530614852905,0.0685181617736816,-0.1884875595569611,0.0530862808227539,-0.0482063069939613,0.0375233069062233) * MODEL21_texOff(vec2(-1,-1));
res += mat4(0.1837068796157837,-0.0632847175002098,0.0016613919287920,0.0392861217260361,0.2923883199691772,-0.1713902205228806,0.1907587945461273,0.0550456829369068,0.0644215345382690,-0.1046456992626190,0.0187383033335209,0.0770180150866508,0.1933846622705460,-0.0455715768039227,0.0375007353723049,-0.1053109914064407) * MODEL22_texOff(vec2(-1,-1));
res += mat4(-0.0972480997443199,0.2820451855659485,0.0114549007266760,-0.0954328626394272,0.0706252008676529,0.4829064607620239,-0.6371517181396484,0.0005180989392102,0.3280143439769745,0.0665246024727821,-0.0503116399049759,-0.1261110603809357,0.1114177703857422,-0.2053108513355255,0.1428771317005157,0.3926100134849548) * MODEL21_texOff(vec2(-1,0));
res += mat4(-0.2571723163127899,0.1627264618873596,-0.4940335154533386,-0.1361546218395233,0.0804422944784164,-0.4231885373592377,0.0650202706456184,0.0518481098115444,-0.0502478554844856,-0.1305799931287766,0.1814480125904083,0.0090866927057505,-0.0510044656693935,-0.1691461503505707,0.0922467112541199,-0.0314207412302494) * MODEL22_texOff(vec2(-1,0));
res += mat4(0.1270498335361481,0.0563284493982792,-0.0435525141656399,0.1569847911596298,0.0576847903430462,0.3461692929267883,-0.0325655154883862,-0.2688976824283600,-0.1341977864503860,-0.1382253766059875,0.2293784171342850,-0.1111817285418510,-0.1402447521686554,-0.3257531225681305,0.0598510466516018,0.1008039116859436) * MODEL21_texOff(vec2(-1,1));
res += mat4(0.1698816716670990,0.3491003513336182,-0.1367681026458740,-0.1165873408317566,-0.2091718912124634,-0.1487034261226654,-0.0569749698042870,-0.2100717276334763,0.0404917001724243,-0.1372035890817642,0.0689046755433083,-0.0367818064987659,-0.0325474888086319,-0.0114965448155999,-0.0137249026447535,-0.0279692262411118) * MODEL22_texOff(vec2(-1,1));
res += mat4(-0.0563433989882469,0.0132494345307350,-0.2434540390968323,0.0796563774347305,-0.2109155058860779,0.0387088693678379,-0.0591037571430206,0.0955820381641388,0.4660535752773285,-0.1204202473163605,0.1332369595766068,-0.0285425651818514,-0.3886952698230743,-0.0434980578720570,-0.0849134400486946,0.0802380964159966) * MODEL21_texOff(vec2(0,-1));
res += mat4(0.0412235632538795,0.1571959257125854,0.2050069272518158,-0.1138664111495018,0.1962715685367584,0.0594439841806889,0.0351715497672558,-0.0129811102524400,0.2055217623710632,-0.0647534057497978,0.0373471938073635,0.0877277255058289,-0.5734645724296570,0.1188675239682198,-0.1145943328738213,-0.1182733029127121) * MODEL22_texOff(vec2(0,-1));
res += mat4(-0.2004909217357635,-0.4817073047161102,0.5596802830696106,-0.0327854752540588,0.0989314392209053,0.4127818942070007,0.7265836596488953,-0.2692042589187622,0.5195841789245605,-0.2357539832592010,-0.3819393217563629,0.1755530238151550,0.6578183770179749,0.1075539961457253,-0.2688144743442535,0.3242723941802979) * MODEL21_texOff(vec2(0,0));
res += mat4(-0.3221310675144196,0.2978510260581970,0.2269985526800156,-0.3184116482734680,0.4845580160617828,0.4407236874103546,0.0099756307899952,-0.3121858239173889,-0.3810067176818848,-0.0553649961948395,0.0202834140509367,0.0409953594207764,0.2532750964164734,0.2731618583202362,0.1237529441714287,0.0134243080392480) * MODEL22_texOff(vec2(0,0));
res += mat4(0.1835541725158691,0.0549701862037182,-0.1749316602945328,-0.2030028849840164,0.0263462308794260,0.2781440317630768,0.0372458845376968,0.3643021881580353,-0.4047883749008179,0.0660117194056511,0.4863115549087524,-0.2024163603782654,-0.6403482556343079,0.2765505611896515,0.1417075097560883,0.5064445734024048) * MODEL21_texOff(vec2(0,1));
res += mat4(0.6106975078582764,-0.1570862233638763,-0.3223383128643036,-0.2497926801443100,-0.4854303300380707,0.0132978223264217,-0.0609334111213684,0.1285556703805923,-0.1412864029407501,-0.1379042416810989,-0.0258826259523630,0.1357705891132355,-0.1285902857780457,-0.0577826797962189,0.0550044551491737,0.1717510819435120) * MODEL22_texOff(vec2(0,1));
res += mat4(0.1389609426259995,0.0835867226123810,0.0309768319129944,-0.0278116948902607,-0.0390677824616432,-0.0111810686066747,-0.0025318188127130,0.0069569633342326,0.0347319357097149,0.0191543344408274,0.0314339138567448,-0.0228427499532700,0.0416300334036350,0.0249234102666378,0.1210031509399414,0.1142473593354225) * MODEL21_texOff(vec2(1,-1));
res += mat4(0.0607251487672329,0.0386395826935768,-0.0219341218471527,-0.1102298423647881,0.1487188935279846,0.0602982006967068,-0.0280748903751373,-0.0211924221366644,0.0042894422076643,-0.0269144997000694,0.0814756453037262,-0.0314031280577183,-0.0213186051696539,-0.1362965404987335,0.0382767543196678,-0.0669511556625366) * MODEL22_texOff(vec2(1,-1));
res += mat4(-0.2397561967372894,0.3023172020912170,-0.2398054003715515,0.0041919997893274,-0.1016605198383331,-0.1521034836769104,-0.1526568531990051,0.0272433310747147,0.0741761848330498,0.1116370111703873,0.1149727106094360,-0.0809784531593323,-0.1448147594928741,-0.0943927690386772,-0.0086280042305589,0.1243222951889038) * MODEL21_texOff(vec2(1,0));
res += mat4(-0.0469366572797298,-0.1655988991260529,-0.1029584184288979,-0.1347874104976654,0.2064601778984070,0.0521226711571217,-0.1366733759641647,-0.0041872998699546,0.1077186539769173,0.0184442866593599,-0.2309073060750961,-0.1637075096368790,-0.0417953692376614,-0.3190860450267792,-0.1593534499406815,0.0136412177234888) * MODEL22_texOff(vec2(1,0));
res += mat4(0.1698798984289169,0.0232755411416292,-0.0876034423708916,-0.3008348643779755,0.0789884999394417,0.0034748215693980,-0.0064704762771726,0.0057828431017697,-0.0190630126744509,-0.0334153175354004,-0.0195646341890097,0.0105131156742573,0.0995147302746773,-0.3130289018154144,-0.0724022984504700,0.0113303456455469) * MODEL21_texOff(vec2(1,1));
res += mat4(-0.0027791252359748,-0.0193455871194601,-0.0415000133216381,0.0568981170654297,-0.2745247483253479,0.1222846284508705,0.1899162530899048,0.1067754998803139,-0.0561975166201591,-0.1500336527824402,0.0526139959692955,-0.3491798937320709,-0.0692384615540504,-0.0307095069438219,0.0498757846653461,0.0019003645284101) * MODEL22_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(0.1552927196025848,0.0782765746116638,0.7966942191123962,-1.1619627475738525) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC mapping 4_2
//!BIND MODEL21
//!BIND MODEL22
//!SAVE MODEL2
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.1443098634481430,-0.1343899369239807,-0.0624338127672672,-0.1094277128577232);
res += mat4(-0.0689977407455444,-0.1693786680698395,0.0109281269833446,0.0609922930598259,0.0296908002346754,0.1195700988173485,-0.0694077461957932,0.0971287414431572,0.0253518298268318,0.1213042959570885,0.0703809782862663,0.0055739870294929,-0.1595942378044128,-0.1336689442396164,-0.0622441768646240,-0.0428023114800453) * MODEL21_texOff(vec2(-1,-1));
res += mat4(0.0860001668334007,-0.0226618759334087,0.1602241247892380,0.0431661494076252,0.1526461094617844,0.2752982378005981,0.0960300788283348,-0.0536719262599945,-0.0171773489564657,0.0457364916801453,-0.0360932648181915,-0.0397153608500957,-0.0277090407907963,0.0729821547865868,-0.0145150292664766,0.0252893269062042) * MODEL22_texOff(vec2(-1,-1));
res += mat4(-0.1407091915607452,-0.4007499516010284,-0.0302001200616360,-0.0606933943927288,-0.2960600554943085,-0.2263117432594299,0.0721478462219238,-0.4578711986541748,0.0960150733590126,-0.1606502830982208,0.2444226741790771,0.0000882153908606,0.1472496986389160,0.3256779909133911,-0.2132861614227295,0.0339313484728336) * MODEL21_texOff(vec2(-1,0));
res += mat4(-0.1477648764848709,-0.1487885862588882,-0.1973863691091537,0.0717295333743095,0.0843430235981941,0.6259996294975281,-0.1214931011199951,-0.1274987608194351,0.2359549105167389,0.3002171218395233,-0.0825233608484268,-0.0157950688153505,0.0706149637699127,0.1762917637825012,-0.0611497573554516,-0.0859689489006996) * MODEL22_texOff(vec2(-1,0));
res += mat4(0.0174895934760571,-0.0567042417824268,0.0409146919846535,0.0258173532783985,0.1421577036380768,0.1234543323516846,-0.1721662431955338,0.1492216140031815,0.1100751459598541,0.0501539446413517,0.1100447699427605,-0.1086079254746437,-0.0608497932553291,0.0087817469611764,0.0714464113116264,-0.1285197436809540) * MODEL21_texOff(vec2(-1,1));
res += mat4(-0.0017177806003019,-0.1463395059108734,-0.1085453778505325,0.1650195866823196,0.0813829153776169,0.1102061793208122,-0.0578421875834465,-0.0232036896049976,-0.1239888817071915,0.0155465165153146,0.1079114526510239,-0.0420837886631489,-0.0775837749242783,0.0148941157385707,-0.0502299368381500,-0.0654754191637039) * MODEL22_texOff(vec2(-1,1));
res += mat4(0.0918162539601326,0.0440697595477104,-0.0515748932957649,0.0417411290109158,0.0353216230869293,0.1535954177379608,0.0439723692834377,-0.1288845241069794,0.1076577678322792,-0.1306740194559097,0.0715952813625336,-0.0681907683610916,-0.3798767924308777,0.1023928597569466,-0.0970670804381371,0.0077168666757643) * MODEL21_texOff(vec2(0,-1));
res += mat4(0.0634560957551003,-0.0550306066870689,0.2073986232280731,0.0520241297781467,0.1162287592887878,-0.2218665480613708,0.3199682831764221,0.0606246069073677,-0.0058511858806014,-0.0667045339941978,-0.0449917949736118,0.0707788690924644,-0.3323366343975067,-0.0763893201947212,-0.0997853428125381,-0.1181001588702202) * MODEL22_texOff(vec2(0,-1));
res += mat4(-0.3101258873939514,0.2616009712219238,0.0584651045501232,0.1656491309404373,-0.0069236233830452,0.2573371529579163,-0.1793291717767715,-0.2718756198883057,0.0953581258654594,0.0524105131626129,0.1183085516095161,0.0583294369280338,0.5036848187446594,-0.5763167142868042,-0.2119628041982651,-0.3140562772750854) * MODEL21_texOff(vec2(0,0));
res += mat4(-0.2497755438089371,-0.0146329319104552,-0.2741575539112091,0.2459975033998489,0.3562706708908081,-0.6528629064559937,-0.4287456274032593,0.2055913358926773,0.1739019453525543,-0.3855968713760376,-0.0958273336291313,-0.7066691517829895,0.2365748286247253,-0.3046728968620300,-0.2590373754501343,-0.0496727414429188) * MODEL22_texOff(vec2(0,0));
res += mat4(-0.0844531357288361,-0.0321611948311329,-0.0951840654015541,0.0577518045902252,-0.1606003493070602,0.2776086628437042,-0.1355003118515015,-0.0880064144730568,-0.1277643740177155,-0.0514567233622074,0.1522682905197144,-0.1040910631418228,-0.2767944037914276,-0.1452194601297379,0.0089118303731084,0.0231996178627014) * MODEL21_texOff(vec2(0,1));
res += mat4(0.2603267133235931,0.0167464651167393,-0.2064073234796524,0.1782064288854599,0.4890212416648865,0.0559245310723782,0.1221160590648651,-0.0202587731182575,-0.4056585729122162,-0.1839511841535568,0.2775998413562775,0.0024275144096464,-0.2624500989913940,-0.0619418807327747,0.0153478365391493,0.0123427547514439) * MODEL22_texOff(vec2(0,1));
res += mat4(0.0816635638475418,-0.0134946266189218,0.0594766475260258,-0.0551253929734230,0.0134431896731257,-0.0652195811271667,-0.0563635528087616,-0.0066532371565700,-0.0004114551993553,0.0105680683627725,0.1324467360973358,0.0467248968780041,0.0301312971860170,-0.1073397025465965,-0.0363437235355377,-0.0474153012037277) * MODEL21_texOff(vec2(1,-1));
res += mat4(0.0199097190052271,0.0901319086551666,0.0448978282511234,0.0505443066358566,0.0438878424465656,-0.0494784042239189,0.0724927335977554,-0.0070675504393876,-0.0012125011999160,0.0295279901474714,0.0705125033855438,0.0555334389209747,-0.0403393507003784,-0.1271172016859055,0.0017914215568453,0.1462216079235077) * MODEL22_texOff(vec2(1,-1));
res += mat4(-0.2827299833297729,0.2052399665117264,0.0042732120491564,-0.3969024717807770,-0.0782120972871780,0.1960176974534988,-0.0675340741872787,0.0027962317690253,0.0516129024326801,-0.0352642722427845,0.0546326488256454,0.0065340655855834,-0.1062376946210861,0.1364430636167526,-0.0536947809159756,0.2098117172718048) * MODEL21_texOff(vec2(1,0));
res += mat4(0.0045875865034759,0.2162927240133286,-0.2158576399087906,-0.0047327815555036,0.1251590698957443,0.1279677897691727,-0.1188964918255806,0.0328494384884834,0.0076038073748350,-0.0561547242105007,0.0335608273744583,0.4332321286201477,0.0021786799188703,0.0844521671533585,-0.2102309316396713,-0.0189208015799522) * MODEL22_texOff(vec2(1,0));
res += mat4(0.0933093801140785,0.1548244059085846,-0.0598701611161232,0.0357220247387886,-0.1141726672649384,0.0536412484943867,-0.0159156844019890,-0.0445508137345314,0.1883231997489929,-0.1547038406133652,0.0530619807541370,0.0059371814131737,0.0602529086172581,-0.0435577929019928,0.0083390390500426,0.0191930737346411) * MODEL21_texOff(vec2(1,1));
res += mat4(-0.0351041629910469,0.2119503468275070,-0.0841927304863930,0.0079463515430689,0.0683520361781120,-0.1657009869813919,0.0611055232584476,-0.0063667562790215,0.0330024957656860,-0.1810818463563919,0.0872574150562286,0.1485669612884521,-0.1305806934833527,0.0041402997449040,0.0223289318382740,-0.0141495745629072) * MODEL22_texOff(vec2(1,1));
res = max(res, vec4(0.0)) + vec4(0.5769761204719543,0.1716064810752869,-0.0821026712656021,0.2092144042253494) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC sub-band residuals 1
//!BIND MODEL1
//!BIND MODEL2
//!BIND FEATURE1
//!SAVE RES1
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(0.0245648548007011,-0.4467784762382507,0.0197526942938566,-0.0110000418499112);
res += mat4(0.0302665308117867,-0.9262221455574036,-0.1161134764552116,-0.0506900474429131,0.2716045379638672,-0.0485871583223343,0.0044713355600834,-0.4274623394012451,0.0749531090259552,-0.3700785338878632,0.0350039415061474,-0.0540786534547806,-0.0607390031218529,-0.8019900321960449,0.0923245251178741,0.1258827745914459) * MODEL1_texOff(0);
res += mat4(-0.0649135261774063,0.0815236791968346,0.0067334296181798,0.1277425885200500,-0.0051357815973461,-0.1485908329486847,0.0074226572178304,0.0050623500719666,0.0588018335402012,-0.0692552924156189,0.1288725286722183,-0.0989386290311813,0.0427936837077141,0.0967708528041840,-0.0455632135272026,-0.0711275041103363) * MODEL2_texOff(0);
res += FEATURE1_texOff(0);
res = max(res, vec4(0.0)) + vec4(0.9927186965942383,0.0570580027997494,1.3226752281188965,1.0069466829299927) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC sub-band residuals 2
//!BIND MODEL1
//!BIND MODEL2
//!BIND FEATURE2
//!SAVE RES2
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(-0.0425243787467480,-0.3715015351772308,-0.0256227850914001,-0.2774516046047211);
res += mat4(0.0238118842244148,0.0295480657368898,-0.0066418983042240,0.1021223962306976,-0.0568209178745747,-0.4355100393295288,-0.2700522541999817,-0.2060186564922333,-0.0689613372087479,-0.1689691990613937,-0.0306748505681753,-0.2461252212524414,-0.0057375836186111,-0.1892303228378296,-0.0285871494561434,-0.5032613277435303) * MODEL1_texOff(0);
res += mat4(0.5463213324546814,0.0972800329327583,0.0307560767978430,0.0678058937191963,-0.0356063023209572,-0.7013865113258362,0.1890443563461304,-0.1036657467484474,-0.1745826154947281,-0.2942218780517578,-0.0485423319041729,-0.2983124554157257,-0.0524431839585304,-0.3261034786701202,0.3217246532440186,0.1958018541336060) * MODEL2_texOff(0);
res += FEATURE2_texOff(0);
res = max(res, vec4(0.0)) + vec4(0.1391339898109436,0.0960328355431557,0.6235341429710388,0.1177272796630859) * min(res, vec4(0.0));
return res;
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!DESC sub-pixel convolution 1
//!BIND RES1
//!BIND RES2
//!SAVE SUBCONV1
//!COMPONENTS 4
vec4 hook()
{
vec4 res = vec4(0.2010385394096375,0.2058132737874985,0.1918809115886688,0.1961363703012466);
res += mat4x4(-0.0005980331334285,-0.0095877395942807,-0.0149448839947581,-0.0026380482595414,0.0320665836334229,-0.0706205591559410,-0.0054677254520357,0.0215112231671810,-0.0025710910558701,-0.0000433265340689,0.0044494951143861,-0.0034823501482606,-0.0050858515314758,0.0109513988718390,0.0208286065608263,-0.0032168829347938) * RES1_texOff(vec2(-1,-1));
res += mat4x4(-0.0145305208861828,0.0246876608580351,-0.0038286084309220,-0.0033089490607381,-0.0920709222555161,-0.0767898634076118,0.0012083095498383,-0.0751532614231110,0.0001302754972130,-0.0107085108757019,-0.0010383903281763,-0.0059571005403996,0.0809685289859772,0.0414833538234234,0.0227938480675220,-0.0211347509175539) * RES2_texOff(vec2(-1,-1));
res += mat4x4(0.0160999298095703,0.0364215746521950,-0.0377063788473606,-0.0449111759662628,-0.0476365163922310,0.1522845029830933,-0.0131391752511263,-0.0476671792566776,-0.0378389135003090,0.0235454943031073,0.0224007442593575,-0.0010372076649219,-0.0089435689151287,-0.0293026417493820,0.0274190884083509,0.0469092652201653) * RES1_texOff(vec2(-1,0));
res += mat4x4(0.0297575183212757,-0.0132508194074035,-0.0044682323932648,-0.0096222748979926,0.2525918781757355,0.1873829364776611,-0.5599535703659058,-0.2372044622898102,0.0033207221422344,0.0256173480302095,0.0294605866074562,0.0323960892856121,-0.1679904460906982,-0.1278967708349228,0.3168168365955353,0.1978507637977600) * RES2_texOff(vec2(-1,0));
res += mat4x4(-0.0047590560279787,-0.0149335600435734,0.0033453819341958,-0.0012247267877683,0.1112466752529144,0.0147760482504964,0.0031189601868391,0.0391573049128056,-0.0028154491446912,-0.0036881719715893,-0.0116015253588557,-0.0037573333829641,0.0047581391409039,0.0071071563288569,-0.0033221673220396,0.0004882142529823) * RES1_texOff(vec2(-1,1));
res += mat4x4(-0.0025197160430253,-0.0018677815096453,0.0038254233077168,0.0041981274262071,-0.1321131736040115,-0.0494364202022552,0.0760654658079147,-0.1386690139770508,-0.0016222692793235,-0.0060105528682470,0.0010201989207417,0.0092753591015935,-0.0194614846259356,0.0087382243946195,-0.0606758072972298,0.0156162241473794) * RES2_texOff(vec2(-1,1));
res += mat4x4(-0.0073722628876567,0.0012844242155552,0.0241398401558399,-0.0075527969747782,-0.0865194946527481,-0.0610522404313087,0.0289319511502981,-0.0994452014565468,0.0281447004526854,-0.0250582899898291,0.0044891634024680,-0.0246205236762762,0.0112307453528047,-0.0010844616917893,-0.0223584957420826,0.0177635718137026) * RES1_texOff(vec2(0,-1));
res += mat4x4(-0.0585863515734673,0.0953190475702286,-0.0555586628615856,0.1033507287502289,0.1560877263545990,-0.0690897777676582,-0.0341389514505863,-0.0661668032407761,0.0531073249876499,-0.0266165956854820,-0.0203275382518768,0.0017760475166142,-0.1300747394561768,0.1810652017593384,0.0381597876548767,0.1397419273853302) * RES2_texOff(vec2(0,-1));
res += mat4x4(0.6259804368019104,0.6062518954277039,0.5450409054756165,0.5966195464134216,-0.0423948727548122,0.0760537460446358,-0.0113651463761926,0.3007817566394806,-0.3218322694301605,0.2713021934032440,-0.3143473267555237,0.2303840517997742,0.3493050038814545,0.3590726852416992,0.4138027429580688,0.3391666412353516) * RES1_texOff(vec2(0,0));
res += mat4x4(0.0790478289127350,-0.0978994593024254,0.0779844969511032,-0.0823706611990929,0.0094470111653209,0.1671760678291321,0.1201528310775757,-0.2016288936138153,0.3667598366737366,0.3651430010795593,-0.3612343966960907,-0.2978236973285675,-0.4231655597686768,0.0091423410922289,-0.1918412446975708,0.4224558770656586) * RES2_texOff(vec2(0,0));
res += mat4x4(-0.0186564289033413,0.0274957418441772,-0.0064405309967697,0.0056951809674501,0.4864942431449890,-0.2563461959362030,0.4357284605503082,-0.2976118028163910,0.0374982468783855,0.0167757049202919,0.0305800959467888,0.0232830215245485,0.0138373551890254,-0.0191283021122217,0.0032355054281652,0.0055057541467249) * RES1_texOff(vec2(0,1));
res += mat4x4(-0.0276355985552073,0.0048149987123907,-0.0251619722694159,-0.0057246969081461,0.0271473955363035,-0.0042668608948588,-0.0594691745936871,0.2255926281213760,-0.0203660242259502,0.0721646770834923,0.0137230781838298,-0.0650938376784325,-0.3049557507038116,0.2035628110170364,-0.2509683668613434,0.1962853819131851) * RES2_texOff(vec2(0,1));
res += mat4x4(0.0109980758279562,-0.0053752651438117,-0.0112550277262926,0.0024017230607569,0.0362104885280132,0.0084348218515515,-0.0106990104541183,-0.0207723993808031,-0.0014961160486564,0.0066790678538382,0.0028113177977502,0.0025022011250257,-0.0093937022611499,0.0016421369509771,0.0035362334456295,-0.0058064293116331) * RES1_texOff(vec2(1,-1));
res += mat4x4(0.0138889988884330,-0.0078343702480197,0.0061464929021895,0.0202130675315857,-0.0257590841501951,-0.0366640128195286,0.0250097587704659,-0.0498071312904358,-0.0103149358183146,-0.0001786737266229,-0.0099909817799926,0.0062733208760619,0.0131437368690968,-0.0005469865864143,-0.0388854071497917,0.0612070746719837) * RES2_texOff(vec2(1,-1));
res += mat4x4(0.0052813654765487,0.0215748809278011,0.0107395220547915,-0.0079439217224717,0.0382786765694618,0.0697424262762070,-0.0415962152183056,0.0657853558659554,0.0209470037370920,-0.0218399092555046,-0.0447359494864941,0.0407319553196430,-0.0040902681648731,-0.0196106657385826,-0.0018554026028141,0.0203906055539846) * RES1_texOff(vec2(1,0));
res += mat4x4(-0.0106181986629963,0.0084018819034100,0.0131329754367471,-0.0198754761368036,0.1117177084088326,0.0990846082568169,-0.0732304081320763,0.0163581725209951,-0.0648830309510231,-0.0451613292098045,0.0206844564527273,0.0031441387254745,-0.0106161693111062,-0.0567689687013626,0.0782861113548279,-0.0306094046682119) * RES2_texOff(vec2(1,0));
res += mat4x4(0.0012452082009986,-0.0026056850329041,-0.0096226977184415,-0.0037850935477763,-0.0190967041999102,0.0534373670816422,0.1599360853433609,0.0834670960903168,-0.0070255175232887,0.0012873009545729,0.0030876772943884,-0.0093916896730661,-0.0033529615029693,0.0043485122732818,0.0089034689590335,-0.0067489291541278) * RES1_texOff(vec2(1,1));
res += mat4x4(0.0004713654634543,-0.0034161377698183,-0.0026913962792605,0.0053522582165897,-0.0040974905714393,0.0273330621421337,-0.0333138220012188,-0.0701237097382545,0.0082997502759099,-0.0183656588196754,-0.0122841577976942,-0.0052855615504086,-0.0023795007728040,-0.0438593104481697,-0.1101513057947159,-0.0182559806853533) * RES2_texOff(vec2(1,1));
return vec4(res);
}
//!HOOK LUMA
//!WHEN OUTPUT.w LUMA.w / 1.300 > OUTPUT.h LUMA.h / 1.300 > *
//!WIDTH LUMA.w 2 *
//!HEIGHT LUMA.h 2 *
//!DESC aggregation
//!BIND SUBCONV1
vec4 hook()
{
vec2 fcoord = fract(SUBCONV1_pos * SUBCONV1_size);
vec2 base = SUBCONV1_pos + (vec2(0.5) - fcoord) * SUBCONV1_pt;
ivec2 index = ivec2(fcoord * vec2(2));
vec4 res = SUBCONV1_tex(base);
return vec4(res[index.x * 2 + index.y], 0, 0, 1);
}

View File

@@ -0,0 +1,544 @@
// The MIT License(MIT)
//
// Copyright(c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files(the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// NVIDIA Image Scaling v1.0.2 by NVIDIA
// ported to mpv by agyild
// Changelog
// Made it directly operate on LUMA plane, since the original shader was operating
// on LUMA by deriving it from RGB. This should cause a major increase in performance,
// especially on OpenGL 4.0+ renderers
//!HOOK LUMA
//!BIND HOOKED
//!BIND coef_scaler
//!BIND coef_usm
//!DESC NVIDIA Image Scaling and Sharpening v1.0.2
//!COMPUTE 32 24 256 1
//!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 >
//!WIDTH OUTPUT.w
//!HEIGHT OUTPUT.h
// User variables
#define SHARPNESS 0.25 // Amount of sharpening. 0.0 to 1.0.
#define NIS_THREAD_GROUP_SIZE 256 // May be set to 128 for better performance on NVIDIA hardware, otherwise set to 256. Don't forget to modify the COMPUTE directive accordingly as well (e.g., COMPUTE 32 24 128 1).
#define NIS_HDR_MODE 0 // Must be set to 1 for content with PQ colorspace. 0 or 1.
// Constant variables
#define NIS_BLOCK_WIDTH 32
#define NIS_BLOCK_HEIGHT 24
#define kPhaseCount 64
#define kFilterSize 6
#define kSupportSize 6
#define kPadSize kSupportSize
#define NIS_SCALE_INT 1
#define NIS_SCALE_FLOAT 1.0f
#define kTilePitch (NIS_BLOCK_WIDTH + kPadSize)
#define kTileSize (kTilePitch * (NIS_BLOCK_HEIGHT + kPadSize))
#define kEdgeMapPitch (NIS_BLOCK_WIDTH + 2)
#define kEdgeMapSize (kEdgeMapPitch * (NIS_BLOCK_HEIGHT + 2))
const float sharpen_slider = clamp(SHARPNESS, 0.0f, 1.0f) - 0.5f;
const float MaxScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.75f;
const float MinScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.0f;
const float LimitScale = (sharpen_slider >= 0.0f) ? 1.25f : 1.0f;
const float kDetectRatio = 2 * 1127.f / 1024.f;
const float kDetectThres = (bool(NIS_HDR_MODE) ? 32.0f : 64.0f) / 1024.0f;
const float kMinContrastRatio = bool(NIS_HDR_MODE) ? 1.5f : 2.0f;
const float kMaxContrastRatio = bool(NIS_HDR_MODE) ? 5.0f : 10.0f;
const float kSharpStartY = bool(NIS_HDR_MODE) ? 0.35f : 0.45f;
const float kSharpEndY = bool(NIS_HDR_MODE) ? 0.55f : 0.9f;
const float kSharpStrengthMin = max(0.0f, 0.4f + sharpen_slider * MinScale * (bool(NIS_HDR_MODE) ? 1.1f : 1.2));
const float kSharpStrengthMax = ((bool(NIS_HDR_MODE) ? 2.2f : 1.6f) + sharpen_slider * MaxScale * 1.8f);
const float kSharpLimitMin = max((bool(NIS_HDR_MODE) ? 0.06f :0.1f), (bool(NIS_HDR_MODE) ? 0.1f : 0.14f) + sharpen_slider * LimitScale * (bool(NIS_HDR_MODE) ? 0.28f : 0.32f));
const float kSharpLimitMax = ((bool(NIS_HDR_MODE) ? 0.6f : 0.5f) + sharpen_slider * LimitScale * 0.6f);
const float kRatioNorm = 1.0f / (kMaxContrastRatio - kMinContrastRatio);
const float kSharpScaleY = 1.0f / (kSharpEndY - kSharpStartY);
const float kSharpStrengthScale = kSharpStrengthMax - kSharpStrengthMin;
const float kSharpLimitScale = kSharpLimitMax - kSharpLimitMin;
const float kContrastBoost = 1.0f;
const float kEps = 1.0f;
#define kScaleX (HOOKED_size.x / target_size.x)
#define kScaleY (HOOKED_size.y / target_size.y)
#define kSrcNormX HOOKED_pt.x
#define kSrcNormY HOOKED_pt.y
// HLSL to GLSL macros
#define saturate(x) clamp(x, 0, 1)
#define lerp(a, b, x) mix(a, b, x)
// CS Shared variables
shared float shPixelsY[kTileSize];
shared float shCoefScaler[kPhaseCount][kFilterSize];
shared float shCoefUSM[kPhaseCount][kFilterSize];
shared vec4 shEdgeMap[kEdgeMapSize];
// Shader code
vec4 GetEdgeMap(float p[4][4], int i, int j) {
const float g_0 = abs(p[0 + i][0 + j] + p[0 + i][1 + j] + p[0 + i][2 + j] - p[2 + i][0 + j] - p[2 + i][1 + j] - p[2 + i][2 + j]);
const float g_45 = abs(p[1 + i][0 + j] + p[0 + i][0 + j] + p[0 + i][1 + j] - p[2 + i][1 + j] - p[2 + i][2 + j] - p[1 + i][2 + j]);
const float g_90 = abs(p[0 + i][0 + j] + p[1 + i][0 + j] + p[2 + i][0 + j] - p[0 + i][2 + j] - p[1 + i][2 + j] - p[2 + i][2 + j]);
const float g_135 = abs(p[1 + i][0 + j] + p[2 + i][0 + j] + p[2 + i][1 + j] - p[0 + i][1 + j] - p[0 + i][2 + j] - p[1 + i][2 + j]);
const float g_0_90_max = max(g_0, g_90);
const float g_0_90_min = min(g_0, g_90);
const float g_45_135_max = max(g_45, g_135);
const float g_45_135_min = min(g_45, g_135);
float e_0_90 = 0;
float e_45_135 = 0;
if (g_0_90_max + g_45_135_max == 0)
{
return vec4(0, 0, 0, 0);
}
e_0_90 = min(g_0_90_max / (g_0_90_max + g_45_135_max), 1.0f);
e_45_135 = 1.0f - e_0_90;
bool c_0_90 = (g_0_90_max > (g_0_90_min * kDetectRatio)) && (g_0_90_max > kDetectThres) && (g_0_90_max > g_45_135_min);
bool c_45_135 = (g_45_135_max > (g_45_135_min * kDetectRatio)) && (g_45_135_max > kDetectThres) && (g_45_135_max > g_0_90_min);
bool c_g_0_90 = g_0_90_max == g_0;
bool c_g_45_135 = g_45_135_max == g_45;
float f_e_0_90 = (c_0_90 && c_45_135) ? e_0_90 : 1.0f;
float f_e_45_135 = (c_0_90 && c_45_135) ? e_45_135 : 1.0f;
float weight_0 = (c_0_90 && c_g_0_90) ? f_e_0_90 : 0.0f;
float weight_90 = (c_0_90 && !c_g_0_90) ? f_e_0_90 : 0.0f;
float weight_45 = (c_45_135 && c_g_45_135) ? f_e_45_135 : 0.0f;
float weight_135 = (c_45_135 && !c_g_45_135) ? f_e_45_135 : 0.0f;
return vec4(weight_0, weight_90, weight_45, weight_135);
}
void LoadFilterBanksSh(int i0, int di) {
// Load up filter banks to shared memory
// The work is spread over (kPhaseCount * 2) threads
for (int i = i0; i < kPhaseCount * 2; i += di)
{
int phase = i >> 1;
int vIdx = i & 1;
vec4 v = vec4(texelFetch(coef_scaler, ivec2(vIdx, phase), 0));
int filterOffset = vIdx * 4;
shCoefScaler[phase][filterOffset + 0] = v.x;
shCoefScaler[phase][filterOffset + 1] = v.y;
if (vIdx == 0)
{
shCoefScaler[phase][2] = v.z;
shCoefScaler[phase][3] = v.w;
}
v = vec4(texelFetch(coef_usm, ivec2(vIdx, phase), 0));
shCoefUSM[phase][filterOffset + 0] = v.x;
shCoefUSM[phase][filterOffset + 1] = v.y;
if (vIdx == 0)
{
shCoefUSM[phase][2] = v.z;
shCoefUSM[phase][3] = v.w;
}
}
}
float CalcLTI(float p0, float p1, float p2, float p3, float p4, float p5, int phase_index)
{
const bool selector = (phase_index <= kPhaseCount / 2);
float sel = selector ? p0 : p3;
const float a_min = min(min(p1, p2), sel);
const float a_max = max(max(p1, p2), sel);
sel = selector ? p2 : p5;
const float b_min = min(min(p3, p4), sel);
const float b_max = max(max(p3, p4), sel);
const float a_cont = a_max - a_min;
const float b_cont = b_max - b_min;
const float cont_ratio = max(a_cont, b_cont) / (min(a_cont, b_cont) + kEps);
return (1.0f - saturate((cont_ratio - kMinContrastRatio) * kRatioNorm)) * kContrastBoost;
}
vec4 GetInterpEdgeMap(const vec4 edge[2][2], float phase_frac_x, float phase_frac_y)
{
vec4 h0 = lerp(edge[0][0], edge[0][1], phase_frac_x);
vec4 h1 = lerp(edge[1][0], edge[1][1], phase_frac_x);
return lerp(h0, h1, phase_frac_y);
}
float EvalPoly6(const float pxl[6], int phase_int)
{
float y = 0.f;
{
for (int i = 0; i < 6; ++i)
{
y += shCoefScaler[phase_int][i] * pxl[i];
}
}
float y_usm = 0.f;
{
for (int i = 0; i < 6; ++i)
{
y_usm += shCoefUSM[phase_int][i] * pxl[i];
}
}
// let's compute a piece-wise ramp based on luma
const float y_scale = 1.0f - saturate((y * (1.0f / NIS_SCALE_FLOAT) - kSharpStartY) * kSharpScaleY);
// scale the ramp to sharpen as a function of luma
const float y_sharpness = y_scale * kSharpStrengthScale + kSharpStrengthMin;
y_usm *= y_sharpness;
// scale the ramp to limit USM as a function of luma
const float y_sharpness_limit = (y_scale * kSharpLimitScale + kSharpLimitMin) * y;
y_usm = min(y_sharpness_limit, max(-y_sharpness_limit, y_usm));
// reduce ringing
y_usm *= CalcLTI(pxl[0], pxl[1], pxl[2], pxl[3], pxl[4], pxl[5], phase_int);
return y + y_usm;
}
float FilterNormal(const float p[6][6], int phase_x_frac_int, int phase_y_frac_int)
{
float h_acc = 0.0f;
for (int j = 0; j < 6; ++j)
{
float v_acc = 0.0f;
for (int i = 0; i < 6; ++i)
{
v_acc += p[i][j] * shCoefScaler[phase_y_frac_int][i];
}
h_acc += v_acc * shCoefScaler[phase_x_frac_int][j];
}
// let's return the sum unpacked -> we can accumulate it later
return h_acc;
}
float AddDirFilters(float p[6][6], float phase_x_frac, float phase_y_frac, int phase_x_frac_int, int phase_y_frac_int, vec4 w)
{
float f = 0.f;
if (w.x > 0.0f)
{
// 0 deg filter
float interp0Deg[6];
{
for (int i = 0; i < 6; ++i)
{
interp0Deg[i] = lerp(p[i][2], p[i][3], phase_x_frac);
}
}
f += EvalPoly6(interp0Deg, phase_y_frac_int) * w.x;
}
if (w.y > 0.0f)
{
// 90 deg filter
float interp90Deg[6];
{
for (int i = 0; i < 6; ++i)
{
interp90Deg[i] = lerp(p[2][i], p[3][i], phase_y_frac);
}
}
f += EvalPoly6(interp90Deg, phase_x_frac_int) * w.y;
}
if (w.z > 0.0f)
{
//45 deg filter
float pphase_b45;
pphase_b45 = 0.5f + 0.5f * (phase_x_frac - phase_y_frac);
float temp_interp45Deg[7];
temp_interp45Deg[1] = lerp(p[2][1], p[1][2], pphase_b45);
temp_interp45Deg[3] = lerp(p[3][2], p[2][3], pphase_b45);
temp_interp45Deg[5] = lerp(p[4][3], p[3][4], pphase_b45);
{
pphase_b45 = pphase_b45 - 0.5f;
float a = (pphase_b45 >= 0.f) ? p[0][2] : p[2][0];
float b = (pphase_b45 >= 0.f) ? p[1][3] : p[3][1];
float c = (pphase_b45 >= 0.f) ? p[2][4] : p[4][2];
float d = (pphase_b45 >= 0.f) ? p[3][5] : p[5][3];
temp_interp45Deg[0] = lerp(p[1][1], a, abs(pphase_b45));
temp_interp45Deg[2] = lerp(p[2][2], b, abs(pphase_b45));
temp_interp45Deg[4] = lerp(p[3][3], c, abs(pphase_b45));
temp_interp45Deg[6] = lerp(p[4][4], d, abs(pphase_b45));
}
float interp45Deg[6];
float pphase_p45 = phase_x_frac + phase_y_frac;
if (pphase_p45 >= 1)
{
for (int i = 0; i < 6; i++)
{
interp45Deg[i] = temp_interp45Deg[i + 1];
}
pphase_p45 = pphase_p45 - 1;
}
else
{
for (int i = 0; i < 6; i++)
{
interp45Deg[i] = temp_interp45Deg[i];
}
}
f += EvalPoly6(interp45Deg, int(pphase_p45 * 64)) * w.z;
}
if (w.w > 0.0f)
{
//135 deg filter
float pphase_b135 = 0.5f * (phase_x_frac + phase_y_frac);
float temp_interp135Deg[7];
temp_interp135Deg[1] = lerp(p[3][1], p[4][2], pphase_b135);
temp_interp135Deg[3] = lerp(p[2][2], p[3][3], pphase_b135);
temp_interp135Deg[5] = lerp(p[1][3], p[2][4], pphase_b135);
{
pphase_b135 = pphase_b135 - 0.5f;
float a = (pphase_b135 >= 0.f) ? p[5][2] : p[3][0];
float b = (pphase_b135 >= 0.f) ? p[4][3] : p[2][1];
float c = (pphase_b135 >= 0.f) ? p[3][4] : p[1][2];
float d = (pphase_b135 >= 0.f) ? p[2][5] : p[0][3];
temp_interp135Deg[0] = lerp(p[4][1], a, abs(pphase_b135));
temp_interp135Deg[2] = lerp(p[3][2], b, abs(pphase_b135));
temp_interp135Deg[4] = lerp(p[2][3], c, abs(pphase_b135));
temp_interp135Deg[6] = lerp(p[1][4], d, abs(pphase_b135));
}
float interp135Deg[6];
float pphase_p135 = 1 + (phase_x_frac - phase_y_frac);
if (pphase_p135 >= 1)
{
for (int i = 0; i < 6; ++i)
{
interp135Deg[i] = temp_interp135Deg[i + 1];
}
pphase_p135 = pphase_p135 - 1;
}
else
{
for (int i = 0; i < 6; ++i)
{
interp135Deg[i] = temp_interp135Deg[i];
}
}
f += EvalPoly6(interp135Deg, int(pphase_p135 * 64)) * w.w;
}
return f;
}
void hook()
{
uvec2 blockIdx = gl_WorkGroupID.xy;
uint threadIdx = gl_LocalInvocationID.x;
// Figure out the range of pixels from input image that would be needed to be loaded for this thread-block
int dstBlockX = int(NIS_BLOCK_WIDTH * blockIdx.x);
int dstBlockY = int(NIS_BLOCK_HEIGHT * blockIdx.y);
const int srcBlockStartX = int(floor((dstBlockX + 0.5f) * kScaleX - 0.5f));
const int srcBlockStartY = int(floor((dstBlockY + 0.5f) * kScaleY - 0.5f));
const int srcBlockEndX = int(ceil((dstBlockX + NIS_BLOCK_WIDTH + 0.5f) * kScaleX - 0.5f));
const int srcBlockEndY = int(ceil((dstBlockY + NIS_BLOCK_HEIGHT + 0.5f) * kScaleY - 0.5f));
int numTilePixelsX = srcBlockEndX - srcBlockStartX + kSupportSize - 1;
int numTilePixelsY = srcBlockEndY - srcBlockStartY + kSupportSize - 1;
// round-up load region to even size since we're loading in 2x2 batches
numTilePixelsX += numTilePixelsX & 0x1;
numTilePixelsY += numTilePixelsY & 0x1;
const int numTilePixels = numTilePixelsX * numTilePixelsY;
// calculate the equivalent values for the edge map
const int numEdgeMapPixelsX = numTilePixelsX - kSupportSize + 2;
const int numEdgeMapPixelsY = numTilePixelsY - kSupportSize + 2;
const int numEdgeMapPixels = numEdgeMapPixelsX * numEdgeMapPixelsY;
// fill in input luma tile (shPixelsY) in batches of 2x2 pixels
// we use texture gather to get extra support necessary
// to compute 2x2 edge map outputs too
{
for (uint i = threadIdx * 2; i < uint(numTilePixels) >> 1; i += NIS_THREAD_GROUP_SIZE * 2)
{
uint py = (i / numTilePixelsX) * 2;
uint px = i % numTilePixelsX;
// 0.5 to be in the center of texel
// - (kSupportSize - 1) / 2 to shift by the kernel support size
float kShift = 0.5f - (kSupportSize - 1) / 2;
const float tx = (srcBlockStartX + px + kShift) * kSrcNormX;
const float ty = (srcBlockStartY + py + kShift) * kSrcNormY;
float p[2][2];
#ifdef HOOKED_gather
{
const vec4 sY = HOOKED_gather(vec2(tx, ty), 0);
p[0][0] = sY.w;
p[0][1] = sY.z;
p[1][0] = sY.x;
p[1][1] = sY.y;
}
#else
for (int j = 0; j < 2; j++)
{
for (int k = 0; k < 2; k++)
{
const float px = HOOKED_tex(vec2(tx + k * kSrcNormX, ty + j * kSrcNormY)).r;
p[j][k] = px;
}
}
#endif
const uint idx = py * kTilePitch + px;
shPixelsY[idx] = float(p[0][0]);
shPixelsY[idx + 1] = float(p[0][1]);
shPixelsY[idx + kTilePitch] = float(p[1][0]);
shPixelsY[idx + kTilePitch + 1] = float(p[1][1]);
}
}
groupMemoryBarrier();
barrier();
{
// fill in the edge map of 2x2 pixels
for (uint i = threadIdx * 2; i < uint(numEdgeMapPixels) >> 1; i += NIS_THREAD_GROUP_SIZE * 2)
{
uint py = (i / numEdgeMapPixelsX) * 2;
uint px = i % numEdgeMapPixelsX;
const uint edgeMapIdx = py * kEdgeMapPitch + px;
uint tileCornerIdx = (py+1) * kTilePitch + px + 1;
float p[4][4];
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 4; k++)
{
p[j][k] = shPixelsY[tileCornerIdx + j * kTilePitch + k];
}
}
shEdgeMap[edgeMapIdx] = vec4(GetEdgeMap(p, 0, 0));
shEdgeMap[edgeMapIdx + 1] = vec4(GetEdgeMap(p, 0, 1));
shEdgeMap[edgeMapIdx + kEdgeMapPitch] = vec4(GetEdgeMap(p, 1, 0));
shEdgeMap[edgeMapIdx + kEdgeMapPitch + 1] = vec4(GetEdgeMap(p, 1, 1));
}
}
LoadFilterBanksSh(int(threadIdx), NIS_THREAD_GROUP_SIZE);
groupMemoryBarrier();
barrier();
// output coord within a tile
const ivec2 pos = ivec2(uint(threadIdx) % uint(NIS_BLOCK_WIDTH), uint(threadIdx) / uint(NIS_BLOCK_WIDTH));
// x coord inside the output image
const int dstX = dstBlockX + pos.x;
// x coord inside the input image
const float srcX = (0.5f + dstX) * kScaleX - 0.5f;
// nearest integer part
const int px = int(floor(srcX) - srcBlockStartX);
// fractional part
const float fx = srcX - floor(srcX);
// discretized phase
const int fx_int = int(fx * kPhaseCount);
for (int k = 0; k < NIS_BLOCK_WIDTH * NIS_BLOCK_HEIGHT / NIS_THREAD_GROUP_SIZE; ++k)
{
// y coord inside the output image
const int dstY = dstBlockY + pos.y + k * (NIS_THREAD_GROUP_SIZE / NIS_BLOCK_WIDTH);
// y coord inside the input image
const float srcY = (0.5f + dstY) * kScaleY - 0.5f;
// nearest integer part
const int py = int(floor(srcY) - srcBlockStartY);
// fractional part
const float fy = srcY - floor(srcY);
// discretized phase
const int fy_int = int(fy * kPhaseCount);
// generate weights for directional filters
const int startEdgeMapIdx = py * kEdgeMapPitch + px;
vec4 edge[2][2];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
// need to shift edge map sampling since it's a 2x2 centered inside 6x6 grid
edge[i][j] = shEdgeMap[startEdgeMapIdx + (i * kEdgeMapPitch) + j];
}
}
const vec4 w = GetInterpEdgeMap(edge, fx, fy) * NIS_SCALE_INT;
// load 6x6 support to regs
const int startTileIdx = py * kTilePitch + px;
float p[6][6];
{
for (int i = 0; i < 6; ++i)
{
for (int j = 0; j < 6; ++j)
{
p[i][j] = shPixelsY[startTileIdx + i * kTilePitch + j];
}
}
}
// weigth for luma
const float baseWeight = NIS_SCALE_FLOAT - w.x - w.y - w.z - w.w;
// final luma is a weighted product of directional & normal filters
float opY = 0;
// get traditional scaler filter output
opY += FilterNormal(p, fx_int, fy_int) * baseWeight;
// get directional filter bank output
opY += AddDirFilters(p, fx, fy, fx_int, fy_int, w);
// do bilinear tap for luma upscaling
vec4 op = HOOKED_tex(vec2((srcX + 0.5f) * kSrcNormX, (srcY + 0.5f) * kSrcNormY));
const float corr = opY * (1.0f / NIS_SCALE_FLOAT) - op.r;
op.x += corr;
imageStore(out_image, ivec2(dstX, dstY), op);
}
}
//!TEXTURE coef_scaler
//!SIZE 2 64
//!FORMAT rgba32f
//!FILTER NEAREST
00000000000000000000803f0000000000000000000000000000000000000000ed0d3e3ba91350bc0000803fd044583c89d25ebb0000000000000000000000003b70ce3b16fbcbbcb29d7f3f645ddc3c89d2debb000000000000000000000000e02d103c98dd13bda4df7e3fe7fb293d55c128bc6f12033a00000000000000005bb13f3c812642bd5b427e3ff931663d1ea768bc6f12033a00000000000000001ea7683cfaed6bbdfb5c7d3fbc05923d744694bc6f12033a0000000000000000b9fc873c03098abda3017c3fc5feb23d5839b4bc6f12833a0000000000000000075f983cbf0e9cbdfa7e7a3ff4fdd43dd044d8bca69bc43a00000000000000009eefa73c7b14aebdde02793f22fdf63d4850fcbc6f12033b0000000000000000ec51b83ced0dbebd22fd763f4d840d3ee02d10bd52491d3b0000000000000000efc9c33c5f07cebdb81e753f098a1f3e9c3322bded0d3e3b0000000000000000a913d03c88f4dbbd01de723fa1f8313e7dd033bd89d25e3b0000000000000000d044d83cf90fe9bd4e62703f9487453e82e247bde02d903b0000000000000000d3bce33cb3eaf3bd849e6d3f50fc583e88f45bbd2e90a03b0000000000000000faedeb3cdbf9febd83c06a3f448b6c3e44fa6dbdca54c13b00000000000000008e06f03c6f8104be82e2673f1283803e250681bd3b70ce3b0000000000000000b537f83ccc7f08be6f81643f83c08a3e280f8bbdd734ef3b00000000000000004850fc3c16fb0bbe97ff603f7d3f953e2b1895bdb9fc073c00000000000000004850fc3c60760fbe849e5d3f77be9f3ec0ec9ebd075f183c00000000000000006e34003dbc0512beecc0593ffa7eaa3ec3f5a8bd55c1283c00000000000000006e34003dcff713bec6dc553f7d3fb53ec5feb2bd3480373c00000000000000006e34003d068115bea5bd513f8941c03ec807bdbd82e2473c00000000000000006e34003d2b8716befb5c4d3f0c02cb3ea60ac6bdf775603c00000000000000004850fc3c197317be151d493fa245d63ea913d0bdd7346f3c0000000000000000b537f83c197317be34a2443f933ae13e8716d9bd24977f3c0000000000000000211ff43c197317bec520403f9f3cec3e6519e2bdb9fc873c00000000000000008e06f03c2b8716be083d3b3fab3ef73ed5e7eabd7446943c0000000000000000faedeb3c068115be143f363f2041013ffc18f3bde3a59b3c0000000000000000d3bce33ccff713bee561313f27c2063fb515fbbd0ad7a33c000000000000000040a4df3cce8812be68222c3f2d430c3f250601bec520b03c0000000000000000d044d83c857c10bee71d273fa5bd113f810405beec51b83c0000000000000000a913d03c5f070ebe6ade213fe71d173fb9fc07be5bb1bf3c000000000000000082e2c73cf1f40abe287e1c3f287e1c3ff1f40abe82e2c73c00000000000000005bb1bf3cb9fc07bee71d173f6ade213f5f070ebea913d03c0000000000000000ec51b83c810405bea5bd113fe71d273f857c10bed044d83c0000000000000000c520b03c250601be2d430c3f68222c3fce8812be40a4df3c00000000000000000ad7a33cb515fbbd27c2063fe561313fcff713bed3bce33c0000000000000000e3a59b3cfc18f3bd2041013f143f363f068115befaedeb3c00000000000000007446943cd5e7eabdab3ef73e083d3b3f2b8716be8e06f03c0000000000000000b9fc873c6519e2bd9f3cec3ec520403f197317be211ff43c000000000000000024977f3c8716d9bd933ae13e34a2443f197317beb537f83c0000000000000000d7346f3ca913d0bda245d63e151d493f197317be4850fc3c0000000000000000f775603ca60ac6bd0c02cb3efb5c4d3f2b8716be6e34003d000000000000000082e2473cc807bdbd8941c03ea5bd513f068115be6e34003d00000000000000003480373cc5feb2bd7d3fb53ec6dc553fcff713be6e34003d000000000000000055c1283cc3f5a8bdfa7eaa3eecc0593fbc0512be6e34003d0000000000000000075f183cc0ec9ebd77be9f3e849e5d3f60760fbe4850fc3c0000000000000000b9fc073c2b1895bd7d3f953e97ff603f16fb0bbe4850fc3c0000000000000000d734ef3b280f8bbd83c08a3e6f81643fcc7f08beb537f83c00000000000000003b70ce3b250681bd1283803e82e2673f6f8104be8e06f03c0000000000000000ca54c13b44fa6dbd448b6c3e83c06a3fdbf9febdfaedeb3c00000000000000002e90a03b88f45bbd50fc583e849e6d3fb3eaf3bdd3bce33c0000000000000000e02d903b82e247bd9487453e4e62703ff90fe9bdd044d83c000000000000000089d25e3b7dd033bda1f8313e01de723f88f4dbbda913d03c0000000000000000ed0d3e3b9c3322bd098a1f3eb81e753f5f07cebdefc9c33c000000000000000052491d3be02d10bd4d840d3e22fd763fed0dbebdec51b83c00000000000000006f12033b4850fcbc22fdf63dde02793f7b14aebd9eefa73c0000000000000000a69bc43ad044d8bcf4fdd43dfa7e7a3fbf0e9cbd075f983c00000000000000006f12833a5839b4bcc5feb23da3017c3f03098abdb9fc873c00000000000000006f12033a744694bcbc05923dfb5c7d3ffaed6bbd1ea7683c00000000000000006f12033a1ea768bcf931663d5b427e3f812642bd5bb13f3c00000000000000006f12033a55c128bce7fb293da4df7e3f98dd13bde02d103c00000000000000000000000089d2debb645ddc3cb29d7f3f16fbcbbc3b70ce3b00000000000000000000000089d25ebbd044583c0000803fa91350bced0d3e3b0000000000000000
//!TEXTURE coef_usm
//!SIZE 2 64
//!FORMAT rgba32f
//!FILTER NEAREST
0000000027a019bf27a0993f27a019bf00000000000000000000000000000000ed0d3e3b1ac01bbf006f993fe71d17bfed0d3ebb0000000000000000000000002e90a03bfb5c1dbff90f993fe63f14bf89d2debb6f12033a0000000000000000d734ef3b1b9e1ebf2731983fd3de10bf55c128bc000000000000000000000000075f183cb29d1fbfcb10973fff210dbffe6577bc0000000000000000000000003480373c4e6220bf48bf953fde0209bf77be9fbc6f12033a000000000000000082e2473c128320bfe63f943f34a204bf3d2cd4bc6f12033a00000000000000001ea7683cd3de20bfbe9f923fc52000bfdcd701bd6f12033a000000000000000024977f3c4e6220bfa54e903f7d3ff5be091b1ebd6f12033a0000000000000000b9fc873cb29d1fbf6ff08d3fe7fbe9be5af539bd6f12833a0000000000000000e02d903c20631ebf4f408b3fe483debe3ee859bd6f12833a00000000000000007446943cff211dbf696f883fbc05d2be6de77bbda69bc43a0000000000000000e3a59b3ccc5d1bbf1b2f853ff8c2c4be4df38ebda69bc43a000000000000000077be9f3cecc019bf910f823f22fdb6be5305a3bd6f12033b00000000000000000ad7a33cbec117bfc4427d3f423ea8be10e9b7bd52491d3b00000000000000000ad7a33cf4fd14bf7d3f753f50fc98be3b01cdbded0d3e3b00000000000000000ad7a33c05a312bf0de06d3f5eba89be6519e2bd89d25e3b00000000000000000ad7a33c3bdf0fbf8fc2653fb37b72beb515fbbd24977f3b00000000000000009eefa73cb1bf0cbfc4425d3faa8251bef08509bee02d903b00000000000000000ad7a33c637f09bf6f81543f69002fbe190416be2e90a03b000000000000000077be9f3c4f1e06bfcc5d4b3f16fb0bbe418222be7cf2b03b000000000000000077be9f3c3cbd02bf4182423fce19d1bda08930beca54c13b0000000000000000e3a59b3c5b42febe151d393f4bea84bddbf93ebe3b70ce3b0000000000000000075f983c99bbf6bef2412f3ffaedebbc287e4cbe89d2de3b0000000000000000075f983c6900efbe4260253f075f183cac8b5bbed734ef3b0000000000000000e02d903c27c2e6be0c021b3fca32443dfa7e6abeb9fc073c00000000000000004d158c3c77bedfbea5bd113f57ecaf3d6c787abee02d103c000000000000000026e4833c22fdd6beab3e073f1283003e810485be2e90203c000000000000000026e4833cf241cfbe7502fa3ed578293e3b018dbe55c1283c0000000000000000fe65773cb003c7be143fe63e97ff503ef4fd94be0e4f2f3c00000000000000001ea7683cd200bebe857cd03e6c787a3eadfa9cbe5bb13f3c0000000000000000f775603c1904b6bea301bc3ebc05923e0b46a5be82e2473c0000000000000000d044583cd6c5adbeb003a73eb003a73ed6c5adbed044583c000000000000000082e2473c0b46a5bebc05923ea301bc3e1904b6bef775603c00000000000000005bb13f3cadfa9cbe6c787a3e857cd03ed200bebe1ea7683c00000000000000000e4f2f3cf4fd94be97ff503e143fe63eb003c7befe65773c000000000000000055c1283c3b018dbed578293e7502fa3ef241cfbe26e4833c00000000000000002e90203c810485be1283003eab3e073f22fdd6be26e4833c0000000000000000e02d103c6c787abe57ecaf3da5bd113f77bedfbe4d158c3c0000000000000000b9fc073cfa7e6abeca32443d0c021b3f27c2e6bee02d903c0000000000000000d734ef3bac8b5bbe075f183c4260253f6900efbe075f983c000000000000000089d2de3b287e4cbefaedebbcf2412f3f99bbf6be075f983c00000000000000003b70ce3bdbf93ebe4bea84bd151d393f5b42febee3a59b3c0000000000000000ca54c13ba08930bece19d1bd4182423f3cbd02bf77be9f3c00000000000000007cf2b03b418222be16fb0bbecc5d4b3f4f1e06bf77be9f3c00000000000000002e90a03b190416be69002fbe6f81543f637f09bf0ad7a33c0000000000000000e02d903bf08509beaa8251bec4425d3fb1bf0cbf9eefa73c000000000000000024977f3bb515fbbdb37b72be8fc2653f3bdf0fbf0ad7a33c000000000000000089d25e3b6519e2bd5eba89be0de06d3f05a312bf0ad7a33c0000000000000000ed0d3e3b3b01cdbd50fc98be7d3f753ff4fd14bf0ad7a33c000000000000000052491d3b10e9b7bd423ea8bec4427d3fbec117bf0ad7a33c00000000000000006f12033b5305a3bd22fdb6be910f823fecc019bf77be9f3c0000000000000000a69bc43a4df38ebdf8c2c4be1b2f853fcc5d1bbfe3a59b3c0000000000000000a69bc43a6de77bbdbc05d2be696f883fff211dbf7446943c00000000000000006f12833a3ee859bde483debe4f408b3f20631ebfe02d903c00000000000000006f12833a5af539bde7fbe9be6ff08d3fb29d1fbfb9fc873c00000000000000006f12033a091b1ebd7d3ff5bea54e903f4e6220bf24977f3c00000000000000006f12033adcd701bdc52000bfbe9f923fd3de20bf1ea7683c00000000000000006f12033a3d2cd4bc34a204bfe63f943f128320bf82e2473c00000000000000006f12033a77be9fbcde0209bf48bf953f4e6220bf3480373c000000000000000000000000fe6577bcff210dbfcb10973fb29d1fbf075f183c00000000000000000000000055c128bcd3de10bf2731983f1b9e1ebfd734ef3b00000000000000006f12033a89d2debbe63f14bff90f993ffb5c1dbf2e90a03b000000000000000000000000ed0d3ebbe71d17bf006f993f1ac01bbfed0d3e3b0000000000000000

1
.config/mpv/submodules Symbolic link
View File

@@ -0,0 +1 @@
../mpv-modules

View File

@@ -35,8 +35,8 @@ mpd_connection_timeout = 5
## Needed for tag editor and file operations to work. ## Needed for tag editor and file operations to work.
## ##
# mpd_music_dir = "~/Music" # mpd_music_dir = "~/Music"
mpd_music_dir = "/jellyfin/music" mpd_music_dir = "/truenas/jellyfin/music"
# #
#mpd_crossfade_time = 5 #mpd_crossfade_time = 5

View File

@@ -6,11 +6,6 @@ require("core.highlights")
-- require("core.lsp-notifications") -- require("core.lsp-notifications")
require("utils.extensions") require("utils.extensions")
require("utils.telescope_extra").setup() require("utils.telescope_extra").setup()
require("utils.git_paste").setup({ telescope_key = "<leader>pg" }) require("utils.functions.git_paste").setup({ telescope_key = "<leader>pg" })
require("utils.treesitter.parsers.hyprlang") require("utils.treesitter.parsers.hyprlang")
require("utils.hyprland.lsp") require("utils.hyprland.lsp")
-- vim.notify = function(msg, level, opts)
-- print("Notification debug:", msg, level, vim.inspect(opts))
-- -- Call original notify
-- require("notify")(msg, level, opts)
-- end

View File

@@ -1,46 +1,55 @@
local catppuccin = require("catppuccin.palettes").get_palette("macchiato")
local sethl = vim.api.nvim_set_hl
-- Customization for Pmenu -- Customization for Pmenu
vim.api.nvim_set_hl(0, "PmenuSel", { bg = "#282C34", fg = "NONE" }) sethl(0, "PmenuSel", { bg = "#282C34", fg = "NONE" })
vim.api.nvim_set_hl(0, "Pmenu", { fg = "#C5CDD9", bg = "dodgerblue" }) sethl(0, "Pmenu", { fg = "#C5CDD9", bg = "dodgerblue" })
vim.api.nvim_set_hl(0, "CmpItemAbbrDeprecated", { fg = "#7E8294", bg = "NONE", strikethrough = true }) sethl(0, "CmpItemAbbrDeprecated", { fg = "#7E8294", bg = "NONE", strikethrough = true })
vim.api.nvim_set_hl(0, "CmpItemAbbrMatch", { fg = "#82AAFF", bg = "NONE", bold = true }) sethl(0, "CmpItemAbbrMatch", { fg = "#82AAFF", bg = "NONE", bold = true })
vim.api.nvim_set_hl(0, "CmpItemAbbrMatchFuzzy", { fg = "#82AAFF", bg = "NONE", bold = true }) sethl(0, "CmpItemAbbrMatchFuzzy", { fg = "#82AAFF", bg = "NONE", bold = true })
vim.api.nvim_set_hl(0, "CmpItemMenu", { fg = "#C792EA", bg = "NONE", italic = true }) sethl(0, "CmpItemMenu", { fg = "#C792EA", bg = "NONE", italic = true })
vim.api.nvim_set_hl(0, "CmpItemKindField", { fg = "#EED8DA", bg = "#B5585F" }) sethl(0, "CmpItemKindField", { fg = "#EED8DA", bg = "#B5585F" })
vim.api.nvim_set_hl(0, "CmpItemKindProperty", { fg = "#EED8DA", bg = "#B5585F" }) sethl(0, "CmpItemKindProperty", { fg = "#EED8DA", bg = "#B5585F" })
vim.api.nvim_set_hl(0, "CmpItemKindEvent", { fg = "#EED8DA", bg = "#B5585F" }) sethl(0, "CmpItemKindEvent", { fg = "#EED8DA", bg = "#B5585F" })
vim.api.nvim_set_hl(0, "CmpItemKindText", { fg = "#C3E88D", bg = "#9FBD73" }) sethl(0, "CmpItemKindText", { fg = "#C3E88D", bg = "#9FBD73" })
vim.api.nvim_set_hl(0, "CmpItemKindEnum", { fg = "#C3E88D", bg = "#9FBD73" }) sethl(0, "CmpItemKindEnum", { fg = "#C3E88D", bg = "#9FBD73" })
vim.api.nvim_set_hl(0, "CmpItemKindKeyword", { fg = "#C3E88D", bg = "#9FBD73" }) sethl(0, "CmpItemKindKeyword", { fg = "#C3E88D", bg = "#9FBD73" })
vim.api.nvim_set_hl(0, "CmpItemKindConstant", { fg = "#FFE082", bg = "#D4BB6C" }) sethl(0, "CmpItemKindConstant", { fg = "#FFE082", bg = "#D4BB6C" })
vim.api.nvim_set_hl(0, "CmpItemKindConstructor", { fg = "#FFE082", bg = "#D4BB6C" }) sethl(0, "CmpItemKindConstructor", { fg = "#FFE082", bg = "#D4BB6C" })
vim.api.nvim_set_hl(0, "CmpItemKindReference", { fg = "#FFE082", bg = "#D4BB6C" }) sethl(0, "CmpItemKindReference", { fg = "#FFE082", bg = "#D4BB6C" })
vim.api.nvim_set_hl(0, "CmpItemKindFunction", { fg = "#EADFF0", bg = "#A377BF" }) sethl(0, "CmpItemKindFunction", { fg = "#EADFF0", bg = "#A377BF" })
vim.api.nvim_set_hl(0, "CmpItemKindStruct", { fg = "#EADFF0", bg = "#A377BF" }) sethl(0, "CmpItemKindStruct", { fg = "#EADFF0", bg = "#A377BF" })
vim.api.nvim_set_hl(0, "CmpItemKindClass", { fg = "#EADFF0", bg = "#A377BF" }) sethl(0, "CmpItemKindClass", { fg = "#EADFF0", bg = "#A377BF" })
vim.api.nvim_set_hl(0, "CmpItemKindModule", { fg = "#EADFF0", bg = "#A377BF" }) sethl(0, "CmpItemKindModule", { fg = "#EADFF0", bg = "#A377BF" })
vim.api.nvim_set_hl(0, "CmpItemKindOperator", { fg = "#EADFF0", bg = "#A377BF" }) sethl(0, "CmpItemKindOperator", { fg = "#EADFF0", bg = "#A377BF" })
vim.api.nvim_set_hl(0, "CmpItemKindVariable", { fg = "#C5CDD9", bg = "#7E8294" }) sethl(0, "CmpItemKindVariable", { fg = "#C5CDD9", bg = "#7E8294" })
vim.api.nvim_set_hl(0, "CmpItemKindFile", { fg = "#C5CDD9", bg = "#7E8294" }) sethl(0, "CmpItemKindFile", { fg = "#C5CDD9", bg = "#7E8294" })
vim.api.nvim_set_hl(0, "CmpItemKindUnit", { fg = "#F5EBD9", bg = "#D4A959" }) sethl(0, "CmpItemKindUnit", { fg = "#F5EBD9", bg = "#D4A959" })
vim.api.nvim_set_hl(0, "CmpItemKindSnippet", { fg = "#F5EBD9", bg = "#D4A959" }) sethl(0, "CmpItemKindSnippet", { fg = "#F5EBD9", bg = "#D4A959" })
vim.api.nvim_set_hl(0, "CmpItemKindFolder", { fg = "#F5EBD9", bg = "#D4A959" }) sethl(0, "CmpItemKindFolder", { fg = "#F5EBD9", bg = "#D4A959" })
vim.api.nvim_set_hl(0, "CmpItemKindMethod", { fg = "#DDE5F5", bg = "#6C8ED4" }) sethl(0, "CmpItemKindMethod", { fg = "#DDE5F5", bg = "#6C8ED4" })
vim.api.nvim_set_hl(0, "CmpItemKindValue", { fg = "#DDE5F5", bg = "#6C8ED4" }) sethl(0, "CmpItemKindValue", { fg = "#DDE5F5", bg = "#6C8ED4" })
vim.api.nvim_set_hl(0, "CmpItemKindEnumMember", { fg = "#DDE5F5", bg = "#6C8ED4" }) sethl(0, "CmpItemKindEnumMember", { fg = "#DDE5F5", bg = "#6C8ED4" })
vim.api.nvim_set_hl(0, "CmpItemKindInterface", { fg = "#D8EEEB", bg = "#58B5A8" }) sethl(0, "CmpItemKindInterface", { fg = "#D8EEEB", bg = "#58B5A8" })
vim.api.nvim_set_hl(0, "CmpItemKindColor", { fg = "#D8EEEB", bg = "#58B5A8" }) sethl(0, "CmpItemKindColor", { fg = "#D8EEEB", bg = "#58B5A8" })
vim.api.nvim_set_hl(0, "CmpItemKindTypeParameter", { fg = "#D8EEEB", bg = "#58B5A8" }) sethl(0, "CmpItemKindTypeParameter", { fg = "#D8EEEB", bg = "#58B5A8" })
vim.api.nvim_set_hl(0, "FloatBorder", { fg = "#8aadf4", bold = true }) sethl(0, "FloatBorder", { fg = "#8aadf4", bold = true })
vim.api.nvim_set_hl(0, "LspSignatureActiveParameter", { fg = "#89b4fa", bg = "NONE", bold = true }) sethl(0, "LspSignatureActiveParameter", { fg = "#89b4fa", bg = "NONE", bold = true })
vim.api.nvim_set_hl(0, "CmpBorder", { fg = "#8aadf4", bold = true }) sethl(0, "CmpBorder", { fg = "#8aadf4", bold = true })
vim.api.nvim_set_hl(0, "CmpDocBorder", { fg = "#8aadf4", bold = true }) sethl(0, "CmpDocBorder", { fg = "#8aadf4", bold = true })
sethl(0, "SnacksIndent1", { fg = catppuccin.red })
sethl(0, "SnacksIndent3", { fg = catppuccin.peach })
sethl(0, "SnacksIndent4", { fg = catppuccin.yellow })
sethl(0, "SnacksIndent5", { fg = catppuccin.green })
sethl(0, "SnacksIndent6", { fg = catppuccin.sky })
sethl(0, "SnacksIndent7", { fg = catppuccin.blue })
sethl(0, "SnacksIndent8", { fg = catppuccin.mauve })

View File

@@ -1,11 +1,12 @@
local map = vim.keymap.set local map = vim.keymap.set
local term = require("utils.terminal")
local map_from_table = require("utils.keymaps.converters.from_table").set_keybindings local map_from_table = require("utils.keymaps.converters.from_table").set_keybindings
local add_to_whichkey = require("utils.keymaps.converters.whichkey").addToWhichKey local add_to_whichkey = require("utils.keymaps.converters.whichkey").addToWhichKey
local telescope_paste_img = require("utils.telescope_extra").find_and_paste_image
local mkdir_under_cursor = require("utils.functions.mkdir_under_cursor").setup()
local term = require("utils.terminal")
local term_factory = term.term_factory local term_factory = term.term_factory
local term_toggle = term.term_toggle local term_toggle = term.term_toggle
local opts = { silent = true, noremap = true }
local nosilent = { silent = false, noremap = true } local nosilent = { silent = false, noremap = true }
-- Leader key -- Leader key
@@ -17,7 +18,7 @@ vim.g.maplocalleader = ","
--- @param command string The command to execute --- @param command string The command to execute
--- @param description string Description of the command --- @param description string Description of the command
--- @return nil --- @return nil
function create_custom_command(trigger, command, description) local create_custom_command = function(trigger, command, description)
vim.api.nvim_create_user_command(trigger, command, { desc = description }) vim.api.nvim_create_user_command(trigger, command, { desc = description })
end end
-- Custom commands -- Custom commands
@@ -34,7 +35,7 @@ local basic_mappings = {
{ key = "<C-u>", cmd = "<C-u>zz", desc = "Scroll up and center", mode = "n" }, { key = "<C-u>", cmd = "<C-u>zz", desc = "Scroll up and center", mode = "n" },
{ key = "n", cmd = "nzzzv", desc = "Next search result and center", mode = "n" }, { key = "n", cmd = "nzzzv", desc = "Next search result and center", mode = "n" },
{ key = "N", cmd = "Nzzzv", desc = "Previous search result and center", mode = "n" }, { key = "N", cmd = "Nzzzv", desc = "Previous search result and center", mode = "n" },
{ key = "<leader>p", cmd = '"_dP', desc = "Paste without yanking", mode = "x", group = "Paste in place" }, { key = "<leader>pp", cmd = '"_dP', desc = "Paste without yanking", mode = "x" },
{ key = "<", cmd = "<gv", desc = "Reselect after indent", mode = "v" }, { key = "<", cmd = "<gv", desc = "Reselect after indent", mode = "v" },
{ key = ">", cmd = ">gv", desc = "Reselect after indent", mode = "v" }, { key = ">", cmd = ">gv", desc = "Reselect after indent", mode = "v" },
{ key = "J", cmd = ":m '>+1<CR>gv=gv", desc = "Move line down", mode = "v" }, { key = "J", cmd = ":m '>+1<CR>gv=gv", desc = "Move line down", mode = "v" },
@@ -162,7 +163,7 @@ local lsp_mappings = {
{ mode = "n", key = "<leader>gb", cmd = ":Gitsigns blame<CR>", group = "Git Blame" }, { mode = "n", key = "<leader>gb", cmd = ":Gitsigns blame<CR>", group = "Git Blame" },
{ mode = "n", key = "gi", cmd = ":Telescope lsp_implementations<CR>", group = "Telescope Implementations" }, { mode = "n", key = "gi", cmd = ":Telescope lsp_implementations<CR>", group = "Telescope Implementations" },
{ mode = "n", key = "gj", cmd = ":Telescope jumplist<CR>", group = "Telescope Jumplist" }, { mode = "n", key = "gj", cmd = ":Telescope jumplist<CR>", group = "Telescope Jumplist" },
{ mode = "n", key = "gr", cmd = ":Telescope lsp_references<CR>", goup = "LSP References" }, { mode = "n", key = "gr", cmd = ":Telescope lsp_references<CR>", group = "LSP References" },
{ mode = "n", key = "gs", cmd = vim.lsp.buf.signature_help }, { mode = "n", key = "gs", cmd = vim.lsp.buf.signature_help },
-- { mode = "n", key = "K", cmd = vim.lsp.buf.hover }, -- { mode = "n", key = "K", cmd = vim.lsp.buf.hover },
{ mode = "n", key = "<leader>ca", cmd = vim.lsp.buf.code_action, group = "Code" }, { mode = "n", key = "<leader>ca", cmd = vim.lsp.buf.code_action, group = "Code" },
@@ -196,10 +197,11 @@ local lsp_mappings = {
{ {
mode = "n", mode = "n",
key = "<leader>cDp", key = "<leader>cDp",
cmd = ":lua vim.diagnostic.goto_prev()<CR<CR>", cmd = ":lua vim.diagnostic.goto_prev()<CR>",
group = "Goto Previous Preview", group = "Goto Previous Preview",
}, },
{ mode = "n", key = "<leader>cl", cmd = ":lua vim.diagnostic.setloclist()<CR>", group = "Set Loclist" }, { mode = "n", key = "<leader>cl", cmd = ":lua vim.diagnostic.setloclist()<CR>", group = "Set Loclist" },
{ mode = "n", key = "<leader>Clr", cmd = ":LspRestart<CR>", group = "Restart LSP" },
{ {
mode = "n", mode = "n",
key = "<leader>cPs", key = "<leader>cPs",
@@ -214,23 +216,45 @@ local lsp_mappings = {
-- {{{ Code Companion Mappings -- {{{ Code Companion Mappings
local code_companion_mappings = { local code_companion_mappings = {
{ mode = "n", key = "<leader>cp", cmd = ":vert Copilot panel<CR>", group = "Copilot Panel" }, { mode = "n", key = "<leader>cp", cmd = ":vert Copilot panel<CR>", group = "Copilot Panel" },
{ mode = "n", key = "<leader>oc", cmd = ":CodeCompanionChat Toggle<CR>", group = "Toggle Codecompanion" }, {
mode = "n",
key = "<leader>Cf",
cmd = function()
local chat = require("codecompanion").chat
chat({ window_opts = { height = 1.0, layout = "buffer" } })
end,
group = "Codecompanion Fullscreen",
},
{
mode = "n",
key = "<leader>Ch",
cmd = function()
local chat = require("codecompanion").chat
chat({ window_opts = { height = 0.24, layout = "horizontal", position = "bottom" } })
end,
group = "Codecompanion Horizontal Split",
},
{ mode = "n", key = "<leader>Cc", cmd = ":CodeCompanionChat Toggle<CR>", group = "Toggle Codecompanion" }, { mode = "n", key = "<leader>Cc", cmd = ":CodeCompanionChat Toggle<CR>", group = "Toggle Codecompanion" },
{ mode = "n", key = "<leader>oc", cmd = ":CodeCompanionChat Toggle<CR>", group = "Toggle Codecompanion" },
{ {
mode = "n", mode = "n",
key = "<leader>Ci", key = "<leader>Ci",
cmd = ":CodeCompanion #{buffer} ", cmd = function()
vim.api.nvim_feedkeys(":CodeCompanion #{buffer} ", "n", false)
end,
group = "Inline CodeCompanion", group = "Inline CodeCompanion",
opts = nosilent, opts = nosilent,
}, },
{ mode = "n", key = "<leader>CT", cmd = ":CodeCompanionChat Toggle<CR>", group = "CodeCompanion Toggle" }, { mode = "n", key = "<leader>Ct", cmd = ":CodeCompanionChat Toggle<CR>", group = "CodeCompanion Toggle" },
{ mode = "n", key = "<leader>Ca", cmd = ":CodeCompanionActions<CR>", group = "CodeCompanion Actions" }, { mode = "n", key = "<leader>CA", cmd = ":CodeCompanionActions<CR>", group = "CodeCompanion Actions" },
{ mode = "v", key = "<leader>Cc", cmd = ":CodeCompanionChat Add<CR>", group = "CodeCompanion Add" }, { mode = "v", key = "<leader>Ca", cmd = ":CodeCompanionChat Add<CR>", group = "CodeCompanion Add" },
{ {
mode = "v", mode = "v",
key = "<leader>Ci", key = "<leader>Ci",
cmd = ":CodeCompanion #{buffer} ", cmd = function()
group = "CodeCompanion #{buffer}", vim.api.nvim_feedkeys(":CodeCompanion #{buffer} ", "n", false)
end,
group = "CodeCompanion Inline",
opts = nosilent, opts = nosilent,
}, },
{ mode = "v", key = "<leader>Ce", cmd = ":CodeCompanion /explain<CR>", group = "CodeCompanion /explain" }, { mode = "v", key = "<leader>Ce", cmd = ":CodeCompanion /explain<CR>", group = "CodeCompanion /explain" },
@@ -246,7 +270,7 @@ local telescope_mappings = {
mode = "n", mode = "n",
key = "//", key = "//",
cmd = ":Telescope current_buffer_fuzzy_find previewer=false<CR>", cmd = ":Telescope current_buffer_fuzzy_find previewer=false<CR>",
"Current buffer fuzzy find", desc = "Current buffer fuzzy find",
}, },
{ {
mode = "n", mode = "n",
@@ -284,6 +308,14 @@ local telescope_mappings = {
cmd = ":Telescope noice theme=dropdown layout_config={width=0.75}<CR>", cmd = ":Telescope noice theme=dropdown layout_config={width=0.75}<CR>",
group = "Telescope Noice", group = "Telescope Noice",
}, },
{
mode = "n",
key = "<leader>Ti",
cmd = function()
telescope_paste_img()
end,
desc = "Find and Paste Image",
},
{ {
mode = "n", mode = "n",
key = "<leader>ff", key = "<leader>ff",
@@ -355,6 +387,25 @@ local telescope_mappings = {
{ mode = "n", key = "<leader>sF", cmd = ":Telescope fidget<CR>", group = "Fidget" }, { mode = "n", key = "<leader>sF", cmd = ":Telescope fidget<CR>", group = "Fidget" },
{ mode = "n", key = "<leader>sg", cmd = ":Telescope live_grep<CR>", group = "Live grep" }, { mode = "n", key = "<leader>sg", cmd = ":Telescope live_grep<CR>", group = "Live grep" },
{ mode = "n", key = "<leader>sh", cmd = ":Telescope command_history<CR>", group = "Command history" }, { mode = "n", key = "<leader>sh", cmd = ":Telescope command_history<CR>", group = "Command history" },
{
mode = "n",
key = "<leader>sn",
cmd = function()
Snacks.win({
file = vim.api.nvim_get_runtime_file("doc/news.txt", false)[1],
width = 0.6,
height = 0.6,
wo = {
spell = false,
wrap = false,
signcolumn = "yes",
statuscolumn = " ",
conceallevel = 3,
},
})
end,
group = "News",
},
{ mode = "n", key = "<leader>sm", cmd = ":Telescope man_pages<CR>", group = "Man pages" }, { mode = "n", key = "<leader>sm", cmd = ":Telescope man_pages<CR>", group = "Man pages" },
{ mode = "n", key = "<leader>s/", cmd = ":Telescope search_history<CR>", group = "Search history" }, { mode = "n", key = "<leader>s/", cmd = ":Telescope search_history<CR>", group = "Search history" },
{ mode = "n", key = "<leader>gc", cmd = ":Telescope git_commits<CR>", group = "Git commits" }, { mode = "n", key = "<leader>gc", cmd = ":Telescope git_commits<CR>", group = "Git commits" },
@@ -366,17 +417,33 @@ local telescope_mappings = {
-- {{{ File Explorer Mappings (i guess) -- {{{ File Explorer Mappings (i guess)
local file_explorer_mappings = { local file_explorer_mappings = {
{ mode = "n", key = "<leader>nt", cmd = ":NvimTreeToggle<CR>" }, { mode = "n", key = "<leader>nt", cmd = ":NvimTreeToggle<CR>" },
{ mode = "n", key = "<leader>nc", cmd = ":lua require('notify').dismiss()<CR>" }, { mode = "n", key = "<leader>nc", cmd = ":lua Snacks.notifier.hide()<CR>" },
{ mode = "n", key = "<leader>D", cmd = ":Dotenv .env<CR>", group = "Dotenv" }, { mode = "n", key = "<leader>nh", cmd = ":lua Snacks.notifier.show_history()<CR>" },
} }
-- }}} -- }}}
-- {{{ Misc Utilities Mappings -- {{{ Misc Utilities Mappings
local misc_utilities_mappings = { local misc_utilities_mappings = {
{ mode = "n", key = "<leader>x", cmd = "<cmd>!chmod +x %<CR>", group = "Make Executable" }, { mode = "n", key = "<leader>x", cmd = "<cmd>!chmod +x %<CR>", group = "Make Executable" },
{ mode = "n", key = "<leader>y", cmd = '"+', group = "System Yank" }, { mode = "n", key = "<leader>y", cmd = '"+y', group = "System Yank" },
{ mode = "v", key = "<leader>y", cmd = '"+', group = "System Yank" }, { mode = "v", key = "<leader>y", cmd = '"+y', group = "System Yank" },
{ mode = "n", key = "<leader>sc", cmd = ":nohls<CR>", group = "Search" }, { mode = "n", key = "<leader>sc", cmd = ":nohls<CR>", group = "Search" },
{
mode = "n",
key = "<leader>m",
cmd = function()
mkdir_under_cursor()
end,
group = "mkdir under cursor",
},
{
mode = "v",
key = "<leader>m",
cmd = function()
mkdir_under_cursor()
end,
group = "mkdir selection",
},
} }
-- }}} -- }}}
@@ -483,12 +550,17 @@ local diffview_mappings = {
desc = "Refresh diffview", desc = "Refresh diffview",
group = "Git", group = "Git",
}, },
{
mode = "n",
key = "<leader>gg",
cmd = ":lua Snacks.lazygit()<CR>",
desc = "Open Lazygit",
},
} }
-- }}} -- }}}
--{{{ Custom Terminals --{{{ Custom Terminals
local programs_map = { local programs_map = {
gg = { cmd = "lazygit", display_name = "lazygit", direction = "tab", hidden = true },
op = { cmd = "ipython", display_name = "ipython", direction = "vertical", hidden = true }, op = { cmd = "ipython", display_name = "ipython", direction = "vertical", hidden = true },
oP = { oP = {
cmd = "ipython", cmd = "ipython",
@@ -528,7 +600,7 @@ end
vim.cmd("autocmd! TermOpen term://* lua set_terminal_keymaps()") vim.cmd("autocmd! TermOpen term://* lua set_terminal_keymaps()")
--}}} --}}}
-- {{{ NVIM-IMAGE -- {{{ IMAGE
local image_mappings = { local image_mappings = {
{ {
@@ -544,6 +616,14 @@ local image_mappings = {
cmd = ":lua require('image').enable()<CR>", cmd = ":lua require('image').enable()<CR>",
desc = "Enable image rendering", desc = "Enable image rendering",
}, },
{
mode = "n",
key = "<leader>pi",
cmd = function()
telescope_paste_img()
end,
desc = "Find and Paste Image",
},
} }
-- }}} -- }}}
@@ -554,6 +634,7 @@ add_to_whichkey(nil, { key = "<leader>c", group = "Code" })
add_to_whichkey(nil, { key = "<leader>ca", group = "Code Actions" }) add_to_whichkey(nil, { key = "<leader>ca", group = "Code Actions" })
add_to_whichkey(nil, { key = "<leader>cc", group = "Calls" }) add_to_whichkey(nil, { key = "<leader>cc", group = "Calls" })
add_to_whichkey(nil, { key = "<leader>C", group = "CodeCompanion" }) add_to_whichkey(nil, { key = "<leader>C", group = "CodeCompanion" })
add_to_whichkey(nil, { key = "<leader>cL", group = "LSP" })
add_to_whichkey(nil, { key = "<leader>d", group = "ODIS" }) add_to_whichkey(nil, { key = "<leader>d", group = "ODIS" })
add_to_whichkey(nil, { key = "<leader>f", group = "Find" }) add_to_whichkey(nil, { key = "<leader>f", group = "Find" })
add_to_whichkey(nil, { key = "<leader>g", group = "Git" }) add_to_whichkey(nil, { key = "<leader>g", group = "Git" })
@@ -563,7 +644,8 @@ add_to_whichkey(nil, { key = "<leader>i", group = "Image" })
add_to_whichkey(nil, { key = "<leader>j", group = "AnyJump" }) add_to_whichkey(nil, { key = "<leader>j", group = "AnyJump" })
add_to_whichkey(nil, { key = "<leader>N", group = "Noice" }) add_to_whichkey(nil, { key = "<leader>N", group = "Noice" })
-- add_to_whichkey(nil, { key = "<leader>o", group = "Open" }) -- add_to_whichkey(nil, { key = "<leader>o", group = "Open" })
add_to_whichkey(nil, { key = "<leader>p", group = "Paste in Place" }) add_to_whichkey(nil, { key = "<leader>p", group = "Paste" })
add_to_whichkey(nil, { key = "<leader>pg", group = "Paste Git Raw" })
add_to_whichkey(nil, { key = "<leader>s", group = "Search" }) add_to_whichkey(nil, { key = "<leader>s", group = "Search" })
add_to_whichkey(nil, { key = "<leader>t", group = "Terminal" }) add_to_whichkey(nil, { key = "<leader>t", group = "Terminal" })
add_to_whichkey(nil, { key = "<leader>T", group = "Telescope" }) add_to_whichkey(nil, { key = "<leader>T", group = "Telescope" })

View File

@@ -1,6 +1,6 @@
return { return {
"sontungexpt/better-diagnostic-virtual-text", "sontungexpt/better-diagnostic-virtual-text",
event = "LspAttach", -- event = "LspAttach",
enabled = true, enabled = true,
config = function() config = function()
local diagnostic = require("better-diagnostic-virtual-text") local diagnostic = require("better-diagnostic-virtual-text")
@@ -130,7 +130,7 @@ return {
down_arrow = "", down_arrow = "",
above = false, -- the virtual text will be displayed above the line above = false, -- the virtual text will be displayed above the line
}, },
priority = 2003, -- the priority of virtual text priority = 10000, -- the priority of virtual text
inline = true, inline = true,
}) })
end, end,

View File

@@ -49,8 +49,8 @@ return {
local s = " " local s = " "
for e, n in pairs(diagnostics_dict) do for e, n in pairs(diagnostics_dict) do
local sym = e == "error" and "" local sym = e == "error" and ""
or e == "hint" and "" or e == "hint" and ""
or (e == "warning" and "" or "") or (e == "warning" and "" or "")
s = s .. n .. sym s = s .. n .. sym
end end
return s return s

View File

@@ -1,56 +1,92 @@
return { return {
"catppuccin/nvim", "catppuccin/nvim",
name = "catppuccin", name = "catppuccin",
priority = 1000, priority = 1000,
opts = { opts = {
flavour = "macchiato", -- latte, frappe, macchiato, mocha flavour = "macchiato", -- latte, frappe, macchiato, mocha
term_colors = true, -- sets terminal colors (e.g. `g:terminal_color_0`) transparent_background = false, -- disables setting the background color.
integrations = { float = {
cmp = true, transparent = false, -- enable transparent floating windows
gitsigns = true, solid = false, -- use solid styling for floating windows, see |winborder|
nvimtree = true, },
mini = { show_end_of_buffer = false, -- shows the '~' characters after the end of buffers
enabled = true, term_colors = true, -- sets terminal colors (e.g. `g:terminal_color_0`)
indentscope_color = "", dim_inactive = {
}, enabled = false, -- dims the background color of inactive window
bufferline = true, shade = "dark",
dashboard = true, percentage = 0.15, -- percentage of the shade to apply to the inactive window
fidget = true, },
indent_blankline = { no_italic = false, -- Force no italic
enabled = true, no_bold = false, -- Force no bold
scope_color = "lavendar", -- catppuccin color (eg. `lavender`) Default: text no_underline = false, -- Force no underline
colored_indent_levels = true, styles = { -- Handles the styles of general hi groups (see `:h highlight-args`):
}, comments = { "italic" }, -- Change the style of comments
copilot_vim = true, conditionals = { "italic" },
native_lsp = { loops = { "bold" },
enabled = true, functions = { "bold", "italic" },
virtual_text = { keywords = { "bold" },
errors = { "italic" }, strings = {},
hints = { "italic" }, variables = { "bold" },
warnings = { "italic" }, numbers = { "bold" },
information = { "italic" }, booleans = { "bold" },
ok = { "italic" }, properties = { "bold" },
}, types = { "bold" },
underlines = { operators = { "bold" },
errors = { "underline" }, -- miscs = {}, -- Uncomment to turn off hard-coded styles
hints = { "underline" }, },
warnings = { "underline" }, color_overrides = {},
information = { "underline" }, custom_highlights = {},
ok = { "underline" }, default_integrations = true,
}, auto_integrations = false,
inlay_hints = { integrations = {
background = true, cmp = true,
}, gitsigns = true,
}, nvimtree = true,
notify = true, mini = {
treesitter = true, enabled = true,
rainbow_delimiters = true, indentscope_color = "",
telescope = { },
enabled = true, bufferline = true,
-- style = "nvchad" dashboard = true,
}, diffview = true,
which_key = true fidget = true,
-- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations) noice = true,
} indent_blankline = {
} enabled = true,
scope_color = "lavendar", -- catppuccin color (eg. `lavender`) Default: text
colored_indent_levels = true,
},
copilot_vim = true,
native_lsp = {
enabled = true,
virtual_text = {
errors = { "italic" },
hints = { "italic" },
warnings = { "italic" },
information = { "italic" },
ok = { "italic" },
},
underlines = {
errors = { "underline" },
hints = { "underline" },
warnings = { "underline" },
information = { "underline" },
ok = { "underline" },
},
inlay_hints = {
background = true,
},
},
notify = true,
treesitter = true,
rainbow_delimiters = true,
render_markdown = true,
telescope = {
enabled = true,
-- style = "nvchad"
},
which_key = true,
-- For more plugins integrations please scroll down (https://github.com/catppuccin/nvim#integrations)
},
},
} }

View File

@@ -8,98 +8,128 @@ return {
}, },
opts = { opts = {
adapters = { adapters = {
copilot = function() -- {{{ HTTP
return require("codecompanion.adapters").extend("copilot", { http = {
schema = { -- {{{ COPILOT
name = "copilot", copilot = function()
opts = { return require("codecompanion.adapters").extend("copilot", {
stream = true, schema = {
tools = true, name = "copilot",
vision = true, opts = {
}, stream = true,
features = { tools = true,
text = true, vision = true,
tokens = true, },
}, features = {
model = { text = true,
-- default = "claude-3.7-sonnet-thought", tokens = true,
-- default = "o3-mini", },
-- default = "gemini-2.0-flash-001", model = {
default = "gpt-4.1", -- default = "claude-3.7-sonnet-thought",
-- default = "gpt-4o", -- default = "o3-mini",
-- default = "o3-mini-2025-01-31", -- default = "gemini-2.0-flash-001",
-- choices = { default = "claude-haiku-4.5",
-- ["o3-mini-2025-01-31"] = { opts = { can_reason = true } }, -- default = "gpt-4o",
-- ["o1-2024-12-17"] = { opts = { can_reason = true } }, -- default = "o3-mini-2025-01-31",
-- ["o1-mini-2024-09-12"] = { opts = { can_reason = true } }, -- choices = {
-- "gpt-4o-2024-08-06", -- ["o3-mini-2025-01-31"] = { opts = { can_reason = true } },
-- "claude-3.7-sonnet-thought", -- ["o1-2024-12-17"] = { opts = { can_reason = true } },
-- "claude-3.7-sonnet", -- ["o1-mini-2024-09-12"] = { opts = { can_reason = true } },
-- "claude-3.5-sonnet", -- "gpt-4o-2024-08-06",
-- "gemini-2.0-flash-001", -- "claude-3.7-sonnet-thought",
-- "claude-3.7-sonnet",
-- "claude-3.5-sonnet",
-- "gemini-2.0-flash-001",
-- },
},
-- max_tokens = {
-- default = 65536,
-- }, -- },
}, },
-- max_tokens = { })
-- default = 65536, end,
-- }, -- }}}
}, -- {{{ LLAMA_CPP
}) llama_cpp = function()
end, return require("codecompanion.adapters").extend("openai_compatible", {
llama_cpp = function() name = "llama.cpp",
return require("codecompanion.adapters").extend("openai_compatible", { formatted_name = "llama.cpp",
name = "llama.cpp", opts = {
formatted_name = "llama.cpp", stream = false,
opts = {
stream = false,
},
schema = {
-- model = {
-- default = "qwen2.5-coder-14b-instruct",
-- choices = {
-- ["qwen2.5-coder-14b-instruct"] = { opts = { can_reason = true } },
-- ["/models/lmstudio-community/DeepSeek-R1-Distill-Qwen-7B-GGUF/DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf"] = {
-- opts = { can_reason = true },
-- },
-- ["/models/lmstudio-community/Qwen2.5-7B-Instruct-1M-GGUF/Qwen2.5-7B-Instruct-1M-Q4_K_M.gguf"] = {
-- opts = { can_reason = true },
-- },
-- },
-- },
temperature = {
order = 2,
mapping = "parameters",
type = "number",
optional = true,
default = 0.2,
validate = function(n)
return n >= 0 and n <= 2, "Must be between 0 and 2"
end,
}, },
}, schema = {
env = { -- model = {
url = "http://localhost:8080", -- default = "qwen2.5-coder-14b-instruct",
chat_url = "/v1/chat/completions", -- choices = {
}, -- ["qwen2.5-coder-14b-instruct"] = { opts = { can_reason = true } },
}) -- ["/models/lmstudio-community/DeepSeek-R1-Distill-Qwen-7B-GGUF/DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf"] = {
end, -- opts = { can_reason = true },
openrouter = function() -- },
return require("codecompanion.adapters").extend("openai_compatible", { -- ["/models/lmstudio-community/Qwen2.5-7B-Instruct-1M-GGUF/Qwen2.5-7B-Instruct-1M-Q4_K_M.gguf"] = {
env = { -- opts = { can_reason = true },
url = "https://openrouter.ai/api", -- },
api_key = "cmd:cat $HOME/.openrouterapikey", -- },
chat_url = "/v1/chat/completions", -- },
}, temperature = {
schema = { order = 2,
model = { mapping = "parameters",
default = "google/gemini-2.5-pro-exp-03-25:free", type = "number",
-- default = "deepseek/deepseek-chat-v3-0324:free", optional = true,
-- default = "google/gemini-2.0-flash-thinking-exp:free", default = 0.2,
-- default = "deepseek/deepseek-r1-distill-qwen-32b:free", validate = function(n)
-- default = "qwen/qwen-2.5-coder-32b-instruct:free", return n >= 0 and n <= 2, "Must be between 0 and 2"
end,
},
}, },
}, env = {
}) url = "http://localhost:8080",
end, chat_url = "/v1/chat/completions",
},
})
end,
-- }}}
-- {{{ OPENROUTER
openrouter = function()
return require("codecompanion.adapters").extend("openai_compatible", {
env = {
url = "https://openrouter.ai/api",
api_key = "cmd:cat $HOME/.openrouterapikey",
chat_url = "/v1/chat/completions",
},
schema = {
model = {
default = "google/gemini-2.5-pro-exp-03-25:free",
-- default = "deepseek/deepseek-chat-v3-0324:free",
-- default = "google/gemini-2.0-flash-thinking-exp:free",
-- default = "deepseek/deepseek-r1-distill-qwen-32b:free",
-- default = "qwen/qwen-2.5-coder-32b-instruct:free",
},
},
})
end,
-- }}}
},
-- }}}
-- {{{ ACP
acp = {
gemini_cli = function()
return require("codecompanion.adapters").extend("gemini_cli", {
defaults = {
auth_method = "oauth-personal", -- "oauth-personal"|"gemini-api-key"|"vertex-ai"
mcpServers = {},
timeout = 20000, -- 20 seconds
},
})
end,
codex = function()
return require("codecompanion.adapters").extend("codex", {
defaults = {
auth_method = "chatgpt", -- "openai-api-key"|"codex-api-key"|"chatgpt"
},
})
end,
},
-- }}}
}, },
strategies = { strategies = {
chat = { chat = {
@@ -141,6 +171,17 @@ return {
}, },
}, },
}, },
opts = {
---Decorate the user message before it's sent to the LLM
---@param message string
---@param adapter CodeCompanion.Adapter
---@param context table
---@return string
prompt_decorator = function(message, adapter, context)
return string.format([[<prompt>%s</prompt>]], message)
end,
completion_provider = "cmp",
},
}, },
inline = { inline = {
adapter = "copilot", adapter = "copilot",
@@ -187,6 +228,55 @@ return {
diff = { diff = {
enabled = true, enabled = true,
provider = "mini_diff", provider = "mini_diff",
provider_opts = {
-- Options for inline diff provider
inline = {
layout = "buffer", -- float|buffer - Where to display the diff
diff_signs = {
signs = {
text = "", -- Sign text for normal changes
reject = "", -- Sign text for rejected changes in super_diff
highlight_groups = {
addition = "DiagnosticOk",
deletion = "DiagnosticError",
modification = "DiagnosticWarn",
},
},
-- Super Diff options
icons = {
accepted = "",
rejected = "",
},
colors = {
accepted = "DiagnosticOk",
rejected = "DiagnosticError",
},
},
opts = {
context_lines = 3, -- Number of context lines in hunks
dim = 25, -- Background dim level for floating diff (0-100, [100 full transparent], only applies when layout = "float")
full_width_removed = true, -- Make removed lines span full width
show_keymap_hints = true, -- Show "gda: accept | gdr: reject" hints above diff
show_removed = true, -- Show removed lines as virtual text
},
},
-- Options for the split provider
split = {
close_chat_at = 240, -- Close an open chat buffer if the total columns of your display are less than...
layout = "vertical", -- vertical|horizontal split
opts = {
"internal",
"filler",
"closeoff",
"algorithm:histogram", -- https://adamj.eu/tech/2024/01/18/git-improve-diff-histogram/
"indent-heuristic", -- https://blog.k-nut.eu/better-git-diffs
"followwrap",
"linematch:120",
},
},
},
}, },
---Customize how tokens are displayed ---Customize how tokens are displayed
---@param tokens number ---@param tokens number
@@ -210,8 +300,16 @@ return {
}, },
}, },
}, },
memory = {
opts = {
chat = {
enabled = true,
},
},
},
}, },
init = function() init = function()
require("plugins.codecompanion.fidget-spinner"):init() require("utils.codecompanion.fidget-spinner"):init()
require("utils.codecompanion.extmarks").setup()
end, end,
} }

View File

@@ -1,5 +1,7 @@
return { return {
"zbirenbaum/copilot.lua", "zbirenbaum/copilot.lua",
cmd = "Copilot",
event = "InsertEnter",
opts = { opts = {
panel = { panel = {
enabled = true, enabled = true,
@@ -49,7 +51,29 @@ return {
listCount = 10, -- #completions for panel listCount = 10, -- #completions for panel
inlineSuggestCount = 5, -- #completions for getCompletions inlineSuggestCount = 5, -- #completions for getCompletions
}, },
telemetry = {
telemetryLevel = "all",
},
}, },
}, },
copilot_node_command = "node", -- Node.js version must be > 20
workspace_folders = {},
-- copilot_model = "",
disable_limit_reached_message = false, -- Set to `true` to suppress completion limit reached popup
logger = {
file = vim.fn.stdpath("log") .. "/copilot-lua.log",
file_log_level = vim.log.levels.OFF,
print_log_level = vim.log.levels.WARN,
trace_lsp = "off", -- "off" | "messages" | "verbose"
trace_lsp_progress = false,
log_lsp_messages = false,
},
root_dir = function()
return vim.fs.dirname(vim.fs.find(".git", { upward = true })[1])
end,
server = {
type = "nodejs", -- "nodejs" | "binary"
custom_server_filepath = nil,
},
}, },
} }

View File

@@ -1,36 +0,0 @@
return {
"nvimdev/dashboard-nvim",
event = "VimEnter",
opts = {
theme = "hyper",
config = {
week_header = {
enable = true,
},
shortcut = {
{ desc = "󰊳 Update", group = "@property", action = "Lazy update", key = "u" },
{
icon = "",
icon_hl = "@variable",
desc = "Files",
group = "Label",
action = "Telescope find_files",
key = "f",
},
{
desc = " Apps",
group = "DiagnosticHint",
action = "Telescope app",
key = "a",
},
{
desc = " dotfiles",
group = "Number",
action = "Telescope ~/.config",
key = "d",
},
},
},
},
depends = { "nvim-tree/nvim-web-devicons" },
}

View File

@@ -0,0 +1,113 @@
return {
"HakonHarnes/img-clip.nvim",
event = "VeryLazy",
opts = {
default = {
-- file and directory options
dir_path = function()
return vim.fn.expand("%:t:r")
end, ---@type string | fun(): string
extension = "png", ---@type string | fun(): string
file_name = "%Y-%m-%d-%H-%M-%S", ---@type string | fun(): string
use_absolute_path = false, ---@type boolean | fun(): boolean
relative_to_current_file = false, ---@type boolean | fun(): boolean
-- logging options
verbose = true, ---@type boolean | fun(): boolean
-- template options
template = "$FILE_PATH", ---@type string | fun(context: table): string
url_encode_path = false, ---@type boolean | fun(): boolean
relative_template_path = true, ---@type boolean | fun(): boolean
use_cursor_in_template = true, ---@type boolean | fun(): boolean
insert_mode_after_paste = true, ---@type boolean | fun(): boolean
insert_template_after_cursor = true, ---@type boolean | fun(): boolean
-- prompt options
prompt_for_file_name = true, ---@type boolean | fun(): boolean
show_dir_path_in_prompt = false, ---@type boolean | fun(): boolean
-- base64 options
max_base64_size = 10, ---@type number | fun(): number
embed_image_as_base64 = false, ---@type boolean | fun(): boolean
-- image options
process_cmd = "", ---@type string | fun(): string
copy_images = false, ---@type boolean | fun(): boolean
download_images = true, ---@type boolean | fun(): boolean
-- drag and drop options
drag_and_drop = {
enabled = true, ---@type boolean | fun(): boolean
insert_mode = false, ---@type boolean | fun(): boolean
},
},
-- filetype specific options
filetypes = {
markdown = {
url_encode_path = true, ---@type boolean | fun(): boolean
template = "![$CURSOR]($FILE_PATH)", ---@type string | fun(context: table): string
download_images = false, ---@type boolean | fun(): boolean
},
vimwiki = {
url_encode_path = true, ---@type boolean | fun(): boolean
template = "![$CURSOR]($FILE_PATH)", ---@type string | fun(context: table): string
download_images = false, ---@type boolean | fun(): boolean
},
html = {
template = '<img src="$FILE_PATH" alt="$CURSOR">', ---@type string | fun(context: table): string
},
tex = {
relative_template_path = false, ---@type boolean | fun(): boolean
template = [[
\begin{figure}[h]
\centering
\includegraphics[width=0.8\textwidth]{$FILE_PATH}
\caption{$CURSOR}
\label{fig:$LABEL}
\end{figure}
]], ---@type string | fun(context: table): string
},
typst = {
template = [[
#figure(
image("$FILE_PATH", width: 80%),
caption: [$CURSOR],
) <fig-$LABEL>
]], ---@type string | fun(context: table): string
},
rst = {
template = [[
.. image:: $FILE_PATH
:alt: $CURSOR
:width: 80%
]], ---@type string | fun(context: table): string
},
asciidoc = {
template = 'image::$FILE_PATH[width=80%, alt="$CURSOR"]', ---@type string | fun(context: table): string
},
org = {
template = [=[
#+BEGIN_FIGURE
[[file:$FILE_PATH]]
#+CAPTION: $CURSOR
#+NAME: fig:$LABEL
#+END_FIGURE
]=], ---@type string | fun(context: table): string
},
},
-- file, directory, and custom triggered options
files = {}, ---@type table | fun(): table
dirs = {}, ---@type table | fun(): table
custom = {}, ---@type table | fun(): table
},
}

View File

@@ -1,35 +0,0 @@
return {
"lukas-reineke/indent-blankline.nvim",
config = function()
local highlight = {
"RainbowRed",
"RainbowYellow",
"RainbowBlue",
"RainbowOrange",
"RainbowGreen",
"RainbowViolet",
"RainbowCyan",
}
local hooks = require("ibl.hooks")
-- create the highlight groups in the highlight setup hook, so they are reset
-- every time the colorscheme changes
hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#ED8796" })
vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#EED49F" })
vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#8AADF4" })
vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#F5A97F" })
vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#A6DA95" })
vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C6A0F6" })
vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#8BD5CA" })
end)
vim.g.rainbow_delimiters = { highlight = highlight }
require("ibl").setup({
scope = { highlight = highlight },
exclude = { filetypes = { "dashboard" } },
})
hooks.register(hooks.type.SCOPE_HIGHLIGHT, hooks.builtin.scope_highlight_from_extmark)
end,
}

View File

@@ -69,7 +69,6 @@ return {
end end
end, end,
}) })
vim.lsp.enable(lsp)
elseif lsp == "basedpyright" then elseif lsp == "basedpyright" then
vim.lsp.config(lsp, { vim.lsp.config(lsp, {
capabilities = capabilities, capabilities = capabilities,
@@ -97,7 +96,6 @@ return {
}, },
}, },
}) })
vim.lsp.enable(lsp)
elseif lsp == "ruff" then elseif lsp == "ruff" then
vim.api.nvim_create_autocmd("LspAttach", { vim.api.nvim_create_autocmd("LspAttach", {
group = vim.api.nvim_create_augroup("lsp_attach_disable_ruff_hover", { clear = true }), group = vim.api.nvim_create_augroup("lsp_attach_disable_ruff_hover", { clear = true }),
@@ -114,15 +112,12 @@ return {
desc = "LSP: Disable hover capability from Ruff", desc = "LSP: Disable hover capability from Ruff",
}) })
vim.lsp.config(lsp, { vim.lsp.config(lsp, {
capabilities = capabilities, settings = {
init_options = { configuration = vim.fn.stdpath("config") .. "/lua/utils/ruff.toml",
settings = { logLevel = "info",
configuration = vim.fn.stdpath("config") .. "lua/utils/ruff.toml",
},
}, },
}) })
end end
vim.lsp.config(lsp, { capabilities = capabilities })
vim.lsp.enable(lsp) vim.lsp.enable(lsp)
end end
end, end,

View File

@@ -3,48 +3,83 @@ return {
dependencies = { dependencies = {
"nvim-lua/plenary.nvim", "nvim-lua/plenary.nvim",
}, },
cmd = "MCPHub", build = "npm install -g mcp-hub@latest", -- Installs `mcp-hub` node binary globally
build = "bundled_build.lua", -- Bundles mcp-hub locally
config = function() config = function()
vim.notify = require("notify")
require("mcphub").setup({ require("mcphub").setup({
use_bundled_binary = true, -- Use local binary --- `mcp-hub` binary related options-------------------
port = 37373, -- Port for MCP Hub Express API config = vim.fn.expand("~/.config/mcphub/servers.json"), -- Absolute path to MCP Servers config file (will create if not exists)
config = vim.fn.expand("~/.config/mcphub/servers.json"), -- Config file path port = 37373, -- The port `mcp-hub` server listens to
native_servers = {}, -- add your native servers here shutdown_delay = 5 * 60 * 000, -- Delay in ms before shutting down the server when last instance closes (default: 5 minutes)
auto_approve = true, use_bundled_binary = false, -- Use local `mcp-hub` binary (set this to true when using build = "bundled_build.lua")
mcp_request_timeout = 60000, --Max time allowed for a MCP tool or resource to execute in milliseconds, set longer for long running tasks
global_env = {}, -- Global environment variables available to all MCP servers (can be a table or a function returning a table)
workspace = {
enabled = true, -- Enable project-local configuration files
look_for = { ".mcphub/servers.json", ".vscode/mcp.json", ".cursor/mcp.json" }, -- Files to look for when detecting project boundaries (VS Code format supported)
reload_on_dir_changed = true, -- Automatically switch hubs on DirChanged event
port_range = { min = 40000, max = 41000 }, -- Port range for generating unique workspace ports
get_port = nil, -- Optional function returning custom port number. Called when generating ports to allow custom port assignment logic
},
---Chat-plugin related options-----------------
auto_approve = false, -- Auto approve mcp tool calls
auto_toggle_mcp_servers = true, -- Let LLMs start and stop MCP servers automatically
extensions = { extensions = {
avante = {}, avante = {
codecompanion = { make_slash_commands = true, -- make /slash commands from MCP server prompts
show_result_in_chat = true, -- Show tool results in chat
make_vars = true, -- Create chat variables from resources
make_slash_commands = true, -- make /slash_commands from MCP server prompts
}, },
}, },
-- UI configuration --- Plugin specific options-------------------
native_servers = {}, -- add your custom lua native servers here
builtin_tools = {
edit_file = {
parser = {
track_issues = true,
extract_inline_content = true,
},
locator = {
fuzzy_threshold = 0.8,
enable_fuzzy_matching = true,
},
ui = {
go_to_origin_on_complete = true,
keybindings = {
accept = ".",
reject = ",",
next = "n",
prev = "p",
accept_all = "ga",
reject_all = "gr",
},
},
},
},
ui = { ui = {
window = { window = {
width = 0.8, -- Window width (0-1 ratio) width = 0.8, -- 0-1 (ratio); "50%" (percentage); 50 (raw number)
height = 0.8, -- Window height (0-1 ratio) height = 0.8, -- 0-1 (ratio); "50%" (percentage); 50 (raw number)
border = "rounded", -- Window border style align = "center", -- "center", "top-left", "top-right", "bottom-left", "bottom-right", "top", "bottom", "left", "right"
relative = "editor", -- Window positioning relative = "editor",
zindex = 50, -- Window stack order zindex = 50,
border = "rounded", -- "none", "single", "double", "rounded", "solid", "shadow"
},
wo = { -- window-scoped options (vim.wo)
winhl = "Normal:MCPHubNormal,FloatBorder:MCPHubBorder",
}, },
}, },
json_decode = nil, -- Custom JSON parser function (e.g., require('json5').parse for JSON5 support)
-- Event callbacks on_ready = function(hub)
on_ready = function(hub) end, -- Called when hub is ready -- Called when hub is ready
end,
on_error = function(err) on_error = function(err)
vim.notify(err, "ERROR") -- Called on errors
end, -- Called on errors end,
-- Logging configuration
log = { log = {
level = vim.log.levels.WARN, -- Minimum log level level = vim.log.levels.WARN,
to_file = false, -- Enable file logging to_file = false,
file_path = nil, -- Custom log file path file_path = nil,
prefix = "MCPHub", -- Log message prefix prefix = "MCPHub",
}, },
}) })
end, end,

View File

@@ -1,63 +1,66 @@
return { return {
"echasnovski/mini.diff", "echasnovski/mini.diff",
depends = { "echasnovski/mini.nvim" }, depends = { "echasnovski/mini.nvim" },
opts = { config = function()
local diff = require("mini.diff")
diff.setup({
-- Options for how hunks are visualized -- Options for how hunks are visualized
view = { view = {
-- Visualization style. Possible values are 'sign' and 'number'. -- Visualization style. Possible values are 'sign' and 'number'.
-- Default: 'number' if line numbers are enabled, 'sign' otherwise. -- Default: 'number' if line numbers are enabled, 'sign' otherwise.
style = vim.go.number and "number" or "sign", style = vim.go.number and "number" or "sign",
-- Signs used for hunks with 'sign' view -- Signs used for hunks with 'sign' view
signs = { add = "", change = "", delete = "" }, signs = { add = "", change = "", delete = "" },
-- Priority of used visualization extmarks -- Priority of used visualization extmarks
priority = 199, priority = 199,
}, },
-- Source for how reference text is computed/updated/etc -- Source for how reference text is computed/updated/etc
-- Uses content from Git index by default -- Uses content from Git index by default
source = nil, source = diff.gen_source.none(),
-- Delays (in ms) defining asynchronous processes -- Delays (in ms) defining asynchronous processes
delay = { delay = {
-- How much to wait before update following every text change -- How much to wait before update following every text change
text_change = 200, text_change = 200,
}, },
-- Module mappings. Use `''` (empty string) to disable one. -- Module mappings. Use `''` (empty string) to disable one.
mappings = { mappings = {
-- Apply hunks inside a visual/operator region -- Apply hunks inside a visual/operator region
apply = "gh", apply = "gh",
-- Reset hunks inside a visual/operator region -- Reset hunks inside a visual/operator region
reset = "gH", reset = "gH",
-- Hunk range textobject to be used inside operator -- Hunk range textobject to be used inside operator
-- Works also in Visual mode if mapping differs from apply and reset -- Works also in Visual mode if mapping differs from apply and reset
textobject = "gh", textobject = "gh",
-- Go to hunk range in corresponding direction -- Go to hunk range in corresponding direction
goto_first = "[H", goto_first = "[H",
goto_prev = "[h", goto_prev = "[h",
goto_next = "]h", goto_next = "]h",
goto_last = "]H", goto_last = "]H",
}, },
-- Various options -- Various options
options = { options = {
-- Diff algorithm. See `:h vim.diff()`. -- Diff algorithm. See `:h vim.diff()`.
algorithm = "histogram", algorithm = "histogram",
-- Whether to use "indent heuristic". See `:h vim.diff()`. -- Whether to use "indent heuristic". See `:h vim.diff()`.
indent_heuristic = true, indent_heuristic = true,
-- The amount of second-stage diff to align lines (in Neovim>=0.9) -- The amount of second-stage diff to align lines (in Neovim>=0.9)
linematch = 60, linematch = 60,
-- Whether to wrap around edges during hunk navigation -- Whether to wrap around edges during hunk navigation
wrap_goto = false, wrap_goto = false,
}, },
}, })
end,
} }

View File

@@ -13,6 +13,7 @@ return {
format_done = "lsp_progress_done", format_done = "lsp_progress_done",
throttle = 1000 / 30, -- frequency to update lsp progress message throttle = 1000 / 30, -- frequency to update lsp progress message
view = "mini", view = "mini",
-- view = "notify",
}, },
-- override markdown rendering so that **cmp** and other plugins use **Treesitter** -- override markdown rendering so that **cmp** and other plugins use **Treesitter**
override = { override = {

View File

@@ -171,8 +171,8 @@ return {
sources = cmp.config.sources({ sources = cmp.config.sources({
{ name = "nvim_lsp_signature_help", group_index = 0 }, { name = "nvim_lsp_signature_help", group_index = 0 },
{ name = "lazydev", group_index = 0 }, { name = "lazydev", group_index = 0 },
{ name = "copilot", group_index = 0 },
{ name = "nvim_lsp", group_index = 1 }, { name = "nvim_lsp", group_index = 1 },
{ name = "copilot", group_index = 1 },
{ name = "codecompanion", group_index = 2 }, { name = "codecompanion", group_index = 2 },
{ name = "async_path", group_index = 2 }, { name = "async_path", group_index = 2 },
{ name = "nvim_lsp_document_symbol", group_index = 2 }, { name = "nvim_lsp_document_symbol", group_index = 2 },

View File

@@ -12,6 +12,7 @@ return {
vim = { "vint" }, vim = { "vint" },
go = { "golangcilint" }, go = { "golangcilint" },
} }
lint.linters.jsonlint.cmd = "vscode-json-language-server"
lint.linters.shellcheck.args = { lint.linters.shellcheck.args = {
"-s", "-s",
"bash", "bash",
@@ -24,22 +25,13 @@ return {
local orig_try_lint = lint.try_lint local orig_try_lint = lint.try_lint
lint.try_lint = function(...) lint.try_lint = function(...)
local bufnr = vim.api.nvim_get_current_buf() local opts = select(2, ...)
local buftype = vim.api.nvim_get_option_value("buftype", { buf = bufnr }) local bufnr = (type(opts) == "table" and opts.bufnr) or vim.api.nvim_get_current_buf()
if vim.api.nvim_get_option_value("buftype", { buf = bufnr }) ~= "" then
-- Skip linting for non-file buffers (like hover docs)
if buftype ~= "" then
return return
end end
return orig_try_lint(...) return orig_try_lint(...)
end end
vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave" }, {
callback = function()
lint.try_lint()
end,
})
end, end,
event = { "BufReadPre", "BufNewFile" }, event = { "BufReadPre", "BufNewFile" },
} }

View File

@@ -7,6 +7,11 @@ return {
---@module 'render-markdown' ---@module 'render-markdown'
---@type render.md.UserConfig ---@type render.md.UserConfig
opts = { opts = {
completions = {
lsp = {
enabled = true,
},
},
injections = { injections = {
gitcommit = { gitcommit = {
enabled = true, enabled = true,

View File

@@ -0,0 +1,172 @@
return {
"folke/snacks.nvim",
priority = 1000,
lazy = false,
---@type snacks.Config
opts = {
-- your configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
bigfile = { enabled = true },
dashboard = { enabled = true },
explorer = { enabled = true },
indent = {
indent = {
priority = 1,
enabled = true, -- enable indent guides
char = "",
only_scope = true, -- only show indent guides of the scope
only_current = false, -- only show indent guides in the current window
-- hl = "SnacksIndent", ---@type string|string[] hl groups for indent guides
-- can be a list of hl groups to cycle through
hl = {
"SnacksIndent1",
"SnacksIndent2",
"SnacksIndent3",
"SnacksIndent4",
"SnacksIndent5",
"SnacksIndent6",
"SnacksIndent7",
"SnacksIndent8",
},
},
animate = {
-- enabled = vim.fn.has("nvim-0.10") == 1,
enabled = false,
style = "out",
easing = "linear",
duration = {
step = 20, -- ms per step
total = 500, -- maximum duration
},
},
filter = function(buf)
return vim.g.snacks_indent ~= false and vim.b[buf].snacks_indent ~= false and vim.bo[buf].buftype == ""
end,
},
input = {
enabled = true,
icon = "",
icon_hl = "SnacksInputIcon",
icon_pos = "left",
prompt_pos = "title",
win = { style = "input" },
},
lazygit = { enabled = true },
picker = { enabled = true },
notifier = {
enabled = true,
timeout = 3000, -- default timeout in ms
width = { min = 40, max = 0.4 },
height = { min = 1, max = 0.6 },
-- editor margin to keep free. tabline and statusline are taken into account automatically
margin = { top = 0, right = 1, bottom = 0 },
padding = true, -- add 1 cell of left/right padding to the notification window
sort = { "level", "added" }, -- sort by level and time
-- minimum log level to display. TRACE is the lowest
-- all notifications are stored in history
level = vim.log.levels.TRACE,
icons = {
error = "",
warn = "",
info = "",
debug = "",
trace = "",
},
keep = function(notif)
return vim.fn.getcmdpos() > 0
end,
---@type snacks.notifier.style
style = "compact",
top_down = true, -- place notifications from top to bottom
date_format = "%R", -- time format for notifications
-- format for footer when more lines are available
-- `%d` is replaced with the number of lines.
-- only works for styles with a border
---@type string|boolean
more_format = " ↓ %d lines ",
refresh = 50, -- refresh at most every 50ms
},
quickfile = { enabled = true },
scope = { enabled = true },
scroll = { enabled = false },
statuscolumn = { enabled = false },
words = { enabled = false },
terminal = {
enabled = true,
bo = {
filetype = "snacks_terminal",
},
wo = {},
keys = {
q = "hide",
gf = function(self)
local f = vim.fn.findfile(vim.fn.expand("<cfile>"), "**")
if f == "" then
Snacks.notify.warn("No file under cursor")
else
self:hide()
vim.schedule(function()
vim.cmd("e " .. f)
end)
end
end,
term_normal = {
"<esc>",
function(self)
self.esc_timer = self.esc_timer or (vim.uv or vim.loop).new_timer()
if self.esc_timer:is_active() then
self.esc_timer:stop()
vim.cmd("stopinsert")
else
self.esc_timer:start(200, 0, function() end)
return "<esc>"
end
end,
mode = "t",
expr = true,
desc = "Double escape to normal mode",
},
},
},
win = { enabled = true },
styles = {
input = {
backdrop = false,
position = "float",
border = "rounded",
title_pos = "center",
height = 1,
width = 60,
relative = "editor",
noautocmd = true,
row = 2,
-- relative = "cursor",
-- row = -3,
-- col = 0,
wo = {
winhighlight = "NormalFloat:SnacksInputNormal,FloatBorder:SnacksInputBorder,FloatTitle:SnacksInputTitle",
cursorline = false,
},
bo = {
filetype = "snacks_input",
buftype = "prompt",
},
--- buffer local variables
b = {
completion = false, -- disable blink completions in input
},
keys = {
n_esc = { "<esc>", { "cmp_close", "cancel" }, mode = "n", expr = true },
i_esc = { "<esc>", { "cmp_close", "stopinsert" }, mode = "i", expr = true },
i_cr = { "<cr>", { "cmp_accept", "confirm" }, mode = { "i", "n" }, expr = true },
i_tab = { "<tab>", { "cmp_select_next", "cmp" }, mode = "i", expr = true },
i_ctrl_w = { "<c-w>", "<c-s-w>", mode = "i", expr = true },
i_up = { "<up>", { "hist_up" }, mode = { "i", "n" } },
i_down = { "<down>", { "hist_down" }, mode = { "i", "n" } },
q = "cancel",
},
},
},
},
}

View File

@@ -36,15 +36,14 @@ return {
dynamic_preview_title = true, dynamic_preview_title = true,
treesitter = true, treesitter = true,
}, },
mappings = { -- mappings = {
i = { -- i = {
-- map actions.which_key to <C-h> (default: <C-/>) -- -- map actions.which_key to <C-h> (default: <C-/>)
-- actions.which_key shows the mappings for your picker, -- -- actions.which_key shows the mappings for your picker,
-- e.g. git_{create, delete, ...}_branch for the git_branches picker -- -- e.g. git_{create, delete, ...}_branch for the git_branches picker
["<C-h>"] = "which_key", -- ["<C-/>"] = "which_key",
["<C-u"] = false, -- },
}, -- },
},
file_ignore_patterns = { "^node_modules/", "^env/", "^__pycache__/" }, file_ignore_patterns = { "^node_modules/", "^env/", "^__pycache__/" },
}, },
pickers = { pickers = {

View File

@@ -26,6 +26,8 @@ return {
"typescript", "typescript",
"rust", "rust",
"go", "go",
"gowork",
"gotmpl",
"json", "json",
"regex", "regex",
"latex", "latex",

View File

@@ -0,0 +1,94 @@
--- @class CodeCompanion.InlineExtmark
--- @field unique_line_sign_text string Text used for sign when there's only a single line
--- @field first_line_sign_text string Text used for sign on the first line of multi-line section
--- @field last_line_sign_text string Text used for sign on the last line of multi-line section
--- @field extmark vim.api.keyset.set_extmark Extmark options passed to nvim_buf_set_extmark
local M = {}
--- @type CodeCompanion.InlineExtmark
local default_opts = {
unique_line_sign_text = "",
first_line_sign_text = "",
last_line_sign_text = "",
extmark = {
sign_hl_group = "DiagnosticWarn",
sign_text = "",
priority = 1000,
},
}
--- Helper function to set a line extmark with specified sign text
--- @param bufnr number
--- @param ns_id number
--- @param line_num number Line number
--- @param opts vim.api.keyset.set_extmark Extmark options
--- @param sign_type string Key in opts for the sign text to use
local function set_line_extmark(bufnr, ns_id, line_num, opts, sign_type)
vim.api.nvim_buf_set_extmark(
bufnr,
ns_id,
line_num - 1, -- Convert to 0-based index
0,
vim.tbl_deep_extend("force", opts.extmark or {}, {
sign_text = opts[sign_type] or opts.extmark.sign_text,
})
)
end
--- Creates extmarks for inline code annotations
--- @param opts CodeCompanion.InlineExtmark Configuration options for the extmarks
--- @param data CodeCompanion.InlineArgs Data containing context information about the code block
--- @param ns_id number unique namespace id for the extmarks
local function create_extmarks(opts, data, ns_id)
--- @type {bufnr: number, start_line: number, end_line: number}
local context = data.context
-- Handle the case where start and end lines are the same (unique line)
if context.start_line == context.end_line then
set_line_extmark(context.bufnr, ns_id, context.start_line, opts, "unique_line_sign_text")
return
end
-- Set extmark for the first line with special options
set_line_extmark(context.bufnr, ns_id, context.start_line, opts, "first_line_sign_text")
-- Set extmarks for the middle lines with standard options
for i = context.start_line + 1, context.end_line - 1 do
vim.api.nvim_buf_set_extmark(context.bufnr, ns_id, i - 1, 0, opts.extmark)
end
-- Set extmark for the last line with special options
if context.end_line > context.start_line then
set_line_extmark(context.bufnr, ns_id, context.end_line, opts, "last_line_sign_text")
end
end
--- Creates autocmds for CodeCompanionRequest events
--- @param opts CodeCompanion.InlineExtmark Configuration options passed from setup
local function create_autocmds(opts)
vim.api.nvim_create_autocmd({ "User" }, {
pattern = { "CodeCompanionRequest*" },
callback =
--- @param args {buf: number, data : CodeCompanion.InlineArgs, match: string}
function(args)
local data = args.data or {}
local context = data and data.context or {}
if data and data.context then
local ns_id = vim.api.nvim_create_namespace("CodeCompanionInline_" .. data.id)
if args.match:find("StartedInline") then
create_extmarks(opts, data, ns_id)
elseif args.match:find("FinishedInline") then
vim.api.nvim_buf_clear_namespace(context.bufnr, ns_id, 0, -1)
end
end
end,
})
end
--- @param opts? CodeCompanion.InlineExtmark Optional configuration to override defaults
function M.setup(opts)
create_autocmds(vim.tbl_deep_extend("force", default_opts, opts or {}))
end
return M

View File

@@ -0,0 +1,4 @@
return {
require("utils.functions.git_paste"),
require("utils.functions.mkdir_under_cursor"),
}

View File

@@ -0,0 +1,36 @@
local M = {}
vim.notify = require("notify")
function M.mkdir_under_cursor()
local word
-- Check if in visual mode
if vim.fn.mode():match("[vV]") then
-- Get visual selection
local start_pos = vim.fn.getpos("'<")
local end_pos = vim.fn.getpos("'>")
local line = vim.fn.getline(start_pos[2])
word = line:sub(start_pos[3], end_pos[3])
else
-- Get word under cursor
word = vim.fn.expand("<cWORD>")
end
-- Remove quotes if present
word = word:gsub("^[\"']", ""):gsub("[\"']$", "")
-- Check if directory exists
local stat = vim.loop.fs_stat(word)
if not stat then
-- Create directory (recursive)
vim.loop.fs_mkdir(word, 493) -- 493 = 0755 in decimal
vim.notify("Directory created: " .. word, vim.log.levels.INFO)
else
vim.notify("Directory already exists: " .. word, vim.log.levels.WARN)
end
end
function M.setup(opts)
return M.mkdir_under_cursor
end
return M

View File

@@ -1,6 +1,6 @@
local M = {} local M = {}
local map = vim.keymap.set local map = vim.keymap.set
local opts = { noremap = true, silent = true } local opts = { noremap = true, silent = false }
--- Set keybindings from a table of mappings. --- Set keybindings from a table of mappings.
--- @param bindings table A list of keybinding mappings. --- @param bindings table A list of keybinding mappings.

View File

@@ -0,0 +1,82 @@
exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
"env"
]
# Same as Black.
line-length = 88
indent-width = 4
# Assume Python 3.9
target-version = "py39"
respect-gitignore = true
[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
select = ["D"]
ignore = ["D107", "D203", "D212", "D213", "D402", "D413", "D415", "D416", "D417"]
# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[lint.pydocstyle]
convention = "numpy" # Accepts: "google", "numpy", or "pep257".
[format]
# Like Black, use double quotes for strings.
quote-style = "double"
# Like Black, indent with spaces, rather than tabs.
indent-style = "space"
# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false
# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"
# Enable auto-formatting of code examples in docstrings. Markdown,
# reStructuredText code/literal blocks and doctests are all supported.
#
# This is currently disabled by default, but it is planned for this
# to be opt-out in the future.
docstring-code-format = true
# Set the line length limit used when formatting code snippets in
# docstrings.
#
# This only has an effect when the `docstring-code-format` setting is
# enabled.
docstring-code-line-length = "dynamic"

View File

@@ -1,8 +1,33 @@
local telescope = require("telescope") local telescope = require("telescope")
local telescopeConfig = require("telescope.config") local telescopeConfig = require("telescope.config")
local actions = require("telescope.actions")
local M = {} local M = {}
function M.find_and_paste_image()
local telescope = require("telescope.builtin")
local actions = require("telescope.actions")
local action_state = require("telescope.actions.state")
telescope.find_files({
attach_mappings = function(_, map)
local function embed_image(prompt_bufnr)
local entry = action_state.get_selected_entry()
local filepath = entry[1]
actions.close(prompt_bufnr)
local img_clip = require("img-clip")
img_clip.paste_image(nil, filepath)
end
map("i", "<CR>", embed_image)
map("n", "<CR>", embed_image)
return true
end,
})
end
function M.setup() function M.setup()
-- Clone the default Telescope configuration -- Clone the default Telescope configuration
local vimgrep_arguments = { unpack(telescopeConfig.values.vimgrep_arguments) } local vimgrep_arguments = { unpack(telescopeConfig.values.vimgrep_arguments) }
@@ -12,56 +37,13 @@ function M.setup()
-- I don't want to search in the `.git` directory. -- I don't want to search in the `.git` directory.
table.insert(vimgrep_arguments, "--glob") table.insert(vimgrep_arguments, "--glob")
table.insert(vimgrep_arguments, "!**/.git/*") table.insert(vimgrep_arguments, "!**/.git/*")
telescope.setup({ vim.tbl_deep_extend("force", telescopeConfig.values, {
defaults = { mappings = {
-- `hidden = true` is not supported in text grep commands. i = {
vimgrep_arguments = vimgrep_arguments, ["<C-h>"] = actions.results_scrolling_left,
}, ["<C-l>"] = actions.results_scrolling_right,
pickers = {
find_files = {
-- `hidden = true` will still show the inside of `.git/` as it's not `.gitignore`d.
find_command = { "rg", "--files", "--hidden", "--glob", "!**/.git/*" },
mappings = {
n = {
["cd"] = function(prompt_bufnr)
local selection = require("telescope.actions.state").get_selected_entry()
local dir = vim.fn.fnamemodify(selection.path, ":p:h")
require("telescope.actions").close(prompt_bufnr)
-- Depending on what you want put `cd`, `lcd`, `tcd`
vim.cmd(string.format("silent lcd %s", dir))
end,
},
},
}, },
}, },
preview = {
-- show images in telescope using kitty
mime_hook = function(filepath, bufnr, opts)
local is_image = function(filepath)
local image_extensions = { "png", "jpg" } -- Supported image formats
local split_path = vim.split(filepath:lower(), ".", { plain = true })
local extension = split_path[#split_path]
return vim.tbl_contains(image_extensions, extension)
end
if is_image(filepath) then
local term = vim.api.nvim_open_term(bufnr, {})
local function send_output(_, data, _)
for _, d in ipairs(data) do
vim.api.nvim_chan_send(term, d .. "\r\n")
end
end
vim.fn.jobstart({
"kitty +icat " .. filepath, -- Terminal image viewer command
}, { on_stdout = send_output, stdout_buffered = true, pty = true })
else
require("telescope.previewers.utils").set_preview_message(
bufnr,
opts.winid,
"Binary cannot be previewed"
)
end
end,
},
}) })
end end

View File

@@ -0,0 +1,49 @@
{
"$schema": "https://opencode.ai/config.json",
"theme": "catppuccin",
"model": "github-copilot/gpt-5.1",
"provider": {
"openai": {
"models": {
"gpt-5": {
"options": {
"reasoningEffort": "high",
"textVerbosity": "low",
"reasoningSummary": "auto",
"include": ["reasoning.encrypted_content"],
},
},
},
},
},
"agent": {
"build": {
"mode": "primary",
"model": "github-copilot/gpt-5.1",
"tools": {
"write": true,
"edit": true,
"bash": true
}
},
"plan": {
"mode": "primary",
"model": "github-copilot/gpt-5.1-codex",
"tools": {
"write": false,
"edit": false,
"bash": false
}
},
"code-reviewer": {
"description": "Reviews code for best practices and potential issues",
"mode": "subagent",
"model": "github-copilot/gpt-5.1",
"prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
"tools": {
"write": false,
"edit": false
}
}
}
}

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