Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c915067aa | ||
|
|
0924309abf | ||
|
|
cf41a13528 | ||
|
|
9bbc594048 | ||
|
|
741b258ac1 | ||
|
|
a87ee98faa | ||
|
|
25b19f2d6a | ||
|
|
8970f2694b | ||
|
|
72a3b9adac | ||
|
|
bf9fc193b3 | ||
|
|
4d00b7455e | ||
|
|
629be0d9ed | ||
|
|
130c934b9b | ||
|
|
9f2586b7ff | ||
|
|
51c1c5ab78 | ||
|
|
f4ca02c3cf | ||
|
|
eac45746ce | ||
|
|
a52133b313 | ||
|
|
a1b270fd4e | ||
|
|
7e98ebd1db | ||
|
|
0b0c67acb7 | ||
|
|
622df58295 | ||
|
|
df6f6ef893 | ||
|
|
ea607c1a52 | ||
|
|
e537f9d5f8 | ||
|
|
cf59251449 | ||
|
|
ef562342e2 | ||
|
|
3d81342725 | ||
|
|
b949951ef9 | ||
|
|
fd8064611a | ||
|
|
959eed38a4 | ||
|
|
bcc6d4bac8 | ||
|
|
4526fe86d9 | ||
|
|
8e82a1f7be | ||
|
|
4d74cee67d | ||
|
|
d4952db497 | ||
|
|
50b2b000a4 | ||
|
|
197fe113a1 | ||
|
|
7487b4deb1 | ||
|
|
4ab37c55cf | ||
|
|
572104f49e | ||
|
|
a407d3cbb0 | ||
|
|
1ec4fc8b13 | ||
|
|
9572e8457d | ||
|
|
d8585fb78e | ||
|
|
e52a7633a0 | ||
|
|
c3fe8b682d | ||
|
|
1508d2f804 | ||
|
|
86eb30f498 | ||
|
|
ddd7a21195 | ||
|
|
4275abe470 | ||
|
|
cf2805d3bd | ||
|
|
52f1c481a6 | ||
|
|
771b961b32 | ||
|
|
6b10cae4e6 | ||
|
|
95cd668cfb | ||
|
|
2a7b553597 | ||
|
|
27b4ec2c96 | ||
|
|
ab133dd82f | ||
|
|
1b0a3db439 | ||
|
|
6d388483ef | ||
|
|
bbecdcc4d8 | ||
|
|
f1ccf88b06 | ||
|
|
d3be13ecda | ||
|
|
1b04e002c2 | ||
|
|
f23cc7b311 | ||
|
|
473c82ec0a | ||
|
|
e621b392af | ||
|
|
884f208330 | ||
|
|
cc45b86271 | ||
|
|
84c5cda668 | ||
|
|
bc96cb13d9 | ||
|
|
f7f2f0cddd | ||
|
|
05b06b1fc1 | ||
|
|
748d58f036 | ||
|
|
1fd4081461 | ||
|
|
2d39018a73 | ||
|
|
059b7dd306 | ||
|
|
0115d54ab8 | ||
|
|
fe5d6c3b3f | ||
|
|
05f9e794a9 | ||
|
|
75065f90cd | ||
|
|
e0db5cc655 | ||
|
|
8186fbb5d3 | ||
|
|
8b81da4069 | ||
|
|
dbfd351ee4 | ||
|
|
a4be24a2a5 | ||
|
|
b038706dff | ||
|
|
b2b77a6b3f | ||
|
|
d002ff6941 | ||
|
|
151ec95289 | ||
|
|
745717a4a0 | ||
|
|
9ddd85de90 | ||
|
|
24fc137e4f | ||
|
|
9a4b04672b | ||
|
|
ff51d52fbb | ||
|
|
f2272d7980 | ||
|
|
cf80bb2167 | ||
|
|
8effa573a0 | ||
|
|
5f22be6c20 | ||
|
|
740273745b | ||
|
|
27b4e1dc0c | ||
|
|
fce392e425 | ||
|
|
d8fd464e33 | ||
|
|
0c38528520 | ||
|
|
b534c8c7ea | ||
|
|
d092ea371a | ||
|
|
99cda7ed04 | ||
|
|
d29c12e4f0 | ||
|
|
f790470935 | ||
|
|
2eb6840ec4 | ||
|
|
677ece81c4 | ||
|
|
caa0765890 | ||
|
|
c76fee70dc | ||
|
|
6f136bfc4d | ||
|
|
e7f33b5dc3 | ||
|
|
9c5733719b | ||
|
|
50bcc2e1a2 | ||
|
|
2c21cfde11 | ||
|
|
e6f243d6a6 | ||
|
|
8845007cbf | ||
|
|
8c71ee21c1 | ||
|
|
75d8651f17 | ||
|
|
165cd2a7f9 | ||
|
|
bc98c5c665 | ||
|
|
ae4edc29e8 | ||
|
|
773a04369e | ||
|
|
45f4c1bc84 | ||
|
|
fb2927c094 | ||
|
|
4814bfb561 | ||
|
|
d8d487c189 | ||
|
|
0669ec0fc2 | ||
|
|
81cac1214d | ||
|
|
d8a0729029 | ||
|
|
aeff087c7d | ||
|
|
beae87b0cc | ||
|
|
e2301aa4ec | ||
|
|
32848aaf71 | ||
|
|
afb4a9e051 |
No files matched your search
@@ -1,6 +1,9 @@
|
||||
name: ci
|
||||
on:
|
||||
# Branches only: a release tag points at a commit CI already checked on
|
||||
# main, and release.yml builds it.
|
||||
push:
|
||||
branches: ['**']
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
@@ -31,3 +34,49 @@ jobs:
|
||||
working-directory: packages/server
|
||||
- run: dart test
|
||||
working-directory: packages/server
|
||||
# Compiling the dedicated server proves it stays Flutter-free.
|
||||
- run: mkdir -p build && dart compile exe bin/server.dart -o build/starsync-server
|
||||
working-directory: packages/server
|
||||
- run: build/starsync-server --help
|
||||
working-directory: packages/server
|
||||
|
||||
# The updater's Windows apply path (running exe parked as .old) only
|
||||
# means something on real NTFS, and the close smoke run needs the real
|
||||
# build. Runner notes: see release.yml.
|
||||
updater-windows:
|
||||
# Not for a "Release v…" commit: release.yml builds it on the same
|
||||
# (only) Windows runner, which this job would hold up.
|
||||
if: ${{ !startsWith(github.event.head_commit.message, 'Release v') }}
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
shell: powershell
|
||||
run: |
|
||||
git init -q .
|
||||
git remote add origin "$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY.git"
|
||||
git fetch -q origin "$env:GITHUB_SHA"
|
||||
if ($LASTEXITCODE) { exit 1 }
|
||||
git checkout -q --force FETCH_HEAD
|
||||
- name: Setup Flutter
|
||||
shell: powershell
|
||||
run: powershell -NoProfile -ExecutionPolicy Bypass -File tool/setup_flutter_windows.ps1
|
||||
- name: Updater tests
|
||||
shell: powershell
|
||||
working-directory: packages/core
|
||||
run: |
|
||||
dart pub get
|
||||
if ($LASTEXITCODE) { exit 1 }
|
||||
dart test test/updater_test.dart
|
||||
# The release build, without publishing: a broken Windows build shows
|
||||
# here, not only on a tag.
|
||||
- name: Windows build
|
||||
shell: powershell
|
||||
run: powershell -NoProfile -ExecutionPolicy Bypass -File tool/package_windows.ps1
|
||||
# The close smoke run on that build (P32): start, open a short clip in
|
||||
# a player with a video output, close; it must exit within 45 s and
|
||||
# leave no process. A runner that cannot show a window skips with a
|
||||
# warning. Here rather than in a job of its own: one build, one runner.
|
||||
- name: Smoke (start, open, close)
|
||||
shell: powershell
|
||||
timeout-minutes: 3
|
||||
run: powershell -NoProfile -ExecutionPolicy Bypass -File tool/smoke_windows.ps1 -Limit 45
|
||||
@@ -14,30 +14,64 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Linux build deps
|
||||
# media_kit_video links libmpv + epoxy via pkg-config. Runner images
|
||||
# differ: some run as root without sudo.
|
||||
run: |
|
||||
if command -v apt-get >/dev/null; then
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev
|
||||
fi
|
||||
SUDO=sudo; [ "$(id -u)" = 0 ] && SUDO=
|
||||
$SUDO apt-get update
|
||||
$SUDO apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev \
|
||||
liblzma-dev g++ libmpv-dev libepoxy-dev xz-utils unzip curl python3
|
||||
|
||||
- name: Setup Flutter (beta)
|
||||
- name: Setup Flutter (stable)
|
||||
run: |
|
||||
git clone https://github.com/flutter/flutter.git -b beta --depth 1 ~/flutter
|
||||
git clone https://github.com/flutter/flutter.git -b stable --depth 1 ~/flutter
|
||||
echo "$HOME/flutter/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Build tarball
|
||||
run: tool/package_linux.sh
|
||||
|
||||
- name: Upload tarball artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux-tarball
|
||||
path: dist/*.tar.gz
|
||||
|
||||
- name: Publish release + manifest
|
||||
- name: Publish release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: tool/release_publish.sh "${{ github.ref_name }}"
|
||||
run: |
|
||||
VER="${GITHUB_REF_NAME#v}"
|
||||
dart tool/release_publish.dart "$GITHUB_REF_NAME" "dist/starsync-$VER-linux-x64.tar.gz"
|
||||
|
||||
windows:
|
||||
# yuuka-windows: host-mode runner (no containers), runs as SYSTEM, has
|
||||
# git + VS 2022 Build Tools but no bash/python — PowerShell and Dart
|
||||
# only. Checkout is plain git: that host's cached actions/checkout
|
||||
# clone was corrupt, and no `uses:` means no action cache to rot.
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
shell: powershell
|
||||
run: |
|
||||
git init -q .
|
||||
git remote add origin "$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY.git"
|
||||
git fetch -q --tags origin "$env:GITHUB_SHA"
|
||||
if ($LASTEXITCODE) { exit 1 }
|
||||
git checkout -q --force FETCH_HEAD
|
||||
|
||||
- name: Setup Flutter
|
||||
shell: powershell
|
||||
run: powershell -NoProfile -ExecutionPolicy Bypass -File tool/setup_flutter_windows.ps1
|
||||
|
||||
- name: Build zip
|
||||
shell: powershell
|
||||
run: powershell -NoProfile -ExecutionPolicy Bypass -File tool/package_windows.ps1
|
||||
|
||||
- name: Publish release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
shell: powershell
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
$Ver = $env:GITHUB_REF_NAME.TrimStart('v')
|
||||
dart tool/release_publish.dart $env:GITHUB_REF_NAME "dist/starsync-$Ver-windows-x64.zip"
|
||||
if ($LASTEXITCODE) { exit 1 }
|
||||
@@ -17,6 +17,7 @@ coverage/
|
||||
# Build artifacts that should never be committed
|
||||
*.tar.gz
|
||||
*.zip
|
||||
/dist/
|
||||
app.*.symbols
|
||||
app.*.map.json
|
||||
|
||||
|
||||
@@ -1,35 +1,40 @@
|
||||
# AGENTS.md — sync_relay_project
|
||||
# AGENTS.md
|
||||
|
||||
Project conventions for agents. Global interaction rules live in the
|
||||
user-level AGENTS.md; this file holds repo-specific facts only.
|
||||
Source of truth order: codebase > `HANDOFF.md` + `docs/ROADMAP.md` >
|
||||
chat history.
|
||||
Repo-specific rules. Global interaction rules live in the user-level
|
||||
AGENTS.md. Source of truth: the code, then the docs below.
|
||||
|
||||
## Docs
|
||||
|
||||
- [README.md](README.md): users. [docs/HOW-IT-WORKS.md](docs/HOW-IT-WORKS.md):
|
||||
plain tour. [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md): packages, sync,
|
||||
media, updater, decisions. [docs/PROTOCOL.md](docs/PROTOCOL.md): wire format.
|
||||
[docs/DEVELOPMENT.md](docs/DEVELOPMENT.md): build, test, release, gotchas.
|
||||
[docs/ROADMAP.md](docs/ROADMAP.md): backlog and epics.
|
||||
- Docs describe current truth only: no dates, no "fixed" notes, no phase
|
||||
logs (git has history, plans go in ROADMAP).
|
||||
- Each fact lives in exactly one file; others link to it.
|
||||
- Code and its docs change in the same commit. A wire change also bumps
|
||||
`RelayConstants.protoVersion` and edits PROTOCOL.md.
|
||||
- Say "server" (there is only one), never "room", in UI, code and docs.
|
||||
|
||||
## Wishlist drafts
|
||||
|
||||
The user drops raw idea/bug lists as drafts (gitignored, never
|
||||
committed: `docs/Wishlist.md`, `docs/drafts/`). Agent duty on sight:
|
||||
translate each entry into its proper place — `docs/ROADMAP.md`
|
||||
backlog (ordered, one sitting-sized item each) or Epics, real bugs
|
||||
with repro detail preserved — then confirm placement with the user
|
||||
and delete the draft. Drafts must never be committed, even partially.
|
||||
The user drops raw idea/bug lists as drafts (gitignored, never committed:
|
||||
`docs/Wishlist.md`, `docs/drafts/`). On sight, translate each entry into its
|
||||
place in `docs/ROADMAP.md` (ordered backlog item or epic; keep repro detail
|
||||
for real bugs), confirm placement with the user, then delete the draft.
|
||||
Drafts must never be committed, even partially.
|
||||
|
||||
## Commits
|
||||
|
||||
Few commits, one per topic/session — never per fix. Rewriting
|
||||
unpushed history (amend, squash) is expected, not exceptional.
|
||||
Commit code + its docs together. No `flutter analyze` unless asked
|
||||
or diagnosing; scoped `dart analyze` on touched files is the
|
||||
pre-commit check. Tests run only when the code under test changed.
|
||||
Few commits, one per topic/session, never per fix. Rewriting unpushed
|
||||
history (amend, squash) is normal. Commit code + its docs together. No
|
||||
`flutter analyze` unless asked or diagnosing; scoped `dart analyze` on touched
|
||||
files is the pre-commit check. Run tests only when the code under test changed.
|
||||
|
||||
## Releases (user pushes tags, CI does the rest)
|
||||
## Releases
|
||||
|
||||
Release flow: `tool/release.sh [patch|minor|major]` derives the
|
||||
version (no typing), bumps all pubspecs, commits, tags → review →
|
||||
`git push --follow-tags` → `.gitea/workflows/release.yml`
|
||||
builds, publishes the Forgejo release, commits
|
||||
`updates/manifest.json` back. `tool/release_publish.sh` is the same
|
||||
flow by hand. Workflows live in `.gitea/workflows` (this forge reads
|
||||
`.gitea` first, `.github` is ignored when it exists).
|
||||
Never commit secrets: tokens arrive via env (`DISCORD_WEBHOOK_URL`,
|
||||
`RELEASE_TOKEN`) or Actions-provided (`GITHUB_TOKEN/GITEA_TOKEN`).
|
||||
`tool/release.sh [patch|minor|major]` then `git push --follow-tags`; CI
|
||||
publishes. Details: [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md). Never commit
|
||||
secrets: tokens come from env (`DISCORD_WEBHOOK_URL`, `RELEASE_TOKEN`) or
|
||||
Actions (`GITHUB_TOKEN`/`GITEA_TOKEN`).
|
||||
@@ -1,321 +0,0 @@
|
||||
# HANDOFF — sync_relay_project (watch-together app)
|
||||
|
||||
Date: 2026-09-12 (updated late session). Phases 0–4 + presence hardening
|
||||
+ UI redesigns done, all green (core 42, server 41, desktop 24).
|
||||
Phases retired as a tracker 09-12 — `docs/ROADMAP.md` is now a flat
|
||||
backlog (Built / Backlog / Epics / Deferred); phase text lives in
|
||||
git history.
|
||||
Black screen (§8) DIAGNOSED + FIXED (avatar-texture teardown race;
|
||||
Visibility keep-mounted) + VERIFIED, incl. over internet. Bisect
|
||||
screens (legacy/minimal/nosheet) REMOVED 09-12 — app.dart routes
|
||||
session straight to SessionScreen. Internet test PASSED (WAN port
|
||||
6969, 09-12); user reports 2-client LAN soak + 1.4 GB real-file
|
||||
test also done 09-12 (outcomes not yet recorded below). Tonight's
|
||||
fixes: server logging wired into app (`initLogging` + hello logs),
|
||||
Cancel aborts pending connect, first-join failure no longer
|
||||
retry-loops. Git repo INITIALIZED (commit 427d851, root
|
||||
.gitignore). Prior chat may be unreliable; this file plus `docs/`
|
||||
is the full state (`docs/ROADMAP.md` is now the phase tracker).
|
||||
|
||||
## 1. What this is
|
||||
|
||||
Private watch-together desktop app (Windows + Linux). Host serves a file
|
||||
or shared link from their own machine; 4–8 friends watch in sync.
|
||||
One binary, three modes: Client (Join), Server+Client (Host, opens
|
||||
ports, self-plays via loopback), `--headless` (server only, no window).
|
||||
North star: <1.5 s drift, seeks settle ~2 s, cache rides short drops,
|
||||
kick kills sync+video, no relay memory growth.
|
||||
|
||||
## 2. Locked architecture (do not reopen without the user)
|
||||
|
||||
- `packages/core`: protocol, sync engine, media abstractions. ZERO Flutter
|
||||
imports (enforced by test). `packages/server`: Relic-based room + media
|
||||
server, also zero Flutter imports. `apps/desktop`: the ONE Flutter
|
||||
binary embedding both. Direct-serve model: host opens ports, clients
|
||||
open nothing. NO host-upload tunnel (the brief's WSS chunk protocol is
|
||||
obsolete unless a VPS tier ever needs remote-host upload).
|
||||
- Server HTTP+WS: **Relic ^1.2.0**. Client WS: **web_socket_channel**.
|
||||
Server lib also uses **web_socket** for event types.
|
||||
- PACKAGES ARE NOT LOCKED (user decision 09-11, overrides the old brief
|
||||
list): pick on merit, no churn where the stack works. Current desktop
|
||||
additions: media_kit_video + media_kit_libs_video (required),
|
||||
file_picker (avatar/media picking), hive_ce + hive_ce_flutter
|
||||
(connect-form persistence), image (avatar shrink). signals + media_kit
|
||||
+ Relic stay (load-bearing).
|
||||
- Sync: heavily Syncplay-inspired + original readiness design, NOT 1:1.
|
||||
Reference clone (scratch, may be gone — re-clone shallow):
|
||||
`git clone --depth 1 https://github.com/Syncplay/syncplay.git /tmp/opencode/syncplay-ref`
|
||||
Audit already done; conscious deviations: clock never moves from
|
||||
reports (theirs follows slowest watcher), no pause-on-leave,
|
||||
force-for-all instead of operator-only setOthersReadiness, and
|
||||
QUORUM gate (09-12, user found solo-play meaningless): HELD→PLAYING
|
||||
needs in-set size ≥ 2 unless ≤1 member is fresh — lone watcher plays
|
||||
alone, second watcher present ⇒ one Space waits. Late joiners outside
|
||||
the set never block.
|
||||
- Single room password (one secret, persisted in Hive on the user's own
|
||||
box — accepted). No op roles (deferred: op flag + second hello
|
||||
secret). Kick = transient nudge: revoke + close + `kicked` reason,
|
||||
instant rejoin with fresh token.
|
||||
- Deferred, do not build: TLS/Caddy, Jellyfin native, updater
|
||||
expansion (v1 `--upgrade` SHIPPED 09-12 — see §9.12; in-app
|
||||
prompt + Windows helper still deferred), playlist (extension shape reserved in PROTOCOL.md), op roles, sounds
|
||||
(researched, wired, no assets — see §7).
|
||||
- Standing rules: health reporting (every failure displays, nothing
|
||||
stalls silently); proto bump + PROTOCOL.md same-commit on ANY
|
||||
wire change (still v4 — quorum/timeouts are server policy, no bump).
|
||||
|
||||
## 3. Repo map (root: Flutter/sync_relay_project/)
|
||||
|
||||
- `packages/core/lib/src/`: constants.dart (tuning: seek 300 ms,
|
||||
drift 5 s, slow 1.5 s @0.95, min_buffer 4 s, heartbeat 1 s, ping 5 s,
|
||||
avatar 256 KiB (base64 chars; wide headroom over any 128x128 PNG
|
||||
— raised 09-12 from 64 KiB, which rejected normal PNGs), name 32, chat 500; dropAfter lives as RoomEngine ctor
|
||||
default, now 30 s), errors.dart, logging.dart, config.dart,
|
||||
protocol.dart (v4 schemas), media_source.dart, sync_engine.dart
|
||||
(RoomEngine + quorum in evaluate's HELD branch; PLAYING branch
|
||||
unchanged).
|
||||
- `packages/server/lib/src/`: session.dart, media_endpoint.dart,
|
||||
room_hub.dart (forgetSocket, sweepClosedSockets via `isClosed` poll,
|
||||
closeAllSockets, onError→forgetSocket), room_server.dart (1 Hz
|
||||
heartbeat: sweepStale + sweepClosedSockets + dropSilentSockets +
|
||||
broadcast; stop() closes client sockets first). `bin/server.dart`.
|
||||
- `apps/desktop/lib/src/`: sync/ (sync_client.dart: hello/intents/
|
||||
fan-out/match-by-`t`; room_diff.dart: diff + debounce + play gate),
|
||||
playback/ (media_kit Player, 64 MB cache, pin props, 0.5 s seek
|
||||
deadband, stop() on leave, SYNC_RELAY_VO/HWDEC env overrides),
|
||||
session/ (session_coordinator.dart: THE brain — room→player,
|
||||
reports, scrub/nudge→seek intents incl. HELD, seek-land retry,
|
||||
idle 8/10 min, reconnect loop, 5 s silence timeout; health.dart),
|
||||
sfx/ (SfxKind/Cue/Service + NoopSfxService — sounds deferred),
|
||||
state/ (session_state.dart: route/mode/lastForm/prefs/host/join/
|
||||
leave; connect_prefs.dart), screens/ (welcome/connect/session),
|
||||
widgets/ (user_section.dart: ConnectProfileCard; member_avatar.dart:
|
||||
THE avatar — memoized, no bg on images, dark ring+fallback;
|
||||
dialogs.dart: kick confirm; media_input.dart: parseMediaInput).
|
||||
- `apps/desktop/test/`: room_diff_test (9), media_input_test (6),
|
||||
updater_test (7: version/manifest/layout + stub-server flows),
|
||||
sync_playback_e2e_test (quorum: solo Space holds, both ready plays;
|
||||
needs mpv + ~/Videos/chiyo.mp4), coord_presence_test (dead server
|
||||
clears + reconnects; needs mpv).
|
||||
- `tool/`: range_logger, shaper (chaos: KB/s cap, latency,
|
||||
--kill-after), fake_viewer, e2e_check (sim timeline, still ALL PASS
|
||||
post-quorum), package_linux.sh (release tarball + Discord card,
|
||||
stamps APP_VERSION).
|
||||
- `docs/`: PROTOCOL.md (v4 + quorum + 15/30 s timeouts + isClosed note,
|
||||
normative), ARCHITECTURE.md (+health rule), mpv-http-contract.md.
|
||||
- `deploy/`: systemd unit. Git repo initialized 09-12 (`git init`,
|
||||
root `.gitignore`, initial commit 427d851 covering phases 0–4 +
|
||||
tonight's connect/logging fixes). Bisection is possible again.
|
||||
|
||||
## 4. Protocol v4 + policy (see PROTOCOL.md for normative detail)
|
||||
|
||||
hello→welcome(token, memberId, mediaUrl?, room-state); intents:
|
||||
ready{ready,source}/force{target:all|memberId,ready}/seek/seek-swap/
|
||||
report{position,buffered,eventId}/chat/kick{memberId}. Broadcasts:
|
||||
room @1 Hz + on change (diff by eventId), feed{actor,action,…}
|
||||
(toasts/log/sounds), kicked{reason}, err. Media:
|
||||
GET /m/<sid>/<token>/<name> (200/206×3 shapes/416/401/403/410/503).
|
||||
Transport PLAYING/HELD; gate = non-empty set AND all in-set ready +
|
||||
buffered≥4 s + fresh AND quorum (in-set≥2 unless ≤1 fresh).
|
||||
Stale >15 s ⇒ out of gate; silent >30 s ⇒ closed + removed.
|
||||
Closed sockets swept every second; socket errors remove immediately.
|
||||
Client: 5 s room-silence ⇒ dead (clear room, warn, reconnect loop
|
||||
1.5 s polite infinite + manual cancel/retry, prior-flag restore).
|
||||
|
||||
## 5. Phase log (all exits met, all green as stated above)
|
||||
|
||||
- P0 scaffold + CI + Flutter-free tests; binary binds/logs/exits.
|
||||
- P1 Range table byte-exact, real mpv traces, shaper built. 503 tested.
|
||||
- P2 sessions: secret→128-bit token, 401/403/410 gates, kick kills WS+
|
||||
media, byte counters, fake_viewer ALL PASS live, proto→3.
|
||||
- P3 engine + readiness: engine tests (fake clock), e2e 15/15 sim,
|
||||
Syncplay audit. Sanity: NaN guards, caps, stale/leave feeds,
|
||||
1 Hz flush, token redaction.
|
||||
- P4 desktop shell→app: SyncClient framing, RoomDiff (eventId diff,
|
||||
slowdown latch 0.95×/0.1 reset, seek-land check), media_kit wiring
|
||||
(pinned buffer props, buffered from demuxer), Space=ready, avatars,
|
||||
toasts+sheet, health display, reconnect loop. Sounds WIRED ONLY
|
||||
(NoopSfxService) — see §7.
|
||||
- P5 presence+sync hardening (user-reported, all reproduced live
|
||||
first): stop() closes sockets; isClosed sweep (~1 s graceful);
|
||||
onError forget (~2–4 s kill -9, was 56 s ghost); drop 60→30 s;
|
||||
client silence-timeout + stuck-reconnect-flag fix + ready-future
|
||||
leak fix; seek race fixed (2 s same-event debounce both
|
||||
transports, edge-aware detector 1 s guard, 0.5 s apply deadband);
|
||||
HELD seeks send intents (paused frame moves for all); arrows
|
||||
nudge ∓10 s; local play gate (in-set+ready); autoplay off;
|
||||
leave() stops player (was leaking audio); kick confirm; Cancel
|
||||
connect; connect-form memory→Hive persistence; file/media
|
||||
Browse buttons.
|
||||
- P6 UI redesigns (two subagents, disjoint files — repeat this
|
||||
pattern): full-bleed video + overlays, controls never autohide
|
||||
(24 h hover) + Ready/Mark-everyone-ready IN the controls bar
|
||||
(intents only, zero local transport buttons), center avatars-only
|
||||
64 px, slide-in toasts, animated right sheet (users/log/chat/swap/
|
||||
Leave w/ confirm), health pill only-when-unwell, ESC closes/
|
||||
asks-leave, global focus-proof keys (Space/Tab/arrows/ESC/F,
|
||||
350 ms throttle, ignored while typing; Tab traversal disabled on
|
||||
the session screen 09-12 — game-style, Tab toggles the sheet), single media field
|
||||
(parseMediaInput + tests), avatar pipeline (128 px PNG, keeps
|
||||
transparency — JPEG did not; self-check measures encoded base64
|
||||
against RelayConstants, single source of truth), tap to
|
||||
pick, no path fields), Discord-like corner profile (connect only;
|
||||
welcome is title+Host/Join; edits apply next join — no rename
|
||||
intent on the wire), dialogs for terminal states.
|
||||
- UX decisions locked along the way: Space flips self-ready only;
|
||||
free seeks any transport (no flag churn); join catch-up never
|
||||
halts; idle 8-min warn + 10-min auto-unready; reconnect = re-hello
|
||||
with flag restore; kick → dialog + connect screen; fixed 1.5 s
|
||||
reconnect + cancel/retry; GMod toasts (social only) + side sheet;
|
||||
avatar fallback = initial circle; "waiting for X (n/m ready)".
|
||||
- Open user questions for later: warning-tone timing; bar width at
|
||||
minimum window; second-ESC on leave dialog (re-asks vs cancel);
|
||||
cancel-stops-host-server (kept: idle means no bound port).
|
||||
|
||||
## 6. Gotchas (learned the hard way)
|
||||
|
||||
1. Relic gives Range as TYPED RangeHeader — convert via unit+first.
|
||||
2. Relic server-side onDone DOES NOT fire for dead peers (proven
|
||||
live both directions: clean close AND kill -9 both ghosted to
|
||||
timeout). Presence = isClosed heartbeat sweep + socket-onError
|
||||
forget + lastSeen timeouts. NEVER depend on onDone. (Docs pattern
|
||||
confirms CloseReceived is a data event.)
|
||||
3. Welcome races room broadcasts — match WS messages by `t`, never
|
||||
by index.
|
||||
4. web_socket_channel streams are single-subscription — one listener
|
||||
per socket (test double-listens throw "already been listened to").
|
||||
5. `sub.asFuture()` can resolve before `onDone` — poll with
|
||||
deadlines in tests.
|
||||
6. Comma-form mpv reconnect flags work here; colon-form rejected
|
||||
(re-verify via set_property if touched).
|
||||
7. Numeric literals corrupted once by tooling — verify with rg after
|
||||
writes touching ports/consts.
|
||||
8. Tool `bash` `&`-backgrounding is unreliable; use nohup + log file
|
||||
in its OWN call, poll in later calls, kill via `fuser -k
|
||||
PORT/tcp` (never `pkill -f`). Chain small calls, never long
|
||||
`&`-chains (they hang the runner past timeout with zero output).
|
||||
9. Tests must not assume threat model beyond trust-basis.
|
||||
10. web_socket_channel 3.x: `channel.ready` errors unhandled on
|
||||
refused connections — eat it (`unawaited(ch.ready.then(...,
|
||||
onError: ...))`); stream onError is the reporting path.
|
||||
11. MediaKit has NO public Player.setProperty — runtime props go via
|
||||
guarded dynamic call on player.platform; cache size via public
|
||||
PlayerConfiguration(bufferSize:).
|
||||
12. NEVER `flutter test`-pump the session screen: media_kit Video
|
||||
hangs the runner (a hung flutter_tester must be kill -9'd by PID;
|
||||
pgrep carefully). Sync-path coverage lives in room_diff (pure),
|
||||
lifecycle (server, raw WS), coord_presence + e2e (real mpv,
|
||||
no widgets). Deleted session_overlays_test.dart for this reason.
|
||||
13. No `flutter analyze` unless asked (IDE covers it) — except
|
||||
deliberate per-change checks; kept clean throughout.
|
||||
14. New `MediaDesktopVideoControlsThemeData` per build is fine
|
||||
(stock guards subscriptions) but wasteful; leave it.
|
||||
15. Env overrides for mpv experiments (no rebuild to switch):
|
||||
SYNC_RELAY_VO (e.g. xv, gpu, gpu-next), SYNC_RELAY_HWDEC (e.g. no).
|
||||
16. Hidden-but-mounted overlays keep focus: closing the sheet left
|
||||
focus on an offstage button, so Space fell through (350 ms
|
||||
throttle hole) into the hidden control. Fix pattern: ExcludeFocus
|
||||
on the closed subtree + unfocus-on-close effect. Same reason new
|
||||
overlay buttons reuse the shared no-focus node.
|
||||
|
||||
## 7. Sounds (deferred, wiring ready)
|
||||
|
||||
Base: Kenney Interface Sounds (CC0, confirmation_* ladder for
|
||||
ascending-ready). Alt ladder: ObsydianX Pack 1 (CC0, avoid paid
|
||||
packs). Soft layer: akx/Notifications (CC0 branch). Playback pick:
|
||||
flutter_soloud (preload WAV, per-play pitch) — NOT added. Swap-in =
|
||||
replace NoopSfxService; cues already fire with readyIndex. URLs +
|
||||
mapping in 09-11 chat (unreliable — re-derive from sources above).
|
||||
|
||||
## 8. Black window while playing (09-12, FIXED)
|
||||
|
||||
Symptom was: room PLAYING ⇒ entire window black (audio + keys
|
||||
alive, unready restored, zero errors). Cause: the waiting-avatars
|
||||
center overlay unmounted its GPU textures (avatar Images) exactly
|
||||
at the HELD→PLAYING flip; teardown racing mpv's frame uploads on
|
||||
the shared GL context fails silently ⇒ black. Legacy chips never
|
||||
unmounted and minimal never mounted, which is why they survived.
|
||||
Fix: center overlay is Visibility(visible + maintainState +
|
||||
maintainAnimation + maintainSize) — avatars stay mounted, paint
|
||||
skipped when hidden. Verified by user with full tree, and holds
|
||||
over internet (WAN 2-client test, port 6969, late 09-12) — CLOSED.
|
||||
RULE: never unmount GPU-textured widgets on a transport-gated
|
||||
branch; keep mounted + skip paint. Bisect screens
|
||||
(legacy/minimal/nosheet + SYNC_RELAY_UI switch in app.dart)
|
||||
DELETED 09-12 (commit tracks this); no commented bisect lines
|
||||
remain in session_screen.dart.
|
||||
|
||||
## 9. Next (ordered, updated 09-12 late session)
|
||||
|
||||
1. §8 black screen — CLOSED (fix verified incl. over internet).
|
||||
2. Remove bisect flags — DONE 09-12 (files deleted, app.dart
|
||||
routes session directly; tree analyzes clean).
|
||||
3. 2-client LAN soak — user reports DONE 09-12 (details pending).
|
||||
4. 1.4 GB real-file media test — user reports DONE 09-12
|
||||
(details pending; api_key must never land in files).
|
||||
5.–8. MIGRATED 09-12 to `docs/ROADMAP.md` backlog (cache-exhaustion,
|
||||
sounds, file-join wart, /health) — the roadmap is now the single
|
||||
backlog; this section keeps session history + user-owned pendings
|
||||
only.
|
||||
9. FIXED 09-12: auto-unready fired while passively watching —
|
||||
the 10-min check keyed off `_lastInput`, refreshed only by
|
||||
explicit actions. Steady playback now counts as activity:
|
||||
warn + auto-unready are skipped while room transport is
|
||||
PLAYING (`session_coordinator.dart` idle block). HELD-and-idle
|
||||
still unreadies after 10 min.
|
||||
10. FIXED 09-12 (second attempt — first theory was wrong): one chat
|
||||
send rendered as TWO log rows. Root cause is server dual
|
||||
delivery, not double-send: `broadcastChat`
|
||||
(`room_hub.dart:69`) emits both a `ChatMessage` (with text,
|
||||
converted to a feed entry client-side) and a textless `feed`
|
||||
entry, and the client logged both. The blank-guard in
|
||||
`sendChat` was defense against a phantom. Real fix: client
|
||||
drops textless `chat` feed entries (`sync_client.dart` feed
|
||||
case) — one send, one row, one toast, one sfx. No wire
|
||||
change, still v4. Chat field also keeps focus after send
|
||||
(dedicated FocusNode, re-requested on submit/button).
|
||||
11. KNOWN (non-breaking, fix later — roadmap backlog #2): seeks feel
|
||||
jumpy (forward-back-forward) — suspect the seek-land retry
|
||||
(`_checkSeekLanded`, `session_coordinator.dart:429`)
|
||||
re-applying SeekAction against the 0.5 s deadband / 2 s
|
||||
debounce and the 1 Hz room echo. Needs a live repro with a
|
||||
timeline log before touching.
|
||||
12. Updater v1 SHIPPED 09-12: `watch-together --upgrade`
|
||||
(`apps/desktop/lib/src/update/updater.dart`, zero Flutter
|
||||
imports, 7 tests) — manifest check, download, sha256, apply
|
||||
over live install (extract-temp + delete-first move-over;
|
||||
ETXTBSY forbids writing the running exe, delete+rename is
|
||||
fine). Version stamped via `--dart-define=APP_VERSION`
|
||||
(wired in `tool/package_linux.sh`; dev runs report
|
||||
`0.0.0-dev`). Publishing is CI-driven: tag `vX.Y.Z` →
|
||||
`.gitea/workflows/release.yml` builds, creates the Forgejo
|
||||
release, uploads the tarball, commits the manifest back
|
||||
(`tool/release_publish.sh` does the same by hand).
|
||||
Manual trigger only: bump desktop pubspec in a release commit
|
||||
first (script enforces tag == pubspec). No silent
|
||||
proto jumps: updater warns when manifest protocol != local.
|
||||
Environment: dart 3.14 beta, flutter 3.48 beta, mpv+ffmpeg present,
|
||||
~/Videos/chiyo.mp4 sample. Never kill the user's Syncplay mpv
|
||||
instance. Git repo at project root (init 09-12); commit code + docs
|
||||
together; prefer FEW commits (one per topic/session, not per fix)
|
||||
over bisect-granularity — user decision 09-12.
|
||||
|
||||
## 10. Window chrome — frameless, mpv-style (09-12, VERIFIED by user)
|
||||
|
||||
Native title bar gone everywhere (`window_manager ^0.5.2`,
|
||||
`TitleBarStyle.hidden` in main.dart GUI path only, headless
|
||||
untouched). New screens MUST bring their own drag + min/max/close
|
||||
or they ship immovable — reuse `widgets/window_buttons.dart` +
|
||||
`widgets/window_chrome_bar.dart` (welcome/connect pattern).
|
||||
Session: drag is `widgets/window_drag_layer.dart`, topmost raw-
|
||||
pointer observer inside the controls stack (a GestureDetector
|
||||
below media_kit's overlay LOSES the arena — do not revert to
|
||||
that); dead zones: bottom 120 px (seek stays exact), open sheet,
|
||||
leave dialog. `modifyVolumeOnScroll: false` is load-bearing for
|
||||
drag — side effect: volume is speaker-button-only, no scroll-
|
||||
volume. Maximize button = media_kit fullscreen toggle in
|
||||
session (no OS maximize there); NO aspect-ratio lock by user
|
||||
decision (custom UI lives outside the video frame). Close =
|
||||
graceful leave + stopServer, then window close. Min size
|
||||
160x90, no max. Verified on KDE Wayland (Arch): bar-drag,
|
||||
video-drag, fullscreen, free resize all good.
|
||||
@@ -1,28 +1,598 @@
|
||||
# sync_relay_project
|
||||
<p align="center">
|
||||
<img src="apps/desktop/assets/icon/icon_256.png" width="128" height="128" alt="Starsync icon">
|
||||
</p>
|
||||
|
||||
Watch-together desktop app (working title). One binary, three modes:
|
||||
<h1 align="center">Starsync</h1>
|
||||
|
||||
- **Client** — GUI Join, sync WS + mpv. No server code runs.
|
||||
- **Server+Client (Host)** — GUI Host starts `packages/server` in-process,
|
||||
listens on a port, self-connects via loopback. Host must open ports.
|
||||
Clients never open ports.
|
||||
- **Headless** — `watch.exe --headless`, same server package, no window.
|
||||
Watch a video with friends, in sync, with the quality of a real mpv player.
|
||||
Pick from your Jellyfin library, paste any direct video link, or pick a file on your own disk;
|
||||
everyone's play, pause and seek stay together.
|
||||
|
||||
v1 order: links support (shared http(s) media URL, Syncplay-style sync)
|
||||
first, file relay (server-proxied bytes, whitelist case) after.
|
||||
Jellyfin native + auto-update are deferred as their own undertakings.
|
||||
Why not Jellyfin SyncPlay: it runs in the browser and its sync is poor.
|
||||
This is a desktop app that drives mpv.
|
||||
|
||||
Layout:
|
||||
Up to 1.2.x the app was called `watch_together` (its files
|
||||
`watch-together-*`); the repository and the update manifest keep their old
|
||||
addresses for now.
|
||||
|
||||
- Desktop only (Linux and Windows), always mpv. No web clients.
|
||||
- No transcoding. Everyone plays the original file.
|
||||
- Friends trust model: no accounts, no roles. A blank password means an open server.
|
||||
|
||||
How it fits together: [docs/HOW-IT-WORKS.md](docs/HOW-IT-WORKS.md).
|
||||
|
||||
## Install and update
|
||||
|
||||
From the Releases page of this repo:
|
||||
|
||||
- Linux: `starsync-<version>-linux-x64.tar.gz`. Extract, run
|
||||
`starsync`. On start it adds itself to your app launcher (and its
|
||||
icon), so the window shows its own icon on Wayland. Needs mpv's library installed (`mpv` or `libmpv2`).
|
||||
- Windows: `starsync-<version>-windows-x64.zip`. Extract, run
|
||||
`starsync.exe`. mpv is bundled. New and not yet tried on a real
|
||||
Windows desktop; reports welcome.
|
||||
|
||||
The folder also holds `watch_together(.exe)` and
|
||||
`watch-together-server(.exe)`, the names up to 1.2.x: they start the new
|
||||
programs, so an update from 1.2.x restarts fine and old shortcuts and
|
||||
service files keep working.
|
||||
|
||||
Your data (settings, sign-ins, folders, logs, yt-dlp and its cookies) lives
|
||||
in `~/.local/share/dev.foxyz.starsync` on Linux and
|
||||
`%APPDATA%\foxyz\Starsync` on Windows. The first start after 1.2.x copies
|
||||
it over from the old places (`~/.local/share/moe.senkochan.watch_together`
|
||||
or `%APPDATA%\com.example\watch_together`, and the app's files in your
|
||||
Documents folder) and leaves the originals where they were.
|
||||
|
||||
Update from the app: the app looks for a new version at start and every
|
||||
few hours, and when one exists a band across the top of the window says so
|
||||
(never over a playing video). "Update and restart" downloads,
|
||||
verifies, applies in place and restarts; "Later" hides it until the next
|
||||
check; the install folder must be writable by you. The version you run is
|
||||
at the bottom of every Settings page (and in the Settings tab's tooltip). Settings has Check now and an auto-check toggle. From a terminal:
|
||||
`./starsync-server --upgrade` (no display needed, so it works on a
|
||||
server box too), `./starsync --upgrade`, or the shipped `update.sh` /
|
||||
`update.bat` (which run the first). Each updates the whole folder, app and
|
||||
server; restart whichever is running to use the new version. A
|
||||
release with a newer protocol is a required update: everyone on a server
|
||||
must run the same protocol version, and a mismatch is refused with a message
|
||||
telling you to update.
|
||||
|
||||
## Getting started
|
||||
|
||||
The app always runs its own server, quietly: your server. When it starts
|
||||
you are on it, alone, and it is a plain player. Three ways in, at the top
|
||||
of the Library the first time; none needs Jellyfin or an account.
|
||||
|
||||
- **Join a friend** (most people): your friend sends you an invite (an
|
||||
address) and, maybe, a password. See [Join](#join).
|
||||
- **Invite friends**: you have the video and friends watch it with you.
|
||||
See [Your server and Invite](#your-server-and-invite).
|
||||
- **Watch on your own**: just play something from the Library, with
|
||||
everything a server has (Jellyfin progress, next episode, skip buttons).
|
||||
Nobody else can reach your server until you invite them; inviting never
|
||||
interrupts what plays.
|
||||
|
||||
## The window
|
||||
|
||||
One window. Along the top, the strip: your avatar (click it for your
|
||||
profile: name, picture with a crop editor, colour, and links to the
|
||||
settings), the Library / Schedule / Settings tabs, and the party. Alone
|
||||
on your server it has just Join a friend and Invite (and "Sharing" while
|
||||
your server is open to friends); with others there it shows everyone's avatar
|
||||
with a ring for their state (green ready, amber buffering, grey not ready,
|
||||
a little faded joining, dimmed reconnecting, dimmed with a moon sitting
|
||||
out; a crown on whoever
|
||||
hosts, a tower on whoever passes the video on). Click the avatars for the
|
||||
member list (each member's app version, amber when it differs from yours,
|
||||
and the server's at the top; force ready, Nudge, Sit out; on your
|
||||
server the invite with Copy invite and Stop sharing, on a friend's "Copy
|
||||
invite address"). Beside them the server and "ready n/m" (who is sitting out or
|
||||
reconnecting does not count), the chat button with unread
|
||||
count, and Invite on your server or Leave on a friend's. Empty strip
|
||||
space drags the window.
|
||||
|
||||
The player fills the window under the strip. Pick a tab and it shrinks to
|
||||
a mini player in a corner: drag it anywhere and it snaps to the nearest
|
||||
corner; double-click or ⤢ makes it big again, × sits you out (below) and
|
||||
× again closes it; the strip's screen button brings it back. F or
|
||||
double-click on the picture goes fullscreen (the strip hides, the party
|
||||
shows in a corner while paused, the window buttons sit in the player's top
|
||||
bar while its controls are up), Esc leaves it. The controls show the
|
||||
show's cover, title and episode top left (a web video: its thumbnail and
|
||||
name; guests get the art too; right-click to copy the title, or the link
|
||||
when you have it, or open it in the browser or Jellyfin); before
|
||||
a video first plays, its banner fills the picture until playback starts.
|
||||
One pill bottom centre, just above the controls, says what playback waits for ("Press Space
|
||||
when you're ready", "Waiting for Bob and Mika · 2/3 ready", "Bob is
|
||||
loading…") or what went wrong, with Retry or Cancel when it helps. Chat and activity open in a panel on the right (chat button or
|
||||
Tab), ready to type; it shows messages (select text to copy it, or
|
||||
right-click for Copy message and, with a link in it, Copy link / Open in
|
||||
browser), and its "Activity" toggle adds
|
||||
joins, ready, seeks and the like between them. Joins, leaves, someone
|
||||
losing connection and coming back, video changes, additions to Up next
|
||||
(the title, its picture and who added it), chat and problems also pop up
|
||||
bottom left with the person's avatar, above the player's controls (never
|
||||
on them); ready, seeks and pauses stay in the activity. Click a message
|
||||
to open the chat (Settings → Notifications & sounds → Chat messages: All
|
||||
by default, or Only when paused, or Off; messages always reach the chat,
|
||||
with their sound). Watching alone, nothing pops up or sounds about the
|
||||
party (there is nobody); the app's own notices still show.
|
||||
|
||||
**While sitting out or in the background.** Sitting out, only chat,
|
||||
nudges, "starting now" (the video starts for the others) and Up next
|
||||
reach you; joins and leaves too if you turn on Settings → Notifications &
|
||||
sounds → "Joins and leaves too". With the window in the background or
|
||||
minimised, the same ones also come as desktop notifications (Linux's
|
||||
notification center, Windows' toasts); clicking one brings the window
|
||||
up, and a chat one opens the chat. Unread chat shows as a count on the chat
|
||||
buttons and, in fullscreen with the controls hidden and the video paused,
|
||||
as a small chip top right.
|
||||
|
||||
Your name and picture change for everyone in the server right away; the
|
||||
colour is yours only.
|
||||
|
||||
**Sitting out.** Step away without leaving: Sit out (your profile, your
|
||||
row in the member list, or × on the mini player) unloads the video on your
|
||||
end, and nobody waits for you any more; you stay in chat. Anyone can sit
|
||||
anyone out, the host too ("Alice sat you out" tells you who). The player
|
||||
then shows the cover, title and where the others are; Join back (or Space)
|
||||
loads the video there and readies you, in the background while the others
|
||||
play on (nobody is paused for you).
|
||||
|
||||
**Auto sit-out.** Idle for 5 minutes while nothing plays, or the window
|
||||
minimised for 10 minutes (playing or not), sits you out by itself, so
|
||||
nobody waits for you; you are back as soon as you return (a key, the
|
||||
mouse, the window's focus). It never happens when you are alone, and an
|
||||
away you chose (or someone else's) stays until you join back. Settings →
|
||||
Party & network → "Auto sit-out" turns it off.
|
||||
|
||||
**Reconnects.** A bad connection does not throw you out: the video keeps
|
||||
playing, the pill says "Connection unstable…" and then "Reconnecting…",
|
||||
and the app comes back on its own as the same member (ready, sitting out,
|
||||
your Up next items and the video you pass on all kept) for up to 10
|
||||
minutes; the others see you dimmed, "reconnecting…". Only a drop of a
|
||||
few seconds or more makes the lost / back sounds. Leave and closing the
|
||||
app tell the others at once; Update and restart keeps your place for the
|
||||
restarted app. Opening Starsync a second time (another window with the
|
||||
same profile) takes your place over, and the first one says so and stops.
|
||||
|
||||
**Nudge.** Nudge in the member list pokes someone, sitting out or not:
|
||||
only they hear it (a sound, a pop-up, and the taskbar entry asks for
|
||||
attention when the window is in the background).
|
||||
|
||||
## Your server and Invite
|
||||
|
||||
Your server starts with the app and stops when it closes. Only this app
|
||||
can reach it until you press **Invite** (in the strip, or in the member
|
||||
list): that opens it on your network at the port from Settings → Party &
|
||||
network (default 8080, with the password set there; blank = anyone can
|
||||
join) and copies an invite ("Join me on Starsync: 192.168.1.20:8080 ·
|
||||
Starsync 1.3.0") to send to friends. Nothing restarts: what plays and Up
|
||||
next carry on, and you are the host (the crown). The invite picks this
|
||||
computer's home-network address (not a VPN or proxy one, nor a Docker or
|
||||
VM bridge). Friends elsewhere need the TCP port forwarded on your router
|
||||
(or a VPN address, or a server they can all reach, like a VPS). Friends
|
||||
open nothing. **Stop sharing** (in the member list) closes it again:
|
||||
everyone else leaves (their app goes back to their own server and says
|
||||
why), you and Up next stay.
|
||||
|
||||
If you put up a local file, your server streams it to everyone from your
|
||||
disk. Nothing is uploaded or stored anywhere.
|
||||
|
||||
Joining a friend leaves your server for theirs; it stays up meanwhile,
|
||||
and leaving theirs brings you back to it as you left it.
|
||||
|
||||
## Library
|
||||
|
||||
What to watch, from three sources (the switch at the top). Drop a video,
|
||||
a folder or a link anywhere on the window, or press Ctrl+V outside a
|
||||
text field, and a small card asks how to open it (put it up, add it to
|
||||
Up next, add the folder to Files, or fill Link).
|
||||
|
||||
- **Jellyfin**: your linked servers (see below); with none linked it
|
||||
points to Files and Link and offers Jellyfin as optional. Library chips beside the
|
||||
switch, then one **Continue** row (what you were watching and what comes
|
||||
next, one card per series, the one you watched most recently first;
|
||||
series not touched for two months drop out) and **Latest in** each
|
||||
library (one card per series: "S1E1" or "3 new"; Show all opens the
|
||||
library newest first). Re-uploads (added long after they aired) are
|
||||
hidden from Latest; the row's ⋮ menu turns that off. Search (/), library
|
||||
grids (sort, unwatched, favourites) and series pages sit behind them.
|
||||
Click a card to select it: its
|
||||
details open on the right with "Put it up · S1E3", mark watched /
|
||||
unwatched, remove from Continue and the episode list (click an episode
|
||||
to choose it). Double-click a card or an episode to put it up at once.
|
||||
Right-click a card or an episode to copy its title or open it in
|
||||
Jellyfin's web page (the details panel has that button too).
|
||||
- **Link**: paste an http(s) link: a video file, or a web page with a
|
||||
video (YouTube, X, and whatever else yt-dlp knows). The preview shows
|
||||
what it is (a page's title, uploader, length and thumbnail, else the
|
||||
file name); in a server, pick how the
|
||||
others get it (everyone fetches it, the server fetches it, or through
|
||||
you). Your last 12 links are listed under it (right-click one to copy
|
||||
or open it). A link seen before shows its preview at once, without
|
||||
asking the site again. A link that does not
|
||||
open here (needs cookies, 403, 404, not a video) says why and goes up
|
||||
only with "Put it up anyway"; in the player, whoever cannot play it is
|
||||
named ("Bob can't play this: Not allowed (403)") and nobody waits for them.
|
||||
- **Files**: your own library from the video folders you add on this
|
||||
computer (the **Library** shows them all together, each folder on its
|
||||
own too), or any file through Browse. Files are sorted into shows and
|
||||
movies by their names and folders: one show split over several folders
|
||||
is one show, OP/ED and specials go under its **Extras**, a folder like
|
||||
"Show (Season 3 - Alicization)" gives the season and its name. Shows
|
||||
are looked up on AniList for their proper name, cover and banner. A
|
||||
show's page has its seasons and episodes and a button for the next one
|
||||
after what you last watched here; when episodes are missing on the way
|
||||
it says so ("66–107 aren't in your folders — skip to 108?"). An
|
||||
episode you put up continues with the next one at its end (see Up
|
||||
next). Matched
|
||||
the wrong show? **Wrong show?** searches AniList and pins the right one
|
||||
for the show everywhere or just one folder; **Episode numbers…** says
|
||||
which episode the first file is when the files count differently. Both
|
||||
stay through rescans. The others stream what you put up from you, and
|
||||
see its proper name too.
|
||||
|
||||
Put it up and the player opens. With nobody else in the server, the
|
||||
buttons say Play and a link plays straight from the site.
|
||||
|
||||
### Up next (the queue)
|
||||
|
||||
Anything can wait its turn instead of going up
|
||||
now: **Add to queue** on the Link page (in the way you picked), or
|
||||
right-click a Jellyfin card or episode, a video in Files, a recent link
|
||||
or an episode on the Schedule for **Add to queue** / **Play next**; the
|
||||
Jellyfin details panel has a queue button (right-click it to play next),
|
||||
and the card for a dropped or pasted video or link has both. A link is
|
||||
checked first, like Put it up. Every app keeps the next item ready,
|
||||
its first seconds already loaded, so skipping to it starts at once.
|
||||
For a link passed on, a member's file or a link the server fetches,
|
||||
the server starts getting the next item while the current one plays
|
||||
(from the app of whoever added it, or by fetching the link itself), so
|
||||
everyone has its start before it goes up; whoever added it keeps the
|
||||
app open for that. Everyone shares one Up next and anyone can change it; what
|
||||
you added stays when you leave.
|
||||
|
||||
In the player, Up next sits in the top bar, right of the title: the
|
||||
next item's picture and title (or what continues the episode). Rest the mouse on
|
||||
it for a larger preview (who added it, its length, whether it is ready
|
||||
to start); ⏭ plays it now, a click opens the queue: drag rows to reorder, hover a
|
||||
row to play it now (▶) or remove it (×), right-click it for more (copy its
|
||||
title or link, open it in the browser or in Jellyfin). To add, press
|
||||
Ctrl+V with the queue open (a copied link or video file goes in at once,
|
||||
its title and picture showing while it is checked), type one after
|
||||
**+ Add link**, or drop a link or a video on it. When a video ends, a card shows
|
||||
what is up next with a 10 s countdown everyone sees, and it plays;
|
||||
Cancel stops it for everyone, and so does seeking back. `>` or Shift+N
|
||||
plays it at once. Under the queue, **Continues with** shows what
|
||||
continues the episode playing: its next episode (a Jellyfin episode's,
|
||||
or a file's next one in your Files library, saying which numbers it
|
||||
skips), added by whoever put the episode up, and greyed because it
|
||||
plays only once Up next is empty; **Clear** drops it for everyone. The
|
||||
further episodes of a Jellyfin series show under it; **+** adds one.
|
||||
|
||||
A link you pass on ("through me") or a file of yours can only be played
|
||||
by your app: if you left when its turn comes, it is skipped ("Skipped …:
|
||||
Foxyz left"). If you are only gone for a moment, the countdown waits for
|
||||
you. A Jellyfin item needs someone with an account on that server. Up
|
||||
next is kept by the server while it runs. If the server restarts, the
|
||||
apps put back what was playing, where it was, and Up next with it (a
|
||||
link the server fetched has to be added again).
|
||||
|
||||
## Schedule
|
||||
|
||||
The week's airing anime, one column per day (AniList), each episode
|
||||
marked with what the Jellyfin server has of it when AnimeFlow is
|
||||
connected (Settings, Jellyfin & integrations): **on Jellyfin** (Put it
|
||||
up, right-click to queue), **downloading**, **waiting for release**
|
||||
(aired in Japan, AnimeFlow downloads it by itself once a release
|
||||
appears; with when AnimeFlow last searched, or **release rejected** when
|
||||
it found releases it won't take, the reason on hover), **failed**, **not monitored** (Request asks AnimeFlow for it),
|
||||
or the time left until it airs. A show AnimeFlow does not follow can be asked for with **Request
|
||||
series**. Episodes you already watched on Jellyfin carry a check on the
|
||||
cover; one you started shows how far you got.
|
||||
|
||||
## Dedicated server
|
||||
|
||||
For an always-on box (no display needed): the release tarball also contains
|
||||
`starsync-server`, a small standalone server without the app. Run it,
|
||||
then everyone (you included) uses Join.
|
||||
|
||||
```
|
||||
/packages/core protocol, sync engine, messages (pure Dart, no Flutter)
|
||||
/packages/server room + media HTTP endpoint (pure Dart, no Flutter)
|
||||
/apps/desktop Flutter app embedding packages/server (the ONE binary)
|
||||
/tool spikes + harnesses (range_logger, shaper, fake_viewer, e2e_check)
|
||||
/deploy systemd unit, notes
|
||||
/docs PROTOCOL.md, ARCHITECTURE.md, mpv-http-contract.md, ROADMAP.md
|
||||
./starsync-server --port 8080 --secret <password>
|
||||
```
|
||||
|
||||
Phases + status: `docs/ROADMAP.md`. Session handoff: `HANDOFF.md` (root).
|
||||
| Flag | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `--port`, `-p` | 8080 | TCP port, all IPv4 interfaces |
|
||||
| `--secret` | empty | password; empty = open server (a warning is printed) |
|
||||
| `--name` | `server` | name reported by `/health` |
|
||||
| `--media` | none | local file to serve as the starting video |
|
||||
| `--advertise-host` | none | host put in file URLs instead of the one each viewer dialled |
|
||||
| `--[no-]yt-dlp` | on | read web pages (YouTube, X, …) with yt-dlp when the server fetches a link |
|
||||
| `--yt-dlp-dir` | next to the binary | writable folder for the server's yt-dlp (systemd: the unit's `StateDirectory`) |
|
||||
| `--yt-dlp-cookies` | none | cookies.txt or cookie-extension JSON export for that yt-dlp (sites that refuse guests); copied into the yt-dlp folder at start, removed from it when not given. **An account login**: keep it private, use a throwaway account for YouTube |
|
||||
| `--log-dir` | `logs` next to `--config`, else next to the binary (systemd: the unit's `StateDirectory`) | folder for the log files (`server-YYYY-MM-DD.log` and the session log `session-YYYY-MM-DD.log`, kept 7 days; passwords, tokens and cookies left out) |
|
||||
| `--config` | none | YAML or JSON file with the same settings (`port`, `secret`, `name`, `mediaPath`, `advertiseHost`, `ytDlp`, `ytDlpDir`, `ytDlpCookies`); replaces the flags |
|
||||
| `--upgrade` | | update the install folder to the latest release ([Install and update](#install-and-update)), then exit |
|
||||
| `--check-update` | | print whether a newer release exists, then exit |
|
||||
|
||||
Enforcement: `core` and `server` must have zero Flutter imports (tested).
|
||||
It prints `READY port=... name=...` once listening and stops cleanly on
|
||||
Ctrl+C or SIGTERM. A dedicated server has no host.
|
||||
To run it as a service, unpack the tarball to `/opt/starsync` and use
|
||||
[deploy/starsync.service](deploy/starsync.service) (copy it to
|
||||
`/etc/systemd/system/`, edit the flags, `systemctl enable --now starsync`).
|
||||
A service set up before the rename (`/opt/watch-together`, running
|
||||
`watch-together-server`) keeps working as it is.
|
||||
|
||||
Something not playing? Settings → About → **Copy diagnostics** puts the
|
||||
app's recent log (passwords, tokens and cookies left out) on the
|
||||
clipboard: paste it to whoever helps you, from both sides if you can.
|
||||
|
||||
While you are in a server, the app also sends its log to that server, which
|
||||
merges everyone's lines and its own into one session log
|
||||
(`session-YYYY-MM-DD.log` next to the server's logs; your own server
|
||||
keeps it in the app's logs folder), so a problem can be read afterwards from every
|
||||
side. Chat is never logged anywhere, nor passwords, tokens and cookies.
|
||||
When something goes wrong, press **Mark a problem** (Ctrl+Shift+B, also in
|
||||
the player's ⚙ and Settings → About) and add a few words if you like: a
|
||||
marker with your name goes in the session log at that moment. In a server,
|
||||
Copy diagnostics can add the session log of the last 6 hours (any member
|
||||
may read it). Don't want to share? Settings → About → **Share diagnostics
|
||||
with the server** off: your log stays on your machine (the server only
|
||||
notes that you don't share; a problem you mark still goes in).
|
||||
|
||||
## Join
|
||||
|
||||
Join a friend in the strip. Servers you got into are listed first (up
|
||||
to 6), with live status (online and how many are watching, or offline,
|
||||
plus "needs update" when its version and yours do not match): click one
|
||||
to rejoin, x to forget it. Or paste the invite (or the address and port)
|
||||
and the password if there is one, then Enter or Join. Before connecting
|
||||
the app checks the server's version: when they do not match it says who
|
||||
has to update ("Bob's server runs Starsync 1.2.1 — they need to
|
||||
update"), and offers the update when it is you. Your name and picture
|
||||
come from your profile (your avatar at the top left). Leave goes back to
|
||||
your own server.
|
||||
|
||||
## Settings
|
||||
|
||||
The Settings tab (Ctrl+,) has a page per topic, each setting with a line
|
||||
of help: Profile; Party & network (your server's port and password for
|
||||
Invite, recent servers with remove); Player (below); Jellyfin &
|
||||
integrations (linked Jellyfin servers, below, the AnimeFlow connection:
|
||||
"connected as <name>" with what you may do, or why not, and playing the
|
||||
next episode automatically); Notifications & sounds (what pops up, chat
|
||||
pop-ups, what reaches you while sitting out or in the background; the sound
|
||||
volume and sound set, and every sound with a preview, its own set and a switch); Updates; Keyboard shortcuts (read-only); About
|
||||
(the version, also at the bottom of every Settings page and in the
|
||||
Settings tab's tooltip; and the credits, e.g. that the Minimal player design is inspired by uosc).
|
||||
|
||||
Player settings live in the player too: ⚙ → Player settings, at the
|
||||
right of its controls, and Settings → Player has the same ones (plus the
|
||||
controls' layout and the custom shader files). Player design: Standard or
|
||||
Minimal (below); progress line when hidden (on by default: a thin line at
|
||||
the bottom of the video while the controls are hidden); upscaling shader
|
||||
(see below); hardware decoding (auto, off or custom; auto is mpv's
|
||||
`auto-copy` on Windows, `auto` elsewhere; the env var
|
||||
`SYNC_RELAY_HWDEC` overrides it); in the player also the subtitle and
|
||||
audio track. Settings → Player → Controls: time display (elapsed / total
|
||||
or remaining), controls size (normal or large), hide the controls after
|
||||
2, 3 or 5 s, and which optional buttons sit in the bar (chapter buttons,
|
||||
subtitles, audio, chat; hidden ones are still in ⚙). Every change
|
||||
applies right away.
|
||||
|
||||
Anywhere in a server (unless you are typing): Space = ready / unready,
|
||||
Tab = chat & activity (Tab never moves between buttons). Anywhere:
|
||||
Ctrl+Shift+B = mark a problem in the session log. Keys while the
|
||||
player fills the window: Left/Right = seek 10 s, Up/Down = volume, Shift+Right = skip 1:30,
|
||||
PgUp/PgDn = previous / next chapter (as in mpv), F = fullscreen, Esc =
|
||||
close the chat, then fullscreen, then shrink the player to mini; from the
|
||||
mini it asks to leave, Ctrl+R = reload video,
|
||||
`<` / `>` or Shift+P / Shift+N = previous / next Jellyfin episode,
|
||||
Ctrl+1..6 = Anime4K mode A, B, C, A+A, B+B, C+A, Ctrl+0 = shaders off.
|
||||
Every seek, skip and chapter jump moves everyone.
|
||||
|
||||
Controls: both designs have the same buttons in the same places, only
|
||||
the look differs. Bottom left: play / pause first (it is your ready, like
|
||||
Space: ✓ while you are ready and the others are not), previous / next
|
||||
episode (when there is one; next plays Up next first), previous / next
|
||||
chapter (when the video has chapters), volume and the time (click it to
|
||||
switch between elapsed / total and the time left). Bottom right:
|
||||
Subtitles and Audio (with the track count; tracks listed as "Japanese ·
|
||||
E-AC3 2.0 · title", subtitles with Off), ⚙, chat and fullscreen last.
|
||||
Everything else is in ⚙: chapters (current one checked; click to jump),
|
||||
Skip 1:30, upscaling shader, change video, copy link, reload video,
|
||||
mark everyone ready, mark a problem, player settings and leave. The top
|
||||
bar has the title, Up next and back to the library (in fullscreen: exit
|
||||
fullscreen and the window buttons). Volume (scroll anywhere on the
|
||||
video, hover the speaker, or Up/Down) goes to 150 % like mpv: past the
|
||||
tick at 100 % the bar turns amber and mpv amplifies; a scroll or key
|
||||
shows the volume for a moment. Lists and menus under the mouse scroll
|
||||
as usual.
|
||||
|
||||
Standard (the default): a seek bar that marks chapter starts with a
|
||||
diamond (hovering it shows the time and the chapter title) over a row
|
||||
of round buttons. Minimal (⚙ → Player settings → Player design, switches
|
||||
right away): a translucent timeline across the bottom tints what has
|
||||
played, stripes the part not downloaded yet, marks chapter starts with
|
||||
dots (click one to jump), shows the elapsed time left and the total or
|
||||
the time left right (click it to switch) and, while less than a minute
|
||||
is buffered, the buffered seconds next to the position; hovering it shows
|
||||
the time there and the chapter title. With the controls hidden it stays
|
||||
as a thin line (unless "Progress line when hidden" is off). Its buttons
|
||||
sit in two glass capsules above it. Minimal's timeline and controls are
|
||||
inspired by [uosc](https://github.com/tomasklaen/uosc) by tomasklaen
|
||||
(LGPL-2.1).
|
||||
|
||||
Skipping: during the opening a "Skip OP" button shows bottom right, just
|
||||
above the controls (it
|
||||
jumps to the end of the opening), during the ending "Skip ED" (to the end
|
||||
of the ending only; what comes after is yours to skip). "Skip OP" and
|
||||
"Skip 1:30" show for 5 seconds when they come up, then only while the
|
||||
controls are up (move the mouse); "Skip ED" and "Next episode" show only
|
||||
while the controls are up. The opening and
|
||||
ending come from Jellyfin's intro / outro segments when your Jellyfin has
|
||||
them (needs a segment plugin, e.g. Intro Skipper), else from chapter names
|
||||
(OP, Opening, Intro / ED, Ending, Credits, Outro). Without an opening or
|
||||
any chapters, on anything longer than 20 minutes, "Skip 1:30" floats there
|
||||
during the first 6 minutes.
|
||||
|
||||
## Ports
|
||||
|
||||
| What | Default | Notes |
|
||||
|---|---|---|
|
||||
| Sync WebSocket and `/health` | TCP 8080 | plain `ws://`, no TLS |
|
||||
| Local file streaming | same port | path `/m/...`, needs a session token |
|
||||
|
||||
Only the one who invites needs the port reachable; until Invite your
|
||||
server listens on 127.0.0.1 and a free port only.
|
||||
|
||||
## Jellyfin
|
||||
|
||||
Settings > Jellyfin & integrations > Add server: type the address, then sign in with
|
||||
Quick Connect (the app shows a code; approve it in Jellyfin under Profile >
|
||||
Quick Connect) or your username and password. Several servers can be
|
||||
linked; each shows its status, and a star picks the default. Sign out
|
||||
revokes the app's sign-in on the server. If a sign-in expires the server
|
||||
shows "Reconnect" instead of disappearing.
|
||||
|
||||
The Library's Jellyfin source is a library browser: Continue watching (with
|
||||
time left), Next up and the latest per library on the start page; library
|
||||
grids with sort (name, date added, release date, rating, random) and
|
||||
Unwatched / Favorites filters; series pages with seasons, episode progress
|
||||
and a "Next up" button; details with the file's tracks; search. Clicking a
|
||||
movie or episode picks it. On wide windows a side pane shows details of
|
||||
whatever is under the mouse.
|
||||
|
||||
Keys in the browser: arrows move, Enter picks or opens, I = details,
|
||||
Esc / Backspace / Alt+Left = back (Esc first clears a search), / or Ctrl+F =
|
||||
search.
|
||||
|
||||
Putting up a movie or episode sends only the item to the server (which
|
||||
Jellyfin server and which item), never a link or your sign-in. Pasting a Jellyfin link (web page or stream link) does the
|
||||
same when the app can reach that Jellyfin; otherwise it is shared as a
|
||||
plain link.
|
||||
|
||||
Watching:
|
||||
- Everyone with their own account on that Jellyfin server plays the file
|
||||
directly with their own sign-in. Jellyfin tracks progress per account:
|
||||
your watched state, Continue watching and resume point follow what you
|
||||
saw (reported on start, every 10 s, on pause, resume, seek and track
|
||||
change, and when it stops). Watched means you were there while most
|
||||
of it played (or while half of it played and it reached the ending),
|
||||
not where it stopped: time you sat out does not count, skipping around
|
||||
does not count, opening a watched episode to check a moment keeps it
|
||||
watched, and a quick peek leaves no resume point. Files and links you
|
||||
watch are remembered the same way on your computer (a show's next
|
||||
episode in Files follows them).
|
||||
- Friends without an account watch through the server: whoever put the
|
||||
item up passes it on automatically, with their own sign-in, which never
|
||||
leaves their computer (only the current item, only to people in the
|
||||
session). They show "via server" in the member list (click the avatars). On your
|
||||
own server (with your sign-in on that item's Jellyfin, whichever of
|
||||
your linked servers it is), or a dedicated server with its own login (`--jellyfin <file>`, see
|
||||
[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), Jellyfin relay), the server
|
||||
fetches it itself instead.
|
||||
- If nobody can pass it on (the person who put it up left), the app says
|
||||
"No Jellyfin account here for ..." with a button to link one; it plays as
|
||||
soon as you are signed in.
|
||||
|
||||
Episodes: the ⏮ / ⏭ buttons next to play (or `<` / `>`,
|
||||
Shift+P / Shift+N) put up the previous or next episode for everyone. From
|
||||
the ending (when it is known, see Skipping above; else in the last two
|
||||
minutes) a "Next episode" button floats in the corner while the controls
|
||||
are up. With "Play the next episode automatically" (Settings, on by
|
||||
default), the episode you put up continues with the next one: when it
|
||||
ends, everyone sees a 10 s countdown, and anyone can cancel it (see Up
|
||||
next). Anyone with an account can put the next one up; friends watching
|
||||
via the host cannot.
|
||||
|
||||
Audio and subtitles: the Audio and Subtitles buttons in the controls pick tracks.
|
||||
Your choice is remembered per series (and as a default) and the closest
|
||||
match (language, then title, then codec and channels) is selected on the
|
||||
next episode. This is per person; nobody else is affected.
|
||||
|
||||
⚙ → Change video in the player opens the Library tab (the player
|
||||
goes mini): the library starts on the series you are watching with the
|
||||
current season, else where you left it.
|
||||
|
||||
Anyone can put up a file from their own computer, also on a dedicated
|
||||
server: it streams from your computer through the server to everyone (the
|
||||
server keeps a few minutes in memory, so seeks and skipping the opening
|
||||
are quick). Keep the app open while it plays. A link goes up "Through
|
||||
me": your computer opens it and passes it on, so it plays for everyone
|
||||
whenever it plays for you (you can't tell ahead which sites want cookies,
|
||||
and YouTube may start asking any day). Under "Other ways" there are two more:
|
||||
- Everyone fetches it: each app plays the link itself.
|
||||
- Server fetches it: the server downloads it once for everyone, for links
|
||||
that are slow or blocked for some. The server must be able to reach it,
|
||||
and it must have a password (an open server refuses: anyone could make
|
||||
it fetch addresses only it can reach).
|
||||
|
||||
Web pages work in all three: the app and the dedicated server each
|
||||
download [yt-dlp](https://github.com/yt-dlp/yt-dlp) by themselves (checked
|
||||
against the release's checksums, updated once a day; Settings → Player
|
||||
shows its version and has "Update now"), so there is nothing to install.
|
||||
Sites that refuse guests (Bilibili answers "HTTP Error 412", YouTube may
|
||||
ask to sign in) need cookies: Settings → Player → yt-dlp → Cookies reads
|
||||
them from a browser, or from a cookies.txt or a cookie extension's JSON
|
||||
export (picked or dropped; every site in it is kept). They stay on this
|
||||
computer and are used by its yt-dlp only (your own playback, "through
|
||||
me", and a server you host). Cookies log yt-dlp in as you on those
|
||||
sites: keep the file private, and for YouTube consider a throwaway
|
||||
account (Google may flag accounts used with yt-dlp). When a page shows
|
||||
no video, the message says which cookies were used: none, your file
|
||||
(and whether it has any for that site), or your browser's (and how many
|
||||
it has for that site), so you know whether to sign in there or add
|
||||
cookies.
|
||||
YouTube works in all three too, and so do pages and links that only
|
||||
offer streaming playlists (HLS `.m3u8`, DASH `.mpd`, the HLS of X videos).
|
||||
Through me and Server fetches it never show the link to anyone; they can't pass on live
|
||||
streams or DRM-protected video (use "Everyone fetches it" for live).
|
||||
Your upload has to beat the video's bitrate: a 25-minute 2 GB episode is
|
||||
about 11 Mbit/s.
|
||||
|
||||
The member list (click the avatars) shows where the video comes from on
|
||||
top: who passes it on, or that the server fetches it, everyone plays the
|
||||
link, or everyone streams it from Jellyfin, with how many watch through
|
||||
the server and, for a relay, how fast it arrives against what the video
|
||||
needs (the bar's mark; past it is keeping up). It turns amber when the
|
||||
source is too slow or its connection dropped ("Bob's connection dropped —
|
||||
playing what the server has (2 min)"), red when it left (the others play
|
||||
out what the server already has; the player's pill says the same and a
|
||||
pop-up tells you once), and whoever passes it on is told once when their
|
||||
upload is too slow. Each member's line says how they get it
|
||||
("via server" with their speed, or "direct") after a dot for their
|
||||
buffer: green enough to play on, amber low, red empty. A red dot on one
|
||||
member while the source keeps up is their own connection.
|
||||
|
||||
## Video quality and shaders
|
||||
|
||||
Each viewer can run mpv GLSL shaders on their own picture; nobody else is
|
||||
affected. The app ships [Anime4K](https://github.com/bloc97/Anime4K) v4.0.1
|
||||
(MIT) with the presets of its mpv guide: Mode A (1080p sources), B (720p),
|
||||
C (480p), A+A, B+B, C+A, each as HQ (strong GPUs, GTX 1080 and up) or Fast
|
||||
(the guide's low-end set). "Custom shaders" runs your own `.glsl` files.
|
||||
|
||||
Pick one with ⚙ → Upscaling shader in the player (also in
|
||||
fullscreen) or Ctrl+0..6; the change applies live and is saved, so the next
|
||||
session starts with it. ⚙ → Player settings and Settings → Player set it too,
|
||||
with HQ or Fast (used by Ctrl+1..6); Settings → Player holds the custom
|
||||
files. Shaders cost GPU time
|
||||
every frame and need hardware video rendering: on media_kit's software
|
||||
fallback they do nothing, and the app says so. A shader that is missing or
|
||||
fails to load shows a toast and switches shaders off.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- "host offline - check address and port": wrong address, or the port is not open.
|
||||
- "wrong server password": password mismatch.
|
||||
- "host runs a different version": update the app on both sides.
|
||||
- Picture frozen but sound fine: Ctrl+R reloads the video.
|
||||
- Everyone waits at "waiting for X": X has not buffered 4 seconds yet or has not pressed Space.
|
||||
- Windows: the build is new; if something is off there, say so.
|
||||
|
||||
For contributors: [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md),
|
||||
[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), [docs/PROTOCOL.md](docs/PROTOCOL.md).
|
||||
@@ -1,17 +1,6 @@
|
||||
# watch_together
|
||||
# apps/desktop
|
||||
|
||||
A new Flutter project.
|
||||
|
||||
## Getting Started
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
|
||||
- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter)
|
||||
- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources)
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
The Flutter desktop app (what users run; hosting runs the server from
|
||||
`packages/server` on an isolate). Layout and rules:
|
||||
[../../docs/ARCHITECTURE.md](../../docs/ARCHITECTURE.md). Build and test:
|
||||
[../../docs/DEVELOPMENT.md](../../docs/DEVELOPMENT.md).
|
||||
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
|
||||
<defs><linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#2d2547"/><stop offset="1" stop-color="#14111d"/></linearGradient><linearGradient id="t1" gradientUnits="userSpaceOnUse" x1="50.7" y1="148.7" x2="184.6" y2="71.4"><stop offset="0" stop-color="#f0795a" stop-opacity="0"/><stop offset="0.45" stop-color="#f0795a" stop-opacity="0.85"/><stop offset="1" stop-color="#ffc56b"/></linearGradient><linearGradient id="t2" gradientUnits="userSpaceOnUse" x1="205.3" y1="107.3" x2="71.4" y2="184.6"><stop offset="0" stop-color="#ffc56b" stop-opacity="0"/><stop offset="0.45" stop-color="#ffc56b" stop-opacity="0.85"/><stop offset="1" stop-color="#f0795a"/></linearGradient></defs>
|
||||
<rect x="8" y="8" width="240" height="240" rx="56" fill="url(#bg)"/>
|
||||
<circle cx="128" cy="128" r="80" fill="none" stroke="#ffffff" stroke-opacity="0.10" stroke-width="6"/>
|
||||
<path d="M205.27 107.29 A80 80 0 0 1 71.43 184.57" fill="none" stroke="url(#t2)" stroke-width="7" stroke-linecap="butt"/><path d="M50.73 148.71 A80 80 0 0 1 184.57 71.43" fill="none" stroke="url(#t1)" stroke-width="7" stroke-linecap="butt"/>
|
||||
<path d="M110 96 L110 160 L162 128 Z" fill="#fff1d6" stroke="#fff1d6" stroke-width="16" stroke-linejoin="round"/>
|
||||
<path d="M71.4 161.6 Q74.7 181.3 94.4 184.6 Q74.7 187.8 71.4 207.6 Q68.2 187.8 48.4 184.6 Q68.2 181.3 71.4 161.6 Z" fill="#f0795a"/>
|
||||
<path d="M184.6 40.4 Q188.9 67.1 215.6 71.4 Q188.9 75.8 184.6 102.4 Q180.2 75.8 153.6 71.4 Q180.2 67.1 184.6 40.4 Z" fill="#ffc56b"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 732 B |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,36 @@
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
// distribute this software, either in source code form or as a compiled
|
||||
// binary, for any purpose, commercial or non-commercial, and by any
|
||||
// means.
|
||||
|
||||
// In jurisdictions that recognize copyright laws, the author or authors
|
||||
// of this software dedicate any and all copyright interest in the
|
||||
// software to the public domain. We make this dedication for the benefit
|
||||
// of the public at large and to the detriment of our heirs and
|
||||
// successors. We intend this dedication to be an overt act of
|
||||
// relinquishment in perpetuity of all present and future rights to this
|
||||
// software under copyright law.
|
||||
|
||||
// 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 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.
|
||||
|
||||
// For more information, please refer to <https://unlicense.org>
|
||||
|
||||
//!DESC Anime4K-v4.0-AutoDownscalePre-x2
|
||||
//!HOOK MAIN
|
||||
//!BIND HOOKED
|
||||
//!BIND NATIVE
|
||||
//!WHEN OUTPUT.w NATIVE.w / 2.0 < OUTPUT.h NATIVE.h / 2.0 < * OUTPUT.w NATIVE.w / 1.2 > OUTPUT.h NATIVE.h / 1.2 > * *
|
||||
//!WIDTH OUTPUT.w
|
||||
//!HEIGHT OUTPUT.h
|
||||
|
||||
vec4 hook() {
|
||||
return HOOKED_tex(HOOKED_pos);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
// distribute this software, either in source code form or as a compiled
|
||||
// binary, for any purpose, commercial or non-commercial, and by any
|
||||
// means.
|
||||
|
||||
// In jurisdictions that recognize copyright laws, the author or authors
|
||||
// of this software dedicate any and all copyright interest in the
|
||||
// software to the public domain. We make this dedication for the benefit
|
||||
// of the public at large and to the detriment of our heirs and
|
||||
// successors. We intend this dedication to be an overt act of
|
||||
// relinquishment in perpetuity of all present and future rights to this
|
||||
// software under copyright law.
|
||||
|
||||
// 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 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.
|
||||
|
||||
// For more information, please refer to <https://unlicense.org>
|
||||
|
||||
//!DESC Anime4K-v3.2-AutoDownscalePre-x4
|
||||
//!HOOK MAIN
|
||||
//!BIND HOOKED
|
||||
//!BIND NATIVE
|
||||
//!WHEN OUTPUT.w NATIVE.w / 4.0 < OUTPUT.h NATIVE.h / 4.0 < * OUTPUT.w NATIVE.w / 2.4 > OUTPUT.h NATIVE.h / 2.4 > * *
|
||||
//!WIDTH OUTPUT.w 2 /
|
||||
//!HEIGHT OUTPUT.h 2 /
|
||||
|
||||
vec4 hook() {
|
||||
return HOOKED_tex(HOOKED_pos);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v4.0-De-Ring-Compute-Statistics
|
||||
//!HOOK MAIN
|
||||
//!BIND HOOKED
|
||||
//!SAVE STATSMAX
|
||||
//!COMPONENTS 1
|
||||
|
||||
#define KERNELSIZE 5 //Kernel size, must be an positive odd integer.
|
||||
#define KERNELHALFSIZE 2 //Half of the kernel size without remainder. Must be equal to trunc(KERNELSIZE/2).
|
||||
|
||||
float get_luma(vec4 rgba) {
|
||||
return dot(vec4(0.299, 0.587, 0.114, 0.0), rgba);
|
||||
}
|
||||
|
||||
vec4 hook() {
|
||||
|
||||
float gmax = 0.0;
|
||||
|
||||
for (int i=0; i<KERNELSIZE; i++) {
|
||||
float g = get_luma(MAIN_texOff(vec2(i - KERNELHALFSIZE, 0)));
|
||||
|
||||
gmax = max(g, gmax);
|
||||
}
|
||||
|
||||
return vec4(gmax, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
//!DESC Anime4K-v4.0-De-Ring-Compute-Statistics
|
||||
//!HOOK MAIN
|
||||
//!BIND HOOKED
|
||||
//!BIND STATSMAX
|
||||
//!SAVE STATSMAX
|
||||
//!COMPONENTS 1
|
||||
|
||||
#define KERNELSIZE 5 //Kernel size, must be an positive odd integer.
|
||||
#define KERNELHALFSIZE 2 //Half of the kernel size without remainder. Must be equal to trunc(KERNELSIZE/2).
|
||||
|
||||
vec4 hook() {
|
||||
|
||||
float gmax = 0.0;
|
||||
|
||||
for (int i=0; i<KERNELSIZE; i++) {
|
||||
float g = STATSMAX_texOff(vec2(0, i - KERNELHALFSIZE)).x;
|
||||
|
||||
gmax = max(g, gmax);
|
||||
}
|
||||
|
||||
return vec4(gmax, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
//!DESC Anime4K-v4.0-De-Ring-Clamp
|
||||
//!HOOK PREKERNEL
|
||||
//!BIND HOOKED
|
||||
//!BIND STATSMAX
|
||||
|
||||
float get_luma(vec4 rgba) {
|
||||
return dot(vec4(0.299, 0.587, 0.114, 0.0), rgba);
|
||||
}
|
||||
|
||||
vec4 hook() {
|
||||
|
||||
float current_luma = get_luma(HOOKED_tex(HOOKED_pos));
|
||||
float new_luma = min(current_luma, STATSMAX_tex(HOOKED_pos).x);
|
||||
|
||||
//This trick is only possible if the inverse Y->RGB matrix has 1 for every row... (which is the case for BT.709)
|
||||
//Otherwise we would need to convert RGB to YUV, modify Y then convert back to RGB.
|
||||
return HOOKED_tex(HOOKED_pos) - (current_luma - new_luma);
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.09991986, 0.13782342, -0.031251684, -0.06356843, -0.3437488, 0.05450952, 0.34347802, 0.46335372, 0.08607224, 0.044988394, 0.137179, 0.17976908, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.024212424, -0.09278509, -0.00040907756, 0.34552294, -0.13254678, 0.113105185, 0.005667946, -0.00036919137, -0.06375679, 0.009184115, 0.115518734, -0.115506776, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.14101827, 0.023523493, 0.044094566, -0.019271746, -0.44348842, -0.08818877, -0.4026149, -0.21995795, -0.15880394, -0.013732858, -0.020751135, 0.012719151, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.013001821, -0.34503505, 0.39219138, 0.18792126, 0.24760444, -0.016173402, 0.10154511, 0.15453082, -0.058132876, 0.016784398, -0.05808539, -0.11039915, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(0.37024534, 0.041440863, -0.3374568, -0.44994286, 0.19555596, 0.20855539, -0.27974075, -0.5372628, 0.21228147, -0.0295346, -0.56700057, 0.030042822, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.12940632, 0.057526, 0.090682045, -0.06985033, -0.13704006, -0.047685407, 0.44615674, -0.48056605, -0.06166251, -0.01883519, 0.2032237, -0.113287605, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.010856669, -0.35820737, 0.16757219, 0.082619876, -0.03967303, 0.038705572, 0.32652855, -0.012030017, 0.015120559, -0.15314877, 0.23442009, 0.09767922, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.046272673, -0.17752305, 0.082018286, -0.2512824, 0.58619463, -0.060903464, -0.022793597, 0.077803515, -0.17025311, 0.05136993, 0.029383298, -0.15475409, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.11212024, 0.13378005, -0.2027488, 0.08056421, -0.11176219, -0.048429377, -0.08396386, 0.10507829, 0.13326839, 0.0430627, 0.051362377, 0.06482755, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.061233472, 0.39222646, 0.029704979, 0.02586828);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.16410656, -0.40521824, 0.13121907, -0.02314597, 0.105412476, -0.060401272, -0.043063477, -0.13933973, 0.12558138, -0.020861467, 0.030370515, 0.13178016, -0.14220351, 0.20736893, 0.003321564, -0.29241714) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.18517321, 0.29162985, -0.26783395, 0.039760686, 0.025527012, -0.067319244, 0.055004176, 0.048916563, 0.12750523, -0.091435954, 0.13818842, 0.36704224, 0.0839921, 0.10186618, -0.17237376, 0.13282418) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.1657887, 0.0131325135, -0.17222486, 0.091398895, -0.12756164, -0.08437298, -0.29052997, 0.3269337, 0.15870757, -0.013529402, -0.0581753, 0.11802371, 0.07099966, -0.024063632, 0.31834844, -0.11183859) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.46036887, -0.07654623, 0.22923063, 0.17463821, 0.10555414, -0.117430426, 0.12406777, -0.011399492, 0.028316498, 0.13684341, 0.009664087, 0.2022659, 0.04953974, -0.31342217, -0.6103131, -0.13605757) * go_0(0.0, -1.0);
|
||||
result += mat4(0.03406955, -0.39819366, 0.61176, -0.46809456, -0.029321073, 0.46619493, 0.36700186, 0.02288561, 0.11464085, -0.10931452, -0.09154022, 0.07334147, -0.5609916, 0.31826234, -0.011012659, -0.46719545) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.056855045, 0.27037027, -0.09269696, -0.563572, -0.06816116, -0.22986612, 0.08693167, -0.16246101, 0.09954046, -0.05374176, 0.0071916827, -0.1788692, 0.3825241, -0.1609887, 0.055204768, 0.10213068) * go_0(0.0, 1.0);
|
||||
result += mat4(0.0646626, 0.102358796, -0.45055822, 0.20557903, -0.23337309, 0.12633002, -0.19299199, -0.15085731, -0.13473304, 0.053790465, -0.10061193, -0.13393497, -0.04264752, -0.029740738, -0.07865285, 0.20883279) * go_0(1.0, -1.0);
|
||||
result += mat4(0.010471527, -0.033218473, -0.46157447, 0.004866583, 0.23226471, -0.059343327, -0.1439596, 0.13619648, 0.013839963, 0.15930325, 0.043742355, 0.17467323, 0.33772305, 0.40261495, -0.08351293, 0.18129359) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.12493434, -0.1875134, -0.074943796, -0.0031701606, -0.037142616, 0.1667002, 0.16665547, -0.011248127, 0.0071619414, 0.0034872112, 0.120318964, -0.09625579, 0.14917047, -0.16310586, 0.07231737, 0.30447328) * go_0(1.0, 1.0);
|
||||
result += mat4(0.093798615, 0.17074613, -0.08780678, -0.012520207, 0.118534856, 0.027508778, -0.2778478, -0.19509242, -0.34137097, 0.32000312, -0.22027159, 0.337515, 0.16220862, 0.108993016, 0.14070526, 0.12784284) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.14325632, -0.1467453, -0.27502358, 0.09370837, 0.11821083, -0.012266484, -0.2100548, 0.4707502, -0.06766648, 0.58165014, -0.2512279, -0.33783755, 0.1318925, -0.04346277, 0.15454485, 0.044500057) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.05683207, 0.0051946463, -0.108000524, 0.10133204, -0.50763863, 0.007308442, 0.8542404, 0.28387356, 0.022709515, 0.294523, -0.3822472, 0.66166407, 0.01404485, 0.031282708, -0.26756814, -0.123147786) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.36455178, 0.3470555, -0.045303088, -0.03170764, -0.15802494, -0.0019141496, -0.25939587, -0.23875342, 0.130428, 0.03954273, -0.17985536, 0.105145946, 0.15804817, 0.12551713, 0.28371975, -0.085748516) * go_1(0.0, -1.0);
|
||||
result += mat4(0.0060625463, 0.2443924, -0.017692259, -0.20214005, -0.09584515, -0.012805372, -0.13942227, 0.16143198, 0.12942013, 0.41785547, 0.046071563, 0.7030026, 0.10499644, -0.20566013, -0.031321276, 0.27830327) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.081274964, -0.14562319, 0.27200526, -0.20491314, 0.012910989, 0.024201397, 0.04816258, 0.21297328, -0.22015952, -0.44160756, -0.056035373, 0.33824417, -0.31645304, 0.15469243, 0.053187452, -0.20989445) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.046550367, 0.033185404, 0.33337244, 0.12853645, 0.23520172, -0.05909214, 0.0861368, 0.10706329, -0.07058717, -0.11759937, -0.18594047, 0.080006264, -0.055425353, -0.12506317, 0.15729053, -0.0915004) * go_1(1.0, -1.0);
|
||||
result += mat4(0.042516407, 0.14844789, 0.16533111, 0.13502933, -0.0655417, -0.057256397, 0.076713726, -0.23448966, 0.12855926, 0.014219275, 0.051761385, 0.053433083, -0.2446715, -0.4008074, 0.19603717, -0.1796951) * go_1(1.0, 0.0);
|
||||
result += mat4(0.14777803, 0.15524907, 0.043158617, -0.06996876, 0.19210646, -0.2144364, -0.47020787, -0.4207906, -0.18074386, -0.2163903, 0.0030754965, 0.36799973, -0.3837698, -0.0022661497, -0.37276733, -0.28934997) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.018297346, -0.080951825, -0.062163066, -0.08050014);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.31543177, 0.23095237, -0.06692611, -0.5867763, 0.003622504, 0.17948842, -0.14627707, 0.1745016, -0.052964583, -0.15551159, 0.05644786, -0.012665164, 0.13107763, 0.11369179, -0.09452995, -0.11973403) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.2694661, -0.115382135, 0.3073268, -0.067228466, -0.25511482, -0.13922207, 0.36758214, -0.18821828, -0.022617863, 0.20333402, -0.11125889, 0.3552245, -0.013346653, -0.099095374, -0.25100616, 0.35521755) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.011012409, -0.13675085, 0.25642, -0.34851208, -0.23184675, 0.18012202, 0.57654136, 0.103173524, -0.16461405, 0.038177088, 0.1234096, 0.013202029, -0.19033363, 0.07469178, -0.017948546, 0.15287702) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.05340533, 0.23797482, 0.20351392, -0.05333351, -0.12181174, -0.23363493, -0.20696607, 0.109941036, -0.11519453, 0.13842066, -0.10687832, 0.29040006, 0.022218632, 0.031238724, 0.2685182, 0.15300068) * go_0(0.0, -1.0);
|
||||
result += mat4(0.22985318, -0.3103802, -0.22916415, 0.25238806, -0.11690287, -0.1947488, 0.118020535, 0.07814263, -0.06335474, -0.007870727, 0.076106325, 0.094677486, -0.16776285, -0.006570437, -0.29589584, 0.41413507) * go_0(0.0, 0.0);
|
||||
result += mat4(0.43607962, -0.36456433, -0.123776875, -0.16634953, -0.091190875, 0.13035081, 0.28627968, 0.27249968, 0.12356344, -0.008616177, 0.09599816, -0.006144557, -0.23490307, 0.3013123, 0.14153156, 0.21837278) * go_0(0.0, 1.0);
|
||||
result += mat4(0.060364585, 0.37860224, 0.039182413, -0.22805426, -0.089910224, -0.06817697, -0.2684275, -0.12528503, 0.036934495, -0.07826616, 0.06559976, -0.08253646, 0.13489649, 0.06237663, 0.126376, 0.21194184) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.12534817, 0.21225189, -0.27818045, -0.3070443, -0.006957577, -0.025105853, 0.12100924, -0.06916452, 0.23081483, 0.1802756, -0.18995638, 0.16603014, -0.2904096, -0.25292823, -0.21834068, 0.13719653) * go_0(1.0, 0.0);
|
||||
result += mat4(0.017209655, 0.10757137, 0.21414296, -0.30885983, 0.10467716, -0.2184891, 0.100061476, -0.1527528, 0.2100472, -0.25768545, -0.22329919, -0.29153427, -0.06983842, -0.103854865, -0.051384352, 0.14629121) * go_0(1.0, 1.0);
|
||||
result += mat4(0.0059623295, -0.26060802, 0.32115817, 0.021025505, 0.09783085, -0.15865178, 0.1473021, -0.24977303, -0.033508282, 0.17480391, -0.091310136, 0.09870876, 0.10504043, -0.06105686, 0.013493489, -0.11278855) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.14875248, -0.14859414, 0.19377062, -0.17456068, 0.101288855, -0.1113682, -0.48944646, 0.1018565, -0.037392337, 0.08539691, 0.1751306, -0.15428723, -0.059375558, 0.027663672, 0.051804014, -0.049813222) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.118846565, -0.19869871, -0.037388258, 0.08456728, -0.11662527, -0.43818352, -0.093285345, 0.038507205, -0.051991668, 0.21008292, 0.10792365, 0.2020924, 0.057021596, 0.09460527, 0.0016551288, -0.0015957063) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.11062174, -0.2639232, -0.060295466, -0.3217331, -0.050545212, 0.30989558, 0.30906132, 0.030323273, 0.028986752, 0.037429404, 0.20855664, -0.19848943, 0.034687653, -0.09599135, -0.06250494, -0.13215867) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.010391146, 0.07657845, 0.44491258, 0.0435906, 0.0075931503, 0.42632654, 0.47022533, 0.34737435, -0.15452717, -0.14613411, -0.45231065, 0.12094409, 0.0067911847, 0.057501152, 0.09876979, 0.044946447) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.15607435, 0.2293058, -0.09520331, 0.012836732, -0.15282455, 0.26437718, -0.1685477, -0.13211122, -0.055801593, -0.016778728, -0.34478986, -0.23228309, 0.12300962, -0.13235827, -0.13987203, -0.16550972) * go_1(0.0, 1.0);
|
||||
result += mat4(0.13161735, -0.09039346, -0.033475474, -0.23686698, 0.1514885, 0.20977421, 0.031431954, -0.0049226107, 0.090661936, 0.15288061, -0.03316583, 0.09646573, -0.32651708, 0.18825398, -0.15777239, 0.17572704) * go_1(1.0, -1.0);
|
||||
result += mat4(0.112157226, -0.08712878, 0.23453182, 0.1043877, -0.14686783, 0.28682423, -0.086443506, 0.059457052, -0.31530112, -0.2700583, -0.06028952, -0.070416875, 0.18053482, 0.16653341, 0.25215197, 0.061915852) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.20122242, 0.076313145, -0.0988483, 0.094337784, -0.35436687, 0.3762327, -0.07809558, 0.3055848, 0.10425242, -0.17087407, 0.030301496, -0.13911743, 0.01630275, 0.24247427, -0.006474477, 0.03842641) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.008952847, -0.0058945753, -0.08097229, 0.020968592);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.2237721, -0.0064096362, -0.31808427, 0.73477733, 0.015353088, 0.23983319, 0.14967978, -0.34920225, -0.07456269, 0.093151815, -0.14331086, -0.24586205, -0.14183366, 0.06401045, -0.22044073, 0.29932275) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.07968509, -0.3349146, 0.16529128, 0.08443499, 0.4095855, -0.17120704, 0.17425705, 0.15298946, 0.2981273, 0.2212369, 0.10392389, -0.28775454, -0.065247655, -0.15255849, 0.13094437, 0.18685219) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.015706737, -0.17755036, 0.2622526, 0.112057306, -0.15876788, -0.38466996, -0.33700845, -0.031711742, -0.023320962, -0.3145249, -0.21223734, -0.1314596, -0.1888095, -0.046370104, 0.09000896, -0.0046378844) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.31127506, 0.31304324, -0.03965752, 0.03649018, -0.029851055, 0.05801377, 0.00040150844, -0.04422069, 0.18019931, 0.14415511, -0.09845236, 0.21895434, -0.013932474, -0.046454947, -0.3403935, -0.006705289) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.34878647, -0.5129283, 0.060250953, -0.16354133, 0.20644619, 0.08732273, -0.24118888, 0.24455065, 0.24449423, 0.44103387, 0.22455928, 0.25738943, -0.26914698, -0.21309987, 0.08386486, 0.021484816) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.057454903, -0.4121922, 0.022661546, 0.37178272, 0.03331408, 0.05044008, 0.04324371, 0.20727943, 0.2432641, 0.076906696, -0.20858039, 0.012439015, -0.19335061, 0.09217451, 0.1968369, -0.19435833) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.16960496, 0.24616167, 0.37977478, 0.14324574, -0.011531225, -0.11312143, -0.18141079, -0.23843932, 0.0086012175, -0.3564491, -0.12639481, 0.009799298, -0.29120612, 0.23756824, 0.18035695, -0.087133996) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.10081239, 0.29191494, 0.10434693, 0.08970636, 0.008997759, 0.104756236, 0.039641086, 0.02323888, -0.11627765, 0.023693223, -0.30801758, -0.120208986, 0.05086147, 0.18498175, 0.15595439, -0.09877306) * go_0(1.0, 0.0);
|
||||
result += mat4(0.101321675, -0.2929976, 0.38810417, 0.5605376, -0.04073937, 0.030110704, -0.18147062, -0.09833952, 0.01927733, 0.15335669, -0.15384074, -0.110595055, -0.054297395, -0.077522054, 0.07918369, -0.068480626) * go_0(1.0, 1.0);
|
||||
result += mat4(0.23263514, -0.11719232, 0.2903209, -0.007503795, -0.020222448, -0.17790157, -0.15600762, -0.08741775, 0.12529704, 0.25548857, -0.04585447, -0.10255033, 0.18350503, -0.29593533, 0.0868933, 0.027004737) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.14958654, -0.006238835, -0.2928948, 0.1988557, -0.17057803, 0.12524141, 0.13978264, -0.019280292, 0.05967142, -0.07790818, -0.5893818, -0.022845713, -0.08596779, 0.07875358, -0.03316667, -0.4369282) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.19195688, -0.060883682, -0.25897828, 0.07063324, 0.090833396, 0.003422883, 0.109534174, 0.031180874, -0.05017118, 0.022862168, -0.270113, -0.057831235, 0.53920543, -0.10252776, -0.091807485, 0.004294343) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.18494242, -0.119284816, 0.3821897, 0.07777979, 0.15568028, -0.2854859, -0.22441281, -0.049155876, -0.15292497, 0.21895619, -0.095677756, 0.15210424, 0.001643022, -0.026176987, 0.048463076, -0.4824009) * go_1(0.0, -1.0);
|
||||
result += mat4(0.007215129, 0.17074333, 0.053930074, -0.027014816, -0.17180431, -0.15163863, -0.0012122132, -0.18934256, -0.08294297, -0.24580221, -0.46552867, -0.27923223, 0.4092668, 0.06288688, -0.1602188, -0.0030876845) * go_1(0.0, 0.0);
|
||||
result += mat4(0.111870885, 0.03317145, 0.14155298, 0.20328505, -0.05104131, 0.13979794, 0.018966835, -0.07238511, 0.05493792, -0.14975783, -0.10293237, -0.21985306, 0.49054706, 0.18288186, -0.26925826, 0.35845932) * go_1(0.0, 1.0);
|
||||
result += mat4(0.3747799, -0.096748486, -0.17139742, 0.25289854, -0.17421168, -0.018461818, 0.09747162, 0.01660535, -0.20580359, 0.56189656, 0.17151354, -0.26347768, 0.28350568, -0.21486014, -0.44330928, -0.008981037) * go_1(1.0, -1.0);
|
||||
result += mat4(0.10169985, -0.18244018, 0.04760736, 0.41017643, -0.09468786, -0.024218475, 0.103733875, -0.22540338, 0.10630112, 0.3677178, -0.104170956, 0.057317447, 0.21764882, 0.0789158, -0.22041337, 0.15065216) * go_1(1.0, 0.0);
|
||||
result += mat4(0.11633995, -0.008195114, -0.14501533, 0.07168025, 0.058413275, 0.055995367, 0.09362145, -0.13827963, 0.13760869, 0.040319785, 0.038895044, 0.2675253, -0.087339684, 0.1412073, -0.17166458, -0.2312994) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.059377354, -0.02055341, 0.07234869, -0.015452986);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.29012984, -0.13150147, 0.31015614, 0.05992291, -0.050289866, 0.14845313, -0.09608898, 0.27913308, 0.060307387, -0.04160452, 0.035932682, -0.08137563, -0.07999419, 0.11818284, -0.27512288, 0.21948813) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.12916058, -0.21759962, -0.33868533, 0.021636661, 0.053470243, 0.1412425, 0.043395396, -0.26751056, -0.01689101, -0.2623835, 0.010809152, 0.062962815, -0.20692012, -0.1677863, -0.23313859, -0.17402615) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.08204112, -0.23672083, -0.0064437394, -0.13200696, -0.056692924, -0.02708657, 0.12536962, 0.004428919, 0.14137582, 0.15404348, -0.105753876, 0.047957454, 0.15734316, 0.16562423, -0.010160829, -0.06602983) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.025653997, -0.10877775, -0.31258908, 0.18841636, -0.36005193, 0.1816357, -0.34537643, -0.0741087, 0.4663994, 0.0065186517, 0.08109033, 0.2976773, -0.35774228, -0.041366056, -0.37852773, 0.050565656) * go_0(0.0, -1.0);
|
||||
result += mat4(0.04392313, 0.11316681, -0.14421389, 0.17985669, -0.1651274, -0.5656209, -0.124100484, 0.42774054, -0.1153939, 0.16829851, 0.2025612, 0.054007456, -0.06868256, -0.56935954, -0.12227961, 0.17688861) * go_0(0.0, 0.0);
|
||||
result += mat4(0.34041, 0.499, 0.15234196, 0.21353458, -0.2732667, -0.049950935, 0.03550811, -0.21051687, 0.2609023, 0.016438454, -0.29874632, 0.37994128, 0.049288407, -0.31126305, 0.029235512, -0.012256015) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.0046853204, 0.15391374, -0.040689662, 0.20186873, -0.08137621, 0.35905558, 0.23733845, 0.21794793, -0.066420384, 0.029600656, -0.31421044, -0.050773863, -0.06260773, 0.04634221, -0.10948491, -0.045498934) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.082953, -0.025837064, -0.09928303, -0.14300232, 0.275064, 0.07793617, 0.22240888, 0.06637834, -0.4382666, -0.2932182, -0.27243167, -0.14221182, 0.5695728, 0.20719238, 0.5575927, 0.40816882) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.18510929, -0.15052167, 0.25277212, 0.06804461, 0.016387, 0.20310035, 0.2903229, -0.0615877, -0.28987274, -0.11942605, 0.013498961, 0.3184152, 0.29543474, -0.042830903, -0.018111207, -0.13263674) * go_0(1.0, 1.0);
|
||||
result += mat4(0.25749087, 0.0053866603, -0.09391162, -0.06129529, -0.094091184, -0.07419633, 0.0013858611, 0.012000353, -0.062903, -0.0204224, -0.12113313, 0.017942557, -0.073379934, 0.052201986, 0.35864577, 0.023564404) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.100115694, 0.19451359, 0.23252094, 0.19506809, -0.12470779, 0.0027281935, -0.17488572, -0.018721964, -0.15159339, 0.18457152, 0.057712987, -0.08191495, 0.19735703, 0.07326743, -0.28563106, 0.01642815) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.068062514, 0.28356665, 0.07377898, 0.42776972, 0.28725025, -0.13045293, -0.17525704, -0.05885591, -0.16676305, -0.2555945, -0.10078422, -0.053032875, 0.084470876, 0.06460686, 0.13824362, -0.05231353) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.22637829, -0.028969254, 0.1968254, -0.13331996, 0.038017053, -0.008854481, -0.2031639, 0.09237089, -0.3821112, 0.1108527, -0.11029933, -0.24542028, 0.22416145, -0.031492114, -0.19144306, -0.0996271) * go_1(0.0, -1.0);
|
||||
result += mat4(0.10776744, 0.16363445, 0.14656505, -0.3737814, -0.06642015, 0.5616549, -0.008412252, -0.37266847, 0.12506576, -0.15329036, 0.037538245, -0.10810259, 0.01706349, 0.1813702, 0.035651788, -0.012786579) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.4023338, -0.2098614, -0.18285121, -0.02727653, 0.26107362, 0.041306913, -0.036515504, -0.045217298, -0.39958602, -0.21229339, -0.021053292, -0.13427502, 0.36178818, 0.20934913, 0.1500852, 0.2634554) * go_1(0.0, 1.0);
|
||||
result += mat4(0.07794611, -0.25937587, -0.06822529, -0.056336135, 0.094220124, 0.21588847, -0.0455218, -0.10968329, -0.08068449, -0.31366697, 0.07799637, 0.24252681, 0.23963861, 0.13715535, 0.010329345, 0.09094301) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.20975718, -0.12550138, 0.14453574, -0.0020878632, -0.07153068, 0.3249998, -0.056577377, 0.18166828, 0.37204072, 0.17018336, 0.3752895, 0.32178587, 0.2571982, -0.27258632, -0.25971004, -0.40536007) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.3243907, -0.06300621, -0.09398436, -0.19549188, 0.14906861, 0.061537784, -0.055284478, 0.11281728, 0.12964857, 0.09979093, -0.1810159, -0.4104283, 0.05807971, -0.056371246, 0.08072554, 0.18479007) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.048888464, -0.0561434, 0.030690912, -0.030496685);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.15332128, 0.027258258, 0.14900503, -0.15982795, 0.17021236, -0.51046044, -0.15287271, -0.058167327, 0.51826185, -0.34817994, 0.004513167, 0.05395769, 0.1990321, -0.049979225, 0.11391989, -0.16062729) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.033682905, 0.019728886, 0.19931756, 0.17381927, 0.2585768, -0.2124572, -0.014632459, 0.39779893, -0.1146207, -0.2396625, 0.08960277, 0.38345298, 0.25497693, 0.11692859, -0.14207517, 0.12667973) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.14911255, 0.08910706, 0.16136818, 0.03914566, 0.24204038, -0.03607149, -0.4571109, 0.10802461, -0.0021356856, 0.00885878, 0.22297303, 0.2367231, 0.045177583, 0.11120606, -0.009971904, -0.059262395) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.24565999, -0.2261384, 0.47373205, 0.024613412, -0.10923052, 0.039027315, -0.42707404, -0.3783373, 0.3544573, -0.5468578, -0.27599156, -0.09455918, 0.18760219, -0.19082001, 0.030565469, 0.20589156) * go_0(0.0, -1.0);
|
||||
result += mat4(0.1973198, -0.03433863, 0.059960485, 0.045642868, 0.1819595, -0.14460869, 0.1286175, 0.2067575, -0.042632047, -0.11842967, -0.11224446, -0.18764776, -0.19563004, 0.027425969, 0.24056377, 0.5949649) * go_0(0.0, 0.0);
|
||||
result += mat4(0.055027682, 0.16331595, -0.2608588, 0.12545955, 0.4588985, 0.03642909, 0.22187738, 0.45190734, -0.001210133, -0.057651415, -0.061199043, 0.11935476, -0.049561135, 0.27509886, 0.13778673, -0.124914035) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.02257459, 0.27705106, 0.044165276, -0.26521233, 0.05982374, -0.2824302, 0.3171142, 0.08430561, -0.10155528, 0.16182268, -0.09183147, -0.19447176, 0.3295707, -0.50616395, -0.036964044, 0.23166709) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.0232342, 0.07299799, -0.18038079, -0.13672702, -0.108305976, 0.15024792, -0.19531927, 0.0870979, -0.26488534, 0.19481428, 0.10737945, -0.14573483, -0.33094683, 0.24155116, -0.09850332, 0.2797003) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.24089853, 0.19506595, 0.4799156, -0.058313113, 0.36212957, -0.44844806, 0.23864488, 0.15477742, -0.07795971, -0.0033861927, -0.11216164, 0.033454563, -0.25893036, 0.23793478, -0.15769425, -0.00033481256) * go_0(1.0, 1.0);
|
||||
result += mat4(0.05772507, -0.1640253, -0.13499664, -0.20460358, -0.024399966, 0.14966168, -0.090857334, -0.039677754, 0.00036956606, -0.24236615, -0.053542696, -0.0049544116, 0.026651502, 0.39019194, -0.2742246, -0.061242323) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.016323274, -0.036179908, 0.029965919, 0.11151491, -0.00016685206, -0.29573023, 0.17996423, -0.20145437, 0.1324275, -0.18442132, -0.24618152, 0.061780427, -0.02770517, 0.28452995, 0.39804098, -0.1174389) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.025068847, -0.053328387, -0.27053785, 0.26866457, -0.09866204, 0.057677213, 0.01850112, -0.18014707, -0.13319959, -0.14411181, -0.26355243, -0.022209354, -0.05062645, -0.036771543, 0.13294417, -0.18458557) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.046194963, 0.038230438, -0.08993043, -0.07236354, 0.11031123, -0.16504908, -0.09517036, -0.16459833, -0.5279925, 0.12686682, -0.05726125, 0.055361677, 0.31593755, 0.027328093, 0.001839602, 0.30581662) * go_1(0.0, -1.0);
|
||||
result += mat4(0.08608678, 0.03168437, 0.007713377, -0.26140293, -0.1268983, 0.13395861, -0.069848835, -0.24080403, 0.018839337, -0.049821075, -0.21461345, -0.14168301, -0.0872339, 0.47096667, 0.022512507, 0.14860632) * go_1(0.0, 0.0);
|
||||
result += mat4(0.06293673, 0.22462969, 0.045494985, 0.021673543, 0.18227446, -0.2956555, 0.08010543, -0.01919729, -0.012190269, 0.241983, -0.046537094, -0.40094566, -0.3853647, 0.1081711, -0.16926058, 0.16138376) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.14854589, -0.17625804, -0.10849075, 0.221543, 0.099971965, 0.13901573, 0.29464146, 0.020068526, 0.054358527, -0.10351705, -0.0062914286, 0.24127026, -0.16914125, 0.12729423, -0.18377453, -0.6452375) * go_1(1.0, -1.0);
|
||||
result += mat4(0.12603393, -0.10986093, 0.2314103, 0.16915044, -0.13619255, -0.09349073, 0.20594226, -0.34507084, 0.19077192, 0.052500796, 0.07185645, 0.029082738, -0.015576321, 0.08254907, -0.5501743, -0.38495848) * go_1(1.0, 0.0);
|
||||
result += mat4(0.09300796, -0.079218306, 0.46825135, -0.08735625, 0.06321122, 0.16234867, 0.042932414, -0.013057422, 0.09697148, 0.23457524, 0.19417483, -0.16804664, 0.18379296, 0.17770062, -0.050235, -0.059676602) * go_1(1.0, 1.0);
|
||||
result += vec4(0.011169491, 0.032399546, 0.138099, 0.023857072);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.22753362, -0.08612073, 0.33140692, 0.08699529, -0.18788953, -0.056579117, -0.12905197, -0.06694621, 0.054559365, 0.15031597, -0.13430363, 0.021646025, 0.14884405, -0.0694291, 0.26149413, 0.11270503) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.17876762, -0.09637848, 0.11285323, 0.2004893, 0.1317187, -0.036162686, 0.17958368, -0.069625, 0.28760737, -0.12505141, 0.12760694, 0.047717955, -0.16811855, -0.16340709, 0.13278298, -0.08403954) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.21917523, 0.079711854, -0.28642535, 0.2822416, 0.03001489, -0.014772918, -0.3487396, 0.10597145, -0.013841082, 0.17034237, 0.10810282, -0.08089695, -0.22184245, -0.59067357, 0.44113398, 0.13045649) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.29906932, 0.013923749, 0.2031124, -0.11846688, -0.13953634, 0.08003455, -0.10164494, -0.21218559, 0.10563715, 0.31033117, -0.075903505, 0.047310907, -0.37824214, -0.14506383, 0.11866701, -0.21384487) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.1353849, 0.19258606, 0.063908584, -0.2043788, 0.27244982, 0.1665306, -0.29357895, -0.22441709, 0.18514316, -0.17840464, 0.20986097, 0.14351055, -0.057732623, 0.42166704, -0.23182064, -0.4957248) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.34830126, 0.109066755, -0.28285867, -0.048280068, -0.12290918, 0.04291651, -0.047484186, -0.03702595, 0.23047262, 0.09398974, 0.022467108, 0.08271034, 0.3066665, -0.54077, 0.057771873, 0.23194093) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.17731948, -0.3175927, 0.1452728, 0.09396786, -0.16433562, -0.01833653, -0.22345604, -0.04161193, -0.14827462, 0.18544114, -0.15544125, -0.06179007, 0.16989979, -0.20985202, 0.16391534, -0.09447268) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.053878862, -0.21034616, 0.023831524, 0.19772215, 0.31647214, 0.0126534775, -0.19130844, -0.049282108, -0.21446131, 0.067189045, 0.09117449, -0.25548774, 0.12109098, 0.22009392, -0.3924665, -0.13340388) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.16096684, -0.18495405, 0.10410178, 0.0015673033, -0.00183498, -0.044303037, -0.062745355, -0.090802394, 0.043269135, 0.06924481, -0.21367405, -0.14619029, 0.11555763, -0.20292862, 0.5799557, 0.14739846) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.21030277, -0.09578802, 0.013482288, -0.21484336, 0.12995781, 0.40431052, -0.3347856, -0.18183486, 0.15550353, -0.04402301, 0.4603779, 0.14874357, -0.07694621, -0.053523075, -0.19607326, -0.10850742) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.2347211, 0.2697403, -0.0634794, -0.17925987, 0.17231455, 0.24999185, -0.5208536, -0.10491828, -0.233575, 0.52950364, 0.0038063182, -0.1380038, 0.022935199, 0.19369157, 0.14586553, 0.1938704) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.10245223, 0.34150192, 0.25862157, -0.20165509, 0.5597771, 0.114510864, -0.122526556, -0.04010975, 0.1704679, -0.23335956, -0.16771887, -0.03783455, -0.056995615, 0.24153493, -0.08082429, -0.24210933) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.103466526, 0.15278348, -0.30526164, -0.080755696, 0.103505425, 0.15862796, 0.14696524, -0.008358076, -0.09180311, -0.12505089, 0.28052542, -0.13551563, 0.07528779, -0.09636086, -0.10369617, 0.23656134) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.25752836, 0.099439755, -0.30716348, 0.035077725, 0.023509016, 0.23106368, 0.05277125, 0.34910464, 0.088015385, 0.26995596, 0.1390645, -0.40671825, 0.18096298, -0.100688554, 0.5492049, 0.2482101) * go_1(0.0, 0.0);
|
||||
result += mat4(0.41411775, -0.107200556, -0.13813478, 0.13768874, 0.27137747, 0.06313619, -0.08522967, 0.03218302, -0.03166121, -0.3415683, -0.52242, -0.1741813, -0.36956537, 0.179129, -0.09742935, -0.11696616) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.07975504, 0.17964838, 0.37122533, 0.16064765, 0.14309953, 0.29473078, 0.0926391, -0.22333665, 0.34612748, -0.3387473, 0.0077308523, -0.07239449, 0.18522519, -0.21297298, 0.11493978, 0.16117814) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.17402779, 0.10023144, 0.11712206, 0.031971734, 0.18713303, 0.08736295, 0.013007052, -0.06943139, -0.20102951, -0.010721135, -0.2562522, 0.34877458, -0.13732676, -0.40258047, 0.25824392, 0.15720639) * go_1(1.0, 0.0);
|
||||
result += mat4(0.044494305, 0.3296108, 0.0017603852, 0.09362289, 0.38839245, 0.40015858, -0.13395199, -0.044521853, -0.56266373, 0.251378, 0.5005789, -0.13106057, -0.18491416, -0.046887, 0.067797676, -0.14694957) * go_1(1.0, 1.0);
|
||||
result += vec4(0.013687534, -0.08185164, -0.04755438, 0.290178);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(M)-Conv-3x1x1x56
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_6_tf
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_2 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_5 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_6 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_9 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_10 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_13 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.08837163, -0.065234736, -0.034704313, 0.0, 0.021405501, 0.013663729, 0.019249594, 0.0, 0.05328863, 0.03580334, 0.046457592, 0.0, -0.12216048, 0.022547891, 0.016400825, 0.0) * g_0;
|
||||
result += mat4(0.061996464, 0.05631466, 0.06808407, 0.0, -0.005013109, -0.0044589997, -0.032367796, 0.0, 0.016481603, 0.13721058, 0.14924648, 0.0, 0.020035887, -0.07250003, -0.08034037, 0.0) * g_1;
|
||||
result += mat4(0.24078514, 0.081361525, 0.053420708, 0.0, -0.009353794, -0.051077116, -0.058007747, 0.0, -0.14071098, 0.01035966, 0.005308949, 0.0, -0.1489842, -0.06711817, -0.05552926, 0.0) * g_2;
|
||||
result += mat4(-0.13002375, 0.012733757, 0.017821986, 0.0, 0.17767483, 0.20204604, 0.1751779, 0.0, 0.12804912, 0.07381453, 0.05655911, 0.0, 0.17044514, 0.07301451, 0.06523978, 0.0) * g_3;
|
||||
result += mat4(-0.1170986, -0.05130371, -0.027939914, 0.0, -0.16645707, -0.121526904, -0.09471366, 0.0, -0.04143118, 0.026693767, 0.034615446, 0.0, -0.084318705, -0.064990036, -0.054324172, 0.0) * g_4;
|
||||
result += mat4(0.12094524, 0.09518409, 0.07387219, 0.0, 0.062216382, 0.053228356, 0.031372335, 0.0, 0.072797105, 0.026258165, 0.009804673, 0.0, 0.120719045, 0.073281154, 0.056623302, 0.0) * g_5;
|
||||
result += mat4(-0.11141495, -0.11566289, -0.10398725, 0.0, -0.0651895, -0.06820691, -0.054204144, 0.0, -0.032746475, -0.008849683, -0.007610222, 0.0, -0.024655705, -0.048778858, -0.041144755, 0.0) * g_6;
|
||||
result += mat4(0.058090195, 0.07538767, 0.059722915, 0.0, 0.044788487, 0.04212742, 0.027502589, 0.0, 0.04892866, 0.015416752, 0.008312418, 0.0, -0.011864114, -0.0074752793, -0.0060824654, 0.0) * g_7;
|
||||
result += mat4(0.043446552, 0.061971307, 0.05758086, 0.0, -0.06379154, -0.053758245, -0.047204215, 0.0, 0.016307736, 0.03423424, 0.030179083, 0.0, 0.041445345, 0.03843772, 0.033059113, 0.0) * g_8;
|
||||
result += mat4(-0.003803544, 0.0008906116, -0.00059585314, 0.0, 0.102071285, 0.11485224, 0.10007254, 0.0, -0.074306004, -0.08803551, -0.07972321, 0.0, -0.030704215, -0.021514274, -0.009049376, 0.0) * g_9;
|
||||
result += mat4(0.0066058086, 0.0011408008, 0.0016199006, 0.0, -0.03916473, -0.042929266, -0.04018418, 0.0, -0.03153446, -0.039413508, -0.034767237, 0.0, 0.113516055, 0.12577052, 0.113335624, 0.0) * g_10;
|
||||
result += mat4(0.02655948, 0.041905303, 0.03861737, 0.0, 0.048471425, 0.049788587, 0.050447535, 0.0, 0.12092813, 0.13564217, 0.12613249, 0.0, -0.0023508538, 0.0012828974, 0.0028730957, 0.0) * g_11;
|
||||
result += mat4(0.0084758485, 0.008800083, 0.008206044, 0.0, -0.056123603, -0.06610845, -0.060320783, 0.0, -0.081793964, -0.101638645, -0.096699014, 0.0, -0.04402356, -0.04177539, -0.03829645, 0.0) * g_12;
|
||||
result += mat4(0.10676299, 0.118409514, 0.10618478, 0.0, -0.05880252, -0.06488367, -0.06432695, 0.0, 0.019221924, 0.017602798, 0.017413978, 0.0, -0.07512528, -0.080483615, -0.066218294, 0.0) * g_13;
|
||||
result += vec4(-0.010478934, -0.008364784, -0.010246552, 0.0);
|
||||
return result + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(S)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.19288683, -0.21397883, 0.111997396, -0.04791413, -0.26682988, -0.06144587, -0.03601853, -0.16693151, 0.038494494, -0.16651472, 0.147657, -0.083003886, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.14286195, 0.08746566, -0.40107322, 0.12390977, -0.33392772, -0.18703035, -0.21326795, 0.04780781, -0.15155545, -0.0010025925, -0.1554875, -0.10676251, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.28095165, 0.022872915, -0.21342312, -0.29982176, 0.025937587, -0.055012174, -0.33779636, 0.0015666655, 0.076416336, 0.06656033, -0.1557806, 0.1078894, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.31584853, 0.07527119, 0.30713862, -0.34014285, -0.50103146, -0.07217874, 0.512807, -0.09597398, -0.32097813, -0.051580857, -0.022466356, 0.01148551, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.026032459, -0.04193211, 0.37703893, -0.031916667, -0.27421117, 1.0906446, -0.049654085, -0.19814016, 0.07819544, 0.06003738, 0.1405805, -0.0064135445, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.041450135, 0.11319654, -0.23237701, 0.08443178, 0.53344345, 0.30857387, -0.057264958, -0.1575803, 0.2325609, -0.027797326, -0.04544767, -0.18720597, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.2531829, -0.074966915, -0.27800754, -0.3146097, 0.20126024, -0.5380133, -0.15082566, -0.19021043, 0.29951036, 0.17123336, -0.01681872, -0.12574998, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.25203633, 0.19882993, 0.14906439, 0.13593598, 0.40712556, 0.084902965, 0.42969635, 0.2961132, -0.057267334, -0.030388135, 8.8084314e-05, 0.0210724, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.13459359, -0.12199573, 0.12591946, 0.24736497, 0.2033463, -0.09388599, -0.094370656, 0.1071285, -0.18479438, -0.066625565, 0.08279283, 0.20130983, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.011108127, -0.07481861, 0.07640154, 0.4964964);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(S)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.056432575, 0.0028165397, -0.026325442, -0.14802271, 0.16885762, -0.062179096, -0.2332292, 0.17513658, -0.08011296, 0.02947316, 0.014771492, -0.17946689, 0.026012989, -0.09823925, 0.036625937, -0.06924322) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.13571467, 0.09831142, 0.12911566, 0.06305893, -0.07188695, -0.20161287, 0.3858435, -0.21069056, -0.12294444, -0.1404628, -0.022659872, 0.23008968, 0.10969853, 0.17640765, 0.39796907, 0.20413099) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.0061665224, 0.055102807, -0.0059629944, -0.021429887, 0.061626043, 0.16898955, -0.21215646, 0.16510476, 0.2238265, 0.19429931, 0.09874656, 0.06828208, -0.122404456, -0.00026717107, -0.28203064, -0.29979932) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.22735378, 0.14538136, 0.11549746, 0.194148, -0.09841722, -0.0661309, 0.348576, -0.017375294, -0.044078812, 0.1298332, 0.04793373, -0.30687734, 0.08353025, 0.083519086, 0.10766399, 0.31796935) * go_0(0.0, -1.0);
|
||||
result += mat4(0.048365135, -0.17566709, -0.33212858, -0.052667376, -0.26443407, -0.010216014, 0.1573303, 0.05725314, 0.08140953, -0.09664591, 0.076109104, -0.026773714, 0.07732627, 0.10188082, -0.28266954, -0.16230233) * go_0(0.0, 0.0);
|
||||
result += mat4(0.29931107, 0.117944, -0.10414009, 0.12795551, 0.12576093, 0.17082554, -0.15803693, 0.13430743, -0.025801308, -0.10797019, 0.0721032, 0.2825884, -0.11025257, 0.12798019, 0.081827976, -0.050441865) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.11827391, 0.08306765, -0.3430314, 0.07898041, -0.023839617, -0.019507334, 0.23176382, -0.40992323, 0.09411734, 0.38415068, -0.25845516, -0.29984522, 0.1470966, -0.0684779, -0.07071314, -0.026773235) * go_0(1.0, -1.0);
|
||||
result += mat4(0.19091596, 0.082110435, -0.5266589, -0.1744098, -0.015838385, -0.046316292, 0.023171103, -0.03731331, 0.2642396, 0.31824252, -0.041754793, -0.09525519, -0.14696182, 0.052168854, 0.039857205, -0.027555354) * go_0(1.0, 0.0);
|
||||
result += mat4(0.15207373, 0.09845733, 0.0142631065, 0.096375965, 0.06089903, 0.17902578, -0.42391995, 0.22475442, 0.016356342, -0.06277531, -0.12173141, -0.18635495, -0.0013459618, 0.15725887, 0.019310836, 0.20293565) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.18395247, 0.30672902, 0.09034339, 0.1821889, -0.0419004, -0.2169228, -0.14052129, 0.11006559, 0.1709272, 0.51062274, 0.13758625, -0.2242552, -0.030382963, 0.3357568, -0.26491287, 0.02501938) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.040511727, 0.12523083, -0.27318433, 0.08388512, 0.25354835, 0.3404216, -0.2632471, -0.17784123, 0.2732347, 0.4468553, 0.084667034, -0.1856242, 0.034099877, -0.00954992, -0.32751867, -0.062207516) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.17564747, 0.11645554, -0.16362113, 0.105654195, -0.2762563, -0.1413764, 0.23264363, -0.14000498, 0.095402054, 0.0715738, -0.19346157, -0.028285999, 0.009799127, 0.04059529, 0.19688335, 0.1282381) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.23575781, -0.11446148, -0.20504695, 0.035568226, 0.36890212, -0.85968876, -0.18545328, 0.33796397, -0.30916876, -0.10445518, -0.3046253, 0.33271998, -0.06263589, -0.2160114, -0.16383372, -0.31173357) * go_1(0.0, -1.0);
|
||||
result += mat4(0.20469664, 0.4039374, -0.070057206, 0.030353077, 0.39843914, -0.15490077, -0.24476516, 0.38238233, -0.21809858, 0.23496576, -0.051794037, 0.033664484, -0.14411364, -0.2515329, 0.124655396, -0.05818785) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.09065731, -0.16787091, 0.013269188, 0.23687351, -0.41504318, -0.048163068, 0.31760025, -0.33648986, 0.29752317, 0.2926866, 0.14408836, -0.33382463, -0.15873958, -0.121961035, 0.11797893, 0.09000567) * go_1(0.0, 1.0);
|
||||
result += mat4(0.13356976, 0.013763947, 0.012169505, -0.109594524, 0.03417223, 0.7031121, 0.65146804, 0.5250268, -0.50132495, -0.419648, 0.2940041, 0.83051753, -0.17595838, 0.1633008, -0.018587278, 0.079596795) * go_1(1.0, -1.0);
|
||||
result += mat4(0.07570128, -0.1581438, 0.03904949, 0.14890033, -0.054611947, 0.17469402, -0.44252598, 0.036181703, -0.4981031, -0.37507218, -0.18466389, 0.2645845, 0.25189674, -0.025896115, 0.034307647, -0.020462232) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.11645865, 0.02296537, 0.040909223, 0.015069485, 0.062284566, -0.22526766, 0.09241534, -0.32623053, 0.18208642, 0.3954284, 0.2884468, -0.25137675, -0.037232924, -0.10185309, -0.17956531, 0.018966453) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.16371979, -0.024620198, -0.035754893, 0.04176776);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(S)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.01921286, -0.26684764, -0.12663573, 0.31641877, -0.25313398, 0.12264074, 0.58750325, -0.14084283, 0.5837018, -0.042300556, -0.20435576, -0.009954825, 0.060783498, 0.05540401, 0.2205112, -0.06578902) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.21930243, -0.03774968, 0.22615197, 0.18338196, 0.011201461, -0.271034, 0.00573116, -0.12248194, 0.47990513, 0.2982416, -0.1087603, -0.050099242, -0.07620939, -0.07148229, 0.03691984, -0.16796488) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.14962853, -0.053769328, 0.02387081, 0.22002189, 0.052237745, -0.26160842, -0.08603077, 0.012542448, 0.08119985, 0.075785555, -0.33437458, -0.43373227, -0.13206963, -0.08759176, -0.03288923, -0.09799959) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.1305593, -0.5974288, 0.06058367, 0.08406488, 0.013692483, 0.06646377, 0.16469325, 0.08990975, 0.42217395, -0.11289523, -0.06165009, 0.48556912, -0.15702641, -0.19922857, -0.0035429662, -0.0022089656) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.1964807, 0.038099788, 0.21587034, 0.039734077, -0.07063389, 0.11604167, -0.24558097, -0.08900199, -0.7684516, -0.1037487, -0.09380674, 0.33144563, -0.16653742, 0.0028585843, -0.33774406, -0.0528696) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.27298656, -0.05665099, 0.09661685, 0.19780266, 0.1025106, -0.22055034, -0.21218458, -0.040628925, 0.0095010325, 0.13118382, -0.42582452, -0.22197723, 0.21006055, -0.06189587, -0.15285942, -0.09526762) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.14494462, -0.046788953, 0.065877035, 0.09911713, 0.35096622, 0.16682479, 0.028363144, 0.36037162, 0.29413632, 0.28212717, -0.025364442, -0.3406269, 0.047262143, -0.11892685, -0.008032766, 0.29743317) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.15191558, -0.36980554, 0.14555687, 0.0043930537, -0.012661432, 0.15737776, -0.115250416, 0.10324491, 0.24491951, -0.15575431, -0.27802598, 0.21959937, 0.18063772, 0.4455559, -0.09693302, 0.33382267) * go_0(1.0, 0.0);
|
||||
result += mat4(0.2717801, 0.13452889, 0.14105384, 0.16324317, -0.40111846, 0.1154301, -0.0076733204, -0.09697362, 0.44306824, -0.02831414, -0.2153124, -0.12075326, 0.060776163, 0.30347148, -0.0036976219, -0.12070682) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.39780128, -0.29875937, -0.12952097, 0.080333896, 0.07520163, 0.021689568, -0.23121156, -0.038140096, -0.1593877, 0.017156163, -0.06038025, 0.009244022, -0.13917233, 0.30957314, 0.243109, -0.104947075) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.07965157, 0.06776501, -0.13288979, 0.005851189, -0.08768168, -0.03689969, 0.12034646, 0.22441491, 0.14453568, -0.17648841, -0.3378289, -0.018329712, 0.11722939, -0.34161824, 0.08424494, -0.01400687) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.08153887, 0.07222914, -0.14663404, -0.038526025, -0.07385973, 0.18440577, 0.35890242, 0.17084727, 0.26345527, 0.15280858, -0.007446105, -0.024403179, -0.30336383, -0.22978698, 0.11612946, -0.23614909) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.07447396, 0.09023449, -0.13798, -0.086943336, -0.30787337, 0.15087669, 0.14418626, -0.03371195, 0.048989657, -0.13075387, -0.13458036, -0.059836224, 0.06495196, 0.269715, 0.3674355, 0.38956037) * go_1(0.0, -1.0);
|
||||
result += mat4(0.34981915, -0.048779126, 0.31717536, 0.38080826, -0.20149232, -0.82969636, -0.10167862, 0.6382858, 0.25976858, 0.4370118, -0.04724865, -0.10014156, 0.19380626, -0.080370255, 0.09578106, -0.035166856) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.026443917, 0.4132611, 0.01822534, 0.12742202, -0.26652107, -0.2996705, 0.30905882, 0.07989903, 0.38249823, 0.21486135, 0.025314959, -0.14717339, -0.13344015, -0.32088286, -0.2833883, -0.30973712) * go_1(0.0, 1.0);
|
||||
result += mat4(0.021517841, 0.006556378, 0.2025686, -0.12044382, -0.38583103, -0.0027515136, -0.06556736, -0.097090125, 0.04676486, -0.11954886, -0.051612873, 0.07831412, -0.18823163, -0.16542958, 0.04245155, 0.6437998) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.39475346, -0.2936861, 0.26768062, -0.28151843, 0.21935691, 0.2101108, -0.15455097, 0.19548604, 0.09188909, -0.020147726, 0.103328265, -0.12574542, -0.34167948, 0.07523185, -0.17669058, 0.62446547) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.37661025, -0.29630858, 0.05451026, 0.1611643, 0.14079669, -0.2170294, -0.038716137, 0.13514164, -0.21235192, -0.07860726, -0.005749412, 0.025625167, -0.13297133, 0.33012658, -0.27434957, -0.18416783) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.0036821906, -0.050239526, -0.01355402, 0.00048220603);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(S)-Conv-3x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.15873, 0.17989138, 0.14648493, 0.0, -0.017379675, -0.017363746, -0.019855022, 0.0, 0.009670625, 0.0070157526, 0.0075994316, 0.0, 0.025388412, 0.027231036, 0.024052646, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.048195973, 0.041760173, 0.037366055, 0.0, -0.115950756, -0.12887983, -0.12535639, 0.0, 0.032125086, 0.03397254, 0.032950625, 0.0, 0.01223746, 0.020822672, 0.0161561, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.0890567, 0.094453335, 0.09014035, 0.0, 0.016081346, 0.017434116, 0.020783134, 0.0, -0.011775135, -0.010094134, -0.018522855, 0.0, 0.072103254, 0.07940666, 0.065876864, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.04841196, -0.06963968, -0.056574684, 0.0, 0.10912542, 0.11813441, 0.10643838, 0.0, -0.013013885, -0.01562045, -0.013802797, 0.0, 0.037505716, 0.04352026, 0.04645123, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.3472869, -0.36243078, -0.33530185, 0.0, 0.23654196, 0.2305048, 0.22150646, 0.0, -0.045226905, -0.041799217, -0.042511635, 0.0, -0.10267792, -0.1123385, -0.10845448, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.011987401, 0.012285043, 0.007813165, 0.0, -0.15911353, -0.17523928, -0.1535267, 0.0, 0.15675929, 0.16531634, 0.15948962, 0.0, -0.09240023, -0.09513292, -0.084187366, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.069052905, 0.07278333, 0.0756627, 0.0, -0.012180326, -0.018794727, -0.031050753, 0.0, -0.044663202, -0.04362803, -0.038904265, 0.0, -0.008540197, -0.011201734, -0.01556625, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.08261173, -0.09042543, -0.07589266, 0.0, 0.043515377, 0.045066774, 0.04037769, 0.0, -0.06262993, -0.07469342, -0.058593787, 0.0, 0.026696987, 0.028740842, 0.037405368, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(0.07975598, 0.09597654, 0.08997132, 0.0, -0.07844719, -0.07880916, -0.06835411, 0.0, 0.05668995, 0.050163813, 0.053357534, 0.0, -0.020040333, -0.019867316, -0.01907621, 0.0) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.017078733, -0.017393313, -0.008266595, 0.0, -0.0033478448, -0.0027439648, -0.0042334674, 0.0, -0.06354017, -0.062058125, -0.04652064, 0.0, -0.010787706, -0.0062706997, -0.007573461, 0.0) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.019895451, -0.016341688, -0.008712399, 0.0, 0.026231976, 0.023955572, 0.0216376, 0.0, -0.061950512, -0.05481285, -0.05261985, 0.0, -0.018804235, -0.016235247, -0.0131616965, 0.0) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.055628926, -0.063315354, -0.057192408, 0.0, -0.0256364, -0.028660972, -0.02937357, 0.0, -0.017604912, -0.020851422, -0.016070362, 0.0, -0.0870202, -0.0832279, -0.07525406, 0.0) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.062738225, 0.07106593, 0.061644047, 0.0, -0.06068257, -0.06983662, -0.066070385, 0.0, 0.024919355, 0.03227179, 0.028569462, 0.0, -0.07866227, -0.098967604, -0.092128105, 0.0) * go_1(0.0, -1.0);
|
||||
result += mat4(0.040397774, 0.047241107, 0.03962998, 0.0, -0.09112752, -0.10057507, -0.09301817, 0.0, 0.10833967, 0.101835825, 0.10027467, 0.0, 0.27189335, 0.27433604, 0.26781923, 0.0) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.044211388, -0.042373534, -0.03658007, 0.0, 0.113148406, 0.12423258, 0.107804194, 0.0, -0.17081551, -0.18562958, -0.17475435, 0.0, 0.09636739, 0.10763415, 0.093332425, 0.0) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.03798545, -0.047811143, -0.050768293, 0.0, 0.018775463, 0.026812987, 0.03452908, 0.0, 0.0055677597, 0.0039081173, -0.0017878668, 0.0, -0.10728597, -0.12618187, -0.109045394, 0.0) * go_1(1.0, -1.0);
|
||||
result += mat4(0.06359783, 0.064184755, 0.04934199, 0.0, -0.009819327, -0.006616115, -0.007431496, 0.0, 0.025055679, 0.024787048, 0.017360551, 0.0, -0.047140837, -0.061695747, -0.06440822, 0.0) * go_1(1.0, 0.0);
|
||||
result += mat4(0.060199022, 0.06482763, 0.059514645, 0.0, 0.026998974, 0.028776823, 0.024897143, 0.0, 0.17968474, 0.19337215, 0.16760105, 0.0, 0.0075838566, 0.010503482, 0.011993149, 0.0) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.0052927984, -0.0060193934, -0.0048643993, 0.0);
|
||||
return result + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.073079124, 0.11507942, 0.028201895, -0.021776304, -0.25251916, -0.08662003, 0.38814726, 0.4146095, 0.06326891, 0.01635252, 0.06423356, 0.13488062, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.059791833, -0.03105604, 0.041643705, 0.35197195, -0.17314838, 0.067622855, -0.032012507, 0.09691628, -0.11094062, 0.007625051, 0.094762206, -0.05824145, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.120281175, 0.027440755, -0.026316144, -0.025291128, -0.41698205, -0.05966847, -0.28400028, -0.06946398, -0.10906026, -0.015854035, -0.028724853, -0.06626416, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.068752654, -0.12652585, 0.38200122, 0.17978846, 0.2749825, 0.015504972, 0.21765926, 0.2246602, -0.062151223, 0.07457783, 0.13588274, -0.037328478, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(0.3718559, 0.025637252, -0.4048626, -0.41484925, 0.24768798, 0.09984098, -0.5663632, -0.6659978, 0.212067, -0.08328392, -0.5277322, -0.016879432, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.11072714, -0.010321538, 0.11265787, 0.0055236337, -0.13345073, 0.004847663, 0.3744461, -0.4038564, -0.09893075, 0.031325124, 0.2883957, -0.04268903, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.10444391, -0.60588187, 0.02543334, 0.10911738, -0.10860678, 0.15701362, 0.29235297, 0.045803998, 0.076250754, -0.10799697, 0.08841044, 0.08145623, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.04246739, -0.1225759, 0.11280305, -0.12079673, 0.5289142, -0.011892906, -0.0800465, 0.05915611, -0.126204, 0.08239301, -0.0092391195, -0.07672885, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.11922264, 0.14036109, -0.09491126, 0.05112697, -0.12543046, -0.08662423, -0.041537095, 0.048038274, 0.11672854, -0.006516173, -0.023524825, 0.030505095, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.07697861, 0.41154122, 0.042374082, -0.087270625);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.09419103, -0.1178418, 0.09523275, 0.24648252, 0.03595256, -0.05417468, -0.029167585, -0.012279932, 0.08852021, -0.12534834, 0.0604663, 0.050634373, -0.19536541, 0.21548285, 0.040379744, -0.28046605) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.13783203, 0.17191975, 0.06956328, 0.005270252, -0.029844455, -0.17657366, 0.03439078, 0.048861686, 0.12017991, -0.087307535, 0.11815637, 0.31309614, 0.08440897, 0.09969244, -0.06220224, 0.2633136) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.098606475, -0.05856224, -0.01163882, -0.020945825, -0.08988821, 0.18520717, 0.011407763, 0.20973705, 0.21017794, 0.038311377, -0.018910313, 0.053878684, -0.08751144, -0.0081623215, 0.29060364, 0.14363094) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.13354321, -0.38046083, 0.14157647, 0.10190452, -0.045502663, 0.0053245644, -0.10817685, -0.048371315, 0.16157807, 0.2086147, 0.07632662, 0.24636099, -0.0053555835, -0.19587666, -0.46687222, 0.002362032) * go_0(0.0, -1.0);
|
||||
result += mat4(0.28275147, -0.1468291, 0.24075283, -0.35119128, 0.18727398, 0.3833064, 0.08667899, 0.15021381, -0.092296466, -0.25686404, -0.116076745, 0.2231862, -0.27637103, 0.12317917, -0.0341737, -0.40077657) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.007041629, 0.18089123, -0.21195571, -0.12346183, -0.06088577, -0.30784377, 0.0048495876, 0.06013008, 0.07200418, -0.0076884073, 0.02632822, -0.0011575016, 0.21025613, -0.2573419, -0.06994815, 0.32497165) * go_0(0.0, 1.0);
|
||||
result += mat4(0.0016823286, -0.014366541, -0.5049525, 0.048534572, -0.0057915323, -0.0030526456, -0.028976317, -0.16376147, -0.15560333, -0.053708192, -0.055678204, -0.13087665, 0.0048869387, 0.027514834, 0.017380254, -0.06743363) * go_0(1.0, -1.0);
|
||||
result += mat4(0.044514824, -0.1754644, -0.26664957, 0.1486667, 0.114894986, 0.061640915, -0.13305616, 0.06450565, 0.03552732, 0.2835473, 0.13800526, 0.005875215, 0.15751484, 0.41759813, -0.19406971, 0.071032055) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.18419577, -0.05527526, 0.017057603, -0.1146602, 0.15775396, -0.01188916, 0.09368113, 0.05765405, 0.064170234, -0.017833546, 0.12100514, -0.06250493, 0.2421206, 0.15719843, 0.23718071, 0.023142194) * go_0(1.0, 1.0);
|
||||
result += mat4(0.079226464, 0.07877355, -0.022315226, -0.13507473, 0.14683898, 0.028739132, -0.24479519, -0.280197, -0.13223173, 0.21732429, -0.1546993, 0.045442928, 0.163642, -0.07062695, 0.03805918, 0.060860883) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.095216066, -0.16650215, -0.34863555, -0.025274571, 0.3064775, -0.034196265, -0.25773287, 0.19570488, -0.005434017, 0.26308087, 0.009404902, -0.24736062, 0.05558232, -0.014217521, 0.03667355, -0.15134114) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.074846864, 0.010901994, 0.035149742, 0.12106729, -0.36042807, -0.011231913, 1.4317516, 0.6400351, 0.105860665, -0.11587906, -0.11065066, 0.19126756, 0.14132085, 0.021570992, -0.3618735, -0.081163004) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.06937371, 0.3815214, 0.026842717, -0.04051589, -0.09472515, -0.027198657, -0.16502109, 0.114273794, -0.15207845, -0.15054241, -0.25099036, -0.10871029, 0.14311226, 0.07640166, 0.47051275, 0.0447809) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.25960425, 0.11150338, -0.042022616, -0.006633396, -0.29595324, -0.0149574205, 0.09806478, 0.03635802, 0.26789796, 0.41416678, 0.05145585, 0.61168057, 0.019582301, -0.118703716, 0.13974573, 0.04498941) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.04119621, -0.15503803, 0.33170196, -0.1158483, -0.06258357, 0.2574262, -0.07890287, -0.6929032, 0.004379942, 0.097908296, 0.009286624, 0.27194506, -0.2476702, 0.13828708, 0.05071857, -0.43693772) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.010842703, 0.13108006, 0.30126816, 0.20221521, 0.018797455, 0.0614624, 0.11102966, 0.019204421, 0.09975456, 0.04676902, -0.044540443, 0.118877, -0.04871634, -0.089208096, 0.027455999, 0.029557817) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.10421777, 0.3135469, 0.14557797, 0.0497297, 0.0034963787, -0.20342828, 0.08332032, -0.09004643, 0.06574797, -0.14168271, -0.08754358, 0.30385306, -0.3374016, -0.4360316, 0.15854433, -0.24081887) * go_1(1.0, 0.0);
|
||||
result += mat4(0.1407836, 0.09678823, -0.02240152, -0.013985894, 0.012281648, -0.24124922, -0.46433777, -0.25915003, 0.042200714, -0.21701157, -0.016618999, 0.13135725, -0.34656256, -0.034729004, -0.29246503, -0.13514486) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.08458621, -0.023144595, -0.057707336, -0.081382714);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.27743992, 0.04277345, 0.019331178, -0.7335445, 0.006292013, 0.19800001, -0.0025032016, 0.16098699, -0.03186617, -0.060173523, 0.08878855, -0.10669283, 0.130609, -0.068515256, -0.03571823, -0.13751523) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.2430821, -0.08233978, 0.082374334, 0.04843392, -0.18989052, -0.041925047, 0.40021122, -0.317836, -0.13517766, 0.032255337, -0.0746507, 0.22114721, -0.045706213, -0.12841983, -0.27830583, 0.05763077) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.08436965, -0.04967552, -0.16798134, -0.1539139, -0.17429228, -0.10166739, 0.35864773, 0.12873615, -0.07667423, 0.04985163, 0.13391761, -0.054322604, 0.085659124, -0.078792974, 0.06481059, 0.058667548) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.17568155, 0.56705236, 0.056562193, -0.020951264, 0.005879628, -0.2502103, -0.19619654, 0.019490348, -0.14527243, 0.16983634, 0.049245857, 0.18316677, 0.055053137, 0.10699275, 0.0016993808, 0.20105995) * go_0(0.0, -1.0);
|
||||
result += mat4(0.36284775, -0.05856962, -0.42545465, 0.31931567, -0.15698905, -0.28837132, -0.028697362, -0.024917847, 0.04317283, 0.024557106, -0.052158598, 0.38654143, -0.1782944, 0.43094924, -0.11738149, 0.21554618) * go_0(0.0, 0.0);
|
||||
result += mat4(0.22645079, -0.20319854, 0.20733371, -0.18697177, -0.05167819, -0.12845007, 0.5543688, 0.2453291, 0.08027872, -0.0628224, -0.06593836, -0.05795855, -0.24527508, 0.23632833, -0.043366548, 0.14135826) * go_0(0.0, 1.0);
|
||||
result += mat4(0.08384414, 0.20807321, 0.030559694, -0.13640808, -0.07641805, -0.10919174, -0.19799095, -0.12955745, 0.093737304, -0.17856954, 0.035103753, -0.044699315, -0.07255943, -0.02331535, 0.2059249, 0.3058302) * go_0(1.0, -1.0);
|
||||
result += mat4(0.022345139, 0.16286038, -0.27228013, -0.41105714, -0.0014384583, 0.089546144, -0.08296848, -0.0050463285, 0.07038578, -0.030679917, 0.031246305, 0.36761853, -0.34799108, -0.0405689, -0.19182852, 0.015853593) * go_0(1.0, 0.0);
|
||||
result += mat4(0.1021783, -0.11396049, -0.08733628, -0.017449526, 0.042015605, -0.14808236, 0.10072531, -0.07403295, 0.15276712, -0.07807765, -0.10013386, -0.26110634, -0.04858846, 0.066066965, 0.13598624, 0.21687816) * go_0(1.0, 1.0);
|
||||
result += mat4(0.07041569, -0.17775945, 0.15697548, -0.15425202, -0.06569677, -0.033233996, 0.22596005, -0.026170855, -0.20729817, 0.1316505, -0.058410037, 0.22166035, 0.09107114, -0.13078825, -0.05639485, -0.02716142) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.057966787, -0.15311252, 0.095924966, -0.055951685, 0.082777694, -0.08471956, -0.39918202, 0.10599212, 0.102710955, 0.21808124, 0.12083635, -0.38835892, 0.031709857, 0.13955092, 0.12647778, 0.011549966) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.09810508, -0.119743295, 0.06166254, 0.13595435, 0.036198203, -0.028710455, -0.40789905, -0.034894038, -0.12622337, 0.14379597, 0.039958883, 0.19636424, 0.047094557, -0.07987105, -0.04905092, -0.07875785) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.34118712, -0.2833933, -0.045028314, -0.40670308, -0.01961924, 0.37131935, 0.29099533, -0.19843055, 0.18604252, -0.0037280058, 0.1091072, -0.40579233, 0.11422739, -0.16490164, -0.0022396361, -0.21486944) * go_1(0.0, -1.0);
|
||||
result += mat4(0.0010853866, 0.2223109, 0.2416471, -0.33326814, 0.2549397, 0.6442047, 0.18411863, -0.19081281, -0.43552014, -0.1793875, -0.58699155, -0.01900168, -0.26955804, -0.071371995, 0.07599079, 0.27434483) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.19644544, 0.14383379, -0.2599538, 0.001666124, -0.16369823, 0.009537702, -0.3690974, -0.048157427, -0.2040159, 0.01522431, -0.11007749, -0.07012568, 0.17536888, -0.012183123, -0.17366478, -0.15090804) * go_1(0.0, 1.0);
|
||||
result += mat4(0.0855136, 0.06863859, -0.17249937, -0.12850079, 0.15325847, 0.22742507, 0.22535504, 0.24032994, -0.109522276, 0.24135293, -0.17784368, 0.08172238, -0.16143093, 0.1358853, -0.09399085, 0.012180792) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.04346881, 0.13367178, 0.10387612, 0.04705543, -0.10315795, 0.5816371, -0.090529, -0.017955385, -0.09032907, -0.52505773, 0.10958755, -0.26151448, 0.17246644, 0.011886279, 0.3566306, 0.32170597) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.27853554, 0.1558035, 0.070289604, 0.17052644, -0.31982365, 0.29085326, -0.09494764, 0.2270542, 0.10514691, -0.24606484, -0.02049181, 0.126686, 0.16719124, 0.013080999, -0.08577963, -0.07057233) * go_1(1.0, 1.0);
|
||||
result += vec4(0.0061747693, -0.029145364, -0.026801255, 0.027419873);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.07447851, -0.07888509, -0.28236163, 0.2479792, -0.065199964, 0.24733023, 0.099619575, -0.26430824, -0.03523585, -0.03547245, -0.10619345, -0.25326422, -0.116270036, -0.065133184, -0.30401528, 0.01563764) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.19106275, -0.26104823, -0.14457102, -0.17298317, 0.24148639, -0.10950928, 0.062851585, 0.042540826, 0.13287601, 0.06975747, 0.15848075, -0.3854902, -0.13132331, -0.16468687, -0.029844414, 0.27754608) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.015378025, -0.14203559, 0.08058816, 0.32896644, -0.074871175, -0.26611313, -0.18830848, 0.091641426, -0.16522385, -0.23424402, -0.12279703, -0.13343342, -0.2509982, -0.0554576, 0.07286022, -0.028823337) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.13543738, 0.049395677, -0.015148539, 0.13301241, -0.12827122, -0.012590744, 0.012936948, 0.008271658, 0.12442749, 0.3497426, -0.16126058, -0.2670464, -0.010479037, 0.07037434, -0.15527055, 0.13205245) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.09535385, -0.3931354, 0.24716614, -0.21284536, 0.14652656, 0.38149378, -0.09607391, 0.06350967, 0.48615915, 0.32634613, 0.146291, 0.2566475, -0.40927815, -0.05268087, -0.04110691, -0.0068722935) * go_0(0.0, 0.0);
|
||||
result += mat4(0.089152284, -0.01860622, 0.016856732, 0.31244752, 0.022529159, -0.0071319416, -0.09786801, -0.13005258, 0.1524636, 0.21627748, -0.07395979, -0.087633945, -0.38435504, -0.08842507, -0.0058702417, -0.32936293) * go_0(0.0, 1.0);
|
||||
result += mat4(0.0816838, 0.0012210817, 0.28217188, 0.36141106, 0.0014665248, -0.0636269, 0.042035818, -0.056671552, -0.032501306, -0.22908778, -0.2067977, -0.004497514, -0.23052917, 0.26728114, 0.15353456, -0.17732324) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.17229734, 0.0818218, -0.10076918, 0.030027041, -0.14819005, -0.085340135, 0.050100215, 0.05683199, -0.12653661, -0.036583595, -0.32319903, -0.15273796, -0.15346588, 0.20005536, 0.23097478, -0.19834782) * go_0(1.0, 0.0);
|
||||
result += mat4(0.055430107, -0.2886931, 0.361814, 0.33160287, -0.084407054, 0.06254009, -0.02332793, -0.018134018, -0.014879812, 0.112346604, -0.20686437, -0.23408228, -0.01091196, -0.062669374, 0.085567676, 0.23738655) * go_0(1.0, 1.0);
|
||||
result += mat4(0.080383554, -0.1172084, 0.19703126, 0.27777427, -0.07559937, -0.25445858, 0.3450109, -0.071967736, 0.2034805, 0.33716002, 0.15314537, -0.22953224, 0.113631405, -0.0058444734, 0.2890972, 0.06557255) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.17646056, -0.025448758, -0.14952567, 0.017148364, -0.15238142, 0.1435677, 0.20273875, 0.22255951, -0.011660059, -0.003515217, -0.17305166, -0.13478355, -0.06558679, -0.032662887, -0.20914736, -0.5397283) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.1679393, -0.109410115, -0.117427185, 0.14982319, -0.06457877, -0.06607065, 0.0018200208, -0.0118605625, 0.046539318, -0.020642165, -0.14413542, -0.09530688, 0.22196163, -0.2187166, -0.10759705, 0.013234591) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.13220267, -0.12540027, 0.26163217, 0.12791659, 0.16204996, -0.4023048, -0.13485721, -0.10187536, 0.059764992, 0.048170995, -0.25281772, 0.2090587, -0.06542371, -0.10791867, -0.21286209, -0.309109) * go_1(0.0, -1.0);
|
||||
result += mat4(0.16233061, 0.120428756, -0.11460241, 0.24531102, -0.2670459, -0.24195078, -0.20964348, -0.12930301, -0.2343609, -0.22543164, -0.28909695, -0.33560297, 0.6009884, 0.39171818, -0.1276308, -0.020736236) * go_1(0.0, 0.0);
|
||||
result += mat4(0.40162864, 0.045881115, 0.032667033, 0.31454235, -0.17351128, -0.009387306, 0.17341217, 0.30810982, -0.025815086, -0.10390133, 0.012544771, 0.036918722, 0.34386298, 0.23177734, -0.046727546, 0.20098232) * go_1(0.0, 1.0);
|
||||
result += mat4(0.11541034, -0.11647824, -0.12874861, 0.004921287, -0.13921295, -0.25733355, -0.1112383, -0.033295818, 0.0035326157, 0.3782048, 0.055785846, -0.1547331, 0.17358719, -0.2789715, -0.13400431, 0.1583795) * go_1(1.0, -1.0);
|
||||
result += mat4(0.4130191, -0.33944547, -0.064674884, 0.39617148, -0.11483455, -0.022601767, 0.1129301, -0.09713594, 0.14681247, 0.34442267, 0.08721343, -0.08309499, 0.088704996, -0.20943391, -0.2891408, 0.1709401) * go_1(1.0, 0.0);
|
||||
result += mat4(0.19503653, 0.17490312, -0.23491044, -0.028934423, 0.04479765, -0.0334551, 0.0602648, 0.0019939998, 0.23314747, 0.21557438, 0.07273092, 0.15467109, -0.11194509, 0.0736583, -0.17628083, -0.3851578) * go_1(1.0, 1.0);
|
||||
result += vec4(0.022887055, 0.01521631, 0.17967467, -0.0131908795);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.10233342, -0.30233157, 0.24238978, -0.007108631, 0.14248851, 0.08486557, 0.0028373515, 0.122387215, 0.10996857, -0.17286511, 0.19819227, 0.07023527, 0.07579955, -0.16861476, -0.210025, 0.12760942) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.091181986, -0.41497424, -0.27567792, -0.09938067, -0.12210428, 0.20617811, -0.017644284, -0.22552875, 0.049019493, -0.18990634, 0.11057753, -0.043193225, -0.15278774, -0.18331046, -0.1837594, 0.029758787) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.1757096, -0.199691, -0.034743477, -0.15369363, -0.1701244, -0.0459655, 0.10508695, -0.09795581, 0.13464944, 0.37202564, 0.14706515, 0.23416734, 0.08302458, 0.20696343, -0.13935481, 0.03092827) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.49887478, 0.24046332, -0.029459715, 0.17374687, -0.15019977, 0.31086043, -0.28297687, -0.22239804, 0.12314376, 0.11594825, 0.17682782, 0.09753434, -0.26263535, -0.12739435, -0.57744014, 0.087381124) * go_0(0.0, -1.0);
|
||||
result += mat4(0.08101439, -0.16185337, 0.112901986, 0.24439482, -0.44051018, -0.70680356, -0.23015513, 0.63106006, -0.08817581, -0.057614524, 0.15352182, -0.049620207, 0.17742544, -0.49583626, -0.3844133, 0.18385352) * go_0(0.0, 0.0);
|
||||
result += mat4(0.17149475, 0.31255633, 0.19286609, 0.21052869, -0.11856372, -0.032373343, 0.06503625, -0.31664965, 0.040755365, -0.027614031, -0.33330554, 0.40148625, 0.056921627, -0.27068445, 0.047014963, 0.103712596) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.09326643, 0.13677256, 0.06390537, 0.08080093, -0.10685094, 0.124757454, 0.14696303, 0.10871933, -0.10971212, 0.01655797, -0.11052674, -0.17361104, 0.015513338, -0.1917502, -0.26384255, -0.022672707) * go_0(1.0, -1.0);
|
||||
result += mat4(0.032367155, -0.087523445, -0.06951093, -0.08128242, 0.2627859, 0.14933161, 0.3114999, -0.007791172, -0.4146471, -0.2530298, -0.43175155, -0.06878434, 0.5724947, 0.25498095, 0.4838959, 0.15076154) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.13427481, -0.10134261, 0.087439895, 0.015921364, 0.15421022, 0.20205952, 0.22928835, -0.07339068, -0.33318612, -0.17467582, -0.04758165, 0.11858059, 0.17408857, -0.099393494, -0.06389948, -0.06494366) * go_0(1.0, 1.0);
|
||||
result += mat4(0.15349221, 0.08508258, -0.09294437, -0.03204993, -0.22561033, -0.15088828, -0.020105945, 0.10041996, -0.024723593, 0.06610271, -0.24423431, -0.050512858, -0.100530736, 0.16394953, 0.16365045, -0.012055956) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.16342951, 0.23113559, 0.21289586, 0.28391558, 0.052211206, -0.17983536, -0.008415342, 0.08977486, -0.054481823, 0.17506577, -0.14162593, -0.070448756, 0.093877845, 0.05161232, -0.25006327, 0.007014646) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.104965575, 0.20048036, 0.024134496, 0.5442797, 0.19958296, -0.05165447, 0.076928124, 0.030868227, -0.0563495, -0.19757621, 0.10801544, -0.24202053, 0.0067657093, -0.17784451, -0.03134409, -0.06741009) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.33347723, -0.12338564, 0.23495969, -0.23091966, 0.059872203, 0.028045453, -0.06781438, 0.111325614, -0.21861015, -0.030451605, -0.04267672, -0.0039260075, 0.0911101, 0.054191053, -0.08498816, 0.04810343) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.05028896, 0.21515386, 0.16005337, -0.32279232, 0.19178568, 0.779363, -0.12682606, -0.4378189, 0.37980273, 0.063021325, 0.19370794, -0.05618088, -0.00088428083, 0.29736623, 0.24649377, -0.0021625878) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.45007992, -0.16040307, -0.1714593, -0.16251564, 0.070867635, 0.21317895, -0.070962, 0.17147541, -0.27786884, -0.33259448, -0.022767346, -0.17967366, 0.21208113, 0.19740848, 0.16877973, 0.09630738) * go_1(0.0, 1.0);
|
||||
result += mat4(0.09235827, -0.35231477, -0.093315996, -0.035850406, -0.08311695, 0.054329164, 0.17788444, -0.020736141, -0.03739786, -0.1678283, 0.12676615, 0.17182353, 0.17408027, 0.07699043, 0.095501214, 0.0069830767) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.16631392, -0.16925642, -0.17081848, 0.017719474, -0.20530944, 0.19215193, -0.039511178, -0.08296625, 0.2240653, 0.100644305, 0.2901835, 0.32166973, -0.10026419, -0.14864013, -0.19926691, -0.11607018) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.13750182, 0.07445518, -0.033964884, -0.085812084, -0.03903257, -0.054933593, 0.06765632, 0.064338475, 0.27182797, 0.07721309, -0.0334218, -0.19344835, -0.14405386, 0.046106674, 0.16596143, 0.0879945) * go_1(1.0, 1.0);
|
||||
result += vec4(0.049844168, 0.02670437, 0.050967637, -0.10779561);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.034357008, 0.00082413113, -0.13382089, -0.05066409, 0.26684088, -0.31363875, 0.073608615, 0.20824149, 0.21509308, -0.07118628, 0.11287014, -0.09817389, 0.16107765, 0.17146803, -0.13836654, -0.05962866) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.029981667, 0.08738892, 0.17735903, 0.15817277, 0.041752994, -0.20031185, 0.064203605, 0.48786053, -0.0033609737, -0.42522693, 0.058846988, 0.22180536, 0.17181319, 0.13097888, -0.059532285, 0.062227458) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.13188283, 0.07971828, 0.28278515, 0.038570832, -0.12815465, 0.29860008, -0.2785862, -0.07612298, -0.14369671, 0.12457525, 0.11982623, -0.018675303, 0.14936846, 0.1284789, -0.0042489986, 0.042810377) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.2892425, -0.20834558, 0.07358541, -0.11190968, -0.16300741, 0.15674856, -0.04297203, -0.29218298, -0.036296643, -0.052267153, -0.22889943, -0.21203549, -0.03553075, -0.20343691, -0.07413655, -0.092966415) * go_0(0.0, -1.0);
|
||||
result += mat4(0.2484468, -0.23412868, -0.070199326, 0.2061922, 0.5047224, -0.48216155, -0.5792768, 0.610787, 0.023935676, -0.040435325, -0.1238493, -0.09576053, -0.26183444, 0.14510648, 0.5365255, 0.5499143) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.058255754, 0.08133753, -0.18663554, 0.26190025, 0.26006857, -0.007619795, 0.14585225, 0.073580734, -0.0396066, 0.2821596, 0.31778112, -0.029853562, -0.19703479, 0.17809318, 0.21089044, -0.106730856) * go_0(0.0, 1.0);
|
||||
result += mat4(0.20549655, -0.05962688, 0.1432124, 0.013446325, -0.19064854, 0.061387196, 0.1792527, 0.0010619498, -0.1456842, 0.18950678, -0.13990986, -0.37644413, -0.083257, -0.2937246, 0.032096215, 0.14719158) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.26601696, 0.4242341, -0.073702715, -0.3221337, 0.026037043, -0.0117916465, -0.024286825, 0.23183465, -0.030869482, -0.045915652, -0.040611852, 0.11372697, -0.25404635, 0.21859063, 0.13869432, 0.19651218) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.028276298, -0.11217159, 0.27144867, -0.010531775, 0.11032058, -0.09957206, 0.12570262, 0.14724332, 0.08758557, -0.11042305, 0.025948172, -0.010910802, -0.029466914, -0.041135952, -0.017091949, 0.05501236) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.12688768, -0.19051413, 0.052141912, -0.13618521, -0.16320245, -0.1601866, 0.16207355, -0.023218745, 0.2103894, -0.06212745, -0.07042835, 0.0996637, -0.1763831, 0.13890013, -0.12125462, -0.105104685) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.10485512, -0.49283037, -0.504295, 0.009089699, -0.17389494, -0.12835866, 0.14188384, -0.22946316, 0.006298799, -0.0348454, -0.0852419, 0.17956656, -0.08088888, 0.35675287, 0.16014415, -0.055372503) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.17157564, 0.1557075, -0.17681694, 0.14834762, -0.13708206, 0.101721555, 0.17070566, -0.22522852, 0.08100986, -0.23204406, -0.38926315, -0.13165781, 0.1040296, -0.045591615, 0.15745829, -0.10410621) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.20517144, 0.35896194, -0.0010962893, -0.18043008, -0.016253468, 0.035292216, 0.06781499, 0.015984116, -0.20261237, -0.28905126, 0.007414641, 0.008870292, 0.52166605, -0.0996688, -0.23151648, 0.2811893) * go_1(0.0, -1.0);
|
||||
result += mat4(0.013482173, -0.04891998, -0.06094191, -0.14416319, -0.00087873987, 0.11979091, 0.06457245, -0.2305623, -0.1476981, 0.2634587, -0.058895197, -0.07394766, -0.27173743, 0.7530214, 0.037599873, 0.22086331) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.10357755, 0.23899554, 0.034912035, -0.14336212, -0.019786308, -0.085470654, -0.03096524, 0.108783185, 0.28971127, 0.24527478, -0.19110362, -0.49510127, -0.15574701, 0.10968643, -0.13727877, 0.04502924) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.10808282, -0.079148844, -0.3244773, -0.2210664, -0.0062175165, 0.1303082, 0.012592612, -0.38039228, 0.26899642, -0.16624425, -0.04438198, 0.42067865, -0.13381268, 0.03408099, -0.2999706, -0.3817641) * go_1(1.0, -1.0);
|
||||
result += mat4(0.030872926, -0.26852018, -0.14650428, 0.16869825, -0.19185568, -0.06341456, 0.12261606, -0.26597574, 0.44865233, 0.21416639, 0.40359476, 0.12814924, 0.2542566, -0.23348318, -0.43142912, -0.35113996) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.03364283, 0.11002299, 0.3311268, -0.14580412, -0.10348537, 0.13331696, -0.0793144, -0.04116661, 0.040704627, -0.14875266, -0.09259674, -0.062087066, 0.063962296, 0.18420577, -0.085616685, -0.16555141) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.037546165, -0.015675364, 0.13989694, 0.027605768);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.35835463, 0.038305778, -0.10198824, -0.021951782, 0.02142098, -0.072417736, -0.2577152, 0.054713376, 0.075116105, -0.21191697, -0.1213158, -0.105036296, 0.12030758, -0.17591658, 0.1726511, 0.17754573) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.32325825, 0.19869742, 0.333873, 0.39670366, 0.20716824, 0.09557955, 0.120742686, -0.2271023, 0.37509173, -0.031341635, 0.10247365, 0.031520665, -0.092765376, -0.13535516, 0.8333728, 0.05886494) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.17573749, 0.16768494, 0.021141645, 0.19668253, 0.21080776, 0.31503728, -0.26834, 0.19103156, 0.21946241, 0.14559007, -0.09761235, -0.23565038, -0.49393657, -0.5332298, 0.09806347, 0.054431103) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.042109374, -0.05564321, 0.27586877, 0.010382545, 0.007322007, 0.13193823, -0.18262729, 0.06399193, 0.14174329, 0.3898842, -0.10398105, 0.01846146, -0.24542394, -0.13020967, -0.16491668, -0.03544872) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.15291597, 0.1566557, 0.14745249, -0.23258151, 0.17843612, 0.15885495, -0.691466, -0.41177312, 0.40330106, -0.07991953, 0.2832403, 0.10656986, -0.19571523, 0.3670614, -0.62296015, -0.5666968) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.17513512, 0.011393021, -0.44352317, -0.059153114, -0.2227142, -0.033094753, 0.09624524, 0.051315393, 0.2632246, 0.09945105, 0.042561427, -0.1234722, 0.23755905, -0.506999, 0.114180565, 0.27887583) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.459564, -0.120326266, 0.17507194, 0.06701153, -0.14124362, -0.36653697, -0.2856802, -0.22955593, -0.08515889, 0.18788262, 0.23427077, 0.021544341, 0.31996533, -0.2668834, 0.08469808, -0.01347926) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.14092083, -0.31244513, -0.044023518, 0.013948701, 0.33119613, -0.011959397, -0.1494438, -0.111066826, -0.11994278, 0.116068155, -0.13032633, -0.037004936, 0.13851176, -0.006655432, -0.39841232, -0.079951204) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.08959123, 0.18297827, -0.0763483, 0.11364159, -0.04361797, -0.029816678, -0.19314721, -0.03484794, 0.044681285, 0.04669291, -0.30017474, -0.07453036, 0.090825416, -0.27414632, 0.36355078, 0.15742934) * go_0(1.0, 1.0);
|
||||
result += mat4(0.18470702, 0.113800436, -0.18546791, 0.044184085, 0.12490399, 0.1826781, -0.01313173, -0.19048993, -0.026458051, -0.1693334, 0.21958382, 0.030458853, -0.059242606, 0.039351143, -0.061676584, -0.06904634) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.114877924, -0.03781683, -0.19207929, 0.007679428, 0.2409049, 0.2965285, -0.38395065, 0.11604976, -0.22588749, 0.48505852, 0.09866521, -0.2585994, -0.011380872, -0.018334057, -0.047188547, 0.3038583) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.2783936, -0.17609318, 0.4904369, -0.31848624, 0.39725313, 0.082951784, -0.15595853, -0.007526218, 0.2355193, -0.30003366, -0.27686292, 0.120900005, -0.1223885, 0.40760317, 0.0013726618, -0.24877374) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.1580051, -0.044973504, 0.00053594523, -0.057797022, 0.18895927, 0.23527777, -0.18095906, -0.076961614, 0.2544444, -0.05932328, 0.13717431, -0.024487074, 0.33157274, -0.09072586, -0.004386734, -0.05180953) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.21685815, 0.061656334, -0.066127226, 0.24831405, 0.26001146, 0.046466008, -0.047196623, 0.13538954, -0.06449239, 0.45951647, -0.13132116, -0.7079741, -0.06683439, -0.47628635, 0.42461708, 0.6475073) * go_1(0.0, 0.0);
|
||||
result += mat4(0.2590011, -0.26020283, 0.0005333198, 0.01555692, 0.37920526, 0.29205114, -0.20281325, -0.1455974, 0.056119893, 0.022032745, -0.30095813, 0.48154855, -0.35761952, 0.07582935, 0.12462687, 0.068093665) * go_1(0.0, 1.0);
|
||||
result += mat4(0.20434918, 0.26690874, 0.028224666, 0.042565826, 0.037406113, 0.5059272, -0.0047208676, 0.0019095197, 0.16626422, -0.23407575, -0.072687164, 0.00063299487, -0.10172441, -0.11645544, 0.008715937, -0.012423992) * go_1(1.0, -1.0);
|
||||
result += mat4(0.08269191, 0.116322584, -0.08155921, -0.04790326, 0.09546776, 0.3632936, -0.08139031, -0.10399187, 0.06618616, -0.26862565, 0.25058737, 0.0410593, -0.07191658, -0.20559746, 0.21857823, 0.12776822) * go_1(1.0, 0.0);
|
||||
result += mat4(0.54989135, 0.38051483, 0.015739547, -0.0068143173, 0.26107135, 0.2585036, -0.12345306, -0.13934542, -0.19018838, 0.2730626, 0.42644337, 0.16693048, -0.15189888, 0.023638237, 0.11272267, 0.039560657) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.20554838, -0.10647836, -0.02824578, 0.08658529);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(M)-Conv-3x1x1x56
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_6_tf
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_2 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_5 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_6 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_9 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_10 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_13 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.030150581, -0.002168429, 0.014918388, 0.0, 0.020940892, 0.04591048, 0.049137186, 0.0, 0.111167125, 0.05311203, 0.0625381, 0.0, 0.020043287, 0.04785493, 0.040921766, 0.0) * g_0;
|
||||
result += mat4(0.04158565, -0.008488135, 0.0020472286, 0.0, 0.049123142, -0.055042226, -0.06489915, 0.0, 0.09238876, 0.10387972, 0.09576964, 0.0, -0.054776173, -0.098954335, -0.09018853, 0.0) * g_1;
|
||||
result += mat4(0.2081418, 0.08273068, 0.040325668, 0.0, -0.09937802, -0.13162258, -0.13989717, 0.0, -0.13983749, 0.01309777, 0.0023888077, 0.0, -0.18937743, -0.07021057, -0.047152344, 0.0) * g_2;
|
||||
result += mat4(-0.09646629, 0.080605574, 0.10463501, 0.0, 0.22579835, 0.24077554, 0.22600271, 0.0, 0.049726978, 0.015292378, -0.0047161994, 0.0, 0.16281025, 0.048491795, 0.038338162, 0.0) * g_3;
|
||||
result += mat4(-0.09772107, -0.043998875, -0.054745924, 0.0, -0.1257736, -0.13175423, -0.10889618, 0.0, -0.015900036, 0.07074481, 0.08210496, 0.0, -0.11321135, -0.12526917, -0.105605066, 0.0) * g_4;
|
||||
result += mat4(0.14187162, 0.14032297, 0.13016908, 0.0, 0.018954534, 0.016011704, 0.010169183, 0.0, 0.04762765, -0.044460997, -0.06499567, 0.0, 0.11133751, 0.09464176, 0.08865274, 0.0) * g_5;
|
||||
result += mat4(-0.16567162, -0.1744712, -0.1637222, 0.0, -0.02412003, 0.0074480795, 0.007903436, 0.0, -0.06161098, -0.046788957, -0.03971239, 0.0, 0.030736001, 0.036460854, 0.03660504, 0.0) * g_6;
|
||||
result += mat4(0.084027, 0.10024112, 0.08152756, 0.0, 0.005087354, -0.026047802, -0.027264625, 0.0, 0.10519243, 0.08977278, 0.077558964, 0.0, -0.052826345, -0.06602686, -0.055083472, 0.0) * g_7;
|
||||
result += mat4(0.007862721, 0.009936555, 0.012004831, 0.0, -0.042322706, -0.061728776, -0.05359773, 0.0, 0.030532641, 0.045623366, 0.04214089, 0.0, 0.030569768, 0.011892851, 0.0074041556, 0.0) * g_8;
|
||||
result += mat4(0.03948997, 0.043119986, 0.039943404, 0.0, 0.0526772, 0.06820589, 0.058139592, 0.0, -0.062081397, -0.06755701, -0.054816127, 0.0, -0.004076369, 0.0061744447, 0.016273081, 0.0) * g_9;
|
||||
result += mat4(0.0071622543, 0.004829105, -0.002032197, 0.0, -0.048541367, -0.059043564, -0.05662218, 0.0, 0.0015553127, 0.009178359, 0.009577062, 0.0, 0.114169896, 0.1349016, 0.11432262, 0.0) * g_10;
|
||||
result += mat4(0.019324556, 0.028323999, 0.027396113, 0.0, 0.016746879, 0.01608199, 0.026891617, 0.0, 0.12068619, 0.13617857, 0.113496214, 0.0, -0.013930715, -0.014250072, -0.00824306, 0.0) * g_11;
|
||||
result += mat4(-0.0024534757, -0.0064973077, -0.007905654, 0.0, -0.019158727, -0.024820521, -0.020509848, 0.0, -0.09608131, -0.11177871, -0.10503465, 0.0, -0.011210447, -0.010875943, -0.015295865, 0.0) * g_12;
|
||||
result += mat4(0.09681486, 0.113604136, 0.10416855, 0.0, -0.08199983, -0.09013433, -0.08562243, 0.0, 0.041304465, 0.048315883, 0.042945288, 0.0, -0.09863276, -0.117853515, -0.09870226, 0.0) * g_13;
|
||||
result += vec4(-0.0039074384, -0.0085585555, -0.0132283475, 0.0);
|
||||
return result + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(S)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.10922428, -0.16249932, 0.15452726, -0.15669551, 0.053448875, -0.16528402, 0.01697721, -0.049275912, 0.20947173, -0.10576949, 0.19738325, -0.025417482, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.3285196, 0.15909512, -0.5273671, 0.23778777, -0.40508887, -0.0609677, -0.4188177, 0.11137456, -0.24131267, 0.10453423, -0.36216277, 0.053446792, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.23072472, -0.082083695, -0.0041477727, -0.09136237, 0.11958912, -0.312698, -0.15842685, -0.013882424, 0.10933724, 0.017880991, -0.022167003, 0.014662608, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.2789985, 0.054727737, 0.22577816, -0.49625716, -0.48472273, -0.011525487, 0.5354349, -0.08814955, -0.27021924, -0.044563178, 0.008232271, -0.13480483, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.18203105, 0.09277001, 0.27071548, -0.17773713, -0.4335171, 1.2275106, -0.07663438, -0.29020032, 0.011992759, 0.060106967, 0.11002492, -0.046098012, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.08363418, 0.063420765, -0.10278259, 0.09357691, 0.38670546, 0.13577081, 0.048631024, -0.024960777, 0.0846784, -0.057097007, 0.06049236, 0.042082917, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.12315548, -0.056513585, -0.09826642, -0.17079762, 0.06479095, -0.36984903, -0.12512982, 0.042867575, 0.08360464, 0.12835538, -0.005067881, 0.02542005, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.18997705, 0.086363226, -0.0007131526, 0.19858918, 0.39745626, -0.0090341605, 0.27864447, 0.20052041, 0.010576528, -0.089242525, -0.025109483, -0.030768145, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(0.05427315, -0.060894873, 0.06548642, 0.095537595, 0.29116166, -0.16159569, -0.13293959, -0.112566955, 0.0059667625, 0.016041303, 0.03831561, 0.09869594, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(0.0113532655, -0.06449327, 0.035503868, 0.5683031);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(S)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.027102098, 0.2640691, 0.1169015, 0.030902913, 0.15404584, 0.1361459, -0.38066056, 0.096569136, -0.111836195, -0.0051853824, -0.0996669, -0.23538585, -0.07060754, -0.18889332, -0.10793357, -0.15154232) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.1378689, 0.21024452, 0.010976513, 0.0179521, -0.05993059, -0.28364083, 0.24486947, 0.21347582, -0.12522404, -0.16091396, 0.15499291, 0.08353191, -0.03342411, -0.08964405, 0.25111282, -0.07550899) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.06398718, 0.05763278, 0.021394925, 0.14780094, -0.033050716, 0.03346528, -0.0846797, 0.0125302235, 0.18018652, 0.24586707, 0.050538495, 0.09879243, -0.100035876, 0.043505374, 0.042692907, -0.08768257) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.11572878, 0.0545887, 0.16437739, 0.2775331, 0.10323911, -0.18938646, -0.17097469, -0.188723, 0.085762165, 0.14605838, -0.15568069, -0.16947642, 0.09042493, -0.087587915, -0.041969277, 0.27252352) * go_0(0.0, -1.0);
|
||||
result += mat4(0.21475963, -0.018211678, -0.5711054, -0.09235345, -0.20367791, -0.23041399, 0.16346097, 0.007901888, 0.12542121, 0.16807431, 0.09862575, 0.16968751, 0.28490388, 0.40945014, -0.22364445, 0.14460565) * go_0(0.0, 0.0);
|
||||
result += mat4(0.27512726, 0.14046481, -0.17684339, 0.102218024, -0.10503195, 0.3080809, 0.03681373, 0.2668656, -0.093752496, -0.07476867, 0.19900662, 0.06028286, -0.19815882, -0.0584525, 0.027984729, -0.02143819) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.16829525, -0.06818115, 0.0006509334, 0.01163159, 0.18918815, -0.10731989, -0.008126929, -0.47991323, -0.11022971, 0.19150843, 0.05272113, -0.34417602, 0.022882428, 0.1774031, 0.062597334, -0.09915319) * go_0(1.0, -1.0);
|
||||
result += mat4(0.32131585, 0.05668815, -0.34203658, 0.05542482, -0.008077225, 0.009148517, 0.10953332, -0.050969962, 0.09904077, 0.46938205, -0.5148919, -0.22275375, -0.10536104, -0.23662373, 0.002147416, -0.14256701) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.19335353, -0.103732094, 0.17156832, 0.0059756916, -0.118641876, 0.14529023, -0.18662338, 0.0447326, 0.026719248, 0.042491894, 0.026437795, 0.05601309, 0.08645617, 0.08365193, -0.039582565, 0.16612953) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.014315469, 0.012588422, 0.037587024, 0.08707526, -0.08064868, -0.28149533, 0.27326405, 0.21468583, -0.04278333, 0.29369017, 0.18653142, 0.035729136, 0.079363555, 0.30725953, 0.0147137, 0.08527481) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.06659263, 0.03452449, -0.33752796, 0.0066543026, 0.48697233, 0.019602561, -0.32033685, -0.20538871, 0.3089118, 0.4315903, -0.13524854, -0.10791581, 0.3315688, 0.13135147, -0.26904663, 0.142365) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.13619833, 0.045271892, -0.029841429, 0.010704955, -0.29257727, -0.10563375, 0.35345638, -0.06734038, -0.043791633, -0.0056891907, -0.078411415, 0.075443126, -0.05746597, -0.19959894, -0.12797245, 0.18837726) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.25673476, 0.120482095, -0.23827696, -0.13557845, 0.300447, -0.3008584, -0.13834439, 0.5459493, -0.26155484, 0.06905137, 0.16247983, 0.039960653, -0.023218757, 0.07977591, -0.11354706, -0.25831422) * go_1(0.0, -1.0);
|
||||
result += mat4(0.0842605, 0.282916, 0.14062001, 0.06356874, 0.55912817, 0.1743876, -0.30324093, 0.052068707, -0.20756413, 0.27321506, -0.26560605, -0.27695876, -0.3927334, -0.5439608, 0.39293098, -0.001130203) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.021890296, -0.12703396, 0.06660714, -0.03164527, 0.0018722567, -0.26552317, 0.06978973, -0.24030049, 0.46008193, 0.5595346, 0.081981994, -0.038414747, -0.010446991, -0.56102365, -0.079274766, -0.01851302) * go_1(0.0, 1.0);
|
||||
result += mat4(0.052988984, 0.030581746, -0.06868741, 0.21545182, -0.5706256, -0.0034910638, 0.48361364, 0.9020033, -0.02242781, -0.13256042, 0.08997955, 0.21001706, -0.059571438, -0.040119104, -0.05029196, -0.127414) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.08275339, -0.05999088, 0.11068767, 0.014646892, -0.041986465, 0.1028236, -0.17218924, 0.026559748, -0.17412743, -0.38364175, 0.17410514, 0.13038695, 0.23155633, 0.2655843, 0.045085523, 0.13005458) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.013383197, -0.064526096, 0.049046878, 0.015992291, 0.123987064, 0.0104690585, 0.07065378, -0.009824511, -0.036109775, 0.13384768, 0.29676288, -0.39475223, -0.009368096, -0.05666906, -0.09132696, -0.082638375) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.106538564, -0.065693766, -0.03790106, 0.04776706);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(S)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.024004154, -0.26474997, -0.5256586, 0.051624652, -0.16621786, 0.2964122, 0.6044247, -0.14335106, 0.17002718, -0.2679876, -0.30162668, 0.1273794, -0.17601459, -0.1782376, 0.104725115, -0.16351137) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.121676154, 0.047741555, -0.06738679, -0.056402843, 0.004424971, -0.35099635, -0.073440626, 0.039784692, 0.15204315, -0.1165704, 0.11231046, -0.27369732, 0.33737272, -0.11880767, 0.09637475, -0.14709689) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.017987821, -0.08798823, -0.062515825, -0.046803873, -0.05871703, 0.27013004, 0.19397618, -0.052147817, 0.003271283, -0.0029015478, -0.07390092, -0.09348337, -0.1574738, 0.06750957, -0.07661155, 0.054327156) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.15215784, -0.72508365, -0.3202069, 0.20295432, -0.19125701, 0.021401431, -0.051837035, -0.025939213, 0.25565025, -0.12872623, 0.13169816, 0.27377388, -0.008718429, -0.05864064, 0.028844763, 0.1144993) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.30012092, -0.1322455, -0.11868545, 0.09857058, 0.082795605, -0.075334676, -0.3752773, -0.02918163, -0.67764, -0.38598236, -0.21023573, 0.38274166, -0.07398165, -0.07213789, -0.28427607, 0.1266569) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.37507388, 0.18809201, -0.21982779, 0.27208912, 0.022066567, -0.27627763, 0.12345216, -0.30041683, 0.017002959, -0.091398515, -0.25207692, -0.29253414, -0.08231422, -0.14665812, -0.07868529, -0.24562219) * go_0(0.0, 1.0);
|
||||
result += mat4(0.08686712, 0.080837384, 0.20736577, 0.008233064, 0.14957365, 0.21801959, -0.04870689, 0.42149112, 0.27255878, 0.33320278, -0.08467146, 0.10381615, 0.055278245, 0.085710146, 0.009097151, 0.29092705) * go_0(1.0, -1.0);
|
||||
result += mat4(0.0012207404, -0.023874281, -0.027035477, 0.005157451, 0.19330226, 0.33711615, -0.16495204, 0.549021, 0.44879642, 0.1978837, -0.20492741, 0.28099406, 0.2631811, 0.40786585, -0.055340275, 0.2575511) * go_0(1.0, 0.0);
|
||||
result += mat4(0.29127392, -0.06287165, 0.12715077, 0.14784902, -0.3183704, 0.42057636, -0.11483724, -0.3019506, 0.010730576, 0.29091576, -0.046116166, -0.23528357, -0.0037143505, 0.1191774, -0.06084074, 0.011641706) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.2579205, 0.036545023, 0.11691888, 0.04996418, 0.21318026, 0.21370813, -0.14114271, 0.031217605, -0.06979331, -0.0690704, 0.04618086, 0.025164584, -0.10994228, 0.109930746, 0.103678934, 0.12193115) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.19843774, -0.11237926, 0.007291354, 0.16480611, -0.15669724, 0.46283355, 0.077065215, 0.112273656, 0.17143534, -0.19934891, -0.25481275, 0.034591813, -0.27032652, -0.2702769, 0.04816228, -0.031614583) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.16307239, -0.11295217, 0.05861256, 0.14225823, -0.015648091, 0.11741865, 0.113366075, 0.023935538, 0.19560932, -0.10553561, -0.042583376, -0.048160724, -0.3116519, 0.13957061, -0.0044852323, -0.015472912) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.15629178, 0.06463271, -0.13176678, 0.025518289, -0.021733627, 0.22236359, 0.019508492, -0.11629477, 0.10801276, -0.021957984, -0.11272639, -0.03615053, -0.121420704, 0.2520835, 0.043395765, 0.1699031) * go_1(0.0, -1.0);
|
||||
result += mat4(0.2886654, 0.21755892, 0.21757497, 0.08442575, -0.109903164, -0.67295986, 0.22886126, -0.027185453, 0.3761606, 0.23199768, 0.05908783, -0.1496158, 0.10832971, -0.3530352, 0.20234483, -0.07615918) * go_1(0.0, 0.0);
|
||||
result += mat4(0.11043024, 0.18943349, 0.42394367, 0.029350199, -0.15085667, 0.020204183, -0.081609115, 0.07907012, 0.33805525, 0.0066280114, 0.0018284445, 0.022983696, 0.004984607, 0.0429299, -0.14568979, -0.29143327) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.16376027, -0.20387048, 0.06522074, 0.17484841, -0.13885716, -0.04380927, -0.03535832, -0.16978237, -0.004799155, -0.25407305, -0.039976966, -0.011992087, -0.22535577, -0.09583549, 0.0334331, 0.016292758) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.38688713, -0.20232083, 0.23887886, -0.10438324, -0.24170811, -0.074868314, 0.03977399, -0.22810821, -0.08257971, -0.11902456, 0.106009185, -0.078289054, -0.11932821, 0.024207884, 0.10070917, 0.79348284) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.4018743, 0.050456528, 0.035341598, -0.03788609, 0.12964934, -0.44461823, 0.029031694, 0.29604837, -0.102386944, -0.13805065, 0.0055692918, 0.14659804, -0.22499937, 0.14680648, -0.3443954, -0.06994176) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.0063428865, 0.0057986965, -0.12526293, -0.059240736);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(S)-Conv-3x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.08631539, 0.09499331, 0.065609254, 0.0, -0.023760278, -0.027293118, -0.022839671, 0.0, -0.012447854, -0.008565141, -0.012041815, 0.0, -0.033292875, -0.031266093, -0.02874347, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.08709062, 0.09760889, 0.08988583, 0.0, -0.09099671, -0.102120616, -0.098076016, 0.0, 0.057814583, 0.06999608, 0.05961344, 0.0, 0.12246188, 0.1319784, 0.12254915, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.07694916, 0.0822054, 0.07549296, 0.0, -0.046808865, -0.051509347, -0.035890795, 0.0, 0.01599848, 0.014677793, 0.0086143715, 0.0, 0.033142705, 0.0426565, 0.035911378, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.0008269902, 0.0009082343, 0.014101725, 0.0, 0.0006387551, 0.005079344, -0.013034868, 0.0, 0.013909732, 0.011026747, 0.012485332, 0.0, 0.027028518, 0.022164145, 0.03183532, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.33575395, -0.36700967, -0.34140685, 0.0, 0.35850254, 0.37535715, 0.34613726, 0.0, -0.12680013, -0.1256115, -0.112494245, 0.0, -0.061541136, -0.059120018, -0.06552594, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.047570463, -0.050335366, -0.04665491, 0.0, -0.110970475, -0.12363716, -0.11072252, 0.0, 0.041563414, 0.059771337, 0.045290247, 0.0, -0.17999935, -0.19700716, -0.17459513, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.078488424, 0.07483357, 0.08347933, 0.0, -0.0063715233, 0.00035415235, -0.010886946, 0.0, 0.031237155, 0.02512343, 0.034399323, 0.0, -0.023146842, -0.026732154, -0.027644241, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.05906883, -0.06784104, -0.04506148, 0.0, -0.003939601, -0.0011749315, -0.006256036, 0.0, -0.1662408, -0.16871658, -0.16598499, 0.0, 0.051277652, 0.04837499, 0.05120855, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(0.08158806, 0.08674548, 0.07437206, 0.0, -0.05765347, -0.06196418, -0.057311118, 0.0, 0.26747537, 0.2668808, 0.2389857, 0.0, -0.010376844, -0.01690028, -0.008414153, 0.0) * go_0(1.0, 1.0);
|
||||
result += mat4(0.030539425, 0.02415435, 0.039969034, 0.0, 0.006491679, 0.014436586, 0.005435709, 0.0, -0.0058292216, -0.013982021, -0.011243379, 0.0, 0.025942149, 0.015361476, 0.019134998, 0.0) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.06322247, -0.07146787, -0.06673042, 0.0, 0.028702464, 0.039047733, 0.039646607, 0.0, -0.072553575, -0.08046175, -0.07027197, 0.0, -0.1447189, -0.1539398, -0.1466465, 0.0) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.046430312, -0.054549117, -0.048076343, 0.0, 0.032971155, 0.02980819, 0.029172963, 0.0, -0.017612953, -0.015100736, -0.01202649, 0.0, -0.026717246, -0.028401854, -0.034548033, 0.0) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.0020459262, -0.0008748501, -0.012601956, 0.0, 0.0054226154, 0.008867029, 0.018921215, 0.0, -0.0021330053, -0.0036601655, -0.0022091097, 0.0, -0.08636891, -0.10203159, -0.09741449, 0.0) * go_1(0.0, -1.0);
|
||||
result += mat4(0.07306159, 0.08245483, 0.06548199, 0.0, -0.1933229, -0.20326294, -0.19189309, 0.0, 0.107496604, 0.11584994, 0.10907522, 0.0, 0.30877885, 0.31297725, 0.30890995, 0.0) * go_1(0.0, 0.0);
|
||||
result += mat4(0.03192904, 0.035112645, 0.033732817, 0.0, 0.074100636, 0.08349646, 0.06659352, 0.0, -0.1136165, -0.12470947, -0.11192198, 0.0, 0.14465587, 0.16328491, 0.13984151, 0.0) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.05098033, -0.053096622, -0.05533725, 0.0, 0.0045651463, -0.007682458, 0.0026934785, 0.0, -0.021199327, -0.016210148, -0.030939564, 0.0, -0.031621892, -0.046702545, -0.02647333, 0.0) * go_1(1.0, -1.0);
|
||||
result += mat4(0.055801813, 0.06430485, 0.05052402, 0.0, 0.0241233, 0.013879883, 0.017344628, 0.0, 0.08707151, 0.10031039, 0.095042154, 0.0, -0.109053336, -0.11414017, -0.111838564, 0.0) * go_1(1.0, 0.0);
|
||||
result += mat4(0.030582374, 0.03604719, 0.040417343, 0.0, 0.038665913, 0.036998056, 0.030004544, 0.0, 0.09209076, 0.10010001, 0.08389406, 0.0, -0.014655714, -0.0074866647, -0.012227013, 0.0) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.008303841, -0.008251826, -0.0069884053, 0.0);
|
||||
return result + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,873 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.14361712, -0.16690509, 0.37253398, -0.45202538, -0.21331833, -0.32675815, -0.33971128, 0.20261937, -0.20606318, -0.215143, -0.079716705, 0.15640882, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.17360486, -0.3435545, 0.08199117, 0.56259036, -0.120246716, 0.24312893, -0.021436244, -0.11864853, 0.19452724, 0.106943935, -0.077393375, -0.3503661, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.072465785, 0.2772823, 0.25493625, 0.3098145, -0.115831695, 0.072458096, -0.014782132, -0.15310249, 0.12178311, -0.015555423, -0.2229811, 0.16469522, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.18652022, -0.30702665, -0.59921896, 0.079824045, 0.4426619, 0.049343713, 0.44902903, -0.2711445, 0.20470268, -0.029203767, 0.29092675, 0.15562426, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.21041247, 0.48450592, -0.110547826, 0.3842122, 0.5303875, -0.26512837, 0.19846216, 0.045673862, 0.12773214, -0.05117536, -0.03510946, -0.30123934, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.3186735, 0.052702922, -0.12499774, 0.055628903, -0.16476867, 0.12642322, -0.18314636, 0.018323101, -0.3609603, 0.25649396, 0.3185421, -0.0057759956, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.16603558, -0.09259665, -0.28760567, -0.14319661, 0.12511417, -0.12551902, -0.00070228375, 0.20914114, -0.22466865, 0.1064727, 0.32598525, -0.08596318, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.03163653, 0.026722813, -0.4361858, -0.21164834, 0.4176763, 0.08203146, 0.35289326, -0.06128859, 0.20506798, -0.07098943, 0.1807802, 0.2658414, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.09821681, 0.058886815, 0.39192092, -0.06791861, -0.15682612, 0.09503328, -0.23400265, 0.026475023, -0.08800713, -0.043749645, -0.18024494, -0.08045564, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.040999945, 0.075765304, -0.0911532, -0.10705836);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf1
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.16406488, -0.2506693, -0.15592022, -0.05529256, -0.3997277, -0.229681, -0.07762124, 0.1843808, 0.07895815, 0.14437248, 0.219114, -0.048090722, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.2150676, 0.09080163, 0.19598733, -0.40578827, -0.33846557, -0.02518622, 0.037079208, 0.20188439, -0.013777575, -0.2369007, -0.30985412, 0.0411912, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.119948365, 0.23014452, -0.14962277, -0.096262485, 0.09625151, 0.2025487, 0.03933539, 0.12268028, -0.24373281, 0.19730613, 0.11634144, 0.12293635, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.08030697, -0.40114692, 0.21532272, 0.20222071, 0.073098, -0.004463858, 0.02820587, -0.18861918, -0.20994501, -0.12444653, -0.23178193, -0.13965288, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(0.14150894, 0.14563078, 0.697704, 0.20918849, 0.26776335, -0.34291518, 0.06394055, 0.17925078, 0.4165139, -0.042595536, 0.105312675, 0.231854, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.024318576, 0.16668217, 0.0729521, -0.7071404, 0.3121693, 0.37295797, -0.015632952, 0.33763757, 0.00706697, 0.10836652, -0.11132417, 0.292844, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.14489831, 0.0027769986, -0.24509215, 0.5557927, -0.1104541, 0.005070684, -0.020032275, -0.5642205, 0.16048644, 0.07248175, 0.20387374, -0.38145426, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.33140838, -0.007438425, 0.26074782, 0.15947102, 0.219755, -0.14690271, -0.07412696, -0.24176367, -0.2230114, 0.027256912, -0.11255796, -0.05882673, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.19712369, 0.003842208, -0.10893768, 0.09047115, -0.10260409, 0.18662766, 0.009733428, 0.0039940844, -0.006444674, -0.15196493, 0.06641555, -0.06169452, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.029148052, -0.03215124, -0.6175828, 0.057135154);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.05195995, 0.15220909, -0.24354807, -0.109075695, 0.020483498, -0.14830725, 0.0018816335, -0.0072673927, 0.0649385, 0.046050787, -0.10789607, -0.046609525, -0.11455093, -0.009358115, 0.11280759, 0.18053898) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.08619698, 0.091353096, -0.16379662, 0.07822936, 0.072919995, 0.1482446, 0.17846228, 0.04639898, -0.18998149, 0.1653338, -0.44187957, -0.010017503, -0.069953404, 0.08784785, -0.16391355, 0.35095468) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.088297926, 0.27259287, 0.013088447, 0.023461785, 0.10037149, -0.017414214, 0.08559885, -0.10822335, 0.10591637, 0.17240539, 0.15749931, 0.026641782, 0.11889612, -0.018095117, -0.08736018, 0.09934933) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.21426749, 0.0800268, -0.19816414, 0.07693414, 0.026270509, -0.11724047, 0.026078718, 0.13080709, 0.12207936, 0.056103867, -0.323923, -0.111454345, 0.059245165, 0.07257926, 0.032195322, 0.27225617) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.20130268, 0.026809234, -0.0020803472, -0.04394057, -0.1982125, -0.033678252, -0.12881789, 0.0025656687, 0.14193355, -0.2541802, -0.13239717, -0.05983356, -0.029376393, 0.33187667, 0.14438996, -0.21993925) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.12772562, 0.022498213, 0.24753313, 0.07440761, -0.17564529, 0.09971503, -0.013372, 0.09459552, -0.21597451, -0.40116546, 0.23446435, 0.1515452, 0.050813515, 0.19662157, -0.10604596, -0.24638489) * go_0(0.0, 1.0);
|
||||
result += mat4(0.23866327, -0.2706382, -0.07480157, 0.03789501, 0.117716484, -0.095995456, -0.0435066, 0.013025061, -0.029759895, -0.036287807, 0.08570493, 0.030151363, 0.18863682, -0.27228612, 0.020479294, -0.07058746) * go_0(1.0, -1.0);
|
||||
result += mat4(0.0026758043, -0.20750894, 0.2802277, -0.07761428, -0.012089615, -0.112726666, -0.03867965, -0.085082226, 0.034227375, 0.19662802, 0.26272395, 0.036822405, -0.23040786, -0.20173554, 0.07110236, -0.26939383) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.14012688, -0.067249745, 0.14726773, -0.0070919944, 0.19275497, 0.04460783, 0.18776374, -0.019941995, -0.076159865, 0.002261728, 0.238768, 0.039375026, 0.13200568, -0.023286859, 0.034387972, -0.01827453) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.0107542025, -0.13001555, 0.06596806, -0.03370635, -0.024291076, 0.10367739, -0.03396605, 0.041960735, 0.16230568, 0.024845246, -0.016806586, 0.22547007, -0.025378102, 0.064547986, -0.2113137, 0.042272836) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.2219356, -0.049535394, 0.10289468, 0.14175911, 0.013058568, -0.15909089, -0.02546921, 0.11721571, 0.13020545, 0.39660174, -0.07601573, -0.16366366, -0.023935124, 0.06681424, -0.26143414, -0.07485668) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.1405031, -0.0645044, -0.15865614, 0.1829069, -0.22526503, 0.08991175, 0.041972812, -0.012462953, 0.3022753, 0.19457603, 0.022607598, -0.25460255, 0.028327515, 0.14420614, -0.077984214, 0.09278112) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.13224132, 0.13115089, -0.188987, -0.19428022, -0.080641985, 0.20909777, 0.067079, -0.19832124, 0.13150498, 0.04450851, -0.2770351, -0.010381239, 0.32295567, 0.04445836, 0.030657565, 0.020271502) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.08188993, 0.039709873, 0.16059989, -0.13279189, 0.11389818, -0.071865685, 0.09312801, -0.08816363, -0.65844774, -0.6854379, 0.21431407, 0.597198, -0.3734657, -0.116027676, 0.015932929, -0.0653176) * go_1(0.0, 0.0);
|
||||
result += mat4(0.24136105, 0.21444799, -0.14235207, 0.08445492, 0.017335927, -0.49877876, -0.06224622, 0.1571534, 0.035594277, 0.059829034, 0.087631516, -0.17090686, -0.005452869, 0.13786094, 0.27586326, 0.046760406) * go_1(0.0, 1.0);
|
||||
result += mat4(0.095078, 0.30310658, 0.010268592, 0.18540539, -0.20722823, -0.0005848572, -0.06464327, -0.111019135, -0.07837157, -0.12183798, -0.09187498, -0.3368629, -0.08216629, -0.20095807, 0.009563313, 0.024838416) * go_1(1.0, -1.0);
|
||||
result += mat4(0.28712475, 0.0641969, -0.034764312, 0.13600683, -0.09211094, 0.009699817, -0.001104855, -0.026146285, 0.33425868, -0.16132632, 0.18051304, -0.104004376, 0.20768233, 0.0888418, 0.050057285, -0.020228952) * go_1(1.0, 0.0);
|
||||
result += mat4(0.11642946, -0.021900529, -0.08910504, 0.15492517, -0.19726521, 0.1434987, -0.24708387, 0.006737377, 0.11353539, -0.15897587, -0.029491093, 0.06002862, -0.09640613, -0.11342702, 0.21375169, 0.0062719737) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.15513068, -0.3151456, 0.20799752, -0.07449935, -0.09226967, 0.112302735, -0.16211908, -0.37986508, -0.27418482, -0.10445544, 0.21112369, -0.06780466, -0.062341, 0.07758948, -0.012719117, -0.16481343) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.16382848, 0.14490448, -0.012869055, 0.1804095, -0.05304844, -0.14624795, -0.14816979, -0.17435774, 0.25356865, 0.11435022, 0.19412366, 0.19499794, -0.10189348, 0.023880519, 0.16822465, -0.17454338) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.04854064, 0.11944563, 0.022984248, -0.0852543, -0.0077684796, -0.044182744, -0.02888099, 0.27452356, -0.07887827, -0.15155658, -0.12841311, -0.21202831, -0.18533322, -0.05852455, 0.0761054, -0.22115342) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.21520375, 0.11415518, 0.18909843, -0.16420493, -0.20909967, -0.3257246, 0.29332343, -0.029541709, -0.1679851, 0.14073059, 0.32720464, 0.13311239, -0.0021121972, -0.08773544, -0.045532625, 0.36960867) * go_2(0.0, -1.0);
|
||||
result += mat4(0.58407414, -0.23632582, -0.16739567, 0.264173, 0.09584864, 0.18455075, 0.20051196, -0.04616608, 0.13441175, -0.0055764276, -0.08625195, 0.097847305, 0.19565724, -0.12183587, -0.11488796, 0.2520169) * go_2(0.0, 0.0);
|
||||
result += mat4(0.01584208, -0.31471413, 0.017104283, 0.0682452, 0.18728764, 0.042960413, 0.06437809, -0.14483811, 0.13882554, 0.016576322, -0.029599546, 0.034904055, -0.20939542, -0.10213055, 0.08821727, 0.0030552552) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.2973797, 0.15791039, 0.10811437, -0.07947077, -0.26328024, -0.061920475, 0.12498813, 0.100570425, -0.018922925, 0.002256239, -0.094379805, -0.032315314, 0.48677605, -0.04879864, 0.028028104, -0.14557233) * go_2(1.0, -1.0);
|
||||
result += mat4(0.016148027, 0.13884154, -0.19554809, -0.006344376, -0.013450252, 0.2581758, 0.10643088, 0.23465036, -0.078438915, -0.099644944, -0.1442203, -0.2285087, 0.33528957, -0.17052084, -0.26595074, 0.14794162) * go_2(1.0, 0.0);
|
||||
result += mat4(0.041404825, -0.0813985, -0.19863169, -0.008302881, 0.023570588, -0.043578386, -0.20971186, 0.14654282, 0.048436746, 0.11266723, -0.25812748, -0.03340969, -0.18430679, -0.046258014, -0.007674466, -0.037139155) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.060693484, -0.08285047, 0.06638212, 0.18479855, 0.11099276, -0.14470962, 0.16915078, 0.32247669, -0.10845523, 0.0027510398, -0.014941873, -0.15779859, 0.051481526, -0.14748912, 0.12125527, -0.059839584) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.27571446, 0.01663349, -0.057985745, -0.089736536, -0.09541078, 0.18101417, 0.084854685, 0.11060913, 0.05631825, 0.066835634, -0.02837782, -0.049748126, -0.050051138, -0.05126488, 0.27121767, 0.06331115) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.13630085, -0.03787764, 0.13351586, -0.024081819, 0.10403757, -0.0034796793, -0.04838045, -0.064052396, -0.34672704, -0.06271465, -0.024577484, -0.13450806, -0.013759927, 0.11706738, 0.07913658, -0.016639082) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.023730129, 0.020174952, 0.048988737, -0.013395666, 0.0073305597, 0.059409764, -0.27721968, 0.13349204, -0.022947624, 0.112007216, -0.008175606, -0.14903043, -0.35755506, -0.02145208, -0.021762518, -0.17889674) * go_3(0.0, -1.0);
|
||||
result += mat4(0.19315337, 0.16287236, -0.07667863, -0.020898499, -0.021058874, -0.20849414, -0.3571716, -0.13001479, 0.44977963, 0.016706442, -0.03471178, 0.35189477, 0.3050666, -0.019236205, 0.16278796, 0.3093703) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.1507458, -0.13747548, -0.05822537, 0.16035356, -0.08386089, -0.03476887, -0.0022021863, -0.032772254, 0.17572841, 0.004200287, 0.045312192, 0.27265742, -0.037853006, -0.056344658, -0.3095155, 0.15215549) * go_3(0.0, 1.0);
|
||||
result += mat4(0.11428048, -0.19523771, 0.016499955, -0.03625986, 0.15670861, -0.077859454, -0.059640404, 0.023970904, -0.009806148, 0.0904747, -0.006978744, 0.15938658, 0.030886533, 0.13507655, -0.002613293, -0.1335748) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.20070468, 0.06281564, -0.026250493, -0.042895693, -0.06574456, 0.10412931, 0.12061968, -0.0750467, -0.10865931, -0.05715226, -0.022071969, 0.02608941, -0.21416737, -0.18582128, -0.091236554, -0.044943426) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.057988428, 0.21430638, -0.17991407, -0.051662743, 0.060244065, -0.021494022, -0.018070806, -0.09278776, -0.011404125, 0.064091586, 0.12852973, -0.16610947, 0.08740408, 0.045517463, -0.27932477, 0.11050971) * go_3(1.0, 1.0);
|
||||
result += vec4(0.012687187, -0.11876551, -0.041985378, -0.10110911);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf1
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.07579397, 0.008718031, 0.03874428, -0.022123579, 0.064964466, -0.27502275, -0.0053009577, 0.11669645, 0.007708085, 0.009340055, -0.13001843, -0.03758108, -0.07045759, -0.08749642, -0.21329811, 0.13205966) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.14087188, -0.12068241, 0.046639618, 0.05115712, 0.108357444, -0.05040456, 0.03280633, 0.09336891, -0.055509757, -0.036777936, 0.043575723, -0.041975956, -0.17782387, -0.12977566, -0.0736514, 0.17304243) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.2638534, 0.0385968, 0.14743716, 0.18057759, -0.036564615, 0.107838504, 0.08324167, 0.13403444, -0.41366392, 0.072824344, -0.013165103, 0.06114856, -0.040475495, -0.14222278, 0.10455181, 0.0021660402) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.30221993, -0.06315301, 0.057081617, -0.020285107, 0.053984016, 0.13086873, -0.30863532, 0.028010197, 0.0070908144, 0.19940577, -0.013766302, -0.039389495, 0.28064504, 0.05970737, 0.074613005, -0.10217121) * go_0(0.0, -1.0);
|
||||
result += mat4(0.042094592, -0.1725651, 0.3514404, 0.008126955, 0.08739713, 0.081543595, -0.12912413, 0.0854203, 0.28885832, 0.107783586, 0.22996111, 0.13907135, 0.071920335, -0.15172984, 0.07151959, 0.1406894) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.1072496, 0.03934067, 0.20014063, 0.051399443, -0.29610988, 0.18659018, -0.17761967, 0.08701774, -0.17493258, -0.08035252, 0.03155133, -0.13986085, 0.023490375, 0.083998375, 0.014006612, 0.03860323) * go_0(0.0, 1.0);
|
||||
result += mat4(0.09324427, 0.10990628, -0.18758917, 0.0054821614, -0.09425237, 0.1192338, -0.063183226, -0.15047066, 0.15664004, 0.037881903, -0.06762073, 0.09622682, 0.028449943, -0.25338468, -0.18897526, -0.18360007) * go_0(1.0, -1.0);
|
||||
result += mat4(0.030310342, 0.2083269, -0.04938559, -0.009608655, 0.019751158, 0.12257741, 0.090964966, -0.09864261, 0.058817703, -0.053385522, 0.15931179, -0.10585003, 0.06986225, 0.3435001, -0.33307528, -0.14035752) * go_0(1.0, 0.0);
|
||||
result += mat4(0.13506691, -0.00015406386, -0.15279713, -0.2290177, 0.019568326, 0.41041428, 0.10566904, -0.08350839, 0.19839814, -0.31052053, -0.04471875, 0.07629561, -0.117245845, 0.19819061, 0.1683647, 0.11896638) * go_0(1.0, 1.0);
|
||||
result += mat4(0.06920538, 0.2656798, -0.06529862, -0.1695985, -0.21614018, 0.17208195, 0.123307765, -0.061470803, 0.07827313, -0.18543327, 0.0937214, 0.098630935, -0.17667519, -0.01978596, -0.09126346, -0.034487445) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.030779282, -0.24423946, -0.08623178, 0.1490136, 0.029337894, 0.17548573, -0.05990294, -0.29123273, -0.10020608, -0.3527181, -0.105286725, 0.27502912, -0.25686985, 0.18521136, -0.110095225, -0.07999611) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.03266192, 0.045139533, -0.03275437, -0.13748369, 0.15633966, 0.089048125, -0.07592367, -0.09013536, -0.18907873, 0.08265683, -0.069233745, 0.27151683, -0.0647864, -0.15308899, 0.021954, 0.05528693) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.10284642, -0.14667438, 0.18669777, 0.053000864, -0.12383836, -0.037600834, 0.29438737, 0.04739594, 0.07846367, -0.11676573, -0.048153553, -0.34298027, 0.028358897, 0.119508564, 0.08012271, -0.019992562) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.22123314, -0.2223458, 0.002969434, -0.07143056, 0.027859585, 0.010600199, 0.056626067, 0.15160584, -0.16350581, -0.044484995, -0.1805076, 0.33351076, 0.073631234, 0.0167081, 0.15704727, 0.107799366) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.006882137, 0.19744347, 0.041128602, 0.17459555, 0.10376277, -0.12519689, 0.0993647, -0.13044195, 0.10485074, 0.1712284, 0.13369127, 0.24649777, -0.038975652, -0.24550107, 0.19567624, -0.09961197) * go_1(0.0, 1.0);
|
||||
result += mat4(0.24763626, -0.0902329, 0.21201743, 0.078442305, 0.013261817, -0.019013328, -0.07576136, 0.14993069, -0.24216306, -0.05666454, -0.064632, -0.38150248, 0.14649945, -0.020437164, -0.13821694, -0.026110074) * go_1(1.0, -1.0);
|
||||
result += mat4(0.21790951, -0.08288076, 0.011415891, -0.1446542, -0.15910968, -0.21221179, -0.06154624, -0.028623452, 0.10872824, 0.17089185, 0.26339474, -0.42544034, 0.095593184, 0.20962211, 0.0034138034, 0.024243662) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.050784085, 0.06333505, 0.041011192, 0.17474842, 0.14517011, -0.4340653, -0.10313813, 0.12524489, 0.18353751, 0.4589042, -0.037463415, 0.07841999, -0.114173576, -0.10669665, 0.029463472, -0.14393249) * go_1(1.0, 1.0);
|
||||
result += mat4(0.12771326, -0.06622126, 0.08327681, -0.15113758, -0.114005744, 0.059280578, 0.04071302, -0.11074485, -0.23312584, -0.032968838, 0.13736604, -0.15776984, 0.067029156, 0.0580463, 0.20655325, -0.2112593) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.16148107, 0.02879793, -0.24918973, 0.009605728, -0.102177374, 0.050518002, -0.00015101423, -0.046602443, 0.5081422, -0.044740383, -0.06243097, 0.076031074, 0.1157983, 0.03965003, 0.109161526, -0.36589798) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.018941574, 0.000912917, -0.2585099, 0.13668273, 0.062664494, -0.09246434, -0.14594543, -0.11160076, 0.015663203, -0.02447256, -0.070794076, 0.11807077, 0.12931514, 0.14109722, -0.07506544, -0.012781477) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.48816162, 0.16294348, 0.011336221, 0.107038386, -0.01978858, 0.039453425, 0.112853855, 0.007536018, -0.005471479, -0.11315905, 0.032013394, 0.11523904, -0.2504089, 0.04803124, -0.09689627, 0.24372064) * go_2(0.0, -1.0);
|
||||
result += mat4(0.61343086, 0.09531598, -0.24803302, 0.23788263, 0.13495958, 0.24733612, 0.1575427, -0.06863399, 0.2341275, -0.15821049, -0.165848, 0.0290172, -0.010136783, 0.04415787, -0.2619951, 0.09987892) * go_2(0.0, 0.0);
|
||||
result += mat4(0.19411229, 0.24528526, -0.250216, -0.33602244, 0.17639299, -0.052413136, 0.122578874, 0.028618507, 0.25713214, 0.22033587, -0.19680484, 0.028938502, -0.083384775, -0.06476429, 0.036840588, -0.14297847) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.2897587, -0.12176407, 0.19259763, -0.106649496, -0.026704982, -0.036201328, -0.06753124, 0.37967134, -0.20092241, 0.006229027, 0.12085137, -0.09810282, -0.1501556, -0.0099991355, 0.25044358, 0.08538966) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.11304407, -0.24147832, 0.21644448, -0.035938095, -0.036439262, -0.042730987, -0.04384442, 0.10325233, -0.32405272, -0.11873838, -0.15075137, -0.036929503, -0.10808143, 0.25799102, 0.13749036, 0.5451476) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.24142508, -0.04895773, 0.09022442, 0.2821465, -0.06298706, -0.1807906, 0.02960867, 0.22310257, -0.1915311, 0.2900501, 0.1670845, -0.080343634, 0.25779882, -0.27144584, -0.23575482, -0.14724477) * go_2(1.0, 1.0);
|
||||
result += mat4(0.020742219, -0.10571064, -0.0010137435, 0.14439318, 0.32805952, -0.027505733, -0.07111945, 0.07043296, -0.09525604, 0.03175366, -0.14633068, -0.15810682, 0.18050082, 0.08191363, 0.07047039, 0.0018573351) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.023874652, 0.14996628, 0.11298528, -0.1508891, -0.052415725, -0.02570088, 0.0055150646, 0.16365297, -0.046594325, 0.18095094, 0.09934885, -0.066233225, 0.2404304, -0.112728044, 0.14004207, 0.11369578) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.14799033, 0.025304591, 0.031008242, 0.03795376, -0.15800071, -0.043169834, 0.10797239, 0.17129694, 0.09674189, -0.11010672, 0.07283912, -0.11063907, 0.108249694, 0.025199141, 0.09162024, -0.1827302) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.08983324, 0.07823903, -0.137839, 0.11909572, 0.11996334, -0.05947995, -0.25459376, -0.18159851, 0.044489045, 0.052461334, 0.13674203, 0.12579007, -0.33665392, -0.07313439, -0.013640538, -0.010538632) * go_3(0.0, -1.0);
|
||||
result += mat4(0.0884388, -0.10034604, 0.047238693, 0.12025125, -0.16648497, -0.20305477, 0.08240087, -0.17453992, 0.19033237, 0.28438845, -0.32885036, 0.14011146, -0.13389368, -0.012868356, -0.15273216, -0.19119217) * go_3(0.0, 0.0);
|
||||
result += mat4(0.09196779, -0.13800567, 0.08842335, -0.18658079, 0.17512907, 0.021311145, -0.06347847, -0.13827331, -0.10689703, -0.1707886, -0.15724367, -0.167876, 0.22493233, 0.3070637, -0.035266686, -0.0068385694) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.2739973, 0.07336105, -0.196827, 0.060224827, 0.05752693, -0.014346674, 0.025412507, -0.27530053, 0.27755278, -0.07631679, -0.053861864, 0.113329165, -0.31025892, -0.012681806, 0.06228483, -0.054306302) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.16827694, 0.16333361, 0.068389125, 0.24560109, 0.11659498, 0.052896734, -0.020310031, -0.17830387, -0.07551057, -0.01822214, -0.037451357, 0.24607496, -0.2033962, -0.11107965, 0.05005381, 0.13685274) * go_3(1.0, 0.0);
|
||||
result += mat4(0.13665263, -0.24541081, 0.0012457973, -0.012630116, -0.09559698, 0.17756529, -0.039300505, -0.044217475, -0.22984356, -0.2294885, 0.104534455, -0.04131095, 0.084843494, 0.038027752, -0.106351435, 0.18853655) * go_3(1.0, 1.0);
|
||||
result += vec4(0.010324113, -0.01262194, 0.0762259, -0.014071781);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.06961854, 0.06914646, 0.120440066, -0.04889646, -0.012870159, 0.01994181, 0.052958567, -0.14740478, -0.0027199117, -0.004924673, 0.10131955, -0.11496505, -0.06742836, 0.08287776, 0.11206167, -0.021625644) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.025003597, 0.05389498, 0.14938618, 0.12255602, 0.050963886, 0.16300994, 0.17633909, 0.03229484, 0.2092038, 0.13367431, -0.09538967, 0.1636076, -0.022082182, 0.10898033, 0.0422286, -0.062253885) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.0018258828, 0.08333001, 0.002765037, -0.022241322, 0.1628206, 0.14671557, 0.3001151, 0.030986495, 0.05225914, -0.04880372, 0.15963705, 0.17972782, 0.055128947, 0.114626616, 0.03460699, -0.07679627) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.08866054, 0.0882386, 0.13833097, -0.079257324, -0.03060485, 0.049487974, 0.092268504, -0.17009564, 0.021603461, 0.20750603, 0.18884364, -0.10977116, 0.31758478, 0.053426504, 0.093257, 0.14912026) * go_0(0.0, -1.0);
|
||||
result += mat4(0.13069148, 0.21368778, -0.4405162, -0.009193694, 0.090230525, -0.15897161, -0.005089127, -0.06011075, -0.27336648, -0.021869129, -0.2084852, -0.0850094, -0.10896211, 0.27229342, -0.044210993, -0.03346366) * go_0(0.0, 0.0);
|
||||
result += mat4(0.05807779, 0.08506817, 0.23984064, 0.12547795, 0.036945213, 0.039088245, -0.10716132, -0.15966031, 0.13548918, 0.07746645, -0.248966, -0.15717135, -0.059498273, 0.0088413125, -0.02828682, -0.021795277) * go_0(0.0, 1.0);
|
||||
result += mat4(0.013289853, 0.007272393, 0.06875863, -0.053158432, -0.03578172, 0.20148727, 0.1961931, -0.16910668, 0.03259818, 0.054221123, -0.0326064, 0.06493197, 0.053533003, -0.11878436, 0.14398894, -0.17543368) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.17906332, 0.1111989, 0.047910325, 0.11560207, 0.09790123, -0.2023765, 0.04265116, 0.0075303926, 0.012974969, -0.0853146, -0.04037416, 0.14489946, -0.0716403, -0.055603035, -0.30376709, -0.011667526) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.053314358, -0.012657763, 0.0077033425, 0.12168191, 0.016371705, 0.11979062, -0.08494259, -0.009617431, 0.1303907, 0.043279216, -0.17285421, 0.15823162, -0.030746695, 0.121796146, 0.13097613, 0.0024783302) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.11677548, -0.06592395, -0.022185773, 0.0031006308, -0.00906918, -0.0006412884, -0.00083743286, 0.083697535, -0.060518038, 0.14058606, 0.122444086, 0.17866874, 0.02376487, -0.06369968, -0.026537767, 0.21466877) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.12340551, -0.015656117, 0.051990572, 0.04361656, -0.05291406, 0.10119005, 0.17603071, 0.10464767, 0.03288951, 0.091776796, -0.17373918, -0.12871055, 0.10205503, -0.17783496, -0.17020486, -0.09781929) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.01845568, -0.008877597, 0.14279746, 0.031775143, 0.041680444, 0.08784194, 0.044564564, -0.0011678484, -0.010219994, 0.10472676, 0.046920944, -0.110975444, -0.1197329, -0.11303071, -0.14893234, -0.091113724) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.03856561, -0.12173735, 0.040876064, 0.13847597, -0.14995924, -0.13332345, 0.18687452, -0.22562599, 0.08920785, -0.0017916666, 0.019448435, 0.2306492, -0.054546747, -0.1465318, -0.10628867, -0.0073827514) * go_1(0.0, -1.0);
|
||||
result += mat4(0.12689775, 0.11765595, 0.13039489, 0.06940679, 0.2672624, -0.03880143, -0.11693099, -0.05516293, -0.09665274, -0.2583138, 0.22954193, -0.19324702, -0.39629623, -0.35457405, 0.10052407, -0.19756024) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.06307673, -0.096393906, -0.0075868783, -0.25133502, 0.03436604, -0.008201423, 0.06386583, 0.106548436, 0.014626536, 0.03485315, -0.043418273, -0.1141408, 0.005102567, -0.11701804, -0.01645601, -0.057083) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.019062268, 0.020416953, -0.08854219, -0.037497565, 0.09449262, -0.09127615, -0.063330196, 0.08736769, -0.12394077, -0.17950213, -0.11101161, 0.16013645, -0.09370585, 0.0047447495, -0.04288296, 0.00314098) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.08263743, -0.14441489, -0.14886282, -0.05694989, 0.4254853, 0.10864832, 0.26322174, -0.042006254, 0.24269578, -0.053833783, -0.11558995, -0.066605136, -0.064816564, -0.25914803, -0.017624624, 0.0402331) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.100058846, -0.030422715, -0.19600148, -0.13322774, 0.1796998, 0.087852575, 0.07324559, -0.0047889417, 0.007248384, 0.08930289, 0.09643387, -0.0060126656, 0.16357517, -0.06628222, 0.030618697, 0.097391844) * go_1(1.0, 1.0);
|
||||
result += mat4(0.09539377, -0.10802722, -0.014952347, 0.1683223, -0.03919409, 0.041155327, -0.012186347, -0.030456683, -0.015024977, 0.061710294, 0.00049987395, 0.27338788, 0.04845922, -0.014114694, -0.06371904, 0.008664) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.063082814, -0.02755945, -0.15663072, -0.053271208, 0.070173115, 0.038125586, -0.11840675, -0.016337764, -0.07963128, -0.06404943, 0.23033784, -0.007848355, -0.04434174, -0.092422634, -0.013985954, -0.038096108) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.037121523, -0.020622304, 0.086708754, 0.045878958, -0.13188364, -0.022858748, -0.22411314, -0.08116162, 0.048863005, 0.039260563, -0.04934298, 0.11015131, 0.028177079, 0.025245499, 0.1067935, 0.15324049) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.068235874, -0.14401375, -0.032677606, 0.02996807, -0.11290208, 0.114133574, -0.09627152, 0.053930115, 0.14560424, -0.15935057, -0.13495773, 0.29710987, -0.23231608, 0.14334352, 0.070753984, -0.08189047) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.22378983, -0.09858718, 0.30114698, -0.0048736916, 0.02198528, 0.21444769, -0.11228022, -0.14812283, 0.092372194, 0.1598949, 0.2534843, 0.4932573, -0.16642319, 0.12972073, -0.04147445, -0.09365905) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.132199, -0.0798279, -0.18289213, -0.15133642, -0.033057958, 0.007495456, 0.070398286, 0.049111973, -0.03361502, 0.032059964, 0.003850814, 0.22922683, 0.20279214, -0.07350396, 0.27681342, 0.11891455) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.095355205, -0.08533997, -0.043466177, 0.03183743, 0.0048090555, -0.07969942, -0.044769235, 0.15350139, 0.06485437, -0.027922742, 0.0850892, 0.00069019396, 0.035737295, 0.20380683, 0.03413393, 0.025630401) * go_2(1.0, -1.0);
|
||||
result += mat4(0.26616514, -0.024066277, 0.09220501, 0.09643391, -0.014585791, 0.22894275, -0.053128377, -0.08719867, -0.08819027, 0.01932318, -0.113633566, -0.15435793, 0.10542983, 0.029819246, 0.33675614, -0.059085276) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.031325538, 0.040770013, -0.049561024, -0.2095101, -0.09537227, -0.075998954, -0.04323478, -0.05470401, -0.110066876, 0.059249427, -0.042351052, -0.047700178, 0.21932366, -0.12850443, 0.035361454, 0.013699006) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.08417607, 0.113477044, 0.03574209, 0.007835156, 0.2021717, 0.030678429, 0.19313626, -0.03506592, 0.04233059, -0.08540689, -0.07128929, -0.13245375, -0.08918939, -0.042622462, 0.19011301, -0.18228586) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.19981891, -0.16255717, 0.042949058, -0.06921157, 0.279451, -0.11536949, -0.13747527, -0.10020231, -0.013784027, -0.06727259, 0.3556115, 0.08460814, -0.15348805, -0.07692103, -0.018658075, 0.0037634284) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.09063814, -0.036312047, 0.13528036, 0.0070792423, 0.11834377, 0.02331524, 0.09386154, 0.07144935, 0.033078104, -0.1397121, 0.09283168, 0.2118868, -0.06313442, 0.032146804, 0.0060367053, 0.005822348) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.035949346, 0.06469895, -0.0051385965, -0.078584194, 0.43195483, 0.0045206803, -0.24012396, 0.21436183, -0.013394304, -0.04198491, 0.06645506, -0.23869638, -0.02311661, 0.06589808, 0.16800866, -0.21120183) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.24937367, -0.042277586, 0.08117994, 0.3105402, -0.26087892, -0.10325264, -0.08689298, 0.0064907144, 0.031937066, 0.09783758, -0.9514562, -0.104631096, 0.27990052, 0.36389935, 0.057687905, 0.14072314) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.19865227, 0.09398578, 0.06911146, 0.13077813, 0.024283953, -0.0036808057, -0.036725305, -0.024085987, 0.061556816, 0.0029027078, 0.24621862, 0.112107046, 0.068239614, 0.052718107, 0.20803368, 0.065064415) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.055511028, -0.08662344, -0.074801624, -0.021917107, 0.18730342, 0.047116343, 0.14872652, 0.10580926, 0.16962165, 0.16628978, 0.17343876, -0.1697205, 0.047853447, -0.22705628, 0.031780355, -0.09273609) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.17306295, -0.067308225, -0.17174196, -0.13221754, -0.24622467, 0.029901514, -0.12799668, -0.04145667, -0.14546, 0.013308366, 0.028113116, 0.1678875, 0.07922657, -0.015584258, 0.17059629, 0.07330948) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.09916512, 0.0623665, -0.022458963, 0.061962493, 0.18569344, -0.06590287, 0.111395456, 0.08477448, -0.03609452, 0.024279302, -0.083497405, 0.06459743, -0.22963138, -0.12262581, 0.006980887, -0.06653474) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.023354841, 0.0019475977, -0.0705355, -0.08216019);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf1
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.13703531, 0.06135254, -0.05032855, 0.0039429665, -0.05997914, 0.03737832, -0.09703001, -0.08112204, -0.096779875, 0.086732335, 0.03021232, -0.14636067, 0.079296306, 0.006656948, 0.08904937, 0.06196539) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.26374274, 0.16698441, -0.08554561, 0.03734819, -0.08525629, 0.12257442, 0.015473835, 0.13266069, 0.008439022, -0.05002345, 0.03232084, 0.17349075, 0.014541135, -0.10353582, 0.13339484, -0.13474584) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.05637785, -0.049726896, 0.06597188, 0.0058668824, -0.10623723, 0.13441847, 0.015975956, -0.07811197, 0.05975957, -0.062021587, -0.06533749, 0.083735935, 0.02666556, 0.029904561, -0.0102926055, -0.10931666) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.22616413, 0.042830274, -0.116208926, -0.053796053, -0.1112898, 0.20703097, -0.34109348, -0.065111674, -0.17255561, 0.16784647, 0.00193431, -0.043237597, -0.02353095, -0.1302526, 0.05119598, 0.01403269) * go_0(0.0, -1.0);
|
||||
result += mat4(0.086109385, -0.053006437, -0.24992542, 0.007938272, -0.0027849772, 0.09198081, -0.17596659, 0.030577915, -0.31807357, -0.29618275, 0.0056317504, 0.3662508, 0.16753437, -0.12481447, -0.057597708, -0.14973637) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.14585754, 0.027715279, -0.039035518, 0.11505972, 0.0038059987, -0.20368981, -0.014822689, 0.094012834, -0.20693347, -0.37216228, -0.12690443, 0.2727411, -0.15475404, -0.01948714, -0.12414737, 0.10378582) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.11750072, 0.051394574, -0.011073509, -0.1100907, -0.1389209, -0.10706716, 0.0017484069, -0.059556484, -0.20038931, 0.24976069, -0.011129469, -0.080446415, 0.19259459, -0.14515446, -0.07275811, 0.039244935) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.101780266, 0.003889027, 0.010705813, 0.011088775, -0.20406786, -0.009807119, 0.23070864, -0.030722639, -0.012015954, 0.025211284, -0.29246482, 0.04907962, -0.10485314, 0.21213223, 0.15788344, -0.014188987) * go_0(1.0, 0.0);
|
||||
result += mat4(0.1546438, -0.15895118, 0.010730076, 0.034053337, -0.018741185, -0.008467293, 0.13143812, 0.022905342, -0.27543658, 0.3054419, 0.07025048, 0.29454592, -0.0032350307, 0.01671764, 0.081928045, -0.10051137) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.014834404, 0.07487839, -0.16554666, -0.04127725, 0.15239598, -0.017607473, 0.09927426, 0.15027349, -0.2073968, 0.041613225, -0.10290223, -0.12565911, 0.022021815, -0.07609557, -0.16338238, 0.04468512) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.01768976, 0.0637369, 0.006542782, -0.0022799321, -0.14728844, -0.058199093, -0.029928437, 0.079634584, 0.095769696, -0.13526416, 0.20718366, -0.10116214, 0.1688786, -0.08906526, 0.020397741, 0.06541649) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.033067044, 0.10095467, -0.13792777, 0.022673525, -0.012797848, -0.11222105, 0.11443862, 0.04893716, 0.11389547, -0.07337629, 0.21447009, -0.032212257, 0.23070163, -0.18156143, 0.14542435, -0.10207653) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.22985588, 0.012290226, 0.018557416, -0.064000085, 0.012936774, -0.104329854, -0.0719669, 0.24160251, 0.03716294, -0.093069404, -0.12110873, 0.013251573, -0.12731232, -0.1995954, -0.07679729, 0.06823493) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.23359679, -0.052702624, -0.08710696, 0.19826421, 0.12880315, 0.19875911, -0.20581602, 0.32980308, -0.14479029, 0.099422045, 0.44737315, 0.13044962, 0.12935589, -0.13621494, 0.14902137, 0.09162335) * go_1(0.0, 0.0);
|
||||
result += mat4(0.10801082, -0.22644557, 0.035719793, -0.12396268, 0.2906566, 0.119107775, -0.15470679, 0.17997102, -0.12866725, -0.12695445, -0.06832712, 0.017622665, 0.08215481, 0.065239124, -0.1256659, -0.06811625) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.097956754, 0.09383762, -0.19813508, 0.0035260199, -0.14278924, 0.0660843, 0.19110036, 0.11025648, 0.15489757, 0.011157471, -0.16014035, -0.050144047, 0.0032884583, 0.061513808, -0.03385016, -0.08534137) * go_1(1.0, -1.0);
|
||||
result += mat4(0.09499595, 0.04162155, -0.26091605, -0.18066265, -0.21523187, -0.036668014, 0.09586408, 0.059850723, -0.10890033, 0.28857672, -0.32993382, 0.05107536, 0.012024929, -0.27968574, 0.15081042, -0.07215633) * go_1(1.0, 0.0);
|
||||
result += mat4(0.15673614, -0.064684846, -0.13838115, 0.1264376, -0.23772664, 0.11594999, 0.0898036, -0.092647165, 0.26081505, 0.05110054, -0.017965768, 0.06740709, -0.24977967, 0.05645255, -0.08204664, 0.0435078) * go_1(1.0, 1.0);
|
||||
result += mat4(0.02560865, -0.1613835, 0.05876215, 0.101586774, -0.00058163394, 0.0013674656, 0.039857507, -0.002919488, 0.05573127, -0.04311352, 0.05305971, 0.10097247, 0.036392104, -0.025071293, 0.029137935, -0.08593101) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.12406646, -0.21399136, 0.05611706, 0.021867402, -0.037916705, 0.05941278, 0.11277805, -0.12387807, 0.008577062, -0.045022104, 0.16465645, -0.07607619, 0.035939474, 0.07221297, -0.13557361, 0.07806311) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.19589397, 0.011909766, -0.01258029, -0.065313555, 0.07366803, -0.0812486, 0.115863465, 0.019752543, -0.15854625, 0.11246406, 0.007201303, 0.0008530298, -0.0287012, -0.036224626, 0.059641607, 0.09416462) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.20361906, -0.20671111, -0.1126041, 0.049152024, 0.17586707, 0.10047246, 0.13149028, -0.16302691, -0.08559989, -0.17756243, -0.0061752857, 0.124775924, 0.020011704, 0.17147969, -0.0003063916, -0.015890911) * go_2(0.0, -1.0);
|
||||
result += mat4(0.11051906, 0.13774526, 0.29333818, -0.029932505, -0.07021508, 0.046212852, 0.11793092, -0.081830084, -0.18609521, -0.108229816, -0.044969153, -0.041069634, -0.13936938, 0.11356429, 0.19260931, 0.093210496) * go_2(0.0, 0.0);
|
||||
result += mat4(0.010555152, -0.15726428, -0.13187453, -0.12396212, 0.17309372, 0.100884624, 0.11547714, -0.030650318, -0.21877939, -0.0015167049, -0.090150684, 0.029793834, 0.1465573, -0.038805004, -0.033211514, -0.04926991) * go_2(0.0, 1.0);
|
||||
result += mat4(0.10250675, -0.030922988, -0.008545946, 0.024706079, 0.105154864, -0.06838902, -0.12627976, 0.032457255, 0.21747419, -0.12865087, -0.056018118, 0.07152061, -0.11214344, -0.029831404, 0.044855718, -0.04316971) * go_2(1.0, -1.0);
|
||||
result += mat4(0.12806997, 0.12385188, -0.06831653, -0.015933594, 0.08645126, 0.013043054, -0.19599608, -0.060719345, -0.23076192, 0.19181651, 0.1292978, 0.036317572, -0.061692618, -0.25434494, -0.10012762, 0.06366783) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.11098094, 0.034632366, -0.053560194, 0.08499573, 0.20842391, -0.020262053, -0.023394845, 0.048971336, 0.10436084, 0.12614205, 0.035942093, -0.07592917, -0.07455495, -0.012119416, -0.011834865, 0.21032205) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.00055114913, -0.06662242, -0.009248925, -0.0024843027, -0.22993802, -0.04828541, -0.08667693, -0.093717255, 0.14400347, 0.030130679, -0.01590651, 0.10399553, 0.14478837, -0.11228224, -0.039653912, -0.042144097) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.011044514, -0.09870122, -0.24879128, 0.111903004, 0.092567004, 0.06100228, 0.0053522107, 0.065252475, -0.18228072, 0.25602147, -0.2863954, 0.103064165, 0.052214783, -0.017557586, -0.07434391, 0.021111684) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.04537496, -0.024985183, -0.15247425, -0.0009907635, -0.09677889, 0.09858206, -0.030702371, 0.03539458, -0.029408665, 0.24335481, -0.1918429, 0.08056781, 0.1548214, 0.2850923, -0.15131058, -0.052048493) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.055409238, -0.13090813, -0.016612396, -0.019183576, -0.18499215, -0.013184845, 0.038750056, 0.10953814, -0.18437819, 0.19183092, -0.09780726, -0.046532292, -0.10841146, -0.17717329, -0.1731886, -0.06741823) * go_3(0.0, -1.0);
|
||||
result += mat4(0.27919188, -0.14904179, 0.22850563, -0.17785722, -0.32835802, -0.19134615, 0.32093298, 0.24667856, 0.51687604, -0.59745705, 0.23057328, -0.41411245, -0.4234339, -0.03083826, -0.13972719, 0.1729651) * go_3(0.0, 0.0);
|
||||
result += mat4(0.042352367, -0.109207705, -0.31047532, 0.08896513, -0.2187999, -0.117951825, 0.060705405, -0.10287316, 0.013815159, -0.023699438, -0.053614594, 0.09065406, -0.15286967, -0.101803675, 0.019537682, 0.12476822) * go_3(0.0, 1.0);
|
||||
result += mat4(0.0016159728, 0.04094818, 0.012745902, -0.051958837, 0.014557628, 0.00061195926, -0.11669799, 0.08763203, -0.27820277, 0.17871988, 0.10634548, 0.05234229, 0.03827577, -0.3117398, 0.027675012, 0.0655132) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.0025006514, -0.1457415, 0.053443488, -0.0050932285, 0.01582735, 0.18783967, -0.066718, -0.15485887, -0.039741408, -0.21280284, 0.1502977, 0.09507925, 0.17178543, -0.014238171, -0.35757875, 0.026410697) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.19434428, -0.079038315, -0.017264817, -0.04004242, 0.0063378955, 0.027904915, 0.02571677, 0.09895997, -0.036605608, -0.19889063, 0.015920812, -0.014095519, 0.4363826, -0.14143194, 0.015463533, -0.1656284) * go_3(1.0, 1.0);
|
||||
result += vec4(0.08523788, 0.052322272, 0.08955637, -0.06945023);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.048841953, -0.010713874, 0.09238948, -0.0789676, -0.093295254, 0.063662216, -0.023454266, -0.06739832, 0.027439933, 0.007399632, -0.03550259, -0.013834889, 0.17168441, 0.06177229, 0.023950668, 0.14574073) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.117296845, -0.07858486, -0.02099164, -0.024150673, -0.11662526, -0.26440877, -0.05449493, -0.13366842, -0.06870016, 0.12457937, 0.25052628, 0.013982828, 0.15127566, -0.031653196, -0.13851896, 0.04148151) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.024360385, -0.31051615, 0.012448293, -0.11265428, 0.06123606, -0.0701936, 0.033618104, -0.064061284, -0.06969811, -0.108838804, 0.014163671, 0.02596177, 0.20071186, -0.0028744373, 0.13663651, -0.05592813) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.13492568, -0.0726796, 0.13431883, -0.085713945, 0.056370113, 0.115660414, -0.14475793, 0.0044200714, 0.027387753, 0.045452334, 0.28178552, 0.017371183, 0.17304336, 0.0582999, 0.14465337, 0.046005037) * go_0(0.0, -1.0);
|
||||
result += mat4(0.064034574, 0.041531377, 0.08218889, -0.44529077, -0.010563538, -0.14926371, 0.051012456, 0.08209141, 0.24089444, -0.225398, -0.22259372, -0.26353076, -0.1687418, -0.11501685, -0.016655196, -0.09882357) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.019985389, -0.19189276, -0.104917, -0.11139956, -0.08406414, 0.031484302, -0.082132496, 0.025829919, 0.07512055, 0.31116992, 0.061163265, -0.074850895, -0.091695994, -0.26492774, -0.06617365, 0.06590624) * go_0(0.0, 1.0);
|
||||
result += mat4(0.1326703, 0.13008863, -0.1659525, -0.058325157, -0.047528613, 0.06777741, 0.06953616, 0.010587038, 0.031675722, -0.08119788, -0.11269768, -0.06225964, -0.26593694, 0.03627298, 0.12866129, 0.17876588) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.29016155, -0.12549841, -0.050858997, -0.088932805, 0.002237332, 0.01287246, 0.30138868, -0.071756564, -0.061206467, -0.11114371, -0.25731218, -0.11551616, -0.069513, -0.004583348, -0.10647163, 0.01981785) * go_0(1.0, 0.0);
|
||||
result += mat4(0.16387528, 0.03450354, 0.03422023, -0.014030813, 0.13418834, -0.010909722, -0.00447121, -0.03082622, -0.23983373, -0.020655053, -0.054034587, -0.07133469, 0.21171515, 0.06268651, -0.1738516, -0.15001713) * go_0(1.0, 1.0);
|
||||
result += mat4(0.040721033, -0.037582736, -0.13819644, -0.123978324, 0.1650318, 0.033942625, 0.17534302, 0.06452234, 0.18384823, 0.0048657497, 0.20220642, -0.0025760103, 0.011163899, 0.027265374, -0.051284578, 0.19202651) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.057493486, -0.031516504, 0.10835143, -0.040618125, -0.07762303, -0.06787725, 0.025559613, -0.0055560498, -0.0017830619, 0.020185964, -0.06656476, -0.008523214, 0.32331157, -0.21633361, 0.15338033, -0.104042485) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.18544987, -0.090446, -0.26797467, -0.082941435, -0.15003708, -0.11446041, -0.0394892, 1.1379096e-05, 0.04978554, 0.3350256, 0.032780237, 0.034625802, 0.0596261, 0.045886245, 0.009002243, 0.04746998) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.17104147, 0.0054165213, 0.09161088, -0.0673989, -0.119282715, -0.09094731, 0.47243354, 0.09914267, -0.13958418, -0.0050379517, 0.14352496, 0.18380567, -0.16128838, 0.08766813, 0.013876981, -0.09808636) * go_1(0.0, -1.0);
|
||||
result += mat4(0.09617889, 0.045525175, -0.2550057, -0.02874332, 0.2743444, -0.20102581, 0.008461914, 0.16626629, -0.13309516, -0.19307104, 0.15780488, 0.15518525, -0.2790243, 0.056782067, 0.16836968, 0.17771688) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.10694667, 0.14490083, -0.037976455, 0.013456577, -0.1166783, 0.060722847, 0.07323464, -0.013812333, 0.03234213, 0.50859296, -0.20670377, -0.019631205, -0.022543924, 0.21776745, -0.093769215, 0.12193299) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.15260598, -0.04798592, -0.02370747, -0.005714705, 0.030857049, -0.16643822, 0.23971851, 0.08117996, -0.069645695, -0.06674784, 0.033509918, 0.06333286, 0.14010383, 0.02218942, -0.036704093, 0.043163314) * go_1(1.0, -1.0);
|
||||
result += mat4(0.14653306, 0.002759894, 0.10548246, 0.24976018, 0.3212893, -0.07108953, 0.14068738, 0.29437128, -0.020556152, -0.17813908, 0.1989112, 0.12182122, -0.19231579, 0.06547012, -0.032785345, 0.089717634) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.23632105, -0.027022298, 0.00586518, 0.01836479, -0.2854795, -0.035417695, -0.07586866, 0.0715673, 0.17984483, 0.11210451, 0.032767817, 0.097993985, -0.010899036, 0.15933803, 0.05454052, 0.06768528) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.017289463, -0.058823984, 0.0807603, 0.32464716, 0.2756627, 0.036061637, -0.034578573, -0.08811335, 0.031841308, 0.11359879, 0.07553143, -0.028648997, 0.057192322, 0.07769366, -0.1998847, -0.06258051) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.0422091, 0.046305113, 0.028377453, -0.031071126, 0.06866086, 0.1538135, -0.009288249, -0.25543538, 0.07067607, -0.114061736, -0.024740022, -0.11824987, -0.17426041, 0.0028396242, 0.12849464, 0.057790644) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.057328146, 0.030677445, 0.07496485, 0.07847613, -0.22358766, -0.15659446, -0.18270054, -0.21316889, 0.084770195, 0.013863274, -0.001335942, -0.04027535, -0.15230416, -0.048156176, -0.04614562, 0.089494966) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.117369525, 0.026577681, -0.1941765, 0.14904885, -0.16210394, -0.19549404, 0.19999947, 0.37138188, 0.14809363, -0.05078633, -0.092692114, -0.08533522, 0.12769112, 0.017061725, 0.104464866, -0.026744602) * go_2(0.0, -1.0);
|
||||
result += mat4(0.0880251, -0.005333869, -0.10327546, 0.30419552, 0.107773595, 0.02335926, -0.19014318, 0.19670166, -0.09443473, 0.10621109, 0.36843884, 0.13197622, 0.24537645, 0.4032842, 0.21791221, 0.08400414) * go_2(0.0, 0.0);
|
||||
result += mat4(0.06408587, 0.15366535, 0.042582024, 0.15629277, 0.028716238, -0.013479061, -0.23052843, -0.2992272, -0.050045617, -0.27255702, -0.038093377, 0.0031149297, -0.05625518, 0.52598304, -0.0845234, -0.09116851) * go_2(0.0, 1.0);
|
||||
result += mat4(0.02294159, -0.011902539, 0.00079296535, 0.030631313, 0.02114366, 0.082455896, 0.09450867, -0.08027284, 0.042443607, 0.15427661, 0.11882799, -0.040319934, 0.23706424, -0.107808165, -0.1730313, -0.06340064) * go_2(1.0, -1.0);
|
||||
result += mat4(0.2645207, 0.002157867, -0.095794424, 0.1141035, 0.08255855, -0.06977906, -0.04348005, 0.27864936, -0.1197219, 0.015997604, 0.09500464, -0.0010631803, 0.07198933, -0.053128377, 0.02176274, -0.001298847) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.045475803, 0.03626341, -0.00891833, 0.17907676, -0.2810277, 0.13725498, -0.02413441, -0.08605496, 0.08306595, -0.012227401, -0.0070282067, -0.019027572, -0.13443586, -0.041331865, 0.029120144, -0.00490357) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.13398282, 0.06475972, 0.2528711, 0.02553969, -0.13428321, -0.03931247, 0.11360386, -0.18912545, -0.3725821, -0.018747944, -0.20893294, -0.012743096, 0.07444533, -0.15381604, 0.29776138, 0.10601149) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.21793252, 0.07817356, -0.109576665, 0.19185133, -0.072846025, 0.04960289, -0.07506936, 0.12839878, -0.0061091883, 0.093669325, 0.009295678, 0.03780657, -0.10901407, 0.1375137, -0.0745914, 0.1468883) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.10739044, 0.30611086, 0.1585515, 0.07903283, 0.05612715, -0.0061900485, 0.13646163, 0.15230569, 0.036846787, -0.15846778, -0.18765065, 0.06611226, -0.07209187, 0.056037188, 0.04302953, -0.03887873) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.05618538, -0.072312586, -0.018046018, 0.049542785, -0.033638306, -0.035169322, -0.25882784, -0.036425237, 0.43763217, -0.07049093, 0.08085481, 0.013634128, -0.2701461, -0.13007875, 0.09603447, 0.2479431) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.02283992, -0.24593964, 0.04616348, 0.023422526, -0.20994014, 0.064769074, -0.07680045, -0.30547765, 0.1518723, 0.31953967, -0.12841515, -0.19525428, -0.0076093865, -0.112106465, -0.04573789, -0.04834478) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.008045419, -0.20285496, 0.15290824, 0.036240693, 0.11959966, -0.15712506, 0.096806675, 0.008780234, -0.19716795, -0.3824029, 0.1376541, 0.13325086, -0.103316806, -0.31788048, -0.071698256, -0.25901568) * go_3(0.0, 1.0);
|
||||
result += mat4(0.13714787, 0.020738773, 0.13716534, 0.12359137, -0.038154524, 0.053202964, -0.12023912, 0.09011213, -0.012448548, -0.026505312, -0.11293235, 0.10613704, -0.39916727, 0.041521315, 0.10659441, 0.027749784) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.26475835, 0.044597875, -0.31229413, -0.17121075, -0.21795374, -0.009583571, -0.13428004, -0.30734754, -0.017038794, 0.113667324, -0.1516075, 0.06525228, -0.13789397, -0.05770066, -0.016166758, -0.29457557) * go_3(1.0, 0.0);
|
||||
result += mat4(0.054183286, 0.022085225, 0.086794585, 0.10968018, 0.1276148, 0.05739452, 0.08860957, -0.08131373, -0.081570424, -0.107991874, -0.03724999, 0.000843539, 0.20231429, -0.123543546, -0.19073018, -0.28328305) * go_3(1.0, 1.0);
|
||||
result += vec4(0.013646388, -0.021442367, 0.0045393505, -0.037433166);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf1
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.13948695, 0.016643738, 0.08168136, 0.02315663, 0.017184775, 0.11487715, 0.05770107, 0.010102888, 0.04955321, -0.045132335, -0.05731744, -0.05798246, 0.2245112, 0.17406365, 0.08979801, -0.10607952) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.2812785, 0.022830509, 0.15164222, 0.13460225, 0.22263442, 0.2558749, -0.122489706, 0.10409658, 0.023308244, -0.19583783, -0.007824269, 0.06256542, 0.11161938, 0.14878923, 0.30865005, 0.08962341) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.20843887, 0.012371968, -0.008279775, -0.042467568, -0.13022369, 0.056743186, -0.018389069, 0.13964763, -0.03361555, -0.053087234, 0.012521351, 0.0209293, 0.015771557, 0.11718523, 0.010176676, 0.021708367) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.14373007, -0.114338934, -0.09077395, -0.11040866, 0.055298284, 0.022516333, 0.18901019, -0.05640152, -0.1413198, -0.08748339, -0.029985962, 0.00712751, -0.071436934, -0.18909407, 0.173448, 0.053675048) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.023129769, 0.42883545, -0.18110612, 0.24296297, -0.02441117, 0.18108079, -0.12298153, -0.19192219, -0.14139178, -0.069563635, 0.1524624, -0.17755614, -0.248875, 0.015161957, -0.16541803, -0.17773613) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.065477535, -0.113195814, -0.08284894, 0.11679537, 0.028445985, -0.026559185, -0.007267581, 0.14052133, 0.14847197, -0.040276285, -0.038166475, -0.030452784, -0.15184602, -0.22223297, 0.113732725, 0.11163395) * go_0(0.0, 1.0);
|
||||
result += mat4(0.04990171, 0.08493333, 0.08668171, 0.14610586, -0.010766879, -0.05690133, 0.10706113, 0.13667485, 0.044783257, 0.029695645, -0.101674624, -0.02023205, 0.031889528, 0.14293797, 0.08712652, 0.08716896) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.21387868, -0.21650635, 0.2743992, -0.048781313, -0.027735803, -0.1543507, 0.11343657, -0.18251626, 0.15225998, 0.13158897, -0.41056108, 0.102582805, -0.09181491, -0.0042975787, 0.056065407, -0.16961528) * go_0(1.0, 0.0);
|
||||
result += mat4(0.08966051, 0.09331515, -0.085415326, -0.022695992, 0.009771476, -0.07143986, 0.0590329, 0.07347928, -0.09033658, -0.06805735, -0.20129825, 0.017873045, 0.16908158, 0.014213783, 0.112663984, 0.10048714) * go_0(1.0, 1.0);
|
||||
result += mat4(0.115590535, 0.08364541, 0.00864431, -0.094349444, -0.11073411, 0.05337711, 0.055587426, 0.12131219, -0.04710173, -0.046455074, 0.110379905, 0.25445566, 0.15154606, 0.04483541, 0.08708686, 0.113456205) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.014296297, 0.24858733, 0.05035193, -0.09225393, 0.034625243, 0.06219943, 0.19825043, 0.04673499, -0.4083363, -0.39954248, -0.08299408, 0.048756655, 0.09862206, 0.01588621, 0.0070629907, 0.04173666) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.17356622, 0.1484559, -0.10054033, 0.013332302, 0.15200937, 0.08985606, -0.031668343, -0.026007611, -0.16339104, 0.054744486, 0.07386605, -0.033910174, -0.0018002358, -0.02968911, 0.054931052, 0.09970459) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.07330346, 0.05938635, 0.01911963, -0.09856661, -0.081916444, -0.046957035, -0.043849826, 0.09572135, -0.13621825, 0.034347896, -0.21189907, 0.10592239, -0.060592845, 0.09957844, 0.050621815, -0.07447668) * go_1(0.0, -1.0);
|
||||
result += mat4(0.044731334, -0.13406886, -0.04138754, -0.06764551, -0.018899845, 0.35320804, -0.10959127, 0.17435175, -0.17941645, -0.30889434, 0.10573405, 0.0319751, -0.15677677, 0.08164649, 0.16559398, -0.08152387) * go_1(0.0, 0.0);
|
||||
result += mat4(0.057760764, -0.12145107, 0.06889264, -0.30627275, 0.011501002, -0.080296256, -0.18067095, 0.10592384, 0.12884894, -0.18973115, 0.18740658, 0.28362688, 0.12934786, -0.010292026, 0.0559999, 0.079962276) * go_1(0.0, 1.0);
|
||||
result += mat4(0.048659086, -0.006250348, -0.041242067, -0.12078197, -0.07152629, 0.05699244, 0.0011704164, -0.023007339, 0.07814492, 0.02546712, -0.08957218, -0.036925297, -0.03383498, 0.12583385, 0.12207602, 0.03910942) * go_1(1.0, -1.0);
|
||||
result += mat4(0.26151723, 0.23277281, -0.021892069, 0.052827276, 0.18268764, 0.28595275, -0.20529993, 0.19892794, 0.0038986763, 0.114547804, -0.020574905, 0.02405073, 0.11713121, 0.04491106, -0.07557327, 0.014374293) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.14276731, -0.06600894, -0.029757235, -0.099975966, 0.023050314, -0.07662015, -0.11542214, 0.087981045, 0.070319094, 0.12462511, 0.008152087, 0.12613884, -0.07071591, 0.0063393894, 0.08699723, -0.0242523) * go_1(1.0, 1.0);
|
||||
result += mat4(0.035586607, -0.26826563, -0.10145326, -0.002177148, 0.022144236, -0.117452875, 0.021346297, 0.051908135, -0.022425706, 0.067299, 0.09406446, 0.078294896, 0.014900606, -0.05468236, 0.07241715, 0.061000507) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.184133, 0.06229474, -0.13819578, -0.025011744, -0.01868356, -0.18940887, 0.092631504, -0.092806384, 0.0035951615, 0.11777577, 0.028149817, 0.0049419673, 0.22230826, 0.06337655, -0.20004818, -0.20937593) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.13852163, -0.094492316, -0.040309057, 0.10771662, 0.18963522, 0.08687606, -0.20030232, -0.082126215, 0.012181411, 0.044306785, -0.036970526, 0.04403363, 0.07911973, 0.0021176056, 0.26944208, -0.06657045) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.027229607, 0.12410596, 0.04348171, 0.0019921176, 0.088246435, -0.02828269, -0.26499373, -0.12566662, 0.025947344, -0.0078000715, 0.058063716, -0.0032702687, 0.0059978673, -0.04860002, 0.027650384, -0.23394564) * go_2(0.0, -1.0);
|
||||
result += mat4(0.07892762, -0.13300626, 0.46678603, -0.033239357, -0.12306804, -0.079602, 0.20534003, 0.23873802, -0.035643574, 0.059950788, -0.26559883, 0.12206408, 0.25408483, 0.029933078, 0.32081822, 0.033947676) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.06847802, -0.017930118, -0.12299636, -0.12987946, 0.09267518, -0.0009083275, -0.035390552, -0.15379669, -0.1132433, -0.036670692, -0.08342377, 0.015636675, 0.022590527, 0.10533322, 0.0389949, -0.059033744) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.041753534, -0.014428097, 0.06999257, -3.546234e-05, -0.033465035, -0.040709455, 0.13118082, -0.21016484, -0.07846085, -0.030885663, 0.06934681, 0.12725256, -0.023784902, -0.13373604, -0.015261479, 0.05234782) * go_2(1.0, -1.0);
|
||||
result += mat4(0.13798563, 0.12757827, -0.26978776, 0.102494285, 0.13285922, 0.35432795, -0.11997128, 0.17108068, -0.12235328, -0.24582328, 0.26962712, -0.086760186, 0.010127441, 0.08048835, 0.047505867, 0.19991067) * go_2(1.0, 0.0);
|
||||
result += mat4(0.03584222, -0.13433793, -0.044629525, -0.0010440781, -0.0033084434, -0.026725832, -0.05386642, -0.13612603, 0.10066015, 0.10499841, 0.031767137, -0.04550841, -0.09391546, 0.1454157, -0.26962402, 0.21015608) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.21956864, -0.13502425, -0.02126954, 0.059263993, -0.13461533, -0.04001395, -0.0924258, -0.069165014, 0.22019973, 0.003270619, 0.022072528, -0.14173602, 0.0028843523, -0.13784003, -0.061057515, -0.0049253837) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.0011410525, -0.16098002, -0.12883134, 0.018262507, 0.001481578, 0.19514659, -0.13703239, 0.096059754, 0.34194204, 0.13983466, 0.14021507, 0.011405113, -0.11303146, -0.17050214, -0.06992079, -0.05566986) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.12307941, -0.02192472, 0.13193923, -0.061640862, -0.16841564, -0.0822524, 0.10141759, 0.02139286, 0.1599039, -0.050632223, 0.16702358, 0.111514546, 0.02397393, 0.037606515, 0.017971672, -0.048641708) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.02697617, -0.08579184, -0.28045088, 0.05262136, -0.059576314, 0.107535526, -0.06188862, 0.0010509328, -0.18178311, -0.17288832, 0.20703638, 0.083048366, 0.03859681, -0.07548898, 0.011605782, -0.021842534) * go_3(0.0, -1.0);
|
||||
result += mat4(0.13198483, 0.37200937, -0.0896539, 0.12450637, 0.037202634, 0.035985112, 0.16579124, -0.08967905, -0.24341385, 0.32482424, -0.3037812, -0.007154969, -0.007152382, -0.017435173, 0.12662841, -0.090513505) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.014726027, 0.08394915, -0.02100581, 0.24882795, -0.023793869, -0.006450114, 0.17093314, -0.06994153, -0.08689907, 0.113542505, -0.053211495, -0.1780173, 0.030043352, 0.2500714, -0.026940798, -0.0069258413) * go_3(0.0, 1.0);
|
||||
result += mat4(0.037078895, -0.03033529, -0.066851325, 0.14718252, 0.066372745, 0.028897487, -0.036055963, 0.035399746, 0.06733992, 0.21021596, -0.18314466, -0.027192699, 0.020213274, -0.17751546, -0.050674338, -0.09382659) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.14761917, -0.22166072, 0.033172436, -0.21982265, -0.09172891, -0.20794454, 0.1738752, -0.13685037, 0.10981111, -0.23169234, 0.053787973, 0.12001196, -0.038242023, -0.047124114, 0.22503005, 0.1015142) * go_3(1.0, 0.0);
|
||||
result += mat4(0.021231879, -0.015423476, 0.058986407, 0.032002006, -0.029305007, 0.008933183, 0.10777483, -0.112574644, -0.023935415, -0.06604598, 0.053859934, -0.08354717, 0.13703763, -0.078382134, 0.12914242, -0.022056468) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.002022359, -0.007333954, -0.038140967, -0.03819673);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.050738923, 0.15003614, -0.18880141, 0.16791905, 0.16549185, -0.26726744, -0.12813666, -0.021510791, 0.070805945, 0.043350577, 0.0035756908, 0.11776675, -0.01824196, 0.12618026, 0.07424072, 0.032886628) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.11678059, 0.0565686, 0.04392921, -0.27621672, 0.2116695, 0.038044345, -0.015018062, -0.028636303, 0.049744565, -0.12935996, 0.027176194, -0.13208814, -0.21195693, 0.08980974, 0.013893243, -0.018403184) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.3214697, -0.03143518, 0.19927292, 0.12566878, 0.16190828, 0.11784847, 0.09943727, 0.11755882, 0.017959306, -0.064603634, -0.14054321, -0.11917774, 0.0056958874, 0.06461699, 0.104604125, 0.021947173) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.24738057, -0.034892898, -0.03364674, 0.017340986, 0.02933764, -0.08090866, -0.034651175, -0.17391174, 0.08536477, -0.17446008, 0.22706915, -0.10555482, 0.0877744, 0.0681237, -0.035909466, -0.10355238) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.090646185, -0.12971672, -0.14531808, -0.060838025, 0.24902023, 0.1310588, 0.18602785, 0.21283495, -0.32160765, -0.070119165, -0.10350057, 0.19260244, -0.2610542, -0.3030521, 0.08432348, -0.22286619) * go_0(0.0, 0.0);
|
||||
result += mat4(0.28333843, -0.053968847, 0.08344997, 0.19987041, 0.22163449, 0.22161576, 0.0030572868, 0.10848695, -0.20529847, 0.08406883, -0.07130339, 0.09987656, 0.29774663, -0.08768785, 0.15567012, -0.010313759) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.1260916, -0.071901485, -0.30566844, 0.19393384, -0.05133266, 0.07868844, -0.24817581, 0.055521224, 0.23277187, 0.16324161, 0.07110341, -0.042626668, 0.052509766, -0.014292625, -0.019677468, 0.041733738) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.04264262, -0.06528029, 0.0013520801, -0.02140956, 0.27304867, -0.029477939, -0.1859993, 0.01418354, 0.07256604, 0.14302284, 0.03309569, -0.15932149, 0.01500576, -0.053860538, 0.1131707, -0.06272606) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.0400483, -0.030188695, -0.108427785, 0.057873204, 0.42774406, -0.11353873, 0.110134825, 0.052191462, 0.00087113964, 0.040683694, 0.100507155, -0.16746339, -0.26971558, 0.06506685, -0.20950548, 0.040783025) * go_0(1.0, 1.0);
|
||||
result += mat4(0.11394146, -0.10693933, 0.2377026, -0.03783948, -0.16496852, 0.046675198, -0.23396324, 0.05696911, -0.02770668, 0.12922443, -0.093586415, 0.102305606, 0.0040032533, -0.038440734, -0.0035825048, -0.22108772) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.17577791, -0.024538597, -0.19877498, -0.14544973, 0.16614193, -0.3279891, 0.14678721, -0.16355143, -0.012954231, 0.20982395, 0.044255227, 0.087878115, 0.11289659, -0.26981032, -0.10789584, 0.24094439) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.0041394173, -0.0937936, 0.15251775, 0.1026978, -0.01999847, -0.02865502, 0.16765144, -0.17490439, -0.016996933, 0.03891808, -0.01858217, -0.106255606, 0.027496144, -0.14120618, 0.023483312, -0.08291959) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.060642462, -0.2957824, 0.33968493, -0.04501478, -0.14999421, -0.0067213452, -0.018236576, 0.01627547, -0.07771579, 0.0124932695, -0.11797959, -0.090979554, 0.0096479915, 0.021336472, -0.07794724, 0.030138575) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.091704845, -0.20800348, -0.22158638, 0.048748583, 0.15139692, -0.2832814, 0.09610812, 0.41077513, 0.0007106381, -0.14465855, 0.0056652213, 0.031696238, -0.03384328, 0.1940933, 0.19262145, 0.014331562) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.16637586, -0.22008398, 0.102937706, 0.15260033, 0.039856806, -0.21082906, -0.19694057, 0.0712475, 0.015049883, 0.17320138, 0.06505415, -0.020279367, -0.018576574, 0.201407, -0.08108244, 0.04151909) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.12496581, 0.107817784, 0.10645319, 0.035113968, 0.0166165, 0.1316661, -0.045253787, -0.03863719, 0.09126881, 0.07553792, -0.029150097, -0.07629157, -0.17978054, -0.27080613, -0.028408276, -0.15366451) * go_1(1.0, -1.0);
|
||||
result += mat4(0.081859134, -0.11599677, 0.027383117, 0.092724435, 0.059302155, 0.10008954, -0.12217131, 0.07471211, -0.20396213, -0.040741358, 0.118772194, -0.21725504, 0.099645875, 0.09691941, -0.07696025, -0.016445495) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.18712623, -0.14458412, 0.03693652, 0.014525352, -0.09607279, -0.19400409, 0.032149505, 0.07106094, 0.051436905, -0.07765334, 0.017043818, 0.17777587, 0.05274306, 0.0062209824, -0.080005355, 0.026041988) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.090594456, -0.041637532, 0.10346829, -0.09393943, 0.027663473, 0.20729685, -0.011156861, 0.021863503, 0.04781304, -0.039483577, -0.092933334, -0.25187445, 0.033062164, 0.010756357, -0.13035728, -0.008321023) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.07772912, 0.010776647, -0.018709056, 0.25634038, 0.00906326, 0.21411708, 0.122652486, 0.07725616, 0.15266491, 0.1274286, 0.10400329, 0.20354506, 0.013765407, -0.039089683, 0.25870228, -0.08919069) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.14971368, 0.06935879, -0.089983195, 0.01406992, 0.16989979, -0.037809014, 0.07157283, -0.050660506, -0.032826405, 0.033794664, -0.0051332368, 0.089349195, 0.06263488, -0.07048108, 0.07263597, -0.11618368) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.013391823, -0.07888697, -0.13984044, -0.01241464, -0.06475807, 0.06978077, -0.20329754, 0.16602662, 0.013664227, 0.12317301, -0.10240692, -0.0657491, -0.31402445, -0.14472555, 0.1739024, 0.0005437834) * go_2(0.0, -1.0);
|
||||
result += mat4(0.16330495, 0.02644609, 0.23837087, -0.07734767, 0.12377497, -0.18478604, 0.35040903, -0.05262452, 0.049074646, -0.0077528385, 0.15370984, -0.22888668, 0.3603141, 0.29372314, -0.4432887, 0.20702155) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.18785694, 0.21085343, -0.111042105, 0.0478716, -0.08214944, -0.0922987, 0.29570273, 0.025100114, 0.25403878, 0.01271447, 0.21851794, -0.1434596, -0.21153769, 0.023305666, -0.10386609, 0.043919638) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.117247805, 0.013329102, 0.0313911, -0.08055777, -0.0053445757, -0.2886372, 0.07938673, -0.06659165, 0.20798062, 0.030106818, -0.04811631, 0.036332276, -0.057687126, 0.03813657, 0.035860628, -0.11273985) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.0031557097, 0.027456097, -0.14444692, 0.08411739, 0.13466308, -0.13212901, -0.0034804344, 0.1464661, -0.21033211, 0.05913627, 0.10233881, 0.009844489, -0.15369488, -0.018978333, -0.07518442, -0.010549853) * go_2(1.0, 0.0);
|
||||
result += mat4(0.112989105, -0.011166866, -0.08277204, 0.046827227, -0.08067428, 0.13465053, -0.1656419, 0.07280515, 0.037523627, -0.050147127, -0.17731906, 0.1067486, 0.119732924, -0.102017604, 0.31421226, -0.14060387) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.1106223, 0.09229271, -0.09355422, -0.02413533, -0.096457504, -0.13282233, 0.022983741, -0.13534859, -0.0056585902, -0.07214356, 0.14617127, -0.13723095, 0.058078192, -0.1038417, -0.10452195, -0.18855028) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.16357008, 0.080841675, 0.1663936, 0.20815827, 0.03813903, 0.34158087, -0.012987109, 0.39152008, -0.027927356, -0.14332302, -0.012866622, -0.016149148, -0.08733816, 0.1960951, 0.19572765, -0.2710826) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.024827998, 0.24175219, 0.030659903, -0.22227505, 0.026898654, 0.009930298, 0.088392995, 0.32644793, -0.10351868, -0.08717382, 0.22931585, 0.05197704, 0.06534648, 0.13636068, 0.062107667, 0.024806283) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.18550465, 0.062058095, -0.08620093, 0.20158216, -0.1460996, 0.14275469, -0.28057688, -0.11685651, -0.09627509, 0.09029933, 0.03669734, 0.1257313, -0.07974307, 0.020742215, -0.0039170664, 0.11340528) * go_3(0.0, -1.0);
|
||||
result += mat4(0.15225565, 0.171972, 0.13573253, 0.0056740018, -0.1667786, 0.06028638, -0.1255049, -0.23327217, -0.139949, 0.029957669, -0.16713464, 0.046236664, -0.05070503, 0.18714412, -0.20076098, 0.1672637) * go_3(0.0, 0.0);
|
||||
result += mat4(0.18468563, 0.07733334, 0.14463845, -0.10712052, 0.36213547, 0.29404843, 0.2110929, 0.14646721, -0.059985258, -0.2709805, 0.073061034, -0.039072156, 0.015898943, -0.17166951, 0.20194982, -0.04723745) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.26353067, 0.050225407, -0.42643914, 0.06601958, -0.10513071, -0.1654714, 0.0593609, 0.027410276, -0.19465327, -0.13865606, 0.05579213, 0.07982532, -0.20893136, -0.008150932, 0.053529713, -0.0317475) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.012075693, -0.27574313, 0.22184552, -0.117393926, -0.49310133, -0.13997443, -0.079180904, -0.053438634, -0.07552426, -0.045796394, -0.037434675, 0.24076645, -0.04395852, 0.10325762, -0.19867313, -0.070216134) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.026107877, -0.030023552, -0.047810435, 0.20572239, 0.061861858, 0.1776161, -0.306099, 0.16332485, -0.1843373, 0.06758581, -0.23902373, -0.10575018, 0.03990962, -0.046113137, 0.14876197, -0.21280771) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.009669773, 0.036289547, -0.050454646, 0.051479716);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf1
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.14542116, -0.15827142, -0.20811677, -0.103433, 0.19787271, 0.33990738, 0.17085013, -0.059132278, 0.013047369, -0.1687924, 0.06732661, -0.050968684, 0.09197164, -0.041265316, -0.108277336, -0.014430892) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.022837132, 0.20440012, -0.14266612, 0.019944299, 0.069084294, 0.3171199, -0.1521742, -0.35806596, 0.13581008, -0.13811131, 0.12219503, 0.17329764, -0.15100783, 0.0862648, 0.118227705, 0.18736814) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.013604392, 0.11496102, -0.18734755, -0.047555517, 0.05297245, 0.006461213, 0.06247472, -0.0202791, 0.02329791, 0.11530998, -0.148774, 0.0965498, 0.1487269, 0.061629567, -0.22488646, -0.005393787) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.29286116, 0.11958281, -0.11193505, -0.17139061, -0.035151243, -0.2635945, 0.0002499315, -0.16346519, 0.23779829, 0.04454211, 0.21293561, 0.25617847, 0.12194803, -0.0017443774, -0.009216221, -0.034387548) * go_0(0.0, -1.0);
|
||||
result += mat4(0.28791443, -0.25421545, -0.058626153, -0.1520494, -0.16808414, -0.39723453, -0.13199537, 0.056999452, -0.048155293, 0.38699663, -0.114719056, 0.001293743, -0.0959443, -0.08189709, 0.26921842, 0.061219636) * go_0(0.0, 0.0);
|
||||
result += mat4(0.00781977, -0.07103863, -0.21942843, 0.2419546, 0.20016691, -0.28697264, -0.034715973, -0.03381459, -0.028126812, 0.046806023, -0.14423183, -0.13472253, 0.009225362, -0.086190686, 0.0041205613, 0.08953202) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.04926224, -0.099740155, -0.088695474, 0.09950333, -0.06495916, 0.20126842, -0.0062843356, -0.034764495, -0.10808971, -0.19946553, 0.075991094, 0.14746219, 0.08247818, 0.07382381, -0.056908615, -0.026823666) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.04837408, 0.12605472, -0.23957102, -0.14252385, -0.046534102, -0.07511751, -0.21040416, 0.2064639, -0.006026243, -0.25005546, -0.063780144, 0.076840036, -0.07484346, 0.017368162, 0.04657373, -0.022188455) * go_0(1.0, 0.0);
|
||||
result += mat4(0.04545079, -0.002226373, -0.11695467, 0.12954631, 0.054903183, 0.15162702, -0.19222596, 0.05351421, -0.079599276, -0.036238387, 0.1362261, 0.037431743, -0.0015106505, 0.18739921, 0.122365154, -0.05871144) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.005558987, -0.13553315, -0.006372213, 0.06633917, -0.22141413, -0.15780807, 0.057122614, -0.057320844, -0.06306763, 0.19112623, -0.041758966, 0.03555483, -0.005718873, 0.009167371, 0.050909385, -0.14599234) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.18175003, 0.10442485, 0.052994236, -0.4001252, -0.08328538, 0.06380226, -0.055015627, 0.010929493, -0.22888647, -0.033181675, -0.07570874, 0.07933599, -0.07894686, 0.12202901, 0.13679314, -0.054344065) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.030145945, -0.06121175, -0.08550973, 0.10082535, 0.07198805, 0.21414264, -0.25636044, 0.028803539, 0.043738026, -0.0367658, 0.27998537, -0.06274612, -0.22862338, 0.002624325, 0.28519824, 0.18540645) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.012136538, -0.07059324, 0.018098673, 0.12078888, -0.087637, 0.041642863, 0.034997553, -0.16741107, 0.04701011, -0.004160269, 0.122639626, 0.0043271836, 0.011551197, -0.16421974, -0.102481335, 0.014233497) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.37945676, 0.25232047, -0.03707734, -0.1985225, -0.11536396, 0.22039749, -0.21809638, -0.10596801, -0.17211124, -0.2035486, 0.011822896, 0.27510995, -0.105182275, 0.022503568, -0.0063389307, -0.071560584) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.16101715, -0.034247126, 0.16626042, 0.031131435, 0.03048031, -0.105447404, -0.05728527, -0.14518815, -0.019103229, -0.15152888, -0.119154684, 0.028724093, 0.05836196, -0.35943082, -0.016481897, -0.0437348) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.07719413, -0.33214888, -0.0541927, 0.16506542, -0.032792456, 0.016834807, 0.1724155, 0.073768586, 0.002303886, -0.001382793, -0.0562648, -0.10167158, -0.19101655, 0.052783452, -0.1422853, 0.09653729) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.30030164, 0.11637444, -0.23238538, -0.27238008, -0.077208534, -0.027645003, 0.10369907, 0.20162316, -0.14428844, 0.1766293, 0.024419712, 0.11301171, 0.07772854, 0.18613201, 0.20721672, -0.1751799) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.1026615, -0.12484944, 0.15386428, 0.038676128, -0.119472496, -0.032417197, -0.14208497, -0.05254358, -0.0035079278, -0.011276316, 0.043117497, -0.010022288, 0.031624593, 0.014969992, -0.031410277, 0.15284787) * go_1(1.0, 1.0);
|
||||
result += mat4(0.018149922, -0.05906194, 0.054767277, 0.008161979, -0.076949194, 0.040888708, -0.006419542, -0.12897012, -0.0028229658, 0.20937827, 0.02741711, -0.04013348, -0.12731804, 0.008064522, 0.002870103, 0.027690327) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.023197446, -0.08888926, 0.15531142, 0.13745947, 0.054352283, -0.121785395, 0.16237587, 0.023567237, -0.36160588, 0.30499592, -0.033180915, -0.1515843, 0.04251452, -0.17903805, 0.03235283, -0.08062386) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.0072868476, -0.2010616, 0.13061914, 0.12846659, 0.11725315, 0.14589547, -0.05373261, -0.081606135, -0.07010131, -0.025378224, 0.10265872, 0.18658938, -0.12165338, 0.036297683, 0.03925332, 0.16576236) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.10300252, -0.11548347, -0.08691649, -0.014866044, -0.3213804, 0.47206497, -0.16032113, 0.026284516, 0.046302956, -0.052474245, -0.025335522, -0.10957576, -0.16872157, 0.19049212, -0.023881195, 0.061396897) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.16202278, 0.52128345, -0.2601511, 0.06116799, -0.21123995, 0.39389637, -0.350544, -0.16157438, -0.02823116, -0.39056876, -0.14267299, 0.03262984, 0.342303, -0.20556125, -0.0019219286, -0.1824844) * go_2(0.0, 0.0);
|
||||
result += mat4(0.23399737, -0.0912646, 0.11152403, -0.20945886, -0.053451832, -0.09786892, -0.059099484, 0.18103573, -0.117154315, -0.18342866, 0.12650815, 0.0067340015, -0.037984423, 0.17667364, 0.071636364, -0.011689163) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.099510275, -0.0925438, -0.009136904, -0.03774997, -0.13348748, 0.3605135, -0.078298144, -0.14712195, 0.22566219, 0.18659295, 0.05614545, 0.10792911, -0.12477693, -0.03587624, 0.08050775, -0.054740936) * go_2(1.0, -1.0);
|
||||
result += mat4(0.10312337, -0.063681684, 0.16496794, 0.09038492, -0.08903926, 0.41163155, -0.013669214, -0.21472235, -0.054991595, 0.0033639956, 0.18160143, 0.17240305, -0.039428882, 0.17087695, -0.1729076, 0.09871825) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.13123736, 0.0802573, 0.077981554, -0.101768315, 0.089998, -0.13781744, 0.122858986, 0.054121554, -0.02640825, 0.13577555, -0.037485655, -0.04179625, 0.000106130996, -0.100183845, 0.00046665114, 0.21791616) * go_2(1.0, 1.0);
|
||||
result += mat4(0.011894387, -0.030088445, 0.025817253, 0.08193235, 0.109322436, 0.10855583, -0.19661167, -0.09405307, 0.2073779, -0.33972177, 0.048635002, -0.14883177, 0.056954246, 0.3953476, 0.18765114, -0.014010224) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.22594279, -0.014942035, -0.1519647, 0.25367293, 0.16330296, 0.03317176, -0.32148597, -0.46503916, 0.19944623, -0.26229686, 0.019909514, -0.059794176, 0.12912126, 0.044948537, -0.08649492, 0.08024645) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.022943841, -0.068013534, 0.11032515, 0.011685601, 0.020096298, -0.3285243, 0.08196111, -0.089537136, -0.03976742, -0.1315977, -0.36306036, 0.24678081, 0.22115967, -0.017472323, -0.19451386, -0.035218123) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.020891193, -0.12721714, -0.15030408, 0.026523203, -0.12413139, -0.11235275, -0.21476477, -0.11326953, 0.028815055, -0.18552732, -0.0076828003, -0.14679903, 0.020509586, -0.18695217, 0.06696879, 0.103938386) * go_3(0.0, -1.0);
|
||||
result += mat4(0.057521313, 0.28509304, -0.2525733, 0.16745082, -0.26614547, 0.18545172, -0.27140215, 0.018639714, 0.19730581, 0.1659491, -0.058363054, -0.4048628, 0.024913948, -0.44124457, 0.13872208, -0.0371103) * go_3(0.0, 0.0);
|
||||
result += mat4(0.100904405, 0.06700356, -0.035322092, 0.21781014, 0.018047005, -0.21737386, -0.3734802, 0.13506944, 0.012760691, 0.06620756, -0.0253398, 0.0030280363, -0.044015452, -0.055860534, -0.3547194, -0.04230283) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.19012743, -0.34408915, 0.18940191, 0.13152952, 0.107553795, -0.00694412, -0.07930157, -0.30964044, 0.034710668, -0.031806916, 0.019838978, 0.017044948, 0.110688254, -0.0029772928, 0.09414367, -0.10760175) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.05745392, 0.29022983, 0.014998233, 0.27365527, 0.08169933, 0.0734232, -0.09404464, -0.26870936, 0.21171738, -0.19529793, -0.064401075, -0.18972695, -0.08024953, -0.027122354, -0.11661348, 0.010131282) * go_3(1.0, 0.0);
|
||||
result += mat4(0.07599435, -0.06851123, 0.06258365, 0.10296892, 0.15556085, -0.041609086, -0.11303363, 0.07082365, 0.013949174, -0.087201476, -0.0855705, -0.12979257, 0.04048528, 0.4211556, 0.04118289, -0.22093314) * go_3(1.0, 1.0);
|
||||
result += vec4(0.07789114, 0.0024746545, 0.1891165, -0.0023716448);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.10883355, -0.14958352, 0.026701333, 0.090302855, 0.033934478, 0.120340124, 0.027125617, -0.16792692, -0.075757094, 0.28692973, 0.013230067, -0.040618937, 0.087148145, -0.05985753, -0.06352023, -0.05775848) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.18206549, -0.10363482, 0.097648725, -0.08801144, 0.31633568, 0.058347676, -0.009121898, 0.02594872, 0.14757825, 0.4730546, -0.008518203, -0.3090668, -0.004052835, -0.14166127, -0.010156037, 0.21191326) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.05735183, 0.039180398, -0.12357178, 0.04830351, 0.120369986, -0.052775342, 0.005902798, 0.07695394, 0.00602021, 0.16758691, 0.10287989, -0.1718468, -0.1319741, 0.16932078, -0.2055026, -0.31820264) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.05427556, -0.28392607, 0.08579091, -0.0015861926, 0.062348455, -0.27778792, -0.07450379, 0.01616914, -0.012357131, -0.056992117, -0.1896176, 0.018156245, 0.06499259, -0.076558664, 0.10341699, -0.08993959) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.05741742, -0.05414434, 0.18006511, 0.09840777, -0.11849741, 0.40419933, 0.21349974, 0.40268886, 0.23218039, -0.0680356, -0.3130592, -0.21271054, 0.13776754, 0.19114101, 0.17373541, 0.43457666) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.060757063, 0.11339545, -0.042958036, -0.06483378, -0.06681766, -0.056395415, 0.037868995, 0.033861663, -0.1041215, 0.0046828864, 0.14360638, 0.087886184, -0.26808187, 0.19876598, -0.05276215, -0.07073776) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.24029991, -0.14217372, -0.011767948, 0.011623913, 0.33820602, -0.24501325, -0.11444902, 0.14536968, 0.16780593, 0.0065867775, -0.074971735, 0.021472024, -0.10853042, 0.09527126, 0.009436061, -0.09688826) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.31893802, -0.0016892607, -0.105592966, -0.116694786, -0.007851739, 0.1429722, 0.0741952, 0.050125953, 0.07185179, 0.1900389, 0.030889044, 0.15422693, 0.12550323, 0.3556344, 0.108276874, -0.099125646) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.33620578, -0.11113713, -0.15881014, 0.028243937, -0.12028756, -0.028566968, -0.002682634, -0.15635195, -0.06869284, -0.03309234, 0.03086361, 0.050773233, -0.08939835, 0.15237434, -0.024076303, -0.13092752) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.31200737, 0.32207087, -0.068700634, -0.39202076, 0.0676771, 0.083766654, -0.05696634, 0.03088338, 0.046761762, 0.09732023, 0.030844063, -0.03369749, -0.12664944, -0.029924957, 0.10551989, 0.086157694) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.1919761, 0.17179352, -0.025805056, -0.05570367, -0.16736336, 0.07430868, -0.13228212, 0.10702857, -0.09723214, 0.1884809, 0.09422538, -0.16902041, -0.1964137, 0.17877853, 0.17453954, -0.11339361) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.11865004, 0.013131073, 0.17317963, -0.2077911, -0.1116894, 0.09672745, -0.023348883, -0.1176519, 0.15893579, 0.22941695, 0.18798698, 0.059098385, 0.09498779, 0.10118143, 0.08737761, -0.016268898) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.025380889, 0.17163627, -0.014800655, 0.12669696, 0.050048903, -0.06513837, 0.020915661, 0.2144372, -0.17799327, 0.0068409992, 0.06751171, -0.16618991, 0.14637277, 0.010591964, -0.15909241, 0.02660789) * go_1(0.0, -1.0);
|
||||
result += mat4(0.3178319, 0.15036377, -0.03386948, 0.13883169, -0.33842105, 0.061425313, -0.04195804, 0.22558802, 0.2250625, 0.060225345, -0.08467863, 0.0014776831, 0.080328, 0.03221249, 0.20838667, 0.11489719) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.0013924981, 0.28233197, -0.17997956, -0.10959627, -0.16253087, 0.016549526, -0.1571556, 0.017017027, -0.14697123, 0.0869202, 0.2104898, -0.15658243, 0.13424201, -0.022636503, -0.09512045, 0.0927298) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.038486905, -0.19215351, -0.2446516, -0.02958912, 0.06899297, 0.028667469, -0.05537665, 0.066711955, -0.0017354499, -0.07466053, 0.028587297, -0.042017035, 0.023596823, 0.0067433366, -0.14685915, 0.13400853) * go_1(1.0, -1.0);
|
||||
result += mat4(0.0573442, 0.1424536, 0.19606829, 0.07141616, -0.032276712, 0.20030099, 0.16644277, 0.10393295, 0.27240822, 0.0071844175, -0.023368603, -0.14067268, -0.20310283, 0.039528254, 0.103837095, 0.08236034) * go_1(1.0, 0.0);
|
||||
result += mat4(0.15616669, 0.3495403, -0.05678421, -0.069600284, -0.07361787, 0.079501756, 0.009530261, -0.032385882, 0.029831208, -0.095407076, 0.010261287, 0.15250465, -0.04868275, 0.058579214, 0.03779718, -0.10810775) * go_1(1.0, 1.0);
|
||||
result += mat4(0.06492073, 0.018667994, -0.004712761, -0.032692235, 0.04027288, -0.114499666, -0.04327484, 0.13778907, -0.09373396, -0.08822919, 0.04796151, -0.057756703, -0.26161298, 0.07182931, 0.12998815, -0.14389744) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.19001032, 0.13091461, -0.2551175, 0.013365716, -0.031779066, 0.002531366, -0.13807543, -0.14165778, -0.2701911, -0.0890182, 0.34704998, -0.008494185, 0.16179956, -0.060182545, 0.060827415, -0.17249492) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.10665868, 0.15999752, -0.042796712, -0.14010513, -0.014244899, 0.017433831, 0.053657144, -0.0965679, 0.23623326, 0.0690172, 0.1290121, -0.025523739, 0.122357905, -0.18172716, 0.02829383, 0.10042929) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.09273112, 0.09466892, -0.009225705, 0.16772579, 0.0813042, -0.16461512, 0.038097944, 0.19834967, -0.033650465, -0.12888893, 0.1414859, -0.021587005, -0.0047441716, 0.08880282, 0.020621201, 0.065779164) * go_2(0.0, -1.0);
|
||||
result += mat4(0.0051817205, 0.20322648, -0.077459775, 0.07461627, 0.1817634, -0.5371515, -0.29336745, -0.57652086, 0.035826538, 0.41058993, 0.21512514, -0.041881148, -0.2490056, -0.07172767, 0.20821427, -0.69866294) * go_2(0.0, 0.0);
|
||||
result += mat4(0.18961228, 0.027452804, -0.0075194626, -0.029665018, 0.28770384, -0.099777386, -0.12160496, 0.07690297, 0.30273837, 0.026466522, 0.18100439, -0.09078488, 0.2035407, -0.062081084, 0.06744994, -0.07512911) * go_2(0.0, 1.0);
|
||||
result += mat4(0.008473044, 0.07501521, -0.11242355, -0.039451122, -0.21818535, -0.07779562, 0.13194147, 0.084983595, 0.0770609, -0.034488454, 0.08823556, -0.07168295, 0.041894365, 0.0789253, 0.06191209, 0.013991105) * go_2(1.0, -1.0);
|
||||
result += mat4(0.10582237, 0.1514222, 0.10751824, 0.08231926, 0.23913008, -0.2673503, 0.036170945, 0.31463087, 0.026397424, -0.26629624, -0.07428361, -0.077513516, 0.0768238, -0.026638538, 0.12589583, -0.11521212) * go_2(1.0, 0.0);
|
||||
result += mat4(0.30389515, 0.18963532, 0.023015842, -0.10240883, 0.045651495, -0.036785256, -0.13346411, 0.16431254, -0.030950911, -0.03381929, 0.09413111, 0.03924852, 0.11044091, -0.10149653, 0.14114548, 0.07801978) * go_2(1.0, 1.0);
|
||||
result += mat4(0.029622428, 0.14528686, -0.034057826, 0.010664312, 0.059213262, -0.29354423, -0.08448559, 0.10569036, -0.02988314, -0.016480735, 0.042203777, -0.028342744, 0.36807576, 0.09301971, 0.123721026, 0.07806503) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.04849538, -0.09201287, 0.10069803, -0.031749677, 0.18774022, -0.27789372, 0.05288653, 0.08097265, 0.006918896, -0.060978457, -0.113319606, 0.008844536, 0.021804892, -0.0011744015, -0.35720357, -0.24996938) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.07147501, -0.09339197, 0.16154395, 0.3372506, -0.0004858638, -0.056553435, -0.12463908, -0.0047342298, -0.009141984, -0.13796125, -0.14035304, -0.104403175, -0.07054226, 0.12142519, -0.24971877, -0.1914648) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.008194284, -0.027617034, 0.004994261, -0.07672895, 0.25697777, -0.18313397, 0.03266311, -0.029157834, 0.010476624, 0.12394092, -0.059660904, 0.08561672, -0.0008583816, -0.044442356, 0.28336492, 0.065344445) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.3570137, -0.06802815, -0.10298613, -0.21256869, 0.3025278, -0.263425, 0.13547331, 0.038517762, 0.14951234, -0.16869017, 0.03293678, 0.21897063, -0.14688788, 0.21619378, -0.27550143, 0.048003722) * go_3(0.0, 0.0);
|
||||
result += mat4(0.15607022, -0.111073844, 0.2733694, 0.05423378, 0.25116092, -0.17350473, 0.13460433, 0.09602139, 0.17372625, -0.0024815476, -0.30154657, 0.0062206364, -0.0051755225, 0.04985103, -0.06310478, -0.30450678) * go_3(0.0, 1.0);
|
||||
result += mat4(0.057571005, -0.019051064, 0.054884393, 0.03993782, 2.6782007e-05, -0.05726912, 0.067192145, -0.08955987, -0.11937056, 0.15837386, -0.011670469, -0.06299701, -0.014917928, 0.23921679, 0.0054613873, -0.23099245) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.035849575, -0.06785954, -0.15053692, 0.011964653, 0.1975448, -0.1633047, -0.024539666, 0.03170174, -0.12585635, -0.021171011, 0.15862562, 0.10296358, 0.3114039, 0.10010659, -0.09519227, -0.12945092) * go_3(1.0, 0.0);
|
||||
result += mat4(0.044433746, -0.058466546, -0.13258536, -0.033972915, 0.0037206819, -0.057343487, 0.13798106, 0.044445634, -0.22623023, 0.2408462, 0.048287082, -0.30717465, -0.13402344, 0.20024839, -0.026932377, -0.034217034) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.05988374, -0.23198523, -0.058251306, -0.038808554);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf1
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.045249436, -0.040327657, -0.2667367, 0.0913868, 0.14961123, 0.07253207, 0.29162952, -0.11320944, 0.017569833, 0.012350104, 0.22532712, 0.025312115, -0.12193993, 0.037391737, 0.03220835, 0.12102545) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.020587588, -0.07043244, -0.28093454, 0.18336722, 0.08153308, -0.05914772, -0.15255487, 0.079236075, -0.4269835, -0.11470208, -0.19043571, 0.2723162, 0.0066251885, -0.17115718, 0.022036036, 0.07349558) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.09441315, 0.042170826, 0.071251415, -0.13891962, 0.10236482, 0.05356262, 0.0291025, 0.063867815, -0.14530063, -0.08727925, -0.0048300857, 0.06766869, -0.3481536, -0.10943503, 0.014951926, 0.11993114) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.13420522, 0.095721036, -0.1756104, -0.09906728, 0.09808904, -0.27402034, -0.102161326, 0.40162942, 0.13465238, 0.20237032, 0.3192343, -0.061512157, -0.20711629, -0.09659007, 0.06838548, 0.30256763) * go_0(0.0, -1.0);
|
||||
result += mat4(0.025805298, -0.0322599, 0.23653145, -0.2760735, 0.11291006, -0.10836205, 0.20742846, 0.06974535, -0.4191803, -0.10882523, 0.038603242, 0.22662747, -0.08845715, -0.26151156, -0.16670766, 0.008536192) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.085842185, -0.21239999, -0.032774646, 0.088163696, 0.038300447, -0.09510875, 0.10113864, -0.14712982, 0.14264707, -0.10895432, 0.03051617, -0.06791873, -0.35589013, -0.12884575, -0.09460007, -0.0879575) * go_0(0.0, 1.0);
|
||||
result += mat4(0.19235751, -0.109611385, -0.037397474, -0.26632717, 0.07878826, 0.19749992, 0.0035685285, 0.11793927, 0.019899402, 0.085741036, 0.08433813, -0.018344546, -0.0901484, 0.08221562, 0.12735383, 0.12801875) * go_0(1.0, -1.0);
|
||||
result += mat4(0.19123435, 0.007882246, -0.018564796, -0.09904253, 0.28052533, 0.6360808, 0.25001726, -0.30590564, 0.07646281, -0.34298185, -0.33293694, -0.036753535, 0.18719083, 0.22131144, -0.1420962, -0.0014709529) * go_0(1.0, 0.0);
|
||||
result += mat4(0.23060241, -0.14145076, -0.113213465, 0.037221998, 0.22163334, 0.18520229, 0.2961799, -0.063605964, 0.022606356, 0.043340076, -0.3233993, -0.075055614, -0.0038865958, 0.19558622, -0.018503085, -0.22932632) * go_0(1.0, 1.0);
|
||||
result += mat4(0.11712158, -0.03590364, 0.38039652, -0.019910801, 0.13338004, -0.07078425, 0.09404417, -0.27607328, -0.02205519, -0.013522961, 0.2924021, -0.16088538, -0.034280356, -0.063614614, -0.061583273, -0.22479968) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.05624079, 0.32659104, 0.47335497, -0.14091404, 0.14739423, -0.07122778, -0.009384643, -0.058900848, 0.06260307, -0.17574102, 0.3538743, 0.2842822, -0.18150197, 0.26806462, 0.24673693, 0.19710627) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.24837571, -0.01663848, -0.13093965, 0.30109972, -0.09680959, 0.074526474, 0.024111765, -0.012781737, -0.08591349, -0.100348584, 0.02363011, -0.02687084, -0.27630556, 0.14074354, -0.016993485, 0.084373675) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.1543391, -0.2008408, -0.21885285, 0.2320177, 0.06669948, -0.05171086, -0.25833863, -0.14085051, -0.035878573, -0.1632403, 0.09782713, 0.22973235, -0.14022017, -0.018347954, -0.29652777, 0.10912002) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.050962634, -0.040519282, -0.04381614, 0.084133334, 0.21222316, -0.091010064, 0.13157965, -0.21375372, -0.021148674, -0.044127557, -0.11400533, 0.097688414, 0.31571037, -0.05167655, 0.27606225, 0.12169133) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.1329087, 0.14291021, 0.043337896, -0.25970098, -0.11379552, -0.040157612, 0.08379851, -0.24104865, 0.1593102, -0.031879216, -0.004603848, -0.019003935, -0.24769545, -0.17577063, 0.16019398, 0.04640235) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.11615644, 0.12189521, 0.12919527, -0.104224406, -0.10143574, 0.14024515, -0.02759362, -0.1467619, 0.09028311, -0.06510291, 0.061612967, 0.10227729, -0.08785846, 0.06464871, -0.05048917, 0.09055746) * go_1(1.0, -1.0);
|
||||
result += mat4(0.34443164, 0.013906371, -0.0595573, 0.09354196, 0.12184454, -0.02698316, -0.06208632, -0.11266858, 0.004904335, -0.33987018, -0.2494041, 0.127125, 0.040493876, 0.0280356, -0.037431944, 0.05823802) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.1762869, -0.20683959, -0.37788594, -0.1244979, -0.17202286, -0.038234763, 0.015924744, -0.014006752, 0.07097758, -0.25219876, -0.3164728, 0.022413896, -0.41423917, -0.03191542, 0.009464804, 0.0770316) * go_1(1.0, 1.0);
|
||||
result += mat4(0.12442388, 0.031095076, 0.18799834, -0.18449762, -0.11995044, 0.11634828, -0.0055850362, 0.08558657, -0.025694892, -0.2854381, -0.32876188, 0.14690274, -0.1835963, -0.1786755, -0.44678628, 0.1678422) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.031241562, -0.1265462, 0.081369035, -0.1184643, 0.0010021052, -0.10810683, -0.039572187, 0.13850863, -0.010703417, -0.057981443, 0.30309856, 0.13869847, -0.16935349, 0.16969836, 0.045642667, 0.26460654) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.28779998, 0.04767888, -0.011856489, 0.114210494, 0.034624737, 0.19084676, -0.02740287, 0.035041407, -0.049002927, 0.10928203, 0.17362499, -0.1280889, 0.00077811617, -0.17594084, -0.18379052, 0.22303762) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.0008487252, -0.060438234, 0.109334275, -0.18768874, 0.13844973, 0.09226474, 0.18361697, -0.19385563, -0.29241335, -0.1033556, -0.3289991, 0.10027422, -0.09454755, -0.22817631, -0.2964217, -0.19499257) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.057920385, 0.06342629, -0.048577324, 0.15952215, -0.061343953, 0.16471362, 0.1501856, 0.027373426, 0.01837245, -0.0732048, 0.09776471, 0.14817989, -0.112215854, 0.109101914, 0.058316242, 0.29969788) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.12411656, -0.033170763, -0.08715826, 0.110862456, 0.1871076, 0.14550175, 0.23373431, 0.19281025, -0.37016305, -0.11924462, 0.026793748, 0.092801645, 0.04318573, 0.20969667, -0.39267823, 0.1938874) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.15932916, 0.22217506, 0.007901788, -0.04037383, 0.09095982, -0.043115042, 0.098845564, -0.073432215, -0.14535685, 0.11504512, -0.07950504, -0.010718905, -0.050012022, -0.13089752, -0.3323894, -0.005423676) * go_2(1.0, -1.0);
|
||||
result += mat4(0.007320675, 0.21108273, 0.20758918, -0.04005568, -0.13234317, -0.15708306, 0.41804615, -0.09720499, -0.09623786, 0.2441289, 0.33276868, 0.17716111, -0.45670444, -0.026252905, -0.01958701, 0.24028622) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.14936383, -0.023504466, -0.028479185, -0.053541556, -0.060263615, -0.087681144, 0.2435555, 0.08470686, -0.17713271, -0.2303349, 0.09337386, 0.039068084, -0.16263027, 0.034289114, 0.16604292, 0.10550447) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.16556105, 0.12211341, -0.0036831333, 0.13802956, 0.065256506, 0.03395266, -0.2296282, 0.21284704, 0.017770419, -0.1722762, -0.1741687, 0.10708671, 0.331979, 0.11924846, -0.09410989, -0.123036265) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.096586555, -0.30475244, -0.24065268, 0.053860847, 0.19413544, 0.05542323, -0.06327867, 0.012265184, -0.08913778, 0.13779551, -0.099127166, 0.007493773, -0.07125554, -0.0011684593, -0.003005287, -0.094847135) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.21711998, -0.13086027, 0.07825239, -0.21121782, 0.055840425, -0.0019166623, -0.05480048, 0.019817038, 0.007626905, 0.14126389, 0.04515749, -0.029315706, 0.18555732, -0.114861906, -0.21993469, 0.031716693) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.06716353, -0.11964145, 0.09711908, -0.061763637, -0.0948045, 0.14189975, 0.2810092, 0.2505306, 0.08872909, 0.086749084, -0.17528322, -0.048835423, 0.124959685, -0.12602286, 0.065660164, -0.06783225) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.23066516, -0.0068310793, -0.0021060852, 0.09136854, 0.09919007, 0.2259628, -0.026603302, 0.1367709, -0.07940821, 0.14962214, 0.00652088, -0.3114987, -0.18900892, -0.20450105, 0.09329685, -0.19482759) * go_3(0.0, 0.0);
|
||||
result += mat4(0.095197074, 0.06346413, -0.05207484, -0.086378016, 0.19733003, 0.1448027, -0.02410627, 0.024829205, -0.20296144, -0.09551166, 0.022987023, 0.09035918, -0.15824226, 0.1350293, -0.06641893, 0.11739518) * go_3(0.0, 1.0);
|
||||
result += mat4(0.08381447, -0.13171835, -0.030271608, 0.14649504, 0.0007350431, 0.15303299, -0.001797464, 0.30294403, -0.07635094, -0.102541, -0.12176348, 0.053775523, 0.08070882, -0.035387367, -0.09521456, 0.22530125) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.04650126, 0.12029137, 0.009236626, -0.1371486, -0.119391896, 0.20490645, 0.17123316, -0.015455403, 0.05842872, 0.14354227, 0.37586045, 0.054906923, 0.062954046, 0.07285954, 0.12260665, -0.08675996) * go_3(1.0, 0.0);
|
||||
result += mat4(0.22510684, -0.010087092, 0.005660375, 0.05069907, 0.10297958, 0.1411009, 0.09538159, 0.00922383, -0.31313825, -0.06449414, 0.109746836, 0.30148697, 0.35861742, -0.045380104, 0.09908991, -0.1933117) * go_3(1.0, 1.0);
|
||||
result += vec4(0.012253057, 0.13434875, -0.10318777, -0.074252345);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.04279202, -0.01698567, 0.18318103, -0.18172316, 0.04757184, 0.07232096, -0.054900512, 0.11956132, 0.048900753, 0.0006714882, -0.09200336, 0.16104606, 0.38940707, 0.2754208, -0.12735553, -0.30017206) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.2469705, 0.103162065, 0.10321547, -0.1292231, 0.3013039, -0.018333653, -0.19897339, 0.122247696, 0.14719778, 0.003909129, -0.19585025, 0.03670547, -0.2132921, 0.33642963, 0.17569672, 0.07414473) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.015335451, 0.15161209, 0.0447609, -0.042884503, 0.14257035, 0.07775234, -0.2064044, 0.03842874, -0.1660166, -0.19817057, -0.10740875, -0.123968095, 0.14156081, -0.2197906, -0.08622206, 0.4185408) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.33392438, -0.12483512, -0.062084857, 0.16336447, 0.09862199, 0.1659862, 0.034751434, -0.11968266, -0.017155796, 0.21001562, -0.053017724, 0.10386376, 0.07066254, 0.50014263, 0.31065208, -0.026068505) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.34320992, -0.030056434, -0.24118581, -0.024320357, 0.327435, -0.036838267, -0.19433706, 0.24561343, -0.1489437, 0.225435, 0.18421564, 0.021147838, 0.264245, 0.16846146, -0.51724315, 0.039252095) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.25945047, 0.12058094, 0.2889452, -0.061687145, -0.10309796, -0.19476385, -0.10393912, 0.16837607, -0.05198191, -0.036113493, -0.11847194, 0.16367626, 0.018113747, 0.059499823, 0.0062132217, 0.15846115) * go_0(0.0, 1.0);
|
||||
result += mat4(0.094601326, 0.053219795, 0.027610637, 0.12041253, 0.21425363, 0.15754686, 0.08518286, -0.00661778, -0.021661628, -0.17554528, -0.014842315, 0.22240937, 0.15908821, -0.20964032, 0.21754523, 0.30307937) * go_0(1.0, -1.0);
|
||||
result += mat4(0.13757955, 0.06684095, -0.03616685, -0.014618309, 0.04168136, -0.17148526, -0.16317028, 0.14210777, 0.102521434, -0.19108291, -0.14441934, 0.14435884, 0.24228935, -0.10589834, 0.24029285, 0.27317202) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.16239886, -0.073841535, 0.067964345, -0.11332664, 0.07695667, -0.047180675, -0.08260769, 0.09427637, 0.09471068, 0.012713836, 0.14605078, -0.062490974, -0.11498225, 0.04150893, 0.37402585, 0.21953487) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.07445113, -0.14220217, 0.09271495, -0.014715529, -0.37606132, -0.14938155, -0.024809113, 0.22279873, -0.011379667, -0.04545505, -0.033382278, 0.08971831, 0.016359061, -0.016230864, 0.052939463, -0.07754285) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.10961948, 0.09230085, 0.061259165, 0.0015837378, 0.053883027, -0.22557226, 0.018400123, 0.43234614, 0.08967873, 0.06687854, -0.4389578, -0.01658211, -0.040707946, 0.0048945122, 0.1433802, 0.049759727) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.027641231, 0.026085567, 0.109188825, -0.19011945, 0.19309571, 0.0084956605, 0.05034047, -0.08674781, -0.008124587, 0.031490494, -0.0744263, 0.084508896, -0.007835403, 0.13120581, 0.0021786217, -0.025225073) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.020191731, 0.24703082, -0.36845222, 0.0032569442, -0.1497622, 0.05968502, 0.09595371, 0.008410154, 0.119981945, -0.09983294, -0.19541258, -0.111814305, -0.25664008, 0.31031236, -0.23063917, -0.13823026) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.092747286, 0.23009373, -0.29804415, 0.05036082, 0.031480987, 0.18805481, 0.3676576, 0.06004687, 0.19841099, -0.058367446, -0.44229323, -0.19645047, 0.037667975, 0.12398346, -0.25753063, -0.26919344) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.019061154, 0.03841801, -0.28433323, 0.38128456, -0.059526864, 0.29960185, 0.014484517, -0.10234412, 0.05444907, -0.12615138, 0.14936689, -0.079120934, 0.028092088, 0.096715964, 0.0037780635, -0.12791039) * go_1(0.0, 1.0);
|
||||
result += mat4(0.26949528, 0.015951393, 0.15355164, -0.030336212, -0.100286454, -0.052609976, 0.03197625, -0.092190474, 0.06131517, 0.18291938, -0.15216532, -0.026021928, 0.18581273, -0.10659101, 0.14806952, 0.20509768) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.2205839, 0.11654808, 0.43800604, 0.03188946, 0.13840868, 0.020377772, 0.038510147, 0.03779825, -0.23494276, 0.08624197, 0.036650848, -0.115041405, -0.03776705, -0.32108167, 0.0094707385, 0.37881464) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.031778246, -0.38020673, 0.16956653, 0.33444092, -0.042172886, -0.03465591, -0.17585713, 0.025507452, 0.07595919, -0.06807453, -0.100295454, -0.019174794, 0.07763043, -0.09321411, -0.05212223, 0.112239085) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.048172995, -0.012284629, 0.12846173, -0.13459995, 0.25443402, -0.013064909, 0.15480834, 0.14016332, 0.036635883, -0.049085367, 0.0506487, 0.26623604, -0.023176057, 0.012088936, -0.1844897, 0.040488705) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.2147455, 0.17323543, -0.2943051, -0.053386763, -0.023367947, 0.090753146, -0.011997397, -0.0626111, -0.13558747, -0.035944186, -0.014752113, 0.25506687, 0.055502877, 0.31465453, -0.16283247, -0.08967175) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.033773236, -0.09510872, -0.09313707, 0.046486538, -0.1699796, -0.11685979, 0.22197925, -0.013884658, 0.12514, -0.12129843, -0.09695589, -0.075202964, -0.12321221, 0.18949097, -0.03694664, -0.2306249) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.08668444, -0.22983012, -0.30873656, 0.07371376, 0.082137264, -0.014844924, 0.2283955, 0.24782042, 0.31113505, 0.14810014, 0.32804835, -0.12014127, -0.17742543, -0.15872951, -0.080107674, -0.16898526) * go_2(0.0, -1.0);
|
||||
result += mat4(0.29746926, 0.19479977, 0.13996765, -0.4268552, -0.16478531, 0.0835479, 0.45685142, -0.05510062, -0.1282004, 0.12359051, 0.34026766, -0.26152933, -0.13128015, 0.329812, 0.27172327, -0.06600192) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.06552484, 0.19600633, 0.12407863, -0.13815112, 0.17426166, 0.040930413, 0.06495108, 0.034157254, -0.029772963, 0.015127817, 0.10718436, -0.13752984, -0.0205358, 0.1884735, 0.104591034, -0.020779913) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.053475305, -0.13616458, 0.05487909, 0.13256747, -0.10030239, -0.12376705, 0.062755466, 0.03264356, 0.068466686, 0.05019395, -0.034875803, -0.17806669, -0.21720818, 0.25592342, -0.2685692, -0.27576914) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.04562929, 0.04225299, -0.22311088, -0.09517893, -0.19886662, -0.11944208, 0.11044239, -0.10464355, 0.037634842, 0.124069214, 0.0927385, 0.108838566, -0.088783056, 0.17008123, -0.1007014, -0.23137446) * go_2(1.0, 0.0);
|
||||
result += mat4(0.10306672, 0.027472405, -0.069015354, -0.14412996, 0.24068132, -0.10624665, -0.25597134, 0.05208812, -0.10230778, 0.006520562, -0.11931577, 0.26738268, -0.09168354, 0.13557245, -0.008878644, -0.22292739) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.09403718, 0.11993688, -0.036254726, -0.053109076, 0.18422048, 0.25203657, 0.10025996, -0.11272799, -0.22040273, -0.05758331, -0.07059054, -0.054108664, -0.20009018, -0.22061199, 0.057880517, -0.26669186) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.08534496, 0.0027822452, -0.01112169, -0.13484463, -0.09446875, -0.057457812, -0.03910888, -0.2816038, -0.096015625, -0.03636662, 0.12532772, 0.092033, 0.038156748, -0.101240925, 0.024886698, -0.086328045) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.2349796, 0.19884427, -0.0734711, 0.08422328, -0.07201622, 0.020658491, 0.1331021, 0.039766714, 0.19280422, 0.13086005, -0.11339721, -0.14782044, 0.19341573, 0.16767374, -0.03593828, 0.18139753) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.040663462, -0.15233721, 0.524604, 0.26603413, 0.07202415, 0.053382196, 0.030758869, -0.06144292, -0.010495834, 0.13868876, -0.020688854, -0.15551737, -0.2958513, -0.32805985, -0.25359175, -0.036683984) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.06644081, -0.145321, 0.24945419, 0.031560224, 0.17245345, 0.23418438, 0.20341763, -0.2619872, 0.038787205, 0.16488725, 0.0019107185, 0.03820528, 0.04169643, -0.34155026, -0.11183654, 0.028614044) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.028469078, 0.010781976, 0.05263661, -0.15337946, -0.20491667, -0.13879907, 0.13934538, 0.061196275, 0.056804053, 0.063193604, -0.2389496, 0.037072126, -0.058510017, 0.036215063, 0.3074709, 0.10517675) * go_3(0.0, 1.0);
|
||||
result += mat4(0.028534278, 0.0022668538, 0.04492863, -0.060705435, 0.06349762, -0.016823182, -0.09148226, 0.03930522, -0.083295114, 0.14799853, -0.08089152, -0.21993661, -0.23298621, 0.05106244, -0.013708201, -0.16311577) * go_3(1.0, -1.0);
|
||||
result += mat4(0.05885827, 0.122300275, -0.16086812, -0.21892425, -0.07548077, 0.09286181, -0.027564062, -0.028723463, -0.0056181233, 0.23472206, -0.0049285595, -0.45054138, 0.07592325, -0.044704806, 0.019616256, -0.06956836) * go_3(1.0, 0.0);
|
||||
result += mat4(0.036423888, 0.20839189, -0.16420732, -0.15954947, -0.11311323, -0.24191359, 0.19845375, 0.084540576, -0.20946553, 0.09259613, 0.03234368, -0.056766506, -0.11992363, -0.06882079, -0.020428827, -0.093375795) * go_3(1.0, 1.0);
|
||||
result += vec4(0.013113342, -0.2905848, -0.029724011, 0.1769613);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf1
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.093678355, -0.08574688, 0.007699401, -0.038818456, -0.10667588, 0.043627866, 0.23127791, 0.061317544, -0.32790044, 0.08618836, 0.009400048, -0.17129329, 0.23541448, -0.015561885, -0.11172365, -0.1190039) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.0052874424, 0.08136584, -0.12633958, -0.016064916, 0.14033778, 0.07755252, -0.26242834, 0.063312635, 0.06861756, 0.14867078, -0.2561066, 0.33325562, -0.106489345, -0.10068009, -0.039633382, -0.016305668) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.27784392, -0.14990395, -0.35981888, -0.2564094, -0.07480205, -0.026457628, 0.1027643, 0.19381845, -0.07160986, -0.15616457, -0.032070953, 0.32998616, 0.15383582, 0.16622585, -0.1435993, -0.02287804) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.09360053, 0.58019537, 0.02028909, 0.413114, 0.025173154, -0.030326266, -0.028177274, -0.12964654, -0.25432733, -0.06556034, 0.023097439, -0.09458851, -0.21772051, -0.10324596, -0.36674342, -0.14803977) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.1227467, 0.20252965, 0.2559927, 0.08719227, 0.030749539, -0.2526622, -0.25694713, -0.2960799, -0.34960067, -0.25393236, -0.28439638, 0.086787805, -0.34202877, 0.21933395, 0.23473133, 0.079260886) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.00147522, -0.16591258, -0.030617915, 0.10052425, -0.1822102, 0.038774874, -0.04285007, 0.07312042, 0.052175622, -0.33510515, 0.027545406, 0.2995306, -0.08535316, 0.11144203, 0.27999434, -0.09770663) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.04394928, -0.26842886, -0.08354109, 0.04077001, -0.009221606, 0.0328837, 0.006459338, 0.08984004, -0.13035133, 0.20004508, 0.21950854, -0.12742348, 0.32386312, 0.085903555, -0.29273173, -0.056370437) * go_0(1.0, -1.0);
|
||||
result += mat4(0.019171638, -0.1824711, -0.10899421, -0.16201603, 0.054712642, -0.020315547, -0.048609916, -0.068621606, -0.055706583, -0.25671515, -0.019494208, 0.08366393, 0.09531471, -0.05988052, -0.024995802, 0.019303525) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.08694609, 0.26762635, 0.10477892, -0.15392998, -0.059596587, -0.047562487, -0.25932398, -0.054960977, -0.00015596532, 0.07196634, -0.017385524, -0.18826845, -0.017969077, -0.27291682, -0.153906, -0.107691295) * go_0(1.0, 1.0);
|
||||
result += mat4(0.17340474, -0.1285696, -0.04484238, 0.15782213, -0.06190358, 0.27896214, 0.28475145, -0.042519942, -0.19862229, -0.1354097, 0.14344497, 0.015599392, 0.18698554, 0.035121564, -0.018465763, 0.0010143917) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.13428356, -0.06612225, 0.19397905, 0.14209093, 0.1526626, 0.2617573, -0.15316434, 0.35452205, 0.05003259, 0.07679617, -0.008399171, -0.0062716682, 0.11833864, 0.1331285, -0.006803729, 0.22615404) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.0020632436, -0.173174, -0.15404437, 0.05430569, 0.21100305, 0.39063898, -0.019479724, 0.17396629, -0.061121427, -0.13424753, -0.008459669, -0.04975768, 0.20599939, -0.11374013, -0.21116278, 0.063624285) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.0073831948, -0.12009769, -0.16402034, 0.054093774, 0.061061747, -0.009054565, -0.02815144, -0.17071937, -0.22791979, 0.073427565, 0.25161973, 0.1011713, -0.23804636, 0.13810354, 0.09063126, -0.23065178) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.31885087, 0.21730177, -0.20516786, 0.04075695, -0.2736768, -0.38779113, -0.19445951, -0.14024325, -0.11824961, -0.102919355, -0.17858729, -0.013441498, 0.16320607, -0.27105078, -0.00019549616, 0.024509901) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.16024838, -0.3132909, -0.15461555, 0.34874174, -0.0051668375, 0.1811257, 0.3384939, 0.16381103, 0.047184363, -0.20424844, -0.1330078, -0.13795874, 0.21890834, -0.08242861, 0.22677775, 0.031102268) * go_1(0.0, 1.0);
|
||||
result += mat4(0.19408257, 0.016361775, -0.202373, 0.2245766, -0.008954751, -0.047279913, -0.09170596, 0.01567793, -0.0019059096, -0.07785436, 0.0756357, 0.09683383, 0.034215495, -0.030802004, -0.077977195, -0.1101297) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.1060503, -0.0044663083, -0.14942732, -0.11696249, -0.04550482, 0.11463188, 0.17801443, 0.07229662, -0.14176941, 0.02773344, -0.10770335, -0.08745911, -0.023052111, -0.17474785, 0.016645849, -0.059080444) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.050500304, -0.14716387, 0.04525464, 0.23543595, 0.08411192, 0.16031684, 0.1659825, -0.03595111, -0.012943453, 0.13354135, -0.051425032, -0.0075654723, 0.11174184, 0.1266808, -0.18799087, 0.10571744) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.15583408, 0.09837484, 0.19239932, -0.03557196, -0.05406335, 0.096456856, -0.13921897, -0.2212671, 0.28973594, 0.04017474, -0.25423512, 0.1522156, -0.10563249, -0.033190794, 0.101713456, -0.08922746) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.0787607, -0.14545321, 0.099762656, -0.2824299, 0.10130184, 0.019948835, -0.1013831, 0.06604923, 0.089561954, 0.28344154, 0.05757009, 0.04981809, -0.15927236, 0.008129835, -0.04280382, 0.10653281) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.28149363, 0.019583186, 0.25983065, 0.30190885, 0.055435803, -0.01970755, 0.04546505, -0.027456624, 0.43886992, -0.032305803, -0.23557569, 0.12753153, -0.18509789, -0.073295385, 0.0083466545, -0.08271229) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.016040009, -0.20475672, -0.015803276, 0.18247975, 0.21178837, -0.041543446, -0.24716362, 0.10105528, 0.19479224, -0.06583694, -0.09192672, -0.037776746, 0.09636229, -0.12086331, 0.13989103, 0.014564729) * go_2(0.0, -1.0);
|
||||
result += mat4(0.19923596, -0.4132588, -0.4254784, -0.33433357, -0.16956097, -0.25086832, 0.23311833, -0.08976422, 0.06432824, -0.0071802614, 0.0033370545, -0.11073493, -0.46609998, -0.09332235, -0.27287352, 0.052513942) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.06954148, -0.06908355, -0.01875471, -0.35067585, 0.038715206, 0.08843527, 0.28899097, -0.024983376, 0.05879495, 0.110363334, 0.055481512, -0.0046147215, -0.035302363, -0.2722019, -0.0829261, 0.21088009) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.101971015, -0.18584369, 0.1469676, 0.025965, 0.07205807, 0.08838771, 0.08537094, 0.023344917, -0.106373414, -0.09254277, -0.25996596, 0.24570447, 0.00590166, -0.20074098, -0.05443169, -0.10562662) * go_2(1.0, -1.0);
|
||||
result += mat4(0.12980327, -0.16834956, -0.1635997, 0.23437372, -0.07374834, 0.0062907683, 0.17292136, 0.0018093853, 0.04122969, -0.025285576, 0.29646805, 0.13402736, -0.040267725, 0.0011441729, -0.18658921, 0.12006417) * go_2(1.0, 0.0);
|
||||
result += mat4(0.13221453, 0.15109141, 0.07707579, 0.05148666, -0.039716493, 0.12869143, -0.012840577, 0.10953536, -0.05721115, -0.120122276, -0.07632444, 0.32949027, 0.00022400127, 0.22217369, 0.2180494, -0.028773604) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.08405412, 0.11332542, 0.120847605, 0.00520135, -0.13689686, -0.1459117, -0.029643068, 0.16147274, 0.21844815, -0.036921967, -0.12862785, -0.15930249, -0.11265427, -0.17471205, 0.0026749703, 0.2048758) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.03768306, -0.07585988, 0.046583172, -0.35557657, 0.012359812, -0.05498573, 0.19581361, -0.08186999, -0.008727976, -0.16623624, -0.03647879, 0.22760212, 0.048297524, -0.12502927, 0.08636729, -0.26437047) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.19518375, 0.17423135, 0.19473018, -0.22721744, -0.25087392, -0.17043075, -0.021999557, -0.27388734, -0.096786864, -0.012226921, 0.16101876, 0.030362492, -0.017619403, -0.2494354, -0.07336028, 0.06842719) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.13816363, 0.14551367, -0.08497621, 0.15563537, -0.01600614, -0.010629245, 0.007773828, 0.2733634, 0.13066974, -0.2223056, -0.12664202, -0.19242655, -0.13211249, 0.065143794, 0.23912583, 0.19819915) * go_3(0.0, -1.0);
|
||||
result += mat4(0.001870705, -0.0028601827, 0.14014813, 0.14659253, -0.037523735, 0.3726274, 0.13139205, 0.0112125, -0.16308945, -0.17571904, 0.12799808, -0.032106552, 0.013872656, 0.432307, -0.14197885, 0.24013121) * go_3(0.0, 0.0);
|
||||
result += mat4(0.117900506, -0.08039036, -0.17504077, -0.08337764, -0.0068703834, -0.07430392, -0.17125578, -0.3470726, -0.20989974, -0.019394008, -0.027336912, 0.18668686, 0.052886557, -0.023217537, 0.004054446, 0.055974416) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.055653654, 0.08726097, 0.01206228, -0.25783783, -0.08736529, 0.19947968, -0.010166337, 0.36168414, 0.20298903, -0.15769973, -0.21389212, -0.19638214, -0.093130395, -0.067289785, 0.10245741, -0.14167903) * go_3(1.0, -1.0);
|
||||
result += mat4(0.04559992, -0.102125205, 0.21949212, -0.07308472, -0.15511832, 0.23785073, 0.04275021, 0.085007004, 0.079402514, 0.10851189, -0.151969, -0.29738536, -0.0776658, 0.1113102, -0.18987878, -0.045522977) * go_3(1.0, 0.0);
|
||||
result += mat4(0.073690206, -0.016468357, 0.122353435, -0.023995928, 0.095143944, 0.23051415, 0.17702249, 0.030164838, -0.09111423, -0.14219609, -0.19734482, -0.24854833, -0.0067356345, -0.1760497, 0.22637916, 0.119141534) * go_3(1.0, 1.0);
|
||||
result += vec4(0.22705397, -0.029518934, -0.026397338, -0.08183741);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_7_tf
|
||||
//!WIDTH conv2d_6_tf.w
|
||||
//!HEIGHT conv2d_6_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.16737834, 0.35369134, 0.14049083, 0.017871622, 0.0058661173, -0.035960242, -0.039154284, -0.01920433, 0.0729212, -0.03617972, -0.42717552, -0.019914677, -0.30816802, -0.07726792, 0.2088459, -0.09198307) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.0991125, 0.11411345, 0.15300295, -0.09510225, 0.014268626, -0.42914182, -0.13365223, -0.19440699, -0.27214321, 0.085696176, 0.1527733, -0.21056797, -0.062475704, -0.023041902, -0.29080424, -0.54386055) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.30736786, -0.16801229, 0.07400606, -0.31128535, -0.11047924, 0.16556956, -0.33445996, -0.09190697, -0.06132585, -0.11021996, 0.014628762, -0.45183894, 0.08186993, 0.19378273, 0.113438204, 0.038364496) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.24129803, 0.29174972, -0.1250327, 0.14254767, 0.0026774528, 0.1742466, -0.021835174, 0.01668921, 0.13646975, 0.313305, -0.23293279, -0.16737306, -0.059818722, 0.06404477, 0.108172625, 0.22065729) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.3504013, 0.20759478, 0.28683922, 0.2771802, 0.13761812, -0.21180478, -0.17020214, -0.21419087, -0.031916566, -0.040439468, 0.39206958, 0.715565, 0.46198523, 0.05055317, -0.07409331, -0.050633535) * go_0(0.0, 0.0);
|
||||
result += mat4(0.122958206, 0.0071205017, -0.21314384, -0.22197853, 0.016202174, -0.15960938, -0.14601983, -0.023609173, -0.07586023, 0.099936776, -0.0480375, -0.08681468, -0.14976887, -0.38979456, 0.16078879, -0.12263952) * go_0(0.0, 1.0);
|
||||
result += mat4(0.1687149, 0.108331114, 0.10112296, 0.01738403, -0.06773097, -0.19410455, -0.09728116, 0.0013846151, -0.038603816, -0.05495021, 0.2453317, -0.40052003, -0.022453755, 0.045039784, 0.0474246, -0.2665161) * go_0(1.0, -1.0);
|
||||
result += mat4(0.06805519, -0.052276067, 0.052459523, -0.0033053474, 0.13439268, -0.06845637, -0.20462433, -0.09088968, -0.00096404477, -0.35103628, 0.15096465, 0.3285226, 0.018747555, -0.06623108, 0.1754265, 0.3211156) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.04583627, 0.122267574, -0.44002235, -0.20039988, 0.039372742, -0.16505809, -0.26659602, 0.12207268, 0.03337428, 0.23131758, -0.009866899, 0.010381569, 0.29676, -0.020599596, 0.17816995, 0.32852224) * go_0(1.0, 1.0);
|
||||
result += mat4(0.09469788, -0.12531966, -0.11786524, -0.3115985, -0.2213199, -0.012536277, -0.13176842, 0.14986996, 0.12069894, 0.2744789, 0.21674646, 0.46060535, -0.4101697, -0.55295914, 0.29993954, 0.114459395) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.18347421, -0.29010707, 0.29127017, 0.087738656, 0.17509815, 0.03982794, 0.1731455, 0.38041735, 0.110374, -0.25045586, 0.36446962, 0.016104888, -0.012112869, 0.10154983, -0.45384112, -0.11416608) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.033837743, -0.020894403, -0.287127, -0.21196121, -0.03255823, 0.2599821, -0.38386443, 0.30563655, 0.39044768, -0.112917066, -0.021323297, 0.12623324, 0.06885038, -0.20750642, 0.07642818, -0.103580445) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.1723114, -0.3726216, -0.21184283, 0.1761503, -0.24993578, -0.31068864, 0.19998416, -0.23127908, -0.052656204, -0.04243976, 0.4397144, 0.01863219, -0.04796025, -0.11009142, -0.0073631364, 0.2716381) * go_1(0.0, -1.0);
|
||||
result += mat4(0.04202001, 0.27142277, -0.027491128, 0.27428457, -0.11009916, 0.39839938, -0.7223327, -0.124673314, 0.08123618, -0.11884722, -0.20375855, -0.7179687, 0.30648115, -0.28195357, -0.3350774, -0.29778734) * go_1(0.0, 0.0);
|
||||
result += mat4(0.071278594, -0.09155223, 0.06417857, 0.08250104, -0.45117077, -0.023316784, 0.38917172, -0.19110887, -0.09265943, -0.2643835, -0.09707039, -0.33238646, -0.0818088, 0.17623149, -0.28457013, 0.13986786) * go_1(0.0, 1.0);
|
||||
result += mat4(0.019971045, -0.046649583, -0.03036858, 0.07944429, 0.26344573, 0.054998036, 0.07139812, 0.21139374, 0.08021858, -0.025791258, -0.0423707, 0.25174072, -0.021300986, 0.13209766, 0.19120613, 0.3840775) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.11456406, -0.33503455, 0.21409267, -0.056933913, -0.12204284, -0.37379473, 0.33474764, 0.38634798, 0.12618992, 0.1353635, -0.22651522, -0.3160159, 0.18621005, 0.024818055, -0.11935204, 0.014005666) * go_1(1.0, 0.0);
|
||||
result += mat4(0.1501391, 0.0014716414, -0.22049955, -0.10928345, -0.07085164, -0.08778668, 0.19251469, -0.4932493, 0.071784936, -0.06903646, -0.060333923, 0.020552203, -0.33637995, -0.22848415, 0.21518159, 0.23815839) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.04230713, -0.19312756, -0.0613665, 0.058912925, -0.17639293, -0.029920885, -0.027867602, -0.16602923, 0.10262268, -0.0743682, 0.15286638, 0.08042581, -0.042299524, 0.0022034592, 0.15304253, 0.049871147) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.004346093, -0.07895582, 0.02089975, 0.13429636, -0.1020282, 0.5270822, 0.017983409, 0.1531299, -0.02891241, -0.07050933, -0.18729019, 0.13855362, -0.11538968, 0.20733222, 0.1546878, 0.11550679) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.21800312, 0.20944421, -0.1817274, 0.022868395, -0.019241469, 0.038916696, 0.088702604, 0.1467791, 0.0048542274, 0.10344671, -0.0107803065, 0.23302868, 0.049728952, -0.016042534, -0.08694045, -0.0028224774) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.1570157, 0.08688841, 0.03926086, -0.040503077, -0.052700017, -0.1432353, -0.04516745, -0.09649034, -0.053716175, 0.07059194, -0.07360609, 0.26307717, 0.121471435, -0.13640986, -0.1113535, -0.38560814) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.014722592, -0.39773384, 0.28259715, -0.10905738, 0.07889424, 0.1415529, -0.15419348, -0.2064834, -0.15126482, -0.28288555, -0.0014232624, -0.26178944, -0.025823193, 0.008017357, -0.08547297, 0.26373458) * go_2(0.0, 0.0);
|
||||
result += mat4(0.2978961, -0.020236012, -0.101216674, 0.15498216, -0.0069343713, -0.088363856, 0.20511419, 0.23958007, 0.045810107, -0.19189738, -0.14137349, 0.04177724, -0.1394684, 0.0071990825, 0.06991723, -0.21052721) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.05615232, 0.22506002, -0.12479586, -0.0070057763, 0.092545755, 0.096306436, 0.041890718, 0.1226944, -0.07541768, -0.08369033, -0.15144373, 0.09310172, 0.28388003, 0.09935607, 0.11299509, 0.0014283776) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.005848455, 0.117699094, 0.23539856, 0.11006195, 0.10962903, 0.28139547, 0.18785141, -0.11635996, 0.057289902, 0.2370178, -0.29825503, -0.13706475, -0.3869794, 0.024066223, 0.36742347, 0.35919484) * go_2(1.0, 0.0);
|
||||
result += mat4(0.13744523, 0.09239356, 0.01173183, 0.119055405, -0.07841836, 0.0668925, 0.22598477, -0.016510552, 0.07971727, -0.17154713, 0.03333588, -0.13790733, 0.15421963, 0.2895701, -0.28440917, 0.015132756) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.054354303, 0.36663428, 0.02634933, 0.18688667, 0.0607547, 0.17321853, 0.086784445, -0.023283, 0.0027200899, 0.026914112, -0.07438439, 0.27042162, 0.09985293, 0.012430832, -0.20694605, -0.20363812) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.42759168, 0.15540305, -0.18979609, 0.0073875943, 0.034251947, -0.34551802, 0.53327596, 0.17446762, -0.25879666, 0.2780996, 0.11094055, 0.17597, 0.13790102, 0.2615357, 0.09666047, 0.36155468) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.052614138, -0.1880028, 0.361331, 0.07957976, 0.12552904, -0.0042941784, 0.096562445, -0.041199915, 0.07412456, 0.16379668, 0.05464284, 0.050022952, -0.028281605, 0.09332573, 0.21379845, 0.21396561) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.07546953, 0.16393837, -0.3060623, -0.64610606, -0.013715101, 0.18005042, 0.045286633, -0.21057944, -0.12779316, -0.10310629, 0.14360385, 0.011625261, 0.05597252, 0.023864657, -0.00018915108, -0.24224915) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.08550672, 0.2438917, -0.30383766, -0.2463794, 0.13835424, -0.079946786, -0.060197506, 0.051599402, -0.24983203, -0.06691107, -0.0041784844, 0.07539119, -0.030340329, -0.23565106, -0.17968354, -0.10262371) * go_3(0.0, 0.0);
|
||||
result += mat4(0.19315718, -0.045718513, 0.120446794, -0.225136, 0.22922774, -0.046026126, 0.11448238, 0.114267804, -0.22327735, -0.03368635, 0.29763463, 0.03673529, -0.0583939, -0.092253424, 0.045279544, 0.04475646) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.062286656, -0.06241419, -0.23600577, -0.24818502, -0.058666106, 0.17710151, -0.1751668, 0.05758226, 0.18278669, 0.033297777, 0.046349872, 0.09178792, -0.0745512, 0.20019765, 0.037281513, 0.22204825) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.24708512, -0.1318695, -0.24966322, -0.31206796, 0.079176836, 0.11837155, -0.12882641, -0.01013533, -0.009065797, 0.0789075, 0.016151598, 0.00020127615, 0.1450729, 0.10825556, 0.09322918, 0.07283566) * go_3(1.0, 0.0);
|
||||
result += mat4(0.2604332, 0.25550258, 0.07709474, 0.28426003, 0.10387355, 0.09152259, 0.18742633, -0.0073229484, -0.20327723, -0.26013616, 0.055792782, -0.1713302, 0.14862068, 0.06698207, 0.17608787, -0.11622757) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.20551574, 0.073114716, -0.21843387, -0.28057778);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_7_tf1
|
||||
//!WIDTH conv2d_6_tf.w
|
||||
//!HEIGHT conv2d_6_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.18413043, -0.12355504, 0.2708789, 0.17259507, -0.069752574, 0.12640886, 0.01075919, -0.028221423, -0.020598855, -0.17259665, 0.16907778, -0.10040477, 0.017177016, 0.0176426, 0.23724149, 0.14657862) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.16921899, -0.33950835, 0.37508205, 0.09996622, 0.13377811, -0.036743056, -0.11633877, -0.23046862, -0.009307903, 0.027441062, 0.054166224, 0.011627087, -0.22831611, 0.043198805, -0.12695734, 0.0062862337) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.17216596, -0.15588646, -0.14179194, 0.12487524, 0.10507964, 0.124544986, -0.0046104924, -0.116668865, -0.006100901, -0.022074439, 0.03376759, 0.10498887, 0.109659016, -0.03567928, 0.29972833, -0.045950003) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.29127, 0.21912472, 0.16494286, 0.027708547, 0.043136686, 0.04409876, -0.07686145, -0.13180132, -0.16630307, 0.15650205, -0.005864527, 0.03916553, 0.15750135, 0.1705246, 0.21626697, 0.06906506) * go_0(0.0, -1.0);
|
||||
result += mat4(0.055395894, 0.28228188, 0.114794776, 0.020619212, -0.031812593, 0.11964309, -0.24317431, -0.36277202, 0.54564184, -0.032843567, -0.118973784, -0.40999004, -0.118530475, 0.09256661, 0.06583871, -0.36627474) * go_0(0.0, 0.0);
|
||||
result += mat4(0.17914769, 0.33976436, -0.11220768, 0.1325754, 0.40586957, 0.3064959, -0.19086123, 0.014164092, -0.17376979, -0.0037554938, 0.11771888, 0.44933778, -0.15937245, -0.10635065, 0.084963776, 0.14630255) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.3723194, 0.21509883, 0.020062352, 0.094394304, 0.030794155, -0.11394617, -0.09103134, -0.0042343247, -0.28981096, -0.061873477, -0.17772584, 0.36440176, 0.007828069, -0.012121627, 0.25862312, 0.24646287) * go_0(1.0, -1.0);
|
||||
result += mat4(0.10368119, -0.06185447, -0.022830853, 0.10918094, 0.18888599, -0.09235343, -0.055134308, -0.2210923, 0.15334128, -0.3084707, 0.31606838, 0.39931116, 0.29489174, -0.24794856, -0.4799932, -0.2617589) * go_0(1.0, 0.0);
|
||||
result += mat4(0.32550937, -0.17103608, 0.3257806, -0.23358762, 0.20370598, 0.13325407, -0.020303056, -0.105462655, -0.22264756, -0.034177396, 0.36885822, 0.20504399, 0.36375418, -0.26149705, 0.022433946, 0.15646128) * go_0(1.0, 1.0);
|
||||
result += mat4(0.007481421, 0.005642636, -0.170087, -0.08915849, 0.6329519, 0.06880098, -0.20856442, -0.1801066, -0.1342754, 0.13643123, 0.26994216, -0.27503812, 0.018052012, 0.058687408, -0.19784917, 0.021157453) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.1486918, 0.12212738, -0.03104796, 0.08664756, 0.3464865, 0.27309546, -0.022896903, -0.32080007, -0.28113958, 0.74847424, -0.33735126, -0.04616876, -0.23119605, 0.4214322, -0.16457441, 0.09162191) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.15863913, 0.1303683, -0.06339421, 0.06328312, -0.3100047, -0.33906308, 0.13805804, -0.14923394, 0.4997829, -0.14977637, 0.02265068, -0.04585939, 0.29802153, 0.3767994, -0.031849556, -0.051892217) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.04541847, -0.13645087, 0.14119779, 0.06409465, -0.29877988, -0.0009743694, 0.028256422, 0.14978185, -0.13014801, -0.24171488, -0.10782599, 0.010709664, 0.21880737, -0.34132662, 0.22972895, -0.07159475) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.1510528, 0.115773134, 0.036761034, -0.284284, -0.35684052, 0.16348189, -0.105475456, 0.08259931, -0.6489164, -0.033928663, -0.04243186, 0.25324553, -0.31829014, 0.066608824, -0.11131264, 0.51919967) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.06517726, 0.1933327, 0.044391852, -0.013346896, -0.3033368, 0.106350735, -0.1351003, -0.13414839, 0.11720078, -0.24844061, -0.2900742, -0.047861837, 0.42789885, -0.47915378, -0.09643217, -0.22915216) * go_1(0.0, 1.0);
|
||||
result += mat4(0.109821886, 0.31451595, 0.13300805, -0.08792569, -0.023928089, -0.038061168, 0.17821129, 0.003772247, 0.14684688, -0.12646271, 0.16072205, 0.011095222, 0.09209181, 0.005167038, -0.08823252, 0.079890974) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.20074554, 0.39979288, -0.007316405, -0.047838025, 0.10849111, -0.22469573, -0.059183244, -0.13663793, 0.07881898, 0.105663374, -0.3152222, 0.08104766, -0.22965154, 0.118780024, -0.07886757, 0.073527716) * go_1(1.0, 0.0);
|
||||
result += mat4(0.1304303, 0.023158893, -0.081089824, -0.15955788, 0.42183343, -0.12898655, -0.14028409, 0.011985, 0.3977131, -0.313598, -0.148818, -0.048350018, -0.13534498, -0.12760727, -0.014968193, 0.06646305) * go_1(1.0, 1.0);
|
||||
result += mat4(0.18085147, -0.11859402, 0.117530234, -0.10420847, 0.1848264, -0.12192718, -0.18729533, -0.10098887, 0.011134682, -0.23658146, 0.12963286, 0.117404245, 0.054487415, -0.030003065, -0.32175776, -0.08044254) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.07251758, 0.073430285, -0.22191651, 0.030512359, -0.029650904, -0.15816379, 0.0418705, 0.04776615, -0.014070836, -0.14669086, -0.009874937, -0.015444495, -0.2747725, -0.061624944, -0.11261252, 0.14757589) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.09274913, 0.046194065, 0.05642919, -0.07803342, 0.23578037, 0.01224276, 0.015608659, 0.05847865, -0.091819406, -0.14424564, -0.034869857, 0.019276984, -0.031180726, -0.21905676, 0.100375675, -0.13659117) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.072157644, -0.13294607, 0.24301524, 0.048643183, -0.04338094, -0.0021709928, -0.06530963, -0.22672611, 0.07479903, 0.08388352, -0.07460508, -0.14517406, -0.072923675, -0.26912874, -0.2769797, 0.054033212) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.5648679, -0.28059873, -0.039906785, -0.39112374, -0.3841447, -0.20383365, 0.12607281, 0.16049421, -0.34394273, -0.022326993, 0.16646549, -0.23433913, 0.071224056, 0.048073303, 0.122035526, 0.14941359) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.11803124, 0.114169255, 0.018188128, 0.0053847185, -0.07537228, -0.048262373, 0.073838905, -0.041833423, 0.044405136, -0.03813592, 0.076818384, -0.06015139, -0.085042655, -0.14306667, -0.21477652, 0.31548396) * go_2(0.0, 1.0);
|
||||
result += mat4(0.19307283, -0.014985916, -0.14332882, -0.05549754, 0.14551677, 0.11406769, 0.2744144, -0.031179624, 0.17578745, -0.11309805, 0.010072839, -0.07453384, -0.23163621, 0.19061968, 0.11016298, 0.108093746) * go_2(1.0, -1.0);
|
||||
result += mat4(0.23180474, -0.12522835, -0.03218773, -0.0031955864, -0.14057393, 0.07269213, -0.20883523, 0.09332164, -0.16037942, 0.25845763, -0.002303125, -0.014625506, 0.17063208, -0.11648214, 0.13988028, -0.024688654) * go_2(1.0, 0.0);
|
||||
result += mat4(0.043369994, 0.12473897, 0.108142346, 0.10268199, 0.16159926, -0.17804666, -0.007889351, 0.07232418, 0.26326916, 0.0474316, -0.41637155, -0.11879895, 0.14051722, 0.08747377, 0.1162202, -0.06443569) * go_2(1.0, 1.0);
|
||||
result += mat4(0.0041097966, 0.109841965, 0.097240336, 0.08123332, -0.081065506, 0.12650634, 0.23450434, 0.09631333, 0.21942414, -0.108897425, -0.033703003, 0.047280088, -0.017764917, -0.058596086, -0.15305139, 0.09055131) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.26824722, 0.014116421, 0.11844865, -0.156046, 0.057152968, 0.21287468, -0.3243975, -0.18181354, -0.07131152, -0.17860547, 0.18918999, 0.15399154, 0.20270234, 0.11524436, 0.05146645, -0.18196748) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.2745638, -0.026905773, 0.045458756, 0.22942849, -0.21052304, 0.20649272, -0.03713028, 0.33655703, -0.12467089, -0.015030098, 0.15504798, -0.05647672, 0.18751477, 0.08505986, 0.04756538, -0.058810517) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.1737789, 0.06552432, -0.34797582, -0.05370679, -0.036056817, 0.085242435, -0.12802805, 0.03710984, -0.09883285, 0.08946925, -0.0446528, 0.07734006, -0.10973603, 0.262812, 0.14010249, -0.1543792) * go_3(0.0, -1.0);
|
||||
result += mat4(0.316673, -0.16414417, -0.23147403, -0.3080756, -0.056620106, -0.11389848, 0.0948114, 0.13236332, -0.40048537, -0.090742044, 0.12090404, 0.024549136, -0.19124876, -0.3007761, 0.16159211, -0.28620452) * go_3(0.0, 0.0);
|
||||
result += mat4(0.032962102, -0.05481415, -0.1185786, 0.18153866, -0.2105442, -0.03802839, 0.14060515, 0.072460145, -0.1523761, -0.11426362, 0.02610123, -0.053477813, -0.20768824, 0.04533907, 0.14381588, -0.041578818) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.021694858, -0.028784249, -0.09928565, 0.07335764, 0.1315628, 0.11288982, 0.078681685, -0.1229723, -0.09618894, -0.07387309, 0.04340066, -0.036534667, 0.37295115, -0.08176548, -0.16579813, -0.13485877) * go_3(1.0, -1.0);
|
||||
result += mat4(0.45979, -0.289226, -0.15456465, 0.0117592, 0.22803205, 0.15497394, -0.38995707, 0.005227681, -0.20515667, 0.17184737, -0.069968715, -0.24724679, -0.048521046, 0.013277072, 0.049562644, -0.05522196) * go_3(1.0, 0.0);
|
||||
result += mat4(0.14561136, -0.18995416, 0.18104567, 0.063063085, -0.09728072, 0.018328888, -0.17258182, 0.069259025, 0.15187183, 0.16760696, -0.14086077, 0.013297849, -0.07579904, -0.09294852, -0.24227127, -0.048749007) * go_3(1.0, 1.0);
|
||||
result += vec4(0.31939298, 0.03303962, -0.010749771, 0.084496394);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-Soft-(VL)-Conv-3x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!BIND conv2d_7_tf
|
||||
//!BIND conv2d_7_tf1
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
#define g_0 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_7_tf_tex(conv2d_7_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_7_tf1_tex(conv2d_7_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_7_tf_tex(conv2d_7_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_7_tf1_tex(conv2d_7_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.121882804, 0.055417646, 0.037575886, 0.0, 0.040015355, 0.10440659, 0.120197006, 0.0, 0.008896276, 0.07269119, 0.09253319, 0.0, 0.009000448, -0.033739295, -0.059260685, 0.0) * g_0;
|
||||
result += mat4(-0.048027042, 0.09210703, 0.123745404, 0.0, -0.007914943, 0.05483587, 0.054822505, 0.0, -0.005998682, 0.005822986, 0.009868176, 0.0, -0.05866792, -0.04236153, -0.022935968, 0.0) * g_1;
|
||||
result += mat4(-0.091270015, -0.033997003, -0.012321896, 0.0, -0.037983265, -0.078790314, -0.085029654, 0.0, 0.10656225, 0.0008334142, -0.0041227583, 0.0, 0.077364065, 0.033960085, 0.029391684, 0.0) * g_2;
|
||||
result += mat4(0.15057671, -0.037442014, -0.037083894, 0.0, 0.015493511, -0.016119987, -0.027061606, 0.0, -0.012329675, 0.0060544596, -0.019787522, 0.0, 0.12182345, 0.11346318, 0.08640806, 0.0) * g_3;
|
||||
result += mat4(0.19254518, 0.009179287, 0.023821035, 0.0, 0.020269603, 0.025629226, 0.040180814, 0.0, -0.025135614, -0.07785793, -0.099851295, 0.0, -0.122886, 0.03322616, 0.0509256, 0.0) * g_4;
|
||||
result += mat4(0.060054794, 0.053996198, 0.047226787, 0.0, 0.038959846, -0.025839888, -0.030583512, 0.0, -0.034999896, 0.011966571, -0.011057454, 0.0, 0.05765179, -0.041760337, -0.0694113, 0.0) * g_5;
|
||||
result += mat4(-0.20393562, -0.0055942894, -0.02089636, 0.0, 0.14781304, -0.01954523, -0.0746086, 0.0, 0.071556985, 0.07512172, 0.067927115, 0.0, 0.084076844, -0.0561336, -0.06856403, 0.0) * g_6;
|
||||
result += mat4(-0.039552618, -0.04448951, -0.04170605, 0.0, -0.00886809, 0.06708884, 0.07120977, 0.0, 0.04834384, -0.10599933, -0.11024835, 0.0, -0.015948117, 0.084044695, 0.10778199, 0.0) * g_7;
|
||||
result += mat4(0.050153337, 0.012563414, 0.014994658, 0.0, 0.10498867, 0.07151875, 0.06761489, 0.0, 0.061650798, -0.035183728, -0.050987806, 0.0, 0.0017240314, 0.041055307, 0.020366805, 0.0) * g_8;
|
||||
result += mat4(0.110105395, -0.044468552, -0.072567016, 0.0, -0.049364448, -0.015713394, -0.021540897, 0.0, -0.01636263, -0.084110685, -0.08281401, 0.0, -0.08940374, 0.047863875, 0.051104594, 0.0) * g_9;
|
||||
result += mat4(-0.081597924, 0.002422661, 0.01143175, 0.0, -0.07504751, -0.09938017, -0.1063178, 0.0, -0.10390281, 0.0262197, 0.060155805, 0.0, -0.24289346, -0.0054961476, 0.045964316, 0.0) * g_10;
|
||||
result += mat4(-0.1829316, 0.047622137, 0.07963877, 0.0, 0.048703995, -0.0026299425, -0.003712008, 0.0, 0.029338706, 0.096882835, 0.102083966, 0.0, 0.078538164, -0.07247937, -0.06820231, 0.0) * g_11;
|
||||
result += mat4(-0.02302231, -0.035528302, -0.030674051, 0.0, 0.029780716, 0.031591274, 0.045867007, 0.0, 0.01335752, 0.037001595, 0.04351411, 0.0, -0.11126892, 0.038589563, 0.06444906, 0.0) * g_12;
|
||||
result += mat4(0.0047764573, -0.063372664, -0.065609895, 0.0, 0.0478139, 0.025694113, 0.025097322, 0.0, -0.1019169, 0.029989049, 0.050038517, 0.0, 0.07504127, -0.017047737, -0.026222635, 0.0) * g_13;
|
||||
result += mat4(0.0024485083, 0.00640911, 0.008171829, 0.0, -0.014622121, -0.06078096, -0.0800138, 0.0, -0.0062360805, -0.014344496, -0.021332184, 0.0, 0.117842786, -0.103745885, -0.13756834, 0.0) * g_14;
|
||||
result += mat4(-0.01942775, 0.08720701, 0.104858086, 0.0, -0.05545872, -0.041375194, -0.035368554, 0.0, 0.080331706, -0.021207837, -0.043905254, 0.0, -0.12515299, 3.445463e-05, 0.018742712, 0.0) * g_15;
|
||||
result += mat4(0.013106969, 0.010379314, 0.012753471, 0.0, 0.07086715, -0.020893, -0.03968904, 0.0, -0.06114372, 0.029510446, 0.035070244, 0.0, 0.11180839, -0.087067656, -0.124039896, 0.0) * g_16;
|
||||
result += mat4(-0.056521703, -0.001166792, -2.3704073e-05, 0.0, 0.011961608, 0.01848977, 0.019861937, 0.0, 0.012167056, 0.018613879, 0.020505793, 0.0, 0.009734187, -0.0308419, -0.035206888, 0.0) * g_17;
|
||||
result += mat4(0.0048758825, 0.018046578, 0.014597015, 0.0, -0.061724614, 0.040989272, 0.05644141, 0.0, 0.070315465, 0.008318584, 0.0028647361, 0.0, -0.11316492, 0.043919202, 0.07653594, 0.0) * g_18;
|
||||
result += mat4(0.031487904, -0.010548384, -0.009984509, 0.0, -0.0022647562, 0.0043304027, 0.0029451603, 0.0, -0.0063251094, -0.013420807, -0.011919729, 0.0, -0.022760967, 0.019141173, 0.01782793, 0.0) * g_19;
|
||||
result += mat4(0.023055293, 0.028219413, 0.024810018, 0.0, 0.031653803, 0.050207954, 0.04504577, 0.0, 0.03877294, 0.0280465, 0.025589157, 0.0, 0.0019387804, 0.023891818, 0.016049948, 0.0) * g_20;
|
||||
result += mat4(0.006562233, 0.03880659, 0.037682824, 0.0, -0.021441424, -0.011277022, -0.012471097, 0.0, -0.030526241, -0.013880651, -0.014213582, 0.0, 0.0075785257, -0.0017350517, -0.0024610942, 0.0) * g_21;
|
||||
result += mat4(0.015097556, 0.020325955, 0.015611413, 0.0, -0.014755199, -0.034323387, -0.032325987, 0.0, -0.008603291, 0.010346807, 0.011044969, 0.0, -0.004739154, -0.026397636, -0.01995132, 0.0) * g_22;
|
||||
result += mat4(0.0097906375, -0.015094543, -0.016887931, 0.0, -0.0007786067, -0.0069163437, -0.008449091, 0.0, 0.025534432, 0.018064791, 0.017047096, 0.0, 0.00055667467, 0.001493328, 0.003636564, 0.0) * g_23;
|
||||
result += mat4(-0.042251963, -0.042396102, -0.040224236, 0.0, -0.004492444, -0.0069470624, -0.0065821502, 0.0, 0.062203273, 0.06213223, 0.053592753, 0.0, 0.06424337, 0.07964681, 0.07316769, 0.0) * g_24;
|
||||
result += mat4(0.026366957, 0.02789826, 0.027239393, 0.0, -0.006712127, -0.0035723334, -0.0032348586, 0.0, -0.04960562, -0.062758155, -0.058574595, 0.0, -0.02896146, -0.020999067, -0.021301663, 0.0) * g_25;
|
||||
result += mat4(-0.013106142, -0.017057793, -0.014653614, 0.0, -0.04254173, -0.043040022, -0.041918345, 0.0, -0.011146975, -0.0043820064, -0.003768677, 0.0, -0.0027743059, -0.0114479, -0.0082087545, 0.0) * g_26;
|
||||
result += mat4(-0.10087762, -0.10447133, -0.1005168, 0.0, -0.04165659, -0.04558967, -0.040086865, 0.0, 0.0016493691, 0.0055392827, 0.0070476984, 0.0, -0.018665023, -0.035552308, -0.03375731, 0.0) * g_27;
|
||||
result += vec4(0.018580848, -0.022256816, -0.0266178, 0.0);
|
||||
return result + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,873 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.1690102, -0.2560719, 0.39658326, -0.3679659, -0.27616683, -0.35619372, -0.3748396, 0.08430813, -0.29574734, -0.31511316, -0.09773105, 0.13616018, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.1326393, -0.259433, 0.025070239, 0.58914864, -0.036478516, 0.30723435, 0.007458902, 0.012962684, 0.2493056, 0.13007334, -0.08448256, -0.38414413, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.11539356, 0.35253766, 0.26143202, 0.2760807, -0.09371543, -0.028165473, -0.028452158, -0.27050856, 0.06718067, -0.0056619495, -0.17654495, 0.17288211, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.16145481, -0.3204927, -0.54317135, 0.11830119, 0.49315026, 0.12008072, 0.50857407, -0.30382085, 0.25807253, 0.020755528, 0.29388228, 0.106109895, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.22728722, 0.50484747, -0.07904469, 0.33114597, 0.50306976, -0.22760947, 0.14773269, 0.17628263, 0.14788547, -0.08223464, -0.10880935, -0.3151985, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.3414351, 0.057279214, -0.14419858, 0.09761111, -0.11794496, 0.021717256, -0.22750235, 0.13986664, -0.38932344, 0.28996095, 0.3773904, 0.13175532, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.1376552, -0.19587159, -0.35147396, -0.097646296, 0.1686707, -0.14385861, 0.031198, 0.12383533, -0.23089902, 0.08707301, 0.3362293, -0.100579016, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.056774966, 0.047585852, -0.36395878, -0.20211312, 0.4077735, 0.12631284, 0.39813092, -0.033365678, 0.2307249, -0.09131807, 0.20823865, 0.31084216, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.12456089, 0.09755632, 0.31490886, -0.06579996, -0.13386595, 0.07564795, -0.26605195, -0.075180635, -0.11182657, 0.06757017, -0.14351276, -0.16828312, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.046043985, 0.055581126, -0.08791638, -0.13022089);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf1
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.15485518, -0.29363206, -0.22610365, -0.14291525, -0.45240572, -0.18319772, -0.12209436, 0.15031648, 0.09878383, 0.06711082, 0.25763842, -0.084633484, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.10204406, 0.16167697, 0.22371867, -0.37947702, -0.24476196, -0.038824454, 0.060157117, 0.15764871, -0.08072927, -0.2210841, -0.31835055, 0.009979876, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.20506924, 0.21132155, -0.0922578, -0.07430473, 0.14529926, 0.20549752, 0.0077948375, 0.13246094, -0.32353187, 0.21074104, 0.092629515, 0.17590871, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.04125819, -0.44050243, 0.23729716, 0.3218237, 0.12943116, -0.011674174, 0.10390632, 0.027775545, -0.20308031, -0.16904089, -0.2121676, -0.022515794, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(0.09664124, 0.20127031, 0.60345304, 0.16697013, 0.23093723, -0.38116834, 0.109695725, 0.0007595324, 0.4092646, 0.009624758, 0.11229678, 0.25326383, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.014879592, 0.19204311, 0.07102085, -0.7312604, 0.34860876, 0.3429918, -0.027331594, 0.27636307, 0.1342437, 0.107820466, -0.12645108, 0.21081445, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.12687613, -0.09247973, -0.25973785, 0.4350873, -0.18987224, 0.028678741, -0.0903819, -0.63974863, 0.205591, 0.11308998, 0.18458389, -0.4149041, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.34691808, -0.025498383, 0.3428986, 0.21663484, 0.23404741, -0.1725327, -0.0036315925, -0.13299675, -0.1873967, 0.031331502, -0.08785591, -0.0013278709, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.35846514, 0.048703704, -0.104165934, 0.16529736, -0.15378916, 0.26030356, -0.07134151, 0.03692383, -0.15807101, -0.18885155, 0.044707954, -0.11444462, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.0022791293, -0.024132347, -0.57621074, 0.028573977);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.010346764, 0.07230188, -0.24734616, -0.09937907, 0.02228549, -0.19550583, -0.019540425, -0.1037373, 0.033996485, -0.075554, -0.20228972, 0.07090153, -0.09194035, -0.058972966, 0.1768268, 0.27517542) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.020078976, 0.12433655, -0.1620775, 0.036401592, 0.079748705, 0.11660013, 0.17917652, -0.017513236, -0.18936846, 0.24478136, -0.45726213, -0.045004416, -0.08295188, 0.067733586, -0.080548316, 0.2744211) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.024916803, 0.27562472, 0.043771956, -0.012240604, 0.0786355, 0.042651594, 0.16049327, -0.14577515, -0.032735053, 0.17658092, 0.16382934, -0.02337374, 0.11551492, 0.056343183, -0.17930213, 0.14259394) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.20010485, 0.06747722, -0.19026905, 0.11013709, 0.13062745, -0.044626113, -0.0062261797, 0.2189639, 0.1403497, -0.022713251, -0.19452858, -0.010305412, -0.06407589, 0.09836748, 0.025805516, 0.23430973) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.14664203, 0.034910418, 0.024714258, -0.066872925, -0.15717538, -0.14179383, -0.14091893, 0.05859166, 0.18919097, -0.18544437, -0.09068573, -0.08615929, -0.051434122, 0.2170678, 0.18409058, -0.17461225) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.11354446, 0.10745854, 0.2682663, 0.05949201, -0.10695986, 0.1407851, -0.03551388, 0.10691649, -0.17148238, -0.38287184, 0.2074456, 0.11828914, 0.048535194, 0.1464864, -0.18169662, -0.14074169) * go_0(0.0, 1.0);
|
||||
result += mat4(0.22160622, -0.1513045, -0.053284165, 0.033202525, 0.15574448, -0.043640967, -0.0093824165, -0.0019965349, -0.097964935, -0.08289824, 0.08239996, 0.07868361, 0.05731752, -0.20441617, -0.013016076, -0.253108) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.031249097, -0.2272863, 0.23573665, 0.03357689, 0.011395065, -0.10885564, -0.06287508, -0.031719524, 0.10331069, 0.17560169, 0.18303394, 0.022961004, -0.17011635, -0.24371737, 0.10678694, -0.3222825) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.1275465, -0.08844758, 0.10994917, -0.00910273, 0.09393154, 0.03894992, 0.14367905, -0.11811715, -0.09077633, -0.015776094, 0.27427456, -0.13283503, 0.18724327, -0.08139094, 0.04933602, -0.051852766) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.06764611, -0.27426586, 0.12045272, 0.09410856, -0.14258035, 0.11802992, -0.09093882, 0.0022018093, 0.4590643, 0.046258576, -0.07827223, 0.448011, -0.103631735, -0.016930219, -0.15421398, 0.11045997) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.17295076, 0.00151352, 0.14938255, 0.08336512, -0.07496541, -0.07561223, -0.0846474, 0.14979269, -0.09142163, 0.23925088, -0.015199518, -0.37749895, -0.20636298, -0.022585187, -0.20371509, 0.0745308) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.06458832, -0.009722021, -0.123604394, 0.06548835, -0.3039139, -0.022024399, 0.05297587, -0.0626883, 0.23556642, 0.1516464, -0.07004877, -0.1845364, -0.05918428, 0.19158973, -0.14983447, 0.030489758) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.36604697, 0.17516142, -0.10853731, -0.22694224, -0.107650936, 0.23013335, 0.094055794, -0.17047717, -0.3006048, -0.08621717, -0.18815655, -0.03570218, 0.09676118, -0.017718751, 0.059138596, 0.073388465) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.12791575, 0.101956226, 0.13091874, -0.046373338, 0.04955811, -0.04030444, 0.13869923, -0.046699073, -0.42611042, -0.7173929, 0.052184317, 0.6178025, -0.02929954, -0.07638965, -0.15000828, 0.030710017) * go_1(0.0, 0.0);
|
||||
result += mat4(0.057806686, 0.20842272, -0.20148766, 0.006666912, 0.13356528, -0.45265228, -0.07354092, 0.21447696, 0.019552143, -0.13645506, 0.14643854, -0.0071413796, -0.15487236, -0.002250615, 0.30622452, 0.0033902125) * go_1(0.0, 1.0);
|
||||
result += mat4(0.06896002, 0.24397352, -0.06479052, 0.20676947, -0.24259068, 0.055320013, -0.09032122, -0.11222854, -0.08982342, -0.114818625, -0.06399291, -0.3024516, -0.06302166, -0.1925528, 0.03458982, 0.028828239) * go_1(1.0, -1.0);
|
||||
result += mat4(0.09764086, 0.09599894, -0.0073313303, 0.14418933, -0.045712367, 0.12657364, 0.04620374, -0.069778584, 0.30047333, -0.012418192, 0.15516461, -0.18087754, 0.08178273, 0.14262857, -0.01741533, -0.12509112) * go_1(1.0, 0.0);
|
||||
result += mat4(0.04697884, -0.1506804, 0.031823065, 0.13397239, -0.18396698, 0.10681781, -0.29586303, -0.0039136545, 0.17560847, -0.12486726, -0.018646788, -0.20688744, -0.030614454, -0.0527634, 0.23593572, -0.10542146) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.19182229, -0.32615846, 0.26283535, -0.1371942, -0.071202695, 0.12056063, -0.11450658, -0.27711076, -0.42096004, 0.0014352369, 0.1559669, -0.14464542, -0.17973948, 0.079166576, -0.12501791, -0.20623216) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.12469872, 0.32190827, -0.059510354, 0.1393449, -0.12845798, -0.019571869, -0.22630808, -0.14031963, 0.36072046, 0.05858427, 0.19278921, 0.121090546, -0.067538865, -0.018770566, 0.14318037, -0.15561756) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.024663208, 0.21110268, -0.016415706, 0.060093414, -0.03739678, -0.107412934, -0.077527136, 0.30331334, 0.17196326, -0.15512557, -0.09499732, -0.15748607, -0.16680105, -0.015185634, 0.16114107, -0.21288376) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.17739037, -0.1190967, 0.13191372, -0.2527187, -0.14992718, -0.30511454, 0.19145966, 0.002194003, -0.12888977, 0.19152176, 0.27528167, 0.099714965, 0.12865707, -0.12051514, -0.055013947, 0.26231763) * go_2(0.0, -1.0);
|
||||
result += mat4(0.46433613, -0.11708138, -0.20157282, 0.32022122, 0.079468675, 0.029407484, 0.2559102, -0.15651533, 0.08644574, -0.09747344, -0.07528584, 0.17354868, 0.19167562, -0.17698488, -0.09896657, 0.17093097) * go_2(0.0, 0.0);
|
||||
result += mat4(0.20283653, -0.33680332, 0.2282385, 0.18832158, 0.20866042, 0.00076752366, 0.16471444, -0.21548858, 0.16193539, 0.17141372, 0.03140222, 0.03913644, -0.030161971, 0.00014570929, 0.08993654, -0.064823024) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.3075755, 0.19942546, 0.015526995, -0.120868504, -0.254515, -0.07791228, 0.03271691, 0.11794217, 0.11258601, 0.045204375, -0.061196107, -0.115958795, 0.3861869, 0.048215542, 0.07016682, -0.009975758) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.07623697, 0.16094944, -0.02283455, 0.14112763, -0.051149167, 0.20429814, 0.011314802, 0.18914083, -0.24240434, -0.08784008, -0.16763984, -0.08492233, 0.31062725, -0.11925119, -0.33195966, 0.2060798) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.016709225, -0.14472668, -0.3677625, -0.09832719, 0.030297454, -0.05775362, -0.1401375, 0.08119674, -0.01795042, 0.05183797, -0.24320887, 0.066842034, -0.22245285, -0.02740993, 0.06316751, 0.053399116) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.039214406, -0.08876633, 0.045552462, 0.19226661, 0.1355001, -0.13942362, 0.17398876, 0.2914014, -0.191809, 0.037143208, 0.013333581, -0.16632195, 0.113767646, -0.106692605, 0.1589787, 0.030107044) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.21997562, 0.13855208, -0.05783191, -0.033682413, -0.010961168, 0.10524961, 0.02177416, 0.18289444, 0.043692037, 0.07853899, -0.039936125, -0.1004449, 0.04494073, -0.020680292, 0.17578089, -0.106598996) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.026852835, -0.16037546, 0.11278316, 0.12656097, -0.006857894, -0.03400118, -0.051564034, 0.00085412664, -0.37556714, -0.05279987, 0.029383834, -0.14246808, -0.056380164, -0.002399925, 0.16025752, 0.036324855) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.022709966, 0.046350412, 0.03390721, 0.02810572, -0.14394265, 0.04215361, -0.3206118, 0.15034916, -0.0028448137, 0.1682989, -0.042686664, 0.020543462, -0.2786501, -0.007482015, -0.040313292, -0.20745736) * go_3(0.0, -1.0);
|
||||
result += mat4(0.05417556, 0.18728684, -0.046121832, -0.27939513, 0.05907976, -0.09191223, -0.16625418, -0.26038164, 0.39956605, -0.052594025, -0.0596556, 0.29517552, -0.015181923, -0.0763375, 0.25131205, 0.13038464) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.036903054, -0.0066989153, -0.062650286, 0.05614359, -0.0064960583, 0.028512698, -0.10906273, -0.010047654, 0.23030473, 0.049983572, 0.10439064, 0.26643834, 0.05041243, 0.09185424, -0.32352915, 0.11295159) * go_3(0.0, 1.0);
|
||||
result += mat4(0.09724027, -0.34962535, 0.06586686, 0.016635379, 0.13831381, 0.01707076, -0.04690347, 0.022350075, 0.018352794, 0.022000022, 0.070613205, 0.117735535, -0.025971051, 0.18832101, -0.09643588, -0.08512127) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.17324433, 0.06810613, -0.057295907, -0.05115964, -0.101570815, 0.12491774, 0.08762367, -0.005862404, -0.05342927, -0.031942457, -0.039624047, -0.04298937, -0.1303138, -0.11869282, -0.024832053, 0.070463404) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.010514842, 0.1376259, -0.11750346, -0.03786737, 0.03459249, 0.015408171, -0.031430878, -0.060825355, -0.072958425, -0.0037895301, 0.041686177, -0.12352204, -0.06261361, 0.054514423, -0.34072715, 0.13860728) * go_3(1.0, 1.0);
|
||||
result += vec4(0.018166734, -0.11002478, -0.05554318, -0.0988193);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf1
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.040142782, 0.0288423, 0.07569487, -0.01490842, 0.14402796, -0.13682005, 0.027765118, 0.03907358, 0.07117706, 0.058157545, -0.23862502, -0.057674367, -0.19220531, 0.0147159435, -0.18028538, 0.0963821) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.1676744, -0.11937339, 0.12137117, 0.07119485, 0.14148116, -0.043578617, -0.029261118, -0.0016938087, -0.057269357, -0.080076694, 0.12193026, 0.07326153, -0.056278303, -0.01630716, -0.03792076, 0.1483611) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.3021578, 0.011601693, 0.11266048, 0.19086999, -0.0122412145, 0.08431291, 0.11615175, -0.008039614, -0.39987534, 0.07820729, 0.03509667, 0.1963505, -0.08839513, -0.21571854, 0.059425723, -0.06830175) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.23135209, -0.12452708, 0.0943565, 0.0028859286, -0.09836373, 0.10681712, -0.3535964, 0.08457615, 0.045332734, 0.16579892, -0.03809797, -0.021596594, 0.2937497, -0.028294371, 0.046484597, -0.037604347) * go_0(0.0, -1.0);
|
||||
result += mat4(0.072675414, -0.16431206, 0.28952035, 0.0076831076, -0.020242939, 0.029483542, -0.092415355, 0.08673106, 0.12109694, 0.14307201, 0.23134442, 0.11731775, 0.09981601, -0.16968462, 0.037470713, 0.14948717) * go_0(0.0, 0.0);
|
||||
result += mat4(0.0029752052, 0.06526503, 0.1866458, 0.07451277, -0.31836876, 0.17115082, -0.13969697, 0.23844297, -0.03244903, -0.08832665, 0.023691226, -0.18230624, -0.074933805, -0.00044301842, 0.050572682, 0.081511915) * go_0(0.0, 1.0);
|
||||
result += mat4(0.039502528, 0.051221415, -0.13968123, -0.091212444, -0.016925618, 0.15409444, -0.017455677, -0.11653652, 0.03539446, -0.00087720866, -0.12839639, 0.037198763, 0.03674469, -0.26444665, 0.019721227, -0.13013805) * go_0(1.0, -1.0);
|
||||
result += mat4(0.039229527, 0.25667152, 0.0032586441, -0.00718359, 0.1617932, 0.10409968, 0.07182867, -0.09810605, 0.07789241, -0.02014911, 0.025767172, -0.14604759, 0.07175764, 0.32513744, -0.20473222, -0.16266066) * go_0(1.0, 0.0);
|
||||
result += mat4(0.13418433, 0.061813723, -0.13927278, -0.2498272, 0.03468218, 0.29483125, 0.063289374, -0.04726235, 0.1898295, -0.33132064, 0.032045014, 0.02159535, -0.1148363, 0.31306976, 0.06456038, 0.048988886) * go_0(1.0, 1.0);
|
||||
result += mat4(0.07151646, 0.2799246, -0.107190795, -0.16431166, -0.28007045, 0.07206954, 0.06775463, 0.009758042, 0.07032184, -0.20843789, 0.087045245, 0.1360676, -0.25718534, 0.028249472, -0.12614648, 0.009949602) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.020241471, -0.23390484, -0.0083223935, 0.08344701, 0.08222297, 0.12026539, -0.08652223, -0.08228822, -0.039576706, -0.24677879, -0.1157289, 0.2590508, -0.23809408, 0.19911982, -0.116798095, -0.035870325) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.024991842, 0.050509237, -0.024134455, -0.12659028, 0.24089767, 0.122712664, -0.10482493, -0.19403952, -0.19177693, -0.06538376, -0.041478425, 0.32176673, -0.1534002, -0.18680622, 0.06763643, 0.020806564) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.03437814, -0.28067374, 0.2830681, 0.038812317, -0.021698112, -0.120865285, 0.22695538, -0.045419116, -0.030475847, -0.01977341, -0.1265364, -0.3109814, 0.012255813, 0.053917278, -0.018620957, -0.14599285) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.016204128, -0.04093018, 0.054571863, 0.02679643, 0.01756274, -0.057685968, 0.16148666, 0.17370272, -0.11065411, 0.06378157, -0.09331551, 0.22985275, 0.057905316, 0.12323568, 0.07748665, 0.09878629) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.018112244, 0.063234635, -0.013184602, 0.16241394, 0.08877139, 0.02145378, -0.02490027, -0.038920373, 0.13127136, 0.14391647, 0.020553736, 0.14401346, 0.06685973, -0.25398204, 0.10369067, -0.055949755) * go_1(0.0, 1.0);
|
||||
result += mat4(0.07710333, 0.047412727, 0.13813803, 0.18624061, 0.16907091, -0.039532468, 0.06234584, 0.06408178, -0.054543987, -0.045220226, -0.11093376, -0.37399602, 0.20372874, 0.004580967, -0.07742308, 0.017989937) * go_1(1.0, -1.0);
|
||||
result += mat4(0.003485311, -0.08897399, -0.013108594, -0.19473282, -0.27081844, -0.16812073, 0.0052992934, -0.055331517, 0.09446357, 0.019280333, 0.16560757, -0.3230032, 0.043096773, 0.059222896, -0.064184934, -0.059852477) * go_1(1.0, 0.0);
|
||||
result += mat4(0.06794279, -0.034135245, 0.083064295, 0.13506731, 0.13064219, -0.44978833, -0.03513717, 0.08999715, 0.1124541, 0.42208397, -0.0038724816, -0.014332087, -0.13751853, -0.04929869, 0.09134992, -0.17687531) * go_1(1.0, 1.0);
|
||||
result += mat4(0.100909084, -0.0131197255, 0.082274795, -0.2138443, -0.08515947, -0.021058358, 0.10951775, -0.06349191, -0.29129833, -0.029262653, 0.25235432, -0.11748315, 0.121980384, 0.062347785, 0.10916932, -0.15993518) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.28893283, -0.05677308, -0.2641288, -0.058937225, -0.16187571, 0.006647366, -0.063294955, 0.04766719, 0.60601914, -0.07831864, -0.15710756, -0.011491797, 0.15587467, -0.08105375, 0.07847514, -0.2803333) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.077989794, -0.09871811, -0.3516344, 0.15292728, 0.010889273, 0.0011189661, -0.16118282, -0.018821161, -0.039708678, -0.00060983415, -0.06367813, 0.009148068, 0.03919827, 0.18782744, 0.028040757, -0.10230145) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.4079609, 0.18640275, -0.12475227, 0.13891742, 0.25121725, 0.16942379, 0.14409852, 0.087600805, 0.045335658, -0.12683709, -0.0077387216, 0.06563413, -0.19857128, 0.106910795, -0.048285246, 0.10768945) * go_2(0.0, -1.0);
|
||||
result += mat4(0.5989075, 0.20941062, -0.20086494, 0.13344856, 0.073034994, 0.22358665, 0.101664364, -0.13463663, 0.18816395, -0.061176624, -0.14712185, 0.027320342, -0.09529667, 0.031148786, -0.28744993, 0.18698911) * go_2(0.0, 0.0);
|
||||
result += mat4(0.14799193, 0.39471942, -0.23340325, -0.4031061, 0.18926248, -0.11091216, 0.118981816, -0.09155061, 0.17049436, 0.19803695, -0.1513267, 0.023817873, 0.0090933135, -0.04134864, 0.060486555, 0.03536634) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.39094314, 0.01779997, 0.12710269, 0.0067333193, -0.31255835, -0.08206612, -0.048528638, 0.369439, -0.19351655, -0.03420455, 0.15831526, -0.052294146, -0.08481741, 0.0787108, 0.1312136, -0.108919285) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.16068119, -0.42190582, 0.19383872, -0.018445708, 0.09803051, -0.020769652, -0.022599563, -0.052448895, -0.20645833, -0.031432863, 0.0025441595, 0.03410379, -0.20268854, 0.04481527, 0.05191063, 0.42317194) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.12786235, -0.23936178, 0.116561726, 0.30756372, -0.09420156, -0.044529166, -0.03585749, 0.1829332, -0.23939075, 0.24030831, 0.019878127, -0.015069802, 0.24300557, -0.22558568, -0.104956664, -0.09393648) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.04607054, 0.012677649, -0.027597688, 0.1618836, 0.29210827, 0.014221155, -0.13591036, -0.06895336, -0.09559534, 0.07956421, -0.11112994, -0.13325493, 0.24562472, 0.11046177, 0.057847694, 0.0016315983) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.03365951, 0.027391057, 0.09653403, -0.14718771, -0.049631152, -0.06467214, -0.058545876, 0.1424002, -0.06320376, 0.181183, 0.10249362, -0.16052136, 0.3013475, -0.04156266, 0.08862033, 0.06888033) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.10045977, -0.004198456, -0.025856055, 0.05739418, -0.1328637, -0.025975171, 0.06553717, 0.11301186, 0.0704087, -0.083569765, 0.16066101, -0.24453588, 0.25370175, 0.037184533, 0.062386766, -0.20025635) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.017958941, 0.06417776, -0.1525265, 0.12451173, 0.14567685, -0.0049682115, -0.23973411, -0.0783304, -0.010629432, 0.08055161, 0.2028341, 0.17640644, -0.20445108, -0.055524793, -0.019326134, 0.081288636) * go_3(0.0, -1.0);
|
||||
result += mat4(0.007882519, -0.03722546, 0.053249408, 0.00071846246, -0.07053029, -0.21583866, 0.1415364, -0.19486657, 0.20685542, 0.17660026, -0.32156837, 0.1746825, -0.14957622, -0.09224378, -0.098153435, -0.13054638) * go_3(0.0, 0.0);
|
||||
result += mat4(0.10051427, -0.17398237, 0.09842799, -0.14187703, 0.116901085, -0.1229543, -0.0007776771, -0.20410055, -0.11373484, -0.111150615, -0.1974002, -0.11641459, 0.024105398, 0.24985977, 0.015871854, -0.10724633) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.18081793, 0.1209351, -0.12867971, -0.019415248, 0.062617876, -0.037130393, -0.07803658, -0.22862352, 0.2586428, -0.030090366, -0.11894069, 0.18087515, -0.40921417, 0.070013195, 0.030540073, 0.035120826) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.13185939, 0.12992652, 0.08125049, 0.075331174, 0.064219765, 0.056629725, -0.020012032, -0.0855444, -0.044063166, -0.05396545, -0.028002812, 0.21837157, -0.15206428, -0.12681007, 0.14895032, 0.12339962) * go_3(1.0, 0.0);
|
||||
result += mat4(0.08066341, -0.14773634, -0.0212227, -0.014011867, -0.048505764, 0.075407125, -0.020620076, 0.0003291325, -0.21815202, -0.23136546, 0.10853532, -0.036058456, 0.10952532, -0.052677035, -0.13005799, 0.18398996) * go_3(1.0, 1.0);
|
||||
result += vec4(0.022609137, -0.028548084, 0.024431901, 0.010504478);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.069641694, 0.104958326, 0.14786446, 0.027633663, -0.004279524, -0.020451711, 0.0883571, -0.016224537, 0.13585235, 0.11078269, 0.20198658, -0.042161036, 0.020466218, 0.20994963, 0.20072585, -0.028024657) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.050872434, 0.12874635, 0.1298729, 0.115810685, 0.07087254, 0.09885682, 0.23018982, 0.19187538, 0.10953604, 0.0033836907, -0.13325337, 0.09830315, -0.06528767, 0.05096927, -0.016355392, -0.039334368) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.027010268, 0.018263958, 0.0360758, 0.016791478, 0.2815702, 0.15517488, 0.43415815, 0.044976447, -0.0070842914, -0.12546758, 0.16874593, 0.077622116, 0.02252915, 0.1769774, 0.07181055, -0.15128697) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.057129618, 0.118046716, 0.07237424, -0.07842637, -0.044214778, -0.12886304, 0.08603301, -0.10416606, -0.15852053, 0.3788151, 0.26181692, -0.09092249, 0.31635332, 0.064212754, 0.21923725, 0.07500004) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.16981383, 0.044409662, -0.3717617, -0.031610407, 0.03658662, -0.09459229, -0.09449437, -0.014000666, -0.19656453, 0.03934163, -0.16304104, -0.12761801, -0.06235523, 0.16438273, -0.036933117, -0.095564745) * go_0(0.0, 0.0);
|
||||
result += mat4(0.09725091, 0.034022827, 0.17699842, 0.1079676, -0.13236652, 0.03718181, -0.06968635, -0.23288171, 0.10275666, 0.08464966, -0.37162134, -0.35782215, -0.11023659, 0.2519236, -0.035197742, -0.019324787) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.09968464, 0.01102193, 0.0073735216, 0.011999313, -0.004998707, 0.09518938, 0.045727003, -0.21544908, 0.006879454, -0.06398254, -0.12584935, -0.06759933, -0.0820037, -0.07775104, 0.021957919, -0.122708224) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.08869767, 0.031296413, -0.0034280645, 0.13778855, 0.10073061, -0.08393937, -0.032959275, -0.0500518, 0.010908757, -0.09189417, -0.057760105, 0.17652664, -0.08729078, -0.09639096, -0.25654703, 0.055152636) * go_0(1.0, 0.0);
|
||||
result += mat4(0.0027847723, -0.12885433, 0.038065907, 0.17450769, 0.0864409, 0.04592345, -0.015443841, 0.077010944, 0.08967368, 0.06800111, -0.23636387, 0.35023567, 0.03165923, 0.03132063, 0.17964344, 0.035610788) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.032017227, -0.0022808525, -0.08470573, 0.05332408, -0.14674746, 0.025374275, -0.018281924, 0.041163016, 0.00096549373, 0.014724006, 0.004913065, 0.18494442, 0.034953076, -0.15731992, -0.13792977, 0.08041999) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.08305006, 8.6318905e-05, -0.007895379, 0.02731387, -0.061324496, 0.050034665, 0.22662131, -0.013876427, -0.074468784, -0.008136604, -0.23337875, -0.1742574, 0.011753501, -0.11666686, -0.22541048, -0.14549944) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.028333234, 0.121047184, 0.06720256, -0.058930036, 0.030258363, 0.07292774, 0.06455556, 0.0019076486, 0.0073987027, 0.17144889, 0.06084024, -0.08762086, -0.114422195, -0.16595861, -0.08706028, -0.10736261) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.02519315, -0.14611271, 0.0388848, 0.19481422, -0.05970354, -0.08391417, 0.18982239, -0.10447052, 0.15587378, -0.023997072, 0.0781739, 0.2182389, -0.023886079, -0.1422596, -0.13352804, 0.005008043) * go_1(0.0, -1.0);
|
||||
result += mat4(0.08842712, -0.100292705, 0.18925671, 0.12198875, 0.061771665, -0.04473232, 0.025053164, 0.039047796, -0.1672479, -0.08934517, 0.33099812, -0.20269585, -0.21640155, -0.22029749, 0.16539703, -0.2442679) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.16332205, -0.101898365, 0.02919932, -0.11900455, 0.14442924, 0.0916815, 0.037550304, 0.024123482, 0.02042624, 0.033472955, -0.059437107, -0.18735693, -0.013749093, -0.06199881, -0.08685079, 0.04252364) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.09047013, -0.055188328, -0.09106191, -0.048969727, 0.05114009, -0.12753403, 0.07116141, 0.060749624, -0.074034564, -0.21952136, -0.09479503, 0.2753584, -0.014141759, -0.14883812, -0.0673838, -0.012279045) * go_1(1.0, -1.0);
|
||||
result += mat4(0.013816464, -0.0747162, -0.19202435, -0.064403646, 0.34980014, 0.04375546, 0.20264609, 0.006684355, 0.11523799, 0.024674915, -0.08697566, -0.04662527, -0.12743855, -0.39463726, 0.0057380227, 0.01286557) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.08146522, 0.074080914, -0.16856177, -0.183158, 0.19228102, 0.12373886, 0.017574452, -0.01753772, 0.045071773, 0.07725093, 0.023422163, -0.011545186, 0.20751388, -0.10795588, 0.07606346, 0.10282933) * go_1(1.0, 1.0);
|
||||
result += mat4(0.12512013, -0.102208994, -0.09125398, 0.12043188, -0.066011876, 0.08831903, -0.017038671, -0.005541508, -0.049607087, 0.08654939, -0.02037085, 0.26887566, 0.005012545, 0.01869507, -0.013064982, -0.010649147) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.006824864, -0.05071593, -0.20786697, -0.07327317, 0.011382597, 0.030494886, -0.04754353, -0.018284699, 0.01305972, -0.036589053, 0.26637617, 0.021887446, -0.026669119, -0.037982125, -0.063445956, -0.009104248) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.032602567, 0.07094331, 0.052653246, 0.08342047, -0.085082285, -0.14674088, -0.23073354, -0.07915851, 0.0017120204, 0.032407638, -0.039819505, 0.16942178, 0.023192152, -0.0353237, 0.10930186, 0.22939779) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.0010455973, -0.11821993, -0.12639599, 0.12250084, -0.12756817, 0.11478416, -0.1862587, 0.016819192, 0.02110181, -0.25492984, -0.1766048, 0.22188173, -0.21305011, 0.113442205, 0.04599144, -0.15840286) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.15086032, -0.17428935, 0.39080557, 0.07576757, 0.121703945, 0.17944208, -0.003140103, -0.11231332, 0.12102969, 0.15310267, 0.17578171, 0.40631834, -0.21299168, 0.024928993, 0.030104794, 0.020753227) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.098734386, -0.020072265, -0.14308836, -0.08490801, 0.017175158, 0.02250534, 0.04060829, 0.033022214, 0.0046218676, 0.17923212, 0.0112105915, 0.09574084, 0.14819936, -0.14692923, 0.12634254, 0.060762513) * go_2(0.0, 1.0);
|
||||
result += mat4(0.030521613, -0.097913325, -0.016720278, 0.11273997, 0.013019863, -0.06557118, 0.0405774, 0.0915019, 0.022414956, -0.053254984, 0.18639986, 0.07820968, 0.06498986, 0.058922634, -0.02240318, -0.086019725) * go_2(1.0, -1.0);
|
||||
result += mat4(0.2058775, 0.01502064, 0.05847032, 0.007249146, 0.086483665, 0.19420148, 0.03892261, -0.013546935, -0.07980237, 0.04347281, -0.10376214, -0.1366535, 0.05285337, 0.07213318, 0.3642818, -0.11331124) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.025740806, 0.14551482, -0.037410017, -0.17477523, -0.11853099, -0.060820814, -0.102599286, -0.13267937, -0.103053465, -0.014044828, -0.01888072, -0.06499249, 0.22311528, -0.051850274, -0.034120858, 0.044562567) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.21360217, 0.10093803, -0.0016407765, -0.1473997, 0.26524043, 0.02112132, 0.23173104, -0.013157391, 0.05945182, 0.044635538, 0.06031638, -0.21435826, -0.10147484, 0.069090195, 0.09641844, -0.09581093) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.08576515, -0.122861005, 0.049567085, -0.085854456, 0.23809357, -0.024966082, -0.10294079, 0.046241313, 0.008621132, -0.08323767, 0.20277941, 0.163423, -0.07386535, -0.088738985, 0.05274358, -0.025479877) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.041135542, -0.008365642, 0.17088248, 0.04025207, 0.13809255, -0.056895368, -0.01582834, 0.07361908, -0.00068995473, -0.09300962, 0.19117641, 0.24832036, -0.06572358, -0.026025, -0.019093119, -0.049720034) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.024900286, 0.11525501, 0.025882801, 0.037742402, 0.36976853, 0.052211333, -0.15143296, 0.1802276, -0.059080046, 0.017990451, 0.026395092, -0.12689115, -0.07705386, 0.1232379, 0.13273561, -0.12521964) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.19788785, 0.044887315, 0.07663442, 0.16688696, -0.2842248, -0.15684547, 0.028387763, 0.0063470444, -0.012245601, -0.038382255, -0.8187406, -0.25245667, 0.23014604, 0.22746666, 0.1594356, 0.16469443) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.12663333, 0.014730006, 0.03765697, 0.15704912, -0.106595434, -0.05317512, -0.081759915, -0.08797109, 0.064620756, -0.06341419, 0.16493447, 0.23102313, 0.068325415, -0.088058695, 0.16885915, 0.036382258) * go_3(0.0, 1.0);
|
||||
result += mat4(0.035389822, -0.11811836, -0.035656307, -0.0680554, 0.1338908, 0.065852076, 0.023307983, 0.0675308, 0.09690683, 0.18170924, 0.09862692, -0.20964378, -0.08601271, -0.20016764, -0.01879598, -0.14629345) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.27183273, 0.013525998, -0.14995874, -0.23938845, -0.26218823, -0.0009874097, -0.13385512, -0.10664239, -0.048931994, 0.039898522, 0.047444753, 0.10934722, 0.10969629, 0.123539805, 0.11692802, 0.14172275) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.1656506, 0.019683002, 0.0221048, 0.12596753, 0.20420644, -0.07930122, 0.04653823, 0.11492255, -0.0050175437, -0.03271697, 0.013389486, 0.034583613, -0.2196601, -0.1615663, -0.013763388, -0.056037936) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.022956269, 0.029688787, -0.070148066, -0.07163476);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf1
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.15104648, 0.05522861, -0.0654341, -0.053517453, -0.08264124, -0.0062249107, -0.20364265, -0.05015117, -0.18837251, 0.030655831, 0.046844713, -0.20673253, -0.14042036, -0.05655449, 0.13994302, 0.011745607) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.16517559, 0.1489214, -0.09149559, 0.025003506, -0.124926426, 0.16974348, -0.020857265, 0.08017403, 0.21836148, 0.0025619378, 0.2331612, 0.085599184, -0.030934382, -0.055194855, 0.09527726, -0.10081552) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.041800212, 0.028859638, 0.09395546, 0.05211183, -0.038541477, 0.021495212, 0.04862346, -0.007864793, 0.038407274, -0.13841268, -0.14963801, 0.26470762, 0.16691841, -0.07262008, 0.034374326, -0.14709206) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.00094978884, -0.028974704, -0.0900548, -0.08401967, -0.08935931, -0.043606587, -0.14497143, -0.05226239, -0.21516493, 0.19410603, -0.089924194, -0.04335071, -0.012618276, -0.2671613, 0.020422975, -0.037739716) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.13403237, -0.02524383, -0.03474901, 0.054432765, 0.11946775, 0.107336655, -0.1431715, -0.13370377, 0.015087512, -0.1917613, 0.073493585, 0.2788855, -0.010510839, 0.06891479, -0.06741307, -0.05271205) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.15432046, 0.04021662, -0.16979513, 0.13660534, -0.10518303, -0.10095502, -0.13092068, 0.022805348, -0.16676381, -0.4273298, 0.020867536, 0.3506733, -0.29459694, -0.055828743, -0.069241956, 0.04106382) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.08890133, 0.07549666, -0.040735144, -0.1506932, -0.22227979, -0.0762723, -0.17766447, -0.05741318, -0.21885683, 0.2379157, -0.15525854, -0.07306285, 0.15580738, -0.04394069, -0.19175608, 0.018283797) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.08503275, -0.105500385, -0.114987396, -0.07166016, -0.2147138, 0.09378708, 0.24550334, -0.0834075, -0.033147786, -0.022304727, -0.31062204, 0.027651973, 0.109098755, 0.18889032, 0.1163026, 0.13863255) * go_0(1.0, 0.0);
|
||||
result += mat4(0.15266588, -0.14901319, 0.033916786, 0.09381096, -0.08196443, -0.16194504, 0.035789456, 0.21234898, -0.48724765, 0.2619442, -0.11215393, 0.25061038, 0.022344576, 0.0116525125, 0.111661114, -0.15242295) * go_0(1.0, 1.0);
|
||||
result += mat4(0.020475458, 0.0797404, -0.13576819, 0.009681671, 0.030504882, 0.049232908, 0.022025917, 0.16912088, -0.23914136, -0.084663324, 0.020925451, -0.1023938, 0.035916872, -0.07538111, -0.11470242, 0.15238516) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.12941381, 0.08509899, -0.029489802, -0.09148447, -0.089406274, -0.116145454, -0.08979843, 0.11908148, 0.15473351, -0.21687616, 0.12607013, -0.08244334, -0.079580925, -0.16613089, -0.09287793, -0.03412643) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.023578499, 0.07394217, -0.13069086, -0.1060499, -0.07559958, -0.21839201, 0.1090753, 0.0787872, 0.07677037, -0.25998843, 0.20039314, 0.046882212, 0.31871012, -0.3048051, 0.15118991, -0.00518087) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.15338503, -0.11057532, 0.075839415, -0.18592294, -0.0155324, 0.038140323, -0.10498194, 0.09070477, 0.05108992, -0.047939524, -0.091004305, 0.09649005, -0.10967152, -0.051909525, -0.05314551, 0.09661584) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.14458802, -0.053263694, -0.0010885567, 0.23342133, 0.01918937, 0.12026143, -0.15691495, 0.30480555, -0.08725869, 0.19082253, 0.3594973, 0.016653897, 0.045152336, -0.088590585, 0.0069655925, 0.1392425) * go_1(0.0, 0.0);
|
||||
result += mat4(0.17944881, -0.17950764, 0.13282645, 0.030974053, 0.32233685, 0.18067117, -0.11472813, 0.097301506, -0.047649745, -0.1053861, -0.081039384, 0.035132434, 0.10204545, 0.085582554, -0.13153993, -0.021741152) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.15573682, 0.16409989, -0.22574787, -0.03877603, -0.18285516, 0.11638645, 0.18321282, -0.017770218, 0.18230622, 0.16433364, -0.12795393, -0.03805153, 0.14386104, -0.0891527, -0.056928284, -0.10961495) * go_1(1.0, -1.0);
|
||||
result += mat4(0.257622, 0.052519716, -0.25421762, -0.1887382, -0.083568096, -0.0064690276, -0.029110614, 0.103327505, -0.17006217, 0.2254096, -0.29366904, 0.04302887, -0.10198446, -0.24423616, 0.16781262, -0.005019004) * go_1(1.0, 0.0);
|
||||
result += mat4(0.103393994, -0.059044626, -0.18192382, 0.0990813, -0.26143607, 0.11036474, 0.04788275, -0.096738026, 0.12825653, 0.13631694, -0.077904984, -0.020790676, -0.25118098, 0.122588515, -0.049440473, -0.10758222) * go_1(1.0, 1.0);
|
||||
result += mat4(0.06693113, -0.13647175, 0.131139, 0.13143918, 0.081720434, 0.117537096, 0.15387627, -0.008771362, 0.08513583, 0.023794742, -0.0661625, 0.115793936, 0.0023350024, 0.02215075, -0.0494433, -0.013404977) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.041419264, -0.17622781, 0.028418267, 0.12114493, -0.23587078, 0.08457395, 0.014364018, -0.103271864, -0.051572207, -0.026424447, 0.16755055, -0.10763651, -0.033440586, 0.068594255, -0.050668504, 0.1941505) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.2780181, 0.037816502, -0.11516711, -0.09822884, 0.13762361, -0.14317706, 0.14350282, 0.000623895, -0.08601606, 0.08118504, 0.15497385, -0.04721711, -0.008936935, -0.014223618, -0.09641698, -0.013884213) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.14349665, -0.03144472, -0.057813704, 0.0667044, 0.09026094, 0.051366236, 0.11139983, -0.015782114, -0.18314016, -0.18774192, 0.0014838242, 0.15759028, 0.062388215, 0.13626057, 0.02576217, -0.06317815) * go_2(0.0, -1.0);
|
||||
result += mat4(0.07151769, 0.14508991, 0.1736844, -0.11487795, -0.07999805, -0.07797908, 0.037923355, -0.059138823, -0.23531209, -0.040207293, -0.068355694, -0.024296658, -0.114820175, 0.19726487, 0.21772414, 0.03659222) * go_2(0.0, 0.0);
|
||||
result += mat4(0.16858695, -0.12135113, 0.009391182, -0.081519485, 0.13340487, 0.07007004, 0.094124354, 0.035519842, -0.3320139, -0.06624027, -0.14716229, -0.09205287, 0.12664132, -0.05655441, 0.0123263765, 0.04641279) * go_2(0.0, 1.0);
|
||||
result += mat4(0.19018422, -0.15428329, -0.009354114, 0.04165953, 0.11024837, -0.107493006, -0.05807292, -0.048029456, 0.24319384, -0.10542357, -0.013699952, 0.06228662, -0.06808749, -0.023227982, 0.16528323, -0.05610251) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.008616222, 0.077674195, -0.08638503, 0.09293109, 0.072474636, 0.05004233, -0.20591061, -0.005301386, -0.15486047, 0.15038474, 0.1262478, 0.021724822, 0.02274613, -0.3088281, -0.08437887, -0.10684698) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.16960032, 0.09365251, -0.030414175, -0.010766254, 0.18181023, 0.12130318, 0.08913089, -0.06070321, 0.05200306, 0.092584535, 0.17694671, 0.033796314, -0.038107123, -0.04335955, -0.049443472, 0.30465958) * go_2(1.0, 1.0);
|
||||
result += mat4(0.07661484, -0.009945252, 0.12866217, -0.07592757, -0.21030053, 0.014371748, -0.072458774, -0.04700072, 0.15534303, 0.2007125, -0.15699059, -0.032897495, 0.08110436, -0.11243608, 0.008632577, -0.10153441) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.034697928, 0.06928288, -0.2796273, 0.14405379, 0.12248569, 0.036539096, 0.06607706, 0.077684596, -0.16473202, 0.1665916, -0.29977503, 0.21047153, 0.13114224, -0.091579035, -0.045458574, 0.03254245) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.053284872, 0.053366095, -0.26152626, -0.03123967, -0.031794485, 0.17670582, -0.07450994, 0.017521491, -0.040290453, 0.38342363, -0.25021288, -0.014660264, 0.1621895, 0.25041878, -0.12124821, 0.068036206) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.11366693, -0.030863572, -0.07411263, 0.12475283, -0.046070684, -0.09033321, 0.013222701, 0.06798592, -0.32814804, 0.057653826, -0.14082801, -0.00217398, -0.22856179, -0.19058353, -0.20992154, -0.03701372) * go_3(0.0, -1.0);
|
||||
result += mat4(0.20345633, -0.1332355, 0.27152926, -0.13477845, -0.25242096, -0.28281286, 0.31289554, 0.14284514, 0.53362453, -0.46766588, 0.4518293, -0.39291728, -0.3573227, -0.014670052, 0.0051881406, 0.16552156) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.15017267, -0.07792945, -0.204405, 0.13964304, -0.13642666, -0.10228306, 0.03238279, -0.08689329, -0.072262034, -0.0258388, 0.05689183, 0.055701543, -0.19800112, 0.012217054, -0.033292748, -0.047611095) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.014704416, -0.12203891, 0.066083655, -0.1409769, 0.0041513643, -0.087383606, -0.17498164, 0.11327789, -0.25947225, -0.0016027623, 0.08202566, 0.042270098, 0.006429511, -0.26576808, -0.08461341, 0.049376782) * go_3(1.0, -1.0);
|
||||
result += mat4(0.0695189, -0.14753938, 0.09578246, -0.16607563, -0.0105561055, 0.17166016, 0.027422488, -0.14175262, -0.009492696, -0.23449713, 0.018270867, 0.14635146, 0.33451268, 0.030959005, -0.46468422, 0.024256868) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.16865666, -0.00015881563, -0.054488145, -0.06222717, -0.032101758, 0.06485387, -0.0028512608, 0.046645947, 0.017593225, -0.19447896, -0.024742266, 0.03970127, 0.29845607, -0.16168733, 0.035172883, 0.07924657) * go_3(1.0, 1.0);
|
||||
result += vec4(0.103826486, 0.045373913, 0.11565896, -0.06568643);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.1851775, 0.053705044, 0.033816848, -0.018555025, -0.21204336, -0.01706974, 0.088259794, -0.13126148, 0.10729598, -0.043457437, 0.08634712, 0.09220895, 0.062131613, -0.01995871, 0.05181067, 0.18520063) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.1662002, -0.14197104, -0.052809287, 0.025287712, -0.08330898, -0.08998097, -0.15642618, -0.14941245, -0.03481203, 0.061857622, 0.26051775, -0.0005498248, 0.086427025, 0.024108192, -0.12418039, 0.022286376) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.058200672, -0.3073398, 0.17150162, -0.13394679, -0.075118184, -0.14607768, -0.006172172, 0.007731589, -0.21818224, -0.06449433, -0.038958784, 0.037722416, 0.28699976, -0.027563032, 0.23295315, 0.028444216) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.12871371, 0.0064904913, 0.14985761, -0.10923005, 0.17413563, 0.1599109, -0.08457703, 0.108153716, -0.08871187, -0.06661137, 0.2754416, -0.009667768, 0.39819396, 0.12392097, 0.14145902, 0.0019376524) * go_0(0.0, -1.0);
|
||||
result += mat4(0.13893189, 0.12715353, 0.015191678, -0.21003054, -0.030412354, -0.01676613, -0.19799289, -0.006130075, 0.37676954, -0.14475077, -0.2065198, -0.30432892, -0.14944535, -0.09121536, -0.107600585, -0.24462196) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.11653076, -0.0068671284, -0.02249137, -0.17877012, -0.15063138, -0.13514869, 0.107643366, -0.03196477, -0.086422764, 0.3079287, 0.17584166, -0.032449376, -0.06917114, -0.2682637, -0.18978168, -0.037039287) * go_0(0.0, 1.0);
|
||||
result += mat4(0.12014731, -0.030360512, -0.12954475, -0.110275604, -0.077214256, 0.019689744, 0.22149551, -0.002266716, 0.09697784, -0.124532826, -0.16776511, -0.034212478, -0.36935154, 0.016926935, 0.1363609, 0.20415346) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.11199535, -0.001692563, -0.09058429, -0.08437503, 0.092625685, 0.06046257, 0.25509837, -0.011657033, -0.17949764, -0.10718947, -0.1180669, -0.24681842, -0.1747311, 0.0014518246, -0.042863015, 0.06103357) * go_0(1.0, 0.0);
|
||||
result += mat4(0.14979295, -0.037154514, 0.01957725, 0.012282435, 0.09168596, -0.05552286, 0.111671515, 0.0078630615, -0.10319766, -0.06416261, -0.23097566, -0.13931875, 0.2110811, 0.013095802, -0.2306504, -0.025639111) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.10091975, -0.10095426, -0.023449723, -0.022170888, 0.054953706, -0.13049407, 0.08289061, 0.023241632, 0.08735388, -0.0058387457, 0.17897247, 0.011434436, 0.008181139, -0.0034718404, -0.015372735, -0.07657766) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.023442164, 0.07535702, 0.024391165, -0.050532013, 0.044168636, 0.0062343236, -0.019756999, -0.009695123, 0.10102337, 0.0052776975, -0.14944167, -0.060957722, 0.24367364, -0.08069369, 0.12170072, -0.047048368) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.18376935, -0.08407229, -0.12943378, 0.0738419, -0.12404976, -0.13367929, 0.11265896, -0.021353, 0.003783386, 0.50088304, 0.14058582, 0.041053623, 0.038247623, -0.014179976, 0.007905778, -0.042492237) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.046272535, 0.052449115, 0.17190954, -0.004745371, -0.045572635, -0.09292636, 0.36309823, 0.16673928, -0.099154025, -0.109614775, 0.17803112, 0.19907133, -0.14306267, 0.06898593, 0.11493454, 0.06795014) * go_1(0.0, -1.0);
|
||||
result += mat4(0.26181114, -0.044014625, -0.21605036, -0.08646438, 0.21038742, -0.084986, 0.0504626, 0.17514943, -0.25218952, -0.18691514, 0.057650108, 0.08653614, -0.101205684, 0.03176334, 0.18569492, 0.17973189) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.0339215, 0.20112811, -0.12986277, 0.028961731, -0.056813832, 0.04451147, -0.07827432, -0.0860976, 0.096853435, 0.3483546, -0.35758162, -0.11749375, -0.035918653, 0.06140711, -0.08520154, 0.02418808) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.09643022, -0.10491069, 0.0068604187, 0.023679713, 0.096521445, -0.29323488, 0.33353668, 0.112864286, -0.1172182, -0.07233183, 0.06607239, 0.08589609, 0.055790007, 0.14396138, -0.14191268, 0.00034840964) * go_1(1.0, -1.0);
|
||||
result += mat4(0.15357164, -0.038462736, 0.08143956, 0.1744909, 0.40503287, -0.114508316, 0.003937322, 0.2536635, -0.042445306, -0.15622465, 0.09155284, 0.010992155, -0.20646071, 0.022801135, 0.08894491, 0.069300614) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.12663515, 0.023849454, -0.053604446, 0.12082873, -0.247968, -0.020969635, -0.03831894, -0.014617553, 0.22630337, 0.037801865, 0.052950703, 0.04285706, -0.14487264, 0.20786528, -0.08719664, 0.1752347) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.073527604, -0.050752833, 0.051830504, 0.32868716, 0.17474994, 0.016937364, -0.08792601, -0.024481766, -0.022229593, 0.030706186, 0.09213566, -0.076506205, 0.073404044, 0.10368055, -0.175889, -0.08453031) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.06838216, 0.007698341, 0.063972116, -0.015604406, 0.16135305, 0.18044342, 0.024137018, -0.23326185, 0.13235588, -0.009096587, -0.058368143, -0.077040404, 0.0011419816, -0.09246194, 0.061036937, 0.049564146) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.023225296, -0.00060856267, -0.07775185, 0.016958566, -0.2641349, -0.08263046, -0.15350416, -0.30203494, 0.113956556, -0.010813236, -0.017738314, -0.13689043, -0.10318342, 0.025793184, -0.010336172, 0.09733422) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.04462596, 0.052866418, -0.34754288, 0.05540498, -0.24492586, -0.32016864, 0.18145293, 0.24873725, 0.32388234, -0.034801524, -0.1347588, -0.07565546, 0.015183539, 0.05059595, 0.08090056, 0.05930932) * go_2(0.0, -1.0);
|
||||
result += mat4(0.045346696, -0.052527856, 0.052270077, 0.13417454, 0.05200045, 0.028119288, 0.005115497, 0.22952151, -0.2158375, 0.12241308, 0.3507457, 0.08616576, 0.07592416, 0.28470486, 0.3432788, 0.24857087) * go_2(0.0, 0.0);
|
||||
result += mat4(0.21311626, 0.052607164, 0.1248861, 0.20193806, 0.045226507, 0.14512901, -0.15103437, -0.17926466, 0.11657411, -0.32711068, -0.16332194, -0.07793982, -0.21802668, 0.5183869, -0.13567342, 0.07823041) * go_2(0.0, 1.0);
|
||||
result += mat4(0.00796368, 0.048073012, -0.14537893, -0.021708772, 0.036246423, 0.1062395, 0.12605369, 0.007073524, -0.1572743, 0.07439501, 0.089162275, -0.0039608316, 0.332032, -0.05461242, -0.17615359, -0.10240517) * go_2(1.0, -1.0);
|
||||
result += mat4(0.20636982, -0.0024615112, -0.10625786, 0.024270926, 0.061810836, -0.13585201, -0.16581286, 0.23549418, 0.01928842, 0.07404979, -0.054449487, 0.04096373, 0.046939734, 0.003980803, 0.02111498, 0.064925276) * go_2(1.0, 0.0);
|
||||
result += mat4(0.10485388, 0.06850885, -0.11292169, 0.16991565, -0.15282536, 0.124175504, -0.050431166, -0.06689582, -0.00059811946, 0.033696912, 0.11055047, 0.033060126, -0.17472714, 0.0048819613, -0.04478706, -0.1344572) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.20473132, 0.056477875, 0.059559986, 0.115130566, -0.058425788, -0.035971727, 0.08334707, -0.096510135, -0.23206294, 0.10635798, -0.21575621, -0.07063254, 0.03877511, -0.107549034, 0.22248401, 0.21702304) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.02557767, 0.09886609, -0.100499466, 0.16687396, -0.084830604, 0.03150401, -0.049512494, 0.05595696, -0.13193256, -0.08585273, 0.14247662, 0.12290477, -0.07168309, 0.14531752, -0.048359327, 0.27716598) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.13297586, 0.20674329, 0.14469388, 0.08981846, -0.004231366, -0.02819193, 0.15470329, 0.17299837, 0.113062344, -0.22716297, -0.21754944, -0.00083956274, -0.14160508, 0.1808253, 0.11268379, 0.27335623) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.07497518, -0.06799594, -0.018158078, -0.00038999433, -0.15169668, -0.06928238, -0.33672288, -0.105485775, 0.33106267, 0.06698315, 0.019718744, -0.06810211, -0.35186404, -0.29145968, -0.056863394, 0.21498048) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.013215512, -0.24763754, 0.20965266, 0.1068435, -0.13234195, 0.053566497, 0.05061848, -0.28645232, 0.15518288, 0.23247199, 0.017553907, -0.25181335, -0.048030723, -0.06663929, -0.111026704, -0.12663394) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.010501938, -0.17995767, 0.06010859, 0.050185587, 0.108627126, -0.101203434, 0.07558728, 0.060466755, -0.106942676, -0.35854608, 0.16015992, 0.16823332, -0.06543775, -0.37310675, 0.014043972, -0.18328045) * go_3(0.0, 1.0);
|
||||
result += mat4(0.09712849, 0.013983463, 0.07291423, 0.031715546, 0.030862397, 0.045510456, -0.22066842, 0.063464865, 0.11721659, -0.10596602, -0.20611264, 0.052158818, -0.3961766, -0.03781582, 0.17633812, 0.1316111) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.25029674, 0.07153423, -0.35125682, -0.18255402, -0.19569087, 0.00432772, -0.0969035, -0.24648514, -0.0040922165, 0.037500706, -0.038137026, 0.056214277, -0.048258524, 0.03567822, -0.05033007, -0.24696785) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.03465209, -0.012495964, 0.22782089, 0.012034795, 0.2916752, 0.08264436, 0.15387125, -0.1473455, -0.15614432, 0.05536727, -0.027079755, 0.010725311, -0.03325222, -0.089212805, -0.10559839, -0.19647683) * go_3(1.0, 1.0);
|
||||
result += vec4(0.0001705175, -0.031081453, 0.010100773, -0.027214011);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf1
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.026301445, -0.021575214, 0.22165509, 0.059994068, 0.03341161, 0.1831188, 0.20342293, 0.110160105, 0.03908121, 0.020673111, 0.07239561, 0.038754333, 0.15266368, 0.16526422, 0.062376205, -0.09759537) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.19817191, 0.10267733, 0.17744653, 0.23283184, 0.18810122, 0.2708428, -0.12651879, 0.020756349, 0.039632563, -0.22201295, 0.04873703, 0.09159713, 0.13838065, 0.21169297, 0.30816007, 0.044463675) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.27859214, 0.07277634, 0.0021458792, 0.0089682285, -0.069680706, 0.090415835, -0.057762265, 0.18703683, -0.03514389, -0.102816254, -0.036509827, 0.038066104, -0.0168311, 0.094478935, 0.04079697, -0.049064912) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.20913245, -0.110538535, -0.08584027, -0.1222067, 0.05414807, -0.045247085, 0.07351766, -0.002078549, -0.1270987, -0.10164512, -0.1857815, 0.08845066, -0.03743333, -0.098948084, 0.21244387, 0.10441866) * go_0(0.0, -1.0);
|
||||
result += mat4(0.015990427, 0.36396438, -0.24094687, 0.30236533, -0.13271736, 0.06057376, -0.19678196, -0.28577125, -0.25427434, -0.08400598, 0.07284403, -0.18552442, -0.16425897, 0.097259276, -0.32386774, -0.2190484) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.004581924, -0.13954072, -0.122360416, 0.14132866, -0.08529257, -0.013296556, 0.0848472, 0.09336581, 0.10332182, -0.016313016, 0.07103558, 0.032564916, -0.13478759, -0.20207484, 0.12986964, 0.1219679) * go_0(0.0, 1.0);
|
||||
result += mat4(0.09817874, -0.10573357, 0.100535244, 0.19608764, -0.13303067, 0.024192972, -0.030689823, 0.02574889, 0.051233094, 0.03489235, -0.18465245, -0.06943822, -0.031604882, 0.1519888, 0.09348508, 0.09187296) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.21365458, -0.23696984, 0.13097638, -0.09435498, 0.16467983, -0.066370346, 0.1269104, -0.095128186, 0.09954892, 0.12489504, -0.43418056, 0.106512725, -0.17860703, -0.07114084, -0.07630834, -0.26642478) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.009044342, 0.02711196, -0.14873673, 0.015405045, 0.0071443473, -0.025285944, 0.07409282, 0.06338527, 0.0149676185, 0.011741382, -0.2133069, -0.028912885, 0.19420496, 0.039629057, 0.057636812, 0.15214856) * go_0(1.0, 1.0);
|
||||
result += mat4(0.07629928, 0.25540486, -0.050925937, -0.18136702, 0.02261603, 0.22343902, 0.003270321, 0.10735731, -0.12541203, -0.10208828, 0.012832783, 0.2591262, 0.08122926, -0.009837677, 0.10308358, 0.19236866) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.0896358, 0.27571487, 0.04406029, -0.047453407, -0.08587119, 0.16366854, 0.20622262, 0.08347545, -0.3501584, -0.28434548, -0.07592983, 0.09098784, 0.07605388, 0.09677056, 0.0015295541, 0.05102585) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.18255898, 0.18618028, 0.0017002645, -0.013004655, -0.06436534, 0.13967068, 0.063077755, -0.10632303, -0.20803222, -0.028537111, -0.03144366, -0.08555215, 0.05154303, 0.02431626, 0.15246728, -0.013708507) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.020998938, -0.05026291, 0.03700117, 0.00830308, -0.1949294, 0.0026698054, -0.034649856, 0.19784226, -0.083901435, -0.069783084, -0.1504053, 0.16595264, -0.07480141, 0.16067508, 0.06010996, -0.021359695) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.040828142, -0.20158486, 0.034770954, -0.1894161, 0.11665004, 0.29729164, -0.10584386, 0.13165873, -0.18863006, -0.26719162, -0.047613148, -0.12728356, -0.2033613, 0.10550052, 0.20095508, -0.11275811) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.0785033, -0.1896073, -0.051492307, -0.1694358, 0.1368308, 0.049355216, -0.05707422, 0.079159185, 0.024578957, -0.0923136, 0.089215435, 0.28670043, 0.027932687, 0.06510816, 0.10810999, 0.05990052) * go_1(0.0, 1.0);
|
||||
result += mat4(0.08135192, 0.0001326522, -0.16098668, -0.18663193, -0.10280192, 0.078255914, 0.047648013, 0.08326376, 0.055962667, 0.06302574, -0.080121025, -0.031820554, -0.019117938, 0.12515336, 0.09794088, -0.03276838) * go_1(1.0, -1.0);
|
||||
result += mat4(0.280923, 0.24079335, 0.007883573, 0.06270414, 0.3055441, 0.19291803, -0.16041607, 0.14836526, 0.0013885222, 0.04538063, 0.10742898, -0.064491205, 0.048174977, 4.237692e-05, -0.15194727, 0.024381457) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.0009164131, -0.031949926, 0.0076425644, -0.036870714, -0.0031292974, 0.017726978, -0.20172147, -0.0770472, 0.26379177, 0.108997814, 0.08069395, 0.2126177, 0.012075376, -0.029457828, 0.062730506, -0.15754452) * go_1(1.0, 1.0);
|
||||
result += mat4(0.09167904, -0.2657421, -0.03443356, 0.03315832, -0.015365421, -0.1029612, -0.108251, 0.04261033, -0.097120754, -0.05616668, -0.09275983, 0.024902184, 0.050058514, -0.013761632, 0.07555132, -0.0046676896) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.10743835, -0.0007361781, -0.042085417, -0.08237517, -0.10094376, -0.24007876, 0.13924706, -0.07526801, 0.01158322, 0.15491122, 0.0069442675, -0.004242352, 0.11429785, 0.02994726, -0.11829945, -0.04108612) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.073622055, -0.064717196, -0.0025231615, 0.13256475, 0.20159899, 0.047977835, -0.10289233, -0.18419135, -0.00888952, 0.059428576, -0.053062655, -0.02730631, 0.14545685, -0.08686949, 0.17454128, 0.035443828) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.010146019, 0.06712568, 0.12614638, 0.023590917, 0.025756737, 0.06603747, -0.17108095, -0.06179699, 0.027241204, -0.13196802, 0.043475866, -0.0397495, 0.05306092, 0.035672903, 0.047219284, -0.16680142) * go_2(0.0, -1.0);
|
||||
result += mat4(0.079427816, -0.06716479, 0.19028603, -0.19694683, -0.061598092, -0.07471188, 0.21170339, 0.30140215, -0.0023369973, 0.04688297, -0.14154115, 0.19283508, 0.1339858, -0.09116279, 0.15305163, 0.029108394) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.14902157, -0.03339153, -0.08532003, -0.10736339, 0.08702709, 0.07607574, -0.09955836, -0.016585784, -0.030078214, -0.060374748, -0.2854279, 0.02441719, 0.034877967, 0.2099041, 0.11125731, -0.059071556) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.08436325, 0.06893047, -0.045362443, -0.02237741, -0.07583875, -0.034830183, -0.024008518, -0.2882329, -0.011109783, 0.101859994, 0.091137715, 0.0020565533, -0.044729806, -0.18168025, 0.069466636, 0.04994174) * go_2(1.0, -1.0);
|
||||
result += mat4(0.11915174, 0.089596465, -0.18965814, 0.015218237, 0.13500094, 0.19921367, -0.008298205, 0.29650384, -0.049439427, -0.27590424, 0.36169067, -0.030582754, 0.02151196, 0.019915426, 0.04543398, 0.16126189) * go_2(1.0, 0.0);
|
||||
result += mat4(0.1620274, -0.08264547, 0.082442135, -0.0034478644, 0.09888509, -0.0034957859, -0.107241705, -0.17729597, -0.05138647, 0.02052103, -0.019507123, 0.037574988, -0.1694345, 0.17871588, -0.22510391, 0.019049853) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.10962245, -0.1329873, -0.060855392, 0.025941676, -0.19536193, -0.120365486, -0.04313703, -0.052912965, 0.20854498, 0.08341353, 0.008687068, -0.20432276, 0.15677948, -0.19000018, 0.01821201, -0.041512605) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.012287526, -0.14180368, -0.098788455, 0.025949089, 0.09442778, 0.2247651, -0.12453263, 0.10435483, 0.274603, 0.06133054, 0.10506106, 0.14727746, -0.048299775, -0.082819685, 0.07319359, -0.047460355) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.070726536, -0.034744017, 0.07521428, 0.070649154, -0.05958955, -0.100232825, -0.010651838, 0.045392875, 0.2930271, -0.04952355, 0.3112155, 0.117203265, 0.025166962, 0.11176862, 0.06716659, 0.07175864) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.011560962, -0.14032063, -0.17424704, 0.07652749, -0.04220116, 0.052874275, -0.00225693, -0.031843517, -0.07520102, -0.13775803, 0.2449317, 0.069658786, 0.052280303, -0.105218224, 0.03574522, -0.020500354) * go_3(0.0, -1.0);
|
||||
result += mat4(0.08793712, 0.26712346, 0.08315631, 0.23813692, -0.04439029, 0.031587064, 0.09561177, -0.13380238, -0.24982157, 0.31701845, -0.3875432, 0.10487225, 0.09201869, -0.037252493, -0.006935219, -0.14650282) * go_3(0.0, 0.0);
|
||||
result += mat4(0.077635325, 0.13732299, -0.071563005, 0.096517466, -0.15051986, -0.111744404, 0.03996857, -0.052670125, -0.1819665, 0.054554947, -0.13774712, -0.20061246, -0.0023742192, 0.15647805, -0.024121126, 0.075497724) * go_3(0.0, 1.0);
|
||||
result += mat4(0.0073632775, -0.06535298, 0.039895996, 0.20666869, 0.13625242, 0.04823007, -0.07135618, 0.04787906, 0.01383074, 0.15382123, -0.15519714, 0.056721795, 0.061946746, -0.0586851, 0.028934354, -0.02264129) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.19791882, -0.111910924, -0.010451344, -0.30566537, -0.1416239, -0.14523096, 0.116883226, -0.18241516, 0.2680614, -0.18487626, 0.17472346, 0.08346682, -0.14510359, -0.029229192, -0.005879142, 0.050247498) * go_3(1.0, 0.0);
|
||||
result += mat4(0.030153519, -0.092469186, -0.022912916, 0.10200855, -0.04237032, -0.05917764, 0.10479645, -0.05619482, -0.18949397, -0.019547248, 0.013868889, -0.1524476, 0.14048979, -0.032521486, 0.1322921, 0.070972025) * go_3(1.0, 1.0);
|
||||
result += vec4(0.012053958, -4.6962363e-05, 0.0020099226, -0.033494607);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.06738501, 0.034009207, -0.21538448, 0.14296548, 0.12896985, -0.23526315, -0.08848608, 0.019602662, 0.14937137, 0.11353096, 0.11884168, -0.016765572, 0.030985225, 0.046430565, 0.06614828, -0.19202724) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.10326068, 0.11014975, 0.17069744, -0.21474148, 0.16761585, 0.13434832, -0.101021074, 0.006307025, 0.07478008, -0.1060066, 0.035315692, 0.033488914, -0.24906659, 0.06269967, 0.11120735, -0.040928528) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.09334615, 0.057705753, 0.12213245, -0.06402275, 0.30694544, 0.034585163, 0.20345578, 0.07489286, 0.07483618, -0.14240396, 0.034846418, -0.03811241, 0.010882573, 0.13204294, 0.017563924, -0.047203008) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.21673942, -0.024010994, -0.10238504, -0.041160326, 0.06838163, -0.20950818, 0.06526309, -0.079094924, 0.02208821, -0.28130978, 0.086275116, -0.089067616, 0.12133826, -0.062600106, -0.020521903, -0.07654401) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.03055029, -0.15683146, -0.20331301, -0.06252028, 0.13350682, 0.20338707, 0.038425338, 0.1581342, -0.27322498, -0.14999662, -0.16681097, 0.0971585, -0.20014858, -0.081635274, -0.0781877, -0.20625232) * go_0(0.0, 0.0);
|
||||
result += mat4(0.38375977, -0.019825654, 0.1886721, 0.22616312, 0.3402173, 0.1825304, -0.05531195, 0.30973226, -0.2676023, 0.14413352, 0.021706983, 0.01732799, 0.23466855, -0.13805965, 0.22570935, 0.018103868) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.15169825, 0.0270689, -0.2503316, 0.17289825, -0.16437647, 0.039233048, -0.35572487, -0.048393793, 0.19270042, 0.24260359, 0.12041881, -0.0009793913, 0.11656858, 0.11007414, -0.0757491, 0.047933612) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.18657999, -0.11252566, -0.05237504, -0.07368097, 0.13882741, -0.13710637, -0.006996468, -0.062354874, 0.23452504, 0.15333645, -0.0022776406, -0.17910439, 0.03629509, -0.16264829, -0.010011833, -0.15313338) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.060544558, -0.04913478, -0.061717357, 0.02323648, 0.28739056, -0.07434013, 0.19110644, 0.100050166, 0.0073363045, 0.08185653, -0.024797903, -0.14424153, -0.20838726, 0.16154376, -0.048517212, -0.025453888) * go_0(1.0, 1.0);
|
||||
result += mat4(0.14975396, -0.13142908, 0.36210674, -0.054021083, -0.10632155, 0.045697935, -0.18946633, 0.02228141, -0.08919603, 0.09800842, -0.17634438, 0.09512711, -0.03425503, -0.12298555, -0.05354435, -0.17112055) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.09958265, -0.057276618, -0.16262266, -0.06415915, 0.14579074, -0.36784375, 0.08034197, -0.04537706, 0.005460582, 0.22313322, 0.07382161, 0.014990379, 0.044636846, -0.2811128, -0.22621547, -0.06044004) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.10569276, -0.03738662, 0.16100396, 0.058593616, -0.048862137, -0.08796426, 0.20101094, -0.11039573, 0.17196764, -0.04601554, 0.008571281, -0.073729075, 0.051433694, -0.051276565, 0.087334655, -0.0360379) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.011119538, -0.28781965, 0.28637868, -0.1742508, -0.07121849, 0.10379717, 0.012615981, -0.029563965, -0.18678424, 0.05291095, 0.039143506, -0.028248642, -0.014103922, 0.029155696, 0.10433492, 0.16305852) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.2231037, -0.13697462, -0.29124337, 0.08519773, 0.15893684, -0.17763218, 0.06950923, 0.34361118, -0.024844287, 0.044008408, -0.033844844, -0.086971916, -0.07884748, 0.2543499, 0.056884114, 0.10068364) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.07710048, -0.23218372, 0.04346047, 0.21769643, 0.06473219, -0.18066105, -0.2511205, 0.15309611, 0.04535977, 0.16450433, 0.10846344, 0.0016952346, -0.010874939, 0.28966382, -0.121990964, 0.12956186) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.007910202, 0.17766511, 0.14364475, 0.1016258, 0.0051045395, 0.18691733, 0.005813767, -0.0070582186, 0.019418601, -0.1604435, 0.016088275, -0.18265302, -0.15719391, -0.17369832, -0.036745597, -0.19647408) * go_1(1.0, -1.0);
|
||||
result += mat4(0.08938396, -0.0073808245, 0.11225727, -0.012303106, 0.096785046, 0.030483445, 0.027719889, -0.052584838, -0.14887555, -0.03422243, 0.12646855, -0.1722482, 0.010239037, 0.06406088, -0.20053658, 0.01964698) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.120734036, -0.12450362, -0.06582111, 0.1639675, -0.19787048, -0.08049789, -0.014257596, 0.058436662, -0.0009387449, -0.08698089, -0.017400503, 0.06295286, 0.09890349, -0.057190523, -0.103520766, -0.04207548) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.0118413875, -0.031288836, 0.09749554, -0.012266401, -0.07998591, 0.22615653, -0.06207416, 0.03257896, -0.076378696, -0.079426095, -0.13968349, -0.15423697, -0.1091681, -0.02893125, -0.032659534, -0.063735925) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.119372696, 0.013176554, -0.029381052, 0.21919228, 0.045041792, 0.24844484, 0.26363325, 0.08480674, 0.087083444, 0.11984778, -0.088715754, 0.06421046, 0.05225977, -0.05140334, -0.055052705, -0.049854077) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.0035781674, 0.0861361, -0.07675145, -0.056479637, 0.16973391, -0.12113791, 0.10729832, -0.03773517, 0.058618728, 0.12148276, 0.17260705, -0.06968724, 0.076358154, -0.15307103, 0.17700425, -0.13467014) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.02752418, -0.06366472, -0.025610954, 0.0013539721, -0.06465272, 0.0806373, -0.07336035, 0.10114861, 0.0041146413, 0.15878421, -0.044668555, -0.12150811, -0.1071482, -0.05086587, 0.18589285, 0.05065092) * go_2(0.0, -1.0);
|
||||
result += mat4(0.07200056, 0.021739854, 0.29476613, -0.08475931, 0.15018553, -0.07886365, 0.36336347, -0.020576432, 0.25866082, -0.059272554, 0.054249667, -0.17822553, 0.1755872, 0.3244387, -0.39173844, 0.33894604) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.11570926, 0.1342677, -0.19511898, 0.0075454637, -0.01890476, -0.14239742, 0.18921931, 0.033990458, 0.31306365, -0.006998358, 0.029190077, -0.005679954, -0.15341778, 0.07766778, -0.25691047, -0.0964161) * go_2(0.0, 1.0);
|
||||
result += mat4(0.019746238, 0.0021332854, -0.00879096, -0.1338671, -0.0001600663, -0.29465106, 0.0867611, -0.114963025, 0.07874301, -0.012734178, -0.11124061, -0.010926616, -0.04941506, -0.07516841, 0.116663, -0.29018974) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.01651721, 0.05955898, 0.023618208, 0.098695934, 0.018553663, -0.054378513, 0.1436929, 0.1693743, -0.27483663, 0.029127488, 0.09619316, -0.06109113, -0.08619361, 0.09315214, -0.02478657, 0.18544984) * go_2(1.0, 0.0);
|
||||
result += mat4(0.09570196, -0.016528936, -0.1559397, 0.14312246, 0.04029428, 0.08773151, -0.043646842, 0.17894371, -0.082413055, 0.0027082344, -0.100171275, 0.01547501, 0.18122818, -0.11933676, 0.26404107, -0.3169703) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.12073344, 0.08683522, -0.09249099, 0.058786053, -0.14480567, -0.121013954, 0.033335857, 0.009353379, -0.055087596, -0.13002734, 0.08890566, 0.05508963, -0.0075715426, -0.15936922, -0.03968994, -0.1690259) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.2011206, 0.23898427, 0.23656492, 0.1287573, 0.14850396, 0.40532517, -0.107408255, 0.40119782, 0.099813245, -0.03830304, 0.101520434, -0.026478073, -0.048469637, 0.106440455, 0.056632314, -0.17825997) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.076735444, 0.05965795, -0.0052469415, -0.21785147, 0.11887833, 0.067560315, 0.051149055, 0.23626682, -0.1297049, -0.035512198, 0.20352256, -0.025064934, 0.04958706, 0.0454198, 0.0113334535, 0.0417486) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.09055751, 0.033915352, -0.21836667, 0.22006813, -0.099022895, 0.11720966, -0.15686816, -0.13586599, -0.094427735, -0.08831514, -0.06182928, 0.09213704, -0.03642064, 0.18129414, -0.012926811, 0.12179882) * go_3(0.0, -1.0);
|
||||
result += mat4(0.19389409, 0.09512252, 0.14768016, -0.16623649, -0.031052284, -0.026814984, 0.106168024, -0.2026781, -0.04581419, -0.0016849053, -0.04101923, 0.038959503, -0.011938445, 0.20096186, -0.26666564, 0.4824324) * go_3(0.0, 0.0);
|
||||
result += mat4(0.17727576, 0.07309147, 0.12131863, -0.163096, 0.17225246, 0.26256254, 0.27685758, 0.09094053, 0.029605515, -0.20217367, 0.047564875, 0.043115832, 0.15089568, -0.09670934, 0.24131384, 0.03337442) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.34192136, 0.12063195, -0.31159517, 0.04170889, -0.30147067, -0.21330686, -0.1514457, -0.121126845, 0.04409098, 9.2206596e-05, 0.027680017, 0.03230512, -0.27993527, -0.093485355, 0.07568645, -0.23585452) * go_3(1.0, -1.0);
|
||||
result += mat4(0.0537712, -0.20847629, 0.1740093, -0.013894753, -0.32719997, -0.059484575, -0.006098233, -0.10336451, -0.14706188, -0.07424865, -0.07045905, 0.17093194, -0.22147557, 0.09086218, -0.11033544, -0.05306482) * go_3(1.0, 0.0);
|
||||
result += mat4(0.00489003, -0.11509064, -0.021005848, 0.16637677, -0.089347586, 0.17545725, -0.17313693, 0.13742085, -0.14577347, 0.07951095, -0.092139855, 0.017118992, -0.053472433, 0.079414465, 0.0330263, -0.11189824) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.034743138, 0.012946433, -0.082333155, 0.07721756);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf1
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.25835788, 0.050451655, -0.1845038, -0.07232528, 0.1323318, 0.26276684, 0.10842882, -0.083056524, 0.17426784, -0.3594826, 0.2728965, 0.08388844, -0.004007842, 0.020535901, -0.051425606, 0.07750436) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.11410436, 0.014572361, -0.27057216, -0.023974562, 0.05234827, 0.15328228, -0.17502303, -0.3199359, 0.12188045, -0.095813684, 0.024145132, 0.0856916, -0.027453909, -0.043129764, 0.16971985, 0.021623038) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.06611095, 0.038625732, -0.13717118, -0.04497733, 0.15213469, 0.04770935, 0.0729271, -0.062052976, 0.004571303, 0.035141192, -0.059409596, 0.044652313, 0.17520894, 0.09665589, -0.1479193, 0.06528058) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.1845968, 0.091479465, -0.09394898, -0.13545018, -0.029501775, -0.21426639, 0.09255898, 0.1257644, 0.20256902, 0.06267267, 0.10378081, 0.13494423, 0.058310498, 0.03642236, -0.16268995, -0.048100803) * go_0(0.0, -1.0);
|
||||
result += mat4(0.2155119, -0.3683131, 0.049449228, -0.20559964, -0.11761922, -0.2518804, -0.020712897, 0.12895772, -0.07543782, 0.5805017, -0.11301444, -0.038493153, -0.06710986, -0.09321189, 0.108671665, -0.03259695) * go_0(0.0, 0.0);
|
||||
result += mat4(0.035307787, 0.108389005, -0.27493554, 0.27029404, 0.25523573, -0.28636125, -0.20766719, -0.008661457, -0.004480811, -0.046390545, -0.16221444, 0.008979624, -0.061375532, 0.035076566, -0.018924266, 0.01380219) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.051922515, -0.12463486, -0.10383422, 0.02220095, -0.1573033, 0.13980615, 0.13248625, -0.16803266, -0.0692132, -0.21552645, 0.13744529, 0.23034313, 0.0052666534, 0.028977966, 0.07720251, -0.06477756) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.14097473, 0.2770271, -0.172289, -0.03000696, -0.028684044, 0.040578447, -0.2290285, 0.082329154, -0.042402364, -0.20926563, 0.08233207, 0.11862443, -0.07038536, -0.02273004, 0.091550544, -0.065856494) * go_0(1.0, 0.0);
|
||||
result += mat4(0.14879914, -0.023923844, -0.23569296, 0.20306346, 0.17502785, 0.28776234, -0.2788995, 0.10012439, -0.05635638, -0.025840463, 0.09222198, 0.118032, 0.08057015, 0.1286071, 0.060189806, -0.052669708) * go_0(1.0, 1.0);
|
||||
result += mat4(0.07076086, -0.15111323, -0.07427972, 0.008372168, -0.17791592, -0.16254742, 0.013961132, -0.0944912, -0.23380096, 0.17377278, -0.09683394, 0.019931393, -0.12042098, 0.0016406325, 0.09393333, -0.06882231) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.21465093, 0.04142968, 0.06840044, -0.37831602, -0.05549571, 0.044905066, -0.07873589, -0.026804, -0.34764197, 0.022487951, -0.077293746, 0.089457795, -0.110094436, 0.24233972, 0.06285107, -0.10851744) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.093270175, 0.084138945, 0.03938272, 0.063565865, -0.010733802, 0.13554469, -0.06650261, 0.033002816, 0.011187271, -0.12821455, 0.20785914, -0.030438649, -0.124710515, -0.022294303, 0.09732408, 0.057609864) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.12833868, 0.021577539, -0.02700365, 0.11799592, -0.03655647, -0.04225167, 0.11049353, -0.16036157, 0.049277548, -0.033842396, 0.10020137, 0.095509745, 0.08060231, -0.09237418, -0.035598125, -0.035926737) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.32829186, 0.3492363, 0.030671779, -0.12606762, 0.010437313, 0.2757115, -0.21517593, -0.15800527, -0.12592544, -0.20578934, 0.10444053, 0.12993255, -0.046079267, 0.03834173, -0.19277227, -0.22124454) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.052546192, 0.026082167, 0.13831234, 0.10982424, 0.012946818, -0.12439852, 0.10134106, -0.10050398, -0.04472338, -0.14325236, -0.20579574, 0.0044005127, 0.22013672, -0.32955512, 0.12404084, -0.008160738) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.10774314, -0.31650826, -0.06601711, 0.19635755, -0.12622592, -0.06396423, 0.13856032, 0.16540553, 0.021387719, 0.23377723, -0.053738154, -0.1000186, -0.08338395, -0.052813534, 0.008122962, 0.13732094) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.18270823, 0.06966014, -0.17788303, -0.27303055, -0.077971615, 0.013978423, -0.02039098, 0.12715338, -0.11924171, 0.18900296, -0.085199654, 0.215198, 0.18587974, -0.009749325, 0.0173584, -0.12018259) * go_1(1.0, 0.0);
|
||||
result += mat4(0.052129295, -0.107416354, 0.12711766, 0.03708665, -0.14369462, -0.055359814, -0.16639823, -0.045143317, -0.06925672, -0.040696755, 0.01999809, -0.016040625, -0.02484878, 0.07417094, 0.050875198, 0.2145528) * go_1(1.0, 1.0);
|
||||
result += mat4(0.055696912, -0.16680926, -0.021987487, 0.024941636, -0.0927883, 0.022136632, 0.033782948, -0.10646058, -0.14944647, 0.25457275, 0.046682496, -0.022462368, -0.07886781, 0.08165927, 0.06848105, 0.0063734027) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.037053242, 0.033215813, 0.18291366, 0.12340375, 0.08491059, -0.28442004, -0.0127422465, -0.039834313, -0.23321372, 0.26676926, -0.05636355, -0.15672484, -0.12891728, -0.15486577, -0.032004442, -0.092745155) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.015779478, -0.18457565, 0.24996394, 0.036197674, 0.15694007, 0.15863103, -0.07332398, 0.0016235278, -0.15536517, -0.056062788, 0.14102836, 0.16915025, -0.08001087, 0.07073164, 0.13796777, 0.123867124) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.045792986, -0.15135059, -0.1354885, -0.043678258, -0.35655212, 0.51232076, -0.12816145, -0.046569496, -0.014127674, -0.06282611, -0.098873, -0.06359104, -0.0919222, 0.11822437, 0.079254694, 0.00579688) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.15683417, 0.61610246, -0.3024612, 0.12917964, -0.09303367, 0.23612969, -0.40842506, -0.12374661, -0.07572449, -0.2613284, -0.09970177, -0.015227848, 0.106239066, -0.21411185, 0.051998455, -0.1364518) * go_2(0.0, 0.0);
|
||||
result += mat4(0.23850034, -0.14394449, -0.0031468747, -0.2380617, -0.027200876, -0.041352056, -0.01864445, 0.033848196, -0.12064239, -0.110480845, 0.08450956, -0.22328654, 0.17664163, 0.22268307, 0.050886698, -0.17475672) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.17808256, 0.010803805, 0.03315186, 0.033143792, -0.14205995, 0.25039625, -0.08784382, -0.13454252, 0.19576813, 0.10755282, 0.22821628, 0.019456752, -0.0422955, -0.016182603, -0.12066697, 0.0548465) * go_2(1.0, -1.0);
|
||||
result += mat4(0.11563777, -0.257929, 0.0010403778, 0.080267854, -0.0025255163, 0.2855168, -0.060352214, -0.07816255, -0.00090574916, 0.049510725, 0.03720483, 0.059250016, -0.08674136, 0.20522198, -0.28694284, 0.1299507) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.14638457, 0.04063328, 0.03139636, -0.007934521, 0.07689684, -0.09467145, 0.10607347, 0.054510128, 0.003306194, 0.05347124, 0.062762424, -0.041480847, -0.07677865, -0.139573, 0.010972524, 0.21957156) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.026845628, -0.043439507, 0.034738723, 0.07281683, 0.14474197, 0.031586993, -0.22767854, -0.0707655, 0.105201736, -0.28805482, 0.008668302, -0.16329518, 0.06157049, 0.3803886, 0.26345953, -0.011096537) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.23328833, 0.085731484, -0.07755016, 0.33559516, 0.07704345, 0.115106605, -0.24114038, -0.44630137, 0.2726737, -0.32170138, -0.009236524, -0.11666051, 0.0457048, 0.07876708, 0.13134004, -0.035318643) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.05140272, 0.011605703, 0.13899171, -0.05071015, 0.18413687, -0.31413674, -0.13043414, -0.15118152, -0.15326938, -0.10720126, -0.23738635, 0.13481396, 0.25115076, -0.009316611, -0.2584441, -0.14389823) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.039723795, -0.14869407, -0.1692942, 0.026501274, -0.10685166, -0.121267825, -0.08584318, -0.09580693, -0.10626739, -0.068417974, 0.11321909, -0.13664317, 0.061380867, -0.2587898, 0.14850819, 0.008178645) * go_3(0.0, -1.0);
|
||||
result += mat4(0.06912782, 0.24230564, -0.048150286, 0.2203717, -0.17417085, 0.105546735, -0.16648416, -0.0045053074, 0.09764028, 0.37122592, -0.1939995, -0.27899942, -0.088152565, -0.53869057, 0.21676709, -0.08056594) * go_3(0.0, 0.0);
|
||||
result += mat4(0.07651754, 0.03704878, -0.0197015, 0.1660726, 0.07002748, -0.11820414, -0.23360898, 0.1481592, 0.029847002, 0.054057185, 0.013176299, 0.06552942, -0.13865773, -0.20105527, -0.37550658, 0.005769631) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.22697811, -0.17426412, 0.10148018, 0.008134666, 0.10771455, 0.16943407, -0.016319012, -0.40176705, -0.06854668, -0.049045276, 0.20919096, 0.13240765, -0.050125647, 0.14902508, 0.052697595, -0.13817468) * go_3(1.0, -1.0);
|
||||
result += mat4(0.04301619, 0.23184754, -0.023551717, 0.3768405, 0.028999053, 0.06709736, -0.05993663, -0.059861984, 0.15499207, -0.22217415, 0.111131504, -0.09082529, -0.19389243, 0.024621522, -0.15305442, 0.010799284) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.035496738, 0.010802548, -0.028718363, 0.19263634, 0.16900502, -0.16661702, -0.027631328, 0.18309957, -0.015860107, -0.03309961, -0.091390446, 0.14000848, -0.0036591904, 0.47659522, -0.09373507, -0.29020965) * go_3(1.0, 1.0);
|
||||
result += vec4(0.08895955, -0.027667087, 0.20500831, 0.00037762933);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.018134737, -0.2296755, -0.07276725, -0.029795367, 0.05382051, 0.092847414, -0.024469728, -0.1674685, 0.0017946451, 0.30074653, 0.0034195695, -0.04892261, 0.18229689, -0.20116119, -0.12702174, -0.08259108) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.1357695, -0.08149211, 0.09314453, -0.21966846, 0.34740716, 0.043606415, 0.04225903, 0.034449834, 0.17248215, 0.39148283, -0.13868807, -0.010550686, 0.044238456, -0.09693464, -0.005044985, 0.24383289) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.19959371, 0.098685324, 0.058746945, 0.010580748, 0.08051514, 0.031898864, 0.017556064, 0.13004355, -0.01727653, 0.11044019, 0.040673427, -0.20064595, -0.23321067, 0.06398686, -0.19126236, -0.2430858) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.12870286, -0.113455534, 0.23722827, 0.070718594, 0.19049989, -0.1927299, -0.06343845, 0.113127775, 0.082530305, -0.10972526, -0.090779535, 0.05731582, 0.11018802, -0.18049154, 0.09269507, -0.10304576) * go_0(0.0, -1.0);
|
||||
result += mat4(0.15513484, 0.06659583, 0.08125296, -0.012350324, -0.09492788, 0.5048303, 0.13206847, 0.39554298, 0.28953737, -0.20913891, -0.26781562, -0.17539899, 0.023778774, 0.29716817, 0.15768486, 0.37702608) * go_0(0.0, 0.0);
|
||||
result += mat4(0.0724462, 0.015571356, -0.032217246, 0.0050658924, -0.22708446, 0.03968809, 0.016753826, 0.0025668752, -0.055932112, 0.113931604, 0.19766758, -0.030027265, -0.17384295, 0.15013468, -0.0070017707, -0.09469028) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.078361556, -0.0954201, -0.006358101, 0.040500037, 0.4190454, -0.17622913, -0.07234791, 0.05462559, 0.18641087, 0.058313597, -0.0180785, 0.13818781, -0.14640772, 0.0699486, 0.0073663946, -0.076789856) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.21421191, 0.08736062, 0.09041226, 0.03608585, 0.02769972, 0.09641289, 0.11824623, 0.05653645, 0.16464607, 0.19839554, -0.13379547, 0.054417104, 0.067530684, 0.18971571, 0.13785432, -0.097639814) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.32658005, -0.14606023, -0.069448665, 0.032998275, -0.28331423, 0.0011900732, -0.020304207, -0.13535896, 0.08298347, 0.045509677, -0.030503955, -0.037504148, 0.049955815, 0.0925771, 0.00058534974, -0.12398032) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.2955836, 0.29059318, -0.018196672, -0.35866606, -0.01309431, 0.03540315, 0.010609202, 0.11956812, 0.10296229, 0.22536302, 0.015201129, -0.23797737, -0.16960852, -0.11414787, -0.034440614, 0.112644605) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.14952518, 0.07024436, -0.083184876, -0.0814617, -0.13303639, 0.016159372, -0.13521518, 0.2221334, -0.056617837, 0.12958299, 0.064461656, -0.20146395, -0.16023181, 0.2640758, 0.27528805, -0.1426518) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.04382363, 0.09856003, -0.08561442, -0.15699928, -0.121069774, 0.04685383, -0.009170197, -0.031489655, 0.18730178, 0.238442, 0.22497098, 0.032015145, -0.03709115, 0.1535079, 0.21674158, 0.10678019) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.12200952, 0.24224263, 0.034097504, -0.028179523, -0.011962496, -0.04489487, -0.05198827, 0.22194928, -0.045400873, -0.049828544, 0.111477956, -0.098361604, 0.12788995, -0.016093334, -0.19886433, -0.011161484) * go_1(0.0, -1.0);
|
||||
result += mat4(0.30563712, 0.013071727, -0.004799883, 0.12888052, -0.259498, -0.041566677, 0.07311124, 0.162324, 0.28371668, -0.004693743, -0.0019395344, 0.029358242, 0.08730285, 0.12184509, 0.05508437, 0.048439097) * go_1(0.0, 0.0);
|
||||
result += mat4(0.12760857, 0.115813166, -0.217695, -0.10629871, -0.227366, 0.09030426, -0.15313712, 0.020528946, -0.20743734, 0.088583544, 0.04594053, -0.22891994, 0.18949282, -0.042186577, -0.17330512, -0.010711361) * go_1(0.0, 1.0);
|
||||
result += mat4(0.029503195, 0.0063797613, -0.17004286, -0.096844055, 0.010218098, 0.04247233, 0.02362808, 0.14700809, -0.08082364, 0.11159672, -0.018505255, -0.15228583, 0.15693732, -0.025359154, 0.024829186, 0.1943192) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.03912932, -0.21989027, 0.12203028, 0.18702275, -0.118537985, 0.21039696, 0.09102061, 0.012288879, 0.031666897, 0.1318455, -0.04901404, -0.07516063, -0.44782668, 0.04884501, 0.047070876, 0.008728358) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.08669101, 0.3053463, -0.08963947, 0.0034188698, -0.070004664, 0.064788476, 0.093737036, 0.070050925, 0.12728429, -0.13179256, -0.014913502, 0.09308136, -0.027638942, 0.008638711, 0.08794172, -0.05531093) * go_1(1.0, 1.0);
|
||||
result += mat4(0.0728421, 0.07872358, 0.11454748, 0.08497922, 0.071820416, -0.11789207, -0.08184197, 0.1359588, -0.2143346, -0.05876081, 0.023172129, -0.08430511, -0.19276723, 0.14283359, 0.15604696, -0.055187486) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.068641685, 0.2732106, -0.2809107, 0.12736696, -0.08642367, 0.023898933, -0.17859498, -0.18299665, -0.06684587, -0.12204666, 0.45898953, -0.24240111, 0.25182098, -0.04395751, 0.10637211, -0.22135144) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.0852072, 0.051133018, 0.03333165, -0.0008938216, 0.10251267, 0.0550774, 0.041769378, -0.21259712, 0.286912, 0.123342015, 0.282759, -0.0730124, 0.14275575, -0.15580742, -0.15224406, 0.045376908) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.03328225, 0.11563978, -0.07451964, 0.030546209, -0.04698351, -0.18544962, 0.037350416, 0.13969816, 0.0556746, -0.06359919, 0.06478219, -0.031694926, 0.13396506, 0.09443612, -0.01922686, -0.06290365) * go_2(0.0, -1.0);
|
||||
result += mat4(0.07495407, 0.063429266, -0.106221214, -0.085107304, 0.2497817, -0.46598253, -0.18833177, -0.2731128, -0.13024822, 0.56053543, 0.055704467, -0.12331414, -0.031199086, 0.05061188, 0.22097112, -0.6611177) * go_2(0.0, 0.0);
|
||||
result += mat4(0.08276988, -0.044184342, -0.03562185, -0.06159881, 0.27694225, -0.07192965, -0.08663714, 0.020221777, 0.14095962, -0.06229397, 0.051374253, -0.038158998, 0.10664802, -0.041305423, 0.051260717, -0.054698635) * go_2(0.0, 1.0);
|
||||
result += mat4(0.12800686, 0.03485072, 0.039914366, 0.034041498, -0.08305794, -0.046292894, 0.22765331, 0.10904922, 0.0013937047, -0.08750301, 0.009126207, -0.065589435, 0.2837707, 0.08884436, -0.07234862, -0.093502745) * go_2(1.0, -1.0);
|
||||
result += mat4(0.113439895, 0.06081726, 0.1122302, -0.022936966, 0.10329637, -0.31816107, -0.051597945, 0.23846027, -0.083913095, -0.29872265, -0.040147282, -0.08981918, -0.04329814, -0.12339693, -0.034489952, 0.013393211) * go_2(1.0, 0.0);
|
||||
result += mat4(0.33091688, 0.1726297, 0.034332044, -0.091396205, 0.15434311, -0.0022870845, -0.15506189, 0.08710491, -0.16063525, 0.042252056, 0.017086457, 0.08134797, 0.08631321, 0.037843138, 0.088296555, 0.0064518084) * go_2(1.0, 1.0);
|
||||
result += mat4(0.09161051, 0.114355795, -0.15304486, -0.030537153, 0.1835368, -0.3287635, 0.031197926, 0.09717476, 0.04276852, 0.113250345, 0.05949038, -0.10599563, 0.43574792, -0.060788117, 0.18409383, 0.12678055) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.018356865, -0.0072578182, 0.12020777, -0.013127592, 0.20136636, -0.22984362, 0.06896224, 0.00044982752, 0.008428429, -0.123316936, -0.09989286, 0.078248784, -0.16313677, -0.003020313, -0.46285018, -0.08967125) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.03451497, -0.10864502, 0.13207638, 0.17194521, 0.0037514758, -0.20222199, -0.12535086, 0.001511977, 0.056294486, -0.2112898, 0.078261316, 0.10118746, -0.044742294, 0.21793383, -0.19927903, -0.21338293) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.034903776, -0.10167085, 0.031066334, 0.0379958, 0.20532596, -0.17457838, 0.16556816, -0.0021619152, 0.02682665, 0.03396325, -0.059273884, 0.1922813, -0.072151475, -0.010240544, 0.2302027, 0.12385962) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.20170145, -0.08203941, -0.028107846, -0.18003726, 0.44744352, -0.13190243, 0.13233365, 0.03626546, 0.085763134, -0.25613126, -0.11213388, 0.15529087, -0.271649, 0.050587676, -0.062583975, 0.057289865) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.040649455, -0.17949733, 0.35847965, -0.040587306, 0.24314344, -0.23811667, 0.13958354, 0.04961874, 0.09858903, -0.04202913, -0.21850993, 0.0700419, -0.09130745, -0.096835814, 0.0022782686, -0.25416258) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.08215545, -0.019647893, 0.055263475, 0.053733055, 0.098485716, -0.1041945, -0.06541415, -0.08868577, -0.07262986, 0.03513784, -0.110529095, -0.03369232, 0.056786604, 0.2569229, -0.05931065, -0.22081214) * go_3(1.0, -1.0);
|
||||
result += mat4(0.066926084, 0.029664058, -0.10779271, 0.11026963, 0.23927264, -0.16914488, 0.022947345, 0.12303853, -0.07066212, -0.013205378, 0.15348643, 0.035568032, 0.20966691, 0.010149819, -0.08814468, -0.064854674) * go_3(1.0, 0.0);
|
||||
result += mat4(0.11493852, -0.074924305, -0.14840698, -0.16956823, 0.056806292, -0.06387947, -0.06880271, -0.04637334, -0.1929893, 0.18226422, 0.064644486, -0.1594863, 0.027403917, 0.13951495, -0.06569123, -0.07700207) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.043347504, -0.20504741, -0.037821215, -0.014486937);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf1
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.047881734, -0.09396414, -0.2839081, 0.3140853, 0.052613556, 0.09940423, 0.23960467, -0.022228222, -0.12065009, 0.07898222, 0.08657881, 0.010852739, -0.050450284, 0.01683982, 0.031813968, 0.053060856) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.10252411, -0.03116448, -0.30114275, -0.0316799, -0.017501019, -0.03006003, -0.2095696, 0.10134927, -0.3901916, -0.15335023, -0.11955071, 0.1337449, 0.101239376, -0.25044814, 0.2128469, 0.018979514) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.13392173, 0.052036732, 0.1682114, -0.026263753, 0.027221246, -0.15121374, 0.13723798, 0.08950682, -0.1182108, -0.07294226, 0.023392374, 0.052329235, -0.05632852, -0.07036173, 0.06872573, 0.05238042) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.18112028, 0.18242362, -0.06812871, 0.032463413, 0.124638766, -0.26765212, -0.07678663, 0.33806562, 0.09674393, 0.15574542, 0.23634006, -0.02873782, -0.1626769, -0.14760062, -0.007274849, 0.09866139) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.10726673, -0.10925056, 0.19967109, -0.19936769, 0.15942842, -0.14870064, 0.15493345, -0.08489036, -0.49053356, -0.17321263, 0.28426084, 0.18721215, -0.09898434, -0.2751838, -0.11833524, 0.028445128) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.11788817, -0.23724948, -0.046072144, 0.035621114, 0.04527003, -0.0073492974, 0.11097195, 0.06806836, 0.04814677, -0.1408476, -0.1325629, 0.00929532, -0.16699041, -0.03034791, 0.08320368, -0.15429299) * go_0(0.0, 1.0);
|
||||
result += mat4(0.2729515, 0.008244692, -0.17441982, -0.39026466, 0.17381759, 0.31194404, 0.055934936, 0.20744409, 0.20119062, 0.0734271, 0.0796807, 0.0031037466, -0.0016392237, 0.033733975, 0.07149338, 0.042083208) * go_0(1.0, -1.0);
|
||||
result += mat4(0.07985744, 0.10945015, 0.018472541, 0.1397503, 0.2005682, 0.42641, 0.23022486, -0.2916921, 0.028285174, -0.31885162, -0.27070364, -0.10390779, 0.0751492, 0.12752363, -0.2279459, 0.08998453) * go_0(1.0, 0.0);
|
||||
result += mat4(0.18450491, -0.140783, -0.008006845, 0.09029298, 0.12536179, 0.26949662, 0.09491545, 0.063907005, 0.11212244, 0.09778506, -0.1835966, -0.053119674, 0.0072294096, 0.25018227, 0.010868525, -0.22721334) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.028011927, -0.20073172, 0.5976166, -0.19494139, 0.17958745, -0.03838646, 0.058325976, -0.29409218, -0.12793432, 0.03245129, 0.35662368, -0.05048354, -0.13368197, -0.06151968, -0.012714591, -0.1763054) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.18468465, 0.31682113, 0.12818255, -0.117110476, 0.13709468, -0.10034022, -0.07994527, -0.1259309, 0.04067299, -0.1147398, 0.28361055, 0.27916273, 0.03696692, 0.16829546, 0.27819383, 0.08305029) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.28920117, -0.033877946, 0.01586206, 0.04681198, 0.024248574, -0.045777842, -0.03342128, 0.07525412, -0.063377544, -0.016737273, 0.11235511, -0.04325238, -0.24170023, -0.09993599, -0.03205371, 0.14339828) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.008357902, -0.11038377, 0.03709221, 0.26775306, 0.07963845, -0.25377446, -0.17630441, -0.10966474, 0.057311732, -0.083327, 0.044497233, 0.06903858, -0.26531395, -0.103399664, -0.14806591, 0.269314) * go_1(0.0, -1.0);
|
||||
result += mat4(0.05450808, -0.041993964, -0.07217651, 0.034468375, 0.2117634, 0.0075620585, 0.05825411, -0.2252478, -0.0527787, 0.049732126, -0.032040413, -0.09361454, 0.29585132, 0.018413153, 0.18384546, -0.024226356) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.031109914, 0.19351351, 0.07405522, -0.06313074, -0.09983541, -0.011495182, 0.11749038, -0.16775608, 0.2790974, -0.09338754, 0.07913264, 0.103792936, -0.18679164, -0.15639925, 0.112943865, 0.07930375) * go_1(0.0, 1.0);
|
||||
result += mat4(0.004106195, -0.036833283, 0.12908752, 0.12869535, -0.02472107, 0.17561707, -0.025890926, -0.18789047, 0.096218705, -0.16306408, -0.02198454, -0.010134957, -0.09710009, 0.002062143, -0.046785697, 0.0029441968) * go_1(1.0, -1.0);
|
||||
result += mat4(0.19648251, -0.015663045, -0.0730215, 0.028611008, 0.13529862, -0.015256192, -0.04119306, -0.24628192, 0.02601027, -0.21184283, -0.1962902, 0.09109358, -0.06792383, 0.092336476, 0.12215351, -0.08596062) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.17530201, -0.0351919, -0.31872514, -0.13933206, -0.07000922, -0.049807087, 0.0010997375, -0.033573963, 0.07442056, -0.33290103, -0.40381998, 0.09435, -0.3280128, -0.09953127, -0.11283648, 0.20685865) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.052573867, -0.035328753, -0.11132943, -0.17515652, 0.05021051, 0.058642425, -0.046640664, 0.0799107, -0.027398815, -0.33619994, -0.22135767, 0.07894002, -0.14941697, -0.0940996, -0.11655085, 0.049795926) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.039301276, 0.041062318, 0.20312686, -0.009338705, 0.013706282, -0.0245852, 0.03458311, 0.09601228, -0.18203016, -0.012260314, 0.17984508, -0.056576703, -0.102844186, 0.24047872, 0.05307189, 0.16066082) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.1478775, 0.0046362123, 0.05459521, 0.07162838, -0.01896149, 0.23700175, -0.14174299, 0.06988599, -0.32545477, -0.08065096, -0.061227743, -0.0010796773, 0.094327345, -0.20760082, -0.19523263, 0.19859222) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.049676366, -0.10381536, 0.02546116, -0.13127093, 0.10954914, 0.0048147943, 0.06962328, -0.30456528, -0.11956627, 0.0150488885, -0.10711722, 0.1684613, -0.1939089, -0.10577047, -0.11980919, -0.036988296) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.054795764, 0.09491116, -0.08494948, 0.059765853, 0.0131597435, 0.20786162, 0.11999637, 0.024381055, 0.22830428, 0.027053319, -0.011646274, -0.12145409, -0.07899559, -0.012688263, 0.10684157, 0.3824219) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.23994572, -0.0031532666, -0.0050638164, 0.14236279, 0.05690383, -0.06259682, 0.052624144, 0.20461404, -0.19230312, -0.11072268, 0.013023965, 0.08931543, -0.21997221, 0.11760443, -0.40943825, 0.28656834) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.06606179, 0.26007771, 0.033754125, 0.119690455, 0.024669139, -0.06752839, 0.12688096, -0.0063201943, -0.17123021, 0.07548857, -0.14213699, 0.034093797, -0.15632647, -0.123243414, -0.42634043, 0.1715022) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.046503466, 0.13876389, 0.17973013, -0.25938338, -0.18824704, -0.11876702, 0.31065792, -0.041042212, -0.061369427, 0.2057992, 0.17295738, 0.3836555, -0.21109799, -0.10167118, 0.16577047, 0.113483034) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.24534856, -0.014482421, 0.22515748, -0.12773542, 0.12794174, -0.02528619, 0.41710484, 0.09154934, -0.17805946, -0.25428918, 0.07294183, 0.047079418, -0.30949152, -0.08919157, 0.17888431, 0.17706038) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.1741826, 0.046225294, -0.10761791, 0.2619953, 0.007373745, 0.05104337, -0.22309966, 0.34529984, -0.034363825, -0.022187237, -0.08609555, 0.16842419, 0.28136057, 0.17843607, -0.11307746, -0.05668021) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.12310616, -0.29661375, -0.10581025, -0.049584012, 0.19651765, 0.08436489, -0.14533581, -0.029874112, -0.15422897, -0.062741704, -0.22694711, -0.15547274, -0.15181333, 0.0286061, 0.022438493, -0.062447168) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.3497046, -0.09455009, 0.060618952, -0.2134236, 0.054515295, 0.07451165, -0.09267233, -0.010513333, 0.13842636, 0.11563433, -0.054750167, 0.050432, 0.1514256, 0.04284002, -0.2095581, 0.07907657) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.11745651, -0.04717057, 0.085377194, -0.065956995, 0.07280491, 0.2730059, 0.11088276, 0.2437957, 0.14018989, 0.1164107, -0.09516929, 0.0022427947, 0.111544006, -0.0680495, 0.09324579, -0.12482022) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.07995795, -0.03387884, 0.019846136, 0.10231208, -0.07017192, 0.18659039, 0.035161644, 0.101182766, -0.14901665, 0.21307294, 0.063894205, -0.27546507, -0.24792959, -0.067731075, 0.13146006, -0.19333683) * go_3(0.0, 0.0);
|
||||
result += mat4(0.034206454, 0.1472648, -0.07406727, 0.014654025, 0.18703444, 0.1319857, -0.10610886, 0.08427947, -0.017536618, -0.06487879, -0.12095286, -0.050414838, 0.03260879, 0.1558894, -0.031887084, 0.11840288) * go_3(0.0, 1.0);
|
||||
result += mat4(0.114811294, -0.14574333, -0.09392587, 0.042283528, 0.08919092, 0.18259068, 0.0980717, 0.21024778, -0.1280008, -0.027260462, -0.1129027, 0.18722472, 0.13733985, 0.047153983, 0.030871978, 0.1998385) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.06783575, 0.004612595, 0.1153467, -0.11531557, -0.048889533, 0.07673577, -0.02041786, 0.22744459, -0.13092506, 0.13484807, 0.40003043, -0.053706612, -0.16985156, -0.04791236, -0.052443005, -0.08363625) * go_3(1.0, 0.0);
|
||||
result += mat4(0.18187882, 0.017893985, 0.17856054, 0.005413129, 0.014147176, 0.15102178, 0.12436294, -0.02176765, -0.16727823, -0.0364111, 0.17074408, 0.12899421, 0.31984514, -0.0072070034, 0.031895883, -0.1991405) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.011865144, 0.11717201, -0.13823777, -0.059450272);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.082203194, 0.021720003, 0.03725474, -0.08048348, 0.2063248, -0.033020593, -0.17585336, 0.06476272, 0.012244563, 0.026554609, 0.014708393, 0.26606125, 0.14248778, 0.12817341, -0.039826933, -0.12751861) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.24573852, 0.19695967, -0.06257417, -0.04782871, 0.3511875, -0.018083302, -0.077342674, 0.15247667, 0.20321761, -0.07479984, -0.09548503, 0.08109568, -0.23808748, 0.07246303, -0.004242619, 0.16162953) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.13296306, 0.19495387, 0.009222276, 0.033592198, 0.20443891, 0.16063854, -0.2581601, -0.016132578, -0.2296461, -0.23647323, -0.15407176, -0.18265317, 0.2343241, -0.049697313, -0.09398783, 0.41931856) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.10866088, -0.40605694, -0.0042648134, 0.07943803, 0.26914695, 0.14816476, 0.037706107, -0.123223364, -0.19962949, -0.053534556, -0.08397409, -0.04244924, -0.075791344, 0.29629225, 0.2311928, 0.099177904) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.1748319, -0.2003186, -0.32659066, -0.21007413, 0.20122464, 0.032196607, -0.026299698, 0.33395135, 0.11411664, 0.05971959, 0.09001304, -0.15936212, 0.012322024, 0.19936106, -0.411186, -0.08319479) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.07349218, 0.006184436, 0.096199185, -0.050186496, 0.064047046, -0.03813128, -0.057007037, -0.025550695, -0.2863145, -0.008512981, -0.20615962, 0.18009211, 0.008298396, 0.22452813, 0.010843521, 0.20169461) * go_0(0.0, 1.0);
|
||||
result += mat4(0.2691149, 0.059546687, 0.08922005, 0.2252196, 0.30341956, -0.024489028, 0.087045394, -0.03856442, -0.14083561, -0.17683443, 0.14137806, 0.15520614, 0.2073925, -0.19525874, 0.23661858, 0.3098405) * go_0(1.0, -1.0);
|
||||
result += mat4(0.006530723, 0.04180736, -0.04762067, -0.064395495, 0.02396811, -0.13332283, 0.0037775645, 0.026309434, 0.0033065109, -0.08315753, 0.02917419, 0.12330464, 0.22819455, -0.07489677, 0.12829056, -0.097994626) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.09983759, 0.032783493, 0.11085758, 0.08993078, -0.057110567, -0.018973934, -0.14946178, -0.03921629, 0.039757587, 0.015860094, 0.04989561, -0.19634786, 0.04351146, 0.019315343, 0.25972188, 0.17989321) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.04111906, -0.165601, 0.0003682197, -0.056232415, -0.32716644, -0.24015541, -0.057547837, 0.05966729, 0.06854747, 0.03599213, -0.18798864, 0.1183447, 0.014268468, -0.1310834, 0.06415977, -0.19414157) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.00070661673, 0.17671427, 0.10584568, -0.060910843, -0.104282066, -0.22676118, -0.01907062, 0.24882245, -0.043454725, 0.07691623, -0.48371696, 0.013537671, -0.025488405, 0.061228953, 0.18548754, 0.028671112) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.0121596735, 0.09595702, -0.08244918, -0.1176173, 0.26773354, -0.021729136, 0.075465776, -0.0928876, 0.12461298, 0.16830076, -0.15302569, 0.113850676, 0.09811088, 0.13006307, 0.24999009, 0.10261325) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.032246377, 0.038265374, -0.26476422, -0.1442876, -0.19866082, 0.08649541, 0.041478764, 0.11155026, 0.21576422, -0.09572912, -0.11174068, -0.19722937, -0.15801935, 0.29604745, -0.08606268, -0.15532136) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.06315591, 0.16151646, -0.009230362, -0.04341246, 0.09085519, 0.21924476, 0.38044852, 0.193819, 0.16622902, 0.0025134624, -0.22688466, -0.025276015, 0.07714917, 0.16302192, -0.11767101, -0.11086476) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.04170153, 0.001859292, -0.26352355, 0.10982333, -0.031867817, 0.15773517, -0.060263418, 0.11117763, -0.017359972, 0.0127261225, 0.0782802, -0.16908924, 0.080516845, -0.05691526, -0.07530135, -0.14553802) * go_1(0.0, 1.0);
|
||||
result += mat4(0.06112685, -0.032287434, 0.17445667, -0.044935808, -0.11449107, -0.051394563, -0.029589338, -0.14555557, 0.03440661, 0.11035615, -0.17175, -0.14851089, 0.037362, -0.18740481, 0.17278154, 0.18073405) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.27670652, 0.19484822, 0.2609349, 0.1455016, 0.04438468, 0.1449185, 0.11185832, -0.18598269, -0.019846648, 0.11886126, -0.098498635, 0.15737785, 0.011406795, -0.18860829, -0.13705735, 0.17535745) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.30244905, -0.28695273, 0.1146976, 0.21144345, -0.037980128, -0.027679864, -0.13992494, -0.04884521, -0.032023884, -0.07921183, -0.16042095, -0.06935386, -0.06570237, -0.1107404, -0.018163798, 0.22625941) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.07292955, -0.07321777, -0.045146503, -0.33291966, -0.096732594, -0.07203495, 0.33692798, 0.2870733, 0.122160144, -0.076574564, 0.042844944, 0.26448342, 0.07672146, -0.028775277, -0.12088313, 0.15583947) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.21589327, 0.05258274, 0.09705794, -0.024653846, -0.039402515, 0.28485695, 0.14711736, -0.10556087, -0.15140481, 0.09039498, 0.017308712, 0.11862922, 0.08230978, 0.21678248, -0.043815188, -0.226433) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.029258793, 0.26618922, 0.02564014, -0.23189862, -0.24074338, -0.18556763, 0.25973624, 0.04746873, 0.0137007125, -0.22239363, -0.12414957, 0.048228756, -0.22406264, 0.282667, -0.021001073, -0.17465611) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.32401654, -0.1495363, -0.20869227, 0.04271639, -0.0087802755, 0.031325378, 0.23834595, 0.039336167, 0.17265107, 0.20947595, 0.28737286, 0.0028783784, -0.057340365, -0.050347418, -0.11915604, -0.1831807) * go_2(0.0, -1.0);
|
||||
result += mat4(0.1811338, 0.07732653, 0.20975596, -0.47129005, 0.07121942, 0.08410583, 0.44170937, -0.19524159, -0.17807977, 0.12837476, 0.20816846, -0.1741958, -0.04411918, 0.06024972, 0.18159702, -0.052485272) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.15229738, 0.27513, 0.28150418, -0.19543962, -0.02045864, -0.07207227, 0.09589587, 0.09110817, 0.061413247, 0.0046052113, 0.11619411, -0.2988938, 0.065739445, 0.10205611, 0.12847126, -0.028355654) * go_2(0.0, 1.0);
|
||||
result += mat4(0.0657154, -0.047568597, -0.16148911, 0.16392621, -0.25281775, -0.061153214, 0.017480455, -0.026288848, 0.20319715, 0.04763355, 0.010444491, -0.26671803, -0.25821987, 0.32863674, -0.30734694, -0.18190521) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.042703815, 0.06633036, -0.048434302, -0.17176376, -0.12699759, -0.1124558, 0.083266065, 0.03354623, -0.13468939, 0.12706263, 0.053659134, -0.06930602, 0.008196115, 0.2034998, -0.06351442, -0.039730288) * go_2(1.0, 0.0);
|
||||
result += mat4(0.09614661, 0.22500272, 0.088511504, -0.16960482, 0.15364788, -0.18854137, -0.13163191, -0.07503735, -0.23177068, -0.0053305267, -0.041978605, 0.0971947, -0.049034655, 0.04486706, 0.09076307, -0.02310868) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.1304683, 0.17743458, -0.09817326, -0.0646786, 0.07886976, 0.20109388, -0.034114968, -0.2029261, -0.03348398, 0.029337432, -0.07302782, -0.02240758, 0.030242773, -0.30032325, 0.02085572, -0.027314361) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.037377544, 0.026350772, -0.07430488, -0.114671774, -0.126935, -0.046512567, -0.033628833, -0.19018382, -0.041053895, -0.031206857, 0.08562848, -0.01875709, 0.21099389, -0.092511, 0.0073047103, -0.009811013) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.11358029, 0.17468451, -0.12739041, -0.14332245, -0.22230148, 0.16862972, -0.04462456, 0.2469604, -0.008622369, 0.0081848325, -0.17032363, -0.16024362, 0.21178265, 0.037127133, 0.08559072, 0.11584694) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.008993893, -0.08037705, 0.4426555, 0.15593371, 0.15273719, -0.03249998, 0.055109, -0.1512612, -0.037183985, 0.20825677, -0.08516227, -0.06664223, -0.10011001, -0.3505215, -0.17941694, 0.052089088) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.109703645, -0.13505603, 0.1336451, 0.13118869, 0.010915504, 0.12748592, 0.21201555, -0.40841985, -0.11059143, 0.033772044, -0.039282143, 0.03095394, 0.10394723, -0.21343367, -0.10699851, -0.028351074) * go_3(0.0, 0.0);
|
||||
result += mat4(0.019704714, 0.06243651, 0.09896519, -0.17492259, 0.012675787, -0.004239029, 0.21319824, 0.069183126, -0.0071114586, 0.123431124, -0.24479835, 0.00723795, -0.045293927, 0.014101029, 0.15746681, 0.042405806) * go_3(0.0, 1.0);
|
||||
result += mat4(0.023828225, -0.0015190929, 0.1194638, 0.082163885, 0.10532113, 0.042044062, 0.02528007, 0.015175004, 0.026613194, 0.33525538, -0.1627064, -0.29887968, -0.197707, 0.038967777, -0.15811683, -0.106895216) * go_3(1.0, -1.0);
|
||||
result += mat4(0.044362027, -0.04946742, -0.14815849, -0.17660522, -0.034201477, -0.012243106, -0.050183997, 0.06407372, 0.039822515, 0.15880872, -0.0672721, -0.4081093, 0.019489579, -0.060278706, -0.015096743, -0.07799167) * go_3(1.0, 0.0);
|
||||
result += mat4(0.11861756, 0.27113584, -0.14107186, -0.10246008, -0.124051, -0.1627854, 0.10698585, 0.2846401, -0.061731786, 0.1724438, -0.12428688, -0.09986041, -0.034171514, -0.07100923, 0.041739646, -0.11308375) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.02981662, -0.26338395, -0.011632586, 0.15063232);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf1
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.17082009, 0.031344634, -0.06131912, 0.00887183, -0.01528174, 0.12943709, 0.24537678, 0.008178781, -0.312396, -0.023583878, 0.07827866, -0.1231261, 0.15081584, -0.18161978, -0.25179705, -0.036934935) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.05768411, 0.16785417, -0.1788644, -0.0067257965, 0.021445744, 0.10066516, -0.23864186, 0.1450302, 0.12892793, 0.19856106, -0.24444748, 0.16531628, -0.044425935, -0.02775357, 0.009059946, -0.12958384) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.025798557, -0.17238182, -0.34056288, -0.20921059, -0.03576266, 0.1476854, -0.06264234, 0.14452787, -0.04130045, -0.07275762, 0.034578666, 0.2914669, 0.20879944, 0.21359251, -0.048695553, 0.2638088) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.022791177, 0.4204545, 0.116855636, 0.20241925, -0.010444933, -0.14462502, 0.022550104, -0.24423064, -0.09417524, 0.045358784, -0.11405829, 0.035979558, -0.2283092, -0.06670842, -0.23852053, -0.22417003) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.14526704, 0.040880535, 0.14076385, 0.07795045, -0.059177604, -0.13056375, -0.3373641, -0.19344307, -0.29891858, -0.32578763, -0.29061425, 0.1562214, -0.13578376, 0.36586633, 0.24936736, 0.054629393) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.025790233, -0.13020341, -0.10084969, 0.15767297, -0.09738769, 0.04034404, 0.0038675873, 0.043515608, 0.16899958, -0.29117966, 0.03420067, 0.14432564, -0.10473084, 0.21014084, 0.07775908, -0.09303797) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.07443987, -0.16225167, 0.036251917, 0.028432872, 0.03759333, 0.004027401, -0.033941846, 0.0019474924, 0.02357054, 0.30748722, 0.1652115, -0.17361522, 0.16905582, 0.08048018, -0.23639561, -0.029408466) * go_0(1.0, -1.0);
|
||||
result += mat4(0.0461233, -0.09346199, -0.07063276, -0.19447634, -0.049339604, -0.0032855074, -0.22661209, -0.0543389, 0.11924857, -0.21691081, -0.1645725, -0.0075736847, 0.018572787, -0.06552861, -0.01777661, -0.11651732) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.06425901, 0.123392984, -0.16395192, -0.093448035, -0.029316641, 0.0986573, -0.23135012, 0.011170849, 0.00023920486, 0.15296175, 0.35453254, -0.05189021, 0.20708887, -0.103900835, 0.081992395, -0.21829562) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.019074136, -0.1572586, 0.27919227, 0.09119617, 0.035954695, 0.2941489, 0.18262725, -0.055522963, -0.21364328, -0.1573611, 0.104966134, 0.08228523, 0.19945285, -0.0039229114, -0.1565048, 0.028975379) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.18501253, 0.006473006, 0.06637501, 0.04295065, 0.06411007, 0.1166344, -0.10060226, 0.46296063, -0.08600344, -0.03560105, 0.012215349, 0.017885283, 0.061346993, 0.17336361, 0.01935021, 0.20198092) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.04451627, -0.10372061, -0.13968691, 0.14479733, 0.1660607, 0.19334625, 0.0085214665, 0.28863636, -0.07600901, -0.014777084, 0.13209191, -0.09045013, 0.104893915, -0.04776884, -0.007936376, 0.104568765) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.023751335, -0.108048, -0.050531313, 0.15916029, 0.13246661, 0.04644228, -0.09586482, -0.17222965, -0.22898191, -0.033484615, 0.078883134, -0.052609313, -0.2721741, 0.045986425, 0.13972299, -0.28923607) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.23364568, -0.008875902, -0.40894926, 0.060443908, -0.2839635, -0.5270991, -0.2500865, 0.002020195, -0.24488612, -0.04982319, -0.009110353, -0.018023955, 0.06647274, -0.25225738, 0.26154432, -0.033934146) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.1535129, -0.21257545, -0.16553773, 0.17471452, -0.06203719, 0.15238857, 0.18702018, 0.18572305, 0.07740396, -0.074217625, -0.072156586, -0.2183728, 0.00403749, 0.13750519, 0.30362993, 0.06550286) * go_1(0.0, 1.0);
|
||||
result += mat4(0.37164542, -0.1980723, -0.15659203, 0.19498909, 0.01748114, 0.011807152, -0.05424202, 0.11926474, 0.050406165, -0.12925303, -0.020280985, 0.08429331, 0.14769496, -0.077555746, -0.15216178, -0.27070466) * go_1(1.0, -1.0);
|
||||
result += mat4(0.35804263, 0.08539285, -0.14785156, -0.13532467, 0.058254432, 0.20448379, -0.006173341, 0.058168225, -0.21714899, -0.13472849, -0.09392532, -0.12753737, -0.097461835, -0.11419082, 0.09384189, 0.06414768) * go_1(1.0, 0.0);
|
||||
result += mat4(0.023494452, -0.22187226, -0.16694295, 0.0204334, -0.26720086, 0.15916729, 0.3098874, -0.10292057, 0.008854983, 0.13375004, -0.04409455, 0.09286524, 0.095829524, 0.12427317, -0.048659876, 0.18300754) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.119153984, 0.10163183, 0.025017537, -0.40096784, 0.026778705, 0.15821172, -0.19947284, -0.33337715, 0.2952563, 0.16820388, -0.057061996, -0.029319009, -0.12184868, 0.09031512, 0.12028806, 0.021044692) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.086744264, -0.046958666, 0.2130253, -0.46672252, 0.07135636, 0.0100029735, -0.13828261, -0.012365689, -0.11374441, 0.21084632, -0.059631422, -0.013799735, -0.037889663, -0.10701892, -0.09493782, 0.15516634) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.031181194, -0.01535001, 0.029270316, 0.13128386, 0.11838377, -0.17051528, 0.12228499, -0.04841128, 0.33350074, -0.006144013, -0.09055018, 0.27470216, -0.26665646, -0.08703671, -0.01719071, -0.23449609) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.12856458, 0.005562174, -0.19517267, 0.13270985, 0.2776414, 0.032003902, -0.15778573, 0.15344355, 0.26930434, -0.13459459, 0.035019353, 0.08896612, 0.12847935, -0.122637205, 0.001815178, 0.08290523) * go_2(0.0, -1.0);
|
||||
result += mat4(0.33805037, -0.15318587, -0.20955376, -0.26121393, -0.026022578, -0.1617741, 0.1336867, 0.026223289, 0.012059392, -0.17295446, -0.060811974, 0.14027825, -0.21134059, -0.08408573, -0.23773228, 0.110836074) * go_2(0.0, 0.0);
|
||||
result += mat4(0.16176093, 0.15307428, -0.07711325, -0.3458805, 0.061291527, 0.023916256, 0.21370678, 0.0015756418, 0.10642374, 0.24807373, 0.11164451, 0.10780487, 0.087194376, -0.2718231, -0.008457387, 0.054078236) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.03259038, -0.20923306, 0.165477, 0.098864526, -0.02734457, 0.08871225, -0.01552188, 0.047712058, 0.055032052, -0.13044262, -0.2899521, 0.22230095, -0.029343741, -0.16427459, -0.005436118, -0.05111821) * go_2(1.0, -1.0);
|
||||
result += mat4(0.20065974, -0.1556366, -0.12620135, 0.44572976, -0.020925352, 0.12025185, 0.20588058, 0.06391864, 0.046870507, 0.16942503, -0.049370963, 0.008779016, 0.04954915, 0.090298936, -0.16466027, 0.011152038) * go_2(1.0, 0.0);
|
||||
result += mat4(0.13587528, 0.047841422, 0.19804007, -0.1672396, -0.072491, 0.04543739, 0.25287256, 0.015226213, 0.02007356, -0.049578942, -0.08796175, 0.1714897, -0.07819061, 0.1509537, 0.093094915, 0.031139288) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.013774682, 0.118201815, -0.009592314, -0.10837201, -0.0686881, -0.083380274, 0.107689425, 0.046642892, 0.119898744, -0.05502989, -0.19719897, 0.0005697584, -0.0921928, 0.032281205, 0.2568853, 0.2325449) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.02991112, -0.09898633, 0.06076172, -0.20906185, 0.0026118348, 0.06130956, 0.06760944, -0.16662054, 0.065741204, -0.13144116, 0.011419801, 0.22552124, 0.1465757, -0.07417319, -0.10788749, -0.24952699) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.19238451, -0.024058497, 0.19580396, -0.067399554, -0.18832864, -0.11752747, -0.078949094, -0.23762032, -0.04141864, 0.022530237, -0.02222157, 0.0054874527, 0.057746816, -0.34854797, 0.028730657, -0.08976777) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.16888975, 0.19949849, -0.08456147, -0.03619044, -0.019596824, 0.11214634, 0.13971676, 0.22926724, 0.03219445, -0.04566354, -0.14948955, -0.22817011, -0.08714846, -0.19684613, 0.15479128, 0.2433362) * go_3(0.0, -1.0);
|
||||
result += mat4(0.16050309, -0.102841675, 0.20855242, -0.011171905, -0.10309409, 0.22455123, 0.15892951, -0.06582373, 0.010079549, -0.2055006, -0.09385158, 0.006519388, 0.11838815, 0.37134558, -0.165772, 0.12704434) * go_3(0.0, 0.0);
|
||||
result += mat4(0.11643292, 0.03294274, -0.09800525, -0.13601723, -0.081318736, -0.059975546, -0.039105035, -0.2893635, -0.13024913, -0.058016162, -0.09961072, 0.10532414, 0.24250132, -0.35546342, -0.092634924, 0.093994915) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.18799333, 0.25611782, 0.014645917, -0.063751906, 0.06498416, 0.16619027, -0.14411639, 0.3914421, -0.07343631, -0.116468735, -0.10941946, -0.2553544, -0.37774643, -0.0018441634, 0.06827239, -0.0122299045) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.11884597, -0.2477297, 0.048488285, -0.06438257, -0.124703035, 0.25932777, 0.0650111, -0.0930877, 0.06463341, -0.000544085, 0.0147504965, -0.170097, -0.13241997, 0.20983136, -0.15956205, 0.03424298) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.034574904, 0.06755256, 0.09508443, -0.17162292, 0.046379335, 0.2178781, 0.08699012, -0.055380464, -0.2237568, -0.07427848, -0.028395249, -0.3225617, -0.084454566, -0.24776657, 0.254169, 0.13229847) * go_3(1.0, 1.0);
|
||||
result += vec4(0.18765923, -0.07697714, 0.028134674, -0.060966115);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_7_tf
|
||||
//!WIDTH conv2d_6_tf.w
|
||||
//!HEIGHT conv2d_6_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.21919365, 0.36627784, 0.12603314, 0.24306288, 0.06447028, 0.06472204, -0.05997039, -0.15651788, 0.017059859, -0.006497198, -0.4189735, 0.021636713, -0.23887977, -0.014220949, 0.031113686, -0.17342716) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.10818789, -0.03273837, 0.33918005, -0.19290088, 0.0955361, -0.34107623, -0.054906327, -0.18083344, -0.060723677, 0.24395694, 0.112975016, -0.07254578, -0.14389384, 0.13235968, -0.15054801, -0.26216486) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.23442148, -0.07857079, 0.022283873, -0.2656417, 0.037092753, -0.037313666, -0.5057047, 0.042533103, -0.120424, 0.00021930189, -0.0044566668, -0.45536995, 0.00040759926, 0.14597592, -0.094990164, -0.036161344) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.15024352, 0.19903262, -0.0734784, 0.092836305, -0.025753846, 0.024750374, -0.07550193, 0.035420835, 0.11084378, 0.26119822, -0.08443512, -0.0047807065, -0.042685136, 0.24889739, 0.098650105, 0.2088369) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.25551823, 0.14455976, 0.19886157, -0.23465924, 0.20711218, -0.20875362, -0.11320392, -0.30852005, -0.06795657, 0.008670962, 0.30601278, 0.6929064, 0.17079145, 0.15744895, 0.06441601, 0.06514001) * go_0(0.0, 0.0);
|
||||
result += mat4(0.03142604, -0.006410137, -0.023654792, -0.05708553, 0.062985405, -0.077010594, 0.078804865, 0.050882503, 0.010274228, -0.15558401, 0.09490256, 0.14964707, -0.11966925, -0.36176664, 0.27809814, -0.18862294) * go_0(0.0, 1.0);
|
||||
result += mat4(0.05609992, 0.0041612233, -0.08498908, 0.04479823, -0.080117956, -0.17423204, -0.22858045, 0.054569032, -0.050866384, -0.020000307, 0.027000953, -0.67724514, 0.16240878, -0.04641204, 0.0648367, -0.20613132) * go_0(1.0, -1.0);
|
||||
result += mat4(0.08542306, -0.08254248, -0.11090553, -0.14140448, -0.10788511, -0.13011602, -0.29319742, -0.26007155, 0.11033401, -0.31966573, 0.32668245, 0.19542319, 0.06329418, 0.20904626, 0.2724067, -0.009155685) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.007403411, 0.0012836396, -0.23446666, -0.03017208, 0.062420018, -0.13611084, -0.2975928, 0.13173148, -0.03679939, 0.13743873, -0.10121899, 0.074514665, 0.1497629, -0.09523838, 0.39018926, 0.37807035) * go_0(1.0, 1.0);
|
||||
result += mat4(0.11441487, -0.19565523, -0.25757137, -0.16148767, 0.15575317, -0.12657928, 0.10479676, 0.062919036, 0.010544159, 0.22931573, 0.20360178, 0.4637635, -0.3395036, -0.52467215, 0.08759308, 0.028030418) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.2699195, -0.34218305, 0.15259695, 0.03139074, -0.024053533, -0.029567484, 0.28480124, 0.20525953, 0.15452823, -0.217713, 0.15861876, -0.012275699, 0.21408023, 0.097508304, -0.57126766, -0.14679857) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.0755847, -0.09751562, -0.29480466, -0.22285318, 0.14196442, 0.114573136, -0.22294767, 0.12463806, 0.3322209, -0.04631724, -0.11097061, -0.27986854, -0.16099304, -0.060079545, 0.00299308, 0.120776065) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.050933484, -0.13776319, -0.18809728, 0.24035202, -0.32528606, -0.41684148, -0.029342847, 0.28642926, -0.07963454, -0.12905268, 0.07606093, 0.24670005, -0.08815598, -0.23320907, -0.008099349, 0.21512873) * go_1(0.0, -1.0);
|
||||
result += mat4(0.19247563, 0.18083979, -0.09719762, 0.15314941, -0.22350982, 0.46515045, -0.3571128, 0.35953265, 0.06921985, -0.4482386, -0.18732521, -0.5043983, 0.35159567, -0.33315298, -0.21884166, -0.16283798) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.021124054, -0.007966742, 0.0052493825, 0.022550896, 0.030403977, 0.3377868, -0.47602004, -0.077664234, -0.07222509, -0.07486097, -0.37971064, -0.5107857, -0.06299477, 0.04930232, -0.3330487, 0.29845512) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.063705474, -0.07917637, -0.02026607, -0.05142568, 0.021577014, -0.07379867, 0.033937998, 0.08148773, -0.02717838, -0.03233838, 0.098000035, 0.036476444, -0.13366953, 0.014477577, 0.24064232, 0.39313284) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.16046515, -0.094624564, 0.35435164, 0.09942324, -0.07137174, -0.27999225, 0.124644354, -0.0062176553, 0.015016751, -0.05500243, -0.23249559, -0.4508382, 0.1860433, 0.10671491, -0.033345353, -0.06611453) * go_1(1.0, 0.0);
|
||||
result += mat4(0.21614046, -0.01307525, -0.18941112, -0.20533535, -0.14481686, -0.47801897, 0.22605121, -0.20298961, -0.06744227, -0.20377496, -0.11926173, 0.15645133, -0.31570885, -0.3495616, -0.024666889, 0.040965475) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.11748018, -0.039976366, -0.00084064255, -0.028653437, -0.16216733, -0.036768105, 0.018064514, -0.0928936, 0.14008482, -0.064511225, 0.24329947, -0.0268608, 0.050330248, 0.08540601, -0.07272679, -0.01187671) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.09459936, -0.011723822, -0.06952858, -0.07808506, -0.065588176, 0.332501, -0.0120042395, 0.07668016, 0.14735217, -0.14856043, -0.06702449, -0.020953184, -0.023006834, 0.06135422, 0.1491448, -0.028061569) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.25136968, 0.25146323, -0.108277924, -0.20407207, -0.0013780294, 0.16108194, 0.25143847, 0.06672421, -0.033905584, -0.021144686, -0.019152718, 0.34619498, 0.14560962, 0.034437314, 0.024790365, -0.049976267) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.24928351, 0.12637813, 0.23609994, 0.12722939, -0.036997862, -0.16554876, 0.11144095, -0.10040036, -0.020359103, -0.080701865, -0.3142192, 0.27257237, 0.13546956, -0.14416885, 0.028196262, -0.2886465) * go_2(0.0, -1.0);
|
||||
result += mat4(0.28524777, -0.4236231, 0.27420738, -0.21095508, 0.23475651, 0.115876295, -0.18837357, -0.0260708, 0.030670704, -0.11516913, -0.11365572, -0.2203149, -0.018612983, -0.10719593, -0.031727783, 0.1403327) * go_2(0.0, 0.0);
|
||||
result += mat4(0.07240512, 0.03139215, 0.12328737, -0.021201206, -0.13971715, 0.072742075, -0.0011289873, 0.0053133667, 0.035639685, -0.04322272, -0.19288473, -0.15812221, -0.19126481, 0.0698514, 0.17619178, -0.035605464) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.18552057, 0.07259671, 0.011667668, -0.15630563, 0.11414356, 0.14482655, -0.04021029, 0.18495587, -0.11386139, -0.09058561, -0.011265998, 0.23358451, 0.0521358, 0.12495261, 0.021644838, -0.048094347) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.09222373, 0.0533347, 0.055820454, 0.22382596, 0.18713981, 0.2668916, -0.019384036, 0.012698582, 0.13325234, 0.20361474, -0.33106443, -0.08571572, -0.21243028, -0.10996386, 0.123459645, 0.1534967) * go_2(1.0, 0.0);
|
||||
result += mat4(0.18133277, 0.18108074, -0.05638664, 0.29533157, -0.2108019, -0.033636626, 0.5015888, -0.15116066, -0.041320793, -0.14764231, 0.07314567, -0.18865979, 0.10276937, 0.094240844, -0.1364283, 0.27812913) * go_2(1.0, 1.0);
|
||||
result += mat4(0.06040915, 0.23753685, 0.19019844, 0.23948252, -0.07535012, 0.11848904, 0.14389765, 0.050067905, 0.16150077, -0.030053454, 0.12478255, 0.26020208, 0.111198805, 0.06787492, -0.12771018, 0.006687384) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.5421617, 0.10414128, -0.21526064, -0.08883624, 0.13145073, -0.29695904, 0.57386386, 0.073361695, -0.09538372, 0.27593842, 0.070922814, 0.21769938, 0.06214975, 0.11847816, 0.10033405, 0.29360098) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.16294672, -0.014815565, 0.22046989, 0.16858687, 0.058917344, 0.21384977, 0.18803519, 0.105688855, 0.0355118, 0.20571202, -0.07341922, 0.26624045, -0.0415102, 0.050942056, 0.19727907, 0.20122413) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.020470422, 0.15815964, -0.13437317, -0.1967045, 0.074902646, 0.08356444, 0.055913117, -0.12837863, -0.18647918, 0.07002247, 0.038864706, -0.07288784, 0.04135125, -0.016055549, -0.1340297, -0.15578008) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.07685624, 0.00079105416, -0.068755336, 0.110282525, -0.014170752, 0.041282844, -0.17035173, 0.19439398, -0.3036256, 0.024148455, -0.19566648, -0.06736254, 0.14203559, -0.13016985, -0.32845357, -0.14266774) * go_3(0.0, 0.0);
|
||||
result += mat4(0.0087252045, 0.098839566, -0.08770506, -0.08499465, 0.015245115, -0.110854514, 0.054458305, -0.018121868, -0.09666134, -0.08316006, 0.24617113, -0.17195955, 0.2574254, 0.06734342, -0.13792352, -0.07306126) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.0073954533, -0.20126835, -0.22545357, -0.29462856, 0.057408337, 0.11939119, -0.01846476, 0.12534486, 0.15751605, -0.14282645, -0.14219986, 0.14283386, 0.14090413, 0.10500912, 0.03039335, 0.17448832) * go_3(1.0, -1.0);
|
||||
result += mat4(0.043910783, -0.09140025, -0.21666165, 0.07616939, 0.104454786, 0.309926, -0.12906921, 0.1140117, 0.09372434, 0.049547072, -0.086615674, -0.034449168, 0.096705064, 0.26001686, 0.027063297, 0.12422948) * go_3(1.0, 0.0);
|
||||
result += mat4(0.1365422, 0.2679611, 0.12037257, 0.43346113, 0.08223084, -0.016788265, 0.13570398, -0.017974345, -0.17922844, -0.09475725, 0.073539585, -0.106947675, 0.08998511, 0.04133868, 0.16586913, -0.26291734) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.19233678, 0.016725872, -0.008011114, -0.1977463);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_7_tf1
|
||||
//!WIDTH conv2d_6_tf.w
|
||||
//!HEIGHT conv2d_6_tf.h
|
||||
//!COMPONENTS 4
|
||||
#define go_0(x_off, y_off) (max((conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_6_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_6_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.36016628, 0.019064043, 0.3073228, 0.16891135, 0.026739368, 0.31136194, 0.11260383, -0.26918694, 0.0419928, -0.3365078, 0.20189743, -0.04136312, 0.039564647, 0.033199426, 0.18768296, -0.017119858) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.28663483, -0.41716507, 0.059281543, 0.043736435, 0.0028875466, 0.13817391, -0.12543318, -0.2794053, -0.023528943, 0.10610115, 0.09100278, 0.040132936, -0.21949205, -0.027810011, -0.0301218, 0.084047124) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.39674807, -0.0040878756, -0.038235947, 0.11880838, 0.009898328, 0.19107847, -0.009313831, -0.1554276, -0.047341663, 0.18049581, -0.029317195, 0.0708909, 0.0708316, -0.110617444, 0.14584038, -0.022261223) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.20400241, 0.0896492, -0.010386381, -0.052133385, 0.005023956, -0.06628705, -0.16436209, -0.25345984, -0.05285192, 0.09706557, -0.03778914, -0.152546, 0.17023252, 0.063713826, 0.00743037, 0.056634087) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.080793336, 0.4204207, 0.19098237, 0.20028038, -0.054076545, 0.22064368, -0.25853387, -0.3643562, 0.2085573, -0.023731, -0.06727709, -0.18683033, -0.18032159, -0.06388348, 0.304463, -0.2517781) * go_0(0.0, 0.0);
|
||||
result += mat4(0.11940941, 0.10624008, 0.16120581, 0.2369602, 0.3321827, 0.4272075, -0.10403669, -0.31388018, -0.006372124, -0.00653671, 0.109810196, 0.2277172, 0.005771998, 0.086026914, -0.08934813, -0.094941735) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.13233568, 0.24112508, -0.0068006413, 0.12466225, 0.11396591, -0.07249253, -0.29090378, -0.12828146, -0.22001141, -0.08532405, -0.11932601, 0.29452974, 0.09572195, 0.017603843, 0.12454017, 0.16321751) * go_0(1.0, -1.0);
|
||||
result += mat4(0.042107448, -0.00807216, 0.06580674, -0.1289527, 0.13977426, -0.037159685, -0.21001346, -0.08698161, 0.22370502, -0.29170328, 0.2179206, 0.36621302, 0.0825477, -0.016513655, -0.11157249, 0.12861598) * go_0(1.0, 0.0);
|
||||
result += mat4(0.2246826, -0.13262233, 0.12131653, -0.15522355, 0.38104856, 0.030237729, 0.1286289, -0.19770473, -0.16175011, -0.13688888, 0.23505463, 0.21333031, 0.76352316, -0.17949077, -0.13124311, 0.1613879) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.050607495, 0.0846705, -0.06136092, -0.033436477, 0.41138348, 0.037043408, -0.02676336, -0.37771952, 0.22147503, 0.06490757, -0.04266158, -0.22606373, 0.045775007, -0.054498192, -0.21495876, -0.036050417) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.06242522, 0.2700824, -0.05602621, -0.12361551, 0.14477442, 0.19403581, 0.23505251, -0.072234035, -0.15831544, 0.4640447, -0.104754634, -0.004539681, -0.20246096, 0.23216484, -0.35886365, 0.11360777) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.14777757, 0.18951412, 0.027219458, 0.11216015, 0.02997997, -0.13466355, -0.0010830094, 0.021302953, 0.23441231, -0.14529245, 0.08068729, 0.10044398, 0.3972878, 0.26570204, 0.0046810666, -0.2863261) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.10385485, 0.1053724, 0.16961229, 0.20727012, -0.025148917, -0.011365095, 0.03899919, -0.030950211, 0.079080455, -0.32767853, 0.064670205, -0.035771385, 0.16833797, -0.21567492, 0.30871257, -0.19965471) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.23420888, -0.004894698, -0.18162623, -0.31107524, 0.11976508, 0.14924951, -0.08723316, 0.21401922, -0.58200324, -0.01177345, -0.049033508, 0.19593577, -0.21139073, 0.13016601, 0.08734843, 0.4158892) * go_1(0.0, 0.0);
|
||||
result += mat4(0.0009789813, 0.33274913, 0.017405733, -0.042906318, -0.26410276, -0.09291333, 0.019387102, 0.105381854, -0.009176527, 0.09483514, -0.28462934, -0.03644404, 0.285194, -0.4260311, 0.14902237, -0.115670316) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.09344311, 0.4463103, 0.19984834, -0.09733857, -0.118717775, -0.0708026, 0.24919955, -0.11234634, 0.1246395, -0.052909933, 0.1525815, 0.07724016, 0.0070534665, -0.06404165, -0.18149726, -0.014058336) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.17353044, 0.15376104, 0.004588994, -0.13554202, -0.19920237, -0.18918681, 0.11327512, -0.117296435, -0.0785251, 0.013677155, -0.2103214, 0.06843426, -0.27790928, 0.09837545, -0.00019213746, 0.09132539) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.01586651, 0.014929441, 0.2426186, -0.1889374, -0.0865462, -0.07454513, -0.20797268, -0.22366855, 0.19704159, 0.0048206006, -0.16707218, -0.14162683, 0.036798395, -0.1663155, -0.12009389, 0.09603803) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.041532192, 0.05753804, 0.17927068, -0.042112097, 0.12080969, -0.15052572, -0.34855765, -0.07356988, -0.28199884, -0.18958664, 0.15879883, 0.08511588, 0.0034213227, -0.05338495, -0.37285298, 0.06626709) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.20219134, 0.22150375, -0.29405454, 0.06597703, -0.018885285, -0.010551704, -0.010774283, 0.08758955, -0.2015349, -0.17006227, -0.24321876, -0.06864207, -0.118437864, -0.043977212, -0.029736811, 0.14040919) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.18709077, -0.09723938, 0.12783436, -0.15167634, 0.29039705, -0.11009911, 0.018371418, -0.060096707, -0.07256923, -0.25799567, -0.06276934, -0.035992302, -0.06729111, -0.059956793, -0.024079734, 0.011838878) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.010449175, -0.08212451, 0.1409803, 0.11861122, -0.18035835, 0.051930565, 0.01049551, -0.09447962, 0.12029649, 0.040604513, -0.059971705, -0.0044667358, -0.22080486, -0.11187681, 0.124374695, -0.004155485) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.28584236, -0.38480133, -0.13987814, -0.4463469, -0.3890419, -0.022498172, 0.17334452, 0.21895568, -0.15450422, -0.10905497, 0.15111905, -0.22554915, 0.106121585, -0.029144369, 0.36059046, 0.22140682) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.23780307, -0.023033705, 0.068205886, -0.110635854, -0.26720005, -0.1608183, 0.19523881, 0.07972837, -0.018495852, -0.2793956, 0.17668398, -0.12020479, -0.079556085, -0.02284952, 0.031480275, 0.31818348) * go_2(0.0, 1.0);
|
||||
result += mat4(0.22501226, -0.00829407, 0.059581667, 0.16512989, 0.18711442, 0.1200968, 0.11812652, -0.16091056, 0.15733972, 0.045156084, 0.20640492, -0.16852027, -0.11217177, 0.06746273, -0.050218176, 0.08643783) * go_2(1.0, -1.0);
|
||||
result += mat4(0.20715691, -0.1082907, 0.027892975, 0.19515261, -0.17838904, 0.1532257, -0.108409844, -0.06632365, -0.13805026, 0.23020233, 0.12416581, -0.14861803, 0.16650471, 0.08158386, -0.09051303, -0.06981649) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.04617126, 0.06579221, 0.25964734, 0.28500968, 0.07641255, -0.090885855, -0.0972522, 0.18298368, -0.06393334, 0.103463, -0.23062052, -0.15270731, 0.13633437, 0.074707486, 0.15065335, -0.024602572) * go_2(1.0, 1.0);
|
||||
result += mat4(0.118319295, 0.010410938, 0.044655934, -0.104725905, 0.030477569, 0.12867387, 0.039075315, 0.18922117, 0.13301082, -0.1601557, 0.038168408, -0.07372259, -0.09522213, -0.095107146, -0.16679631, 0.044673234) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.46229, -0.30780822, -0.09081465, 0.1433387, -0.0315039, 0.059409115, -0.24948491, -0.17146957, 0.060843736, -0.041989822, 0.054005735, 0.22835566, 0.12036598, -0.0070898845, 0.17276852, -0.17754094) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.35119572, 0.020034311, 0.08751943, 0.08193488, 0.041884877, 0.22649358, -0.07447533, 0.20845473, -0.04859846, -0.16206735, 0.06819576, -0.053000778, 0.18146423, 0.04694148, 0.045293212, 0.06783575) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.280914, -0.14998704, -0.23485807, -0.015608296, 0.1549556, -0.11992663, -0.094974115, 0.05887284, 0.053392075, 0.10322464, -0.075066686, 0.068358354, -0.18663338, 0.009901499, -0.123370335, -0.12502703) * go_3(0.0, -1.0);
|
||||
result += mat4(0.7748568, -0.17870626, -0.20770052, 0.024692526, -0.056430295, -0.06324113, -0.03660047, 0.29629672, -0.51896983, -0.027231261, 0.05903762, 0.077677645, -0.061675485, -0.20277846, 0.10352223, -0.08198446) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.06347568, 0.21643166, -0.09718546, 0.0372257, -0.029537952, -0.0357135, -0.09548363, 0.18225233, -0.29609334, -0.3496132, 0.18245913, -0.10162589, -0.18189451, -0.09077887, 0.117313184, -0.06863874) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.047373574, -0.020289376, -0.25748715, -0.13568166, 0.15656634, -0.06841899, 0.012100781, -0.13611819, 0.0016357322, -0.23870537, 0.14035743, -0.14700134, 0.2535575, -0.13697346, -0.13693139, -0.10365287) * go_3(1.0, -1.0);
|
||||
result += mat4(0.4283934, -0.316192, -0.012617617, 0.018468965, 0.21436644, 0.18408814, -0.42651537, 0.12504087, -0.13894933, 0.091662176, -0.20096369, -0.080727175, -0.005487846, 0.17046383, 0.1383948, -0.0054956395) * go_3(1.0, 0.0);
|
||||
result += mat4(0.20014295, -0.027282396, -0.06317007, 0.04452042, 0.064600386, 0.072222926, -0.33409226, 0.08063831, -0.022607977, 0.1308856, -0.39691743, -0.094889864, -0.1810531, 0.011367248, -0.2531222, -0.22468317) * go_3(1.0, 1.0);
|
||||
result += vec4(0.26886886, 0.05874665, 0.10268232, 0.05833081);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v4.0-Restore-CNN-(VL)-Conv-3x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!BIND conv2d_7_tf
|
||||
//!BIND conv2d_7_tf1
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
#define g_0 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_7_tf_tex(conv2d_7_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_7_tf1_tex(conv2d_7_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_7_tf_tex(conv2d_7_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_7_tf1_tex(conv2d_7_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.09689336, 0.06046458, 0.072598994, 0.0, 0.11994565, 0.104477674, 0.09302802, 0.0, -0.05718302, 0.050438102, 0.08814741, 0.0, 0.0308889, 0.0033925986, -0.01715605, 0.0) * g_0;
|
||||
result += mat4(-0.028314235, 0.06597744, 0.0966897, 0.0, 0.035656154, 0.07770106, 0.075551905, 0.0, 0.0001793458, -0.000479495, -0.00297406, 0.0, -0.053916585, -0.016807461, -0.0057141334, 0.0) * g_1;
|
||||
result += mat4(-0.047189303, -0.0207, -0.020910334, 0.0, -0.07933196, -0.06961211, -0.086069845, 0.0, 0.0943727, 0.008463375, 0.010755166, 0.0, 0.062410597, 0.022625161, 0.04068433, 0.0) * g_2;
|
||||
result += mat4(0.10270994, -0.019080428, 0.0050091282, 0.0, -0.004672948, -0.013966742, -0.0063746064, 0.0, -2.5856789e-05, 0.03151499, -0.0023983798, 0.0, 0.113539025, 0.12381699, 0.100360274, 0.0) * g_3;
|
||||
result += mat4(0.07868885, -0.030913834, -0.009213676, 0.0, 0.04870991, 0.021467991, 0.038739506, 0.0, -0.042969644, -0.07122453, -0.08798675, 0.0, -0.09784122, 0.021434791, 0.02510374, 0.0) * g_4;
|
||||
result += mat4(0.050420716, 0.0729716, 0.076532185, 0.0, -0.019112485, -0.01037939, -0.026948035, 0.0, -0.02591423, 0.008927897, -0.00042541025, 0.0, 0.1043701, -0.0071186824, -0.041817162, 0.0) * g_5;
|
||||
result += mat4(-0.16143242, -0.0009298223, -0.01228508, 0.0, 0.07744052, -0.018313263, -0.0488145, 0.0, 0.09241393, 0.07128674, 0.055164956, 0.0, 0.054884013, -0.04834418, -0.06281626, 0.0) * g_6;
|
||||
result += mat4(-0.049036566, -0.05979936, -0.05594288, 0.0, -0.014564307, 0.031926468, 0.037857566, 0.0, 0.015474487, -0.11385003, -0.11527764, 0.0, -0.07076006, 0.057038613, 0.095983796, 0.0) * g_7;
|
||||
result += mat4(0.03094887, -0.008734403, 0.00042712069, 0.0, 0.053891554, 0.05837673, 0.06200635, 0.0, 0.09071558, -0.04202184, -0.046172567, 0.0, -0.0425916, 0.04905093, 0.020835675, 0.0) * g_8;
|
||||
result += mat4(0.096628904, -0.037792254, -0.043241944, 0.0, -0.011923947, -0.025950424, -0.031381752, 0.0, -0.060941868, -0.07859433, -0.07535451, 0.0, -0.026777223, 0.08604982, 0.07829908, 0.0) * g_9;
|
||||
result += mat4(-0.06435972, 0.0036599538, 0.00786578, 0.0, -0.061972067, -0.05681472, -0.06667608, 0.0, -0.106890626, 0.007406496, 0.029977169, 0.0, -0.20519382, -0.044860814, 0.0021225857, 0.0) * g_10;
|
||||
result += mat4(-0.16876474, 0.012789643, 0.026692612, 0.0, 0.017817136, 0.026935097, 0.02227043, 0.0, 0.01690181, 0.07716103, 0.086527, 0.0, 0.07923805, -0.10443151, -0.10859543, 0.0) * g_11;
|
||||
result += mat4(0.003730466, -0.024648283, -0.022169832, 0.0, -0.0062762927, 0.022062732, 0.032966793, 0.0, 0.016349113, 0.017197203, 0.020952817, 0.0, -0.1763789, 0.035497356, 0.053835396, 0.0) * g_12;
|
||||
result += mat4(0.020886675, -0.07054202, -0.079142675, 0.0, 0.06664387, 0.044960167, 0.042230908, 0.0, -0.095019594, 0.012421141, 0.0142890485, 0.0, 0.056814816, -0.012751135, -0.014684506, 0.0) * g_13;
|
||||
result += mat4(0.011765893, 0.0008920681, -0.0018258415, 0.0, -0.010473814, -0.023085753, -0.028783914, 0.0, -0.023034256, -0.0024786016, -0.0052162083, 0.0, 0.1643386, -0.06132718, -0.09289065, 0.0) * g_14;
|
||||
result += mat4(0.016597198, 0.09389637, 0.10833379, 0.0, -0.043163072, -0.04714812, -0.035274632, 0.0, 0.09634976, -0.009292612, -0.022424143, 0.0, -0.08765172, 0.0051558353, 0.010900356, 0.0) * g_15;
|
||||
result += mat4(0.030815786, 0.021069322, 0.01812191, 0.0, 0.084839165, -0.0080813095, -0.029270556, 0.0, -0.10456346, 0.062386703, 0.0665605, 0.0, 0.11926609, -0.1104228, -0.13291118, 0.0) * g_16;
|
||||
result += mat4(-0.07159541, -0.007267032, -0.010134558, 0.0, 0.008234213, 0.045609634, 0.040295456, 0.0, 0.018416971, 0.01308482, 0.014649557, 0.0, 0.035107512, -0.02140815, -0.030279048, 0.0) * g_17;
|
||||
result += mat4(0.01918586, 0.03875863, 0.03229402, 0.0, -0.07917104, 0.041135103, 0.057182517, 0.0, 0.08609541, 0.0079662455, 0.004327576, 0.0, -0.14332893, 0.03120354, 0.056732506, 0.0) * g_18;
|
||||
result += mat4(0.03200192, -0.0035752193, -0.0031064528, 0.0, -0.010902813, 0.014607456, 0.019431474, 0.0, -0.016461229, -0.004938204, -0.004655488, 0.0, -0.033470232, 0.0026075812, 0.005896968, 0.0) * g_19;
|
||||
result += mat4(0.037410006, 0.048742272, 0.04348088, 0.0, 0.037719514, 0.030768529, 0.03127472, 0.0, 0.056426726, 0.03066893, 0.016440205, 0.0, -0.010599352, 0.022832409, 0.023211194, 0.0) * g_20;
|
||||
result += mat4(-0.005733291, 0.06365659, 0.06663611, 0.0, -0.041917093, -0.016493445, -0.020438088, 0.0, -0.0014357592, -0.0022506563, -0.0045095007, 0.0, 0.029893145, -0.009129354, -0.015173116, 0.0) * g_21;
|
||||
result += mat4(0.013052085, 0.005108175, 0.0025906067, 0.0, -0.021950055, -0.036447693, -0.036141638, 0.0, -0.036296472, 0.0068928464, 0.013102313, 0.0, 0.0060471976, -0.024798103, -0.023548538, 0.0) * g_22;
|
||||
result += mat4(0.0067743887, -0.06191211, -0.062355213, 0.0, 0.0016080744, -0.020445071, -0.016840393, 0.0, 0.028264903, 0.01852915, 0.015891539, 0.0, -0.023877412, -0.013271666, -0.008158679, 0.0) * g_23;
|
||||
result += mat4(-0.04317466, -0.018953001, -0.020452993, 0.0, -0.009322576, -0.03022352, -0.030970376, 0.0, 0.05653658, 0.05430553, 0.046692245, 0.0, 0.05615359, 0.059338935, 0.056018773, 0.0) * g_24;
|
||||
result += mat4(0.022878079, 0.03392234, 0.033057988, 0.0, -0.017554542, -0.0141542535, -0.014122613, 0.0, -0.048634093, -0.05316463, -0.047988772, 0.0, -0.058002178, -0.040221967, -0.034025013, 0.0) * g_25;
|
||||
result += mat4(-0.018253656, -0.04197674, -0.040467236, 0.0, -0.04358929, -0.028309818, -0.025425073, 0.0, -0.008488672, -0.001727991, 0.00035808363, 0.0, -0.0011709273, 0.0052514165, 0.0059479307, 0.0) * g_26;
|
||||
result += mat4(-0.08333935, -0.09818201, -0.09476284, 0.0, -0.033692095, -0.046259012, -0.045797516, 0.0, -0.007577072, 0.0022402718, 0.0016200038, 0.0, 0.0029786075, -0.020728534, -0.018938033, 0.0) * g_27;
|
||||
result += vec4(0.047567394, -0.02504617, -0.028163986, 0.0);
|
||||
return result + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.010995803, 0.077095956, -0.043992598, 0.06048717, 0.1164834, -0.11689607, 0.072985925, -0.078805886, 0.01182932, 0.054985743, -0.09018186, 0.044907484, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.1813623, -0.14752422, 0.025720436, -0.17639883, 0.15697388, 0.10445984, -0.1843076, 0.5264643, 0.047516696, -0.097305484, 0.09740847, -0.29619336, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.014534763, 0.09486465, 0.046173926, 0.039391946, 0.09609376, -0.060574662, 0.042200956, -0.3269777, 0.051006425, 0.059818447, 0.04366627, 0.17699827, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.04268535, -0.08152529, 0.10577459, -0.036936995, -0.051562306, 0.054872766, 0.09194519, 0.0025066638, -0.01073954, 0.00064474024, 0.10038221, 0.02131141, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.51751363, -0.40028602, 0.3469574, 0.5933738, -0.91357684, -0.67692596, 0.57815677, 0.39809322, -0.16341521, -0.27169713, 0.12232366, 0.4318641, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.12601124, -0.06263236, -0.45907676, -0.41514075, 0.3330334, -0.1929565, -0.6333532, -0.6552794, -0.045809917, 0.046351526, -0.26173338, -0.30252662, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.0030332592, 0.012103107, 0.010537323, -0.02038607, 0.095558085, 0.097704545, 0.083433494, 0.026790185, 0.01943357, -0.061712462, -0.00015703632, -0.032268334, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.016870102, 0.5215812, -0.11525501, 0.027527615, -0.09045733, 0.61310345, -0.1575268, 0.1905386, 0.020172214, 0.3503187, -0.08209157, -0.051328037, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(0.005494087, -0.010656317, 0.07682753, -0.08116042, -0.03934524, 0.16589017, 0.101483546, -0.066603065, 0.03494657, -0.07885597, 0.074227594, 0.0016264897, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(0.014463938, -0.0031906287, 0.007015422, -0.003888468);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.08532478, -0.14302494, -0.017921071, -0.0032664281, -0.09841952, 0.024187077, 0.10701477, 0.14110753, -0.05714981, -0.10897174, 0.073803626, 0.103992954, 0.07914382, 0.032193683, -0.18346278, -0.09723936) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.034482613, -0.10742312, -0.047286414, -0.08641124, -0.33896688, -0.036533825, -0.48337597, 0.034040943, -0.13598205, -0.080917805, 0.08540263, -0.012667689, -0.009171425, -0.120026454, -0.20536867, -0.032149274) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.18687321, 0.066278316, 0.024327392, 0.08816582, -0.08017908, 0.09488853, 0.26018232, -0.101504356, 0.17487666, 0.31057635, 0.14785016, -0.09622089, -0.07537452, -0.13844088, -0.05810814, 0.09907489) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.04183032, 0.15207712, 0.005002397, 0.32277516, -0.16169126, -0.119836345, -0.04068436, -0.096728764, 0.11943901, 0.1789597, -0.20412198, 0.19009817, 0.36630696, 0.06946421, -0.5254373, -0.11896399) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.31916487, -0.98911583, 1.0728644, -0.39280394, 0.33458877, -0.17325239, -0.645045, -0.28524077, -0.14512783, 0.24996442, -0.09837877, 0.05468934, 0.31559715, -0.020504637, -0.026724018, 0.24507573) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.23759829, -0.08530173, -0.16665787, -0.22463752, 0.109896734, 0.13446991, -0.049552456, -0.02385489, -0.01245375, 0.3833208, 0.05758832, 0.1528937, 0.0501858, -0.19651426, 0.0076587177, -0.03297025) * go_0(0.0, 1.0);
|
||||
result += mat4(0.14554465, -0.01826686, 0.10284085, -0.19152659, -0.017585073, -0.05511482, 0.06362406, 0.023924058, -0.0018977845, -0.103172876, 0.03287086, -0.20085956, 0.36062446, 0.10749464, -0.20984372, 0.018256644) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.005534592, 0.3709197, -0.18287498, 0.1720451, 0.030155553, -0.023265475, 0.0058617783, -0.031765483, 0.037328955, -0.2730994, 0.35090837, -0.3269043, -0.028477207, 0.32756507, -0.15989502, 0.12158258) * go_0(1.0, 0.0);
|
||||
result += mat4(0.10873739, 0.19583772, 0.060394943, 0.09410379, -0.04739245, 0.026561242, 0.022990001, 0.1093272, -0.01071349, -0.022938967, -0.046423864, 0.2385325, -0.0319821, 0.046962265, 0.09081178, -0.11001857) * go_0(1.0, 1.0);
|
||||
result += mat4(0.13012704, 0.112289295, 0.030790284, -0.050499484, 0.11784853, 0.08107028, -0.07556717, -0.15643, 0.015249331, 0.015299608, 0.07748125, 0.054485757, 0.044857923, 0.12161275, -0.048292994, -0.033995003) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.12931514, 0.15114146, 0.070513315, 0.11246343, 0.4142387, 0.213479, -0.5439916, 0.07776645, 0.13109331, 0.2021147, 0.25932786, -0.22157331, 0.02377734, -0.014970623, -0.1943276, 0.18440372) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.22365458, -0.19829084, -0.06881161, -0.06468993, 0.17202774, 0.0048758537, -0.09235021, 0.18941896, 0.064125344, -0.09067088, 0.09748182, 0.13561936, -0.05876288, -0.0122420965, -0.054380875, -0.17743628) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.18582906, -0.09263032, -0.08210888, -0.20515606, 0.11484005, 0.08557595, 0.0009253741, -0.051202174, -0.18535301, -0.1529345, -0.13092944, 0.03770747, -0.020947013, 0.19187425, -0.15494856, -0.048979875) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.38131633, 0.4278787, 0.19763695, 0.27655518, -0.08711912, 0.07374453, -0.064803004, 0.5983854, 0.2361923, -0.057221692, -0.37138999, -0.24259573, 0.13890724, 0.25706333, -0.54021406, 0.08095518) * go_1(0.0, 0.0);
|
||||
result += mat4(0.0991328, -0.022651536, -0.029148921, -0.009812537, -0.09523686, -0.15704902, 0.052389514, 0.21561539, 0.1950314, -0.08572602, 0.0016523858, 0.14125621, -0.030999828, 0.12009709, 0.0373512, -0.105043754) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.11251988, 0.12106985, 0.011923068, 0.3662747, 0.004800994, 0.017972551, 0.004761366, -0.07934206, -0.13755941, -0.022852683, 0.1502225, 0.009758547, -0.16964264, 0.00984782, 0.07855833, 0.035730787) * go_1(1.0, -1.0);
|
||||
result += mat4(0.01964957, -0.27226487, 0.033933397, -0.117632054, -0.009058229, 0.047830686, -0.01125145, 0.136628, 0.0056388285, 0.3028781, -0.12286517, 0.23498532, -0.009319075, -0.444048, 0.16174883, -0.06367683) * go_1(1.0, 0.0);
|
||||
result += mat4(0.02343933, -0.010915871, -0.058680378, -0.21886891, -0.010750894, -0.06671997, 0.0602906, -0.07903071, 0.066891186, 0.06650588, 0.14362891, -0.101870626, 0.02264628, -0.06940821, -0.077616625, 0.110911585) * go_1(1.0, 1.0);
|
||||
result += vec4(0.032014452, -0.020821465, 0.0826416, -0.002838458);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.06963679, -0.07560548, -0.069522075, 0.0038078027, -0.08002613, 0.13671301, 0.084461786, -0.039376218, 0.19136548, -0.123174496, 0.26566333, -0.16583005, -0.18664864, -0.023539122, -0.21928434, -0.026818147) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.16660932, -0.18558703, 0.37230486, 0.118128106, -0.14098641, 0.14659132, -0.22217897, 0.12952235, -0.4139033, -0.04308319, 0.12885277, -0.17986743, -0.23556231, -0.08351981, -0.43240538, 0.019033253) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.18008037, -0.04448665, 0.011906908, -0.023056917, 0.18136618, -0.04723555, -0.0050158803, -0.14823224, -0.2105281, 0.023047728, -0.14040631, -0.03178526, -0.13477588, -0.01820428, 0.058358394, 0.23792502) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.07363309, -0.061728477, 0.03573137, -0.0050971056, -0.012813505, -0.17236637, 0.1697835, 0.055788577, -0.22263195, 0.10324512, 0.58971673, -0.4872246, -0.1555681, 0.032747746, -0.096495196, 0.070196226) * go_0(0.0, -1.0);
|
||||
result += mat4(0.14174286, 0.099460006, -0.088765986, 0.58350676, -0.025177564, -0.46004987, 0.37007022, -0.11437029, -0.5164534, -0.60465246, 0.38859612, -0.32846406, 0.050266482, -0.20334712, 0.18316261, -0.19327633) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.09377763, -0.0012762006, -0.028991895, -0.26523829, 0.20173682, 0.037923716, -0.03174243, 0.07103378, -0.10764164, -0.30752546, 0.20556998, -0.1892279, 0.08115748, -0.023550175, -0.07627362, 0.11746628) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.06998859, -0.017997518, 0.069938794, -0.14943017, -0.14179112, 0.16643842, -0.110231474, 0.08895815, -0.24074875, 0.3277253, -0.07435203, -0.23452802, 0.039962552, -0.07145652, -0.022511544, -0.04571222) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.059785757, -0.23771374, -0.030571314, 0.25222278, 0.106601834, 0.34398326, 0.14511436, -0.03867526, -0.38982397, -0.11944689, 0.12997924, -0.13079585, 0.005729482, 0.012653905, -0.063693404, 0.09632285) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.04933823, 0.0547175, 0.050636575, -0.10060694, 0.1344485, 0.19752938, -0.100068115, -0.028829506, -0.14096203, -0.079092234, 0.092109434, 0.011606209, -0.04052607, -0.008347507, 0.06956573, -0.028109524) * go_0(1.0, 1.0);
|
||||
result += mat4(0.21918017, -0.11115073, 0.2262453, -0.06889667, -0.11256312, -0.07438075, -0.088454485, 0.13672407, -0.06905764, 0.08128395, 0.016103368, 0.050190717, 0.09691516, 0.05845721, 0.4886816, 0.041121427) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.3449472, 0.09711974, -0.13881907, -0.018265123, 0.27855873, -0.07030004, 0.29545054, 0.37216932, 0.08657718, 0.099066615, -0.10574013, -0.17667885, -0.14855732, -0.11351448, 0.66945946, 0.11312157) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.2526151, -0.04594331, -0.06606611, 0.09104881, 0.06857995, -0.075284235, -0.17664689, 0.21578754, 0.0696524, 0.09142951, 0.080997564, -0.0682772, -0.0011445724, -0.11736295, 0.2519232, -0.101926275) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.12913518, 0.058357026, 0.195421, -0.15651494, 0.2877076, 0.0033844314, -0.07831594, 0.052855384, -0.031295884, 0.03301088, -0.18408822, 0.06732994, 0.23742151, -0.12568143, 0.22810535, -0.11545694) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.49203303, -0.22656603, 0.1723193, -0.51250046, -0.09742038, 0.758559, -0.3387505, -0.6193586, 0.14136684, 0.27679884, -0.050113205, 0.31041816, -0.36475047, -0.48746544, 0.3233227, 0.4579754) * go_1(0.0, 0.0);
|
||||
result += mat4(0.46636763, 0.1507748, -0.2581362, 0.15413165, -0.17160143, 0.14256273, -0.074575804, -0.099299066, -0.0017214464, 0.13778336, -0.07378213, -0.15489665, -0.10533715, -0.0011083825, 0.39584312, 0.0023906573) * go_1(0.0, 1.0);
|
||||
result += mat4(0.026959421, -0.06391859, 0.0034752619, 0.14521928, -0.0010877338, -0.032619733, 0.005375293, -0.018952755, 0.03381545, -0.007652831, 0.034141563, 0.046016496, 0.11219674, 0.030913852, 0.077403754, 0.17192438) * go_1(1.0, -1.0);
|
||||
result += mat4(0.040326044, 0.17290725, -0.1220239, -0.09594783, -0.025229257, 0.17913155, -0.26623353, -0.033396784, -0.03075146, 0.009143897, -0.0136083895, -0.13886899, 0.075683735, -0.11584183, 0.22182357, 0.19350322) * go_1(1.0, 0.0);
|
||||
result += mat4(0.15726025, -0.10215694, -0.060057458, 0.26487043, -0.04075552, -0.016496127, 0.0015382086, 0.108562306, 0.026795091, 0.0441233, -0.08754318, -0.0460157, 0.048422016, 0.14107347, 0.07986661, 0.1047697) * go_1(1.0, 1.0);
|
||||
result += vec4(0.0766796, 0.08115133, -0.05703058, 0.14025708);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.18038331, 0.21830973, -0.10019419, -0.022745568, -0.14944611, -0.15669158, 0.46361133, -0.07289843, 0.02976627, -0.09000817, 0.113060996, 0.05635241, 0.012762965, -0.022688959, 0.01629751, 0.061114635) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.024338024, -0.10004009, -0.13709056, -0.0851965, 0.23927099, -0.024349794, -0.16574804, 0.084686354, -0.047885604, 0.09688507, -0.12733915, 0.06980246, 0.11480734, 0.014669346, -0.07505829, 0.04676309) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.054203495, 0.011881634, -0.036115017, -0.0686298, -0.13682245, -0.15678032, 0.057050128, -0.03368558, 0.13011025, 0.033391044, -0.09841339, -0.027057761, -0.18701133, 0.20852546, -0.13660902, 0.0005817616) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.08077834, 0.35952288, -0.07647382, -0.0033230998, 0.13929126, -0.09155619, 0.14128102, 0.16005981, 0.18161216, -0.09485738, 0.0029118075, 0.052682754, 0.03242074, 0.08299826, 0.073796146, -0.06446532) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.36655015, 0.4606936, 0.19073649, 0.31655258, -0.006838053, -0.579939, 0.089126326, -0.14021218, -0.3437716, 0.16714323, 0.17705944, -0.22418492, -0.3883696, -0.2302651, 0.2581861, 0.21983066) * go_0(0.0, 0.0);
|
||||
result += mat4(0.0992383, -0.014257871, -0.023896435, 0.19868234, 0.0408007, 0.07995299, 0.16102871, -0.11668251, 0.22458278, -0.05587917, 0.19373615, -0.016202094, -0.25106144, 0.15634494, 0.11624891, -0.2930768) * go_0(0.0, 1.0);
|
||||
result += mat4(0.024616942, 0.36248252, -0.14779098, -0.019894283, -0.007111256, 0.010641561, -0.09541178, 0.21236233, 0.009501827, 0.08132797, -0.13983901, 0.027207611, 0.038444366, -0.013995817, -0.16242191, 0.03294123) * go_0(1.0, -1.0);
|
||||
result += mat4(0.0131698875, -0.18124102, -0.13503514, -0.06099072, 0.07422735, -0.20906176, -0.049005672, 0.08739405, -0.031758767, -0.1978915, 0.23094437, 0.54512614, 0.21338555, -0.011205669, -0.23727885, -0.29533875) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.0010255767, -0.07168225, -0.033568826, 0.22161655, -0.087293416, 0.11350447, 0.13653576, 0.061226424, -0.13074352, 0.058425818, 0.038460605, 0.2749964, -0.012814839, 0.085885845, -0.038151987, -0.17960808) * go_0(1.0, 1.0);
|
||||
result += mat4(0.19728905, -0.040724937, -0.18270236, 0.046735186, 0.03507326, 0.119867206, -0.12691991, 0.18119748, -0.052895024, 0.11348764, -0.043787055, 0.004703516, 0.006752757, -0.06939761, -0.009801806, -0.075640485) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.051735226, 0.1732299, -0.10672899, 0.0320877, -0.4913656, 0.2102274, 0.43920282, 0.059108034, 0.08349019, -0.16517872, 0.15436842, -0.1075667, 0.022741623, -0.26693836, 0.3645307, 0.017874828) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.034464058, 0.014929155, 0.054227423, 0.14167373, -0.0023630706, -0.08904212, 0.11918041, -0.034539603, 0.06048089, -0.06807333, 0.14447778, 0.035260547, 0.09979546, -0.1924939, 0.14596114, -0.12069667) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.04427228, -0.23673469, 0.010357103, -0.2907043, -0.06845721, -0.078984015, 0.06867713, -0.058163825, -0.12154615, 0.08430951, 0.1922373, 0.030108064, -0.43081748, -0.38715646, -0.022240646, -0.15403675) * go_1(0.0, -1.0);
|
||||
result += mat4(0.46885306, -0.33421394, -0.6695223, -0.41841158, 0.30317923, 0.24244753, -0.1047785, -0.18656285, 0.06261881, -0.4405616, 0.24233986, 0.40070608, 0.81440526, 0.11305212, -0.8826317, -0.023478031) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.07879348, -0.024378026, -0.041883785, -0.17030984, 0.23229122, -0.011237109, 0.12058088, 0.20766267, -0.36519575, 0.09599417, -0.1271098, 0.06990154, 0.21161246, 0.041002538, -0.36046275, 0.007304667) * go_1(0.0, 1.0);
|
||||
result += mat4(0.10873893, 0.003872542, -0.13476561, -0.036068805, -0.054637462, 0.02304618, 0.04707738, -0.2856381, 0.07124422, 0.010866545, 0.20484549, -0.008342406, -0.43660247, -0.041055538, 0.33536008, -0.060022205) * go_1(1.0, -1.0);
|
||||
result += mat4(0.1966458, 0.0016302796, -0.25712642, -0.09639119, -0.006955351, 0.10882133, 0.1107341, 0.062697805, -0.1074494, 0.17361663, 0.6429869, -0.39846307, -0.26302996, 0.048710946, 0.40387508, 0.4299715) * go_1(1.0, 0.0);
|
||||
result += mat4(0.18948616, 0.24086732, -0.064474985, -0.11069709, 0.1279659, -0.13438123, -0.028438117, 0.125883, 0.018153818, -0.21942288, 0.020390838, -0.22797634, -0.10821287, -0.17175092, 0.122016855, 0.20699544) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.05101961, -0.060740646, -0.024465766, 0.058471628);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.14533128, 0.07266841, 0.13238011, -0.23328504, 0.031516243, 0.058471266, -0.06394412, 0.090752736, -0.0042359144, 0.12357294, -0.04377495, 0.0011743477, 0.05412243, -0.08146249, 0.04002749, -0.032876283) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.036972385, -0.15238069, -0.3453321, -0.36025128, 0.07597202, -0.02368151, -0.3889606, 0.34607083, 0.3133179, -0.21712309, -0.4210954, 0.21450534, 0.15226828, 0.25326282, 0.45327064, -0.3350824) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.019018406, -0.33060563, -0.092601225, 0.14970545, 0.1441509, -0.19228427, -0.032771986, 0.26331595, 0.052981265, -0.06627376, -0.08634131, 0.038706224, 0.13403937, -4.4842476e-05, 0.049002815, -0.12719193) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.17527401, -0.0035254909, -0.047959115, -0.4526988, -0.07510284, 0.0013256798, -0.07539148, 0.24220634, -0.08708839, -0.14494033, -0.17085724, -0.099797316, 0.0068515535, -0.08918779, 0.27164719, -0.1702649) * go_0(0.0, -1.0);
|
||||
result += mat4(0.31848368, 0.48983255, -0.44140294, -0.65174145, -0.004199057, 0.19494705, 0.5196497, -0.027118586, 0.032509074, -0.23900363, -0.14489244, 0.36314297, -0.23168536, -0.20960593, 0.61471456, 0.12401275) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.24317405, 0.21560913, 0.15564032, 0.11606844, -0.15039803, -0.59578896, 0.14100945, -0.026194477, 0.37237462, -0.49472088, -0.15215331, -0.38820064, -0.25089455, -0.29643852, -0.09513793, 0.019779462) * go_0(0.0, 1.0);
|
||||
result += mat4(0.12498539, 0.0710632, -0.25012368, -0.2272255, -0.08647026, 0.12277892, 0.011025097, -0.12168395, -0.13489573, 0.016708186, -0.15583871, -0.057124946, 0.1216943, 0.019803725, 0.06952334, -0.032985855) * go_0(1.0, -1.0);
|
||||
result += mat4(0.28794885, 0.33783793, -0.14469545, -0.081780486, -0.50320613, -0.067601606, -0.06847453, -0.021648854, -0.34295765, 0.15071863, -0.06619896, -0.084465064, 0.31909832, 0.015414661, 0.14930317, -0.11295768) * go_0(1.0, 0.0);
|
||||
result += mat4(0.24530606, 0.25526014, 0.09971985, -0.07749641, -0.2361951, -0.07997673, 0.03617294, 0.02959561, -0.4498983, -0.014073485, -0.20587012, 0.06396779, 0.1262825, 0.027433183, 0.14469334, 0.011538011) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.038572453, -0.023108613, -0.039481267, -0.012160024, -0.004521989, -0.028665857, 0.04295255, 0.10580258, 0.05439479, -0.072261885, 0.11030243, 0.08934696, 0.09133867, 0.017547369, 0.097613186, 0.05491059) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.09972817, 0.057730395, 0.12665828, 0.32861367, -0.16186063, 0.0745509, 0.2394045, -0.08687853, -0.034404907, -0.05843572, 0.0684561, -0.1355754, 0.19248672, -0.60372186, 0.12583947, 0.4388962) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.10341107, 0.061113223, 0.08773817, -0.082504354, -0.16612078, 0.2681751, 0.019737698, -0.17122322, -0.135949, 0.3048101, 0.087803006, 0.11373851, 0.013192192, -0.27022064, 0.35529897, -0.15321451) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.032835662, 0.11123062, -0.11322452, -0.17300649, 0.04680824, 0.12849288, 0.17269878, -0.048671383, 0.05189037, -0.009078046, 0.22105052, 0.013008137, -0.009738674, 0.15391739, 0.20969556, 0.14189166) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.47377753, 0.3038031, 0.18604809, 0.1931698, -0.2964668, -0.12287907, -0.7107761, 0.26619422, -0.33923018, 0.19200724, 0.013786281, -0.17496964, 0.079325035, -0.3694445, 0.0054486147, -0.33018264) * go_1(0.0, 0.0);
|
||||
result += mat4(0.14903802, -0.028043179, 1.5238678e-05, 0.021232028, 0.16025065, 0.14746875, -0.22831628, -0.12177345, 0.038778774, 0.32188168, -0.042017702, 0.27155936, 0.17920609, 0.04099755, 0.28527525, 0.074623376) * go_1(0.0, 1.0);
|
||||
result += mat4(0.057019282, -0.112741895, 0.030361209, 0.14567861, 0.056265317, -0.01573537, -0.06707608, 0.016657263, 0.09829025, -0.026795063, 0.023042196, 0.09438241, -0.025483066, -0.052787006, 0.19730279, 0.021218104) * go_1(1.0, -1.0);
|
||||
result += mat4(0.19868211, -0.01531125, 0.108596824, -0.035456363, 0.0033609823, 0.057961613, -0.013726211, 0.101742364, 0.33357215, 0.14468077, 0.29711527, -0.24662566, -0.119014986, -0.1899639, 0.11246697, -0.0035374009) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.05602109, -0.15539522, 0.010730943, 0.057116497, -0.02037749, 0.084210664, -0.028235348, 0.10574697, 0.056925274, 0.07922333, -0.090088, 0.1615985, -0.0044301567, -0.089945644, 0.024176618, -0.041844133) * go_1(1.0, 1.0);
|
||||
result += vec4(0.0015292584, -0.043625206, -0.09429898, -0.06280405);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.06051604, -0.028152643, -0.21418124, 0.13032125, 0.42565975, -0.09571944, -0.34494513, 0.30004, -0.073245734, -0.028659137, 0.0032105136, -0.05009555, -0.048971225, 0.04814533, 0.002843805, -0.046224426) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.07495975, 0.018714864, 0.21229684, -0.13614887, 0.79988647, -0.0697328, 0.38232988, 0.24165109, 0.25947478, -0.0009418982, -0.17369923, 0.10007766, 0.024117598, 0.028611807, 0.15090801, -0.06344829) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.07982219, 0.0900347, 0.007609254, -0.0034791247, 0.013611781, -0.13560618, 0.09685799, 0.06276075, 0.134693, -0.14370437, -0.25175703, -0.0016138123, -0.0075672898, -0.13325731, -0.061100446, 0.0059743375) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.039018434, -0.19668463, -0.43018532, 0.31886247, 0.4965479, 0.114569925, 0.19110382, 0.27343535, 0.0707728, -0.11877004, -0.25827697, 0.37012872, 0.1474777, 0.07056952, -0.14965728, 0.061595406) * go_0(0.0, -1.0);
|
||||
result += mat4(0.506543, -0.16268773, 0.455319, -0.0702646, 0.70102173, -0.14041683, 0.70184857, 0.4817842, -0.3389246, -0.14463086, 0.13763213, -1.1259074, 0.47722015, 0.38352612, -0.04293366, -0.5604627) * go_0(0.0, 0.0);
|
||||
result += mat4(0.17606944, 0.15897374, 0.13499324, 0.29241478, -0.032824475, 0.11128662, -0.22204424, -0.051803727, 0.013195331, -0.42040786, -0.3950585, 0.70745844, 0.38646924, -0.19080774, -0.15171832, -0.10742828) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.039278325, 0.18421806, -0.044948544, 0.07902063, -0.2149251, 0.09913459, -0.09743655, -0.26899317, -0.002695496, -0.07554527, -0.22373366, 0.17830558, -0.047994815, -0.06789183, -0.06755918, -0.104452066) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.0493473, -0.30411786, -0.056439694, -0.06582185, -0.21309847, 0.100670904, -0.22966193, -0.045954112, 0.12728062, -0.25081897, -0.094699375, -0.4036555, 0.060854495, -0.64373237, -0.21522263, -0.6683476) * go_0(1.0, 0.0);
|
||||
result += mat4(0.063481025, 0.11744312, -0.043330096, 0.33817932, -0.06679828, -0.23207302, -0.10188898, -0.10590511, 0.058780864, 0.047292337, -0.11834696, 0.10076128, -0.036641665, 0.30200714, -0.0002892557, -0.10303763) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.10842604, 0.042055763, 0.29702973, -0.07409644, -0.030164458, -0.012098744, -0.06396587, -0.08787527, 0.051854923, 0.12997511, 0.11468497, 0.15022379, 0.007814715, 0.014517445, 0.025484756, 0.01078619) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.29229385, 0.040265664, -0.15376821, 0.075579196, -0.05593569, -0.045405343, 0.12099204, 0.1571252, 0.17841713, 0.04673325, 0.14550509, 0.08603346, -0.049786013, 0.06121843, -0.16273825, -0.13857752) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.06903744, 0.2628764, -0.13582836, -0.35678583, -0.13821034, -0.019381443, -0.19570538, -0.09298511, 0.08965436, 0.09745909, 0.20055099, 0.024967568, 0.08144204, 0.004633625, 0.12809834, -0.009431525) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.09784006, 0.010729353, 0.046643205, -0.110926524, -0.21556224, 0.00016300633, 0.122175336, 0.15004392, 0.013864355, 0.24767809, 0.13865592, 0.0155424485, -0.1450483, -0.15688781, -0.06195043, -0.13745981) * go_1(0.0, -1.0);
|
||||
result += mat4(0.018991318, 0.55401963, 0.11709872, -0.028442185, -0.46035343, -0.10215539, -0.60193926, 0.47882316, -0.23346989, 0.037200127, 0.22814943, -0.08231696, -0.36430013, -0.011152757, 0.48752213, 0.29796222) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.07258066, -0.023222538, 0.23230423, -0.30317304, 0.03942911, -0.06899803, 0.23778579, 0.07418621, -0.17443737, 0.33387753, 0.007354842, -0.123447575, -0.1745315, 0.11071779, -0.11949625, -0.22832453) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.024909232, -0.0308135, 0.12170621, -0.13298757, 0.045828197, -0.1532345, -0.06633672, 0.23591088, 0.04964077, 0.14091493, 0.038343724, -0.029780807, 0.05762822, -0.048930667, -0.02434709, 0.07109019) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.16039175, 0.3004474, -0.17278233, 0.13677922, 0.18838613, 0.15054552, 0.32901475, -0.1288333, 0.26378244, -0.05119892, 0.34533516, 0.25180495, 0.19452183, 0.0843233, -0.08029368, 0.39877903) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.07097129, -0.26492423, -0.055032317, -0.093516104, -0.11795062, 0.04086253, -0.07989471, 0.059686553, 0.09378249, 0.45851848, 0.2510942, 0.19599153, 0.019765077, -0.02920918, -0.04125142, -0.13859107) * go_1(1.0, 1.0);
|
||||
result += vec4(0.04400571, -0.04015565, 0.0140529545, 0.05474095);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.014236042, -0.0031431736, -0.1551387, 0.12515116, -0.28528872, 0.36161992, 0.15750743, -0.17111474, 0.13792591, -0.0657419, -0.17471549, 0.14650472, 0.034169197, -0.019157575, 0.23520657, -0.20358163) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.02015035, 0.12993371, 0.11199667, -0.09854378, 0.5001741, 0.03462961, 0.24919736, 0.08505297, -0.20902094, -0.24141377, -0.15360375, 0.049974803, -0.037157424, -0.048510186, 0.20106035, -0.118480384) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.086798504, -0.009607818, 0.034812123, -0.005187592, 0.0351509, 0.021755, -0.04996161, -0.041231696, 0.0020545553, 0.015730752, -0.07507172, 0.018597523, -0.02393343, 0.07624775, 0.03892451, -0.0025574185) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.035725456, 0.06809103, 0.51926994, -0.39983147, -0.16402833, -0.1243394, -0.25922915, 0.28285915, 0.15959994, -0.2351732, 0.2650535, -0.30193794, -0.11468332, 0.050777763, -0.51894253, 0.4408367) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.27042082, 0.22243942, 0.14902467, 0.38428563, 0.46612173, 0.5169912, -0.22330502, -0.11300288, -0.36141354, 0.0668681, 0.2984152, 0.1275798, -0.24121419, 0.2952039, -0.45109174, -0.3822957) * go_0(0.0, 0.0);
|
||||
result += mat4(0.26543504, -0.05742226, -0.052103903, -0.013124308, -0.14358385, -0.04024543, 0.07665455, -0.012301872, -0.18752757, -0.03913891, 0.038205814, -0.006583095, -0.25550908, -0.25725332, -0.12454206, -0.0058936924) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.0018946569, 0.019746022, -0.13080788, 0.11450627, -0.013743845, -0.027179785, -0.14425103, 0.07109661, 0.023703793, 0.086905524, 0.03151253, 0.0132474145, 0.041018624, 0.04548913, 0.2718715, -0.20008296) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.076830454, 0.11652955, 0.5068201, -0.3082819, 0.058615055, -0.006765798, -0.057522714, 0.049981344, -0.006897243, -0.21763432, 0.16896053, -0.21176189, -0.061227098, 0.03566485, 0.08901554, -0.050980624) * go_0(1.0, 0.0);
|
||||
result += mat4(0.02327798, 0.07662976, 0.034811985, -0.03238033, -0.0021881019, -0.030997375, -0.069672935, 0.04040273, -0.1217442, 0.104173124, 0.09862539, 0.020557549, -0.022286594, 0.10287763, -0.021694934, 0.07542515) * go_0(1.0, 1.0);
|
||||
result += mat4(0.124069154, -0.08579466, -0.07816314, 0.11332851, -0.034682628, -0.11038275, 0.04750615, -0.096100725, 0.039588403, -0.15149672, -0.05529172, 0.034304325, -0.022520235, -0.05023852, -0.2674731, 0.21886522) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.1948599, -0.14946899, -0.39548838, 0.18042913, -0.007919619, 0.19826505, 0.23789087, 0.009140256, 0.11857748, 0.18215668, 0.13606293, -0.09209675, -0.080678545, -0.020431137, -0.07728839, -0.051353537) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.07616472, -0.0032800382, -0.045657665, -0.039144326, -0.37786487, -0.08877774, 0.053579114, -0.070886396, 0.011311804, 0.107276045, 0.013236154, 0.009832061, 0.08292063, 0.12258811, 0.0005569043, -0.009806432) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.28062925, 0.15946878, -0.1021801, -0.06471589, -0.26999477, 0.21230288, -0.14243907, 0.2555922, -0.09608517, 0.26339412, 0.20891234, -0.23538485, 0.33958244, -0.12569186, 0.43289876, -0.33462036) * go_1(0.0, -1.0);
|
||||
result += mat4(0.16265294, 0.2625464, -0.34452894, 0.2233622, 0.13850005, -0.42999864, -0.5385177, -0.11035979, 0.51662, -0.78238726, -0.09422375, 0.83759475, 0.44468537, 0.14301361, 0.108906105, 1.1596143) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.73757625, -0.12369605, 0.23523071, 0.006587637, -0.15445381, 0.22757277, 0.052819528, 0.10183905, -0.07912228, -0.16998893, -0.13360223, 0.014348178, -0.17778571, -0.41047302, 0.10241381, -0.08526306) * go_1(0.0, 1.0);
|
||||
result += mat4(0.14712952, 0.048995696, 0.05299946, -0.06817572, 0.1498064, -0.079825334, 0.40354064, -0.31789717, -0.1998377, 0.00955295, -0.32318407, 0.30898204, -0.039571725, -0.026203401, -0.16292085, 0.08574385) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.6353329, -0.56000775, -0.17279743, 0.18198174, -0.19555812, 0.056538377, 0.34365895, -0.07799055, 0.19011354, -0.13952748, 0.029196098, -0.19596763, -0.069196045, -0.17402656, 0.07948411, -0.016226962) * go_1(1.0, 0.0);
|
||||
result += mat4(0.25592864, 0.083498634, -0.28515807, 0.10789751, 0.0043962947, 0.07085363, 0.048724182, -0.025131436, -0.0049440865, -0.033094388, -0.032935806, 0.04266025, 0.20026933, 0.0927841, -0.006839351, -0.013012285) * go_1(1.0, 1.0);
|
||||
result += vec4(0.02021373, 0.0014037411, 0.0012718709, 0.017278494);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Conv-4x1x1x56
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_6_tf
|
||||
//!SAVE conv2d_last_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_2 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_5 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_6 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_9 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_10 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_13 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.0067711817, 0.08160003, 0.0247279, 0.03084815, -0.026977416, -0.02120602, -0.025078611, -0.029852165, -0.011627478, -0.012742972, 0.022736797, -0.0028815821, -0.007515677, 0.0172887, -0.023259213, 0.009608947) * g_0;
|
||||
result += mat4(-0.028660107, -0.014015208, -0.027838672, -0.013171922, 0.0029435428, 0.027047642, -0.017478354, 0.022834882, -0.037572853, -0.0034044068, -0.0149029335, -0.013362301, 0.009827443, -0.015742151, -0.0074795415, -0.0022266617) * g_1;
|
||||
result += mat4(-0.07579662, -0.039754186, -0.066026606, -0.046816852, 0.1099032, 0.043956704, 0.073109835, 0.04680284, -0.06896613, -0.008838632, -0.044584926, -0.01319039, -0.0021152915, -0.04503326, 0.027061926, -0.028334105) * g_2;
|
||||
result += mat4(0.15458213, 0.059769996, 0.09327123, -0.028782733, 0.023459995, -0.15390377, -0.13432898, -0.1127775, 0.072764635, -0.0020463336, 0.034736466, -0.0012086042, -0.05847183, -0.029952323, 0.052969377, 0.09590908) * g_3;
|
||||
result += mat4(-0.07476772, -0.016574614, 0.04131183, 0.017335678, 0.009654406, 0.072183535, -0.002266456, 0.086873695, 9.310129e-05, 0.0056416965, -0.004188391, 0.023132093, -0.05183336, -0.025825873, -0.03684392, -0.0075729224) * g_4;
|
||||
result += mat4(0.00878842, 0.03869637, -0.035759524, 0.003345386, -0.064184256, -0.034568302, -0.06672922, -0.0686381, -0.06794392, -0.10685906, 0.04679947, -0.012535639, 0.006932529, -0.007783515, 0.109123886, 0.13804391) * g_5;
|
||||
result += mat4(-0.03160699, 0.050473, -0.09030729, 0.0649397, 0.11466501, 0.17912874, -0.0081851315, 0.052244574, 0.051632743, 0.061941486, 0.06546816, 0.12174249, -0.05104755, -0.018193979, -0.032196652, -0.035292786) * g_6;
|
||||
result += mat4(0.013612735, -0.0024100312, -0.068611205, -0.07369285, -0.019647537, -0.066944756, -0.010012875, -0.06785739, -0.062246565, -0.087313406, -0.044278186, -0.09368995, 0.052555013, 0.13604961, 0.05645059, 0.08763303) * g_7;
|
||||
result += mat4(0.04218486, -0.05028401, 0.059086576, -0.03545452, 0.027737848, 0.0043074046, 0.0011001764, -0.073026665, -0.04094988, 0.044061556, -0.009812515, 0.06841999, -0.06612581, 0.037223976, -0.07759491, -0.04356598) * g_8;
|
||||
result += mat4(-0.027558247, 0.014248466, -0.019813016, -0.058107473, -0.016717663, -0.020424338, 0.0053625097, -0.009917319, 0.013678771, 0.0113340765, 0.0061787106, -0.036083996, -0.020179711, -0.011310535, 0.054827053, -0.0008278952) * g_9;
|
||||
result += mat4(0.028690035, -0.012079616, 0.11931408, -0.048533775, 0.069336995, 0.0049852817, 0.013774468, 0.035233382, -0.07384821, 0.0003354423, -0.0059171803, -0.04503906, 0.08727279, 0.005138857, -0.17724465, 0.055782065) * g_10;
|
||||
result += mat4(-0.20744391, 0.24348328, -0.3145766, 0.17026486, -0.022870807, -0.01648648, -0.05912279, -0.012555373, -0.066004686, 0.03182394, 0.16285324, -0.1221846, -0.31816196, 0.007928748, 0.43180224, -0.015949022) * g_11;
|
||||
result += mat4(0.16363169, 0.14781676, -0.2377973, -0.1571377, -0.09038187, 0.0046504294, 0.033955004, -0.051421452, 0.046735536, 0.006827522, -0.121338, 0.12671822, 0.15833299, -0.1858712, -0.1942371, 0.17336044) * g_12;
|
||||
result += mat4(-0.018145572, -0.015550516, 0.044410378, 0.046016492, 0.084021375, 0.05327457, -0.008270992, -0.045435544, 0.07185879, -0.131923, 0.26721445, -0.26745328, -0.07093472, 0.042701527, 0.13793674, -0.095621444) * g_13;
|
||||
result += vec4(0.016836504, 0.010161949, 0.021351453, 0.01278978);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(M)-Depth-to-Space
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_last_tf
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_last_tf.w 2 *
|
||||
//!HEIGHT conv2d_last_tf.h 2 *
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
vec4 hook() {
|
||||
vec2 f0 = fract(conv2d_last_tf_pos * conv2d_last_tf_size);
|
||||
ivec2 i0 = ivec2(f0 * vec2(2.0));
|
||||
float c0 = conv2d_last_tf_tex((vec2(0.5) - f0) * conv2d_last_tf_pt + conv2d_last_tf_pos)[i0.y * 2 + i0.x];
|
||||
float c1 = c0;
|
||||
float c2 = c1;
|
||||
float c3 = c2;
|
||||
return vec4(c0, c1, c2, c3) + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(S)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.0057322932, 0.12928207, -0.056848746, 0.18680117, -0.0306273, 0.25602463, 0.053723164, 0.20419341, 0.0018709862, 0.022848232, -0.04105527, 0.10169034, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.009471417, -0.12957802, 0.096014425, 0.21836184, 0.00021601951, -0.22997683, 0.23666254, 0.41192335, 0.021762101, 0.0047863554, 0.008233427, 0.108514786, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.01156376, -0.18988979, 0.04614705, -0.044767227, 0.01050636, -0.26426336, 0.23741047, 0.0027636609, -0.027718676, -0.14202335, -0.016650287, -0.06637125, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.057809234, -0.11033858, 0.056533534, -0.06292466, 0.13880666, -0.18710336, 0.2441031, -0.25326246, 0.0032683122, -0.026437074, 0.0023248852, 7.640766e-05, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.49110603, 0.4429004, -0.44015464, -0.41174838, -0.87738293, 0.7808468, -1.0929365, -0.59699076, -0.18409836, 0.185138, -0.11773224, -0.17097276, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.10580959, -0.055947904, -0.03431237, -0.080236495, 0.14862584, -0.15393938, -0.18872876, -0.3170681, 0.03559387, -0.003990826, 0.021298569, 0.012844483, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.040715586, -0.25781113, 0.08896714, -0.1225879, -0.15790503, -0.54010904, 0.29588607, 0.10401059, 0.003413123, -0.108357325, 0.0112870345, -0.11888622, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.0049315444, 0.02376202, -0.08224771, 0.121118225, -0.041512914, -0.027994309, -0.585988, -0.069672115, -0.017247835, 0.0056576864, 0.04319012, 0.055003505, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(0.37521392, 0.15916082, 0.059708964, 0.19046007, 0.8120325, 0.38343868, 0.3436578, 0.5287958, 0.16570656, 0.06957687, 0.014022592, 0.074799836, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(-0.01050964, -0.00939481, 0.17684458, 0.027366742);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(S)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.011029496, 0.05866063, -0.09460646, -0.017664742, -0.022488879, 0.18384217, -0.00397663, -0.064733066, 0.08466802, 0.10667488, 8.0212536e-05, 0.0908869, 0.13580276, 0.00097438256, 0.12176522, -0.08218466) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.16062798, -0.10190268, 0.03280682, 0.05621916, -0.009684231, -0.08464307, 0.17058301, -0.096469186, 0.1967505, -0.1450099, 0.093607284, -0.28240147, -0.21377413, 0.10079291, -0.1741522, 0.17330575) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.060160473, 0.06316997, 0.0046929033, -0.049405966, 0.13851729, 0.06830702, -0.0586872, -0.040827133, 0.007052838, -0.03576886, -0.111261636, 0.039155316, -0.07380389, -0.09369825, 0.04471156, 0.09678487) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.36683616, -0.035950605, -0.24414362, -0.009159744, 0.19335322, -0.099253505, 0.075083904, -0.00076695543, 0.65291303, -0.25599423, 0.19827642, 0.065899536, -0.07423247, -0.068967685, 0.0050554527, -0.060272824) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.020688485, -0.83178276, 0.11104878, 0.26454413, 0.13655476, 0.37675047, -0.22219229, -0.01751935, 0.44552696, 0.92510307, 0.16063261, -0.62011045, 0.19366647, -0.06996067, -0.2504841, 0.00803723) * go_0(0.0, 0.0);
|
||||
result += mat4(0.0051537007, -0.057168536, -0.16110587, 0.25232598, -0.04447099, 0.11997351, 0.14808103, -0.34443566, -0.26212573, -0.21970181, 0.2724405, 0.21050811, -0.07949061, -0.064808235, -0.21208277, -0.0042361654) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.0888952, -0.20169449, 0.19144905, -0.016882861, -0.013283103, 0.07552998, -0.24686803, 0.012453213, -0.065454446, -0.016123284, -0.47316182, 0.070926026, 0.09219782, 0.13118166, 0.074736096, 0.0077910526) * go_0(1.0, -1.0);
|
||||
result += mat4(0.5832154, 0.1138069, -0.039765622, 0.3182784, -0.25497997, 0.0013993139, 0.39285088, -0.48511526, -0.39891505, -0.19094779, -0.082146175, -0.20826934, 0.020590555, -0.0012490178, -0.4398621, 0.14377014) * go_0(1.0, 0.0);
|
||||
result += mat4(0.21917395, 3.4314657e-05, 0.25734863, -0.3433305, 0.015720673, 0.2676127, -0.06807297, 0.15040149, -0.23638041, -0.0050233034, -0.13666134, 0.4542111, -0.033572577, -0.08450588, -0.23341487, 0.053490847) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.17482175, 0.057647135, 0.33135444, 0.0850751, -0.1718849, -0.0854123, 0.036795795, -0.13874969, -0.10903869, -0.19007301, -0.06064334, -0.03786032, -0.036696054, 0.07844446, 0.012523185, -0.01562906) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.04411997, -0.10331819, 0.10050193, 0.12406485, 0.07431592, 0.30109692, -0.17511666, -0.13263564, -0.10192587, 0.07821255, -0.22415096, 0.25552443, 0.17881326, -0.13914281, 0.109979235, -0.0016463579) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.01911644, -0.15412527, 0.028903123, 0.20831817, 0.00375175, 0.08110953, 0.074919395, -0.17581624, -0.015677985, 0.06504228, 0.08817818, -0.12518327, -0.09537373, 0.028905088, -0.051288474, 0.054334078) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.2852779, -0.28924024, 0.36805123, 0.21079305, -0.28336474, 0.1679663, -0.08641141, -0.10699407, -0.16090055, 0.1287612, -0.15910125, 0.05734755, 0.15883245, 0.0053026294, 0.080674745, 0.0505137) * go_1(0.0, -1.0);
|
||||
result += mat4(0.17639062, 0.3790122, -0.19588692, -0.020314282, 0.26197383, 0.09014768, 0.19696823, -0.41025418, -0.08308115, -0.33279485, -0.22528782, 0.06172439, -0.1365661, -0.13094363, -0.005086559, 0.089024484) * go_1(0.0, 0.0);
|
||||
result += mat4(0.05262993, 0.0006296959, 0.1657725, -0.32591924, 0.12126701, 0.061543245, -0.10526848, 0.041583937, 0.094976954, 0.09416157, -0.22019257, -0.058390073, -0.2073888, 0.057273377, 0.19558284, 0.004208022) * go_1(0.0, 1.0);
|
||||
result += mat4(0.30005738, 0.18478931, -0.23342943, 0.22455733, -0.016488122, 0.099634305, 0.31620836, -0.15731157, 0.09595808, 0.0013774688, 0.48273298, -0.07027936, -0.18764344, -0.26194447, -0.11794225, -0.012173601) * go_1(1.0, -1.0);
|
||||
result += mat4(0.117986746, -0.13846518, -0.019614812, -0.3011192, 0.5501164, 0.3408611, -0.40090847, 0.15706886, 0.13050972, 0.051776595, 0.20792943, 0.23389706, -0.22965533, -0.053367328, 0.3911586, -0.032988597) * go_1(1.0, 0.0);
|
||||
result += mat4(0.054753624, -0.008485731, -0.2451672, 0.17528129, 0.13657846, 0.010480436, 0.07651423, -0.43316832, 0.12736236, 0.13804524, 0.12529011, -0.30946237, -0.14423579, 0.08403089, 0.24335162, 0.057288036) * go_1(1.0, 1.0);
|
||||
result += vec4(0.012077211, 0.013045883, 0.0380778, -0.02908858);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(S)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.036115196, -0.06971895, -0.07508942, 0.016036168, 0.12120111, 0.24536026, 0.044755507, -0.20663576, 0.029635755, -0.15427187, 0.027148994, -0.20795093, 0.10170582, 0.077919215, 0.66063017, -0.4632968) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.0052889925, -0.019060908, -0.08660142, -0.022095207, -0.08097976, -0.015142803, -0.18552722, -0.078493506, -0.16293915, -0.20099808, -0.08370822, 0.3701389, 0.09094984, 0.2487225, 0.24338846, 0.044003833) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.061406493, -0.017232792, -0.10917424, 0.11203319, 0.040699825, -0.019294346, 0.084953666, -0.018133596, 0.07209552, 0.016069936, 0.17805555, -0.089537814, 0.15809004, 0.1027023, 0.15044671, -0.15530108) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.0948676, -0.040305693, -0.005591629, -0.048048403, -0.07547777, 0.056606572, 0.021390207, 0.32600567, -0.20805131, -0.099587254, 0.029613169, 0.0092129605, -0.29429698, -0.09898621, 0.44470885, -0.89487344) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.122259885, 0.11445877, 0.06666907, 0.1869428, -0.1553992, -0.1658741, 0.2988138, -0.57746625, -0.34609964, 0.11169158, -0.41877756, 0.38075635, 0.21293911, 0.09640372, -0.12754214, -0.08026104) * go_0(0.0, 0.0);
|
||||
result += mat4(0.15128808, 0.050087795, 0.09219755, -0.18080945, 0.0044571217, -0.046019405, -0.1289922, 0.20305426, 0.19601224, 0.04667917, 0.17465587, 0.027672665, 0.18441725, 0.06845396, 0.11288585, -0.23283863) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.072962, -0.06639447, 0.049347494, -0.1386401, 0.10396071, 0.08187777, -0.04280746, 0.07390891, 0.06628344, 0.037797406, 0.021885803, -0.013147403, 0.22376558, 0.36243078, 0.12874891, -0.0023783944) * go_0(1.0, -1.0);
|
||||
result += mat4(0.074945286, 0.16045591, -0.11798349, 0.12910712, 0.054760084, -0.095626175, -0.047832094, 0.03493912, 0.11817307, 0.037452437, -0.14301221, -0.027356789, -0.052390423, 0.11373512, 0.07686775, 0.010008694) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.023999173, -0.091900624, 0.02388157, 0.03173873, 0.0065633506, -0.033716757, -0.1198324, 0.12057766, 0.026465805, -0.07517131, -0.07760598, 0.060463097, 0.07345541, 0.046037503, 0.21101558, -0.26785463) * go_0(1.0, 1.0);
|
||||
result += mat4(0.15544604, -0.03902825, 0.04630384, -0.25173616, -0.0691359, 0.07476507, 0.009071253, 0.089964196, -0.26539803, -0.3958477, -0.22155671, 0.20735882, -0.105860494, -0.003996804, -0.044815883, 0.39544627) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.6169709, 0.23717614, -0.37884676, -0.7484867, 0.020169826, -0.30718836, 1.0965588, -0.20711036, -0.39149985, -0.06843563, -0.06522909, 0.103805855, 0.03265825, -0.15137726, 0.12837899, -0.01294922) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.23638196, -0.4560866, -0.11948684, -0.1464144, 0.10690008, 0.007835961, 0.11864342, -0.13101323, -0.16509797, 0.075027354, 0.08122998, 0.13451207, 0.0011890623, 0.052157886, 0.08372405, -0.07085038) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.21997726, -0.16488647, -0.0291317, 0.17997476, 0.1493211, 0.027494298, 0.0034613227, -0.3207727, 0.18699001, 0.14728633, -0.042895135, -0.07612043, 0.125076, -0.14714554, -0.03480009, -0.22753975) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.5342686, -0.7426105, -0.38294584, 0.42549992, 0.46053204, 0.7867879, 0.106234804, -0.041163098, 0.5198579, -0.5219404, 0.14809476, -0.41802374, 0.06810794, -0.15122683, -0.047409, 0.13178343) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.50428164, 0.18220626, 0.35510704, -0.081787474, 0.03155813, 0.019284263, 0.0032388573, -0.20513348, -0.05385551, 0.17803182, -0.26206362, 0.2870375, 0.008557827, 0.08401449, -0.027598893, -0.010791235) * go_1(0.0, 1.0);
|
||||
result += mat4(0.16657415, 0.067647465, 0.093076974, -0.14438486, -0.10017002, 0.0022367141, 0.03250936, -0.052794546, -0.009178676, -0.019673595, -0.0016697067, -0.15424626, -0.112123474, -0.11079971, 0.011987111, -0.11747758) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.023021797, -0.058703423, -0.037978355, -0.062433913, -0.13130441, 0.048656322, 0.056839373, 0.109036915, -0.07823158, 0.14785293, 0.058555078, -0.11679035, -0.14002073, 0.07395252, 0.098268874, -0.06710464) * go_1(1.0, 0.0);
|
||||
result += mat4(0.14906375, 0.030001195, -0.10338215, 0.0662968, -0.161953, -0.13682815, 0.09563142, 0.009514228, -0.009491218, 0.06737101, -0.1393389, 0.15231515, -0.073147796, 0.00767062, 0.028675212, 0.014213088) * go_1(1.0, 1.0);
|
||||
result += vec4(0.018736731, -0.0026039074, 0.050130025, -0.055364225);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(S)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!SAVE conv2d_last_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.019100675, -0.014241565, 0.004667036, -0.03865062, 0.106731094, 0.026099661, 0.014594411, -0.011881356, 0.0040967264, -0.004626336, 0.006469508, 0.010875305, -0.033909045, -0.085905954, 0.07861378, 0.019452631) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.20777655, -0.060354974, 0.0023840065, -0.064121604, -0.17397617, 0.019293457, -0.09707183, 0.080641985, 0.01025124, -0.017382381, 0.008661793, -0.010995665, 0.21943407, -0.115574986, 0.14471593, -0.068836235) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.057942886, -0.06311754, 0.2253396, -0.04159292, -0.020731755, 0.007877151, 0.041525815, 0.025278691, 0.03041967, -0.025137542, 0.024364179, -0.024543528, 0.029438615, -0.015506873, 0.081686, -0.07812221) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.054237515, 0.0676094, -0.0047708177, 0.0043467237, -0.10032304, -0.020498628, 0.04240586, 0.07272254, 0.0784221, 0.017945962, -0.022310399, -0.013134622, 0.015638694, -0.10001543, 0.1043031, 0.05898838) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.021652509, 0.35796642, 0.059497777, 0.23948468, 0.15454951, -0.10017235, -0.19072174, -0.44812536, -0.03974552, 0.04529369, 0.22207436, 0.026222564, -0.09705454, 0.5623026, -0.3354105, -0.017278556) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.053682446, -0.03411237, -0.09399936, 0.15128824, -0.07463, -0.042020727, 0.0031783928, 0.13481957, -0.07731454, 0.044114403, -0.23085599, 0.060444202, -0.15015422, 0.0018040676, -0.18684982, 0.2812511) * go_0(0.0, 1.0);
|
||||
result += mat4(0.0029329916, 0.001596018, 0.0007512241, 0.016544111, -0.04876942, -0.05272409, 0.037884697, 0.049948208, 0.015518177, 0.11368592, -0.03815777, -0.013149978, -0.027638039, 0.107719295, -0.04115787, 0.02745414) * go_0(1.0, -1.0);
|
||||
result += mat4(0.016691081, 0.010204119, 0.04078854, 0.01613337, 0.03325829, 0.0114824055, -0.017286912, -0.07284126, -0.110984206, -0.21041764, 0.0089543555, 0.18986733, 0.01537506, -0.2059135, 0.029074017, 0.013117443) * go_0(1.0, 0.0);
|
||||
result += mat4(0.013965926, 0.029871881, 0.0034499036, -0.011343668, 0.022120327, -0.0068748263, 0.009324342, -0.039081004, 0.08032371, 0.050809264, 0.035050742, -0.2032847, 0.06305391, -0.021958945, 0.038569167, -0.22465245) * go_0(1.0, 1.0);
|
||||
result += mat4(0.046307724, -0.012419472, 0.007673863, -0.042344846, 0.011042414, 0.016994251, -0.018166406, -0.016955731, -0.13240299, 0.01768431, -0.027607648, 0.0699927, -0.02840628, 0.004414203, 0.0049618417, 0.011084679) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.119954154, -0.007455482, -0.031108133, -0.009946449, 0.0077065965, 0.01660345, 0.032943666, 0.016376585, 0.10273124, 0.1556573, -0.24643841, 0.107307844, -0.068235755, 0.0561896, -0.0104672015, 0.042693343) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.01634601, 0.04195375, -0.10401894, 0.047641944, -0.034602515, -0.0034419263, -0.010457858, 0.015194475, -0.03962551, -0.030031368, 0.16036317, 0.019283568, -0.05877721, 0.016504882, -0.15523468, 0.018161612) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.08083991, 0.0024665035, -0.049373373, 0.030371357, 0.0113322195, -0.014676956, 0.011646689, -0.01142667, 0.124930486, 0.06625774, -0.045840867, -0.009693036, -0.012649251, -0.07388084, 0.008790075, 0.0013844534) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.33941835, -0.2763476, -0.118311435, -0.063535266, 0.20936015, 0.13731301, 0.13443594, 0.07464433, 0.059650812, -0.36973104, 0.16444235, -0.37082872, 0.06432777, -0.18283032, -0.044489607, -0.13895285) * go_1(0.0, 0.0);
|
||||
result += mat4(0.13533665, 0.08268915, -0.03675727, -0.14348659, 0.0186255, -0.05051692, 0.056702953, 0.0061717895, 0.047663026, -0.088188455, 0.23254345, -0.014015464, 0.08400204, -0.0073777726, 0.2202068, -0.12366078) * go_1(0.0, 1.0);
|
||||
result += mat4(0.04361004, 0.046543695, 0.0064863074, -0.03358146, -0.022602187, 0.018138997, -0.011071864, 0.010244091, -0.019814799, -0.17250171, 0.040823266, -0.040131986, 0.010125854, 0.020660749, 0.0020435036, -0.010819304) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.004810193, -0.11286074, 0.051985834, 0.04788631, -0.023950428, 0.036145125, -0.038203828, 0.052401308, 0.022986965, 0.26420745, -0.06076917, -0.09252999, 0.03164547, 0.15652153, -0.037934, -0.0035418556) * go_1(1.0, 0.0);
|
||||
result += mat4(0.03358366, -0.005219482, 0.007060882, -0.06569114, -0.02941682, 0.00966056, -0.0153679885, 0.019905418, -0.107232265, -0.03405676, -0.044340115, 0.26892832, -0.04723829, -0.02589829, 0.004563232, 0.19318114) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.00346731, -0.0046263863, -0.004627155, -0.0057769152);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(S)-Depth-to-Space
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_last_tf
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_last_tf.w 2 *
|
||||
//!HEIGHT conv2d_last_tf.h 2 *
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
vec4 hook() {
|
||||
vec2 f0 = fract(conv2d_last_tf_pos * conv2d_last_tf_size);
|
||||
ivec2 i0 = ivec2(f0 * vec2(2.0));
|
||||
float c0 = conv2d_last_tf_tex((vec2(0.5) - f0) * conv2d_last_tf_pt + conv2d_last_tf_pos)[i0.y * 2 + i0.x];
|
||||
float c1 = c0;
|
||||
float c2 = c1;
|
||||
float c3 = c2;
|
||||
return vec4(c0, c1, c2, c3) + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,969 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.3053028, -0.037464816, 0.113983095, 0.12537485, -0.18630321, 0.084269725, -0.01351514, -0.20190673, -0.12298384, -0.037622184, -0.070214555, -0.19367279, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.41849324, 0.099702746, -0.04276645, -0.047299717, 0.20074473, 0.14217933, 0.15571699, 0.19553481, 0.21868695, -0.053848714, 0.016413521, 0.14117444, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.030540446, -0.052293833, 0.0715466, -0.31160545, 0.07808315, -0.16860045, 0.032828577, -0.2955024, -0.110374965, 0.04043687, -0.014024628, 0.058699366, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.10727635, 0.054200135, 0.20853694, 0.21086875, 0.122690216, -0.091823794, 0.310609, -0.01738923, -0.0013488946, 0.10835534, -0.077265196, 0.086751856, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.77150255, 0.40530515, -0.41257596, -0.14367618, 0.46888494, 0.2650122, -0.934199, 0.40476102, 0.32293493, 0.20251967, 0.19891106, -0.29698747, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.12505147, -0.41904053, -0.065798186, 0.34075752, 0.026240354, -0.2977496, 0.032647505, -0.003566783, 0.10290523, -0.23417123, -0.06014203, 0.094735645, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.11207838, -0.04062474, 0.023897955, 0.08605987, -0.020888371, 0.045541205, -0.07231824, -0.25884083, -0.11796847, -0.002691391, 0.0050435597, 0.02756291, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.4615728, 0.041790638, 0.08971143, 0.20213957, -0.38537467, 0.19938901, 0.08594364, -0.08621994, -0.08163473, -0.133266, -0.09561729, -0.014209637, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(0.0787417, -0.0483673, 0.07621572, -0.060169693, -0.013465177, -0.17152289, 0.02515561, 0.17675288, -0.05173998, 0.10768042, -0.029858522, -0.013957215, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(0.0072128535, -0.05658625, 0.052939568, -0.1760861);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf1
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.112743355, 0.0422517, 0.21350034, -0.0967133, 0.16265953, 0.0022497, 0.015078242, 0.08204187, 0.035236806, -0.0468228, -0.09464228, -0.001864949, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.25631642, -0.41485596, -0.16662048, 0.13201024, 0.057921384, 0.2240005, -0.30038536, -0.08305622, 0.2228756, 0.32263795, 0.10608189, -0.18616734, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.08997524, 0.11516871, 0.19212262, -0.035154644, 0.11612274, -0.04056247, 0.14974374, 0.029173585, -0.07629641, -0.14353512, 0.041081246, 0.20230265, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.2262286, 0.055954933, -0.14499907, 0.17314723, 0.16590612, -0.06688698, -0.11118816, -0.012938116, -0.043101817, 0.026133137, 0.2958395, 0.06543993, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.07311521, -0.3041244, -0.47978505, -0.6350967, -0.17432262, 0.34965977, 0.25399777, -0.16590433, -0.49957857, 0.0549526, -0.40869385, -0.08780993, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.3014447, -0.00021343959, -0.14953177, 0.028001398, -0.14931908, -0.14910097, -0.13287953, -0.45026535, 0.17378895, 0.024704922, -0.027308129, -0.10292025, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.06732655, -0.13119644, 0.066014715, 0.081011154, -0.15154321, 0.2407805, 0.07733481, 0.12312706, 0.1741804, 0.008495716, -0.14125362, -0.043644864, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.11465958, 0.42001364, 0.011069392, 0.3203028, -0.058801666, -0.37830314, -0.030540617, 0.2245139, -0.11310525, -0.14845212, 0.19957744, 0.25789997, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.16037206, 0.21326372, 0.020099448, 0.018666709, 0.122083254, -0.16033986, -0.10725163, 0.2556128, 0.1650688, -0.10475823, 0.048623525, -0.103755645, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(0.007717166, -0.027800834, 0.0795002, 0.0053199283);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.0056740534, -0.21186607, -0.18014967, 0.118979976, -0.0015611284, -0.07708486, 0.060131397, 0.11653345, 0.027150517, 0.10837246, 0.08583816, -0.14032431, 0.017552888, 0.0035846964, 0.03980114, 0.064649396) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.03289318, -0.12004539, 0.26514888, -0.15079662, 0.04214227, -0.027273783, -0.027950313, 0.19614808, 0.18510003, -0.10346252, -0.029836183, 0.09174428, -0.0088710375, -0.18273513, 0.06601674, 0.009983851) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.08476211, 0.043996535, 0.056711517, 0.009976895, 0.07039107, -0.024862664, -0.059921104, 0.046850603, 0.04983447, 0.04863198, 0.21777405, -0.0576961, 0.045321796, -0.0060038245, 0.096396215, -0.10842004) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.15746164, 0.041757874, 0.035169285, -0.1734288, -0.24219254, -0.13318908, 0.2272079, -0.02902605, 0.07750601, -0.1467191, -0.12296749, -0.07533314, -0.07073083, 0.17909113, 0.04789308, 0.17245363) * go_0(0.0, -1.0);
|
||||
result += mat4(0.057547905, 0.1464685, -0.33115456, -0.26956198, -0.26298407, -0.059824817, 0.022509675, -0.09251868, 0.36277944, -0.2072429, 0.21095088, -0.45492023, 0.07428653, 0.1593302, -0.2945834, 0.12825087) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.1318458, 0.27804148, 0.037600737, 0.12047866, 0.0065036337, 0.0017241207, 0.060497303, -0.14786585, -0.15149063, 0.02731698, 0.048886403, -0.0025970868, -0.026979815, 0.07348884, 0.015636757, -0.107966796) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.079988025, -0.01626299, 0.06517438, 0.086406484, -0.1484504, 0.070595, 0.20620634, 0.09713373, -0.13620836, 0.012067949, -0.00068703433, -0.038030174, 0.22300471, -0.0012400965, -0.014827909, -0.08927486) * go_0(1.0, -1.0);
|
||||
result += mat4(0.15634936, 0.052028038, 0.038081627, 0.12720168, 0.07342066, -0.04318368, -0.0065998454, 0.12109317, -0.45398173, 0.03666754, -0.17773737, 0.038516667, -0.13009632, -0.007457001, -0.013938809, 0.09776142) * go_0(1.0, 0.0);
|
||||
result += mat4(0.029636936, 0.12864171, 0.11347291, -0.11812842, -0.0870342, 0.035678383, 0.050338242, 0.045754932, -0.07072752, 0.010447726, 0.039642975, -0.08795004, -0.1191525, 0.00967509, 0.13485421, -0.053204738) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.011072695, -0.09613245, -0.09094804, 0.028029291, -0.04031162, 0.15690295, 0.25094184, -0.21776834, 0.06524669, 0.06412185, -0.052852992, -0.08097702, -0.039127756, 0.036357917, 0.104585476, 0.25095442) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.08328618, -0.006246033, 0.099708706, -0.014916097, 0.17727195, 0.4369228, 0.14760216, 0.06707674, 0.025167737, -0.022487842, -0.038962565, 0.15380669, 0.08125089, 0.09844594, 0.33538374, -0.003161368) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.0128195705, -0.05475118, -0.037705053, -0.0012077648, -0.17425515, 0.091487505, -0.12909423, 0.0074876705, 0.13438368, 5.778033e-05, 0.04563314, -0.12185897, -0.053612474, -0.049824294, -0.12851205, 0.12856449) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.025741795, 0.01867236, -0.00027440622, 0.10502768, 0.27042285, -0.14947751, 0.11143123, 0.2575913, -0.07414089, -0.33919522, -0.13194235, -0.20088726, 0.23121537, -0.08197353, 0.06693911, 0.015411386) * go_1(0.0, -1.0);
|
||||
result += mat4(0.09143717, 0.22842278, 0.06501074, -0.20009698, -0.042117566, -0.23452093, -0.074082755, -0.10612558, 0.077631965, 0.08343657, -0.07657599, -0.43297377, 0.7092466, -0.16272525, 0.17222248, -0.056038965) * go_1(0.0, 0.0);
|
||||
result += mat4(0.081200436, 0.046752565, 0.028254949, 0.18820632, 0.096592255, 0.05896745, 0.14845169, 0.034777895, 0.07195204, -0.1908046, -0.015341971, 0.02606145, -0.010377239, 0.0755547, -0.15285216, 0.047916733) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.06825636, -0.049540907, -0.024328846, 0.03506251, 0.2060094, 0.054119263, -0.06671269, 0.052428722, 0.055792283, -0.14336903, -0.03180757, 0.013760968, -0.037398104, -0.06880077, -0.023608573, 0.0360965) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.16937497, -0.30156836, 0.0021435453, 0.025772978, -0.17990975, 0.046133514, -0.32447076, -0.083382785, -0.081322014, -0.022132374, -0.05319431, 0.11794733, 0.08943906, 0.12927428, 0.105764806, -0.051034793) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.011012306, 0.047636557, 0.050260928, 0.051847618, 0.010985655, -0.13752967, 0.023869954, 0.07011459, -0.18244945, 0.07239806, -0.013638856, -0.026982805, 0.11395993, -0.031304818, -0.08714153, 0.077115685) * go_1(1.0, 1.0);
|
||||
result += mat4(0.08707592, 0.2265186, 0.13363098, -0.039588258, -0.029561255, 0.019238092, 0.024606103, -0.0019022018, -0.062285982, -0.0629511, -0.03753033, 0.109805316, 0.016018672, -0.08284564, -0.04092752, -0.030386891) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.0016500859, 0.01616536, -0.099148355, 0.24161765, 0.028064307, -0.028680569, 0.054400917, -0.1978921, -0.08584302, -0.096797146, -0.06546965, -0.09342837, 0.030265866, 0.07057579, -0.02080932, 0.053178705) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.030304352, 0.047440585, -0.04248429, 0.08568772, -0.051317703, 0.036739342, 0.00865767, -0.018183297, -0.07335176, 0.025001721, -0.068509035, 0.1814819, -0.09756565, -0.024179723, -0.05959287, 0.0352454) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.023015196, -0.022870664, -0.12028372, -0.111095205, 0.11065281, -0.19900022, -0.24012049, -0.017028643, -0.13484617, 0.050107025, 0.10741765, 0.037951697, 0.013090438, -0.0010045726, -0.029447839, -0.1859787) * go_2(0.0, -1.0);
|
||||
result += mat4(0.17922719, -0.24138594, -0.44595388, -0.032014426, 0.06897096, 0.07125395, 0.1944457, -0.035794795, -0.24022278, -0.13230884, -0.1277025, 0.21229011, -0.12249393, 0.06141907, 0.2687936, -0.26896995) * go_2(0.0, 0.0);
|
||||
result += mat4(0.0397242, -0.30710965, 0.28815824, -0.06642567, -0.07588877, -0.019552408, 0.0057806037, 0.11465521, 0.03560534, -0.10640553, 0.023589289, -0.16667193, 0.02066607, -0.01026633, -0.02655378, 0.082493655) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.007902949, -0.08501038, -0.029395591, -0.07072227, -0.01800967, -0.14564751, -0.08372804, -0.049974415, 0.1756957, -0.02042449, -0.04413007, -0.016873527, -0.2385717, -0.001741017, 0.08298281, -0.019873247) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.01803727, 0.0642893, 0.21513617, 0.066888265, -0.042107955, -0.123470366, 0.045296013, -0.11958806, 0.48208967, -0.027188249, 0.12136116, 0.05246265, 0.13522038, -0.016297493, 0.028486907, -0.059840377) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.1373251, -0.11281026, -0.06418318, 0.08444032, 0.062874556, -0.009133875, -0.049571835, -0.042995855, 0.12483249, -0.025967957, -0.11202483, 0.09862257, 0.099986054, 0.009230306, -0.09042664, 0.046612263) * go_2(1.0, 1.0);
|
||||
result += mat4(0.03203309, 0.106030256, 0.045741174, -0.020529225, -0.028610658, -0.055219248, -0.21404657, 0.07746393, -0.059359375, 0.0033258004, -0.0054513607, 0.06856653, 0.18043655, -0.119936846, -0.05639265, -0.10240379) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.0004331875, 0.10426754, -0.008130048, 0.012795991, -0.14372933, -0.40797862, 0.105197415, -0.0041354536, -0.079792455, 0.0914027, 0.012418237, -0.11449173, 0.020261409, -0.14681602, -0.13355242, 0.18290488) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.052306626, 0.010864275, -0.072627716, -0.009773121, 0.09484167, -0.09631301, 0.14896165, -0.21220942, -0.11994051, -0.002957136, -0.118194886, 0.08661347, 0.10005298, -0.029620873, 0.101668894, 0.0242806) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.055188183, -0.06322889, 0.12994595, 0.03140751, -0.092755616, 0.04239107, 0.18460171, 0.08471877, 0.014203371, 0.13608724, 0.035351243, -0.07883493, -0.10067456, 0.14417742, 0.0054235114, 0.100745104) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.043811034, -0.16055201, -0.11927185, 0.20517266, 0.16734722, 0.27720267, 0.1205665, 0.045803893, -0.07874647, 0.06764307, -0.11157022, 0.080770165, -0.044105835, -0.03276538, -0.10945451, 0.100562036) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.044731796, -0.12854387, -0.061937924, -0.21604767, -0.036132332, -0.024353411, -0.16718283, 0.14903957, -0.11620588, 0.14563644, 0.23363836, 0.08400659, 0.15248756, -0.1424437, 0.112882614, -0.04096889) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.0486021, -0.05714939, 0.042517707, -0.06106919, -0.12970918, -0.071898215, -0.044727243, -0.026308542, 0.05687118, -0.0394057, -0.109454155, -0.0021216893, 0.018588595, 0.08061093, 0.0500373, -0.0034918839) * go_3(1.0, -1.0);
|
||||
result += mat4(0.11269324, -0.17924047, -0.12965205, -0.07287767, -0.015830642, -0.044497102, 0.20014328, -0.14054494, 0.1232692, 0.2395109, 0.14093149, 0.03518561, -0.14088139, -0.09045081, -0.07283352, 0.053434785) * go_3(1.0, 0.0);
|
||||
result += mat4(0.020512339, 0.026349569, -0.06666101, 0.05554806, -0.03044066, 0.26656216, 0.019155584, -0.12118906, 0.087923005, -0.1716557, 0.050843164, 0.037432503, -0.030232614, 0.030457936, 0.04232163, -0.066400655) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.0216415, 0.09015036, -0.030761974, -0.26541537);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf1
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.04688368, 0.13853125, 0.1714716, -0.03034447, -0.08090605, 0.1225867, 0.17535992, 0.012508419, -0.0010665918, -0.07481546, -0.15541986, 0.0671128, -0.029307734, -0.076674186, 0.03925896, -0.07140553) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.13273083, 0.062933214, 0.04200143, -0.0080243945, -0.120439716, -0.090192355, -0.022639645, 0.00020024918, -0.11211478, -0.12949537, 0.025783822, 0.009155746, 0.01004339, -0.0661901, 0.10630156, 0.053137038) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.07113487, -0.16011865, -0.10838903, -0.0034704183, 0.110606894, -0.14915739, 0.036511585, -0.003103608, -0.0551775, -0.13140677, 0.05270299, 0.12139221, 0.02226174, 0.008415268, -0.06647426, 0.118130066) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.045172617, -0.0020388453, -0.27287582, 0.002428232, -0.2833772, 0.13788106, 0.073339015, 0.10666715, 0.08455194, 0.16499293, 0.089058325, 0.008815447, 0.034657538, -0.109856166, -0.11499077, -0.02918854) * go_0(0.0, -1.0);
|
||||
result += mat4(0.07910854, -0.26334837, -0.3246593, -0.08246522, 0.09211476, 0.40793833, -0.09658794, -0.14430091, -0.50632644, 0.087234974, 0.26298127, 0.3687086, 0.06492316, 0.23082961, 0.18233871, -0.09283792) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.022744032, 0.21690565, 0.2694824, -0.12230013, -0.07969618, 0.21595429, -0.034979805, 0.008938489, 0.21289209, -0.446482, -0.042927746, -0.13587558, -0.032581557, -0.07182814, -0.054092336, -0.009542036) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.0034912943, -0.080354184, -0.08577375, -0.1521193, 0.09809233, 0.034529503, -0.100664355, 0.008191219, -0.014303411, -0.02862216, -0.18669915, -0.12384598, 0.046499267, 0.093707144, 0.10661308, 0.15079576) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.031025652, -0.0384342, 0.14258307, 0.25531343, 0.0075049917, -0.03966595, 0.062381975, 0.19593526, -0.2868182, 0.03162008, -0.4391041, -0.524017, -0.034463473, -0.0066741486, -0.24586639, 0.10521736) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.07452321, -0.0227877, -0.025402244, 0.115727395, -0.039511252, -0.07785703, -0.013689458, 0.0066024344, -0.052957747, 0.011206241, -0.0021671024, 0.077190824, -0.11709912, 0.046635598, 0.123751156, -0.03712064) * go_0(1.0, 1.0);
|
||||
result += mat4(0.055411004, -0.0020031065, 0.06685547, -0.018829947, -0.06378933, -0.18389674, -0.0023551763, 0.0670314, 0.13038594, 0.0601923, -0.03035789, -0.019537423, -0.014483204, -0.056800704, 0.08663347, -0.106859975) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.06603686, 0.07360526, -0.0072026253, -0.06778907, -0.039178446, 0.012397263, -0.13482279, 0.05745685, -0.055182382, -0.10545766, 0.003857615, 0.041947857, -0.15239377, 0.041826613, 0.058879383, -0.0042669442) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.0697229, -0.010702144, -0.032265816, 0.013317131, 0.105028264, 0.21032134, 0.06845646, -0.018358687, 0.064568676, 0.08437135, -0.000723181, 0.1324007, 0.05527932, -0.049871888, -0.10125047, -0.005040889) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.006467578, -0.05120533, -0.011780779, -0.011742203, -0.34242442, -0.020819988, 0.17381702, -0.059836414, -0.028882682, 0.23210457, 0.16579404, -0.03708216, -0.23541835, -0.03290251, 0.029319672, 0.26189178) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.30955994, -0.06408282, -0.16872866, 0.10767772, -0.041430887, 0.051697977, 0.12523535, -0.060389146, 0.026289431, 0.06359533, 0.13526368, 0.2479901, -0.3263977, 0.10216362, -0.0030894123, 0.046437826) * go_1(0.0, 0.0);
|
||||
result += mat4(0.10061438, -0.17047118, -0.21593021, -0.023389054, -0.17507865, -0.30822313, -0.22044766, 0.16078933, 0.07099252, -0.11573018, 0.24712858, -0.0659458, -0.037504572, -0.12297423, 0.03342632, -0.058119852) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.020957774, -0.0224927, 0.04069268, -0.07911167, 0.074009344, 0.065916434, 0.008222278, 0.11625076, -0.25299504, 0.03357169, -0.021988, 0.015821831, -0.0021187372, -0.030700417, -0.004374924, 0.027358979) * go_1(1.0, -1.0);
|
||||
result += mat4(0.06549052, -0.048067164, 0.05489091, -0.28851983, 0.13378961, 0.026875904, -0.09877994, -0.19947459, -0.1274035, -0.022928834, -0.26344195, -0.025870804, 0.022505255, 0.0070861108, 0.121051334, -0.025964163) * go_1(1.0, 0.0);
|
||||
result += mat4(0.059426542, -0.0327433, 0.2313695, -0.07046268, 0.20479666, 0.027021704, 0.2564928, -0.11689885, -0.07407976, -0.019611249, 0.093463086, -0.121553615, 0.035009407, -0.008135333, -0.075931996, 0.047803063) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.059434246, -0.1652242, -0.124611154, 0.04743711, 0.10530296, -0.13869187, -0.036534663, -0.035206333, 0.06067593, 0.06126907, 0.120151915, -0.06722673, 0.008103894, 0.037225723, -0.007520425, 0.065720856) * go_2(-1.0, -1.0);
|
||||
result += mat4(-3.6759695e-05, -0.036789574, 0.013370567, -0.037871476, -0.013454664, 0.15086569, 0.10164699, 0.057703357, -0.12871023, 0.12827681, -0.055057358, -0.040753044, -0.0142621, 0.08563361, -0.04615499, -0.03130452) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.117965914, 0.09056485, 0.07272314, 0.009695964, -0.11331058, 0.07467256, -0.08291521, 0.00937355, -0.04097737, 0.07752905, -0.017335521, -0.12539999, 0.039462104, -0.0007037007, 0.06034812, -0.09497377) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.20828065, 0.0400099, 0.047638226, -0.046423353, -0.026133502, 0.098207295, 0.056742374, 0.017029466, -0.058164768, -0.046973787, -0.17328712, -0.0012984811, 0.050085854, 0.11296557, 0.12639083, 0.058543045) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.098907426, 0.22031747, 0.101559944, 0.06616554, 0.026110496, 0.56487054, 0.23754556, -0.07540935, 0.31768414, -0.47653618, 0.015073956, -0.33731326, 0.087285936, -0.24593173, -0.26141426, 0.15003823) * go_2(0.0, 0.0);
|
||||
result += mat4(0.046026446, -0.13767281, 0.064847544, 0.07717139, 0.08544123, -0.11092969, 0.072325274, 0.010849038, -0.3055905, 0.66436774, 0.1434729, 0.0494463, 0.07115603, 0.083811216, 0.020431712, 0.06537088) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.15532711, 0.030139687, 0.040853374, 0.11089222, -0.08150315, -0.015851755, -0.06787692, 0.096075505, -0.011956207, -0.0017758606, 0.1277494, 0.16156575, -0.038588695, -0.0626418, -0.041797023, -0.19467135) * go_2(1.0, -1.0);
|
||||
result += mat4(0.12917455, 0.017410474, -0.20125067, -0.08040003, -0.13494664, 0.17789102, -0.19909395, 0.08441434, 0.078570575, -0.06330619, 0.23767303, 0.5442659, -0.009227878, -0.021818208, 0.14318731, -0.09042824) * go_2(1.0, 0.0);
|
||||
result += mat4(0.097801, 0.09345441, 0.17846581, -0.14773296, 0.06536365, 0.07642184, -0.011880635, 0.02086135, 0.013336972, -0.053295113, -0.13410404, 0.027241753, 0.087728985, -0.044033397, -0.13098569, 0.009423933) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.02488427, 0.0134966355, -0.0075000813, 0.07272353, 0.015842725, 0.13765687, 0.028079558, -0.08384948, -0.06666623, -0.023220664, 0.025091043, -0.055167805, -0.18826278, 0.04423603, 0.13499942, 0.059128854) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.01935146, -0.030980906, -0.031569187, -0.0036869382, 0.036753897, 0.118464164, 0.15871695, -0.09842428, 0.023324292, 0.071796335, -0.07869346, -0.10751301, -0.2588698, 0.064011686, 0.17386378, -0.039197855) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.08590827, 0.005497696, -0.026512025, 0.015661815, 0.1102415, -0.08268483, -0.0032903247, 0.10049029, -0.008157236, -0.035823178, -0.017570151, -0.081716835, -0.3531045, 0.010005245, 0.017141227, -0.016376914) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.16617337, -0.007689783, 0.00954665, 0.07117733, -0.001669262, -0.012331606, 0.051613946, 0.062780835, 0.06123557, -0.20243123, -0.19181818, 0.032895602, 0.19760677, 0.004464939, 0.12754539, -0.27360034) * go_3(0.0, -1.0);
|
||||
result += mat4(0.15006685, -0.083587274, -0.03215495, -0.16992462, -0.011944293, 0.058361508, -0.088097006, 0.023880545, -0.04168166, -0.06960282, -0.092672385, -0.057278465, 0.23540072, -0.1721208, -0.018213503, -0.23494521) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.124885194, 0.1905868, 0.11108704, 0.03163991, 0.11383064, 0.101223364, 0.069428995, -0.14298953, -0.07609092, 0.13704266, -0.07749446, -0.0005389336, -0.04617235, 0.18011934, 0.08350316, 0.09416366) * go_3(0.0, 1.0);
|
||||
result += mat4(0.073356606, 0.067966126, -0.21285574, 0.0782625, -0.0034364646, -0.032581426, -0.05538558, -0.1317288, 0.14552782, -0.1132393, 0.13063973, -0.00833602, 0.0026844777, 0.028135289, -0.02536825, -0.028372496) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.318728, 0.07862527, -0.12176221, 0.35010242, -0.029198067, 0.016302662, 0.17667587, 0.12605923, 0.1556697, -0.06061443, 0.05843511, 0.10891248, 0.01267106, -0.018492714, -0.15945031, -0.050723754) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.21555941, -0.016813517, -0.084676236, -0.07545412, -0.14518794, -0.014592766, -0.2446481, 0.0530632, 0.0847341, 0.12342537, -0.028644923, 0.083479315, -0.04179012, 0.0025225023, 0.16006976, -0.026940256) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.060742114, -0.037577342, 0.055704296, 0.03134311);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.13129333, -0.022117995, -0.009753253, 0.020439912, 0.044090994, -0.0916335, 0.0036765633, -0.11719207, -0.06413809, 0.04079378, -0.00085516454, -0.06306388, -0.12660664, -0.054126263, -0.005513979, 0.06364538) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.028422508, 0.23270117, -0.28674677, -0.10820166, 0.024321957, -0.0811145, -0.07290707, -0.02125165, -0.064260505, 0.052076746, -0.009654081, 0.08363882, -0.02037171, 0.15006389, 0.121593125, -0.011237004) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.14672333, 0.015381624, 0.1028172, -0.041823238, 0.0072677187, -0.042953942, 0.06426537, -0.0938381, -0.05990813, -0.04599802, -0.11264726, -0.027826328, -0.058160868, 0.10747306, -0.07327458, 0.07998872) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.08702181, -0.03750975, -0.045659006, 0.04488332, 0.09102003, 0.066556975, -0.04353586, 0.08994567, -0.13561495, -0.10653702, 0.006989605, 0.028230097, 0.07177144, 0.2938447, -0.00943923, 0.022120917) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.1801194, -0.11119162, 0.1977298, -0.247902, -0.16654298, -0.07423158, 0.114130594, 0.0014401592, 0.006954727, -0.09810646, -0.051310766, 0.19487657, 0.2545855, -0.06328558, -0.04617056, 0.09444692) * go_0(0.0, 0.0);
|
||||
result += mat4(0.011378825, 0.16044368, 0.017211074, 0.14472178, 0.032992378, -0.008925819, 0.035120245, -0.012409223, 0.074333005, 0.1178002, -0.128956, -0.13624239, -0.2791275, 0.21457297, -0.1476131, 0.04874687) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.03491764, -0.061763793, 0.05779039, 0.0054837577, -0.023937583, 0.08281698, 0.032306053, -0.014566218, 0.12738499, -0.0132100545, -0.051833414, 0.0057818824, 0.012158851, -0.20231532, -0.0043795826, 0.10285843) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.22269921, -0.15135509, -0.039143335, 0.033390045, 0.06770212, -0.14538582, -0.08011057, 0.03796648, -0.025913516, 0.13925864, 0.18309896, 0.012709204, -0.24912506, 0.3217706, 0.0394195, 0.017977878) * go_0(1.0, 0.0);
|
||||
result += mat4(0.00080196525, 0.059145816, 0.05720508, 0.0056548906, 0.005168018, 0.09938438, 0.0200503, -0.05516137, 0.061309986, -0.019621318, -0.1541441, 0.019540716, 0.030571707, -0.09054893, 0.032851614, -0.27210873) * go_0(1.0, 1.0);
|
||||
result += mat4(0.27061436, -0.114008114, -0.0020118617, -0.1656827, 0.09770587, 0.029897455, -0.03307522, -0.04661818, 0.033011347, 0.18498488, -0.05162084, 0.087471776, -0.24665618, -0.12538423, -0.08123797, -0.010210389) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.075188264, 0.0020608555, 0.18558815, 0.041179713, 0.11232638, 0.05507779, -0.19599183, 0.027942855, 0.06199144, 0.22141005, -0.06121163, 0.014993597, 0.24105869, -0.019737717, -0.112485714, 0.0157406) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.09425698, 0.0207658, 0.12074599, 0.009430481, 0.11889248, -0.025782838, 0.0034711843, 0.05113582, 0.012531833, -0.0018606635, -0.09137569, 0.018120576, 0.4051155, 0.02222076, -0.16001017, 0.10981527) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.03582557, 0.014994796, -6.4688604e-05, 0.24618183, -0.11697727, 0.24388117, 0.038502026, -0.3511993, 0.101741396, -0.10748137, 0.035059888, -0.017535849, 0.09450039, 0.06541661, 0.12149035, 0.28798738) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.27143848, 0.017990451, -0.69144464, 0.037944376, -0.04551905, 0.09263134, 0.4259611, -0.14107811, -0.10641847, 0.23065196, 0.040813655, -0.07789163, 0.3087666, 0.08190437, 0.16409059, -0.06455426) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.08290655, -0.35286915, -0.18082355, -0.32229406, 0.1608227, 0.030915622, 0.09207708, 0.02655054, 0.039464593, 0.026095424, 0.052584656, 0.033881903, -0.01751319, -0.0011676399, 0.04002607, 0.1630013) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.012021132, 0.12163766, -0.07410629, -0.06879096, 0.017859738, -0.039261997, -0.028677614, -0.23610398, -0.15963873, -0.0006119958, 0.11275506, 0.0082659265, 0.05677582, 0.08676638, -0.08669759, -0.10475464) * go_1(1.0, -1.0);
|
||||
result += mat4(0.12792721, 0.06888765, 0.31803077, 0.26002547, -0.067599155, -0.011822328, -0.2589909, -0.30024147, 0.11076704, 0.15200609, -0.018180368, -0.19146141, 0.22298847, 0.059484895, 0.034478076, 0.15610938) * go_1(1.0, 0.0);
|
||||
result += mat4(0.0870121, -0.016420847, -0.011579898, 0.097182855, -0.120095566, -0.06843338, -0.043460473, -0.060684606, -0.027540063, -0.008499213, 0.033570655, -0.06866259, 0.01429712, -0.07424434, 0.0009466247, 0.09142678) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.03781424, 0.04587032, 0.03744051, 0.02712279, -0.051038064, 0.0669144, -0.02640278, 0.12384894, -0.0022533627, -0.010022036, 0.07536463, -0.030489929, 0.09418577, 0.155089, -0.011290433, -0.02102941) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.0053278613, -0.07160643, 0.039028414, 0.04123311, -0.10693177, -0.1170874, 0.07230816, -0.033255517, -0.119176835, 0.0786526, -0.11880206, -0.11354601, -0.037539184, 0.14404313, 0.069760695, 0.024738638) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.03413808, -0.006487654, 0.10006853, 0.22228058, -0.13796462, -0.14042488, 0.04017443, -0.031790894, -0.06673143, 0.009888688, 0.08831443, -0.0045771743, -0.028375361, -0.04704813, 0.07128581, -0.07012518) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.06954315, -0.23728988, -0.14192343, -0.08236467, -0.2552115, 0.04102959, -0.06355397, -0.08340241, 0.17617856, 0.20281969, -0.16249381, 0.10843737, -0.04392261, -0.08587206, 0.053069845, -0.15482199) * go_2(0.0, -1.0);
|
||||
result += mat4(0.124981806, 0.12828638, -0.061472785, -0.20108232, -0.14905351, -0.40766275, -0.35427195, -0.13183996, 0.09307428, -0.07697028, 0.06702549, -0.22656697, 0.019868268, -0.19361132, 0.08784669, 0.20249842) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.004661343, -0.09333453, -0.24876262, -0.07906779, 0.110697776, -0.37069768, -0.042212646, -0.0046135853, -0.2254257, -0.023392014, 0.031476703, -0.045574382, -0.12675518, -0.076056994, -0.08228006, -0.040303517) * go_2(0.0, 1.0);
|
||||
result += mat4(0.16182694, 0.0512523, 0.051189836, 0.048962783, -0.05156489, -0.17987493, -0.012037288, 0.06953726, -0.09458492, 0.1610021, -0.004063283, -0.032922342, 0.08995396, 0.1939926, -0.018710036, -0.08153231) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.064830944, 0.06121252, -0.18886387, -0.12976822, -0.031117212, 0.12219633, 0.19070715, 0.12495262, -0.11994464, -0.24687837, -0.08425294, -0.016920334, -0.13286817, -0.3260188, -0.11776061, 0.1651019) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.17652592, 0.002499805, -0.030541016, -0.01393431, 0.031418208, 0.08209422, 0.12430871, 0.4387016, -0.108871914, -0.09041422, 0.031226631, -0.1638517, 0.20756467, 0.014476537, -0.012701195, -0.03440563) * go_2(1.0, 1.0);
|
||||
result += mat4(0.005320072, -0.0032291536, -0.017209187, 0.031944863, -0.2479921, -0.24433962, -0.13832912, 0.07835928, -0.17707248, 0.028202811, -0.19121435, 0.164587, 0.123152815, 0.0050288937, 0.084104605, -0.0380019) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.16008669, -0.018608516, -0.013778938, 0.033447385, -0.01242472, -0.070916265, 0.026909694, -0.07318777, 0.15158044, 0.12047607, -0.1709358, 0.2031767, 0.0025611701, -0.21457459, 0.2791286, 0.10159932) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.14320926, 0.020023825, -0.0484187, 0.011563084, -0.2640472, -0.013056275, 0.004234292, -0.095376395, 0.28363484, -0.0058227647, -0.0777649, 0.05238444, 0.41757923, -0.07081097, 0.012567031, -0.13029522) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.07266207, 0.042793367, -0.08212271, -0.23401663, -0.19457819, 0.4191269, -0.03095442, 0.15339781, -0.28451788, 0.09316364, 0.10231693, -0.22844811, 0.111623526, 0.120017685, 0.18777381, 0.014420896) * go_3(0.0, -1.0);
|
||||
result += mat4(0.15037206, -0.29763284, 0.2601235, 0.0193363, 0.13686465, 0.009907918, -0.37781665, 0.04916627, 0.14114739, 0.5043813, 0.0447959, -0.029427614, 0.041768756, 0.27211213, 0.14163221, 0.086162075) * go_3(0.0, 0.0);
|
||||
result += mat4(0.19159287, 0.21363218, 0.15053211, 0.08992885, 0.100828275, 0.09379921, 0.030783929, 0.11664482, -0.059145752, -0.19400764, -0.09351283, -0.016430443, -0.12910964, -0.067078374, 0.11760082, 0.121194765) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.055059325, 0.09299572, 0.06848913, 0.06334532, -0.1476285, 0.111801244, -0.033960916, 0.06474366, -0.04952303, 0.27885208, -0.052447475, 0.09226763, -0.15024844, -0.0033919013, 0.013498364, 0.09135676) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.017010042, -0.122343406, -0.19097193, -0.27957183, -0.18206005, 0.102321096, 0.22794476, 0.0439245, -0.23710132, -0.08070259, 0.17377135, 0.23811814, 0.17799385, 0.049567625, 0.1470908, 0.07329385) * go_3(1.0, 0.0);
|
||||
result += mat4(0.0038071256, 0.19454515, -0.01222965, -0.07390379, -0.0532754, 0.03942833, 0.123840906, 0.023459576, -0.0658742, -0.023957543, -0.14682837, 0.1221027, -0.010986398, -0.066184506, 0.03026491, -0.0638446) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.06427697, -0.00039365015, 0.011889719, 0.060232002);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf1
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.012110923, 0.07818654, 0.07964548, 0.11885079, -0.07694473, -0.01378252, 0.006632789, -0.12876098, 0.0069211307, 0.022278586, 0.069553085, 0.16569804, -0.11123615, 0.06125189, -0.11232848, 0.1559266) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.3261174, -0.25586754, 0.21129315, 0.3135101, 0.1509055, 0.0044283345, 0.024674175, -0.08000473, 0.01213029, 0.09093019, 0.04942677, 0.09806723, -0.16454464, -0.14433062, -0.058094524, -0.060819894) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.023174008, 0.02858724, 0.07685972, 0.036857616, -0.10415571, 0.10241035, -0.01893166, 0.02065923, 0.058356714, 0.096426114, -0.03772327, -0.1529002, 0.13740575, -0.048291504, -0.06152548, -0.15199897) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.029300174, -0.13222043, 0.0139825605, -0.02274408, 0.062944874, 0.028447356, 0.05960515, 0.034447193, 0.03133432, -0.019283533, -0.024591971, -0.0043914663, 0.15245225, 0.006851478, -0.051783554, 0.17453748) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.09125915, 0.081739366, 0.01196335, 0.23130219, -0.22557035, -0.13537665, 0.0022028848, -0.043430023, 0.22759882, 0.07920754, -0.027986467, -0.14051494, -0.19557038, -0.03585936, -0.4258294, -0.03856216) * go_0(0.0, 0.0);
|
||||
result += mat4(0.18511422, -0.09368415, 0.1551229, 0.04322566, -0.023400841, -0.02261204, 0.15129441, -0.007954805, -0.10739125, 0.019459398, 0.013128325, 0.018073296, 0.20886365, -0.20662378, -0.03814699, -0.09272838) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.027352437, -0.039882626, 0.12598103, -0.093930446, 0.030846786, -0.09325075, -0.009084744, -0.024584265, 0.07159868, 0.14162529, 0.19019091, 0.058855128, -0.09880401, -0.01843218, 0.14753596, -0.2449532) * go_0(1.0, -1.0);
|
||||
result += mat4(0.06565521, 0.09150168, -0.08654865, 0.0829788, -0.07596146, -0.01815166, -0.08786775, -0.03477514, 0.20538878, -0.012766377, 0.020719538, 0.088188395, -0.034300096, 0.29972988, -0.20005241, 0.018425167) * go_0(1.0, 0.0);
|
||||
result += mat4(0.11713916, 0.024167519, 0.05167596, -0.0027117804, -0.016994188, 0.048177514, -0.012556207, 0.010979094, 0.09098878, 0.028514355, 0.06063336, -0.06624107, 0.012754856, 0.013208708, -0.061374772, -0.0025992664) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.09053513, 0.03183455, 0.017340872, 0.12934409, -0.022161964, -0.0015361432, -0.049972344, -0.12763855, 0.12779881, -0.04697911, 0.018968226, -0.119873665, 0.05462772, -0.13919477, -0.10226718, -0.2540179) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.29912186, -0.09291771, 0.050926663, 0.49361777, 0.21372582, 0.076717265, -0.058968987, -0.1572678, 0.3194591, -0.120582424, 0.03942037, 0.023128232, 0.24321598, 0.07046334, -0.21204855, -0.648296) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.05366883, -0.020366706, 0.020979457, -0.06893884, 0.04837168, 0.017253762, 0.008874203, -0.020785445, -0.20425391, 0.060179923, 0.046167206, 0.09863377, -0.14381303, 0.038928367, -0.06590863, -0.18408588) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.07099762, 0.2029403, -0.033945918, 0.15202214, 0.0901113, -0.27336198, -0.17693861, -0.16206753, -0.17642029, 0.09400492, -0.11165698, -0.07863893, -0.16306102, -0.056210615, 0.22173557, 0.013508989) * go_1(0.0, -1.0);
|
||||
result += mat4(0.08541511, -0.27093616, -0.35273993, -0.48919773, 0.038383547, -0.16013749, 0.012996215, -0.03434873, 0.07024113, -0.28971404, 0.10623425, -0.0019642068, -0.062374946, 0.3291145, 0.22468035, -0.42971882) * go_1(0.0, 0.0);
|
||||
result += mat4(0.020427933, 0.15062793, 0.08308975, -0.025095072, 0.030093266, -0.09649862, -0.03382388, -0.0016017791, 0.105402954, 0.020693144, -0.051065, 0.07704679, 0.02864139, -0.00135146, 0.03762216, 0.029277142) * go_1(0.0, 1.0);
|
||||
result += mat4(0.01700994, 0.12214317, 0.06749582, 0.07354159, -0.093085855, -0.065021954, 0.010773045, -0.00095128635, -0.045384295, -0.072611265, -0.043900184, 0.049471326, 0.029131187, 0.03180158, -0.13313527, 0.05280797) * go_1(1.0, -1.0);
|
||||
result += mat4(0.14751251, -0.15087761, 0.09932281, -0.099232934, -0.062390897, 0.112391844, -0.09159478, 0.15856399, 0.034708973, 0.01819943, -0.02730164, -0.13562973, -0.05687333, -0.0114601655, 0.07025971, 0.02496533) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.0117268525, -0.026162883, 0.07481553, 0.13420302, 0.029870516, 0.07405776, -0.06379041, 0.09631234, -0.07754842, 0.035888605, 0.0034764851, -0.040771756, -0.092022054, -0.034230903, -0.02281844, -0.0028173258) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.059846643, 0.016772347, -0.02287152, 0.07036337, -0.024946844, 0.09826078, -0.068491876, 0.20852126, 0.073890835, -0.058288682, 0.013093785, -0.05776076, 0.0516503, 0.052794468, 0.10837015, 0.038539834) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.16391893, -0.008062687, -0.35022175, 0.2510062, -0.15820411, 0.048403125, 0.024878092, 0.037888516, -0.035924178, -0.068953894, -0.025386479, 0.24405715, -0.018495679, -0.051277515, 0.14754932, -0.031538483) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.038429607, -0.047140498, -0.018157095, -0.029318782, -0.04094171, -0.11870087, 0.11214255, 0.07142628, 0.021007229, -0.005681072, 0.1662777, 0.10829575, 0.112268396, 0.03567479, -0.06738845, 0.0032037434) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.032217573, 0.2102397, -0.20617546, -0.07920811, 0.12918773, 0.054486286, -0.13656865, 0.05806265, 0.01963165, 0.049910642, 0.15538268, 0.10724465, -0.09697837, -0.03070673, -0.0071386313, -0.11899626) * go_2(0.0, -1.0);
|
||||
result += mat4(0.130827, 0.0051715383, -0.07212691, 0.45726067, 0.2773031, 0.2973666, 0.3951691, 0.01333662, -0.14561643, 0.04508669, 0.121690124, 0.13326228, -0.22579186, 0.058161184, 0.09281702, -0.00079749606) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.00771113, 0.09912341, -0.41895548, -0.06705759, 0.029148718, 0.052991726, 0.18665347, -0.031787418, 0.23053595, 0.09444956, 0.10691037, -0.06325714, -0.05335701, 0.1917427, -0.0065284846, 0.032622546) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.056801565, -0.019131258, -0.0939022, -0.08130343, -0.11051993, 0.0035269214, -0.047361933, -0.0543875, 0.10854369, 0.06445185, 0.016828364, -0.022595318, 0.1450623, 0.033027507, -0.020425137, 0.16169788) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.08747717, 0.07770065, 0.018155783, 0.07160794, 0.09860347, -0.04329888, -0.0043579484, -0.2014418, -0.060260013, 0.0036374568, -0.17566042, -0.2268221, 0.001273691, -0.2609373, -0.19417606, -0.04102927) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.086845055, -0.114253804, -0.13433142, -0.025941795, -0.0155711295, -0.13578776, 0.12059696, -0.08760523, -0.0057348222, 0.12164273, 0.07270617, -0.06352636, 0.08894258, 0.04140841, 0.1230304, -0.030357126) * go_2(1.0, 1.0);
|
||||
result += mat4(0.03320213, 0.015911903, -0.06288296, -0.121976145, 0.2713457, 0.13913193, -0.092420585, 0.105714336, 0.10294281, -0.04591945, -0.11767934, 0.032249406, -0.06506192, -0.04639334, 0.08137017, -0.031746846) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.13717805, 0.0071242675, -0.077256985, -0.14974317, -0.08467893, -0.20126395, -0.06240603, 0.09554399, -0.075844854, 0.28380412, 0.046030026, 0.053188596, 0.50943077, 0.1179795, 0.32203588, -0.06712207) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.18528835, 0.0016975187, -0.0041140947, 0.11234392, -0.34049067, -0.056880493, -0.04325441, 0.09905571, 0.10978758, 0.009608353, -0.10801905, -0.04071131, -0.09096832, -0.12350487, 0.011801418, 0.22521795) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.040283076, -0.034117915, -0.026142653, -0.06058959, 0.12511659, 0.4131219, 0.59190845, 0.39758852, 0.16032091, -0.5975032, -0.14516282, 0.115154505, 0.03874097, 0.18462797, 0.22934213, 0.05285643) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.17804009, 0.33769128, -0.14572927, -0.029545018, 0.3897, -0.055615567, 0.15232995, 0.48788264, -0.21422523, 0.03397293, 0.0337794, -0.19830915, -0.022457365, -0.35096076, 0.42616987, -0.19268763) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.13191561, -0.18337126, 0.017879983, -0.070472844, -0.09409196, -0.025770849, -0.060219247, 0.10869267, -0.17341033, -0.09199785, -0.0667796, -0.093538545, -0.21300837, 0.030474098, -0.04540468, 0.041321553) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.0998177, -0.08669185, -0.0090886615, 0.0021083376, 0.08900095, 0.5062186, 0.45537788, 0.029077586, -0.1001008, -0.0077697043, -0.0096318, 0.11706454, 0.07401959, -0.00650215, 0.06092762, 0.037442297) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.18500404, 0.0024998419, -0.11761331, -0.026825588, 0.27255726, 0.093010515, 0.3281413, -0.051473666, -0.050259475, -0.17258662, -0.23394547, 0.104795866, 0.035074063, -0.061560635, 0.05975411, -0.094255395) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.023440497, -0.021479638, 0.0036277648, 0.004972212, 0.02416659, -0.09856867, -0.03971455, -0.27094853, 0.026615402, -0.0047890246, -0.13755885, 0.16591635, -0.0016293586, 0.133207, 0.047790572, 0.029041538) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.0063728676, -0.029053684, -0.052831043, 0.006475641);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.0431447, 0.047972627, 0.09522898, 0.19048582, 0.0015511789, 0.1182684, -0.065335006, 0.061233886, -0.02451869, 0.065670215, -0.015341636, 0.06836347, 0.10215459, 0.17516296, 0.0857072, 0.072732896) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.10117189, 0.049022958, -0.016017418, -0.12119866, 0.089112304, 0.016286526, -0.025251161, 0.03239003, -0.0783818, -0.086096615, -0.13673106, -0.15934734, -0.51308054, -0.061430074, -0.16208844, 0.2227776) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.011567444, 0.025550444, -0.018439503, -0.015003767, 0.11606929, -0.11613111, -0.040906087, -0.015202219, 0.03932618, -0.1106059, 0.03703376, 0.018548314, -0.12761284, -0.038109995, -0.23577367, 0.20272344) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.025444161, -0.075270735, 0.10999789, 0.16305386, 0.016178958, -0.074034974, 0.1177035, -0.077481024, -0.047774278, -0.029782977, 0.23137823, -0.2389453, 0.033015423, -0.10381626, -0.16437943, 0.20906886) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.098473966, 0.11013442, -0.18486807, 0.1907086, -0.17564997, -0.08509439, -0.42472756, -0.17446618, 0.3440862, 0.12719585, -0.12213955, -0.02246555, 0.18982963, 0.20809166, -0.36067408, 0.51116616) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.019805575, 0.07812505, 0.061653323, -0.08379226, 0.026396899, 0.009063019, -0.10845824, 0.0827647, 0.045301896, -0.07748021, -0.07435832, 0.14860612, -0.077515624, 0.010588131, -0.22704287, 0.26849246) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.02884339, -0.09512523, -0.038564682, 0.08862835, 0.041666254, -0.10532901, 0.040582962, -0.10063983, -0.15736029, -0.03644334, -0.005061672, 0.04302295, -0.046482194, -0.05262547, 0.05110866, 0.03204655) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.005932702, 0.033263832, 0.0044865874, -0.02328917, 0.056534443, -0.14084046, 0.022353357, 0.015087431, -0.2734596, -0.026544483, 0.06297078, 0.11277746, 0.06127936, 0.02466357, -0.04970561, 0.02098484) * go_0(1.0, 0.0);
|
||||
result += mat4(0.013603583, 0.036264602, 0.10985147, 0.01532773, -0.09012781, 0.1132652, -0.17016481, 0.025332611, -0.077462606, 0.02990799, -0.10627784, -0.006231141, -0.089164406, -0.051507175, -0.043900985, 0.09049239) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.15391691, 0.1915742, 0.014101639, -0.022153432, 0.06291936, -0.017871676, -0.016763045, -0.14741553, -0.011252563, -0.20720159, -0.030648025, -0.0142307645, 0.010291614, -0.09243969, -0.052940153, 0.0061574522) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.032283742, 0.030768922, 0.1070225, -0.027818602, 0.10032608, 0.0061178426, -0.03561339, -0.26687133, 0.14369439, -0.11362691, -0.08980895, 0.066520914, 0.33414948, 0.006998835, 0.09193012, -0.2857383) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.059588976, -0.02046844, -0.042585023, 0.031939838, 0.12796514, -0.06155685, 0.03540324, 0.009929082, -0.0039611827, 0.10790477, 0.049435645, -0.083034374, 0.23874004, -0.07460337, -0.020173345, -0.2006587) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.13217632, 0.052319963, -0.026713084, -0.0051368694, -0.10380872, -0.28659084, 0.0044393227, 0.005174543, -0.05092618, -0.07092548, -0.027397033, -0.01609789, 0.13699281, -0.14706929, 0.17737861, -0.23746766) * go_1(0.0, -1.0);
|
||||
result += mat4(0.19268502, 0.14133929, -0.1305119, -0.4034132, 0.057504695, -0.24550998, -0.081932545, 0.45489246, -0.29331785, 0.19625074, 0.063166246, 0.15158689, 0.6715147, -0.4610189, 0.08921431, 0.17761138) * go_1(0.0, 0.0);
|
||||
result += mat4(0.044718128, -0.011809122, 0.024131307, -0.30093196, -0.05607289, 0.047759805, 0.004210022, 0.098192796, 0.030430846, 0.008207501, 0.12266905, -0.10549182, 0.11584339, -0.091016166, -0.08635591, -0.13889709) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.19226642, 0.07147627, -0.14759602, 0.4041079, 0.0744628, -0.19612685, 0.1498252, -0.06273549, 0.017959936, 0.10858338, -0.14985329, 0.062042814, -0.13240446, -0.24362786, 0.113626175, -0.15332204) * go_1(1.0, -1.0);
|
||||
result += mat4(0.08383099, -0.13935047, -0.25981048, 0.16491203, 0.07513876, -0.28346774, 0.19722275, -0.044425573, 0.020889329, -0.22140723, 0.025403097, -0.09183192, 0.014202567, -0.18666178, 0.062913105, -0.047674105) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.1862771, 0.25878942, -0.043018065, 0.22144824, 0.016088247, 0.12113542, -0.11965952, -0.01587184, 0.07830932, -0.16069177, 0.13421321, 0.018718706, 0.09548377, 0.018543294, 0.013614677, -0.1054485) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.2121733, -0.015635416, 0.027564054, -0.085904464, 0.064805664, -0.070543915, 0.08966146, -0.06359783, 0.01131311, 0.046913184, -0.09809833, -0.092063695, -0.087217696, 0.012411829, 0.0045399712, 0.027389864) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.19307798, 0.09449126, 0.084036835, 0.30262446, 0.011706106, 0.029800637, 0.04612629, 0.006186647, 0.11228541, 0.055147965, 0.17659879, -0.023410015, 0.19965266, -0.06684007, -0.081968054, -0.052410994) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.058564443, 0.08252549, 0.058217794, 0.0864448, -0.25663558, 0.080260284, -0.0010294432, 0.05830051, -0.07684524, 0.1820709, 0.04438993, 0.019178499, -0.12425012, -0.04596089, -0.010032888, -0.0012803525) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.43352658, 0.15262963, 0.25620222, 0.22428556, 0.09667152, 0.0037820593, -0.07951691, -0.11553085, 0.12982155, 0.17988266, -0.14283511, 0.074744284, 0.03604327, 0.00452661, -0.12865154, -0.020020623) * go_2(0.0, -1.0);
|
||||
result += mat4(0.06850602, -0.18057181, 0.2093389, -0.07333886, 0.28406742, -0.048766967, 0.18114483, 0.47292945, -0.2340266, -0.06862712, 0.28263155, 0.3150323, -0.054724697, -0.16958356, 0.27928987, -0.19666018) * go_2(0.0, 0.0);
|
||||
result += mat4(0.03281329, 0.0038649621, -0.07108877, 0.10791149, 0.15235375, -0.3083721, 0.168294, 0.10379698, 0.029038485, 0.16282903, 0.04483725, -0.018684763, 0.108186625, 0.027885616, -0.019351846, 0.1623065) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.110499054, 0.31347123, 0.030852, 0.01631416, -0.1466389, 0.080429435, -0.18689284, 0.10667815, 0.20645237, -0.18004708, -0.10570413, -0.15435064, -0.019000605, -3.126077e-06, 0.037761535, -0.015040956) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.023364332, -0.023399066, 0.2712722, 0.049637552, -0.10222765, -0.2698945, 0.20991959, 0.04921932, 0.21510898, -0.0751939, -0.19781734, -0.28162366, -0.041881047, 0.0065111094, -0.04102195, 0.0982682) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.032176614, 0.019144032, -0.08985387, 0.091637276, 0.1012352, 0.0003583357, 0.07897295, -0.09531175, -0.001155058, 0.074372366, -0.026186578, 0.07283374, 0.06052053, 0.009307753, -0.03874333, -0.06228009) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.022224072, -0.15717922, -0.1406057, -0.05941157, -0.028769474, -0.21226564, -0.036570027, 0.22266355, 0.14120889, 0.014577123, 0.10216447, 0.018429281, 0.056729726, -0.055834044, 0.058146577, -0.11999068) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.009995364, -0.020045493, -0.0057422677, 0.0643022, 0.016475432, -0.030856136, 0.042140726, 0.15077904, -0.32955253, 0.0694449, 0.17931722, 0.3439302, -0.12484157, -0.10958869, -0.15755124, -0.09755644) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.008314924, 0.07704758, 0.043228816, -0.08110893, 0.099286236, -0.053224478, 0.22877018, -0.189486, -0.00798416, 0.018341504, 0.10734141, 0.0752633, -0.042524844, -0.086395286, 0.14299925, 0.026488977) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.052531082, 0.19139186, 0.12205995, -0.2573172, 0.15157184, 0.0073150825, 0.089774385, 0.06604469, -0.16528498, -0.002511137, 0.14287429, -0.07819732, 0.025014274, 0.15338829, 0.0761692, -0.02803716) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.21000335, 0.15277153, 0.08546171, 0.2816124, -0.16559112, -0.11068559, 0.47053605, -0.009787771, -0.0013089112, -0.06985127, 0.44743782, 0.25142467, -0.32670796, 0.044035822, -0.12545367, -0.2996084) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.11526387, 0.15654811, 0.099616654, 0.15473685, 0.21278231, 0.046207245, 0.117993094, -0.26825273, -0.12539764, 0.14013724, 0.17357737, -0.05387817, 0.076738276, -0.13339446, 0.15005626, -0.2108176) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.0008846504, -0.05998622, -0.028892396, 0.04784136, 0.0104263965, 0.10899508, -0.073364735, 0.077516064, -0.074248806, -0.21749993, -0.26203, 0.041161157, 0.09366407, -0.026498007, 0.0122177545, 0.03892727) * go_3(1.0, -1.0);
|
||||
result += mat4(0.04349908, 0.13671173, 0.2242545, -0.028021423, -0.03802222, 0.0052366396, -0.010709643, 0.031290106, 0.06291333, -0.024909683, -0.15439379, -0.04502091, 0.2062182, -0.5983536, -0.09670497, -0.38446042) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.008962513, 0.13044207, 0.04964221, 0.012250417, 0.012129821, 0.019985713, -0.06421885, 0.009168735, -0.044516414, 0.071368866, -0.006634213, 0.06497366, 0.08578495, -0.10586125, 0.06628038, -0.14006054) * go_3(1.0, 1.0);
|
||||
result += vec4(0.056541316, 0.041788545, -0.036094554, -0.021763096);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf1
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.0647927, 0.053666476, -0.14723225, 0.027874574, -0.0003166473, 0.07337155, -0.061972085, -0.012667777, -0.17071614, 0.091927536, -0.051160213, 0.21336353, 0.13854574, 0.09582817, 0.032316446, 0.13838023) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.0398984, 0.108049214, 0.093780346, -0.022015186, -0.15188989, -0.1381083, 0.2998843, 0.21623154, -0.08862326, 0.025862623, 0.06895634, 0.13529755, 0.06957801, -0.0011681129, 0.105972745, -0.04722446) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.026321493, -0.04828038, -0.012545767, -0.005490858, -0.054038163, 0.075943105, -0.11526662, 0.022242405, -0.03543104, -0.12451852, -0.14911178, 0.013503498, 0.08773292, 0.09695139, -0.013498657, -0.27424073) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.018575635, -0.11321618, -0.07853153, 0.04104883, 0.0018416744, 0.11579002, 0.03685964, -0.031546146, -0.1755398, 0.23517849, -0.08095411, 0.031999595, -0.18542038, -0.26171613, -0.20567231, -0.05683613) * go_0(0.0, -1.0);
|
||||
result += mat4(0.1538556, 0.21723682, 0.12131733, -0.15308167, 0.103326, -0.006956118, 0.043583486, -0.23811384, -0.103285454, 0.05543916, -0.37894246, 0.32072112, 0.22651967, 0.03516268, 0.34612176, 0.23688535) * go_0(0.0, 0.0);
|
||||
result += mat4(0.040021293, 0.0029912095, 0.04885362, 0.061496444, 0.016926387, -0.118446946, 0.038948335, -0.0934512, -0.25194243, -0.054018084, -0.07149527, 0.017903058, 0.0845516, 0.33802906, 0.11953944, -0.081294954) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.09558082, -0.36974236, -0.07524102, 0.11131445, 0.047626104, 0.12854609, -0.10264962, -0.044669047, -0.05572307, 0.34475142, -0.16806377, -0.0037204176, 0.03400533, -0.04047774, 0.024379745, 0.09056291) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.039392482, 0.2553437, 0.11705501, 0.03219211, 0.073977776, -0.16610906, -0.032796364, -0.054669864, -0.07123178, 0.00079619256, -0.36920992, -0.029054813, 0.12830003, 0.004987549, 0.08724278, -0.029499404) * go_0(1.0, 0.0);
|
||||
result += mat4(0.021272454, -0.063295126, 0.011779576, 0.103093, -0.011095461, 0.027948728, -0.014605259, -0.04723974, -0.05334346, -0.044831257, -0.07296399, -0.03314197, -0.01687865, -0.09261895, -0.06128567, 0.092708185) * go_0(1.0, 1.0);
|
||||
result += mat4(0.0077418387, 0.00871427, 0.060824487, 0.1093608, -0.021077013, -0.057341542, -0.04769576, -0.08144089, 0.0212823, -0.06731425, -0.04134463, -0.0016761447, -0.03402026, 0.036424547, 0.11689576, -0.14946719) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.18536687, 0.020073935, 0.17041959, 0.024790209, 0.08397728, -0.13884324, 0.013950321, -0.055075396, -0.09317963, -0.05723721, -0.060491834, 0.0017911601, -0.109154835, 0.010338362, -0.1982491, -0.21752335) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.031852514, 0.031424347, 0.07817056, 0.07770759, 0.019805199, -0.091223724, 0.11914662, 0.1673029, -0.018734453, 0.16275099, 0.23245652, 0.36139074, -0.1396047, -0.14774057, 0.13756078, -0.123794965) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.034937833, 0.20777488, 0.10104809, -0.035140667, 0.2536575, 0.010970045, 0.16896339, -0.081219964, -0.062478427, -0.0010431948, -0.027980985, 0.11446318, -0.127309, 0.21002083, 0.044436257, -0.16986957) * go_1(0.0, -1.0);
|
||||
result += mat4(0.06309646, -0.042341243, 0.36642808, 0.18653205, 0.06973023, 0.06315932, -0.323688, 0.25672218, 0.042820994, 0.13792914, -0.12892757, -0.09220378, -0.18939693, 0.03862022, -0.17376114, -0.24673308) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.02130602, -0.35428852, -0.011634983, -3.9823462e-05, 0.110818714, -0.2981158, 0.060209107, 0.012538829, -0.0744833, -0.050204318, -0.12676497, -0.031484153, -0.28799182, 0.22338839, -0.070876874, -0.02102363) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.07929991, 0.014598492, 0.23034762, 0.024872296, 0.07480494, -0.17139243, -0.014421178, 0.056448363, -0.028626937, -0.022152562, 0.044871796, -0.048653606, 0.009350802, 0.019022083, -0.08554845, -0.0922645) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.027405115, 0.1831188, 0.28516722, 0.19882526, 0.27299204, -0.06910511, 0.03244419, -0.0031333128, 0.061055277, -0.114398144, 0.03729459, -0.07840815, -0.37776002, -0.24129418, -0.54815483, -0.2702045) * go_1(1.0, 0.0);
|
||||
result += mat4(0.053723935, 0.13472083, 0.09563273, 0.19009806, -0.18722993, -0.25939655, -0.016197463, -0.067061596, 0.1647598, 0.061905228, 0.06191816, -0.018582113, -0.07218153, 0.11278394, 0.05478068, -0.104871586) * go_1(1.0, 1.0);
|
||||
result += mat4(0.0036616288, -0.045782693, -0.226954, -0.05043515, -0.078096785, -0.036197383, 0.09269631, 0.016823346, -0.0060579977, -0.041455746, 0.09032774, -0.09217121, 0.058089796, 0.060311552, 0.033079024, 0.022586476) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.0436363, -0.079482526, 0.0027447809, 0.039558932, 0.13275702, 6.898711e-05, -0.21961488, -0.11315821, 0.0076181027, -0.025279062, -0.15829584, -0.063141204, 0.062049046, 0.13117202, -0.02435016, 0.109555416) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.010148116, 0.056620967, -0.015910713, -0.07370375, 0.1529919, 0.005792597, 0.02771225, -0.17027487, 0.096740395, 0.063347995, 0.17823112, 0.054105148, 0.04995114, -0.28613812, 0.06369567, 0.15978208) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.13688345, 0.16967694, -0.061759472, 0.013682004, -0.1290496, 0.07167547, -0.065592445, -0.17897636, 0.057080988, 0.035630587, 0.09140394, -0.08695068, 0.16807681, 0.014749346, 0.07875138, 0.034913708) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.098915346, -0.31459075, -0.10892429, 0.1557498, -0.19764107, -0.26881596, -0.03589311, 0.45288458, -0.34171388, 0.12675741, 0.18415868, -0.19770056, 0.29025507, -0.15812592, 0.09685835, 0.0027761247) * go_2(0.0, 0.0);
|
||||
result += mat4(0.06425249, -0.01169722, 0.06379363, 0.053835012, -0.07356561, -0.06367294, 0.108630784, -0.14137438, 0.08536725, -0.03209748, 0.07250959, -0.014214082, 0.07170588, -0.25647813, 0.1092683, 0.18791042) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.023783233, 0.14261739, 0.102011986, -0.03633555, -0.05032627, 0.09378387, 0.11764051, 0.1353335, 0.032817088, -0.1352964, -0.00667997, -0.13388929, 0.022861317, 0.0037358075, 0.018605746, -0.0009892831) * go_2(1.0, -1.0);
|
||||
result += mat4(0.22419162, -0.23105696, -0.09900454, -0.15831396, 0.12398773, 0.097933106, -0.13189293, 0.1330756, -0.19673057, -0.037342317, -0.13462654, -0.08974021, 0.030326528, -0.0815862, -0.118352115, 0.009187904) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.012130391, -0.06408448, 0.13710785, -0.06678414, -0.09970725, -0.14895032, -0.02366641, 0.029581001, -0.07101809, 0.09414698, 0.018300869, 0.009139046, -0.0027311493, -0.2359952, -0.011602826, -0.007582444) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.15473361, -0.06868751, -0.030721204, -0.08650113, 0.071349874, -0.08177769, 0.1611948, 0.18305337, -0.0144878505, 0.10975452, -0.026968453, -0.04909913, -0.059665974, 0.056036238, -0.11623168, -0.10584912) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.096973225, 0.054132458, -0.010600018, 0.089397885, -0.0031138035, 0.037452973, 0.041115325, 0.1924831, 0.14759748, 0.032560788, -0.082884625, 0.0324635, -0.083511285, -0.050381303, 0.025589975, -0.0981257) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.09183111, 0.034952193, -0.048511654, 0.020719057, 0.1863456, 0.01902738, 0.14455654, -0.008500172, 0.16385981, -0.07806569, -0.031216217, -0.17002788, -0.08882952, 0.07335293, -0.2223089, 0.01706056) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.08361569, 0.046698716, -0.016646344, 0.09351987, 0.0054158634, -0.13641126, -0.12396605, 0.011380122, 0.040951792, -0.11222528, -0.0031548145, -0.0022303525, 0.0350846, -0.03280425, -0.09972476, -0.113325305) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.19961461, -0.27561286, -0.12783135, -0.062596925, 0.005870981, -0.24796526, 0.18717633, -0.16945636, -0.076396205, -0.08411448, 0.13751988, 0.21014418, -0.008655945, -0.09848541, -0.14536901, -0.2132181) * go_3(0.0, 0.0);
|
||||
result += mat4(0.14118621, 0.20831147, -0.020545695, 0.008340737, 0.016840864, -0.16912372, -0.121718146, 0.15108089, -0.19803092, -0.07827729, -0.047639225, -0.12277847, 0.04974115, -0.09349339, -0.2756667, -0.19581003) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.0036992705, 0.16539848, 0.022026122, 0.07740234, -0.035687633, -0.004568715, 0.017408118, -0.09757294, -0.094941914, -0.3381112, -0.12724453, 0.025583982, -0.18571027, 0.047607586, -0.0704089, -0.055323426) * go_3(1.0, -1.0);
|
||||
result += mat4(0.13821335, 0.028168043, 0.09990671, -0.032266147, -0.067236245, 0.11512147, -0.112986445, -0.10818019, -0.10062181, 0.21276556, 0.01681818, 0.069806606, 0.09628121, 0.06456379, 0.10394843, -0.02343886) * go_3(1.0, 0.0);
|
||||
result += mat4(0.041937463, 0.072631165, 0.045366894, -0.0046993676, 0.03946691, 0.121010706, -0.030089365, -0.007266469, 0.0092267515, 0.14853416, -0.033248078, -0.027284347, -0.10031526, 0.15864117, -0.16782752, -0.18466589) * go_3(1.0, 1.0);
|
||||
result += vec4(0.07722432, -0.025165567, 0.034291282, -0.09902708);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.004729794, -0.0124398535, -0.08538641, -0.058604605, 0.008671952, 0.25604513, 0.020800482, 0.24144122, -0.028920606, -0.04705229, 0.030192787, 0.0010597534, 0.017666103, 0.0041322373, 0.20027764, 0.08919112) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.0001626656, 0.05816014, -0.0060765734, 0.08811165, 0.35835367, -0.016291425, -0.56892496, 0.083845764, 0.15026698, -0.15916558, 0.08069463, -0.3931291, -0.0123534845, -0.111639686, -0.14637001, -0.08171439) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.114976816, 0.023376396, 0.13855027, 0.07438716, -0.069991484, 0.20377779, 0.23929878, -0.040769435, 0.018832395, 0.005638609, -0.091848075, 0.027843866, 0.023744943, -0.06620523, -0.11678267, 0.0844119) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.0035854098, -0.08432094, -0.17799544, -0.10041983, 0.25605857, 0.021009786, 0.030499447, -0.09928291, 0.052178737, -0.08286175, -0.057888374, 0.024606042, 0.046342995, 0.13875343, 0.11279266, 0.19826262) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.016232021, -0.21539623, 0.0936961, 0.021143785, 0.094262615, 0.049040064, 0.40978724, 0.15347758, 0.08884813, -0.24887115, -0.14756748, -0.5020875, 0.112477, 0.1466549, -0.33418837, 0.5769466) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.16832942, -0.07354198, -0.12081261, -0.055348314, 0.39716053, 0.25583258, 0.09870877, 0.2151021, -0.025700683, -0.1801462, -0.04616654, -0.02782245, -0.054461803, -0.00042802413, -0.00163228, -0.004240747) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.05193433, -0.0018198475, -0.17647028, -0.19462106, 0.1538165, 0.054894235, 0.12183955, 0.07340974, -0.0019901982, 0.0357373, -0.07597063, -0.06681543, -0.00090057997, -0.053894397, -0.010301875, -0.16553953) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.30873474, -0.2836045, 0.057037193, -0.5016378, 0.11952749, 0.102353275, 0.2351629, -0.14635189, -0.019398788, -0.08776502, 0.021669978, -0.089918956, -0.2187901, -0.1180891, -0.049789533, -0.16109149) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.078335494, -0.08867304, 0.03349591, -0.1000293, -0.20235832, 0.22917585, -0.09905303, 0.08381748, 0.014350217, -0.14478815, -0.027479894, -0.026432173, -0.10309177, -0.09860884, -0.019177807, -0.06963025) * go_0(1.0, 1.0);
|
||||
result += mat4(0.008169383, 0.12532842, -0.23369955, 0.077973194, 0.09076616, -0.021277165, 0.1721421, -0.26914293, -0.014729218, -0.023279984, -0.057670787, 0.003598546, -0.015225789, -0.0115396585, -0.26196182, -0.10724508) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.16542235, 0.06589374, 0.07410237, 0.26753154, -0.3356288, 0.3096256, 0.07112498, -0.0992165, 0.15020338, -0.11021673, 0.18803611, 0.12918204, 0.109007336, -0.031968266, 0.057093572, 0.035949256) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.065006174, 0.031055925, 0.0390232, -0.01678507, -0.21553491, 0.14171642, -0.19541772, -0.033691674, -0.06241631, 0.07497651, 0.024557155, 0.056778047, -0.060191352, -0.0261998, 0.07493729, -0.0699132) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.008541382, 0.020270415, -0.027760057, -0.040962905, -0.26732433, 0.34379438, -0.23012447, 0.0051356517, -0.04059567, 0.0972959, 0.039965224, -0.14796777, -0.0016924662, -0.116963714, -0.026353523, -0.29799464) * go_1(0.0, -1.0);
|
||||
result += mat4(0.03329303, -0.12663862, -0.0004959157, -0.11162377, 0.26238343, 0.43260252, -0.16504994, 0.10727678, -0.22505566, 0.43474057, 0.43304008, 0.05143919, 0.40494493, 0.08689636, -0.035733614, 0.25727916) * go_1(0.0, 0.0);
|
||||
result += mat4(0.12175736, -0.014467151, -0.17461288, -0.18480565, -0.26439998, 0.307935, -0.058916792, -0.014292711, -0.0569471, 0.10751278, -0.04134206, 0.1847734, -0.07519831, -0.033909313, -0.05001451, -0.136606) * go_1(0.0, 1.0);
|
||||
result += mat4(0.1424893, -0.026820501, 0.19645774, -0.0011315406, -0.14680974, 0.07662838, 0.21108222, 0.13260938, 0.17923595, -0.085527614, 0.08217639, 0.06579479, 0.05985784, -0.09016323, 0.11172888, 0.111903176) * go_1(1.0, -1.0);
|
||||
result += mat4(0.19842595, 0.0093640275, 0.10433465, 0.13341904, -0.082806975, 0.22555825, -0.1315717, 0.11907785, 0.24012424, 0.47776055, 0.1835734, 0.17483878, 0.079803735, 0.01155073, -0.21146573, -0.16484722) * go_1(1.0, 0.0);
|
||||
result += mat4(0.15064004, 0.021381427, 0.18301587, 0.21225913, 0.054995645, 0.03212186, 0.052798916, -0.048424408, 0.03609021, 0.0964704, -0.059469886, -0.05133066, -0.08157349, 0.051145166, -0.09107608, -0.1362262) * go_1(1.0, 1.0);
|
||||
result += mat4(0.090521574, -0.014747857, -0.081675015, -0.118686825, 0.04848682, -0.033071827, 0.008534588, 0.023765508, 0.16849907, -0.21797262, -0.17049783, -0.07824179, -0.033794608, 0.052612655, 0.095820345, -0.07262317) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.22816367, -0.13772108, -0.036353834, -0.47638395, -0.0530902, 0.14089061, 0.076203234, 0.18006112, 0.121814854, -0.20750527, 0.08266107, -0.28634354, 0.14301859, -0.13458411, 0.00501663, -0.039783802) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.103384845, -0.14389835, 0.08275834, -0.068423435, 0.22643796, -0.02966374, -0.2847584, 0.037081387, 0.02349005, -0.19353923, -0.00095957273, -0.13623689, -0.073120415, 0.03941467, 0.21864155, -0.014019576) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.082576886, 0.17085212, 0.08971252, -0.04213377, -0.032548156, 0.022137715, 0.08399252, -0.0011743539, -0.09410863, -0.41728264, -0.20709297, -0.18933547, 0.027059928, 0.09743364, 0.2504647, -0.041173562) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.20924084, 0.291118, 0.029851688, 0.16953468, 0.02936709, 0.12213576, 0.22944322, 0.108747594, 0.0001881129, -0.27398208, -0.009702691, 0.15449248, -0.9472944, -0.26114875, -0.28161275, -0.3495961) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.12994622, -0.2758638, -0.1091727, -0.0968308, -0.14323105, 0.035175014, -0.08023811, 0.006023802, -0.031529594, -0.1486306, -0.3398172, -0.23240276, -0.29163983, 0.173475, 0.18809283, 0.22197202) * go_2(0.0, 1.0);
|
||||
result += mat4(0.048254848, -0.083444916, -0.014334202, 0.060992356, -0.023099286, -0.09492961, 0.05592045, 0.0026059286, 0.08998117, -0.108810075, -0.053304546, 0.045926623, 0.068255246, 0.099023566, 0.01595483, 0.1336309) * go_2(1.0, -1.0);
|
||||
result += mat4(0.21916585, 0.2837387, 0.14624594, 0.18843961, -0.06747584, 0.054924384, -0.082568415, 0.05011459, 0.014297759, -0.3884833, -0.054417178, -0.18970548, 0.088336475, -0.030646667, -0.2980552, -0.030035203) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.02748568, -0.011897529, -0.2370837, -0.016740574, -0.0282112, 0.050353892, -0.10761107, -0.00036999505, 0.037646662, -0.17742962, 0.06489219, -0.158852, -0.08016933, 0.07808515, -0.105895035, 0.079869986) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.0058994526, -0.037170693, 0.2574696, 0.06199102, -0.04497728, -0.10667442, -0.15183865, 0.0212881, -0.030842574, 0.073473394, 0.010764398, -0.00084518327, -0.03893014, -0.009649613, 0.07443129, 0.15108284) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.11325495, -0.096435815, -0.097331434, -0.049700152, -0.17231967, 0.047090057, -0.019111065, 0.104790315, -0.15004838, 0.13950798, 0.055996202, -0.070548095, 0.047154237, -0.007650949, -0.053611025, -0.012242293) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.12787002, -0.04958212, 0.053988468, 0.0017896162, 0.049493514, -0.009475431, -0.0022641935, 0.03933694, -0.005174597, 0.043754533, -0.1432976, 0.037084177, -0.04601288, -0.032077815, -0.059897035, 0.12584484) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.019409029, 0.10492923, 0.268368, 0.12597778, -0.17733063, -0.0085961, -0.27136415, -0.049664587, 0.012515404, -0.21444482, -0.39275557, -0.12297177, 0.06800057, 0.19228315, 0.06245887, 0.35772634) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.16317715, 0.2288402, -0.23235172, 0.22230752, -0.1646375, 0.13366091, 0.16681044, -0.17399235, 0.33997267, -0.3179832, -0.34756508, 0.39843196, -0.10748536, 0.322923, 0.23339489, 0.08684083) * go_3(0.0, 0.0);
|
||||
result += mat4(0.02835275, 0.12314228, 0.24030593, 0.30856124, 0.055735108, -0.044914473, 0.0031432225, 0.07469899, 0.1778018, 0.107083894, -0.023706734, -0.15501897, 0.0943098, -0.034707237, -0.18622099, 0.05257965) * go_3(0.0, 1.0);
|
||||
result += mat4(0.042839274, 0.12597966, 0.08979042, -0.0647561, -0.050434645, 0.049438696, -0.20008127, -0.05572608, 0.046238814, 0.12622325, -0.019017145, -0.13960391, -0.040050175, 0.14298008, -0.20270552, 0.13391526) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.0073277587, 0.10606624, -0.08940439, -0.09656414, 0.12387374, -0.0013147948, 0.23607181, -0.00037969893, 0.050353236, -0.17266603, 0.27796733, -0.09877832, 0.02711225, 0.096394345, 0.07457944, 0.21541388) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.18612787, -0.00027517386, -0.17136407, -0.06413671, 0.025629476, -0.04570916, 0.0008431566, -0.03419168, 0.08123608, 0.09465922, 0.11975521, 0.1269741, 0.08413221, 0.12125001, 0.04727287, 0.072378494) * go_3(1.0, 1.0);
|
||||
result += vec4(0.04244928, -0.014280219, 0.017129054, -0.08807801);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf1
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.01973856, -0.05053795, 0.015545361, 0.10867395, 0.33441806, 0.14731607, 0.6793983, -0.21394718, -0.00846322, 0.09146322, -0.07427475, -0.078477465, -0.090998545, 0.133366, 0.105515696, -0.13784988) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.05404873, 0.09784018, -0.1337389, -0.18082313, 0.13461179, -0.3816801, 0.12209786, 0.08176651, 0.10461896, -0.43315184, 0.017470734, 0.20423968, -0.03941875, -0.101959296, -0.09440259, 0.09154717) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.17229515, -0.06907825, -0.008382803, -0.16671611, -0.01576541, 0.03985307, 0.08209482, -0.11707446, -0.11793074, 0.13702396, -0.02013158, 0.07302033, -0.022301994, -0.11464677, 0.036753565, -0.093276784) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.017650167, 0.009475923, -0.17856382, 0.15925962, 0.06434641, -0.15568036, 0.038135886, 0.18855911, -0.04427734, 0.1878215, 0.10856261, 0.0041275816, -0.12046199, 0.13610138, 0.3741596, -0.12934728) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.24631616, 0.0169485, -0.035534818, 0.37795424, -0.08546174, 0.07817259, 0.42897213, -0.47965595, -0.0146556785, -0.20510523, -0.18889453, 0.06476019, 0.1021008, -0.35398817, -0.031071864, -0.21416448) * go_0(0.0, 0.0);
|
||||
result += mat4(0.32810766, 0.050585747, -0.17658374, -0.13881154, 0.16417882, -0.21286008, -0.106835455, -0.1722344, -0.14151084, 0.08962986, 0.057395387, -0.01623662, 0.02570415, 0.15626897, -0.12687978, 0.080729105) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.050597478, -0.018753758, -0.036346875, -0.017908493, 0.058593344, 0.008303028, 0.05254987, -0.06635018, -0.022532012, 0.029511122, 0.026682215, -0.054647952, 0.069466785, -0.08892492, 0.025351115, -0.023130694) * go_0(1.0, -1.0);
|
||||
result += mat4(0.2412473, -0.16138165, -0.15117447, 0.11851003, -0.096868426, 0.082690425, 0.27923304, 0.11590443, 0.19363573, -0.15770023, -0.066793665, 0.011681678, 0.14037277, -0.112065665, -0.048159517, 0.009453693) * go_0(1.0, 0.0);
|
||||
result += mat4(0.1580054, -0.0060506654, 0.05267837, -0.09178131, -0.09107123, 0.23191126, 0.21108283, -0.070422985, 0.024321035, 0.06131459, 0.066626504, 0.032481454, 0.044402298, 0.1390604, -0.14432502, 0.040869843) * go_0(1.0, 1.0);
|
||||
result += mat4(0.10264861, 0.013504324, 0.012482852, -0.1781206, -0.12799414, -0.27026084, -0.123830505, 0.098105, -0.039127555, 0.09367889, 0.122323096, 0.1416734, 0.044763107, -0.21801683, -0.14018978, 0.17646866) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.017453065, 0.11498537, -0.10998983, -0.3116098, -0.3099762, 0.5024706, 0.051817298, 0.03170681, -0.18937826, 0.07946567, -0.11978771, -0.09523745, -0.0033551592, -0.11768945, 0.08932359, -0.06689581) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.1507582, -0.013266159, -0.073085934, -0.07252967, -0.06301927, -0.13218755, 0.12984878, -0.13678701, 0.023422396, 0.082123175, 0.006906731, -0.004018426, -0.15813835, 0.13711788, 0.016018609, 0.13443229) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.06960673, 0.16156524, -0.1374069, -0.05803206, -0.077960715, -0.10676749, 0.26282015, 0.03521529, 0.058099385, -0.014738148, 0.0011174522, 0.24279532, -0.023991548, -0.108812414, -0.08886019, 0.20584475) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.08043308, 0.063343, 0.055290066, -0.15991378, -0.08096304, -0.23888679, 0.019161629, 0.38381267, 0.3672934, -0.119608454, -0.43623593, -0.46014485, -0.5323366, 0.1318621, 0.087373205, -0.05535459) * go_1(0.0, 0.0);
|
||||
result += mat4(0.20640239, -0.1369444, -0.21677823, 0.08202178, 0.10515278, 0.06810837, 0.073207974, 0.23623931, 0.102422275, -0.05016664, -0.0039228587, -0.1810343, -0.2235563, -0.1246854, 0.1428113, -0.10609135) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.031941894, -0.08905056, 0.21501167, 0.11244667, -0.011811734, 0.21630247, 0.07589472, -0.040489636, -0.11824066, -0.11520391, -0.10075633, -0.035642453, 0.062144946, 0.0073282206, 0.14119269, -0.060479023) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.29382935, -0.056808118, 0.051812876, -0.061358813, -0.08344258, 0.124203674, 0.037964176, -0.01961274, -0.000951725, 0.50005037, -0.24176972, 0.06487161, -0.15469861, 0.04336187, 0.17826353, 0.040010225) * go_1(1.0, 0.0);
|
||||
result += mat4(0.02044482, -0.0879271, -0.01053958, -0.31148303, 0.07497373, -0.11548258, -0.1666126, 0.02369657, -0.058044076, 0.010801491, -0.005933901, -0.08910467, 0.007953008, 0.03761974, -0.029501524, 0.16816042) * go_1(1.0, 1.0);
|
||||
result += mat4(0.1779597, -0.10213089, 0.29942423, -0.016642543, -0.015537001, -0.04676146, 0.09585872, -0.0055750017, -0.014361908, -0.20667697, -0.11348746, 0.13081487, -0.10437329, 0.14328459, 0.11648822, -0.09163837) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.019033967, -0.12420627, -0.07748253, 0.43203858, -0.109799065, 0.07605535, 0.060791396, -0.24517195, -0.15674245, 0.21267459, 0.10665515, -0.073150024, -0.1358355, 0.0054066703, -0.16434059, -0.06031853) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.18834068, 0.26840356, -0.12937617, 0.16103932, -0.0062331813, -0.13630053, -0.013911821, 0.022389365, -0.044232946, -0.056454606, 0.022426741, 0.18010215, 0.041900013, 0.03375041, -0.11376866, -0.010313381) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.12497669, -0.31161824, 0.097568035, 0.19443443, -0.05056519, -0.0031457904, 0.1055554, -0.083650924, 0.07630523, -0.34177595, -0.093093194, 0.20701368, -0.030962149, -0.054470222, -0.23853977, 0.004326528) * go_2(0.0, -1.0);
|
||||
result += mat4(0.34370202, 0.085750066, -0.16071722, -0.54335934, -0.35595295, -0.050744478, -0.17405547, 0.008628697, -0.007086256, 0.23164117, 0.340156, 0.5475976, -0.15292351, 0.28019544, 0.038059216, 0.0044727) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.08231968, -0.0052294536, 0.07451547, 0.22278999, -0.3305531, 0.0017458396, 0.10818422, -0.21325395, -0.08807993, -0.110342845, 0.10082142, -0.051594347, 0.24192205, -0.18042035, -0.0095462985, -0.08757798) * go_2(0.0, 1.0);
|
||||
result += mat4(0.096379586, 0.021887815, -0.05097233, -0.06797989, -0.026171045, 0.022944937, -0.015915364, 0.037667938, 0.17216732, -0.014889412, 0.07343887, 0.028236505, 0.0015047621, 0.1355103, -0.09918284, -0.07673695) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.25385055, 0.15163356, 0.0030003798, 0.18464413, 0.05611221, 0.099498056, -0.07128191, 0.042955168, 0.027493173, 0.07440157, 0.07814497, 0.096160784, 0.13571084, 0.056412842, -0.031997006, -0.16073681) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.21634746, 0.025153082, -0.064477116, 0.0005679147, -0.0029436245, 0.12794618, 0.024849026, 0.03018052, 0.11723976, 0.059955597, -0.013594654, 0.09091745, 0.04775348, 0.21260159, -0.07463213, -0.06727042) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.12166018, 0.024545137, 0.08611618, -0.17627168, 0.09042604, -0.14157623, -0.22147785, 0.09100581, 0.11078359, 0.031410985, -0.17170976, 0.09532806, -0.059569277, 0.09392676, 0.11784347, -0.21471368) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.1483187, -0.2217563, 0.12032977, 0.14932398, 0.27428308, -0.04568031, 0.12670338, 0.09586169, 0.06700745, 0.005126449, 0.0027694793, -0.033667028, 0.06447861, -0.08585174, -0.05509812, -0.11358761) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.22750492, 0.032906335, -0.029479047, 0.11580199, -0.05812372, -0.032269973, 0.05219915, 0.041658226, 0.010897959, 0.065550454, 0.0076911976, -0.045743827, 0.11614996, -0.10393113, -0.0012606392, -0.034367524) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.09350742, 0.09561609, 0.3735968, 0.031685118, -0.042026598, 0.17006761, -0.3910107, 0.16984761, 0.25679177, 0.036610503, -0.13772772, 0.11101589, -0.1137049, 0.07211461, 0.18065079, -0.12324793) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.020749722, 0.14413361, -0.061903823, -0.21550268, 0.31306142, -0.11532895, 0.029482557, 0.03282164, -0.09800627, -0.20765196, 0.33030233, 0.075725295, 0.49252015, 0.042455837, -0.07264194, -0.10401895) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.22697076, -0.15738785, 0.09740376, -0.072098814, -0.06638972, 0.12336611, 0.0073687397, 0.048267826, 0.06717852, -0.027047804, -0.123397194, 0.17829034, 0.04215185, 0.066311836, -0.061742183, -0.046373066) * go_3(0.0, 1.0);
|
||||
result += mat4(0.041311592, 0.2813485, 0.055084586, -0.01823069, 0.08105147, -0.087944716, -0.10135052, -0.02653456, 0.063169874, -0.1351186, 0.06722432, -0.016406318, 0.08666922, 0.0555909, 0.12086502, -0.17224412) * go_3(1.0, -1.0);
|
||||
result += mat4(0.26026788, -0.18303715, 0.029279215, -0.12858874, 0.027197823, 0.0919464, 0.00849638, 0.10547888, -0.12952055, -0.14414985, 0.1903315, 0.05004528, -0.12657289, 0.038008716, -0.036606666, -0.054025438) * go_3(1.0, 0.0);
|
||||
result += mat4(0.069167465, 0.2699947, -0.11137602, -0.05888806, -0.107324794, -0.07598601, 0.06042177, 0.0064530694, -0.039780665, -0.076666445, -0.00846108, -0.06165907, -0.06978219, -0.19108103, -0.040026028, -0.120319635) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.14375664, -0.0056876075, 0.052177623, 0.07152566);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.15667982, -0.31441393, 0.29112124, -0.15737213, 0.022372838, 0.10690639, -0.12019085, -0.051941186, -0.30367845, 0.02612279, 0.2372532, 0.2021648, -0.20481086, -0.003770439, 0.14981231, 0.066780254) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.03270688, -0.42270073, 0.044317324, 0.15907793, 0.14681059, -0.2934784, 0.24933252, -0.067273855, 0.07752533, -0.23194817, 0.0686707, 0.08999225, 0.121678345, -0.12916678, 0.012397381, 0.012315053) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.10090412, -0.20792678, 0.11076032, -0.02938975, -0.1944187, -0.2003259, 0.04438032, 0.36946484, -0.019868722, -0.15830222, 0.042811528, 0.015641417, 0.113098525, 0.080257006, 0.011135628, -0.2877629) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.15482685, 0.06579119, 0.28301102, 0.23729764, 0.15990537, 0.4529694, 0.107880585, 0.10668121, -0.42430598, -0.2631025, 0.10513542, -0.036242936, -0.09827965, -0.0069260495, -0.11689201, -0.041436482) * go_0(0.0, -1.0);
|
||||
result += mat4(0.08472191, -0.13051608, 0.047930017, 0.36831668, 0.1164478, 0.21384816, 0.22062506, 0.2094167, 0.48668453, 0.32302913, 0.36268055, -0.091801375, -0.079141125, -0.26613805, -0.16608004, 0.03810683) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.13474251, -0.04824603, 0.23303726, -0.116136365, 0.0056330245, 0.15829784, 0.0012259148, 0.12648389, 0.038680512, 0.05131116, 0.024099711, 0.4555406, 0.0035716395, 0.11633299, 0.094744846, -0.2457627) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.0576871, -0.04037522, 0.16857862, 0.0031084458, -0.027274646, -0.18154246, 0.13337846, 0.035422433, -0.0030749738, -0.17288287, 0.019983152, -0.31871706, -0.03280405, 0.06825421, -0.1563798, 0.05031885) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.066631876, 0.012560506, 0.1690693, -0.018248236, 0.0450104, 0.016296914, -0.14910112, -0.16191053, 0.5078224, -0.017615631, 0.15226597, -0.13373777, 0.20148668, 0.060258996, 0.13215344, 0.18430072) * go_0(1.0, 0.0);
|
||||
result += mat4(0.12976126, -0.072738245, 0.053067926, 0.09752956, -0.04716214, 0.04136464, 0.014162617, -0.06621296, -0.09617736, 0.057469178, 0.01280261, -0.042976785, -0.12570308, 0.006027807, 0.031038594, 0.06569918) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.12655424, -0.41563693, -0.030971345, -0.06357555, -0.14121394, -0.15667427, 0.14398985, 0.05995984, 0.0821605, 0.12462943, 0.007492498, -0.0030187522, -0.22804567, -0.10487421, 0.13180672, -0.13978589) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.075991526, 0.12352044, -0.17844258, 0.010614991, -0.18293494, 0.25009897, -0.080779895, 0.21548378, 0.22215544, 0.048670914, -0.057372037, 0.078176, 0.17490411, 0.004919551, 0.059619516, 0.12660357) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.06282951, 0.10929357, 0.026720649, -0.15939257, 0.17107709, -0.04334904, -0.03047162, -0.101681694, 0.03118431, 0.19994627, 0.025729552, 0.035035726, -0.0012207883, -0.08618888, 0.061205562, 0.009940555) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.23581573, 0.08002133, -0.15170844, 0.08872338, -0.25767094, -0.09273545, 0.18153891, 0.2544269, -0.084598936, -0.089766875, -0.14610913, 0.002247754, 0.1802837, -0.019625561, 0.30239686, -0.032793984) * go_1(0.0, -1.0);
|
||||
result += mat4(0.5223286, 0.10347663, 0.4000593, 0.25440502, -0.07646958, -0.31940606, 0.053407036, -0.09356492, 0.2738851, 0.23945184, -0.2907089, -0.45822915, 0.13415676, 0.17187089, 0.08731114, -0.27670014) * go_1(0.0, 0.0);
|
||||
result += mat4(0.059273496, -0.107137166, 0.12087539, 0.179237, -0.021209063, -0.02548005, 0.061256204, 0.033822674, 0.54491127, -0.2475085, 0.08055858, -0.4071213, -0.045093834, 0.07161349, 0.08219979, -0.31735933) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.29527053, 0.021469543, 0.07202354, -0.07103959, 0.03990857, 0.2490762, -0.19419849, -0.13916986, -0.05325315, 0.12922864, -0.041463424, -0.031249814, 0.073991664, -0.09723187, 0.35132217, 0.024760868) * go_1(1.0, -1.0);
|
||||
result += mat4(0.09606787, -0.0951808, -0.0059865676, -0.052033573, -0.3118038, 0.4432636, -0.12943317, 0.09484738, 0.10621756, -0.10550469, 0.11264014, 0.1402276, -0.012679125, -0.08809835, 0.029994955, -0.15121669) * go_1(1.0, 0.0);
|
||||
result += mat4(0.123397775, 0.048338536, -0.00975707, -0.103767075, -0.041053303, -0.07228534, 0.046792876, 0.0668788, 0.29554394, 0.012451002, 0.19568972, 0.112091154, 0.10882395, -0.0995439, 0.051324263, 0.24967718) * go_1(1.0, 1.0);
|
||||
result += mat4(0.2699648, 0.17300771, -0.16056584, 0.1099392, 0.11674778, -0.19811755, 0.111880325, -0.06075038, -0.095849104, -0.04510651, -0.04180761, -0.0052786698, 0.11037549, -0.24115366, 0.018509468, -0.07819484) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.10981622, 0.044488225, 0.050722387, -0.3146652, -0.0013019707, -0.24084032, -0.10475088, 0.026944289, 0.1592903, 0.33087498, 0.061839584, -0.043863457, -0.06904603, -0.08635262, 0.088630445, -0.15485142) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.06810522, 0.19927117, -0.08130387, 0.11612667, -0.015104349, -7.738651e-05, -0.06419643, -0.14813533, 0.026650215, 0.015038833, 0.08161237, 0.058321163, 0.015005185, -0.16189656, 0.024501886, 0.1927279) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.31858218, 0.11962043, -0.20560326, -0.13190113, 0.02138715, -0.057066392, -0.085771754, -0.124566585, 0.044749223, 0.13687828, 0.1195792, 0.14021616, 0.26204133, 0.05119197, -0.13980037, 0.050747477) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.21238558, -0.0734057, -0.2036023, -0.34308743, -0.29370925, 0.2393742, -0.37877437, 0.036869828, -0.17053255, -0.26900926, -0.23330869, 0.32902205, -0.4882585, 0.27430108, -0.033711653, 0.15501487) * go_2(0.0, 0.0);
|
||||
result += mat4(0.23487025, 0.085289046, -0.14281847, 0.12543266, 0.15871634, -0.13858907, 0.14810285, -0.0239261, 0.1286852, 0.07754033, 0.01072327, -0.14313328, 0.05480442, -0.12195059, 0.11341822, 0.08224607) * go_2(0.0, 1.0);
|
||||
result += mat4(0.19490337, 0.023521842, -0.24548791, 0.0035114093, -0.07937166, -0.07674376, 0.08365873, -0.003286068, 0.023862893, 0.009626835, 0.032829892, 0.0078141205, 0.053484406, -0.08297165, 0.09303188, 0.004273738) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.0032906602, 0.13636959, 0.027821168, 0.06270053, 0.024775786, -0.077529594, 0.03799126, 0.030000908, 0.031749167, 0.04360487, 0.004448846, -0.17835903, -0.30834544, 0.013150946, -0.13758293, -0.03296242) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.14166978, 0.034131095, 0.049779188, 0.09453289, -0.011406557, -0.07020709, -0.0031981543, -0.03443845, -0.00010218944, 0.0855161, -0.10951453, 0.042758763, 0.1718446, -0.1577923, 0.0410027, -0.04992991) * go_2(1.0, 1.0);
|
||||
result += mat4(0.1219178, 0.105126485, -0.041097324, -0.08110963, -0.04857337, -0.11544925, -0.14572923, 0.092435546, 0.091857366, 0.15425235, -0.020324683, -0.05764375, -0.020458939, -0.10527823, -0.085554086, 0.16358297) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.12372687, -0.009976829, 0.14252265, -0.1321053, -0.05965866, -0.1393898, -0.017603246, -0.02714342, -0.16824952, -0.23083204, -0.012299022, -0.06689838, -0.015830487, 0.21299921, -0.11637202, 0.0074968333) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.01979935, -0.182785, -0.015397454, 0.14175794, -0.011465284, 0.11285164, -0.036115747, 0.07150463, -0.083641894, -0.10221778, -0.13871445, 0.099696055, 0.04603662, -0.06463785, -0.007984529, -0.0032940735) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.072830334, -0.057334073, 0.09086239, 0.13039105, 0.06350303, 0.17130788, -0.2181585, -0.09137403, -0.31397742, -0.019071499, -0.017274613, 0.13762084, 0.10195637, -0.021455176, 0.04011394, -0.08029658) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.26982597, -0.40265098, -0.4151411, 0.038557775, -0.095602125, 0.3503172, -0.029988842, -0.03484708, 0.095536314, -0.0030311556, 0.31589827, 0.52763534, -0.12629713, -0.24356791, 0.0059487303, 0.42298427) * go_3(0.0, 0.0);
|
||||
result += mat4(0.054166105, 0.18827972, -0.081673265, -0.06720384, 0.09375001, 0.22173035, -0.14050071, 0.108400136, -0.15553835, -0.08716729, -0.037366748, 0.10971073, -0.02560103, -0.26702073, -0.05201882, 0.2432563) * go_3(0.0, 1.0);
|
||||
result += mat4(0.16196893, 0.0889265, -0.09887943, -0.042956755, -0.054403376, -0.123823255, 0.045847844, 0.017027669, 0.00539936, -0.112265736, 0.050549984, -0.104931094, -0.06883012, -0.25745714, 0.11155538, -0.15363649) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.22157209, 0.18200903, -0.13290548, 0.026721261, -0.06066069, -0.18150693, 0.08768983, 0.037362453, -0.1073367, -0.070236765, -0.41223463, -0.168915, -0.15517351, -0.13949952, -0.13307643, -0.15935421) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.026589906, 0.0930502, 0.05195435, 0.06301585, -0.01107014, -0.019382332, 0.027223695, -0.004045145, -0.15238355, -0.0345132, 0.06355168, 0.0011230056, 0.16690113, 0.0017829507, -0.0023939044, -0.09471834) * go_3(1.0, 1.0);
|
||||
result += vec4(0.024455175, 0.01669877, -0.066231176, 0.036848705);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf1
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.01763509, -0.17156707, -0.06841296, -0.026132878, -0.10600523, 0.11245994, 0.121395074, -0.09331501, 0.12764473, 0.0428028, -0.11837395, 0.2092563, -0.04357652, -0.0490096, 0.024701532, 0.10518723) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.17130826, -0.31987694, -0.07639005, 0.21362033, 0.058639023, 0.066175915, -0.25344703, -0.07923442, -0.14766373, 0.040518284, -0.031103026, -0.040075514, -0.051108997, -0.28214613, -0.18504949, 0.27544948) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.030991005, -0.011353306, 0.15237464, 0.15458584, 0.1250524, 0.19959912, 0.14049476, 0.38410887, 0.07378578, -0.017728366, 0.0963528, -0.043756213, -0.039577194, -0.11800575, -0.08392266, -0.07599512) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.022089608, -0.027317125, 0.051330008, -0.0075439885, 0.021650828, -0.0009390209, -0.12043464, 0.049332134, -0.055557396, -0.053297505, -0.0918705, -0.13089466, -0.10994107, 0.072746456, 0.11496739, -0.05225977) * go_0(0.0, -1.0);
|
||||
result += mat4(0.29730305, 0.26317745, 0.052159555, -0.32006654, 0.48288685, -0.049926184, -0.08091092, -0.13825637, -0.1485706, -0.288657, -0.41443697, 0.06856032, -0.23809211, -0.12953928, 0.4783034, -0.47557938) * go_0(0.0, 0.0);
|
||||
result += mat4(0.026139118, -0.23031352, 0.04861487, 0.033556074, 0.2702056, 0.22802536, -0.15385233, 0.1664119, 0.18749923, 0.36927548, -0.011473684, -0.11771165, -0.16859052, -0.4513202, 0.12863952, 0.02482837) * go_0(0.0, 1.0);
|
||||
result += mat4(0.0073229345, -0.061915245, 0.06710329, 0.0062416573, -0.00555983, 0.14592186, 0.11201052, -0.123630054, 0.32611257, -0.11279885, -0.059449438, 0.2891043, -0.10519016, 0.040108994, -0.012468261, 0.02083298) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.057483062, 0.08454755, -0.15529329, -0.12572923, 0.2600099, -0.02319978, -0.04037675, 0.11496361, 0.07728194, -0.12908956, -0.025529336, 0.112581626, 0.02971823, 0.11659056, -0.01298622, 0.017061908) * go_0(1.0, 0.0);
|
||||
result += mat4(0.22417091, -0.00222947, 0.04980858, 0.12260437, -0.025507605, 0.042577885, 0.120813504, -0.048522256, -0.038494784, -0.0072195013, -0.23012944, -0.020850847, -0.078296244, -0.014830018, 0.19759563, -0.10000253) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.032090195, 0.023757193, -0.08989734, 0.14419042, 0.0112194475, -0.093776144, -0.020197887, 0.29295877, 0.06872183, 0.09511462, -0.03245769, -0.06504889, 0.05132126, 0.00399527, 0.075911656, 0.250893) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.3418496, 0.25525784, 0.0018161442, 0.028484365, -0.17573346, -0.12457501, 0.18466166, 0.20209278, 0.10282706, 0.16353399, 0.025052028, -0.059714165, -0.055806916, -0.28651386, 0.112798095, 0.11624314) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.018793896, 0.07500149, -0.01728254, -0.1726998, -0.13333, 0.09590344, -0.036537904, -0.11522523, 0.19445558, 0.22680458, 0.12061006, -0.06225618, 0.1127748, 0.28380096, -0.07099846, -0.007440302) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.43887648, -0.10018577, -0.29267642, 0.12149727, -0.14333835, 0.04161915, 0.19442867, 0.16506511, 0.09655387, -0.0014398015, 0.13189743, -0.14068556, 0.049408, 0.0829072, 0.2950336, 0.36965907) * go_1(0.0, -1.0);
|
||||
result += mat4(0.41486958, -0.023498302, -0.37900022, -0.31752598, 0.13758768, -0.18782206, -0.31358528, 0.3330786, -0.4039293, -0.06539036, 0.032599606, 0.10663507, -0.26369813, -0.17365438, 0.20723309, 0.1801556) * go_1(0.0, 0.0);
|
||||
result += mat4(0.004117444, -0.14894462, 0.14915143, -0.047375835, -0.2609916, -0.10172324, -0.14925237, -0.33830285, 0.12131607, -0.18156646, -0.42382464, -0.052582145, 0.2329045, -0.4576963, 0.13756892, 0.055571318) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.31689477, 0.017058033, -0.01904924, -0.016893756, -0.011479519, 0.07316262, -0.07086077, 0.08923511, -0.08190091, -0.025866933, -0.06909204, -0.028601022, 0.023224542, 0.03082087, 0.2230426, -0.16713654) * go_1(1.0, -1.0);
|
||||
result += mat4(0.13457374, 0.110913865, -0.1130815, -0.031438913, -0.55201167, 0.04831016, 0.25107765, -0.014003224, 0.19532952, 0.02062346, 0.04839241, 0.088673405, 0.30325848, -0.20222804, -0.085780576, 0.22512968) * go_1(1.0, 0.0);
|
||||
result += mat4(0.076354, 0.021940092, -0.16170324, 0.0025543426, -0.0032400405, -0.0046705627, 0.06241069, -0.031247333, 0.098353796, 0.03723474, 0.22971998, -0.017877292, 0.119858086, 0.008041448, 0.2140585, 0.10343376) * go_1(1.0, 1.0);
|
||||
result += mat4(0.08627595, 0.04532834, 0.027579082, -0.16222088, 0.15583228, -0.14371829, -0.07243855, -0.111895435, -0.14438897, -0.10250594, 0.0034202964, -0.066547595, -0.034390844, -0.021545287, 0.014540157, -0.10215731) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.19720152, 0.21534947, 0.1130938, -0.011730973, 0.013247983, -0.10344174, -0.1906514, -0.015767017, -0.020093633, -0.26487067, -0.005960781, -0.057149183, 0.030110173, 0.047692046, -0.19308545, -0.25292158) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.039498243, 0.053682897, -0.01844695, -0.017540915, 0.039454967, -0.27696076, 0.09503274, -0.038958035, 0.17321438, -0.036311295, 0.03123055, 0.02310311, 0.040591653, 0.0054627894, -0.03520426, -0.026101988) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.055991564, 0.06512919, -0.12532505, 0.024075158, -0.04926237, -0.11701171, 0.026792146, 0.013033238, -0.052847516, -0.01550091, -0.008442071, -0.077945165, -0.033220004, -0.13678443, -0.07040586, 0.121846326) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.19537796, -0.016634773, 0.10707109, -0.024361614, -0.16002733, -0.44066608, 0.16488662, 0.013152995, 0.22407806, 0.12854017, 0.19028598, -0.08379244, -0.05594235, -0.15909895, 0.511962, 0.39027596) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.032652248, 0.06004893, 0.011166194, 0.102761306, -0.035113614, -0.29961765, -0.013817978, 0.20938557, 0.08488225, -0.1118558, -0.0375328, -0.035511103, 0.0046933405, 0.20203683, -0.13552529, -0.12685429) * go_2(0.0, 1.0);
|
||||
result += mat4(0.03054923, 0.08224908, -0.059128158, -0.02583655, -0.02133876, 0.0048713544, 0.10848829, 0.06324404, 0.028332822, -0.011002306, -0.027557913, -0.06072362, 0.1019048, -0.02587316, 0.08563405, -0.08119947) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.10568117, 0.1075248, 0.19379964, -0.14337265, 0.019374132, -0.0907804, -0.13827625, -0.03628561, 0.014735499, -0.026882607, -0.25948793, 0.034926686, -0.05988073, -0.22735636, 0.053511668, 0.04765336) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.029848114, 0.09183966, 0.084713496, 0.09422864, 0.069713995, -0.10584984, -0.020899031, 0.059645247, -0.075805016, -0.01828552, 0.06689195, -0.13804196, -0.023465823, -0.034038994, -0.12946706, 0.058709413) * go_2(1.0, 1.0);
|
||||
result += mat4(0.061918218, 0.038984764, 0.013660938, -0.19340219, -0.014949839, 0.12946278, 0.12725051, 0.13429146, 0.05993008, -0.015394284, 0.011232483, 0.0344157, 0.022161875, -0.023923954, 0.061736204, 0.025963215) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.048136763, 0.03162042, -0.01967249, 0.06374493, 0.034645267, 0.22403605, 0.036197048, -0.06903216, -0.1024706, -0.0005459356, 0.049185563, 0.16309108, 0.07394778, 0.10351343, 0.28430694, -0.13531347) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.14705071, -0.09458433, 0.03063114, 0.07901115, -0.11911086, -0.06428132, -0.013549552, -0.041342866, -0.20770676, -0.15104479, 0.054365363, -0.11652907, 0.05639815, 0.070518605, 0.0017846811, -0.00056205114) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.27148908, 0.07358356, 0.13644488, -0.13824654, 0.0112991175, -0.021521023, -0.10197379, 0.007816017, -0.13314332, 0.12318473, -0.043214846, -0.15759036, -0.19744353, -0.10267182, -0.28249928, 0.11233295) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.096474804, 0.17893109, 0.014679829, -0.21218887, -0.24170275, 0.10603527, 0.05375366, -0.059315052, 0.17087384, 0.13633691, -0.37958893, 0.43264794, 0.17829923, 0.06485103, -0.37551817, -0.22082718) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.30536333, -0.033212308, -0.25232, 0.11730442, -0.11176368, 0.26223183, -0.049025323, -0.01375941, -0.29028055, 0.16842811, -0.035684332, -0.4180911, -0.1611732, 0.07683385, -0.14263596, 0.17508087) * go_3(0.0, 1.0);
|
||||
result += mat4(0.23580009, 0.025621435, -0.15757325, 0.008123166, -0.021905439, -0.02162503, -0.059497356, -0.01636353, 0.047654126, -0.084423855, -0.033733923, 0.0127116265, -0.059593942, -0.053935718, -0.050729543, 0.013887048) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.19232626, 0.07915767, -0.05909752, 0.007695347, 0.058876406, 0.057521783, -0.080253534, 0.2011056, -0.27965516, -0.08033169, -0.13025513, 0.12854645, 0.053400308, -0.18445957, -0.18463044, 0.27920377) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.061806213, -0.020037206, 0.003183183, -0.029844081, -0.039553937, 0.028905323, -0.11367984, -0.097321615, -0.10112643, 0.0039709485, -0.06020118, -0.23871279, -0.077974856, 0.05806996, -0.21440302, 0.11898043) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.023832673, 0.03702965, -0.04749135, -0.10982549);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.030931145, 0.013683292, -0.0650242, -0.028732346, 0.120067924, -0.029404473, 0.0038229884, -0.14631765, 0.041900825, -0.076596744, -0.11096378, -0.27100095, 0.0052598766, -0.05929686, -0.06816563, -0.086864315) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.043620087, -0.16360405, 0.006527374, 0.15706524, 0.08338088, -0.19027525, 0.22595987, -0.054963548, 0.01825031, -0.03149212, 0.025471251, 0.06429379, -0.011633275, -0.079389006, -0.0030728737, 0.17345747) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.011275288, -0.10668036, 0.05718997, 0.010336089, 0.33393976, -0.2029354, 0.075444475, -0.092244044, 0.07605498, 0.20125951, 0.10493973, -0.12306946, 0.03658231, 0.08233366, -0.12205888, -0.116969004) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.0070305974, 0.105127215, 0.006041873, 0.26743913, 0.028119443, 0.14823505, -0.28344348, 0.12362866, -0.1215781, 0.08104382, 0.102011785, 0.085380934, 0.061244503, -0.06230063, -0.05353345, 0.1166729) * go_0(0.0, -1.0);
|
||||
result += mat4(0.08945733, 0.4101902, -0.06404005, 0.040728435, 0.13076581, -0.20805469, -0.10897316, -0.14924604, 0.10090762, 0.015475414, 0.26346552, 0.12096677, -0.20199244, 0.2780031, 0.18515368, 0.35105625) * go_0(0.0, 0.0);
|
||||
result += mat4(0.07463155, 0.26932517, -0.06768551, 0.10470878, -0.1423996, 0.013550665, -0.06167201, -0.1022994, -0.3107166, -0.15609552, 0.1695213, -0.1277181, 0.12582655, -0.1596128, 0.015612055, -0.19826376) * go_0(0.0, 1.0);
|
||||
result += mat4(0.011745468, 0.006471601, 0.008110513, 0.025831396, 0.1272883, -0.221959, 0.11993834, -0.007903633, 0.009993582, -0.10170755, 0.026594637, -0.027883623, 0.030666083, -0.036415886, 0.007469573, 0.0674783) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.022760388, -0.10911659, -0.012589904, -0.046462692, 0.36987287, 0.71668935, -0.04466556, 0.12082762, 0.0026539841, 0.07070946, -0.00020439121, -0.13925348, 0.08672072, 0.20075354, -0.066352285, 0.14655356) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.081081845, -0.21956222, 0.06781787, -0.106362104, -0.03016425, -0.010460211, -0.009725996, -0.009805538, 0.07037355, 0.19254607, 0.038890257, 0.29580075, -0.10355764, 0.12613009, 0.02485986, -0.031927988) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.13882205, 0.21770848, 0.015392157, 0.010310204, 0.008225721, 0.07457836, 0.09984027, -0.25452816, 0.2193511, -0.22262146, -0.12950355, 0.026151875, 0.022114651, -0.030566849, 0.034688126, 0.03047327) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.0363441, 0.19290726, -0.1143055, 0.30871987, -0.05780708, 0.082128406, -0.115280904, 0.07636388, 0.48947453, -0.29715258, 0.146737, -0.3275992, -0.055972476, -0.09991753, 0.17435446, 0.10917291) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.026389305, 0.054523308, -0.028950177, 0.06913328, -0.18626037, 0.08829993, 0.10407121, 0.001246911, 0.103938825, -0.3117343, -0.045564886, 0.07316613, 0.0027089121, 0.099437356, -0.046500806, -0.0927284) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.051037624, -0.2068234, 0.061572235, -0.3345198, 0.16960172, -0.30289862, -0.002583443, 0.39312238, 0.08246557, 0.16374862, -0.31902805, -0.13205275, -0.032050006, 0.01670186, 0.13852347, 0.120012194) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.67096996, -0.06274476, 0.18575665, 0.80282855, 0.23201196, -0.0054729837, 0.050396994, -0.42014772, 0.34904522, 0.26281372, 0.24697208, 0.55475426, 0.49850988, -0.06581312, -0.0068906257, -0.15741143) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.04252036, -0.28224963, 0.009723064, 0.116357096, 0.2992567, -0.26702902, -0.05648925, 0.12729199, -0.37574205, 0.54211813, -0.25248805, -0.13023548, 0.18903324, -0.5182459, 0.0141203115, -0.19444294) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.0017735233, -0.010132458, -0.040924776, -0.13767008, 0.20757031, -0.06509882, -0.09756446, 0.018974079, 0.090851985, -0.010158765, -0.03999607, -0.12055641, 0.03629025, -0.018645551, -0.05506811, -0.014202848) * go_1(1.0, -1.0);
|
||||
result += mat4(0.16203491, 0.011118734, -0.18486023, -0.024290733, -0.3673846, -0.20295864, 0.23055002, -0.1555852, -0.02706522, 0.03262891, 0.008724611, -0.03760652, -0.20946771, -0.01951837, 0.16955496, 0.11690098) * go_1(1.0, 0.0);
|
||||
result += mat4(0.0783421, 0.22656651, -0.15715368, -0.024174158, 0.020260733, 0.032390315, -0.029133298, 0.086601086, 0.13871798, -0.12525433, 0.16097449, 0.058946393, 0.029865682, 0.08508385, 0.040569812, -0.09402932) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.05063873, 0.11269313, -0.057484943, -0.13579641, 0.047973365, -0.07103839, -0.07838756, -0.0028928046, -0.019466015, 0.018428024, 0.010016324, -0.057396665, -0.19495595, 0.034307264, -0.022888038, 0.08112259) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.09790086, 0.10613111, 0.06611674, 0.19356097, -0.00073371036, -0.019078335, 0.076719105, -0.016212497, -0.3283475, -0.07547389, -0.08140701, 0.3185625, -0.25060275, 0.16820994, -0.123497784, 0.43272668) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.06365342, 0.11186735, -0.17493224, -0.04207358, 0.0003117533, 0.034089327, -3.067692e-05, -0.03422754, 0.16267666, 0.054771993, 0.048384454, -0.041866794, 0.0036008756, 0.0021496525, 0.20258942, -0.06297619) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.03578836, 0.08763908, -0.22370125, -0.32465744, 0.019142643, 0.011316954, 0.17920344, 0.031633645, 0.03766343, -0.116487674, -0.05281752, -0.018965483, 0.049297336, -0.34511214, 0.42598158, 0.051361635) * go_2(0.0, -1.0);
|
||||
result += mat4(0.26638633, -0.33628765, 0.04437907, 0.09616201, -0.020049393, 0.2560829, -0.027108455, 0.255752, 0.3666511, 0.052277412, -0.46667686, 0.48482272, 0.51302284, -0.06941614, -0.17967525, -0.07889891) * go_2(0.0, 0.0);
|
||||
result += mat4(0.18503937, 0.088710256, 0.2083147, -0.20758459, -0.036416974, 0.018303726, 0.03729963, -0.035969947, -0.2685231, -0.42169708, -0.039593916, -0.02642618, 0.29050872, -0.25723743, -0.111259766, 0.15001127) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.026473878, -0.07241443, 0.022400148, -0.03214132, 0.0859297, -0.0036677981, -0.07039137, 0.03703108, 0.042322673, -0.01222808, -0.08151938, 0.033109214, -0.048737407, 0.25929528, -0.40535828, -0.123594694) * go_2(1.0, -1.0);
|
||||
result += mat4(0.10233285, 0.22455986, -0.13368733, 0.033236265, -0.052114893, -0.11709317, 0.009709581, 0.19201641, -0.02973698, 0.032114245, -0.09771862, 0.085680574, 0.15827927, -0.15042172, 0.21833214, -0.13262676) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.08460587, -0.09473209, 0.019323658, -0.057233352, 0.0019434267, -0.14437936, 0.034232683, 0.0030602294, -0.023598112, 0.10692026, -0.09960999, 0.005887181, 0.014738836, -0.32473162, -0.10886747, -0.08365826) * go_2(1.0, 1.0);
|
||||
result += mat4(0.10900178, 0.00080280803, -0.14009437, -0.053074867, -0.07811151, -0.03456029, -0.104943685, 0.016918905, -0.11335709, 0.079421654, 0.13481963, 0.037818357, -0.027339859, 0.05856774, -0.044562265, 0.03908084) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.07628258, -0.23815769, 0.2840278, -0.3541637, -0.044292126, -0.09310441, -0.1335055, -0.031899665, -0.11981227, 0.24012394, -0.041896038, -0.10168982, 0.20248915, -0.10036763, -0.044115108, 0.08520525) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.07234102, -0.119480744, -0.01401321, -0.025182616, -0.031284854, -0.050089385, 0.014808948, 0.038662236, -0.18539418, 0.017342187, 0.023812262, 0.13428104, 0.020824855, -0.07433546, 0.054307282, 0.08511016) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.11046813, -0.04663274, 0.33497185, 0.023273284, -0.24681108, 0.116665915, 0.12045893, 0.13306482, -0.039098527, 0.04747061, 0.042796664, 0.053514794, 0.011861975, -0.048702, 0.008408589, -0.09497112) * go_3(0.0, -1.0);
|
||||
result += mat4(0.34634927, 0.37973458, -0.79267627, -0.7362719, 0.35489878, -0.07635863, 0.24082923, -0.27480397, -0.3236968, -0.25523046, 0.05118527, -0.040529836, -0.6000509, 0.39020586, 0.27632973, 0.5141453) * go_3(0.0, 0.0);
|
||||
result += mat4(0.16761221, -0.033125393, 0.00561569, 0.083019435, -0.101278506, 0.07810264, 0.12060661, 0.16048536, 0.14257826, -0.15996903, 0.018831912, -0.094429865, -0.22227801, 0.426937, -0.054677445, 0.05067348) * go_3(0.0, 1.0);
|
||||
result += mat4(0.02233958, 0.02608942, -0.045318656, 0.06509929, 0.035911568, 0.025316885, 0.0840986, 0.08326237, 0.048455603, -0.13630742, 0.07230253, -0.047261715, -0.092630014, 0.04786565, 0.10354939, -0.07094341) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.1463382, -0.14900577, 0.2835977, -0.106733374, -0.11554754, -0.168429, -0.1411373, -0.20654152, -0.06388508, 0.039648015, 0.08543832, -0.13253337, 0.017264463, -0.06346233, -0.10823598, 0.067361064) * go_3(1.0, 0.0);
|
||||
result += mat4(0.04419582, 0.039152585, 0.06222691, 0.05757103, 0.012084537, 0.051425997, -0.061130576, 0.16752882, 0.07497411, 0.13495837, -0.15585983, -0.02050144, -0.08555421, -0.09147339, 0.025115604, 0.05948922) * go_3(1.0, 1.0);
|
||||
result += vec4(0.00590038, 0.03082865, 0.002111702, -0.03330112);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf1
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.009029573, 0.029218858, 0.029705316, -0.019268971, -0.0023235187, -0.072589695, 0.1424836, 0.09049359, 0.04342995, 0.18134294, 0.018145641, 0.14789368, 0.050923645, 0.06524081, 0.036812488, 0.11108108) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.026506428, 0.016968496, 0.015961196, 0.010030791, -0.3141888, -0.06769598, -0.23920257, -0.031002127, -0.07351358, -0.19290134, -0.24282931, -0.18831016, -0.0928966, 0.075177215, -0.19699521, -0.05810917) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.017991852, -0.079427645, 0.035970494, -0.017095685, -0.27197137, -0.20046075, 0.2616644, 0.021876303, -0.077394076, -0.04978692, 0.20363241, -0.013741705, -0.032103598, 0.14403099, 0.01442474, 0.048115995) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.16939245, -0.001777, 0.026244136, -0.14122388, -0.056853324, 0.54357284, -0.19769607, -0.03187079, 0.04559263, -0.16048127, 0.12830622, 0.1442168, 0.006611398, -0.01618195, 0.012860053, -0.16539487) * go_0(0.0, -1.0);
|
||||
result += mat4(0.13116026, -0.006161343, 0.7209969, 0.18338475, 0.3099777, 0.6500026, 0.3883795, -0.021434233, 0.31667513, 0.008917659, 0.14124091, -0.22335114, 0.12198921, -0.16449445, 0.08773425, 0.30054978) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.10413989, -0.10316161, 0.04342709, -0.021252686, 0.120892406, 0.37798002, -0.35963747, 0.021069285, 0.37587845, -0.08159587, 0.011139747, 0.2501104, -0.094568014, 0.037900843, -0.025109999, -0.030106556) * go_0(0.0, 1.0);
|
||||
result += mat4(0.09680291, -0.040868275, 0.051731605, 0.089064725, -0.56098557, -0.38148618, -0.017037416, 0.08508287, -0.019247344, 0.019857002, -0.03512887, 0.031057188, -0.09648583, -0.04474188, 0.028748507, -0.11880965) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.010236943, 0.04257042, -0.08202597, -0.004203426, -0.26801527, -0.11716526, -0.017402772, -0.05819106, -0.13394608, 0.0234606, -0.15404865, -0.06801164, -0.0047627664, -0.1975249, 0.09420144, 0.23249897) * go_0(1.0, 0.0);
|
||||
result += mat4(0.107361935, 0.07373787, 0.06242962, 0.05236332, -0.028867323, 0.025924044, -0.042526353, -0.0015729597, -0.1323144, -0.4040712, 0.023919407, -0.09535502, 0.049100045, 0.081110805, 0.08946112, 0.058505684) * go_0(1.0, 1.0);
|
||||
result += mat4(0.13236825, -0.04468476, -0.04426802, 0.031087106, -0.09093992, -0.07470971, -0.01591504, 0.05924266, -0.21910913, 0.065537, -0.18358919, -0.02533145, -0.1512009, -0.04953928, 0.015540006, -0.0043442883) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.14016777, -0.1086958, 0.16316028, 0.050777458, 0.23148167, 0.04944809, -0.10599886, -0.10447021, -0.40729257, -0.10926556, 0.069055155, 0.110635415, 0.108922414, -0.1716362, 0.10743909, -0.102534756) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.017795928, -0.066930935, 0.09396082, 0.092585504, 0.14223933, 0.059458215, 0.072033696, -0.04507726, -0.19956456, 0.1251282, -0.31733638, -0.10465904, 0.08546377, 0.048638333, 0.031372465, -0.08720661) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.108719654, -0.092161916, -0.014724377, 0.20068261, -0.24350016, 0.2113636, -0.07483714, -0.45665312, -0.25134233, 0.2753893, -0.11324696, -0.04472, 0.1576102, -0.045395147, 0.06013951, -0.12507361) * go_1(0.0, -1.0);
|
||||
result += mat4(0.546225, -0.281897, 0.19477816, -0.116612464, -0.3145171, -0.41660902, 0.333625, 0.35902345, 0.48333502, 0.4662005, 0.10222491, -0.15314859, -0.3036888, 0.22849742, 0.20740797, 0.41399437) * go_1(0.0, 0.0);
|
||||
result += mat4(0.007284074, 0.0393942, -0.31192186, -0.15687793, -0.289214, -0.015956698, -0.24718472, -0.1637855, -0.00765037, 0.26677555, 0.20215511, 0.37790874, -0.22096673, 0.25287116, -0.2446764, -0.13610223) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.16734968, 0.16721225, -0.053508647, -0.041097626, 0.062356673, 0.07812319, -0.263546, -0.39739034, 0.003389846, 0.12676363, -0.13175991, -0.19019242, -0.011847587, -0.007580052, -0.023946386, 0.046034034) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.17047611, 0.13298693, -0.07506747, -0.045542978, 0.33571973, 0.20192616, 0.30674616, 0.25668672, -0.24134545, 0.031693842, -0.009647641, 0.040534843, 0.03159419, -0.1100516, 0.11371316, 0.06098735) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.05518961, 0.19402988, -0.09646874, -0.059196774, -0.0073436056, -0.1381309, 0.06868669, 0.061328378, -0.1480867, -0.15774113, -0.022572191, 0.122521356, -0.04067007, -0.10145177, 0.13006335, -0.099452734) * go_1(1.0, 1.0);
|
||||
result += mat4(0.06962972, 0.07768411, 0.021085173, 0.108355984, -0.03132525, 0.10220273, -0.11626593, -0.14104277, 0.018778645, -0.024237925, 0.048783034, 0.09074447, 0.4120426, -0.01948466, 0.073218934, 0.055681944) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.22553118, -0.12923603, -0.22068842, -0.35037905, 0.005709937, -0.09528472, 0.08718399, 0.13200706, 0.17220478, 0.096844435, -0.30439013, -0.14122063, 0.15733318, -0.1014675, 0.33836862, 0.042193163) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.15826897, -0.034870047, 0.09295099, -0.17674965, -0.042326324, 0.06680338, -0.074267656, -0.0631393, -0.11267909, -0.19795708, 0.22005288, 0.35703793, 0.033995766, -0.12663686, -0.02449896, -0.123250045) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.021434195, 0.058398597, 0.04828315, -0.0016824572, -0.04291545, -0.0744907, -0.07698706, -0.15937585, -0.18852457, -0.17966963, 0.023800725, 0.025979731, -0.51412296, -0.018316887, -0.23076254, -0.12298674) * go_2(0.0, -1.0);
|
||||
result += mat4(0.16054317, -0.0002730893, -0.54173076, -0.62443435, 0.04300197, -0.08529622, 0.15392275, 0.15742144, 0.025834514, -0.2800517, -0.17600477, 0.0020806703, -0.3010582, 0.45233512, 0.25595665, 0.103661336) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.024034392, -0.43800178, 0.28606912, -0.20908915, 0.078471914, -0.030501373, -0.059055753, 0.050494444, 0.063274644, -0.025071034, 0.17561312, -0.100698635, -0.25631955, 0.039981876, -0.18506624, 0.08366402) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.1413656, 0.03589635, -0.020917566, 0.017598262, 0.020156413, -0.018854238, 0.027228508, -0.03806087, -0.021715842, 0.071974196, -0.040065665, 0.08459291, -0.23530225, 0.16599682, -0.2772327, 0.10041177) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.055056706, 0.1286236, -0.11890451, -0.1790546, 0.16517544, -0.040448934, 0.12548013, 0.017075695, 0.07185459, -0.13236302, 0.19354409, 0.12767012, 0.31120765, 0.16378082, -0.036915366, -0.19724306) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.02225051, 0.033263147, 0.003279449, 0.08826271, -0.047833472, 6.574577e-05, 0.13721916, 0.04801998, -0.014958419, 0.08791209, -0.08076282, 0.024002168, -0.18028922, 0.23835851, -0.23309888, -0.119310364) * go_2(1.0, 1.0);
|
||||
result += mat4(0.044960875, 0.18821983, 0.027640678, 0.013462449, 0.19011214, 0.21559924, -0.03329638, 0.07234414, 0.030880248, -0.11273214, 0.102028474, 0.12203351, 0.035855662, 0.008828778, 0.007218363, -0.012421797) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.09450626, 0.025191775, -0.10738468, 0.16237053, 0.073676676, 0.12488881, -0.048748355, 0.007877263, 0.3572506, -0.07911043, 0.14684045, 0.0015310893, -0.33411503, -0.1151223, 0.004201752, 0.017775744) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.10607509, -0.008143826, -0.08448629, -0.27557802, 0.0046665915, 0.008158659, 0.030826218, 0.020516023, 0.2333065, -0.017463414, -0.041772116, -0.03027809, -0.028166672, -0.080471426, 0.048199337, 0.08341059) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.14640257, -0.18334304, -0.061674733, 0.0008892598, -0.2374775, -0.2721524, -0.040371176, 0.26362613, 0.19872928, -0.11246391, 0.0842288, 0.11188515, 0.0045209546, -0.04250933, -0.0738212, -0.069005966) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.08760266, 0.4816288, -0.21241407, 0.22734411, -0.1783721, -0.26842996, 0.099888, -0.2867675, 0.085521065, -0.3780281, -0.018543908, -0.039699722, 0.75688565, -0.5333645, 0.47567275, 0.09518891) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.04072665, 0.05998423, -0.48314768, -0.29495844, 0.10358383, -0.09816629, 0.028586809, -0.047708735, 0.008320228, 0.04089551, -0.18359782, -0.27615002, 0.12414414, -0.072417594, 0.25932562, 0.30268723) * go_3(0.0, 1.0);
|
||||
result += mat4(0.14481631, 0.06484443, -0.09898657, -0.06553556, 0.25750044, -0.07265585, 0.12903488, -0.022347894, -0.04693863, -0.000107379274, 0.030295763, -0.0325354, 0.086214684, -0.021326948, 0.039682828, -0.034843277) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.031971477, -0.25145087, 0.03931631, 0.14262606, -0.06044626, 0.22820354, -0.10506207, 0.18064679, 0.0069641788, 0.01477993, -0.003626875, 0.118767865, 0.109416224, -0.002998205, 0.035680585, 0.07843882) * go_3(1.0, 0.0);
|
||||
result += mat4(0.03375426, -0.059815384, 0.11632834, -0.12411481, 0.022583738, 0.02544465, -0.054889992, -0.07031964, -0.10140042, 0.16750422, -0.1448294, -0.09316004, 0.035582513, -0.026138382, -0.031955894, 0.040148776) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.03573331, 0.032919675, 0.011109369, 0.008329268);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_last_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.11498094, -0.053904895, -0.11520678, -0.05479549, 0.028396055, 0.032767884, 0.052479446, 0.05257866, -0.25706592, -0.3454966, -0.24713765, -0.2854201, -0.10287636, 0.0023146886, -0.09190338, -0.011193905) * g_0;
|
||||
result += mat4(-0.05461422, 0.008780496, -0.07738697, -0.032230727, -0.047554165, -0.025061952, -0.051897213, -0.009545297, -0.14548294, -0.15184018, -0.01313442, -0.015299784, -0.0007883845, -0.12866738, -0.15260352, -0.27081275) * g_1;
|
||||
result += mat4(0.11007706, 0.035344437, 0.11020841, 0.0425353, 0.1613199, 0.18417408, 0.09274313, 0.11943135, 0.106862, 0.079875536, 0.0937752, 0.068030775, 0.029093558, -0.06441164, 0.06467169, -0.021989612) * g_2;
|
||||
result += mat4(0.049548414, -0.012455486, 0.07185561, 0.021865537, 0.020969186, -0.03374196, -0.024260623, -0.07739141, 0.07164591, 0.12741035, 0.0379913, 0.076403245, 0.07049977, 0.0744538, 0.0062989634, 0.01818882) * g_3;
|
||||
result += mat4(-0.12511204, -0.010836819, 0.13709816, 0.22472954, 0.21280868, -0.006484726, 0.17554289, -0.009977173, 0.078398876, 0.20698707, 0.13432744, 0.29740283, -0.24750128, -0.32757792, -0.19807857, -0.2537023) * g_4;
|
||||
result += mat4(-0.27207088, -0.1385644, -0.2166476, -0.07687419, -0.20300622, -0.29678395, -0.13135734, -0.20851587, 0.0361364, 0.011243289, -0.06845459, -0.11796941, 0.11575868, 0.070215136, -0.10295678, -0.12281369) * g_5;
|
||||
result += mat4(0.13619795, -0.0019436983, -0.12701888, -0.25933513, -0.20134166, 0.00062823144, -0.076756015, 0.11002947, 0.0059049693, -0.18756741, -0.0718802, -0.2589954, 0.23413423, 0.30107784, 0.14445266, 0.18920745) * g_6;
|
||||
result += mat4(0.1494216, 0.0587532, 0.05478662, -0.039123338, 0.23322394, 0.29950607, 0.24384268, 0.27843767, -0.16094431, -0.04705998, -0.016345032, 0.028868208, -0.102872886, -0.04659664, 0.104105346, 0.14305067) * g_7;
|
||||
result += mat4(-0.001037014, 0.010001526, -0.0052278573, 0.024779709, 0.06857274, 0.067640975, 0.085439384, 0.09242789, -0.066597246, -0.055928994, 0.0015658981, 0.016131008, -0.03524695, -0.018364554, -0.047754433, -0.014295886) * g_8;
|
||||
result += mat4(-0.042207, 0.02835915, -0.1404656, -0.08563323, -0.030979915, -0.0673764, 0.10733943, 0.057902794, 0.00022424995, -0.0023634837, -0.10778953, -0.10202357, -0.020368295, -0.019088887, -0.06875738, -0.08504131) * g_9;
|
||||
result += mat4(-0.00043458896, 0.00045652856, -0.02016843, -0.020062413, -0.08740103, -0.042085808, -0.10644177, -0.09226477, 0.11212161, -0.00048174805, 0.021872435, -0.05868698, 0.0333954, 0.058184672, 0.05532576, 0.07621587) * g_10;
|
||||
result += mat4(0.054245148, 0.001020329, 0.09106849, 0.05303779, 0.009889632, 0.01309413, -0.09187347, -0.08618193, -0.011621187, 0.016222361, 0.061095525, 0.060885344, 0.078050986, 0.0111776795, 0.08829944, 0.032022282) * g_11;
|
||||
result += mat4(0.01643529, 0.02285545, -0.03498564, 0.00769657, -0.0042474116, 0.015836312, -0.025771018, -0.0016368, -0.008897948, -0.012588166, -0.01416411, -0.003578984, 0.025991246, 0.021237152, 0.017450012, 0.025172485) * g_12;
|
||||
result += mat4(0.014568868, 0.017796224, -0.036679734, -0.03138748, 0.019457601, -0.027607411, -0.004529679, -0.038048342, -0.054055385, -0.03876025, 0.041948095, 0.005869784, 0.02439633, 0.05177997, 0.016000897, 0.0057169925) * g_13;
|
||||
result += mat4(-0.03021866, 0.017678728, -0.01371109, 0.013548159, -0.0038099394, -0.014066414, 0.028093752, 0.0027308422, -0.010615999, 0.012673458, -0.03028171, -0.016818244, -0.06530097, -0.018845048, -0.0072947564, -0.0038243714) * g_14;
|
||||
result += mat4(-0.019006258, -0.007847591, 0.03690709, 0.06714211, 0.0073993434, -0.009766907, -0.0021441753, -0.01308625, 0.06658726, 0.06701995, -0.027305668, -0.016032105, -0.028976806, -0.0036668575, -0.0027825525, 0.0105632655) * g_15;
|
||||
result += mat4(0.028945107, -0.0014701135, 0.048950657, -0.01923516, -0.0014054152, 0.002650635, -0.005300331, 0.004860559, 0.011158468, 0.005940625, -0.012095051, 0.0041518128, -0.020433836, -0.025870577, -0.0007547932, -0.026509356) * g_16;
|
||||
result += mat4(-0.004545374, 0.04264545, 0.021741537, 0.029115127, 0.04225599, -0.0055392785, 0.026570829, -0.031795148, -0.008307126, 0.020176455, 0.010904648, 0.017765503, -0.10806103, -0.01776947, 0.00070428237, -0.06356262) * g_17;
|
||||
result += mat4(-0.05663172, 0.05908046, -0.03837452, 0.06636983, -0.007960516, -0.06384041, 0.023125881, -0.030108837, 0.0038054318, -0.023263922, 0.020264054, -0.0062937695, 0.031630237, 0.020909082, 0.03594235, 0.035879835) * g_18;
|
||||
result += mat4(-0.0050448794, 0.033650696, -0.002830413, 0.035174295, -0.024521282, 0.013054315, -0.020833842, 0.037953895, 0.08249671, 0.024239466, -0.012758333, -0.027316988, 0.051040914, 0.0005025873, 0.039778862, 0.0024668393) * g_19;
|
||||
result += mat4(0.017232442, 0.022482058, 0.020233413, 0.024337437, 0.07986929, 0.06234036, 0.12662584, -0.05271183, -0.009718745, -0.0046989853, -0.0030333172, -0.04034237, -0.0113442, 0.022746231, -0.035293855, -0.009433693) * g_20;
|
||||
result += mat4(0.015766997, 0.013647276, -0.029327558, 0.039106004, -0.010398323, -0.032851525, 0.02908329, -0.003789618, 0.12963496, 0.010851003, 0.1126276, -0.049255487, 0.06867432, 0.07970792, 0.017840397, -0.026481882) * g_21;
|
||||
result += mat4(-0.058729574, -0.07886952, 0.033267397, 0.02755372, -0.0172006, 0.012404398, -0.0230168, -0.015059758, -0.09239916, -0.029533267, -0.043251917, 0.0035152994, 0.022931995, 0.101714484, -0.044946067, 0.094993) * g_22;
|
||||
result += mat4(-0.04708704, -0.032475296, -0.03228093, -0.08810475, 0.013745045, 0.027828002, -0.031922746, 0.022986397, -0.061620213, -0.03694645, -0.055026993, 0.0031291894, -0.028799903, -0.0025357977, -0.03441407, 0.0028600092) * g_23;
|
||||
result += mat4(0.058981724, -0.10447273, -0.088705614, 0.16546178, -0.023549391, -0.008831522, -0.018411588, 0.029640056, -0.068086684, -0.05414636, -0.029401174, 0.036180343, -0.031988926, -0.047249753, 0.008162177, 0.00548062) * g_24;
|
||||
result += mat4(0.05287462, -0.030657746, 0.02821435, 0.037005343, 0.03534311, -0.15614955, 0.07085459, -0.11997641, -0.009156166, -0.021968868, -0.054147746, -0.07307657, -0.006428544, -0.017528288, 0.012614676, 0.037840024) * g_25;
|
||||
result += mat4(-0.021977803, 0.047799855, 0.02660416, -0.07292106, 0.045195807, -0.0056674764, 0.10824326, -0.112114795, 0.1447127, -0.0119616175, 0.0011661504, -0.04553905, 0.13048342, 0.14574122, -0.105522245, -0.102792375) * g_26;
|
||||
result += mat4(-0.16397473, 0.15785863, -0.06666504, -0.01682913, 0.06070918, 0.070222184, 0.037701584, 0.026657054, -0.0835267, -0.009457008, 0.13232987, 0.13508691, -0.056414206, -0.06818828, 0.079076104, 0.032249212) * g_27;
|
||||
result += vec4(-0.10795144, -0.09953324, -0.055413827, -0.03875493);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_last_tf1
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.024905335, -0.0020974763, 0.02695263, 0.00016802056, -0.024053082, -0.02133723, -0.031614035, -0.031826317, 0.120421864, 0.10555479, 0.08609448, 0.116875134, 0.046175968, 0.04224941, 0.059216674, 0.035143953) * g_0;
|
||||
result += mat4(0.059397914, 0.016519934, 0.07189327, 0.047407165, 0.04808963, 0.02792908, 0.057017103, 0.034324065, 0.14228246, 0.11275426, 0.088058695, 0.059600517, 0.02063494, 0.052596953, 0.047207687, 0.08789091) * g_1;
|
||||
result += mat4(-0.013453174, 0.008474715, -0.017593835, 0.009218917, 0.070580654, 0.040542338, 0.08812338, 0.074653216, -0.016356857, 0.015809007, -0.008739107, 0.0097674895, -0.018381525, -0.007775341, -0.040571664, -0.011188163) * g_2;
|
||||
result += mat4(-0.026196122, -0.034825727, -0.042998232, -0.033436514, -0.01678153, -0.004592797, -0.010311677, 0.0008815291, -0.08899181, -0.10274026, -0.066960976, -0.082430154, -0.057137426, -0.07554528, -0.030993424, -0.050372377) * g_3;
|
||||
result += mat4(0.022921838, -0.010479244, -0.050794605, -0.073633075, -0.053708922, 0.009594084, -0.071259, -0.01054356, 0.005165821, -0.08024963, -0.049251772, -0.09581235, 0.17995799, 0.09743011, 0.13533138, 0.11643848) * g_4;
|
||||
result += mat4(0.09727046, 0.07292666, 0.06820908, 0.041535784, -0.0049705, 0.0048759184, -0.035702795, -0.015944308, -0.010730028, 0.018847652, 0.06466244, 0.086318985, -0.05661574, -0.040698618, 0.010839972, 0.0027009705) * g_5;
|
||||
result += mat4(-0.04628466, 0.010060396, 0.02609333, 0.08664702, 0.057045907, 0.033591177, 0.02186063, -0.024303377, 0.006569828, 0.08025825, 0.016128821, 0.10180713, -0.12228169, -0.112990454, -0.078443415, -0.09126021) * g_6;
|
||||
result += mat4(-0.12733299, -0.087755, -0.07374111, -0.044979006, -0.025347412, -0.004083168, 0.023782173, 0.02900392, -0.017815407, -0.041119996, -0.057978686, -0.13521095, 0.08364004, 0.06950181, 0.023554614, 0.008043734) * g_7;
|
||||
result += mat4(0.009062775, -0.003570175, -0.007378757, -0.0018487388, 0.01145638, 0.05217187, -0.008250244, 0.008433307, -0.056756936, -0.044681005, -0.08096105, -0.08033185, -0.023784965, -0.01859799, 0.013042476, 0.021188647) * g_8;
|
||||
result += mat4(-0.0071619656, -0.012498299, -0.05144986, -0.078112476, -0.034992415, -0.017038302, -0.04464615, -0.044504963, 0.024249, -0.004297534, 0.03674578, 0.03090718, 0.04698553, 0.008344952, 0.057619847, -0.0338724) * g_9;
|
||||
result += mat4(-0.011845145, -0.0045043705, -1.6646482e-06, -0.0038495932, -0.01992515, 0.004827126, 0.019493148, 0.00862289, 0.10151322, 0.0021909082, 0.09940764, 0.03728846, 0.027824005, 0.04358071, 0.014909185, 0.036326095) * g_10;
|
||||
result += mat4(0.022513246, 0.028257169, 0.0102195935, 0.03301329, 0.052253865, -0.0021944977, 0.08247392, 0.03256867, -0.040685873, -0.0052207555, -0.0451257, -0.054165114, 0.01647699, 0.0028809097, -0.015233776, -0.0008741886) * g_11;
|
||||
result += mat4(0.017371105, 0.01597189, -0.052552313, -0.008554715, -0.0023150423, 0.006076517, -0.012868931, 0.0039361073, -0.007524978, -0.004284313, -0.021520883, -0.010327569, 0.02543678, 0.008725823, -0.0073885336, 0.005528395) * g_12;
|
||||
result += mat4(0.019192757, 0.016561812, 0.0027538154, 0.0013078215, 0.007916496, -0.042525183, -0.013173432, -0.05265476, -0.062195376, -0.011255499, 0.020898128, 0.021532273, -0.001524097, 0.034835674, -0.004051403, -0.0292426) * g_13;
|
||||
result += mat4(-0.049191684, -9.43322e-06, -0.009106849, 0.012845289, -0.019482708, -0.011163468, 0.0034011535, -0.007062845, -0.006469714, 0.03177786, -0.033006195, -0.0006813464, -0.053963087, 0.00085209147, 0.02734121, 0.034086403) * g_14;
|
||||
result += mat4(-0.03232248, -0.004037002, -0.010319106, 0.030889064, 0.019604538, 0.0020888883, 0.010277864, 0.000661223, 0.057915937, 0.030683514, 0.00042533095, -0.013019287, -0.015896408, 0.0038484468, -0.0042103594, 0.02174542) * g_15;
|
||||
result += mat4(0.032975145, 0.0011456647, 0.04913679, -0.017063798, 0.0117176045, 0.007440557, 0.0020480808, 0.009415731, 0.027573857, 0.015140836, -0.01679426, -0.006124731, -0.03206279, -0.029842237, -0.010428016, -0.028513178) * g_16;
|
||||
result += mat4(-0.00506859, 0.055869613, 0.010164368, 0.027031485, 0.042289548, -0.0054258504, 0.032214936, -0.029970925, -0.0058315448, 0.022889478, 0.01681123, 0.02985076, -0.111186065, -0.02202099, 0.0030994313, -0.062343158) * g_17;
|
||||
result += mat4(-0.060951103, 0.06079555, -0.0396464, 0.070911355, -0.011480358, -0.06803282, 0.01637355, -0.043100975, -0.00423709, -0.028337711, 0.021635853, 0.0014857082, 0.030084312, 0.018155476, 0.043694943, 0.038795974) * g_18;
|
||||
result += mat4(-0.0060662925, 0.029721662, -0.008117774, 0.034551267, -0.024477571, 0.018841071, -0.027095588, 0.034495078, 0.082398005, 0.008998768, -0.016399248, -0.043801688, 0.05936684, 0.006066549, 0.045399766, 3.5319943e-05) * g_19;
|
||||
result += mat4(0.019259382, 0.02494012, 0.029301709, 0.028329274, 0.09122267, 0.06900443, 0.1412115, -0.043169618, -0.01627418, -0.004989528, -0.0042651827, -0.04556752, -0.023623291, 0.013007996, -0.04483056, -0.015727345) * g_20;
|
||||
result += mat4(0.016332543, 0.016384754, -0.030676385, 0.045312885, -0.0100853555, -0.032632045, 0.031514473, -0.0070776115, 0.13642761, 0.0023589598, 0.12214136, -0.062155515, 0.08240989, 0.08894205, 0.03325406, -0.016589595) * g_21;
|
||||
result += mat4(-0.06494277, -0.08158925, 0.030425413, 0.019835634, -0.012624623, 0.013942616, -0.030527417, -0.021668324, -0.09444672, -0.033064254, -0.044167448, 0.0011024752, 0.03210801, 0.12662941, -0.03912534, 0.1112649) * g_22;
|
||||
result += mat4(-0.04716062, -0.03751481, -0.031030515, -0.09067383, 0.0077815712, 0.02169541, -0.035285182, 0.02290573, -0.0704085, -0.03916127, -0.058103334, 0.004915147, -0.0333844, -0.011548617, -0.031151932, -0.00043817286) * g_23;
|
||||
result += mat4(0.05976319, -0.107285, -0.097245865, 0.17706421, -0.021453341, -0.0047738464, -0.017621001, 0.033400454, -0.07225561, -0.05599672, -0.027600193, 0.038664024, -0.03762786, -0.052429967, 0.0104017975, 0.007116869) * g_24;
|
||||
result += mat4(0.06014114, -0.029824806, 0.03209269, 0.04392036, 0.031300627, -0.16249833, 0.06878509, -0.12658615, -0.012383169, -0.025043553, -0.06527381, -0.08149099, -0.014006842, -0.018669648, 0.014510818, 0.042045828) * g_25;
|
||||
result += mat4(-0.023342922, 0.047104675, 0.029629575, -0.082307704, 0.04035797, -0.0013049254, 0.11085582, -0.11031226, 0.14778149, -0.016699014, -0.00634342, -0.055320874, 0.14306462, 0.15896587, -0.110229075, -0.1069649) * g_26;
|
||||
result += mat4(-0.17449625, 0.15787153, -0.06711028, -0.023110518, 0.06862914, 0.074063435, 0.042682912, 0.029800726, -0.08768606, -0.009814701, 0.14180017, 0.14780663, -0.05672417, -0.074305914, 0.07873489, 0.028458012) * g_27;
|
||||
result += vec4(0.06026231, 0.040204916, 0.037672628, 0.023496555);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Conv-4x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_last_tf2
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.1765669, 0.14268716, 0.19186598, 0.15799578, 0.016374417, 0.018578433, 0.0039475, 0.0046772263, 0.39840183, 0.36909792, 0.35409746, 0.37422222, -0.108508386, -0.1331279, -0.10336035, -0.14776541) * g_0;
|
||||
result += mat4(-0.057757027, -0.14071062, -0.025283009, -0.09397916, -0.09031894, -0.14219165, -0.08299535, -0.13970287, -0.12259208, -0.14382727, -0.22002274, -0.25016093, -0.048906635, 0.06620249, 0.016965045, 0.1295978) * g_1;
|
||||
result += mat4(-0.16748372, -0.13718611, -0.18565705, -0.15029612, -0.080749065, -0.09955825, 0.032431383, 0.023855643, -0.2748885, -0.23232168, -0.29121292, -0.26405892, 0.16556135, 0.18657646, 0.1424068, 0.18855052) * g_2;
|
||||
result += mat4(0.10960496, 0.10851629, 0.095003806, 0.11053746, 0.09885307, 0.14437789, 0.13191165, 0.17365928, 0.16558935, 0.15473324, 0.21136154, 0.19976667, -0.07267957, -0.11469687, -0.029134216, -0.06817615) * g_3;
|
||||
result += mat4(0.10202856, 0.04216857, -0.03959349, -0.09849683, -0.1576996, -0.049997438, -0.1579918, -0.058789205, 0.029792828, -0.07311781, -0.045432188, -0.11312683, 0.24257647, 0.16204113, 0.17869382, 0.16024388) * g_4;
|
||||
result += mat4(0.17193612, 0.12692013, 0.13177487, 0.0796725, 0.0797928, 0.08952722, -0.012468046, 0.011071511, -0.068559825, -0.024852324, 0.0526428, 0.07917346, -0.085534215, -0.09591339, 0.04615827, 0.024577664) * g_5;
|
||||
result += mat4(-0.14653449, -0.067267366, -0.002524394, 0.086243175, 0.13660401, 0.08039592, 0.09179008, 0.022573143, -0.024744196, 0.09120211, 0.017654825, 0.14114714, -0.16093308, -0.14538004, -0.09950235, -0.111152865) * g_6;
|
||||
result += mat4(-0.188637, -0.12968326, -0.1200479, -0.06537649, -0.12589337, -0.106242515, -0.02788782, -0.025949068, 0.04948153, 0.02222735, -0.025291357, -0.12379292, 0.11074645, 0.11902375, -0.00056989543, -0.0024386419) * g_7;
|
||||
result += mat4(0.018286629, 0.0072215167, 0.00037828335, 0.0047001047, 0.011478272, 0.041745186, -0.015742473, -0.002282524, -0.03440817, -0.02196847, -0.07838253, -0.07993771, -0.010155526, -0.017590692, 0.027141469, 0.029741213) * g_8;
|
||||
result += mat4(0.016512005, 0.004950637, -0.0238836, -0.05587327, -0.03164328, -0.009499985, -0.059880238, -0.061794154, 0.023154303, -0.013266373, 0.04701534, 0.0415862, 0.06357814, 0.033057794, 0.08389772, 0.00035060212) * g_9;
|
||||
result += mat4(-0.016403968, -0.012538788, -0.0015746636, -0.004771009, -0.021361275, -0.009695242, 0.020548422, -0.0024130535, 0.07796766, -0.01516671, 0.09961382, 0.042754963, 0.017363647, 0.03729065, -0.004795824, 0.01550197) * g_10;
|
||||
result += mat4(-0.0028093113, 0.011869523, -0.02216933, 0.011177349, 0.033342455, -0.021146454, 0.07830085, 0.032490104, -0.03281833, 0.0060484232, -0.04081057, -0.04945058, -0.0056189033, -0.010636801, -0.041949317, -0.025739705) * g_11;
|
||||
result += mat4(0.012979897, 0.016758928, -0.049062215, -0.0035748442, 0.0085972, 0.0036381132, -0.0055621094, 0.0041307937, -0.0008907763, -0.0034079372, -0.025680453, -0.015531803, 0.012816766, 0.009977763, -0.016416566, 0.0034859509) * g_12;
|
||||
result += mat4(0.021753248, 0.016452711, 0.009833835, 0.0065052663, 0.0014061348, -0.046160888, -0.0132271005, -0.05051269, -0.05746351, -0.0012690664, 0.017191738, 0.018192926, -0.008879476, 0.026354216, -0.012801991, -0.029587373) * g_13;
|
||||
result += mat4(-0.04220692, -0.0015560482, -0.0019648245, 0.013402305, -0.018259782, -0.0036008905, 0.0035650074, -0.0019178417, 0.00051580026, 0.027355857, -0.017914988, 0.004937948, -0.046335887, 0.00013612259, 0.030293299, 0.030688645) * g_14;
|
||||
result += mat4(-0.036683388, -0.0031274238, -0.026074665, 0.021684237, 0.022639066, 0.0022493738, 0.011508554, -0.0006385944, 0.04890418, 0.020119468, 0.004167364, -0.008356099, -0.008598796, 0.0089028, -0.0029575853, 0.016687104) * g_15;
|
||||
result += mat4(0.027207986, 0.0011099194, 0.042383645, -0.015179333, 0.014744431, 0.006148344, 0.005165422, 0.0070196544, 0.030286826, 0.016620956, -0.01611366, -0.00667594, -0.029524863, -0.024751091, -0.013321004, -0.025199674) * g_16;
|
||||
result += mat4(0.0027477827, 0.054622147, 0.010154094, 0.025437292, 0.031773083, -0.01055473, 0.022864206, -0.029010754, -0.0029999653, 0.025018329, 0.015316208, 0.027188798, -0.10096525, -0.017268656, 0.0012529213, -0.062078856) * g_17;
|
||||
result += mat4(-0.053670805, 0.057336535, -0.037418038, 0.06443577, -0.016027879, -0.058168363, 0.007034215, -0.03390141, -0.0019346164, -0.027947908, 0.021723913, -0.0018286633, 0.030507812, 0.018293543, 0.042917266, 0.033528328) * g_18;
|
||||
result += mat4(-0.004559579, 0.029667616, -0.001870353, 0.0378995, -0.017147437, 0.020192018, -0.021574946, 0.031568103, 0.07487145, 0.0032376775, -0.018893708, -0.041981626, 0.054478757, 0.0061423797, 0.041280247, 0.000878061) * g_19;
|
||||
result += mat4(0.017076394, 0.023647636, 0.029403262, 0.029923365, 0.08866472, 0.060613394, 0.1314274, -0.04490231, -0.016304834, -0.0062647443, -0.0031828512, -0.03989252, -0.024330825, 0.00741213, -0.04075287, -0.01615817) * g_20;
|
||||
result += mat4(0.017866978, 0.017720113, -0.02846163, 0.040761847, -0.0063438355, -0.02347501, 0.029564403, -0.0029562064, 0.12505588, -0.0073986333, 0.11250363, -0.06179967, 0.07854423, 0.08546533, 0.034743227, -0.010757377) * g_21;
|
||||
result += mat4(-0.06416677, -0.08344284, 0.030138884, 0.017635904, -0.012087523, 0.014205202, -0.03221233, -0.023834767, -0.091186255, -0.028958676, -0.04724334, 0.00013161585, 0.027391518, 0.1249978, -0.045047652, 0.10737729) * g_22;
|
||||
result += mat4(-0.04326348, -0.03543181, -0.029558217, -0.08582413, 0.007812453, 0.014296562, -0.028779754, 0.018517692, -0.063755795, -0.036619596, -0.050809663, 0.005431336, -0.029205568, -0.011827915, -0.031110523, -0.005648626) * g_23;
|
||||
result += mat4(0.05499293, -0.10000709, -0.0943537, 0.16143042, -0.019952895, -0.0039807972, -0.014841254, 0.0320363, -0.065173544, -0.049425576, -0.023904482, 0.03759679, -0.03207411, -0.047782745, 0.01352581, 0.008140566) * g_24;
|
||||
result += mat4(0.055923894, -0.025134467, 0.029583648, 0.04096879, 0.027551858, -0.14995384, 0.06467113, -0.11633077, -0.01563784, -0.026909819, -0.06292879, -0.078409635, -0.009081105, -0.015533088, 0.019585673, 0.04334208) * g_25;
|
||||
result += mat4(-0.021717606, 0.042464726, 0.02743202, -0.07388838, 0.03460472, 0.0038285658, 0.099842004, -0.098247, 0.13276267, -0.020793032, -0.008603039, -0.051913783, 0.12959045, 0.14735717, -0.10888226, -0.10263746) * g_26;
|
||||
result += mat4(-0.16819532, 0.141579, -0.062480718, -0.021918943, 0.06348125, 0.06849444, 0.03888676, 0.027375204, -0.08194279, -0.012574497, 0.13523251, 0.13739482, -0.047547445, -0.058767617, 0.07009549, 0.028136581) * g_27;
|
||||
result += vec4(0.069033325, 0.040207114, 0.027286075, 0.0065334598);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-CNN-x2-(VL)-Depth-to-Space
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_last_tf
|
||||
//!BIND conv2d_last_tf1
|
||||
//!BIND conv2d_last_tf2
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_last_tf.w 2 *
|
||||
//!HEIGHT conv2d_last_tf.h 2 *
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
vec4 hook() {
|
||||
vec2 f0 = fract(conv2d_last_tf_pos * conv2d_last_tf_size);
|
||||
ivec2 i0 = ivec2(f0 * vec2(2.0));
|
||||
float c0 = conv2d_last_tf_tex((vec2(0.5) - f0) * conv2d_last_tf_pt + conv2d_last_tf_pos)[i0.y * 2 + i0.x];
|
||||
vec2 f1 = fract(conv2d_last_tf1_pos * conv2d_last_tf1_size);
|
||||
ivec2 i1 = ivec2(f1 * vec2(2.0));
|
||||
float c1 = conv2d_last_tf1_tex((vec2(0.5) - f1) * conv2d_last_tf1_pt + conv2d_last_tf1_pos)[i1.y * 2 + i1.x];
|
||||
vec2 f2 = fract(conv2d_last_tf2_pos * conv2d_last_tf2_size);
|
||||
ivec2 i2 = ivec2(f2 * vec2(2.0));
|
||||
float c2 = conv2d_last_tf2_tex((vec2(0.5) - f2) * conv2d_last_tf2_pt + conv2d_last_tf2_pos)[i2.y * 2 + i2.x];
|
||||
float c3 = c2;
|
||||
return vec4(c0, c1, c2, c3) + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.029052526, 0.059789784, -0.024398074, 0.06907132, 0.18920785, -0.12923062, 0.0766382, -0.12048348, -0.017786544, 0.06251133, -0.068393864, 0.056690093, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.14032267, -0.077691495, -0.009036259, -0.13049065, 0.20954624, 0.023231741, -0.2759354, 0.49927905, 0.039609738, -0.092625424, 0.09426452, -0.2246486, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.023119625, 0.046549924, 0.073033765, 0.03727065, 0.04498207, 0.024455868, 0.17602317, -0.3150503, 0.019985953, 0.03670126, 0.0071220254, 0.107966185, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.111121014, -0.084099665, 0.12595509, -0.048271902, -0.007799661, 0.04831373, 0.11868961, 0.11607051, 0.05169621, -0.050569464, 0.120362274, 0.034607537, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.41167754, -0.44940078, 0.35485214, 0.58048695, -1.0151424, -0.70137614, 0.38405335, 0.37337455, -0.096364655, -0.14538667, 0.17917591, 0.32259464, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(0.06378494, -0.040756933, -0.4773648, -0.47702238, 0.1803328, -0.21388084, -0.5509359, -0.6491179, -0.048081584, -0.0025129975, -0.28561604, -0.22229671, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.037024107, 0.016497454, -0.05315267, -0.023392007, 0.1840294, 0.12675077, 0.037417043, -0.022394283, -0.028192522, -0.016344562, -0.07269005, -0.04747136, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.039480202, 0.5577544, -0.117326505, 0.06622856, -0.038784727, 0.65673745, -0.109742545, 0.22294083, 0.00038519394, 0.24552485, -0.07008514, 0.00029412706, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.009279719, -0.031882852, 0.14124188, -0.0759899, -0.024016602, 0.15252088, 0.13614258, -0.09961189, 0.05446014, -0.03827061, 0.11210173, -0.028823104, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(0.012836382, -0.0062823873, -0.03165346, -0.0017501811);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.06215308, -0.054471835, 0.1285146, 0.037585296, -0.14467795, 0.0057610427, 0.006528968, 0.18607244, 0.03762581, -0.121003255, 0.0827445, 0.076479666, 0.07540097, 0.16371846, -0.18786757, -0.12048073) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.11520603, -0.22384967, 0.0970881, 0.045122143, -0.40358877, 0.12487416, -0.4489702, 0.04854906, -0.08240888, -0.0058777514, 0.19108902, 0.042189106, -0.07843178, 0.0012592699, -0.11303816, -0.1118517) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.29387334, 0.08150406, -0.06009834, 0.07054583, -0.146034, 0.04053809, 0.23284695, -0.08233496, 0.0957811, 0.20221621, 0.13570721, -0.081069246, -0.031743366, -0.038912926, -0.059060514, 0.05190416) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.18404631, -0.034244366, -0.13406059, 0.2242061, -0.23668705, -0.10359684, -0.09689738, -0.04932347, -0.0020525968, 0.15236467, -0.2634303, -0.029878438, 0.3283669, 0.09891668, -0.46656898, -0.03271751) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.1824976, -1.0545974, 0.93027455, -0.13887188, 0.3128633, -0.2734884, -0.831517, -0.18065166, -0.2119423, 0.19241124, -0.13313763, -0.10523897, 0.2675327, -0.06853148, 0.007885104, 0.26000848) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.18109167, -0.019768981, -0.14131357, -0.3181756, 0.22158594, 0.1431138, -0.12970252, -0.011459096, -0.03742945, 0.2316056, -0.054623842, -0.09360549, 0.10176328, -0.108150974, 0.122787155, 0.07614884) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.02370754, -0.10264054, 0.030659392, 0.056694325, 0.034085, -0.0538203, 0.09111551, 0.0063995267, 0.0835243, -0.06623529, 0.20924146, 0.09457414, 0.27925664, 0.049511474, -0.22062886, 0.03312504) * go_0(1.0, -1.0);
|
||||
result += mat4(0.17009354, 0.34391564, -0.1680695, -0.051450633, -0.044037253, -0.1412577, 0.01097572, -0.049040757, 0.104024716, -0.34571946, 0.5213214, -0.17010914, -0.016452854, 0.3303069, -0.22249438, 0.23866816) * go_0(1.0, 0.0);
|
||||
result += mat4(0.20491506, 0.20098424, 0.015425732, -0.033999693, -0.0111842435, 0.09945295, -0.025766203, 0.17068656, 0.049262784, 0.0077788536, 0.068585835, 0.19229786, -0.013048818, 0.04877973, 0.024053875, -0.06846659) * go_0(1.0, 1.0);
|
||||
result += mat4(0.14208305, 0.09790381, -0.008420949, -0.016165754, 0.02445528, 0.08700781, 0.046639573, -0.22105917, -0.08529265, 0.06606378, 0.0947481, 0.08149193, -0.0959293, -0.037756894, -0.008136973, 0.046241503) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.2577669, 0.13766493, 0.021107635, 0.018978242, 0.452542, 0.25566816, -0.68909633, 0.03804329, 0.06771752, 0.07894156, 0.22501312, -0.047511246, 0.00040517355, -0.0202232, -0.27541754, -0.040150844) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.30176973, -0.15739526, -0.038548045, -0.07003333, 0.32053417, 0.025467036, -0.044913124, 0.20454903, 0.12475206, -0.03966162, 0.07139637, 0.12101497, -0.10777517, -0.062379625, 0.06598757, -0.14795317) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.12068516, 0.0026514034, -0.055378057, -0.0976728, 0.15887645, 0.15590422, 0.076294206, -0.15417404, -0.16548084, -0.18422292, -0.1670212, 0.041155312, -0.11765263, 0.16991171, -0.21535093, 0.01542368) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.37845853, 0.5732961, 0.114283465, 0.14638355, -0.109194644, 0.087304994, -0.15938401, 0.58242995, -0.025850652, 0.02730721, -0.48582682, -0.2547883, 0.1899583, 0.24296008, -0.8162976, 0.018036429) * go_1(0.0, 0.0);
|
||||
result += mat4(0.1633212, -0.117295206, 0.021892091, 0.07762347, -0.09726402, -0.1364192, 0.10752197, 0.42020246, 0.06665656, -0.10822656, 0.1337331, 0.0552859, 0.04700212, 0.108017646, -0.2009353, -0.0435288) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.045603696, 0.05774526, -0.0071174325, 0.24119262, -0.06899063, 0.016012343, 0.009982042, -0.19038968, -0.17796072, -0.12510185, 0.22739507, -0.1805478, -0.100294635, 0.017557602, 0.039842658, 0.13116726) * go_1(1.0, -1.0);
|
||||
result += mat4(0.0131523665, -0.20472725, 0.121814765, -0.17769355, 0.097669855, 0.09648846, -0.072887406, 0.22992326, -0.019087939, 0.35375193, -0.057155706, 0.17699116, 0.030690158, -0.423475, 0.03703492, -0.03429164) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.12143413, -0.018402342, 0.04536776, -0.12743106, 0.03355068, -0.09694192, 0.09913357, -0.036602203, 0.11038047, 0.13236065, 0.12966877, -0.10163848, 0.0030612876, -0.116145626, 0.045318183, 0.11492169) * go_1(1.0, 1.0);
|
||||
result += vec4(0.05657016, -0.04848861, 0.10297782, -0.0076417355);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.088122115, -0.009916053, -0.124469265, -0.032139737, -0.13709281, 0.09177288, -0.06794775, -0.03962873, 0.17613642, -0.11064388, 0.2531882, -0.3817648, -0.1172188, -0.042132895, -0.098772734, -0.114560865) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.18876404, -0.14613804, 0.23869626, 0.06580185, -0.13533239, 0.25754455, -0.29734856, 0.028218834, -0.39304733, -0.14716247, 0.19408274, -0.18518063, -0.31482637, -0.1508887, -0.3841371, 0.021975968) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.22316615, -0.0923483, 0.16932568, -0.13138154, 0.139829, 0.010975908, -0.0587337, -0.054484393, -0.13758336, -0.030077504, -0.050642505, -0.14933856, -0.040563874, -0.030220931, 0.2867556, 0.17022403) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.12611523, -0.07087836, 0.08281469, 0.024588918, -0.023549056, -0.13102995, 0.17571726, 0.0740372, -0.3167631, 0.17491543, 0.4459055, -0.4687942, -0.19755729, 0.03723031, -0.06757113, 0.03502462) * go_0(0.0, -1.0);
|
||||
result += mat4(0.12098187, 0.12341856, -0.061940372, 0.7251308, 0.055730965, -0.5169302, 0.37959704, -0.08753306, -0.45700142, -0.4960699, 0.1690022, -0.40233734, 0.0262836, -0.13345262, 0.11002605, -0.16773209) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.20428565, 0.117523015, -0.044863444, -0.1770644, 0.22925, 0.029694336, -0.23891294, 0.039587863, -0.11235541, -0.23890465, 0.037618574, -0.039127905, 0.14058869, 0.020599412, -0.074353516, 0.12343045) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.04680316, -0.049870726, 0.06975308, -0.21486782, -0.08177838, 0.09760846, -0.031408366, 0.13881667, -0.14650045, 0.29182404, -0.080848776, -0.25525567, 0.018876432, -0.015662232, -0.016014043, -0.08435915) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.100864016, -0.24647528, -0.007994345, 0.13047779, 0.14746517, 0.25517163, 0.054900885, -0.07251866, -0.29500577, -0.03758923, 0.05514366, -0.058372885, -0.03055354, -0.062586576, 0.017739896, 0.08644674) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.029502464, -0.08905223, 0.0047584837, -0.09646073, 0.044714086, 0.15522493, -0.070930906, -0.026954453, 0.057949875, -0.017211404, -0.00566463, -0.0050975676, 0.0050182147, -0.010722001, 0.011812942, -0.04698445) * go_0(1.0, 1.0);
|
||||
result += mat4(0.18863353, -0.11575336, 0.26541254, -0.15280409, 0.14376, -0.05783716, 0.08554402, 0.27605456, 0.004611954, 0.074173525, -0.07963756, 0.082979314, 0.099553905, -0.06539344, 0.4330784, 0.07996894) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.31001288, 0.035875235, 0.049856357, -0.09614268, 0.23397788, -0.12425775, 0.45108303, 0.27973723, 0.0753222, 0.11388394, -0.043821793, -0.05610102, -0.06536777, 0.009822641, 0.7956708, -0.05798737) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.19827974, 0.010130333, -0.13153136, 0.11593003, -0.15762039, -0.0040722084, 0.20404483, 0.28999883, 0.08152756, 0.07773477, 0.019730574, 0.0123460535, -0.034676805, -0.19133334, 0.01860159, -0.12945038) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.1861255, 0.039945368, 0.28345293, -0.17425321, 0.36748698, 0.03729066, -0.35957313, 0.11234573, -0.07122196, 0.012845119, -0.09049443, 0.10106711, 0.07425845, -0.14626606, 0.46169114, -0.2652126) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.6222811, -0.08538015, 0.023319554, -0.7206892, -0.33495513, 0.2960924, -0.033479776, -0.29255456, 0.29802337, 0.47570458, 0.012769826, 0.19874385, -0.25652033, -0.4018595, 0.3055839, 0.1881051) * go_1(0.0, 0.0);
|
||||
result += mat4(0.32152474, 0.0024920676, -0.113435976, 0.14440896, -0.287736, 0.0251382, 0.28160754, 0.02769615, 0.067614004, 0.0832741, -0.095353454, -0.19792004, -0.40394694, -0.24224225, 0.3224996, 0.030300485) * go_1(0.0, 1.0);
|
||||
result += mat4(0.0045148246, -0.04621849, -0.026470715, 0.0588576, 0.14559188, 0.037437905, -0.13778603, 0.08173416, 0.033548757, -0.015654223, 0.15016593, 0.07761835, -0.016546778, 0.02640291, 0.112717085, 0.020371364) * go_1(1.0, -1.0);
|
||||
result += mat4(0.114227325, -0.0405595, -0.11662477, 0.014747093, 0.11170598, 0.58740836, -0.27560827, -0.1848705, -0.02491223, -0.15605451, 0.0028677192, -0.11290364, -0.12331832, -0.3191161, 0.3505101, 0.15236251) * go_1(1.0, 0.0);
|
||||
result += mat4(0.21131381, 0.13965495, -0.103683874, 0.26049778, -0.010777816, 0.015093082, 0.13207617, 0.14064828, -0.007847294, 0.025702007, -0.082993574, -0.04923462, -0.052900862, -0.006775377, 0.1432969, 0.09598549) * go_1(1.0, 1.0);
|
||||
result += vec4(0.08015534, 0.10264796, -0.031173404, 0.21282151);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.13262276, 0.18682314, -0.1433667, -0.0061677806, -0.15057871, -0.15389217, 0.40721065, -0.082456455, 0.028175479, -0.06136406, 0.13517159, -0.0066659097, -0.03311807, -0.056219388, 0.066265404, -0.017012158) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.0652481, -0.02717338, -0.17586891, -0.1458622, 0.37166637, -0.13651049, -0.095090784, 0.1450258, -0.08856753, -0.029000161, -0.11024598, 0.14231622, 0.027118085, 0.060637098, -0.028174674, 0.020973917) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.17137158, 0.015818363, -0.1761587, -0.07798954, -0.22039492, -0.08250406, 0.15350278, 0.05466543, 0.07231244, 0.124937475, -0.14530692, -0.036220204, -0.20202135, 0.16154502, -0.1472417, 0.045183204) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.06751513, 0.3630837, -0.23374555, -0.17641832, 0.23866339, -0.12625019, 0.14955078, 0.3757683, 0.25546572, -0.0009440543, -0.029705383, 0.12500505, 0.039303612, 0.02745342, 0.06280759, -0.027673393) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.40253955, 0.5532656, 0.15580782, 0.23305601, 0.04307387, -0.37548792, 0.021682428, -0.14554474, -0.44655007, 0.12335231, 0.22693188, -0.19185324, -0.39905196, -0.36661598, 0.34626722, 0.3220371) * go_0(0.0, 0.0);
|
||||
result += mat4(0.13051705, -0.051269528, 0.027860573, 0.12866034, 0.095374286, 0.0072371624, 0.06641015, -0.040609945, 0.14411138, 0.03813084, 0.024812538, -0.069997884, -0.2398024, 0.16384888, 0.004522481, -0.2734798) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.048976544, 0.36923414, -0.23769425, -0.02964149, 0.13426293, -0.070416726, -0.036279447, 0.21007125, -0.0062456504, 0.12307804, -0.18920022, 0.016429992, 0.091225415, -0.00714184, -0.079064, 0.050525308) * go_0(1.0, -1.0);
|
||||
result += mat4(0.007005748, -0.1929285, -0.27960134, -0.014070343, -0.012031938, -0.21320626, 0.22591045, 0.06750757, 0.038049847, -0.08933499, 0.15640227, 0.36653376, 0.11274315, 0.0015512784, -0.14319079, -0.41117874) * go_0(1.0, 0.0);
|
||||
result += mat4(0.039254356, 0.04123307, -0.14476523, 0.19676228, -0.1746638, 0.068685316, 0.19318552, -0.007086376, -0.08810745, 0.041937724, 0.1393943, 0.27539206, -0.08331265, 0.043064818, -0.02783017, -0.13006629) * go_0(1.0, 1.0);
|
||||
result += mat4(0.18761271, -0.009960496, -0.18572417, 0.010640895, 0.10240658, 0.036137953, -0.109363064, 0.05820501, -0.04092678, 0.11809751, -0.11843415, 0.11893309, -0.06356792, 0.1509876, -0.12252014, -0.0070098704) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.0012312894, 0.038436964, -0.046054237, 0.04859312, -0.4190657, 0.2529927, 0.23133701, -0.00065297337, -0.039581586, 0.00905735, 0.16532114, -0.12568031, 0.17818217, -0.28053075, 0.38509414, -0.03763847) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.0897875, 0.063593514, 0.07660054, 0.12268424, 0.21554653, -0.1025501, 0.2557211, 0.04492533, 0.10992355, -0.035215836, -0.009733763, -0.02165148, 0.08618596, -0.19276536, 0.18174514, -0.18021213) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.002999377, -0.12630916, -0.030010369, -0.2676409, -0.20229307, 0.15253967, -0.12200155, -0.1552754, -0.16193017, 0.10819683, 0.10696224, -0.1920264, -0.29354608, -0.32021165, 0.08644405, -0.16153689) * go_1(0.0, -1.0);
|
||||
result += mat4(0.49931613, -0.3669461, -0.49107462, -0.3654748, 0.32047966, 0.03246311, -0.06424334, 0.009108802, 0.2367612, -0.46587244, 0.16957493, 0.3237888, 0.93676794, 0.01834384, -0.9349752, -0.04654371) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.112562165, 0.006074484, -0.12288025, -0.08560263, 0.25336134, 0.025205871, 0.25063732, 0.12370882, -0.40429187, 0.12992847, -0.2816234, 0.08179623, 0.27197668, 0.066299304, -0.12988937, 0.16257611) * go_1(0.0, 1.0);
|
||||
result += mat4(0.047864527, -0.05821779, -0.06311128, -0.0065775234, -0.065763995, 0.014864688, 0.09148591, -0.25059348, 0.008846306, -0.22123712, 0.4062609, -0.100248575, -0.50293785, -0.13373566, 0.21480446, -0.0841981) * go_1(1.0, -1.0);
|
||||
result += mat4(0.19313097, -0.061253734, -0.1801314, -0.20178059, -0.039574936, 0.08167749, 0.010974997, 0.069656976, -0.13193963, 0.35555324, 0.62686867, -0.28656846, -0.27831817, -0.0040086447, 0.4031064, 0.47767937) * go_1(1.0, 0.0);
|
||||
result += mat4(0.15396428, 0.069321476, -0.15190981, -0.24133344, 0.106151104, -0.11271092, 0.06878746, 0.14279713, -0.02006402, -0.36284852, -0.00926688, -0.39887694, -0.20926239, -0.021860912, 0.07588468, 0.2620174) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.0073282495, -0.040352557, -0.063710704, 0.07255652);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.17903937, -0.0014294779, 0.1824805, -0.19555633, -0.0052551827, -0.013796094, 0.06358042, 0.13301018, 0.008874768, 0.06605332, 0.06117636, 0.012946474, 0.048656575, 0.0060409275, -0.0671362, -0.06897735) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.16098012, 0.10772552, -0.13175552, -0.5299018, 0.068713695, -0.048258893, -0.49698257, 0.36581638, 0.21755004, -0.12125899, -0.27382872, -0.12268086, 0.014334542, 0.20573758, 0.45879167, -0.29648975) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.06860283, -0.18047708, 0.024707617, 0.11900479, 0.09474589, -0.16559775, -0.054095846, -0.011377782, -0.008733984, 0.105020404, -0.040116277, -0.0022003972, 0.1453799, -0.032110006, -0.018741792, -0.12511599) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.20024729, -0.01969923, -0.026999667, -0.39064395, -0.14559332, -0.11634086, -0.13226044, 0.11779975, -0.08838282, -0.0882447, -0.23166943, -0.15760234, 0.030928904, -0.032423917, 0.20324136, -0.19692755) * go_0(0.0, -1.0);
|
||||
result += mat4(0.49499384, 0.7327846, -0.6173799, -0.53821295, -0.15000962, 0.11169762, 0.6942423, 0.07956513, 0.06913002, -0.19037646, -0.19826908, 0.68080276, -0.2747096, -0.15832238, 0.47366706, 0.090432756) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.18274948, 0.09204629, 0.16644076, 0.05641037, 0.03328184, -0.6218293, 0.26432592, -0.093742386, 0.33038342, -0.24853565, -0.23683667, -0.37430722, -0.20684583, -0.32283148, -0.07633969, -0.08765815) * go_0(0.0, 1.0);
|
||||
result += mat4(0.06821987, 0.06395764, -0.14685121, -0.15894371, -0.093540885, 0.057568345, -0.048376244, -0.009256543, -0.26325077, -0.03193119, -0.16857445, -0.02404981, 0.110593356, 0.042911418, 0.06626762, -0.0312436) * go_0(1.0, -1.0);
|
||||
result += mat4(0.3108626, 0.37123847, -0.082249805, -0.21339422, -0.3756041, -0.08518717, -0.16853802, 0.011641729, -0.30096757, 0.26942274, -0.08990497, -0.19451031, 0.21974437, -0.04231723, 0.26160353, -0.040834647) * go_0(1.0, 0.0);
|
||||
result += mat4(0.11795158, 0.24436565, 0.043223023, -0.0159957, -0.19689156, 0.13223267, -0.013983249, 0.09437164, -0.47648698, -0.00082660443, -0.085406005, 0.10885898, 0.104696035, -0.053257108, 0.024389362, 0.0282572) * go_0(1.0, 1.0);
|
||||
result += mat4(0.032890156, 0.0115719065, -0.01898909, -0.03034875, -0.041037276, -0.1026382, 0.03337663, 0.20108728, -0.00023235095, -0.018033072, -0.028535927, 0.07359915, 0.075182244, 0.02959868, 0.15107772, -0.09815672) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.004040557, 0.06707476, 0.039022792, 0.52437925, -0.08027356, 0.040488366, 0.035332825, 0.07683081, -0.03521227, -0.081861034, 0.090804815, 0.10580108, 0.20452882, -0.58755285, 0.04303056, 0.41562977) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.09290062, 0.03495193, 0.02347216, -0.012873525, -0.076936446, 0.1453216, -0.03742271, -0.14174925, -0.058219753, 0.19095406, 0.055627216, 0.09437343, -0.010424211, -0.314692, 0.3314579, -0.053285643) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.053961687, 0.1483992, 0.042458896, -0.1966439, 0.13864957, 0.07587672, -0.06519269, 0.09530391, 0.04215073, 0.039545458, 0.21056756, 0.09972659, 0.02987125, -0.08102741, 0.07075036, 0.21867757) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.5512795, 0.03104814, 0.27901977, 0.122875504, -0.2656715, 0.007895486, -0.6735937, 0.20810314, -0.31432617, 0.07420857, 0.2573659, -0.35361463, 0.19826569, -0.47774056, 0.15816487, -0.29203883) * go_1(0.0, 0.0);
|
||||
result += mat4(0.35078493, -0.07371588, -0.026663188, -0.20976657, -0.009644347, 0.037428845, -0.33933878, -0.010807704, 0.088060796, 0.16753472, -0.12296045, 0.17563403, 0.1501952, 0.07353703, 0.32531765, 0.11667607) * go_1(0.0, 1.0);
|
||||
result += mat4(0.096126616, -0.058021486, -0.03439203, 0.06868024, 0.047914367, 0.026945053, 0.04207778, 0.046023168, 0.16024022, 0.07846185, 0.004195093, 0.07272046, -0.10458233, -0.0904536, 0.16049337, 0.015941419) * go_1(1.0, -1.0);
|
||||
result += mat4(0.032256138, -0.055398785, 0.079738356, 0.113359064, 0.11975066, -0.074372105, 0.102006756, -0.011490042, 0.15155345, 0.0025528704, 0.23328577, -0.059241068, -0.067783386, -0.18220833, 0.0057692174, 0.039900843) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.06173998, -0.07121991, -0.01118306, -0.063749574, -0.032665797, 0.0014987896, 0.03113169, 0.06916617, 0.0066490914, -0.052818965, -0.050131317, 0.10337558, -0.030870482, -0.14671221, 0.12152145, -0.05003445) * go_1(1.0, 1.0);
|
||||
result += vec4(-0.010524109, -0.008519857, -0.08958723, -0.07917139);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.11029161, 0.027180295, -0.115622066, 0.16493714, 0.29633296, -0.11739625, -0.36390316, 0.15221693, -0.009233659, -0.062213745, -0.07184558, 0.07418268, -0.05182182, 0.0066014086, -0.006811494, -0.010030367) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.18361749, 0.08565693, 0.24127418, -0.20478591, 0.6198113, -0.17994536, -0.011840256, 0.120292775, 0.2873902, -0.019704796, -0.062267166, 0.0104749305, -0.048370067, -0.028105626, 0.11494511, -0.15941763) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.08084502, 0.10195475, -0.03200553, 0.032734055, 0.030348243, -0.028927604, 0.045914374, 0.029237835, 0.07756032, -0.06346545, -0.290196, 0.057043966, 0.13982558, -0.12195619, -0.15895663, -0.10097537) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.12018707, -0.320156, -0.4089669, 0.26015735, 0.59622765, -0.05654362, 0.28581724, 0.32069868, -0.0013007161, -0.060870633, -0.2732852, 0.2357145, 0.2137239, 0.0110256495, -0.069258444, 0.113870576) * go_0(0.0, -1.0);
|
||||
result += mat4(0.54700065, -0.072552234, 0.27267826, -0.26660076, 0.7043544, 0.18192886, 0.80024594, 0.2447395, -0.3289639, -0.2681839, 0.063631415, -1.0118654, 0.45691678, 0.42904988, -0.2301862, -0.6652257) * go_0(0.0, 0.0);
|
||||
result += mat4(0.19215634, 0.030154131, 0.07679603, 0.50318545, 0.056434657, 0.028623195, -0.14471184, -0.13905096, -0.03254216, -0.1191584, -0.18907212, 0.49208716, 0.5069476, -0.1490824, -0.104480386, -0.06595394) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.08893682, 0.13113782, 0.023672188, 0.013086517, -0.25986442, 0.038162243, -0.10951209, -0.2027832, -0.013547809, -0.029482972, -0.17670235, 0.13529542, -0.0621569, -0.0979757, -0.10714689, -0.08474307) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.032828752, 0.00037559783, 0.023968933, -0.047482926, -0.20302027, 0.08830911, -0.20885307, -0.11137413, 0.16585048, -0.076796696, -0.030462325, -0.2020944, 0.048723634, -0.45607433, -0.29950324, -0.5867916) * go_0(1.0, 0.0);
|
||||
result += mat4(0.008863689, 0.061761267, -0.039097138, 0.24465923, -0.05917457, -0.21383028, -0.085846715, -0.14150433, 0.0988731, -0.0160538, -0.045119412, 0.095252946, -0.057551738, 0.21348421, -0.03480491, -0.26071647) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.21351442, 0.10038809, 0.34001955, -0.100911774, 0.0208522, -0.028755441, 0.025793588, 0.013080005, 0.03849989, 0.13662058, 0.04311886, 0.17398632, -0.01397261, -0.016415505, -0.0070752064, 0.007656161) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.280189, 0.09252764, -0.077729605, 0.12662902, -0.10433321, 0.03644144, -0.06625324, 0.05696802, 0.15468478, 0.08328583, 0.069849946, 0.061947342, -0.05560477, -0.0074776993, -0.15365681, -0.03526299) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.05886785, 0.15303846, 0.0066637015, -0.19983207, -0.07803175, -0.10772685, -0.12690999, -0.08275092, 0.033436153, 0.08424011, 0.17092863, 0.0043526487, 0.014620474, 0.044702258, 0.1686881, -0.016890949) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.1833738, 0.14381635, -0.025888365, -0.14182197, -0.25804865, 0.07216123, 0.025790794, 0.14096753, 0.023591481, 0.15610993, 0.026975863, 0.008755717, -0.13039349, -0.063048325, -0.121329494, -0.12331732) * go_1(0.0, -1.0);
|
||||
result += mat4(0.0005065098, 0.44017914, 0.18493074, 0.13099027, -0.36087477, -0.37567857, -0.48981526, 0.5590752, -0.23918836, 0.19170256, 0.16816153, -0.29986876, -0.44738817, 0.018545123, 0.66217834, 0.31810755) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.16725904, 0.05753713, 0.058880586, -0.336765, 0.013667228, 0.056172702, 0.13465533, -0.07573556, -0.06313958, 0.06746643, 0.18878669, 0.09404202, -0.21780397, 0.12862128, -0.09476746, -0.34096682) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.07169524, 0.072302215, 0.052789338, -0.14035568, 0.078670934, -0.22246763, -0.0098074945, 0.024950746, 0.10949147, 0.06182366, 0.021721192, 0.12129548, 0.094007075, 0.06076156, 0.016474832, 0.08092115) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.10960447, 0.1878152, -0.029822018, 0.10598909, 0.1582181, 0.086522795, 0.093725055, 0.12908185, 0.23202112, -0.28859115, 0.26614165, 0.124523655, 0.19427507, 0.059677128, 0.003624697, 0.44220912) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.03620583, -0.102766834, 0.025527107, -0.11316131, -0.1507822, 0.0543862, -0.08225627, -0.06438472, 0.04580623, 0.6329729, 0.23854075, 0.35752076, 0.04363613, -0.12580468, -0.0006126687, -0.04995386) * go_1(1.0, 1.0);
|
||||
result += vec4(0.060475674, -0.042036578, 0.06406282, 0.05569301);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x3x3x8
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.008187961, -0.08433309, -0.17281345, 0.1306418, -0.2925821, 0.20668334, 0.14854355, -0.15960559, 0.08599311, -0.096088655, -0.10121403, 0.067429096, 0.049158614, 0.036637552, 0.22137405, -0.17016457) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.024813082, 0.028489944, 0.06814137, -0.1245949, 0.54239255, 0.08648708, 0.28979865, 0.110916786, -0.1927179, -0.17756873, -0.1878214, 0.05795718, -0.080397904, 0.22125137, 0.1907366, -0.016493658) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.027259264, 0.01494357, 0.04852894, 0.037580628, 0.031005561, 0.003570554, -0.072993, -0.053475574, 0.031119492, -0.14140029, -0.10386501, -0.015266508, 0.01153506, 0.16006693, 0.088294305, 0.04201491) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.13026185, 0.097255, 0.49145448, -0.33619553, -0.21144676, 0.019042643, -0.27274492, 0.3033865, 0.14040698, -0.13656893, 0.28211337, -0.26930946, -0.1626638, 0.105105706, -0.50837296, 0.39536825) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.42495522, 0.14972518, 0.0007564128, 0.37367433, 0.44553527, 0.3338494, -0.26058698, 0.087256804, -0.4324135, 0.20706014, 0.33552194, -0.13375738, -0.13469471, 0.22374928, -0.36969653, -0.34171587) * go_0(0.0, 0.0);
|
||||
result += mat4(0.26543954, -0.004381978, 0.10609993, -0.09718426, -0.15620759, -0.03287476, 0.093032375, 0.00028344034, -0.11699793, -0.016492033, 0.023340177, 0.0062737763, -0.14305823, -0.2721832, -0.160177, -0.06915171) * go_0(0.0, 1.0);
|
||||
result += mat4(0.03334679, 0.12436332, -0.13226178, 0.13868971, 0.017779246, -0.012697869, -0.11553709, 0.08638636, 0.0955215, -0.0309646, 0.040856246, -0.03978358, 0.023490254, -0.07178907, 0.23794931, -0.1714287) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.11820261, 0.116130814, 0.58924234, -0.37785482, 0.016644944, -0.071019046, 0.0076222476, -0.024118654, -0.076183304, -0.14971451, 0.06356606, -0.07225465, -0.17400762, 0.030856986, 0.03957665, -0.0070553776) * go_0(1.0, 0.0);
|
||||
result += mat4(0.10954708, 0.063694, -0.058218896, 0.0010372304, 0.032423936, 0.006164447, -0.031383317, 0.012955956, -0.17115591, 0.16328962, 0.07279567, 0.06571465, 0.005532307, 0.13575353, 0.04082173, 0.041579492) * go_0(1.0, 1.0);
|
||||
result += mat4(0.03146011, -0.08227295, -0.03498218, 0.04772092, 0.12055223, -0.12383867, 0.05448358, -0.07948453, -0.019064998, -0.0964146, -0.024651276, 0.041473705, -0.06493721, -0.054806646, -0.21607941, 0.20078054) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.25740683, -0.33160943, -0.37422308, 0.12679969, -0.032204475, 0.41485202, 0.4538808, -0.082535125, 0.11784846, 0.10195789, 0.064491615, -0.10170162, -0.09500746, -0.15640756, -0.079364255, -0.12576963) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.02532797, -0.014487023, -0.09441118, -0.060885422, -0.41196415, -0.1359501, 0.07101173, -0.053279232, 0.010979353, 0.1914526, 0.054606825, 0.015926225, 0.10410896, 0.010272597, -0.048138764, -0.02698072) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.35856235, 0.099759184, -0.11972965, -0.03850837, -0.5143867, 0.3721666, -0.100802526, 0.21814734, -0.11864143, 0.15086797, 0.047075786, -0.14188164, 0.48882273, -0.12767795, 0.4937544, -0.41288656) * go_1(0.0, -1.0);
|
||||
result += mat4(0.21679138, 0.023770422, -0.5454043, 0.18567741, 0.15965948, -0.84900963, -0.4684333, -0.21884751, 0.5876668, -0.9346244, -0.30144307, 0.97177315, 0.24103107, 0.35953388, 0.2032729, 1.2934744) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.5121466, -0.123357795, 0.1833694, 0.048652876, -0.20895603, 0.0619325, 0.064119816, 0.072841786, -0.21813762, -0.126957, -0.23441431, -0.009071302, -0.09766064, -0.12546945, 0.086008705, -0.0072638122) * go_1(0.0, 1.0);
|
||||
result += mat4(0.15312338, -0.051029235, 0.07638347, -0.14028431, 0.10694411, -0.14639509, 0.3193828, -0.22767228, -0.19987194, 0.18207504, -0.19648756, 0.24752761, -0.03402804, -0.04186147, -0.20177092, 0.09467012) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.3587345, -0.20358992, -0.11016057, 0.21079709, -0.26201126, 0.040362626, 0.3186598, -0.059521858, 0.27564716, -0.041431133, 0.19315968, -0.30228892, 0.01191173, -0.10380854, 0.03030344, 0.026699625) * go_1(1.0, 0.0);
|
||||
result += mat4(0.13373446, -0.011457521, -0.24851708, 0.06563771, -0.051668253, 0.09096929, -0.013976447, 0.041433394, -0.046981215, -0.00015144625, 0.05696515, 0.024501698, 0.2714476, -0.017434085, 0.025333954, -0.054034695) * go_1(1.0, 1.0);
|
||||
result += vec4(0.06757453, -0.021112159, -0.015639946, 0.05520713);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Conv-4x1x1x56
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_6_tf
|
||||
//!SAVE conv2d_last_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_2 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_5 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_6 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_9 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_10 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_13 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.03795613, 0.09572901, 0.019826923, 0.10568741, -0.0030050736, -0.018890928, 0.0095737, 0.00807826, -0.022741016, 0.0046556294, -0.017018225, -0.010523109, -0.017621946, -0.0006488902, -0.009405731, -0.0027796263) * g_0;
|
||||
result += mat4(-0.046617493, -0.018167915, -0.039274286, -0.027566826, -0.015821747, 0.003789104, -0.0020801623, 0.004032968, -0.05708595, -0.018440764, -0.032891296, 0.004184342, 0.047413353, 0.0034510887, 0.019148773, -0.0035636695) * g_1;
|
||||
result += mat4(-0.046619494, -0.017274255, -0.03372405, -0.011152855, 0.10981248, 0.036214054, 0.07969624, 0.05590572, -0.031791378, -0.00307391, -0.0032425344, 0.0025762853, 0.0053703627, -0.02076939, -0.00058634114, -0.012593452) * g_2;
|
||||
result += mat4(0.110471316, 0.031102506, 0.07860556, -0.018570926, -0.05038586, -0.07667239, -0.0819002, -0.08958284, 0.03846167, -0.007570915, 0.008598097, -0.0082979705, -0.03610172, -0.022735123, 0.02343143, 0.030037913) * g_3;
|
||||
result += mat4(-0.075562544, -0.020187575, -0.020969959, 0.0062222136, 0.019780673, 0.059694994, 0.019240001, 0.05951303, 0.004168261, 0.00041100322, -0.0013793377, 0.002048099, -0.040564027, -0.031818517, -0.015498987, -0.02695407) * g_4;
|
||||
result += mat4(-0.0016428401, 0.018965026, -0.013192817, -0.008289604, -0.044686675, -0.009061507, -0.049217258, -0.043777503, -0.07308355, -0.063734084, 0.019393511, -0.028853234, 0.057311818, 0.04126226, 0.086301416, 0.11784249) * g_5;
|
||||
result += mat4(-0.06087458, 0.046508487, -0.10723279, 0.017619802, 0.13637137, 0.2054238, 0.013641375, 0.091581754, 0.03556439, 0.0500333, 0.0696777, 0.0922045, -0.020914901, -0.025425691, -0.050319638, -0.049094327) * g_6;
|
||||
result += mat4(0.0030941095, -0.008679898, -0.05815756, -0.038728733, -0.062450465, -0.073838525, -0.030359933, -0.08355475, -0.039032117, -0.0689333, -0.04834296, -0.079471886, 0.09694701, 0.17491414, 0.093450785, 0.16742545) * g_7;
|
||||
result += mat4(0.035618782, -0.027659958, 0.055540156, 0.013073733, 0.12144545, 0.05981087, -0.015131131, -0.0476281, -0.090847984, 0.005347584, 0.015588529, 0.024184622, -0.10743599, -0.01785147, -0.08566232, -0.14611128) * g_8;
|
||||
result += mat4(-0.03812077, 0.018126076, -0.016625525, -0.06906415, -0.06267368, -0.058914356, 0.0009385371, -0.026746314, 0.048242237, 0.028906677, -0.028120263, -0.004209134, 0.009636235, 0.013206963, 0.07449269, 0.038961377) * g_9;
|
||||
result += mat4(-0.014510558, -0.021065345, 0.09356215, -0.005815953, 0.08807958, 0.067895725, 0.08723713, 0.057831496, -0.10227873, -0.07699344, -0.06321843, -0.07448854, 0.09820774, 0.007563063, -0.14045772, -0.014161681) * g_10;
|
||||
result += mat4(-0.18385889, 0.2255883, -0.29741547, 0.14618248, -0.08100661, -0.06860545, -0.112705804, -0.122642964, -0.06736901, 0.06971933, 0.12909706, -0.0418256, -0.32786265, 0.032497127, 0.4390302, 0.032726523) * g_11;
|
||||
result += mat4(0.10560793, 0.083280005, -0.20369564, -0.14290833, -0.119196005, -0.028741803, 0.020456403, -0.06509816, 0.073811695, 0.02724128, -0.08691891, 0.10240907, 0.16827166, -0.17502932, -0.18295282, 0.15154512) * g_12;
|
||||
result += mat4(0.0036247042, -0.002368346, 0.049646147, 0.058079436, 0.14403848, 0.07125248, 0.040327612, -0.013934329, 0.03871744, -0.1717596, 0.20666012, -0.24093682, -0.09846371, 0.011563227, 0.11973811, -0.0574434) * g_13;
|
||||
result += vec4(0.022095086, 0.021079032, 0.030224537, 0.02154015);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(M)-Depth-to-Space
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_last_tf
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_last_tf.w 2 *
|
||||
//!HEIGHT conv2d_last_tf.h 2 *
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
vec4 hook() {
|
||||
vec2 f0 = fract(conv2d_last_tf_pos * conv2d_last_tf_size);
|
||||
ivec2 i0 = ivec2(f0 * vec2(2.0));
|
||||
float c0 = conv2d_last_tf_tex((vec2(0.5) - f0) * conv2d_last_tf_pt + conv2d_last_tf_pos)[i0.y * 2 + i0.x];
|
||||
float c1 = c0;
|
||||
float c2 = c1;
|
||||
float c3 = c2;
|
||||
return vec4(c0, c1, c2, c3) + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,969 @@
|
||||
// MIT License
|
||||
|
||||
// Copyright (c) 2019-2021 bloc97
|
||||
// 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.
|
||||
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.28296316, -0.020139743, 0.1038232, 0.09352482, -0.16964972, 0.07910997, -0.049914766, -0.10661066, -0.121037185, -0.029087039, -0.02511847, -0.078911744, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.3927183, 0.01805193, -0.031168332, -0.13300525, 0.20814548, 0.118818566, 0.1655351, 0.095023684, 0.17600809, -0.03928444, -0.014350658, 0.08458312, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.079089314, -0.0421829, 0.05452305, -0.22055493, 0.013279097, -0.12875281, 0.02452735, -0.101503745, -0.085946664, 0.05539176, 0.022408713, 0.14837204, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.102643915, -0.011254746, 0.1478563, 0.1030208, 0.12396588, 0.0016621432, 0.2551224, -0.10399001, -0.01068436, 0.07155532, -0.104522154, 0.026937222, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.8789423, 0.35707328, -0.29964274, -0.064913996, 0.4962815, 0.26001287, -0.9511284, 0.49574667, 0.39539725, 0.16308042, 0.119878456, -0.30259115, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.08852938, -0.32612664, -0.006712046, 0.28693515, 0.06320871, -0.3322611, 0.04651086, -0.11020996, 0.01821082, -0.22851005, -0.07803438, 0.021527015, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(0.12295851, -0.011285535, 0.015859747, 0.04005441, -0.018136669, 0.03171969, -0.0406123, -0.10731229, -0.12117574, 0.005033036, 0.047838476, 0.026843475, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(0.4655988, 0.05519082, 0.039515793, 0.28410903, -0.36144528, 0.13039446, 0.11338478, -0.2141387, -0.10026682, -0.07903024, -0.09410254, 0.043833878, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(0.110124744, -0.024725702, 0.028102143, -0.09493807, -0.06455328, -0.15164614, 0.04425987, 0.15483347, -0.045039337, 0.07210396, -0.005390788, -0.03832707, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(0.007907974, -0.035503313, 0.057224784, -0.19763541);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x3
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!SAVE conv2d_tf1
|
||||
//!WIDTH MAIN.w
|
||||
//!HEIGHT MAIN.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (MAIN_texOff(vec2(x_off, y_off)))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.012326053, 0.050769784, 0.1278702, -0.100782245, 0.14329414, -0.054558773, 0.023473471, 0.056829426, 0.048292916, 0.0046510273, -0.11478287, 0.0011030561, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.29542983, -0.55061895, -0.068554066, 0.1433222, -0.072878316, 0.30201668, -0.2223378, -0.06704077, 0.16955832, 0.3279914, 0.17619601, -0.1276919, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.09623417, 0.30559412, 0.094622105, -0.076706685, 0.07943858, -0.084815115, 0.12472551, 0.079850115, -0.13044213, -0.21300878, -0.095747225, 0.13412355, 0.0, 0.0, 0.0, 0.0) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.21291664, 0.17195296, -0.20080926, 0.1064855, 0.10228669, -0.09580175, -0.11217631, -0.09740562, -0.0033135475, -0.053094357, 0.2983595, 0.035281878, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.08955812, -0.45707774, -0.4606922, -0.5754473, -0.11395895, 0.33530128, 0.29705846, -0.18877256, -0.43502945, 0.114171304, -0.3750776, -0.081597246, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.26109028, 0.02662961, -0.10441071, 0.11199392, -0.12038989, -0.09642296, -0.061320662, -0.33058178, 0.20212512, 0.00840794, 0.14357455, -0.038080238, 0.0, 0.0, 0.0, 0.0) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.09533881, -0.13644339, 0.068756215, 0.079305276, -0.053370547, 0.19572955, 0.0682981, 0.14469264, 0.15582883, -0.057183057, -0.13919263, -0.016394936, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.041189935, 0.39878023, 0.028704925, 0.30194348, -0.04486593, -0.33899093, -0.103968106, 0.21802065, -0.077099144, -0.07389541, 0.18069103, 0.18894517, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.12399862, 0.19246885, 0.034825478, -0.0044787163, 0.13121822, -0.13573012, -0.030162754, 0.1899518, 0.102326415, -0.061512686, -0.005647928, -0.0937634, 0.0, 0.0, 0.0, 0.0) * go_0(1.0, 1.0);
|
||||
result += vec4(0.019286277, -0.033644073, 0.08196311, 0.0054393094);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.04088509, -0.06585775, -0.3094732, 0.12059048, 0.041417453, -0.06144871, -0.06655134, 0.03308842, 0.09287731, 0.010969216, 0.10343026, -0.11185897, 0.05685865, -0.09490512, 0.040908635, 0.03501189) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.04854754, -0.098667145, 0.67147833, -0.11299351, -0.022114437, -0.029202767, 0.014179382, 0.26027945, 0.22076549, -0.16490546, -0.0010764733, 0.08405975, 0.11849154, -0.19072372, -0.35719597, -0.059621073) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.079224996, 0.0669873, -0.1718969, -0.05002573, 0.044926763, -0.02904369, 0.017489236, 0.01144465, 0.059109706, 0.064998455, 0.14725484, -0.23879208, 0.039234288, -0.027365638, 0.26172164, -0.094598554) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.07159218, -0.03181544, 0.113837324, -0.053089984, -0.098298974, -0.29500297, 0.1608509, -0.044355504, 0.050882854, -0.19417204, -0.080487266, -0.00879743, 0.0007914453, 0.16640955, 0.21786706, 0.16398212) * go_0(0.0, -1.0);
|
||||
result += mat4(0.16324541, 0.19753313, -0.46597233, -0.2593132, -0.2781038, -0.21973547, -0.024623038, -0.16348499, 0.3628299, 0.044888914, 0.04054647, -0.63605887, 0.02099492, 0.060544077, -0.49359834, 0.36336297) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.16885692, 0.31907207, 0.020906802, 0.13290039, -0.037330728, -0.022859452, -0.020451576, -0.113437995, -0.085683934, 0.054102756, -0.044824492, 0.061346747, -0.038684413, 0.098444365, -0.06734984, -0.17084897) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.015821548, -0.119599186, 0.1614827, 0.08383641, -0.07933593, 0.12528986, -0.06300182, 0.09286327, -0.10199266, 0.02419403, 0.0028411683, -0.09028338, 0.07962534, -0.08676035, -0.19237737, -0.115502626) * go_0(1.0, -1.0);
|
||||
result += mat4(0.09471972, 0.21153462, -0.14393018, 0.055180002, 0.1817461, 0.016607309, -0.0771979, 0.11181317, -0.5491086, -0.102757886, -0.20952754, 0.022466583, -0.075119644, -0.14725658, 0.38451517, 0.12920731) * go_0(1.0, 0.0);
|
||||
result += mat4(0.0867803, 0.114654355, 0.21199988, -0.15367955, -0.01803536, 0.056378633, 0.0018388306, 0.024613786, -0.13306658, 0.017211098, 0.073351346, -0.12064064, -0.10484361, -0.067748636, 0.033206712, -0.13061953) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.002236411, -0.022144757, -0.04586377, 0.101181075, -0.03511624, 0.08440529, 0.18544284, -0.22786349, -0.042184375, 0.015734851, -0.038622506, 0.038529944, -0.09170703, 0.034527462, -0.07817406, 0.10547265) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.12135524, -0.07412039, -0.04979351, -0.082267545, 0.13343571, 0.29196215, -0.4364121, -0.10226428, 0.060835477, -0.23307934, -0.018231759, 0.15550235, 0.09095689, 0.18164484, 0.1322021, -0.022567045) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.0054531163, -0.039762255, -0.030490747, 0.04779882, -0.15290286, 0.056712102, -0.0776974, 0.04114215, 0.15946816, -0.03882117, 0.16770308, -0.026126247, -0.027203865, -0.064107865, -0.13670811, 0.1556276) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.092548385, -0.027285473, 0.084179096, 0.014961629, 0.2564254, 0.07626849, 0.28534448, 0.2588713, -0.018600503, -0.2433456, 0.041392803, -0.045712482, 0.26388907, -0.053502295, 0.14522223, 0.032808404) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.0013780193, 0.3482449, 0.071003586, -0.30707207, -0.05122194, -0.2833618, 0.07910779, 0.051078696, 0.021535402, 0.13021478, 0.022049015, -0.533547, 0.57265025, -0.12843914, -0.14913581, -0.1433724) * go_1(0.0, 0.0);
|
||||
result += mat4(0.07382619, -0.12152924, 0.13364957, 0.181974, 0.15804219, -0.10126773, 0.3029618, -0.12874149, 0.13743348, -0.23245592, -0.20119278, 0.029547188, 0.042436857, 0.04213892, -0.07975374, 0.023821082) * go_1(0.0, 1.0);
|
||||
result += mat4(0.022782229, -0.08359311, -0.060623147, 0.06565042, 0.09828792, 0.044808697, -0.28872305, -0.00092168007, 0.021737702, -0.08698349, 0.1950025, 0.07931995, 0.040952396, -0.07443172, -0.021157127, 0.0056698937) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.09995892, -0.2047294, 0.1414849, 0.062335726, -0.22492298, 0.05269799, -0.029233055, -0.050517935, -0.12534393, -0.12194023, -0.07035469, -0.070764475, 0.18903446, 0.07691209, 0.06153371, 0.011280912) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.036189888, -0.07586571, -0.05888163, 0.010425367, -0.028375402, -0.18870986, -0.19146784, 0.19274063, -0.18856238, 0.0064240266, -0.14537223, -0.06971656, 0.0852742, -0.04866623, -0.031686075, 0.031702038) * go_1(1.0, 1.0);
|
||||
result += mat4(0.0618941, 0.100858234, 0.2628019, -0.048507668, -0.051001363, -0.03195978, 0.035452217, -0.001991919, -0.09649028, -0.047445696, -0.09221298, 0.07602656, -0.02382384, -0.119645916, 0.085616075, -0.07076033) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.019222878, -0.0491929, -0.4902266, 0.18501294, 0.014529614, -0.077125326, 0.011563931, -0.20236616, -0.101982154, -0.021150962, -0.07537948, -0.1540349, 0.028949164, -0.06827332, 0.0067634755, 0.09582376) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.05995539, -0.031138182, 0.01334257, 0.06827176, -0.030762246, 0.006615233, -0.03562788, 0.016249394, -0.14797118, 0.014671043, -0.09325859, 0.25653747, -0.11474991, 0.05436232, 0.031051394, 0.04179694) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.032279838, -0.030521005, 0.0029688699, 0.005165139, 0.15907808, -0.20421815, -0.07713175, 0.067530625, -0.08619395, 0.026114263, 0.08821273, 0.011591694, 0.018677557, 0.057708874, -0.25859246, -0.18693781) * go_2(0.0, -1.0);
|
||||
result += mat4(0.10823143, -0.31875235, -0.24394153, -0.0025489891, 0.016761065, -0.19857498, -0.07858479, -0.07811158, -0.38551694, -0.049090322, -0.050053325, 0.23398961, 0.014974165, 0.17498055, 0.29105362, -0.353647) * go_2(0.0, 0.0);
|
||||
result += mat4(0.05621677, -0.19492444, 0.460332, 0.055917628, -0.06404381, -0.06684098, 0.053624872, 0.057300456, -0.019248677, -0.15110065, 0.032379635, -0.12673225, 0.0068658157, -0.13001235, -0.017716292, 0.064182095) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.06764552, 0.004707433, -0.13827331, -0.21957871, -0.03789028, -0.04962028, 0.022955444, -0.058468018, 0.13735814, -0.031270552, -0.018490225, 0.0063876202, -0.052979283, -0.030049473, -0.004811771, -0.0044099926) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.028652798, -0.027029367, 0.62600744, 0.0900562, 0.03869923, -0.20111556, 0.095930666, -0.13164565, 0.5562579, 0.011937122, 0.22882107, 0.030288015, 0.09856272, 0.04736032, -0.077492185, -0.10207275) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.10581002, -0.16504957, -0.5688921, 0.0414545, 0.04749444, -0.052849945, -0.011017121, -0.025284614, 0.14316759, -0.08547362, -0.09654446, 0.08682504, 0.050776027, 0.0678741, -0.04913651, 0.07527552) * go_2(1.0, 1.0);
|
||||
result += mat4(0.04126091, 0.0048704315, 0.041699376, -0.05820725, -0.09664279, 0.07648305, -0.17979898, 0.11698985, -0.025436765, 0.023232851, 0.010656572, 0.08157569, 0.19584864, -0.022928072, 0.053339157, 0.0039929505) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.040733483, 0.12260473, 0.08071146, 0.07257762, -0.016945919, -0.31637576, -0.24281953, -0.0038469466, -0.10203634, 0.13631973, 0.06505259, -0.13119389, -0.09723076, -0.139551, -0.07504509, 0.08645985) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.017005404, 0.049066268, -0.007544932, -0.04884536, 0.09984347, -0.04447364, 0.4902235, -0.062780835, -0.18389583, 0.07305648, -0.22014385, 0.08004685, 0.0992568, -0.08569604, 0.093966395, -0.07047139) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.0017705248, 0.020553982, -0.09167042, 0.0036356782, -0.11867446, -0.07055574, 0.40252638, 0.09657129, 0.0888632, 0.1031708, -0.022127641, -0.023769693, -0.0861388, 0.13420185, -0.11774454, 0.038774434) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.15173717, -0.13590458, -0.0891863, 0.12289548, 0.13942605, 0.22152588, -0.19292432, 0.14169839, 0.010543665, 0.07648361, -0.057333756, 0.09535759, -0.053601623, -0.026824495, 0.09365424, 0.17476946) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.070416056, -0.061970036, -0.039723337, -0.18874651, -0.07098426, -0.019835865, -0.5612458, 0.060437083, -0.03774378, 0.18536821, 0.28587544, 0.035555754, 0.15771326, -0.13527197, 0.13342534, -0.06564073) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.10967661, 0.025388904, 0.09003177, -0.04087592, 0.09531671, -0.11809294, -0.41613623, 0.038198076, 0.01019813, -0.018864965, -0.18400626, -0.038704176, 0.0105671035, 0.024449013, -0.008989595, -0.027171193) * go_3(1.0, -1.0);
|
||||
result += mat4(0.16193569, -0.21445285, -0.20130903, -0.13498883, -0.008031679, 0.050757203, 0.78938776, -0.03749514, 0.11998137, 0.19368882, 0.12328945, 0.0058578993, -0.13852382, -0.033867255, -0.018267661, 0.036348555) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.06254118, 0.087295115, 0.031116437, 0.0416281, 0.061828617, 0.34479564, -0.15537797, -0.17144552, 0.13989387, -0.13792284, 0.056215156, 0.12714528, -0.0198865, 0.04927947, 0.013614583, -0.041810013) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.044073943, 0.12072677, -0.0022342638, -0.24414532);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!SAVE conv2d_1_tf1
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.07115729, 0.01065505, 0.19167988, -0.02504489, -0.15064801, 0.079008736, 0.05437936, 0.027479589, -0.021383656, 0.032731537, -0.06657876, 0.022649521, -0.06501893, -0.02335689, 0.010445489, -0.05430297) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.1178601, 0.07425715, 0.063272275, -0.18308601, -0.13955134, 0.005166404, -0.022591779, -0.016827974, -0.024990188, -0.13372071, -0.056342285, 0.12489847, 0.081861794, -0.07083351, 0.021897513, 0.0629395) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.051357627, -0.13874975, -0.09887168, -0.011908862, 0.03639772, -0.13195883, -0.05321156, 0.03913229, -0.08160194, -0.07128151, 0.043625016, 0.11966009, 0.03162217, 0.018834392, -0.0625129, 0.10726711) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.15922394, -0.043482754, -0.22571066, 0.009280428, -0.3882705, 0.08418719, 0.15329506, -0.028419001, -0.011272379, 0.15897545, 0.041217074, -0.0143014155, 0.09451862, -0.056342427, -0.14568482, 0.05556279) * go_0(0.0, -1.0);
|
||||
result += mat4(0.13879324, -0.23339099, -0.24573983, -0.09575104, 0.03823306, 0.4752516, -0.1696623, -0.18472373, -0.1510259, 0.23040254, 0.4196143, 0.3462817, 0.035172507, 0.18228662, 0.22475636, -0.19945027) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.08876766, 0.19567333, 0.25174314, -0.09637879, -0.007957943, 0.13510521, 0.030193076, -0.0018362573, -0.006884444, -0.41804117, -0.1026309, -0.053339038, -0.1283198, -0.03033918, 0.055674326, 0.094377995) * go_0(0.0, 1.0);
|
||||
result += mat4(0.06780768, -0.07774435, -0.0616546, -0.046531744, -0.11723141, 0.10792474, 0.013314576, -0.031451598, -0.009870351, 0.10215877, -0.13101454, -0.19878799, -0.09712651, 0.10423937, 0.14170039, -0.03359521) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.020114673, -0.015194169, 0.03657608, 0.17162928, 0.070458665, -0.08041664, 0.14067306, 0.19699603, -0.28763783, -0.033556152, -0.6588468, -0.48221052, -0.123711474, -0.080758795, -0.3187303, 0.121004865) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.074900605, 0.09297913, -0.08621144, 0.116730206, -0.034766622, -0.10381484, 0.060793545, -0.014790814, -0.123858415, -0.0010626495, 0.20547503, -0.07206306, -0.17324795, 0.023932874, 0.017495958, -0.09924652) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.015568068, 0.005394868, 0.15463537, 0.06416607, -0.045670815, -0.013540727, -0.12960619, 0.0006581649, 0.09432853, 0.05575682, -0.022219105, 0.022416297, 0.0148129435, -0.067619696, 0.022989385, -0.09695771) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.107209, 0.07072438, -0.10235772, -0.12078849, -0.02751833, -0.043195058, -0.17197154, 0.120612316, -0.17310137, -0.09429793, 0.06511165, 0.18072544, -0.21168593, 0.16383737, 0.25012484, -0.089589044) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.005439779, 0.0028433986, -0.09885586, -0.06572956, -0.0061691296, 0.15485546, -0.23724958, 0.004232802, 0.07794742, -0.012552598, 0.07554404, 0.10843201, -0.013223918, -0.08705092, -0.23228747, 0.03599732) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.043396916, -0.10680695, -0.019935586, -0.06703658, -0.30075943, -0.010179525, 0.30197874, 0.04888297, 0.00779067, 0.22583807, 0.2039884, -0.0074303118, -0.19240093, -0.024718538, 0.057117213, 0.19431825) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.37633005, 0.043971814, -0.21423087, 0.118503235, -0.15058799, 0.115756795, -0.13719647, 0.020510519, 0.1123193, 0.14797291, 0.05467349, 0.2039607, -0.31973588, 0.1667847, -0.017739004, -0.11280262) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.0084394775, -0.1281101, -0.20841378, 0.01986435, -0.04122467, -0.21089631, -0.08062371, 0.11315133, 0.05693114, -0.23773515, 0.03792205, -0.008872407, 0.04554895, -0.10683658, 0.10683206, 0.06875721) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.103948504, -0.007483217, -0.12571928, 0.054868475, -0.030646881, -0.010098222, 0.019018777, -0.07072212, -0.10689893, 0.16498323, 0.048089568, -0.10912806, -0.027318537, -0.025491163, 0.012588013, 0.072701246) * go_1(1.0, -1.0);
|
||||
result += mat4(0.14094622, -0.028118243, 0.016804086, -0.18000692, 0.33351874, 0.14980756, -0.07135749, -0.16573106, -0.17243773, 0.054617904, -0.2933543, -0.12602285, 0.08480712, -0.05704333, 0.22336398, 0.026583148) * go_1(1.0, 0.0);
|
||||
result += mat4(0.046759557, -0.03100408, 0.40000245, -0.08521555, 0.19592628, -0.15150753, 0.25288078, -0.061794683, -0.047818147, -0.12249124, 0.020410215, -0.11503924, 0.046108168, 0.030459814, -0.14096366, 0.09120256) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.087491795, -0.024289595, -0.09060237, 0.020922959, 0.09557061, -0.08556962, -0.0503455, -0.010846053, 0.0030694185, -0.008256591, 0.08290225, -0.034981687, 0.07342003, -0.021816112, -0.13905519, -0.06265962) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.08126147, -0.05866924, -0.015698025, 0.093630895, -0.02379264, 0.115918085, 0.19431724, 0.041815966, -0.051647816, 0.15277039, -0.03721037, -0.085520886, 0.041766718, 0.104392216, 0.0559556, 0.0049254233) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.11176419, 0.112272635, 0.1367475, -0.010482275, -0.06719008, 0.064003386, -0.08132314, 0.015465676, 0.052741583, 0.06779717, 0.038533892, -0.16428822, 0.040990274, 0.002559234, 0.097567044, -0.058192518) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.17228632, 0.008296625, 0.009418271, 0.037103783, -0.0601486, 0.04531715, 0.19613501, 0.112170085, -0.02256726, -0.093685195, -0.1341531, -0.038480807, 0.109840475, 0.062418167, 0.15140085, 0.050787117) * go_2(0.0, -1.0);
|
||||
result += mat4(0.15433665, 0.2104034, 0.12395812, 0.13799714, 0.14945604, 0.67457545, 0.27575177, -0.047493283, 0.24992993, -0.5305435, 0.0131732905, -0.36911693, 0.14442082, -0.18583177, -0.2861722, 0.19419897) * go_2(0.0, 0.0);
|
||||
result += mat4(0.040242445, -0.13234852, 0.10056324, 0.055854917, 0.07447713, -0.023067042, 0.00021051937, -0.0495407, -0.22037992, 0.68047297, 0.05774606, -0.012461005, 0.104557075, 0.04832623, 0.010292581, -0.050617047) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.060079176, 0.086553656, 0.0060872175, -0.012576339, 0.025149338, -0.07379716, -0.18048704, -0.007130346, 0.007826557, -0.095655076, -0.0032888134, 0.21027069, -0.09868755, -0.1180311, 0.0081250835, -0.05078016) * go_2(1.0, -1.0);
|
||||
result += mat4(0.19124818, -0.05949092, -0.36762074, -0.08203597, -0.10276991, 0.111005515, -0.2845309, 0.113985784, 0.07206471, -0.026585411, 0.20032002, 0.5691625, -0.0460136, 0.03874166, 0.09858682, -0.15913802) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.00397842, -0.014763085, 0.080231026, -0.09142265, 0.03637215, 0.064106315, -0.030963007, 0.0557953, 0.04173885, -0.024534896, -0.2092259, 0.06913638, 0.08103145, -0.0033994897, -0.10903093, 0.062850125) * go_2(1.0, 1.0);
|
||||
result += mat4(0.01206918, 0.024855271, -0.051995132, 0.013999821, -0.021517826, 0.06216198, -0.050853133, -0.064136736, -0.047408275, -0.07858566, 0.074464396, -0.038218755, -0.13216262, 0.008905726, 0.10333, 0.03049554) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.027152343, -0.069046065, -0.013017797, 0.0763, -0.08611993, -0.020867927, 0.012807627, -0.11971997, 0.025972975, 0.095127404, -0.070044935, -0.21399231, -0.22536097, -0.028828809, 0.123399965, -0.15967365) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.038314234, -0.014114242, 0.012115026, 0.05505015, 0.11785298, -0.08772618, 0.034408223, 0.09134674, -0.04727011, 0.020709611, -0.01780165, -0.14374214, -0.30412516, -0.011123043, -0.024216317, -0.007538433) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.17673545, 0.077738725, 0.056153737, 0.028693894, 0.05688375, 0.021928595, 0.014585902, 0.019364892, 0.029056642, -0.2072201, -0.17548367, 0.085471265, 0.16439342, -0.0052957633, 0.22321554, -0.19246858) * go_3(0.0, -1.0);
|
||||
result += mat4(0.1914782, -0.15620962, -0.16686897, -0.04141303, 0.07696967, -0.013115313, -0.057627093, -0.13849305, 0.08699377, -0.07339016, -0.053074118, -0.059418138, 0.19988623, -0.23852244, -0.12574267, -0.29139704) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.017691063, 0.18901291, 0.16250716, -0.11039392, 0.056900974, 0.036662772, -0.13399602, -0.11378214, -0.10924602, 0.2130181, -0.042094063, -0.012445028, 0.013168919, 0.119448364, -0.014406005, 0.0054324497) * go_3(0.0, 1.0);
|
||||
result += mat4(0.11552786, 0.090796515, -0.11559005, -0.035706047, -0.044022456, -0.027642358, 0.08824298, 0.035067793, 0.18125483, -0.15502097, 0.094219126, 0.07493505, 0.022493582, 0.038250685, -0.076567575, -0.059311453) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.08612596, 0.016376335, -0.0023271537, 0.32511148, 0.03789289, 0.13106889, 0.22370385, 0.21145949, 0.1844514, -0.0766592, 0.093758754, 0.13821359, -0.062405586, 0.0028724174, -0.13588348, 0.00024406122) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.08991004, 0.074423954, -0.020964831, -0.070288494, -0.1192369, -0.015506713, -0.28136373, 0.042911243, 0.08215164, 0.11065419, -0.006201638, 0.057742044, 0.0014476188, -0.01443158, 0.22631277, -0.06787264) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.07235962, -0.019149294, 0.05072898, 0.03962245);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.14315613, -0.031299837, -0.011195234, 0.0073360316, 0.07264984, -0.110979274, 0.06560588, -0.040463638, 0.28964168, -0.05644335, -0.060729366, -0.15811591, 0.028339373, 0.027486937, 0.0360574, 0.05856459) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.16211128, 0.20672597, -0.30374205, -0.056202736, -0.10893948, 0.053066984, -0.18297112, 0.028844962, 0.22754766, -0.07141921, 0.07142953, -0.1357581, 0.008053467, 0.04668908, 0.17258649, 0.22506891) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.07014762, 0.032112304, 0.028849715, 0.09427007, 0.008323501, -0.085777245, 0.083501115, -0.16150802, 0.24127382, -0.1305689, -0.027557204, -0.15057805, 0.09748757, 0.08182083, -0.107643455, 0.020552907) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.04630706, -0.056070503, 0.058440026, -0.005662525, 0.08736355, 0.08821088, -0.049539115, 0.08171937, 0.28466523, -0.025859421, -0.0026971614, -0.15181617, -0.022231927, 0.3566104, -0.024887348, 0.12051598) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.20976813, -0.23778942, 0.28854275, -0.27583683, -0.27604774, -0.15861328, 0.09581984, 0.06572128, 0.092306405, -0.06962751, -0.042226445, 0.035234913, 0.084891975, -0.03846841, -0.1473667, 0.2810354) * go_0(0.0, 0.0);
|
||||
result += mat4(0.028011162, 0.08945262, 0.15859836, 0.18426442, 0.10649845, -0.0918649, -0.12257575, -0.00914911, 0.23701023, -0.030067213, -0.01938559, -0.11026175, -0.5953985, 0.28875506, -0.035278864, -0.05043055) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.14445779, -0.06907616, 0.13078876, -0.0089114, -0.110637166, -0.123719245, -0.094949, 0.046267383, 0.4727523, 0.0073195575, -0.014788787, -0.14922102, -0.021974785, -0.10706751, 0.00049029186, 0.09215345) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.20936993, -0.22377276, -0.07697398, 0.039161056, 0.044213686, 0.037542075, -0.06600642, 0.017124292, 0.3406197, 0.011907687, 0.019732054, -0.22745137, -0.22178015, 0.49051985, -0.03707166, 0.14849792) * go_0(1.0, 0.0);
|
||||
result += mat4(0.07833466, 0.10888627, 0.16015877, -0.049263358, 0.29002127, -0.010949114, 0.013081097, -0.071674205, 0.3532135, 0.013165473, -0.05282189, -0.16688257, 0.009552089, -0.2740816, 0.04927233, -0.37047002) * go_0(1.0, 1.0);
|
||||
result += mat4(0.23682123, -0.027914839, 0.02372468, -0.07127212, 0.053436097, 0.057737537, -0.008556659, -0.025973454, 0.06468388, 0.18805866, -0.08180048, 0.058999106, -0.3058321, -0.06642967, -0.092997625, 0.10527466) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.1353085, -0.016593851, 0.21518163, -0.10272456, 0.14382689, 0.05056661, -0.27799338, 0.11351653, 0.05838342, 0.28104934, -0.03777824, 0.003435516, 0.057915565, -0.17574134, -0.24437475, 0.13420977) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.13400255, -0.056437124, 0.11310834, 0.040429913, 0.098928474, -0.020769242, -0.079605736, 0.0494632, 0.0660877, 0.098982334, -0.055884495, -0.046533633, 0.17815505, 0.027310565, -0.24176653, -0.025550256) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.03637618, -0.012618673, 0.11865397, 0.19804053, -0.03522831, 0.24310908, -0.056454524, -0.44885796, 0.02212509, -0.20253624, 0.038810212, -0.17396528, 0.08970355, 0.005103078, 0.061075203, 0.44292897) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.25074747, -0.0015575301, -0.685015, 0.07345307, -0.08419402, 0.06640714, 0.43799296, -0.17571151, 0.0049855476, 0.09024738, 0.055744022, 0.018739637, 0.34734032, 0.114896655, 0.0404696, -0.11327049) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.12284062, -0.31131, -0.14712588, -0.18645866, 0.17581487, 0.1357234, 0.09913364, 0.005298711, -0.056155153, 0.042429443, 0.039454732, -0.04111384, 0.2623163, 0.09701166, 0.022825675, 0.050480727) * go_1(0.0, 1.0);
|
||||
result += mat4(0.058734808, 0.038528245, -0.042670116, -0.15190329, -0.028179986, -0.05362995, 0.017090468, -0.24449602, -0.08240927, -0.033122182, 0.009938243, -0.0052937623, 0.2171439, 0.06879817, -0.10361997, 0.018995138) * go_1(1.0, -1.0);
|
||||
result += mat4(0.027555468, 0.016337285, 0.19074728, 0.26690376, -0.088713005, -0.0021182299, -0.23062791, -0.32101163, -0.0040022335, 0.16835448, 0.05424022, -0.02156396, 0.24163729, 0.10243619, -0.04331782, -0.014350939) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.13836963, 0.053369813, 0.036432605, 0.062288612, -0.06264361, -0.049093347, -0.0315955, -0.11237456, -0.064744405, -0.0151798045, 0.044210885, 0.010166375, -0.038355727, -0.05203739, -0.075036794, 0.1664177) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.08583114, 0.08268218, -0.05771351, 0.10195048, -0.10128163, 0.10874855, -0.02580701, 0.028834302, 0.1950179, -0.0130183315, 0.0092119705, -0.060479227, 0.117747106, 0.061403573, -0.0028475628, -0.032362986) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.05310153, -0.061091065, 0.19438389, -0.10475873, 0.00045120303, -0.24876194, 0.017168125, -0.050173752, 0.012073283, 0.035660096, -0.017562328, -0.110271364, -0.015546384, 0.17965329, 0.10068208, -0.014481325) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.085558474, -0.0007109211, 0.20868625, 0.150163, -0.19283043, 0.025976779, 0.08384698, 0.031011146, 0.17268184, 0.008871077, -0.04097794, -0.12868725, 0.01336166, -0.038823843, 0.1703644, -0.067780636) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.06480841, -0.44256654, -0.19949587, -0.030677497, -0.27930573, -0.041867044, -0.15648738, 0.11573067, 0.28664824, 0.009770385, -0.058617204, -0.06607673, -0.038160402, 0.009497089, 0.03303058, -0.079379834) * go_2(0.0, -1.0);
|
||||
result += mat4(0.17752203, 0.10979527, -0.058749028, -0.30194217, 0.30484176, -0.20980492, -0.05234784, -0.2590473, 0.23003183, 0.21903595, -0.024891363, -0.14337292, -0.02971356, -0.29613075, -0.045642294, 0.23826689) * go_2(0.0, 0.0);
|
||||
result += mat4(0.018211683, -0.005840598, -0.19021381, -0.096696235, 0.39998052, -0.34746838, -0.039627917, 0.087701194, 0.15526368, -0.008095372, -0.044220537, -0.08634815, -0.121496454, -0.06792033, -0.14959472, 0.078917444) * go_2(0.0, 1.0);
|
||||
result += mat4(0.33109078, 0.012287281, -0.034155898, -0.04840956, 0.068748444, 0.006142039, 0.06598935, 0.024775596, 0.22379673, 0.056089353, -0.006119644, -0.018509025, 0.10084137, 0.15556572, -0.041211523, -0.21550669) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.058160853, 0.08899222, -0.17401625, -0.1449813, -0.015872562, -0.03780256, 0.15702572, 0.34013954, 0.1580772, 0.074823864, 0.035488904, -0.01627819, -0.15551315, -0.3638866, -0.09833458, 0.15037175) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.12707977, -0.19947061, -0.11524648, 0.09216174, -0.07161296, 0.05675567, 0.06843247, 0.2803306, 0.25222927, -0.044076066, 0.053775772, -0.09939824, 0.16903089, 0.11475717, -0.07015584, -0.036021322) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.12290332, -0.05469477, 0.02696626, 0.051133692, -0.05541504, -0.2811521, -0.13008943, 0.031793896, -0.32529324, -0.01663752, -0.0658181, 0.17300756, 0.22281154, -0.11001508, 0.09578194, -0.055437982) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.083753526, -0.048933715, -0.13912897, 0.10929772, -0.1789828, -0.1586524, -0.10964165, -0.08210391, -0.11568187, -0.04813496, -0.2417861, 0.24446528, 0.13570863, -0.26869404, 0.3013413, 0.11678686) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.21105368, 0.15749952, -0.18983693, -0.023642758, -0.1633653, 0.10107988, 0.052329395, -0.080253236, 0.15375629, -0.045091413, 0.05070866, 0.12416106, 0.16600485, -0.10412354, 0.061849747, -0.084013924) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.03863923, 0.03690167, -0.053106382, -0.07523278, -0.04214836, 0.53898096, 0.15308584, 0.22835171, -0.24771535, 0.1402687, 0.1000896, -0.08719167, 0.0886567, 0.15255097, 0.14695966, -0.06659865) * go_3(0.0, -1.0);
|
||||
result += mat4(0.110334344, -0.12696493, 0.24256139, 0.02536166, 0.08322421, 0.022147777, -0.35030407, 0.13734557, 0.053133942, 0.43650532, -0.30170345, 0.08751837, 0.012917502, 0.27496436, 0.11422729, 0.15508565) * go_3(0.0, 0.0);
|
||||
result += mat4(0.16684863, 0.26743406, 0.15951683, 0.033597723, -0.044719726, 0.1127182, 0.007923161, 0.06415458, -0.07269362, -0.07828715, 0.09216738, 0.11528897, -0.13371283, -0.124177165, 0.14804523, 0.14156726) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.041141883, 0.023617791, 0.11484465, 0.13131519, -0.14753738, 0.17067687, -0.017538434, 0.24042644, -0.058103643, 0.3143255, 0.02476919, -0.0024666793, -0.26759955, -0.06099211, 0.006415725, 0.10394301) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.04198037, 0.03277123, -0.25069895, -0.21043587, -0.27417016, 0.08047665, 0.29731026, 0.07629813, -0.15695353, -0.14299184, 0.026618432, 0.13265325, 0.07727133, 0.12872085, 0.13887435, 0.1347057) * go_3(1.0, 0.0);
|
||||
result += mat4(0.039232086, 0.117847264, -0.071643315, -0.040677182, -0.029160816, -0.06968689, 0.12880929, 0.037579957, -0.036671028, -0.022678757, -0.069731854, 0.10590314, 0.028034678, -0.015759282, 0.047180142, -0.16366881) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.079253934, 0.001511763, 0.100159355, 0.01585197);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!SAVE conv2d_2_tf1
|
||||
//!WIDTH conv2d_1_tf.w
|
||||
//!HEIGHT conv2d_1_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_1_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_1_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.024126908, 0.01737047, 0.04563732, 0.08303721, -0.21339902, 0.00025652428, -0.09666459, -0.07654246, -0.01201168, 0.14373912, 0.22268519, 0.049181588, -0.0751725, 0.006847365, -0.025867194, 0.19233267) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.25251204, -0.34213448, -0.0022676045, 0.29270738, 0.08876456, 0.067294724, 0.2865476, -0.009144941, -0.074606106, 0.14566834, 0.14162645, 0.10980335, -0.7958991, -0.15410729, 0.038512416, -0.17033637) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.115404196, -0.11004134, 0.13174473, -0.0006875606, 0.0051814034, 0.058522645, -0.0795437, 0.0011465811, -0.019500278, 0.12752724, 0.16985136, -0.054932587, 0.16734739, -0.04686017, -0.072241016, 0.054562975) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.07528159, -0.113516726, 0.2081102, 0.009942251, 0.08256535, 0.050133914, 0.012745932, 0.13902397, 0.009369715, 0.083261885, 0.17366019, 0.069754004, 0.030654406, -0.045856245, -0.055254143, 0.16265897) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.14366727, 0.24948351, 0.12160293, 0.10929859, -0.116071545, -0.11725494, -0.13926856, -0.026759636, 0.12723772, 0.1938045, -0.02745115, -0.0644584, -0.23854719, 0.059308372, -0.446269, -0.06978486) * go_0(0.0, 0.0);
|
||||
result += mat4(0.21108554, -0.1717225, 0.066633105, 0.15418948, -0.08902029, 0.047925282, 0.15817304, -0.080941506, 0.007364865, 0.10506626, 0.20205018, -0.078695655, 0.14004812, -0.3195092, 0.19157887, -0.12697977) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.08145032, -0.14292753, 0.066565305, -0.061348185, -0.08738346, 0.011608093, -0.0024047727, -0.024741996, -0.11547277, 0.10013328, 0.21730538, 0.05598899, -0.17741105, 0.075944185, 0.027434295, -0.2550598) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.026223006, 0.11214396, -0.133987, 0.1303522, 9.32011e-05, -0.14755996, -0.14002979, -0.039624512, 0.045111652, 0.17618611, 0.17764348, 0.104528464, 0.20592515, 0.07240335, -0.27604735, 0.038880046) * go_0(1.0, 0.0);
|
||||
result += mat4(0.17734227, -0.002935363, 0.07505682, -0.029969893, -0.024536638, 0.11236127, 0.119374484, 0.08002781, -0.003541722, 0.1428466, 0.1729824, 0.055412393, -0.04790376, 0.18020035, 0.05376964, -0.1520942) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.11352182, -0.019249126, 0.10782615, 0.03079928, 0.020381734, -0.08998433, -0.09211494, -0.054406203, 0.1828849, -0.07692097, 0.004733955, -0.026685018, -0.08044814, -0.071961075, 0.029184176, -0.22562811) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.34489468, -0.07447471, 0.026422959, 0.33550653, 0.22130035, 0.059709545, -0.07646962, -0.18386386, 0.33911958, -0.07534871, 0.040870134, 0.051136248, 0.32681262, 0.20612194, -0.1609581, -0.70460784) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.27617922, 0.09758603, 0.05103887, -0.09281693, -0.007143339, 0.006635712, -0.055270564, -0.022629099, -0.13023081, -0.013819027, -0.038695697, 0.047280338, -0.13964762, 0.09852924, -0.10056262, -0.084967695) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.1370323, 0.030904075, -0.033860117, 0.08926374, -0.14616281, -0.29926816, -0.23738252, -0.21374625, -0.14039646, 0.11503669, 0.082101606, -0.061717354, 0.021357644, -0.10676707, 0.03214661, 0.029967157) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.29881296, -0.22195289, -0.3512607, -0.2277441, 0.033705913, -0.23267402, -0.119738854, -0.18925253, 0.068823405, -0.15160555, 0.2585695, 0.10484223, -0.012574211, 0.38808516, 0.2599094, -0.4991424) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.07474731, 0.22742131, 0.014462262, 0.08409484, 0.09579643, -0.0519534, 0.0007793075, -0.044820115, -0.010144471, -0.040506937, 0.0056340825, 0.057767954, -0.14988829, -0.05099549, 0.007204364, -0.07094934) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.05736621, 0.12072876, -0.02037183, 0.05012334, -0.1173538, -0.10062993, -0.0033958228, 0.0142556345, -0.011005385, -0.0066177617, -0.058390465, 0.048240293, 0.09835053, 0.17917523, -0.06466951, 0.017518612) * go_1(1.0, -1.0);
|
||||
result += mat4(0.1413101, -0.30268928, -0.17851736, -0.10797371, -0.01964573, 0.14356858, -0.06759965, 0.17416531, 0.13905385, -0.017476829, 0.06541924, -0.044690568, -0.080723755, -0.08610206, 0.095347285, -0.09233214) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.07254187, -0.091158785, 0.018472971, 0.03514051, 0.018888336, 0.107934274, -0.018830854, 0.10007211, -0.053966418, -0.035646267, -0.031214178, -0.05980228, -0.13045661, -0.011743741, -0.03325275, 0.071065165) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.037697386, 0.054388218, -0.010934479, 0.2266702, 0.049999133, 0.017648092, -0.044225454, 0.21611899, -0.03805845, 0.054236397, -0.018563407, -0.060588073, -0.031215845, 0.075081706, 0.07333242, -0.09651128) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.32236508, -0.0026381002, -0.30787975, 0.2963127, -0.13276175, 0.1058753, -0.12744896, 0.09749292, -0.02683677, -0.0041124597, 0.006103888, -0.09997201, 0.092101686, -0.08375288, 0.09641652, 0.053333007) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.027999232, -0.060004722, -0.009207874, -0.0952888, -0.038418446, -0.13316345, 0.099323496, 0.048450433, 0.0443969, 0.056023613, 0.1156147, 0.018980766, 0.040020484, 0.07555044, 0.0039174426, -0.044098593) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.101029314, 0.33333415, -0.22052327, -0.035329416, 0.17229559, 0.12564908, -0.07879576, -0.09248896, -0.03239869, 0.022611454, 0.05610472, -0.02181683, -0.06347532, -0.077292696, 0.02005389, -0.078899406) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.028139396, -0.04349171, -0.019393284, 0.42110333, 0.37065667, 0.5282552, 0.43816927, 0.19155908, 0.051832534, 0.02050813, 0.030795977, 0.023960136, -0.27617985, 0.19165507, -0.005492024, -0.13349663) * go_2(0.0, 0.0);
|
||||
result += mat4(5.0700226e-05, 0.21293098, -0.39902148, -0.058406413, -0.06766975, 0.1129277, -0.012398328, 0.025031524, 0.03519656, 0.06486415, 0.15710293, 0.014098051, 0.057754945, 0.116186336, -0.14429826, 0.051864166) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.012280755, 0.043744788, -0.06420968, 0.012739398, 0.043073926, 0.031230433, 0.00036492705, -0.039208546, -0.09329152, 0.06928111, 0.11622664, -0.009106846, 0.111528054, -0.020315262, 0.036427997, 0.15881014) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.066635534, 0.13901882, 0.0885122, 0.1030835, 0.08539728, -0.015466482, 0.0706688, -0.1611047, 0.02179479, -0.00048529037, 0.08708685, -0.00894464, -0.13046473, -0.21456988, -0.20666413, 0.049039323) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.100800075, -0.03772198, -0.095183305, -0.15150243, -0.08743059, -0.24299338, -0.019315414, -0.1574107, -0.013610722, 0.064871654, 0.058439128, 0.008972897, 0.10339555, -0.027356634, 0.07666196, 0.048524544) * go_2(1.0, 1.0);
|
||||
result += mat4(0.046309173, -0.03858991, -0.13260359, 0.0017626585, 0.1453724, 0.1402359, -0.079240486, 0.13017912, 0.0629575, -0.15448172, -0.1856442, -0.044694453, -0.17226808, -0.08065212, -0.008038736, -0.15994963) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.18369722, 0.03849556, -0.035185467, -0.20205377, 0.03879293, 0.02712859, -0.051278092, 0.14862835, 0.10261192, 0.18085574, -0.025982017, -0.029160796, 0.5301373, 0.09614058, 0.35518438, -0.014906588) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.31154996, -0.06868871, -0.012681131, 0.028093819, -0.37321633, -0.14738804, 0.06060776, 0.050054748, 0.013779029, -0.020390315, -0.12487434, -0.0029474346, -0.274524, -0.09142805, 0.0132142445, 0.1577639) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.02177336, -0.020817943, -0.0111796055, -0.0046033757, 0.45033064, 0.3573757, 0.55279994, 0.602122, -0.05536106, -0.33642644, -0.1851379, -0.052192084, 0.03683446, 0.13613251, 0.20098919, -0.090587094) * go_3(0.0, -1.0);
|
||||
result += mat4(0.1520822, 0.37173554, -0.061298244, 0.0019386727, 0.44656134, 0.13406622, 0.39018136, 0.5722051, -0.13074401, 0.012778576, -0.2837446, 0.16098566, 0.100189455, -0.40386122, 0.17464107, -0.17862785) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.01217905, -0.24295084, 0.08192982, -0.14160301, -0.05936872, -0.003312342, -0.07542139, 0.13488367, -0.21560493, -0.14342502, -0.19195864, -0.09448305, -0.1038431, -0.075766176, 0.03226791, 0.06455397) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.076916575, -0.10891301, 0.032635316, 0.03848802, 0.15750243, 0.48169684, 0.5410635, 0.017279895, 0.012730932, -0.0059071835, 0.030766146, -0.0225503, -0.030178519, -0.05866621, 0.033593398, -0.00033098995) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.10757409, 0.2644168, -0.025696747, -0.0077012815, 0.31728277, 0.29771668, 0.2443613, -0.047722775, -0.083712585, -0.12742844, -0.3138776, -0.059888497, 0.12291351, -0.14435866, 0.051414594, -0.11889901) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.063888945, 0.002844068, -0.06129518, 0.03381495, 0.10176077, -0.11625004, -0.10745763, -0.20636752, -0.03820934, 0.01926402, -0.20310643, 0.09767577, -0.00776684, 0.13453315, -0.036967937, 0.09780335) * go_3(1.0, 1.0);
|
||||
result += vec4(0.019374544, -0.050425697, -0.005817216, -0.0059976326);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.028328063, 0.038015317, 0.14893384, 0.10103896, 0.028176744, -0.02067147, -0.10970998, 0.015726602, -0.07402682, -0.075281784, -0.012586929, 0.053476278, 0.14823362, 0.20312984, 0.24213, 0.039118115) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.009731573, -0.019011121, 0.016360838, -0.0073153526, 0.14594506, -0.0427664, -0.094225354, -0.013891855, -0.037061375, 0.024959227, -0.12289382, -0.21792257, -0.33579424, 0.052678566, 0.04346115, 0.07943186) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.0022269129, 0.013298362, -0.045071404, -0.007918287, 0.010860651, -0.073057, -0.0042394064, 0.03340809, 0.04938919, -0.024218693, -0.008147567, 0.08848061, -0.06840333, 0.10077341, -0.272586, -0.06542769) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.15929016, -0.1415167, 0.057084452, 0.06830724, 0.0046992986, 0.068573505, 0.22142749, -0.18493174, -0.1006019, -0.11373546, 0.17520057, -0.12888812, 0.05176946, -0.14703397, -0.20610721, 0.16611591) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.0069309813, 0.22358349, -0.18569049, 0.13456121, -0.21528137, 0.04618922, -0.47261322, -0.09682613, 0.5402922, 0.15818685, 0.05288464, -0.09949312, 0.21833964, 0.06652228, -0.2694682, 0.58216536) * go_0(0.0, 0.0);
|
||||
result += mat4(0.040808782, 0.023110595, 0.12678777, -0.09057271, 0.03159572, 0.044006016, -0.10090222, 0.09940838, -0.08454473, -0.118349984, -0.053009644, 0.24352531, -0.103818566, 0.12536442, -0.17832974, 0.25161982) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.026323501, -0.14911288, -0.0073903934, 0.06902844, 0.07188603, -0.05006621, 0.06539817, -0.048083752, -0.08032579, -0.07449341, -0.015944218, 0.032426495, 0.069349505, -0.07441237, 0.055614363, 0.065174624) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.046432327, -0.051616143, 0.017791865, -0.047294978, 0.025944458, -0.0020909954, 0.083794415, -0.055740435, -0.3720184, 0.06654654, 0.1944378, 0.07806658, 0.00870193, 0.005404396, -0.059417505, -0.06270168) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.011699918, -0.03260685, 0.016413182, -0.02199741, -0.042898953, -0.018734168, -0.12387174, 0.06405199, -0.050764065, 0.07050078, 0.006969675, 0.05508108, -0.079687595, 0.12154926, 0.071177684, 0.046873443) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.2158498, 0.03612371, -0.05268691, -0.065594874, 0.06997431, -0.07327132, -0.03323361, -0.23306306, -0.00011140713, -0.1891967, -0.017328357, 0.15796778, -0.061359044, 0.008202449, -0.031317197, -0.020873578) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.022816254, -0.014594548, 0.0064240466, 0.07976367, -0.0070318123, -0.07651652, -0.111756384, -0.2788498, 0.16634429, -0.1583179, -0.10245271, 0.10480152, 0.345051, -0.07809675, 0.046080578, -0.32139245) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.020630263, 0.032152038, 0.0019161701, 0.05435833, 0.078139454, -0.10090956, 0.14244889, 0.017286595, 0.0039871824, -0.026395446, 0.14158171, 0.0010112645, 0.17055373, -0.08093189, -0.049234428, -0.33473247) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.10982378, 0.029386539, -0.15483, -0.04345961, -0.16869037, -0.30862433, 0.060743757, -0.032285906, 0.017884266, -0.09846199, -0.090971105, -0.1693697, -0.063690096, -0.08489718, 0.18247683, -0.19921213) * go_1(0.0, -1.0);
|
||||
result += mat4(0.1898742, 0.22187345, -0.28495324, -0.42578775, 0.12833633, -0.2251503, -0.025917793, 0.6011678, -0.36586264, 0.23302059, -0.072634645, 0.0064221635, 0.56792957, -0.4684677, 0.05015159, 0.30121225) * go_1(0.0, 0.0);
|
||||
result += mat4(0.10837159, 0.14743729, -0.03639783, -0.34797576, -0.18306817, -0.07957882, -0.111433275, 0.30104128, -0.102763996, -0.01020151, 0.016333267, -0.012390819, 0.11835027, -0.12597388, -0.006298998, 0.0513052) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.23662986, 0.23325302, -0.046104953, 0.36488137, 0.06990537, -0.06887873, -0.012611426, -0.02618366, -0.05296669, 0.195254, 0.016366778, 0.01693462, -0.08488424, -0.24656284, -0.035283253, -0.15318634) * go_1(1.0, -1.0);
|
||||
result += mat4(0.061704446, -0.26930714, -0.24598889, 0.27657726, 0.05046488, -0.341884, 0.10704377, -0.15971762, 0.072999336, -0.2005826, -0.05874223, -0.053938035, -0.08284583, -0.22792995, 0.1027033, -0.012932447) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.029079054, 0.14774945, 0.026151389, 0.12380946, 0.08926635, -0.08387116, -0.17018612, -0.09304499, 0.086990625, -0.27579373, 0.003823722, -0.024723161, 0.08762848, -0.10080674, -0.012214886, -0.30239874) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.25756493, 0.2537789, 0.21723714, 0.0017929028, -0.014724892, 0.086692676, 0.11934202, -0.025869334, 0.008618976, -0.0046638376, -0.06863114, -0.07598151, -0.17309345, 0.009138105, -0.099874064, 0.07377463) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.39971545, 0.16774859, 0.13102596, 0.30735064, -0.060374007, -0.036933452, 0.14408773, 0.06479284, 0.03806265, 0.045560133, 0.043136165, -0.019244662, 0.17573427, -0.11398941, -0.0751098, 0.041702736) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.074492976, 0.18349282, -0.009050458, 0.0869807, -0.23123743, -0.015426683, -0.14346392, 0.005445149, -0.05322614, 0.10287576, 0.16083732, -0.09557319, -0.13891783, -0.13752605, -0.023572346, 0.13608918) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.31140685, 0.40130782, 0.07704675, 0.27509958, 0.09711739, -0.18293281, -0.14500841, -0.15334702, 0.098314695, 0.22749798, 0.006017282, -0.013669673, 0.07147038, 0.022289474, -0.036797456, -0.0013958871) * go_2(0.0, -1.0);
|
||||
result += mat4(0.0547557, -0.03036202, 0.65113044, 0.10668893, 0.304707, -0.1456157, 0.27668485, 0.2279428, -0.42439902, -0.0073047588, 0.045635667, 0.271637, -0.19595222, -0.28107607, 0.3905438, -0.29898256) * go_2(0.0, 0.0);
|
||||
result += mat4(0.076843366, 0.037181348, 0.08652873, 0.1756985, 0.03728033, -0.22783624, 0.16810594, -0.022009399, 0.16058537, 0.24559903, 0.05266939, -0.13929726, 0.15964857, 0.0013167082, 0.015017631, 0.101646364) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.3022452, 0.20052882, 0.13433233, 0.04250016, -0.15248592, 0.014216527, -0.23489903, 0.13919333, 0.22891816, -0.0053335144, -0.05567782, -0.12769286, -0.05337762, -0.11429989, -0.00882089, -0.030790573) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.11763547, 0.1073185, 0.15810886, 0.013149736, -0.028268294, -0.24712053, 0.08592036, 0.075742744, 0.19626461, -0.10880887, -0.22599675, -0.37207767, -0.032548983, -0.011045266, -0.035218395, 0.099996395) * go_2(1.0, 0.0);
|
||||
result += mat4(0.05631665, 0.029538663, 0.043909863, 0.13720988, 0.10980592, -0.047748722, 0.080308706, -0.06828442, 0.1144396, -0.12510885, -0.067976676, 0.030742755, 0.07134681, -0.06652312, -0.0642328, -0.034490924) * go_2(1.0, 1.0);
|
||||
result += mat4(0.019588284, -0.15197967, -0.16797094, -0.026324488, 0.014429439, -0.028491383, 0.059453625, 0.23443304, 0.02504347, 0.08872467, 0.032782357, -0.085310735, 0.013040259, -0.09837991, 0.073533125, -0.03544458) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.02198588, -0.09614766, 0.024655875, 0.025384603, 0.012162857, 0.065071434, 0.018112874, 0.19828922, -0.33289856, 0.011323505, 0.13696423, 0.31772846, -0.06587399, -0.05569957, -0.16469179, -0.22545892) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.009093827, 0.086783886, 0.060070645, 0.049957857, 0.041628215, 0.082412794, 0.117729135, -0.178277, 0.08326062, -0.07120824, 0.1788718, 0.050748438, -0.08952197, -0.14609487, 0.05515471, 0.14784457) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.10823147, -0.05108019, 0.092807196, -0.13899301, 0.19123949, -0.044189975, 0.0030145745, 0.08935499, -0.10338727, 0.01996205, 0.15671325, -0.08229972, 0.05603653, 0.043324884, 0.13562247, -0.11487494) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.18872134, -0.07302765, 0.030137405, 0.30928415, -0.07689583, 0.045998566, 0.45554903, -0.1653404, 0.14705873, -0.10649596, 0.46833125, 0.17608039, -0.43967086, 0.056812476, -0.17908083, -0.40455228) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.08093384, 0.032636635, 0.124594346, 0.13655491, 0.16780408, -1.4671803e-05, 0.13044862, -0.397665, -0.013273644, 0.08253894, 0.16302188, -0.052874118, 0.04073075, -0.18063635, -0.00838661, -0.31084144) * go_3(0.0, 1.0);
|
||||
result += mat4(0.06804371, -0.14755388, -0.12055216, -0.00437858, -0.044694718, 0.22744909, 0.012434794, 0.06245207, 0.00560859, -0.15815294, -0.19711316, 0.07711764, 0.03078979, -0.09560189, 0.10509056, 0.010651465) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.026342146, 0.13919179, -0.0030414977, 0.06607403, 0.071292974, 0.065464914, -0.027091878, 0.10620255, -0.052090824, 0.06840278, -0.08457357, 0.08867469, 0.2976581, -0.6702739, -0.15472057, -0.3066263) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.00072869845, 0.046573937, -0.08363707, 0.07867379, 0.038065, 0.01228845, 0.031746328, -0.024448024, -0.065555945, 0.1220454, 0.032151606, -0.022336006, -0.0010816467, -0.026455112, 0.112422734, -0.10285581) * go_3(1.0, 1.0);
|
||||
result += vec4(0.052450567, 0.10404023, -0.059578225, 0.009724121);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!SAVE conv2d_3_tf1
|
||||
//!WIDTH conv2d_2_tf.w
|
||||
//!HEIGHT conv2d_2_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_2_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_2_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.037506457, -0.06573841, -0.087879084, -0.06359248, -0.0017873603, -0.009097742, 0.010108622, 0.026364084, 0.012306545, 0.12607974, -0.088268295, 0.14034338, 0.24951904, 0.0983314, 0.03635719, -0.047059253) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.05570699, 0.11044774, 0.04827364, -0.03185735, -0.032498132, -0.062959515, 0.2933071, 0.22244357, 0.061075654, 0.0064111133, 0.011452209, 0.11576761, 0.13969804, 0.20502032, 0.1114938, 0.022496287) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.054194342, 0.000389916, -0.039589155, -0.018707246, -0.036095835, -0.06873059, -0.077109694, 0.028726012, -0.08820959, -0.109247595, -0.05745309, 0.043230128, 0.033671502, 0.16398554, 0.030398889, -0.17000203) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.09218165, -0.12813722, -0.040984686, -0.016605416, 0.054269493, 0.12971285, -0.013961638, -0.17803082, -0.014683587, 0.2502267, -0.14249405, -0.025687713, -0.097426265, -0.30111355, -0.21776466, 0.008809217) * go_0(0.0, -1.0);
|
||||
result += mat4(0.21033873, 0.15221386, 0.18138756, -0.08248389, -0.10091519, -0.06940753, -0.014009188, -0.3009861, -0.02452202, -0.08800422, -0.36376888, 0.18485394, 0.35076657, -0.13293292, 0.24624826, 0.39373755) * go_0(0.0, 0.0);
|
||||
result += mat4(0.014170062, -0.029623963, 0.057001226, 0.09269898, -0.14630881, -0.16557585, 0.06735037, -0.015008042, -0.27238864, 0.081130914, -0.07869508, 0.098087415, 0.11217335, 0.48223323, 0.18613088, -0.035602476) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.21623239, -0.1125095, -0.09964635, 0.101452544, 0.11877652, 0.13471957, -0.10402355, 0.0077938605, 0.030518647, 0.22309083, -0.2115206, 0.017967062, -0.042780407, 0.099759325, -0.10465051, -0.033807248) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.059608232, 0.06684556, 0.00039066386, 0.08542961, 0.097183906, -0.1868667, 0.07778909, -0.06172202, 0.0021662437, -0.05387577, -0.4077133, -0.028940776, 0.110816136, -0.04154161, 0.030078325, 0.072834246) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.01881586, -0.06384429, -0.054874837, -0.016731417, -0.06570834, -0.13579571, 0.0033891131, -0.059161015, -0.11559389, 0.02149361, -0.08791608, -0.008113861, 0.08313892, -0.07327947, -0.013473171, 0.13254371) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.11458958, -0.08827364, -0.025030116, 0.12626298, 0.0070429775, 0.0337767, 0.051719055, -0.09654129, -0.04867615, -0.03609001, -0.06522421, -0.044131942, -0.048825134, 0.10652733, -0.015310965, -0.07341175) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.05782829, 0.014247012, 0.12126171, 0.100055166, 0.24079333, -0.20155986, 0.1640186, -0.12158374, -0.153708, -0.24445893, -0.10536192, 0.12758626, -0.19430119, -0.019024884, -0.080120996, -0.29866305) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.017357074, 0.04390695, 0.12889594, 0.11451521, 0.03333342, -0.16417275, 0.10196121, 0.13059081, 0.09948873, 0.15007107, 0.22664218, 0.35449567, -0.089776486, 0.025239054, 0.12463201, -0.13109131) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.064875744, 0.40551752, 0.11903257, 0.14822967, 0.14993542, -0.12758526, 0.23159283, -0.06080246, -0.084577255, 0.14307548, -0.02186462, 0.05793564, -0.050965074, 0.23895216, -0.07796932, -0.1624384) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.15942748, 0.07191155, 0.42204422, 0.35219797, 0.23286703, -0.283381, -0.2749432, 0.25922084, 0.10494953, 0.14575887, -0.19649154, -0.14563714, -0.03709703, 0.023375817, -0.05610175, -0.32548484) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.04872624, -0.3592348, -0.027413938, 0.0836858, 0.046842758, -0.35193914, 0.06154142, 0.05559191, -0.22538327, -0.097689696, -0.21317257, -0.033945527, -0.23628096, -0.016477302, 0.027297588, -0.04105733) * go_1(0.0, 1.0);
|
||||
result += mat4(0.11543502, -0.043297376, 0.118703, 0.15013209, 0.03191795, 0.014122794, 0.05156918, 0.023102578, 0.0808462, -0.06445798, 0.15860644, -0.062393136, -0.018691704, -0.00032888897, 0.01196705, -0.025045555) * go_1(1.0, -1.0);
|
||||
result += mat4(0.08301664, 0.12298539, 0.20151077, 0.2993159, 0.16968682, -0.18196446, -0.13322797, -0.13693243, -0.0048389523, -0.057406515, 0.21409932, -0.060822334, -0.08554752, -0.19363636, -0.35241908, -0.32256603) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.0523748, 0.17082025, 0.08556144, 0.19181536, -0.2445756, -0.3616732, -0.01641404, -0.078599006, 0.23907976, 0.025989126, 0.07574993, -0.06859337, -0.06667767, -0.022847861, -0.037942342, -0.21112117) * go_1(1.0, 1.0);
|
||||
result += mat4(0.15098672, 0.024212115, -0.19068481, -0.22606348, -0.15221487, -0.032165635, -0.06244531, -0.043535717, -0.07398802, -0.06088507, -0.013834592, -0.10145823, 0.06901983, -0.0862135, -0.05545454, 0.15514566) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.044767097, -0.07583697, -0.17739761, -0.25538698, 0.0966659, -0.0013492911, -0.23315248, -0.21652249, -0.14381947, 0.017784966, -0.15960035, -0.13297895, 0.009810349, -0.041348267, 0.05443229, 0.17781278) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.0052824756, 0.087268956, -0.022167318, -0.09450279, 0.1254372, 0.075806946, 0.028893303, -0.09019378, 0.03488572, 0.046265777, 0.026162563, 0.003914548, -0.0632334, -0.19494742, -0.03602023, 0.113897055) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.11311528, 0.2616239, 0.12303548, 0.13427438, -0.26537886, 0.015112677, -0.03641703, -0.014114427, -0.023280613, 0.03626403, 0.12833157, 0.19168468, 0.2119137, -0.02374797, 0.117919676, 0.07794395) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.13746078, 0.25739196, 0.008431936, -0.053867325, -0.13228695, -0.20661803, 0.026474724, 0.3205188, -0.41819036, 0.42812085, 0.17249924, -0.15810613, 0.39602605, -0.10873597, 0.1457145, -0.060503867) * go_2(0.0, 0.0);
|
||||
result += mat4(0.03706167, -0.036211733, 0.06519942, -0.2123978, 0.019934088, 0.17494182, -0.017252771, -0.067341134, -0.15416612, -0.114118524, -0.00028491023, -0.08172238, -0.11722721, -0.2647645, 0.13316637, 0.13562322) * go_2(0.0, 1.0);
|
||||
result += mat4(0.11832847, 0.22822993, 0.020318847, 0.0734738, -0.025950216, -0.072782144, 0.11133989, 0.18845533, -0.004584898, -0.10486471, 0.054522812, -0.14136603, 0.01940983, -0.039433163, 0.008390286, 0.013686628) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.042335663, 0.0035399816, -0.1813205, -0.25639042, 0.1042524, 0.07707001, -0.04922454, 0.18140413, -0.22322963, 0.030809738, -0.11041754, -0.040288754, 0.09431559, -0.08017892, -0.18317147, -0.019331435) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.061776266, 0.0069793356, 0.019964112, -0.14504445, -0.00070097746, -0.027107855, 0.030182542, -0.05625612, -0.04958449, 0.123165295, 0.0013953283, 0.017912487, 0.031161329, -0.31798717, 0.018331604, 0.030411277) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.0530594, -0.07933117, 0.024755973, 0.004785411, 0.045512546, 0.12833083, 0.023195961, -0.018028054, 0.014223835, 0.102213494, 0.052169293, -0.020509718, 0.017905682, 0.021354724, -0.0410789, -0.066523656) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.017061293, -0.08770806, -0.04889939, 0.01825556, -0.03228951, -0.06838898, -0.09249373, 0.18103507, 0.087000825, 0.04175679, -0.09305919, -0.2792485, 0.03405797, 0.062147446, -0.04757652, -0.021603985) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.04115162, 0.02547615, 0.07033616, 0.09814065, 0.2597489, -0.0335038, 0.14097647, 0.047022782, 0.1374654, -0.27390274, 0.02080897, -0.15251215, -0.025431091, 0.08871465, -0.22243279, -0.07792812) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.061674852, -0.051326606, -0.04885301, 0.08548189, -0.07100394, 0.044875987, -0.19810183, -0.09841128, -0.06628199, -0.041564234, 0.1111919, -0.044448826, 0.06980301, 0.00046094303, -0.045978926, -0.20736355) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.18405268, -0.28115878, -0.33536536, 0.0753763, 0.028309148, 0.0014874876, 0.28369543, -0.2133985, 0.16520546, 0.29562506, 0.109781906, 0.028433772, -0.02691105, -0.39038795, -0.12942268, -0.080103286) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.05387814, -0.04672615, 0.046064686, 0.2791977, 0.11359623, -0.204098, -0.018091407, 0.13550591, 0.04216003, -0.1631328, -0.043013666, -0.045698896, 0.032403514, 0.010206319, -0.25789943, -0.36328712) * go_3(0.0, 1.0);
|
||||
result += mat4(0.11280466, 0.11671405, -0.02122692, 0.021664057, -0.07836575, 0.014747725, 0.030007286, -0.10128616, -0.13695373, -0.10353946, -0.043571353, 0.05922437, -0.11293257, 0.0828006, -0.07322761, -0.08197273) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.0010509897, -0.1674067, 0.08191839, 0.056608744, 0.061343428, 0.19574693, 0.05302967, -0.006813754, -0.016064182, 0.22949885, -0.06631832, 0.034382205, 0.12674272, 0.06583508, 0.19319807, 0.011400221) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.032175347, -0.021227444, -0.027698517, 0.067299634, 0.23929007, 0.20669897, 0.004856941, 0.0009404045, 0.04919408, 0.020296812, 0.012571405, -0.16185577, -0.012276781, 0.16609742, -0.15718406, -0.20344186) * go_3(1.0, 1.0);
|
||||
result += vec4(0.022815697, 0.012251767, 0.045309987, -0.0879881);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.010501252, -0.046741538, -0.0017120431, -0.04840009, 0.20547974, 0.3366821, -0.10182207, 0.17451541, -0.03404171, -0.15138055, 0.16771653, -0.07168161, 0.102572344, 0.08266354, 0.20205829, 0.13429944) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.05584234, 0.06844309, 0.025430907, 0.124140054, 0.36385667, 0.12099467, -0.41671994, 0.085477844, 0.19748127, -0.21473993, 0.005037813, -0.3973761, 0.04669592, -0.100342326, -0.09403772, -0.034248166) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.17654696, 0.009085064, 0.028360577, 0.033909567, 0.09377573, 0.27896938, 0.103994116, 0.0008595595, 0.064523555, 0.040994007, -0.06337235, 0.05662917, 0.0037455747, 0.017608117, -0.14610702, 1.2175746e-05) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.04631749, -0.14251712, -0.16420849, -0.16259338, 0.46187812, 0.17576592, 0.00049142196, 0.029193122, -0.003925961, -0.11218227, 0.007026237, -0.20583045, -0.0010964901, 0.19355829, 0.2221649, 0.1187224) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.041567978, -0.31510913, 0.01618704, 0.04979329, 0.101294376, 0.16356954, 0.21361789, 0.20735294, 0.1900854, -0.4151726, -0.30471593, -0.59483325, 0.033624128, 0.11495109, -0.15194787, 0.4920959) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.18910064, -0.06516878, -0.20508374, -0.063928686, 0.7289614, 0.26674315, 0.2929481, 0.4026098, -0.033123735, -0.090371035, -0.029094126, -0.15197921, -0.08723726, -0.060160585, -0.07908409, -0.08826931) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.08321312, -0.09749648, -0.08783197, -0.23072585, 0.24343425, 0.10888949, 0.17419606, 0.04136083, 0.0066000987, -0.06112787, -0.12176007, -0.20907228, -0.0008522778, -0.054704696, -0.07197735, -0.0877179) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.40559706, -0.3801705, 0.05970925, -0.6157092, 0.28944594, 0.1252121, 0.403247, -0.122819394, -0.096336536, -0.2324694, 0.05980106, -0.19970767, -0.16646989, -0.10164633, -0.09282806, -0.08897996) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.14336498, -0.12967408, -0.016268672, -0.021431219, -0.0850116, 0.37105832, -0.04093888, 0.08540873, 0.035717323, -0.07282701, -0.009123291, -0.0036565473, -0.02508944, -0.087611906, 0.03604423, -0.00089080486) * go_0(1.0, 1.0);
|
||||
result += mat4(0.1373875, 0.05283984, -0.11992707, 0.102294855, 0.3305128, 0.044920854, 0.31622922, -0.04711731, 0.001336024, 0.022799017, -0.062343203, 0.017140022, -0.07556853, -0.12864219, -0.25721326, -0.20741239) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.22062224, 0.09266222, 0.22466063, 0.18527372, -0.06940306, 0.1317168, 0.019784274, -0.07422301, 0.04061616, 0.0022494853, 0.21723995, 0.24732308, 0.14088804, 0.0116154915, 0.102064446, 0.020701224) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.025154127, 0.045180723, -0.05877639, -0.099235624, 0.13630918, 0.24653725, -0.05723323, -0.022995364, -0.10826078, 0.049667366, 0.12618053, 0.1557369, 0.037487056, -0.22215757, 0.005912914, -0.20549043) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.09641055, 0.098845296, -0.08192096, -0.03691394, -0.18450394, 0.29955688, -0.082493715, -0.06268039, -0.0754319, 0.21018648, -0.016580105, -0.1810546, 0.13857666, -0.0327626, 0.03161804, -0.32589525) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.18272439, -0.17595461, 0.047229152, 0.14596708, 0.40453747, 0.5658558, -0.17969102, 0.21557859, -0.34232348, 0.40355968, 0.53874254, 0.0012561383, 0.28154096, -0.06745097, -0.13049632, 0.42997465) * go_1(0.0, 0.0);
|
||||
result += mat4(0.081179485, -0.0041369614, -0.12001932, -0.102107175, -0.050293338, 0.29165673, 0.08062538, 0.22925815, 0.19389379, 0.28463286, -0.057207666, 0.23133168, -0.07545728, 0.06729763, -0.103593476, 0.014468794) * go_1(0.0, 1.0);
|
||||
result += mat4(0.069821335, -0.010299579, 0.069458775, 0.03894593, -0.054688405, 0.32758355, 0.13935772, 0.37506017, 0.24083133, -0.06105339, 0.25636867, 0.09627044, 0.08939188, 0.006728639, 0.10629504, 0.07887502) * go_1(1.0, -1.0);
|
||||
result += mat4(0.10563019, 0.077379815, 0.045456886, 0.09303406, 0.11326298, 0.28762257, -0.35142374, 0.10285745, 0.28762287, 0.3592446, 0.23816557, 0.22676824, 0.030372012, -0.028023086, -0.30956736, -0.27588373) * go_1(1.0, 0.0);
|
||||
result += mat4(0.110499, 0.009828844, 0.086689755, 0.1839749, 0.16656482, 0.083707325, 0.19506347, -0.01547141, 0.13804145, 0.2206598, -0.16484791, -0.0021595939, -0.06844408, -0.07861768, 0.040771082, -0.13347322) * go_1(1.0, 1.0);
|
||||
result += mat4(0.02667995, 0.019265587, -0.18211095, -0.102116466, -0.042541366, -0.07700912, -0.020587347, -0.03532171, 0.14816427, -0.1672272, -0.17522137, -0.04657808, 0.013430233, -0.0021270285, 0.109880306, 0.004838907) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.14285165, -0.1364756, 0.017568532, -0.27690783, -0.015461915, 0.045437083, 0.018187419, 0.12473493, 0.17991658, -0.15642665, 0.10009151, -0.19040193, 0.1734127, -0.13817501, 0.0710856, -0.12921426) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.14114712, -0.18893671, 0.16121174, 0.035988737, 0.17872387, -0.106395856, -0.23183517, 0.012380416, 0.043066982, -0.28539032, -0.049011275, -0.21125022, -0.11976977, -0.015564958, 0.18880925, -0.0034812456) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.05894521, 0.17266215, -0.0458901, 0.08049924, 0.0156061025, -0.0047465423, 0.09714626, 0.045990974, -0.08786066, -0.37803304, -0.19629405, -0.08546443, 0.014874948, 0.16931784, 0.24799919, 0.06316819) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.28352743, 0.29973608, -0.014540065, 0.2865005, 0.048086923, 0.18976144, 0.22969759, 0.1643124, -0.11259408, -0.107592925, 0.184308, 0.30998367, -1.0860825, -0.29118305, -0.51242536, -0.38492215) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.17199941, -0.14274743, -0.14213641, -0.1691383, -0.17294803, -0.013992068, -0.12135059, 0.082377024, -0.11255549, -0.124990575, -0.32526177, -0.08199375, -0.25591666, 0.1882329, 0.07895415, 0.22012262) * go_2(0.0, 1.0);
|
||||
result += mat4(0.026025832, -0.07267515, 0.09738688, 0.074536435, -0.060470507, -0.037861936, 0.0507819, -0.054857653, 0.0043173633, -0.18107842, -0.02996759, 0.04072402, -0.012617744, 0.061665237, 0.0013981885, 0.08679919) * go_2(1.0, -1.0);
|
||||
result += mat4(0.27913737, 0.39656082, 0.1579819, 0.2774727, -0.007996453, 0.08704765, -0.016933938, 0.07066135, 0.12361742, -0.20802726, -0.13705719, -0.18794124, 0.037409827, -0.03351758, -0.2970392, -0.11001984) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.027419567, 0.043236237, -0.19843115, -0.056489736, -0.017010912, 0.070949584, -0.14881176, -0.0780235, 0.0039477753, -0.16772608, -0.009547604, -0.14060417, 0.0103197545, 0.07129672, 0.034949142, 0.014112084) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.06467971, 0.084101565, 0.26296136, 0.08878442, -0.11232121, -0.054373942, -0.17263442, 0.046408508, 0.032239515, 0.042490713, 0.036938053, -0.034339923, -0.07139367, 0.032505415, 0.0045828503, 0.24428385) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.053585388, -0.08175568, -0.04787236, 0.06061965, -0.0740297, 0.11113596, -0.12467945, 0.08229154, -0.01941305, 0.12903687, 0.09095716, -0.13062255, -0.0102068605, 0.107291475, 0.030279635, 0.07464777) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.11041978, -0.0123585425, 0.11147018, 0.07380536, 0.06632908, 0.011784447, 0.029638765, -0.01566135, 0.009105331, 0.05252663, -0.17972581, 0.01210126, -0.10749957, -0.028144639, -0.105761215, 0.083784826) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.058018316, 0.15083058, 0.2725673, 0.024263225, -0.067711554, 0.051117413, -0.31144425, -0.15761986, 0.017503206, -0.14361219, -0.38261738, -0.20354146, -0.04211545, 0.12921454, -0.01319619, 0.35809723) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.107978396, 0.3230084, -0.13806303, 0.12903036, 0.039864987, -0.006241628, 0.18701774, -0.10785807, 0.30056882, -0.3092082, -0.4273322, 0.3784662, -0.026107281, 0.23165871, 0.35258314, -0.06654702) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.15840323, 0.15210885, 0.04086692, 0.19169305, 0.11847602, 0.0009038581, 0.095951624, 0.043941673, 0.1512248, 0.0749449, -0.027045414, -0.19729601, 0.08265063, -0.045218006, -0.10732461, 0.05197371) * go_3(0.0, 1.0);
|
||||
result += mat4(0.13637526, 0.28841978, 0.10298119, -0.005948496, 0.020897362, -0.02186902, -0.16207378, -0.021084815, 0.029192554, 0.07076991, -0.07210881, -0.06752328, 0.0006557475, 0.08986717, -0.29430988, 0.21411087) * go_3(1.0, -1.0);
|
||||
result += mat4(0.18667863, 0.3117322, -0.0859705, -0.038189936, 0.10214859, -0.11244034, 0.2680223, -0.072901204, -0.07434324, -0.17855306, 0.23134363, -0.055360887, -0.020968167, 0.0858459, 0.078975916, 0.13254759) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.15676941, 0.03476677, -0.09922334, -0.15847856, -0.0033982224, 0.020932984, 0.12874377, 0.048792202, 0.06521213, 0.12456798, 0.15958112, 0.15981804, 0.07657683, 0.1759313, 0.012727211, 0.120304115) * go_3(1.0, 1.0);
|
||||
result += vec4(0.08911729, -0.027969634, -0.010653148, -0.08001697);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!SAVE conv2d_4_tf1
|
||||
//!WIDTH conv2d_3_tf.w
|
||||
//!HEIGHT conv2d_3_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_3_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_3_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.003206617, 0.04896987, 0.049652386, 0.10869342, 0.36313584, -0.070666805, 0.93581825, -0.52484274, -0.14278883, 0.064016834, -0.05534331, 0.02961736, -0.1319316, 0.05740655, 0.2405951, -0.12313382) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.014092832, 0.07058761, -0.07887866, -0.27478936, -0.31456405, -0.31036922, -0.18380909, -0.11277979, -0.034889866, -0.37914017, -0.056245584, 0.24008954, -0.03414483, -0.023189066, -0.010568316, -0.004604883) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.15443979, -0.050161768, -0.012300917, -0.08834887, 0.082193285, 0.06878423, 0.1478042, -0.3774468, -0.18659878, 0.14238152, 0.033605397, 0.13560006, -0.032682173, -0.024561955, 0.05656941, -0.034246165) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.04691462, 0.064624496, -0.15950382, 0.16081297, -0.1417951, -0.109690994, -0.021205869, 0.19361454, -0.006306647, 0.3401972, -0.00014070333, 0.11619607, -0.13437814, 0.05464789, 0.37712076, -0.12470751) * go_0(0.0, -1.0);
|
||||
result += mat4(-0.40016884, 0.010666597, -0.005395378, 0.51084363, -0.009875391, 0.3969395, 0.47768033, -0.3392299, -0.1509509, -0.057620626, -0.1834601, -0.09998148, 0.10095897, -0.2213528, 0.02546703, -0.28506726) * go_0(0.0, 0.0);
|
||||
result += mat4(0.26652217, -0.106772706, -0.12609608, -0.0949661, -0.10869194, -0.55331933, -0.011515521, -0.27978876, -0.2124893, 0.03954004, 0.1691768, 0.05590268, 0.1539662, 0.10703386, -0.027286088, 0.2168544) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.04862511, 0.06919758, -0.12962708, 0.016036907, -0.030030789, -0.20159967, 0.0013158675, -0.07799172, -0.032236706, -0.0035921712, -0.085437834, -0.025374755, -0.06251374, -0.009269627, -0.07519051, -0.01884611) * go_0(1.0, -1.0);
|
||||
result += mat4(0.23940067, -0.19496065, -0.05494683, 0.11601073, -0.074225076, 0.24976431, 0.41665986, 0.12029472, 0.16815041, -0.115868434, 0.06333614, 0.032145746, 0.15990137, -0.14886795, 0.034102913, -0.07727595) * go_0(1.0, 0.0);
|
||||
result += mat4(0.14702639, -0.013711502, 0.011437429, -0.11201445, -0.2582659, 0.34539905, 0.058082145, -0.18346462, 0.0027891365, 0.072565466, 0.12716974, 0.050636146, 0.092657596, 0.08541754, -0.1266164, 0.027881607) * go_0(1.0, 1.0);
|
||||
result += mat4(0.043362036, 0.020758621, 0.09906072, -0.22401148, -0.19104514, -0.25774476, 0.074128486, 0.08558291, -0.075419895, 0.20380639, 0.06398196, 0.015925938, 0.089786015, -0.100721814, -0.1374862, 0.26110905) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.12547149, 0.08151811, -0.15953775, -0.33995447, -0.50784314, 0.46155545, 0.24986996, 0.03404644, -0.047789436, -0.12438347, -0.14143273, -0.17951359, -0.08057819, 0.023863006, -0.008539273, -0.06775414) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.1430169, 0.056971863, -0.021576611, -0.045342956, -0.22356391, -0.15344621, -0.0467977, -0.22970036, -0.0125351725, 0.16957329, -0.0069183917, -0.013949834, -0.048609708, 0.05261722, 0.023262242, 0.2123519) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.019523792, 0.008228363, -0.04616012, -0.14341992, -0.19307113, 0.005937241, 0.24048887, -0.04279845, 0.022574252, 0.15558265, -0.035000063, 0.18318397, -0.05392528, -0.26044658, -0.13493988, 0.056433514) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.28926027, -0.17381874, 0.07685766, -0.0061521684, -0.47455552, -0.49213487, 0.36924496, 0.29042044, 0.201094, -0.14280887, -0.4531411, -0.52902204, -0.28123, 0.1401882, 0.32054895, -0.11357518) * go_1(0.0, 0.0);
|
||||
result += mat4(0.14173324, -0.12069898, -0.07242415, 0.105665006, 0.017373435, -0.056042343, 0.07270201, 0.022111928, -0.01106541, 0.01666006, 0.013564169, -0.36628693, -0.25450787, -0.28179473, -0.04721874, -0.21912882) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.09464695, -0.027919646, 0.13088459, 0.17504032, -0.101641014, 0.29687008, 0.08832321, 0.020538324, -0.15108941, -0.21930224, -0.026915176, -0.07078217, 0.10723033, 0.034364715, 0.18183397, -0.119012214) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.21713468, -0.0846604, 0.046551514, -0.14989382, 0.08672032, -0.07933831, 0.08093595, -0.064147756, -0.15980323, 0.50000644, -0.091568656, 0.03201994, -0.1848647, -0.0646309, 0.03288009, 0.046442386) * go_1(1.0, 0.0);
|
||||
result += mat4(0.053532355, -0.054523747, -0.040242642, -0.31438905, 0.06452703, -0.18785381, -0.14987698, -0.067642935, -0.19892459, -0.057256676, 0.05943023, -0.17331842, 0.02588534, 0.13134238, -0.07121775, 0.23446162) * go_1(1.0, 1.0);
|
||||
result += mat4(0.20633182, 0.01686198, 0.17934167, -0.02063493, 0.042606052, -0.05289458, 0.031508356, 0.00082803797, 0.0756423, -0.047548845, 0.01456339, 0.15910533, -0.20119642, 0.029213727, 0.111036316, -0.047010012) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.09258436, -0.27904224, -0.086695746, 0.33095327, -0.20126075, -0.050745636, -0.048944805, -0.10536587, -0.012995092, 0.07926994, 0.15071853, -0.13644052, -0.05188447, -0.06750699, -0.14227037, 0.028751127) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.18562223, 0.10250865, -0.17573993, 0.20434102, -0.05187468, -0.06441594, -0.052127104, -0.01925564, 0.02927959, -0.12711872, 0.059629507, 0.15696885, -0.010168965, 0.09971862, -0.03177664, -0.022744441) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.21474063, -0.15679085, 0.09609374, 0.109079376, -0.049934637, -0.07393633, 0.16688468, -0.018888129, 0.04240162, -0.31895876, -0.106516436, 0.20008606, -0.054410245, 0.028970616, -0.18008347, -0.013362003) * go_2(0.0, -1.0);
|
||||
result += mat4(0.37891293, 0.042730846, -0.24735828, -0.5234527, -0.3681344, -0.06609157, -0.14993733, -0.020316398, 0.123008475, 0.29632482, 0.32149333, 0.35999274, -0.18967044, 0.46154186, -0.016041815, 0.097378336) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.14873263, 0.07600569, -0.051758345, 0.1803135, -0.23121934, 0.13574593, 0.043973465, -0.13992754, -0.061972607, -0.124083005, -0.049196843, -0.07700431, 0.21572952, -0.25241727, 0.1218322, -0.07773728) * go_2(0.0, 1.0);
|
||||
result += mat4(0.040287063, 0.024240922, 0.021917762, -0.050616946, -0.023174169, 0.05977014, 0.018892275, 0.04014965, 0.11715485, 0.062129, 0.024620812, 0.013617107, 0.075699426, 0.1858111, -0.11769179, -0.08085602) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.3194255, 0.08695645, -0.09453595, 0.2564516, 0.02192303, 0.08167247, -0.06257352, 0.043801844, 0.04392246, 0.2020571, 0.045180902, 0.18857521, 0.1835961, -0.043788187, -0.08768916, -0.14755538) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.22074097, 0.13768476, -0.16183749, 0.059949517, -0.011375954, 0.08581876, 0.004800447, 0.019403988, 0.014646056, 0.07363176, -0.058036458, 0.0706421, 0.08082624, 0.17740329, -0.05484784, 0.050796065) * go_2(1.0, 1.0);
|
||||
result += mat4(-0.032330472, -0.067666024, 0.18980837, -0.19077848, 0.1111905, 0.03855666, -0.11272314, -0.00577739, 0.17697452, -0.053044144, -0.07510145, 0.061853852, -0.024240626, 0.14846492, 0.14804313, -0.20275854) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.17133904, -0.16356844, 0.1978664, 0.13877816, 0.28208038, 0.031539194, 0.11313891, -0.0014802719, 0.0033749861, 0.046372313, 0.054808807, -0.0024151779, 0.0068782056, -0.16414621, -0.07545907, -0.2521294) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.1746992, -0.037628956, -0.0044012754, -0.004390821, 0.0050341445, -0.112742625, 0.051241755, 0.01984483, 0.0003531837, 0.043500375, 0.030881992, 0.003503799, 0.13611782, -0.02509031, -0.007503557, -0.009321301) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.087250136, 0.12374122, 0.2959519, 0.11314702, 0.22080182, 0.106726184, -0.29768205, 0.14931595, 0.23356548, -0.008709153, -0.0797829, 0.046940215, -0.07027616, 0.20533602, 0.0723021, -0.1963585) * go_3(0.0, -1.0);
|
||||
result += mat4(0.00609982, 0.35277408, -0.22781096, -0.28912535, 0.42393112, -0.07654207, 0.12636793, 0.049337976, -0.0967726, -0.19349189, 0.36800626, 0.09745645, 0.47663373, 0.03876107, -0.042987954, 0.016161885) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.047490966, -0.05823166, 0.036158644, 0.025337253, -0.046618905, 0.108276576, -0.024148034, 0.0026794411, 0.1497962, -0.09328474, -0.03160641, 0.24351281, -0.05198027, 0.030720685, 0.00014528916, -0.2224931) * go_3(0.0, 1.0);
|
||||
result += mat4(-0.007338369, 0.18710312, 0.14617369, -0.0070655346, 0.10464997, -0.029674934, -0.11842202, -0.09114357, 0.08524458, -0.08082762, 0.06479597, -0.023760766, 0.07523641, 0.0067315935, 0.101266846, -0.2780903) * go_3(1.0, -1.0);
|
||||
result += mat4(0.14181875, -0.19523518, 0.1068169, -0.10284853, 0.11634046, -0.117397435, 0.09113022, 0.009371062, -0.022120507, -0.1127032, 0.092574745, -0.021989716, -0.088107705, -0.13541982, 0.08130504, -0.0678927) * go_3(1.0, 0.0);
|
||||
result += mat4(0.09948295, 0.23699793, -0.042369924, 0.16744529, -0.10045506, -0.045623623, 0.04871897, -0.0023967526, 0.02602692, -0.089873284, -0.050681606, -0.09332558, -0.09596149, -0.06988313, 0.0007193808, -0.11936899) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.04928105, -0.003357327, -0.03886671, 0.076106146);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.13425097, -0.23487093, 0.2480183, -0.2806276, -0.041303713, 0.100773126, -0.110890545, 0.036205858, -0.331331, -0.12929262, 0.16300063, 0.3776673, -0.20316373, -0.011239426, 0.10650887, -0.027857736) * go_0(-1.0, -1.0);
|
||||
result += mat4(0.09517376, -0.3004956, 0.05033304, -0.07464521, 0.009204248, -0.23034886, 0.30492118, -0.1215848, 0.15728685, -0.10430078, 0.04038878, 0.08034804, 0.04320418, -0.2929594, -0.018968396, 0.02542387) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.10651935, -0.2736715, 0.19267319, -0.033337504, -0.06697293, 0.028424729, 0.047814637, 0.44929537, 0.02565344, -0.253426, -0.040931404, -0.05018104, 0.032979824, -0.035349697, -0.039578713, -0.3116414) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.09176126, 0.031713437, 0.24861507, 0.31351718, 0.36284143, 0.3622709, 0.16165464, 0.07319267, -0.6303202, -0.21209712, -0.02169929, 0.037275597, -0.1295319, 0.033090707, -0.029330662, 0.054679472) * go_0(0.0, -1.0);
|
||||
result += mat4(0.15021572, -0.15177831, 0.1318225, 0.46864823, 0.059443284, 0.07404233, 0.22612074, 0.21105285, 0.319694, 0.09397257, 0.14277866, -0.0235649, -0.037205156, -0.40715128, -0.18572816, 0.058741573) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.122751735, -0.20926422, 0.2099333, -0.11627138, 0.04171681, 0.0669586, -0.03831368, 0.27334675, 0.0492008, 0.12854317, 0.03308622, 0.45236585, 0.03122829, 0.13853219, 0.05084764, -0.3965012) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.0019293908, -0.15562099, 0.12418126, 0.0045440597, 0.05442391, -0.15613738, 0.14828286, -0.17687118, -0.053517755, -0.33350968, -0.062314924, -0.31358472, -0.09670371, 0.043190923, 0.008150662, 0.09928506) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.06698031, -0.099411525, 0.24259582, -0.1073659, 0.06762824, 0.059605874, -0.20944163, -0.1598055, 0.32746908, -0.17759447, 0.2859796, -0.1274256, 0.30796206, -0.00791448, 0.114059694, 0.14775705) * go_0(1.0, 0.0);
|
||||
result += mat4(0.16291203, -0.14958477, 0.14716864, 0.2056065, -0.019337546, 0.032286238, 0.0030445335, -0.08208513, -0.14208078, 0.13601872, -0.23367858, -0.19092909, -0.20207883, -0.016950991, 0.009309007, 0.1376546) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.11093091, -0.32362202, -0.041845415, 0.029758021, -0.07261404, -0.048653398, 0.19167832, 0.09343212, 0.030472826, -0.15078579, -0.0056376588, 0.0045257527, -0.24521805, -0.10473077, 0.11163019, -0.1724187) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.08601668, 0.16612485, -0.07751539, 0.07261594, -0.19028407, 0.23896623, -0.10416726, 0.23500614, 0.1955228, 0.08699591, -0.049277775, 0.13447775, 0.19434914, -0.11481196, 0.088043146, 0.13352895) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.013221233, 0.07521129, 0.042819552, -0.11163175, 0.066080205, -0.25043094, -0.010348969, -0.013258202, 0.09444396, 0.29623637, 0.025016114, 0.050744686, -0.12219596, -0.0735393, -0.024817836, -0.06897588) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.25720942, 0.19861753, -0.18535058, 0.12190362, -0.33756095, -0.0038898317, 0.09739055, 0.41227046, -0.10030796, 0.025445882, -0.23542109, 0.08677691, 0.08140194, -0.22716106, 0.14016968, -0.0927231) * go_1(0.0, -1.0);
|
||||
result += mat4(0.58745646, -0.12533307, 0.30129984, 0.08898194, -0.07972344, -0.37581098, 0.06863413, -0.13185541, 0.21801205, 0.31779078, -0.3804784, -0.3200699, 0.14534226, 0.05912262, 0.07938948, -0.34869507) * go_1(0.0, 0.0);
|
||||
result += mat4(0.024675166, -0.067802526, 0.030065436, 0.06509131, 0.14367498, 0.022554757, 0.014991865, -0.029914752, 0.5123549, -0.012557206, -0.13014166, -0.34184244, -0.09080884, 0.13782553, -0.018931886, -0.35642785) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.37336427, -0.02705006, 0.14392053, 0.024049882, -0.024705589, 0.14556128, -0.12120506, -0.06275598, -0.1284325, 0.11409197, -0.08397436, -0.075944416, 0.056465942, 0.04016099, 0.096723564, -0.08359723) * go_1(1.0, -1.0);
|
||||
result += mat4(0.20243345, -0.09287934, -0.11676041, 0.005206654, -0.2879361, 0.41677123, -0.16924824, 0.22429213, 0.082279116, -0.1780833, 0.20209241, 0.12970525, -0.030272234, -0.19200714, 0.0015769673, -0.1389732) * go_1(1.0, 0.0);
|
||||
result += mat4(0.04211243, 0.07331798, -0.055724114, 0.04086206, -0.04635456, 0.027212424, 0.021861525, 0.12424812, 0.43009162, 0.021664696, 0.20828371, 0.11859106, 0.07390811, -0.1861182, 0.034559406, 0.18561925) * go_1(1.0, 1.0);
|
||||
result += mat4(0.22596797, 0.025346763, -0.056839246, 0.09137385, 0.07363095, -0.12382036, 0.08911783, -0.012355983, -0.07869761, 0.051298574, 0.00816572, -0.044984274, 0.07962154, -0.2254524, -0.007821531, -0.04936664) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.06265961, -0.17783198, 0.11678783, -0.12965304, 0.014506855, -0.17513473, -0.23593299, 0.14054537, 0.1580306, 0.31872272, -0.0042505316, -0.070422255, -0.01316396, 0.0058355615, 0.062464185, -0.06086727) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.079526044, 0.23932967, -0.1139716, 0.15888569, 0.06526993, -0.06958436, -0.04070066, -0.12081254, 0.026716579, 0.014887845, 0.0061467467, 0.127956, 0.040913627, -0.0032820841, 0.086145625, 0.22520025) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.25577608, 0.02553098, -0.14822578, -0.11907723, -0.09787419, -0.03544863, -0.08098151, -0.01305555, 0.20404844, 0.11294246, 0.10096346, 0.15795162, 0.2554626, 0.09361069, 0.001985862, -0.0051444587) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.24454486, -0.014714279, -0.2954907, -0.39995646, -0.15907967, 0.30107877, -0.34781745, 0.095281735, -0.12492393, -0.28375402, -0.16872306, 0.2531788, -0.52085644, 0.35986066, 0.07716912, 0.09565738) * go_2(0.0, 0.0);
|
||||
result += mat4(0.2493129, 0.06395661, -0.09491958, 0.19702488, 0.109871864, -0.051376317, 0.15404263, -0.21282886, 0.1188967, 0.07824094, -0.016752928, -0.14027214, 0.10949832, -0.27629098, 0.081909016, 0.1354018) * go_2(0.0, 1.0);
|
||||
result += mat4(0.18950915, -0.034574565, -0.10378051, -0.15800652, -0.06835184, -0.06987467, 0.035007782, 0.04686656, 0.054061133, 0.014833506, -0.0035361175, 0.016156103, 0.120767444, -0.10196722, 0.10668838, -0.09058739) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.032248627, 0.056413256, 0.042716432, 0.06681831, 0.047605485, -0.07629479, 0.14311917, -0.06909803, 0.10640394, 0.10701861, -0.0051839007, -0.15133362, -0.32146424, -0.039978918, -0.12280021, 0.0048507582) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.1954503, -0.09257865, 0.11023244, -0.01817947, -0.0035485283, -0.015536726, 0.0071826433, 0.042538714, -0.015454641, 0.079593316, -0.07242554, 0.031178504, 0.2319168, -0.10519467, 0.013837495, -0.040088437) * go_2(1.0, 1.0);
|
||||
result += mat4(0.12625901, 0.04531166, 0.038758352, -0.05790713, -0.10029771, -0.118265375, -0.23944628, 0.11955388, 0.070732996, 0.19404806, -0.019913414, 0.04609079, 0.06262817, 0.022330387, -0.029681094, 0.03719176) * go_3(-1.0, -1.0);
|
||||
result += mat4(-0.07737922, 0.0024623116, -0.037666153, -0.19271135, -0.015002153, -0.0059966356, 0.0024538909, -0.0401021, -0.18540399, -0.11140236, -0.11102473, -0.06390247, 0.016754225, 0.35000673, -0.19139731, 0.07363001) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.02150171, -0.2311761, -0.025124706, 0.16819553, -0.0013348719, 0.32091036, -0.061826598, 0.12579474, -0.036611024, -0.018266583, -0.11280143, 0.11073158, 0.050171874, -0.14706045, 0.029553955, 0.0052631944) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.19249865, -0.22854832, 0.09472751, 0.014705341, 0.059496958, 0.13427268, -0.06309558, -0.07153743, -0.31890163, -0.0657967, -0.040345218, 0.09544393, 0.07359761, 0.11245483, 0.00033233972, 0.031550154) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.24668917, -0.37181908, -0.50614715, -0.101197146, -0.1569055, 0.27734125, 0.17144768, -0.04336267, 0.03658949, 0.06747124, 0.30720958, 0.56301194, -0.11314631, -0.29258573, 0.16256689, 0.5221001) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.022761503, 0.13063031, 0.002526217, -0.03466151, -0.15225072, 0.40217137, -0.089131154, 0.19195192, -0.1379853, -0.04640692, 0.104670234, 0.12268618, -0.012009209, -0.20534724, 0.028777445, 0.22195113) * go_3(0.0, 1.0);
|
||||
result += mat4(0.23697586, 0.08793654, -0.10565018, 0.013993297, -0.025932996, -0.13859354, 0.14333159, -0.099132575, -0.049601994, -0.0917448, -0.0021633878, -0.009032609, -0.034750953, -0.30761167, 0.058994945, -0.19427797) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.26944515, 0.30523893, -0.17787015, 0.10827742, 0.06457236, -0.12202401, 0.15371302, 0.011699893, -0.06253491, -0.10976804, -0.37283847, -0.23996784, -0.2750512, -0.024101513, -0.094127975, -0.17462716) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.026286924, 0.06250577, 0.095423855, -0.02849258, -0.12916361, -0.10954709, -0.05825132, -0.102924265, -0.19550376, -0.11730307, 0.032346163, -0.17682706, 0.16651174, 0.031927045, -0.004800601, -0.06323844) * go_3(1.0, 1.0);
|
||||
result += vec4(0.0095873345, 0.04959374, -0.15246227, 0.0044831373);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!SAVE conv2d_5_tf1
|
||||
//!WIDTH conv2d_4_tf.w
|
||||
//!HEIGHT conv2d_4_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_4_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_4_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.021453971, -0.108874515, 0.0005208881, -0.09774453, -0.0053757126, 0.20114918, 0.24454592, 0.04932251, -0.0037210248, -0.0240578, -0.07736935, 0.27604944, -0.12430849, -0.13093218, -0.014840212, 0.13450128) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.19143668, -0.23023333, -0.10232715, 0.24396868, 0.056112397, 0.14535592, -0.25882182, -0.26274678, -0.23119931, 0.07735849, -0.14785223, -0.21026523, -0.2064457, -0.34512606, -0.17808662, 0.30146623) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.0072161015, -0.013303738, 0.07591899, 0.027883789, 0.210858, 0.1422139, -0.027882019, 0.2618474, -0.048504543, 0.07377317, -0.05427271, -0.10014041, -0.12974857, -0.13140713, -0.02249253, 0.08203184) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.07855138, -0.13984342, 0.10037151, -0.056781758, 0.24686107, -0.0048190085, -0.2693424, 0.31722167, -0.28716075, -0.06422215, -0.06738793, -0.06723655, -0.08194382, -0.007975044, 0.20108353, -0.13338897) * go_0(0.0, -1.0);
|
||||
result += mat4(0.35129568, 0.27930936, 0.024239251, -0.10712293, 0.48684034, -0.04380574, -0.0064479653, 0.03754327, -0.13139078, -0.44939983, -1.0460628, -0.016004754, -0.14476573, -0.07113434, 0.515311, -0.400374) * go_0(0.0, 0.0);
|
||||
result += mat4(0.13104302, -0.23410062, 0.091530964, -0.003652217, 0.16696814, 0.16406855, -0.08138474, 0.047526445, 0.25358474, 0.37850454, 0.0362802, -0.046476766, -0.093869686, -0.4143772, 0.08641024, 0.115896136) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.04416574, -0.052188106, 0.05141859, -0.008132604, -0.013658864, 0.1021097, 0.19391364, -0.09257973, 0.15225394, -0.16920799, -0.16172324, 0.41466942, -0.07087308, 0.08632938, -0.07496043, -0.023530172) * go_0(1.0, -1.0);
|
||||
result += mat4(0.09337352, 0.062108494, -0.219173, -0.046151914, 0.22507025, -0.08966131, -0.123690315, 0.08666376, -0.10731867, -0.08518657, 0.024199447, 0.17898631, 0.120247275, 0.089923285, -0.08756211, 0.1775775) * go_0(1.0, 0.0);
|
||||
result += mat4(0.20326594, -0.060535498, -0.061659336, 0.113954924, -0.073462196, 0.15917051, 0.11728326, -0.072256014, -0.0752342, 0.06265616, -0.19494365, -0.25413772, -0.06641352, -0.015642308, 0.16825356, 0.0027654327) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.17029639, -0.05388927, -0.13159063, 0.0795609, 0.00501164, -0.0703107, -0.08229201, 0.07546247, 0.092942156, 0.059050936, -0.07987315, 0.010874322, 0.037708692, -0.0017377702, -0.030414931, 0.28946167) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.2692667, 0.2258295, 0.062060453, 0.1934921, -0.023051793, -0.038611185, 0.21473692, 0.33520013, 0.029885106, 0.103782356, 0.05217351, -0.13349791, -0.034186684, -0.3015818, 0.033423528, 0.21218027) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.013587494, 0.021273775, -0.022650799, -0.011939531, -0.11202949, 0.09365859, -0.042938907, -0.009910716, 0.27254924, 0.07752608, 0.029586637, 0.024899973, 0.04375618, 0.31453863, -0.006775175, 0.008228053) * go_1(-1.0, 1.0);
|
||||
result += mat4(-0.49562672, -0.12472124, -0.13618441, 0.09660054, -0.2275429, -0.0902811, 0.18311924, 0.11677185, -0.13325182, -0.061613016, -0.011462703, -0.12538978, 0.054934092, 0.06742866, 0.25515345, 0.35692096) * go_1(0.0, -1.0);
|
||||
result += mat4(0.5266911, -0.09655596, -0.41069564, -0.3174325, 0.1431904, -0.17732115, -0.36320353, 0.37975433, -0.5158582, -0.21019879, 0.06852925, -0.06648648, -0.18956456, -0.018139647, 0.35707653, 0.07378416) * go_1(0.0, 0.0);
|
||||
result += mat4(0.04151976, -0.037361674, 0.06936584, -0.10462262, -0.22264048, -0.043842267, -0.12742832, -0.21778631, 0.0715335, -0.17921853, -0.3856251, -0.16335362, 0.21045755, -0.5026229, 0.14405337, 0.23096423) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.32437655, 0.07860345, -0.0021187086, 0.123870686, -0.16616751, 0.11004699, 0.04754715, -0.0075211064, -0.08026408, 0.04284957, -0.018143758, 0.032623176, 0.06614686, -0.035856936, 0.13667971, -0.15696613) * go_1(1.0, -1.0);
|
||||
result += mat4(0.11260625, 0.03274457, -0.033769324, -0.11558525, -0.35377702, 0.0019119612, 0.24906515, -0.06853208, 0.0009843144, -0.0050376705, 0.063123666, 0.009872904, 0.19592324, 0.0028321196, -0.114693984, 0.16404222) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.03699667, 0.011842293, -0.12273219, 0.04081692, 0.008484447, -0.052331816, 0.07151068, 0.018538639, 0.077749036, 0.07189092, 0.22443593, -0.2436085, 0.023654116, -0.05127411, 0.27350748, 0.12180999) * go_1(1.0, 1.0);
|
||||
result += mat4(0.16090482, 0.059198547, 0.04856637, -0.19173436, 0.12747662, -0.079715036, -0.20203276, -0.13818277, -0.123076215, -0.07168488, 0.0644838, 0.03524764, 0.0005124138, -0.06789178, 0.048645556, -0.098922126) * go_2(-1.0, -1.0);
|
||||
result += mat4(0.29220074, 0.25197285, 0.09825887, 0.030363245, -0.033246458, -0.08370418, -0.12231589, -0.023000835, 0.082732, -0.16907515, -0.052518822, 0.07991363, 0.06222654, -0.06747275, -0.18931144, -0.42009747) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.02667354, 0.03842717, -0.012755562, 0.061840586, 0.01060547, -0.29081437, 0.010907111, 0.07930905, 0.12273201, 0.017574295, 0.051024225, 0.019036688, 0.07671181, 0.049130872, -0.09734168, -0.070569195) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.08517651, 0.0767222, -0.15657257, 0.18501835, -0.13749431, -0.2833894, 0.109219365, 0.033763003, 0.18988928, 0.13461404, -0.036578514, -0.13256857, -0.097819485, -0.17316358, -0.06512401, 0.1937444) * go_2(0.0, -1.0);
|
||||
result += mat4(-0.32173568, -0.072075866, 0.13004705, -0.15507852, -0.23741087, -0.29364398, 0.10723945, -0.11976219, 0.20620506, 0.17970093, 0.24463713, -0.12555319, -0.021192182, -0.1374317, 0.5359718, 0.59974134) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.01101575, 0.040466793, -0.009630791, 0.13422947, -0.13290837, -0.24789505, -0.061713737, -0.07838521, 0.05379315, -0.14643523, -0.09155805, -0.049997047, 0.06696885, 0.20043123, -0.07542329, -0.08041673) * go_2(0.0, 1.0);
|
||||
result += mat4(0.022160506, 0.01611432, -0.10189221, -0.022767285, -0.06682965, 0.047138248, 0.06860934, -0.012574086, 0.04010214, -0.041280016, -0.034621384, -0.018262599, 0.09731754, -0.059062295, 0.14786182, -0.15185094) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.052484483, 0.06899427, 0.18380043, -0.058414727, 0.07685985, -0.07206598, -0.101362616, -0.012002652, 0.008517392, 0.079471916, -0.30394664, 0.028600946, -0.03270232, -0.23564856, 0.045065008, -0.0034684737) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.049757, 0.07614825, 0.16394803, 0.027053174, 0.0451278, -0.09351286, -0.0042182617, 0.12332257, -0.025281021, -0.03843008, 0.12857373, -0.07611989, -0.0062898803, 0.022618141, -0.13122174, -0.03328411) * go_2(1.0, 1.0);
|
||||
result += mat4(0.12251631, 0.047008447, 0.027589995, -0.12207328, -0.1510795, 0.06724553, 0.17066906, 0.16992114, -0.0026905634, -0.035480864, 0.033738773, 0.018674552, 0.028614907, -0.019945908, -0.0156899, -0.09562145) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.116588935, 0.14205505, 0.099545434, -0.045527786, -0.049273346, 0.20760757, 0.053965498, -0.12198069, -0.14654607, 0.041820496, 0.038068503, 0.24565905, 0.09786504, 0.18309233, 0.23802327, -0.085740186) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.1262052, -0.011846116, -0.058820397, -0.019373653, -0.09569547, -0.08265971, -0.05178388, -0.020502446, -0.17525336, -0.22874829, 0.0075891856, -0.189923, 0.09809122, 0.109637566, -0.0005973885, -0.06477921) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.28209856, 0.11276813, 0.054377034, -0.00891202, -0.095922634, 0.071109876, -0.039932176, -0.047409832, -0.06504704, 0.11923986, 0.0013364811, -0.122095086, -0.20282102, -0.022717483, -0.115474045, 0.020858249) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.16130303, 0.072821185, -0.021358958, -0.11687897, -0.15543966, 0.05783285, 0.10317231, -0.12240756, 0.053357504, -0.090291016, -0.21943556, 0.46947235, 0.19072579, 0.017349033, -0.55443907, -0.10510661) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.4155687, 0.019206723, -0.20055711, 0.028732464, -0.1981807, 0.20637372, 0.03305817, -0.17949893, -0.21051097, 0.21483344, 0.0061496794, -0.48980987, -0.26750582, 0.09230394, -0.117223755, -0.07636286) * go_3(0.0, 1.0);
|
||||
result += mat4(0.20611528, -0.00095511036, -0.21555157, -0.07065484, 0.06880411, 0.068082534, -0.10104979, 0.16050354, -0.07437897, -0.13145325, -0.017651044, 0.055096775, -0.05443345, -0.018634815, -0.011232755, -0.10835) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.2637829, 0.07681072, 0.015995527, 0.004554211, 0.07495561, 0.18873464, -0.14303622, 0.25786543, -0.14117226, -0.008715274, -0.17176823, -0.0006595096, -0.06566383, -0.19184378, -0.18945406, 0.20968987) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.03293623, 0.003399063, 0.08051177, -0.0072856937, -0.07375858, 0.075319655, -0.10791501, -0.002204552, -0.093564905, -0.122712255, -0.10658267, -0.015067637, -0.033247817, 0.09952069, -0.13724248, 0.068189256) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.001935585, 0.05018077, -0.0154469935, -0.034524206);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.0053346683, 0.010174534, -0.050979972, -0.06134544, -0.007238652, -0.012790015, 0.036398683, -0.09181499, 0.11328388, -0.14236617, -0.17519625, -0.34661606, 0.008069393, -0.028871074, -0.02980949, -0.0853359) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.05187267, -0.09381704, 0.035209883, 0.29482442, -0.0018002815, -0.029504262, 0.2609028, -0.09480671, -0.0737553, -0.070559524, 0.081991084, 0.1513024, 0.048344653, -0.09336617, 0.0034569732, 0.10530542) * go_0(-1.0, 0.0);
|
||||
result += mat4(-0.06749591, 0.0065624053, 0.013237342, 0.14225115, 0.27183163, -0.15656447, 0.031672053, 0.009592649, -0.0202286, 0.26220062, 0.19387855, -0.18505628, 0.040554795, 0.07295961, -0.13291295, -0.12600344) * go_0(-1.0, 1.0);
|
||||
result += mat4(0.039192002, 0.0846215, -0.06593224, 0.28147796, 0.06301313, 0.26323164, -0.16742979, 0.22004774, -0.17470881, 0.060716614, 0.15430811, 0.18970133, 0.08858931, -0.027321626, -0.037833836, 0.07344837) * go_0(0.0, -1.0);
|
||||
result += mat4(0.0633813, 0.35046157, -0.101075254, 0.015974075, 0.19010352, -0.7135035, -0.24324696, -0.42072615, 0.06825536, -0.052808974, 0.28965715, -0.0015640302, -0.27062586, 0.4279925, 0.035623744, 0.46321228) * go_0(0.0, 0.0);
|
||||
result += mat4(0.02639867, 0.26469797, -0.09086266, 0.07440796, -0.192054, 0.1010368, -0.04398074, 0.056824226, -0.27057743, -0.20455118, 0.19338831, -0.21843775, 0.20736177, -0.26259273, -0.07667085, -0.19504389) * go_0(0.0, 1.0);
|
||||
result += mat4(-0.007056104, 0.04284205, 0.01933733, 0.07267832, 0.0012616975, -0.30140647, -0.019223223, -0.046687007, -0.037844718, -0.014929125, 0.022630794, 0.046716493, 0.057279173, -0.08055539, -0.027891241, 0.019557232) * go_0(1.0, -1.0);
|
||||
result += mat4(0.035518404, -0.10087327, 0.0011048123, -0.123707846, 0.37190285, 0.43751532, -0.022599256, -0.041709043, 0.11357196, -0.029839104, -0.056960747, -0.17228557, 0.08558022, 0.046361133, 0.021548864, 0.24297418) * go_0(1.0, 0.0);
|
||||
result += mat4(-0.043598346, -0.09812348, 0.056599542, -0.09833163, -0.07193007, 0.015760094, -0.053177495, -0.015448543, 0.035163186, -0.03889347, 0.121799015, 0.15738566, -0.115644835, 0.043310717, 0.060173217, -0.059635755) * go_0(1.0, 1.0);
|
||||
result += mat4(-0.111604795, 0.1678389, 0.049967546, 0.045353863, -0.013896185, 0.035128903, 0.040686198, -0.16442506, 0.1149577, -0.14343217, -0.08858, 0.02656137, 0.059526477, -0.13914491, 0.12757027, 0.034920372) * go_1(-1.0, -1.0);
|
||||
result += mat4(0.15849945, 0.12067003, -0.1579611, 0.30790725, -0.041249942, 0.03948043, -0.12535375, -0.02566875, 0.3150059, 0.027081972, -0.026308673, -0.25326517, 0.016824603, -0.13551097, 0.1412756, 0.037750524) * go_1(-1.0, 0.0);
|
||||
result += mat4(0.1562541, -0.041948073, -0.14951487, 0.119380556, -0.21773878, -0.019281754, 0.08185942, 0.09982689, 0.017187534, -0.18181366, -0.09270861, 0.08527679, 0.051988564, 0.08686172, -0.12665209, -0.07205808) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.08860466, -0.17931758, 0.10191625, -0.47623265, 0.1562338, -0.2960855, 0.013664795, 0.29452285, 0.1463958, 0.17562817, -0.41623253, -0.196999, -0.049113005, 0.0556021, 0.054452494, 0.14073615) * go_1(0.0, -1.0);
|
||||
result += mat4(-0.5345973, -0.069205046, 0.37001884, 0.6955835, 0.22635284, -0.09021557, -0.04693607, -0.4458824, 0.25049326, -0.06503396, 0.07584689, 0.5394811, 0.33387923, -0.010540017, 0.038980547, -0.13371105) * go_1(0.0, 0.0);
|
||||
result += mat4(-0.04414677, -0.22056313, 0.05580458, 0.11914465, 0.19864987, -0.1025625, -0.010050287, 0.15919746, -0.40589634, 0.4966349, -0.47632688, -0.022637444, 0.17247641, -0.51093113, 0.21157944, -0.2890017) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.034673482, -0.0075900992, -0.061077584, -0.03859898, 0.32444152, -0.14619137, -0.1375446, -0.030322462, 0.029679669, 0.079344586, -0.03862258, -0.05766807, 0.104488336, 0.006179548, -0.1168102, 0.069729604) * go_1(1.0, -1.0);
|
||||
result += mat4(0.08504003, 0.042162962, -0.17509954, -0.06258286, -0.45796555, -0.061748773, 0.25438437, -0.02988987, -0.06897794, 0.105180845, -0.08879189, -0.120605074, -0.1478659, -0.13201937, -0.01755498, 0.020606143) * go_1(1.0, 0.0);
|
||||
result += mat4(0.08932581, 0.1453785, -0.12802933, 0.049442187, 0.045360584, 0.16079827, -0.14142223, 0.10168491, 0.20244479, -0.17981426, 0.19759466, 0.05217847, 0.04889828, 0.06941533, -0.111836776, -0.08046399) * go_1(1.0, 1.0);
|
||||
result += mat4(-0.011953735, 0.11362504, -0.122588776, -0.10408559, 0.051712614, -0.05161036, -0.068698496, -0.015663281, -0.06346889, 0.06561636, 0.03783044, 0.02756004, -0.036310352, -0.16962235, -0.062494226, 0.0069608325) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.16857432, -0.17322211, 0.15971284, 0.19980437, -0.007965961, -0.015480705, 0.036090557, 0.07414387, -0.2941106, -0.24430539, 0.01070864, 0.22401866, -0.34321144, 0.09537491, -0.08020218, 0.45404655) * go_2(-1.0, 0.0);
|
||||
result += mat4(-0.021609096, -0.11348408, -0.01450652, -0.063170746, 0.06990935, -0.035983834, -0.038010992, -0.10578655, 0.29232737, 0.048835874, 0.054028947, -0.12924139, -0.03058583, 0.028469706, 0.09563202, 0.085674495) * go_2(-1.0, 1.0);
|
||||
result += mat4(-0.01894022, 0.037628658, -0.102314636, -0.28041583, 0.07495663, -0.058895253, 0.16422969, -0.07163792, 0.039416216, -0.13800906, -0.039811566, -0.10612402, -0.047593113, -0.28491783, 0.41632858, 0.15253194) * go_2(0.0, -1.0);
|
||||
result += mat4(0.26240867, -0.05335849, -0.014135048, 0.055749495, -0.020126658, 0.2952794, -0.015241771, 0.36143306, 0.43075684, 0.1921996, -0.4329065, 0.5114495, 0.7326109, -0.054901246, -0.076693356, -0.26104695) * go_2(0.0, 0.0);
|
||||
result += mat4(0.14548428, 0.14578429, 0.17193514, -0.07973242, 0.011952286, -0.047767498, 0.025101405, 0.0016503566, -0.26948047, -0.16503395, -0.061791085, 0.030557185, 0.15400517, -0.054951698, -0.14611247, 0.3550633) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.05926111, -0.083442695, 0.046579204, -0.017723244, 0.12846185, 0.018434443, -0.17914511, -0.077696435, 0.060048338, 0.02956987, -0.11914462, 0.057770032, -0.054673657, -0.005353606, -0.39014184, 0.08306877) * go_2(1.0, -1.0);
|
||||
result += mat4(0.07357362, 0.23051825, -0.22640751, 0.080715515, -0.14467078, 0.009734264, 0.054320686, 0.24534328, -0.16038458, 0.06575425, 0.058553413, 0.17755087, 0.08184439, 0.17078212, 0.148369, -0.09309279) * go_2(1.0, 0.0);
|
||||
result += mat4(-0.11160211, -0.07590204, -0.01676188, -0.062253337, 0.016433533, 0.0146132, -0.040350936, 0.06749202, -0.031521842, 0.1441664, -0.09916073, 0.050578352, -0.06560962, -0.31174552, 0.056873083, -0.077912) * go_2(1.0, 1.0);
|
||||
result += mat4(0.09344025, 0.075936995, -0.1627903, -0.04781558, -0.01878236, 0.045879602, -0.11507387, -0.025356822, -0.09113391, 0.07263937, 0.08232447, 0.08727616, -0.024921807, 0.051639438, 0.006532631, -0.018751068) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.022455849, -0.12924309, 0.26318657, -0.32464805, -0.09627585, 0.04496843, -0.09630052, -0.025761643, -0.090804085, 0.24410398, -0.03162944, -0.1961483, 0.14065808, -0.064709485, -0.0040163463, 0.05445074) * go_3(-1.0, 0.0);
|
||||
result += mat4(-0.020935195, -0.1028065, 0.0012804621, 0.02302866, -0.00924972, -0.0041193594, 0.0060590385, -0.003394384, -0.23241943, -0.023235107, 0.08077456, 0.15720141, 0.06568382, -0.09971436, 0.09056065, 0.04271102) * go_3(-1.0, 1.0);
|
||||
result += mat4(-0.20997737, -0.12892777, 0.4658528, 0.13622813, -0.2867294, -0.09359254, 0.18821026, 0.25550604, -0.18562363, 0.080713026, 0.13463654, 0.045504905, -0.013133853, -0.1316404, 0.08379897, -0.00047142128) * go_3(0.0, -1.0);
|
||||
result += mat4(0.3276134, 0.21952826, -0.80777377, -0.69810224, 0.34190908, -0.09293263, 0.33313555, -0.27255502, -0.24287084, -0.07741488, 0.06090265, -0.10161252, -0.37684909, 0.4678029, 0.13506591, 0.42470258) * go_3(0.0, 0.0);
|
||||
result += mat4(0.080790855, -0.09707547, -0.05506975, 0.027011644, -0.1434346, 0.01363872, 0.12616752, 0.16789167, 0.1656414, -0.11586835, 0.059612263, -0.074029386, -0.19813071, 0.46032718, -0.03935981, 0.0067143585) * go_3(0.0, 1.0);
|
||||
result += mat4(0.10322512, 0.0822636, -0.16766444, 0.041008063, -0.027768405, 0.23103505, 0.06737122, 0.15258405, 0.04557388, -0.18179403, 0.12489025, -0.09759324, -0.05925805, 0.04869987, 0.07329833, -0.09738542) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.10823879, -0.403376, 0.3264802, -0.16503738, -0.057512645, -0.20902547, -0.14862378, -0.3192005, -0.046263676, 0.12744917, -0.019174274, -0.02318789, -0.085088454, -0.05723332, 0.0039772973, 0.07991316) * go_3(1.0, 0.0);
|
||||
result += mat4(0.10313916, 0.04410904, 0.03286652, 0.059946325, 0.019948404, 0.070217304, -0.017572487, 0.20332281, 0.06776308, 0.029285522, -0.14116238, -0.05864782, -0.18382367, -0.06568212, 0.11855615, 0.101256005) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.036374483, 0.029420665, 0.04437756, -0.04474691);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x3x3x16
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!SAVE conv2d_6_tf1
|
||||
//!WIDTH conv2d_5_tf.w
|
||||
//!HEIGHT conv2d_5_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define go_0(x_off, y_off) (max((conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_1(x_off, y_off) (max((conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_2(x_off, y_off) (max(-(conv2d_5_tf_texOff(vec2(x_off, y_off))), 0.0))
|
||||
#define go_3(x_off, y_off) (max(-(conv2d_5_tf1_texOff(vec2(x_off, y_off))), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.059325468, 0.10884231, 0.018158086, 0.031802185, 0.10368743, -0.06776637, 0.048326045, -0.06312353, -0.0025675546, 0.09309577, -0.025533969, 0.029684044, 0.017237723, 0.062099144, 0.047039766, 0.050348036) * go_0(-1.0, -1.0);
|
||||
result += mat4(-0.04767078, -0.06409279, 0.112965874, 0.04621161, -0.28172916, -0.13897015, -0.022806352, 0.26966885, 0.02019569, -0.10707113, -0.43058416, -0.14103983, -0.13225646, -0.020053176, -0.17319782, -0.009653082) * go_0(-1.0, 0.0);
|
||||
result += mat4(0.0031349238, -0.060933832, 0.107986666, -0.019791966, -0.23946726, -0.18045186, 0.18286318, -0.05431065, 0.11742379, -0.019123906, 0.33327517, 0.07455424, -0.035427105, 0.18659347, -0.050884776, 0.019193258) * go_0(-1.0, 1.0);
|
||||
result += mat4(-0.22954239, 0.011265787, -0.026520751, -0.12629737, -0.07009803, 0.44925988, -0.15938939, 0.11956771, 0.11535644, -0.1302371, 0.1235775, 0.16483483, 0.022965495, 0.110546246, 0.00064579415, -0.12753843) * go_0(0.0, -1.0);
|
||||
result += mat4(0.047553673, 0.16213869, 0.7510964, 0.21228868, 0.40994287, 0.61919236, 0.3982374, -0.016163021, 0.3291035, 0.1134356, 0.12384387, -0.31114763, 0.21338554, -0.04721641, 0.122114286, 0.2717476) * go_0(0.0, 0.0);
|
||||
result += mat4(-0.06529201, -0.08936482, 0.031857736, -0.02372691, 0.0416097, 0.28484538, -0.38181338, -0.05129518, 0.40150553, -0.01970737, 0.1043854, 0.11986372, -0.2267319, 0.0014845231, -0.035269983, 0.11712099) * go_0(0.0, 1.0);
|
||||
result += mat4(0.079867415, -0.09982735, 0.10313241, 0.055490237, -0.42685422, -0.3431141, -0.06037366, 0.17539841, -0.010511819, -0.09743252, 0.050748866, 0.11064108, -0.09785722, -0.10230299, -0.04106169, -0.016831731) * go_0(1.0, -1.0);
|
||||
result += mat4(-0.06847075, -0.026447225, -0.123430386, 0.063637204, -0.37617612, -0.09615662, -0.26226708, -0.008175561, -0.08101131, 0.11093525, -0.13149206, -0.06363292, -0.0482858, -0.2771799, 0.10528571, 0.119109035) * go_0(1.0, 0.0);
|
||||
result += mat4(0.09151277, 0.029019276, 0.041349206, -0.011239478, 0.035083957, 0.05281079, -0.0742173, -0.018509442, -0.17175299, -0.4226507, -0.118186444, -0.0771296, 0.107038856, 0.0819975, 0.12445646, 0.07091557) * go_0(1.0, 1.0);
|
||||
result += mat4(0.1275357, -0.097659886, -0.0114354445, 0.023900568, -0.02511702, 0.005830569, -0.010882143, -0.04046068, -0.08638482, 0.08664022, -0.15654318, 0.03333846, -0.12521335, -0.11987078, 0.028556254, -0.020760164) * go_1(-1.0, -1.0);
|
||||
result += mat4(-0.38474286, -0.15288061, 0.04925842, 0.050009686, 0.23555282, 0.054784663, -0.0971203, 0.017791113, -0.35539824, -0.08806168, 0.08992579, 0.22714761, -0.047685623, -0.17510797, 0.1137738, -0.069451034) * go_1(-1.0, 0.0);
|
||||
result += mat4(-0.16623408, -0.08202571, -0.03291826, 0.0016267949, 0.20682698, 0.08788948, 0.10241089, 0.019209227, -0.14802241, 0.091788374, -0.238735, -0.06633396, 0.02360112, 0.1521805, -0.022510838, -0.08931379) * go_1(-1.0, 1.0);
|
||||
result += mat4(0.034280665, -0.12431295, 0.092791, 0.15279225, -0.43373865, 0.20077267, -0.15919733, -0.27969292, -0.26948065, 0.19652127, -0.27456176, 0.04137772, 0.006545539, 0.0031402514, 0.03849979, -0.10978278) * go_1(0.0, -1.0);
|
||||
result += mat4(0.62025917, -0.32462567, 0.2817292, -0.18380783, -0.3338593, -0.49056754, 0.32645953, 0.4146035, 0.3773462, 0.54346967, -0.032203436, -0.14506778, -0.30044907, 0.40134314, 0.24155408, 0.24397472) * go_1(0.0, 0.0);
|
||||
result += mat4(0.089335114, -0.05529855, -0.18364899, -0.153323, -0.18347202, -0.060125064, -0.29216367, -0.2717291, 0.10592963, 0.38889876, 0.25363386, 0.33723134, -0.103703365, 0.14922962, -0.21206948, -0.20289616) * go_1(0.0, 1.0);
|
||||
result += mat4(-0.035760924, 0.18820894, -0.12723185, -0.018780319, 0.124459654, 0.28909087, -0.2763883, -0.45110545, 0.098143585, 0.16052029, -0.055098705, -0.14840914, -0.0019514654, 0.07090622, -0.055036955, -0.0035953245) * go_1(1.0, -1.0);
|
||||
result += mat4(-0.124669634, 0.23131305, -0.05750295, -0.056296032, 0.35691026, 0.2640789, 0.49912274, 0.26795143, -0.26460487, -0.026896512, -0.07179325, 0.17373477, -0.13186656, 0.0021319336, -0.016407885, 0.3014283) * go_1(1.0, 0.0);
|
||||
result += mat4(-0.09491939, 0.11503968, -0.14077829, -0.043197304, -0.061866064, -0.1574549, 0.0054375776, 0.066160634, -0.17686372, -0.26767558, -0.038844116, 0.122724466, -0.05043839, 0.063884266, 0.0064002997, -0.13583377) * go_1(1.0, 1.0);
|
||||
result += mat4(0.031301867, -0.02947819, -0.0016769855, 0.12952408, -0.025022922, 0.065425046, -0.072289295, -0.071249105, 0.14579567, -0.09058119, 0.12663712, 0.1515388, 0.44767743, 0.02971349, 0.015892735, -0.08058422) * go_2(-1.0, -1.0);
|
||||
result += mat4(-0.2868111, -0.10812653, -0.29182926, -0.38444322, -0.0875354, -0.07220258, 0.05978065, 0.093328245, 0.058548283, -0.013913258, -0.20954674, -0.16400063, 0.3185215, 0.068897314, 0.15869021, 0.022877626) * go_2(-1.0, 0.0);
|
||||
result += mat4(0.116845705, -0.12729645, 0.056697316, -0.21263942, -0.07000074, 0.073977455, -0.09006404, -0.029770354, -0.20823102, -0.20088868, 0.15658094, 0.24306639, -0.0453592, -0.16011035, 0.08521533, -0.032264974) * go_2(-1.0, 1.0);
|
||||
result += mat4(0.1114789, -0.1083731, 0.10465276, -0.08903837, -0.06455987, 0.040030345, -0.07937248, -0.20654759, -0.26873547, -0.19390975, -0.039021965, -0.025602374, -0.5575801, -0.08876011, -0.19116728, -0.2401055) * go_2(0.0, -1.0);
|
||||
result += mat4(0.37626424, -0.0912155, -0.6153361, -0.71465075, 0.018208932, -0.14997734, 0.23627761, 0.20832567, 0.07427123, -0.37869486, -0.26574427, 0.187582, -0.37201726, 0.17809474, -0.02568795, 0.23900814) * go_2(0.0, 0.0);
|
||||
result += mat4(-0.085337594, -0.50634587, 0.30636734, -0.2760558, 0.01893911, -0.08425695, -0.023656169, 0.021421626, 0.16813251, -0.039550815, 0.21165498, -0.027628547, -0.123874225, 0.013802332, -0.2732087, -0.09419671) * go_2(0.0, 1.0);
|
||||
result += mat4(-0.07190724, -0.019237598, 0.020249542, 0.07541295, -0.03817686, 0.09266451, -0.12214172, -0.01344174, 0.03281797, 0.057655178, -0.059896503, 0.014948791, -0.13952477, 0.18810949, -0.19016883, 0.06842416) * go_2(1.0, -1.0);
|
||||
result += mat4(-0.13111524, 0.14539744, -0.10212538, -0.2169032, 0.13810973, -0.12576458, 0.124372825, 0.04992259, 0.21758182, -0.22160134, 0.24321079, 0.017698256, 0.39995426, 0.074034885, 0.120019354, -0.15522505) * go_2(1.0, 0.0);
|
||||
result += mat4(0.023914235, 0.1424257, 0.010302871, 0.15150794, -0.040021677, 0.015862139, 0.14459212, 0.08632827, 0.04257336, 0.055059638, 0.0030461506, 0.011985334, -0.049230937, 0.07851301, -0.05119983, -0.111701734) * go_2(1.0, 1.0);
|
||||
result += mat4(0.04485158, 0.116597414, 0.00014909732, -0.012128512, 0.15801767, 0.18273115, -0.033926453, 0.05170487, -0.040683754, -0.18606974, 0.08324687, 0.069539666, 0.07098698, -0.014132968, 0.029499048, -0.07263477) * go_3(-1.0, -1.0);
|
||||
result += mat4(0.04309544, 0.089722805, -0.018306322, 0.29061043, 0.15191254, 0.15917647, 0.0073858183, 0.039199475, 0.42514518, -0.053955313, 0.10820046, -0.09134685, -0.3087313, -0.16339037, -0.05226669, 0.044995327) * go_3(-1.0, 0.0);
|
||||
result += mat4(0.008636428, 0.029086163, -0.09151674, -0.36466715, -0.0128008155, 0.018820466, -0.02700147, -0.0064047636, 0.28287655, 0.02709404, -0.05233492, -0.08967187, -0.042183813, -0.13990502, -0.005085154, -0.028511493) * go_3(-1.0, 1.0);
|
||||
result += mat4(0.00022532263, -0.09108507, 0.0089569865, 0.052016005, -0.19314727, -0.355347, 0.08082937, 0.2134498, 0.21036889, -0.10165983, 0.20334485, 0.14575538, 0.017676214, -0.13149881, -0.018741794, -0.019599862) * go_3(0.0, -1.0);
|
||||
result += mat4(-0.20513605, 0.47578803, -0.18631598, 0.2535432, -0.049522053, -0.37224755, 0.11227206, -0.37000927, 0.19969453, -0.47287735, -0.07506754, -0.0957071, 0.82927394, -0.54057014, 0.5800732, 0.08937558) * go_3(0.0, 0.0);
|
||||
result += mat4(-0.022189412, 0.14622113, -0.4772564, -0.31178755, 0.10667427, -0.07335338, 0.06144331, 0.00056827103, -0.08263861, -0.009126272, -0.22802618, -0.20760304, 0.12688845, -0.061324466, 0.33361357, 0.38350767) * go_3(0.0, 1.0);
|
||||
result += mat4(0.021188622, 0.1151918, -0.10654739, -0.03341855, 0.24870358, -0.06689332, 0.11881217, -0.0045951125, -0.039464932, -0.030190004, 0.014174111, -0.025356272, 0.07469406, -0.0059695644, 0.008267219, -0.0991054) * go_3(1.0, -1.0);
|
||||
result += mat4(-0.009981438, -0.36484948, 0.04801225, 0.22368562, -0.055985868, 0.229039, -0.10823553, 0.1477355, -0.0091677625, 0.06279847, 0.034393013, 0.031901076, 0.28783056, 0.086422645, 0.20860936, 0.054018307) * go_3(1.0, 0.0);
|
||||
result += mat4(-0.08720452, -0.07756267, 0.018853918, -0.014108689, -0.019337144, 0.021249043, -0.05633926, -0.109904505, -0.088990815, 0.16876367, -0.13149975, -0.054357648, 0.08588134, -0.10262266, 0.12052009, 0.05154292) * go_3(1.0, 1.0);
|
||||
result += vec4(-0.010602045, 0.053976092, 0.008913503, 0.0011945717);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_last_tf
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.105475314, -0.07022547, -0.16326137, -0.12503424, -0.004623021, -0.0143323885, 0.042996034, 0.03422294, -0.38310882, -0.4431925, -0.28772846, -0.3213578, -0.018014904, 0.02429277, -0.07177951, -0.04458822) * g_0;
|
||||
result += mat4(-0.0973233, -0.032439478, -0.08420249, -0.054693196, 0.012960555, 0.06929602, 0.004247494, 0.061315402, -0.09607745, -0.16862066, 0.01537482, -0.038459156, 0.019662246, 0.059920583, -0.1071646, -0.06478967) * g_1;
|
||||
result += mat4(0.15711947, 0.0754732, 0.17891979, 0.098270796, 0.14122486, 0.14893766, 0.12408279, 0.14845194, 0.16199848, 0.14090912, 0.13496809, 0.1119815, 0.03974558, -0.057513904, 0.09213575, -0.0012252429) * g_2;
|
||||
result += mat4(-0.011343602, -0.02488338, 0.07799659, 0.06503721, 0.06380687, 0.048929837, -0.05555838, -0.050519127, 0.14673206, 0.18085165, 0.07261422, 0.09738158, 0.07395791, 0.005573146, -0.05454926, -0.13565786) * g_3;
|
||||
result += mat4(-0.08591514, -0.05664865, 0.23980616, 0.24876402, 0.19052829, 0.011938714, 0.21487322, 0.058656186, 0.036630988, 0.14918756, 0.013127693, 0.13092093, -0.37889576, -0.4068804, -0.27258882, -0.30605716) * g_4;
|
||||
result += mat4(-0.25149816, -0.21979512, -0.24949454, -0.20483162, -0.10972783, -0.17315808, -0.08562763, -0.16086778, 0.044681527, 0.050807394, -0.019424994, -0.022418005, 0.10039492, -0.013666552, -0.22373566, -0.34493732) * g_5;
|
||||
result += mat4(0.1419155, 0.081392206, -0.18103191, -0.2122926, -0.1445937, -0.015969204, -0.12368782, -0.0044421684, -0.09534078, -0.14815839, -0.1052107, -0.16341865, 0.3050403, 0.34488317, 0.16171226, 0.18700944) * g_6;
|
||||
result += mat4(0.12444696, 0.08712589, 0.06266247, 0.031022022, 0.17707655, 0.24904409, 0.20961654, 0.2610619, -0.099262595, -0.06900819, -0.034567446, -0.020191457, -0.1468561, -0.04683958, 0.14910224, 0.244686) * g_7;
|
||||
result += mat4(-0.002428158, -0.012889509, 0.0006541127, -0.0058380975, 0.096147396, 0.07791617, 0.119144954, 0.11699654, -0.024602454, -0.07894611, -0.00021709128, -0.03979557, 0.0028512406, -0.015790012, 0.0082511455, 0.029357092) * g_8;
|
||||
result += mat4(-0.01410329, -0.004162405, -0.09005045, -0.07753674, 0.004509965, -0.024188736, 0.13799691, 0.10589621, -0.023018798, 0.0064198375, -0.103344224, -0.07463909, -0.060048997, -0.071094714, -0.13042289, -0.14482167) * g_9;
|
||||
result += mat4(-0.009015246, 0.01581748, -0.035448726, -0.012348933, -0.101627484, -0.05530413, -0.14063041, -0.121775225, 0.074719116, 0.033839386, 0.045573987, -0.006698053, 0.0015141299, 0.003634417, 0.017102007, 0.0074890694) * g_10;
|
||||
result += mat4(0.0042357175, 0.018735386, 0.058959343, 0.057424515, -0.021633089, -0.037194982, -0.14109972, -0.1506368, 0.004357002, -0.006871023, 0.05337361, 0.039684236, 0.087463334, 0.07772685, 0.12278512, 0.1224218) * g_11;
|
||||
result += mat4(0.018359886, 0.046934873, -0.008225237, 0.020650858, -0.03961538, -0.014779162, -0.04161338, -0.00953579, 0.0017313146, 0.0068857935, -0.0024282748, 0.0047545764, 0.02635904, 0.027336216, 0.02701322, 0.029939381) * g_12;
|
||||
result += mat4(-0.00067966996, 0.024480496, -0.015218739, -0.010472019, -0.03994461, -0.052318517, -0.04450191, -0.043226667, -0.03166469, -0.03799331, 0.015428865, -0.018422252, 0.00040845043, 0.03558268, -0.0099401595, -0.00054432114) * g_13;
|
||||
result += mat4(-0.0032104475, 0.019604867, -0.02486679, 0.002134673, 0.014368818, -0.0013395248, 0.017318068, 0.0021403218, -0.02198377, 0.010297547, -0.041619625, -0.02740482, -0.067249276, -0.03040953, -0.021304253, -0.009557115) * g_14;
|
||||
result += mat4(-0.019099236, -0.037010793, 0.013720462, 0.023708181, 0.016356282, -0.00028589502, -0.010570909, -0.009186907, 0.03493662, 0.055599142, -0.017043956, 0.004204044, -0.013573257, -0.013537684, 0.008151195, 0.0074913655) * g_15;
|
||||
result += mat4(0.009309031, -0.0014795153, 0.025114728, -0.0066442797, -0.012085473, -0.0030560147, 0.002144206, 0.0009732741, 0.022301642, -0.0091133695, 0.0011837826, -0.020275833, -0.021349607, -0.011693419, -0.018912962, -0.022418445) * g_16;
|
||||
result += mat4(-0.0045772395, 0.031085191, 0.01215795, 0.023887333, 0.023408212, 0.0005998807, 0.011254428, -0.004634461, 0.016601006, 0.046663348, 0.031117432, 0.04910873, -0.113230005, -0.035702843, -0.058746565, -0.053893737) * g_17;
|
||||
result += mat4(-0.020218112, 0.056803435, -0.0037077996, 0.05123925, -0.016713811, -0.05551032, -0.005916611, -0.037839632, -0.007671626, -0.009099201, -0.0010055836, 0.003332688, 0.020744357, 0.01957675, 0.057906736, 0.041446246) * g_18;
|
||||
result += mat4(0.022438819, 0.04616756, 0.035925094, 0.0639705, 0.0009332198, 0.020964272, -0.010805394, 0.031757344, 0.051255573, 0.032838948, 0.00055445684, -0.03195623, 0.04753827, 0.016436901, 0.04788274, 0.022093765) * g_19;
|
||||
result += mat4(0.03479086, 0.035946105, 0.04343359, 0.04015664, 0.06081792, 0.061758887, 0.10128842, 0.007471392, -0.027261607, -0.01290544, -0.029938918, -0.050834358, -0.015550162, 0.0072828676, -0.04580556, -0.029642029) * g_20;
|
||||
result += mat4(0.011150116, 0.029789668, -0.00354488, 0.045047592, -0.018265083, -0.020843878, 0.015457328, 0.0053232997, 0.0791804, -0.028661052, 0.079342775, -0.039631505, 0.14613943, 0.08323415, 0.049641483, 0.047863442) * g_21;
|
||||
result += mat4(-0.103034586, -0.107580125, 0.00044325445, 0.007830247, -0.017059505, 0.010152936, -0.02845979, -0.01841766, -0.10722863, -0.025262646, -0.07402096, -0.025055556, 0.0013303137, 0.12574737, -0.0161103, 0.06077798) * g_22;
|
||||
result += mat4(-0.0420636, -0.062703885, -0.06476972, -0.10516001, 0.018120673, 0.024305122, -0.013997766, 0.015815413, -0.06317691, -0.03968166, -0.054052643, -0.016300509, -0.08255892, -0.01612941, -0.04194852, -0.012637189) * g_23;
|
||||
result += mat4(0.042659573, -0.10762496, -0.077143244, 0.12583935, -0.022020226, -0.0042312425, -0.016734738, 0.027007964, -0.06609771, -0.056038737, -0.0058528963, 0.035508137, -0.019722374, -0.055094264, 0.010977759, -0.009833099) * g_24;
|
||||
result += mat4(0.063830875, -0.019885639, 0.055574782, 0.039456647, 0.01576898, -0.1389799, 0.063411795, -0.11600623, -0.013968303, -0.03318867, -0.06806915, -0.09373464, -0.022723546, -0.03329239, 0.014282872, 0.027576538) * g_25;
|
||||
result += mat4(-0.018100513, 0.06204485, 0.010761461, -0.045085587, 0.009286288, 0.02310671, 0.10633246, -0.090849996, 0.13112675, -0.01639808, 0.0022725316, -0.076779045, 0.11831251, 0.1460306, -0.10849466, -0.07749171) * g_26;
|
||||
result += mat4(-0.15850247, 0.118011266, -0.10121594, -0.007109052, 0.071873754, 0.06954878, 0.0377852, 0.044174008, -0.062925555, -0.01758927, 0.1416964, 0.17206357, -0.035632525, -0.04652215, 0.061932907, 0.034339) * g_27;
|
||||
result += vec4(-0.11952045, -0.10779418, -0.0626279, -0.042614873);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_last_tf1
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(-0.009000901, -0.018048609, 0.013095594, 0.002321373, 0.0004716619, 0.00504148, -0.016826658, -0.014922383, 0.15059204, 0.16593806, 0.115392484, 0.12520894, 0.05049829, 0.060210057, 0.086421266, 0.07242362) * g_0;
|
||||
result += mat4(0.06268658, 0.030466434, 0.07876877, 0.04129863, 0.04142328, 0.009963961, 0.051785357, 0.012811113, 0.1295883, 0.139931, 0.07733839, 0.08014211, 0.07156476, 0.0342396, 0.051614303, 0.043559864) * g_1;
|
||||
result += mat4(0.00041542648, 0.016051646, -0.011512418, 0.013076814, 0.03734479, 0.02791584, 0.012426691, 0.022044811, -0.034128398, -0.027107332, -0.021998279, -0.012139807, -0.033177473, -0.016310865, -0.078221664, -0.041203145) * g_2;
|
||||
result += mat4(-0.008398536, -0.010332053, -0.050231732, -0.039691273, -0.042082537, -0.030281143, -0.014039778, -0.0020190612, -0.11956351, -0.13638765, -0.09794402, -0.10228069, -0.08344795, -0.07944541, -0.004189214, -0.028206991) * g_3;
|
||||
result += mat4(0.0002908945, -0.00831185, -0.06870294, -0.083311856, -0.024992501, 0.0038247898, -0.049389005, -0.020098582, -0.0135326125, -0.040408995, -0.012083491, -0.042174604, 0.16112538, 0.13720983, 0.13937058, 0.10870099) * g_4;
|
||||
result += mat4(0.078961425, 0.082619205, 0.06910667, 0.06579004, -0.0077012256, -0.00038692637, 0.00015553503, -0.012561662, 0.00053048285, -0.01461681, 0.02600344, 0.024862211, -0.06958201, -0.048246548, 0.058762506, 0.036662634) * g_5;
|
||||
result += mat4(-0.023527982, -0.0028001352, 0.047800142, 0.09616409, 0.049143843, 0.030836122, 0.057244994, 0.025672587, 0.027565151, 0.039868724, 0.045296676, 0.04623187, -0.124759234, -0.14106254, -0.06337279, -0.076839216) * g_6;
|
||||
result += mat4(-0.0911771, -0.064436875, -0.05308137, -0.022082496, -0.0040269364, 0.0014464161, -0.0029555515, 0.016098293, -0.026650434, -0.014081368, -0.06747348, -0.05481826, 0.097423114, 0.08620988, -0.01607732, -0.015440677) * g_7;
|
||||
result += mat4(-0.014001735, -0.015001655, -0.013250577, -0.009930805, 0.04885879, 0.07092224, 0.025783395, 0.03792237, -0.04332465, -0.06244993, -0.046748653, -0.07132349, -0.0053951666, -0.016514057, 0.023807624, 0.044013456) * g_8;
|
||||
result += mat4(-0.009097996, -0.016898679, -0.05043909, -0.063178614, -0.016210863, -0.02157998, -0.02654472, -0.042961173, 0.012103852, 0.019015301, 0.02492281, 0.03389976, 0.015276502, 0.009577683, 0.04132527, -0.00070621347) * g_9;
|
||||
result += mat4(-0.0057500796, 0.00728164, -0.003422421, 0.0038979584, -0.03127353, -0.019125199, -0.012988815, -0.031890683, 0.09352588, 0.019210607, 0.09824038, 0.016637104, 0.010692808, 0.022393884, 0.008312123, 0.014120716) * g_10;
|
||||
result += mat4(0.013895599, 0.023097904, 0.009370535, 0.014099512, 0.0124661345, -0.015076684, 0.03287286, 0.005912471, -0.03944815, -0.020340785, -0.06822037, -0.059383288, 0.03634978, 0.007832939, -0.007142306, -0.0061968984) * g_11;
|
||||
result += mat4(0.033002097, 0.0516016, -0.021056438, 0.005715988, -0.02223013, -0.007962324, -0.024417123, -0.0014790733, 0.002167189, 0.00043749413, -0.007284963, -0.0027283782, 0.026238248, 0.01756047, 0.008969755, 0.014201024) * g_12;
|
||||
result += mat4(0.011576685, 0.02087598, 0.0026766327, -0.0041780816, -0.05277701, -0.05412841, -0.05958835, -0.050426245, -0.00662945, -0.021645393, 0.03423904, -0.0064581474, -0.030403355, 0.018391011, -0.026089542, -0.0051510665) * g_13;
|
||||
result += mat4(-0.046202097, -0.0066081425, -0.03698851, 0.0034165455, -0.011859245, -0.020945566, -0.0028196946, -0.010053285, -0.011400397, 0.030595876, -0.018915813, 0.006780077, -0.060040582, -0.009586898, -0.004477886, 0.011279908) * g_14;
|
||||
result += mat4(-0.028692413, -0.032535568, 0.0017473884, 0.02207169, 0.0192618, 0.008956797, -0.0033381556, 0.006326402, 0.0169569, 0.041449737, -0.02611751, 0.0006410355, 0.006233776, 0.0008467914, 0.011884985, 0.009222136) * g_15;
|
||||
result += mat4(0.017076496, -0.0045380928, 0.03444613, -0.009804047, -0.004829834, -0.004889702, 0.0057807956, 0.0015014127, 0.03458368, -0.0035773432, -0.007769679, -0.032449644, -0.021396799, -0.017612215, -0.012764735, -0.025224172) * g_16;
|
||||
result += mat4(-0.011824532, 0.02335273, 0.00764845, 0.019215155, 0.022186808, 0.0066053392, 0.0071694753, -0.0036117272, 0.032144524, 0.05025988, 0.03982363, 0.052400436, -0.10555114, -0.03809396, -0.05334183, -0.05524487) * g_17;
|
||||
result += mat4(-0.024599254, 0.058805298, 0.00069874676, 0.06263439, -0.018460508, -0.053566024, -0.0022889362, -0.035818785, -0.0135854995, -0.015712813, 0.0012080368, 0.005957637, 0.009450094, 0.03186346, 0.059969924, 0.057706963) * g_18;
|
||||
result += mat4(0.026783831, 0.05475865, 0.027565574, 0.06032707, -0.0015639095, 0.024381682, -0.010199071, 0.037544634, 0.039889377, 0.03318851, -0.016529158, -0.0343188, 0.045666486, 0.021665907, 0.042189375, 0.02444145) * g_19;
|
||||
result += mat4(0.03791853, 0.043746054, 0.056224477, 0.05098111, 0.075256795, 0.074653305, 0.116220035, 0.01853866, -0.04133627, -0.009134169, -0.0420953, -0.05210053, -0.021748418, 0.004422131, -0.05422814, -0.035721727) * g_20;
|
||||
result += mat4(0.013814317, 0.03149986, -0.004971173, 0.04782029, -0.01693027, -0.017984565, 0.019328078, 0.008521426, 0.0845641, -0.027555496, 0.08150416, -0.04623306, 0.16494128, 0.09300831, 0.074097835, 0.0627848) * g_21;
|
||||
result += mat4(-0.10307174, -0.112654425, -0.005589254, -0.0062108496, -0.012491583, 0.011512013, -0.03142282, -0.023683488, -0.099848576, -0.031290524, -0.07236223, -0.037460987, 0.008760208, 0.1473594, -0.009216949, 0.07251379) * g_22;
|
||||
result += mat4(-0.04915367, -0.07121096, -0.06572174, -0.10967046, 0.019548079, 0.023992533, -0.019842865, 0.012366459, -0.07207817, -0.04237792, -0.054463565, -0.015374731, -0.092071235, -0.020860313, -0.054475963, -0.02303954) * g_23;
|
||||
result += mat4(0.04160816, -0.118427366, -0.08661791, 0.12787233, -0.01990174, 0.0012960634, -0.016121056, 0.031429946, -0.06830865, -0.057132352, -0.0022302791, 0.03845933, -0.026981276, -0.063532256, 0.011805961, -0.009616678) * g_24;
|
||||
result += mat4(0.07094465, -0.022284096, 0.060676746, 0.042626668, 0.011207256, -0.14960343, 0.05866539, -0.12742221, -0.021092903, -0.039463162, -0.07879986, -0.10232898, -0.026127055, -0.038111385, 0.019167708, 0.032637425) * g_25;
|
||||
result += mat4(-0.014270794, 0.07157703, 0.013714203, -0.047801998, 0.0060221693, 0.022788104, 0.10630103, -0.09606649, 0.12690987, -0.017079826, -0.0077072172, -0.082584485, 0.13256006, 0.16012523, -0.10966099, -0.07927409) * g_26;
|
||||
result += mat4(-0.17171615, 0.12114435, -0.10746857, -0.0074188868, 0.07854815, 0.07759372, 0.04310874, 0.051465522, -0.05963588, -0.014506484, 0.15522978, 0.18746643, -0.03845241, -0.0489534, 0.05837339, 0.032978524) * g_27;
|
||||
result += vec4(0.05825913, 0.051491056, 0.038389463, 0.03321517);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Conv-4x1x1x112
|
||||
//!HOOK MAIN
|
||||
//!BIND conv2d_tf
|
||||
//!BIND conv2d_tf1
|
||||
//!BIND conv2d_1_tf
|
||||
//!BIND conv2d_1_tf1
|
||||
//!BIND conv2d_2_tf
|
||||
//!BIND conv2d_2_tf1
|
||||
//!BIND conv2d_3_tf
|
||||
//!BIND conv2d_3_tf1
|
||||
//!BIND conv2d_4_tf
|
||||
//!BIND conv2d_4_tf1
|
||||
//!BIND conv2d_5_tf
|
||||
//!BIND conv2d_5_tf1
|
||||
//!BIND conv2d_6_tf
|
||||
//!BIND conv2d_6_tf1
|
||||
//!SAVE conv2d_last_tf2
|
||||
//!WIDTH conv2d_tf.w
|
||||
//!HEIGHT conv2d_tf.h
|
||||
//!COMPONENTS 4
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
#define g_0 (max((conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_1 (max((conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_2 (max(-(conv2d_tf_tex(conv2d_tf_pos)), 0.0))
|
||||
#define g_3 (max(-(conv2d_tf1_tex(conv2d_tf1_pos)), 0.0))
|
||||
#define g_4 (max((conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_5 (max((conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_6 (max(-(conv2d_1_tf_tex(conv2d_1_tf_pos)), 0.0))
|
||||
#define g_7 (max(-(conv2d_1_tf1_tex(conv2d_1_tf1_pos)), 0.0))
|
||||
#define g_8 (max((conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_9 (max((conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_10 (max(-(conv2d_2_tf_tex(conv2d_2_tf_pos)), 0.0))
|
||||
#define g_11 (max(-(conv2d_2_tf1_tex(conv2d_2_tf1_pos)), 0.0))
|
||||
#define g_12 (max((conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_13 (max((conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_14 (max(-(conv2d_3_tf_tex(conv2d_3_tf_pos)), 0.0))
|
||||
#define g_15 (max(-(conv2d_3_tf1_tex(conv2d_3_tf1_pos)), 0.0))
|
||||
#define g_16 (max((conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_17 (max((conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_18 (max(-(conv2d_4_tf_tex(conv2d_4_tf_pos)), 0.0))
|
||||
#define g_19 (max(-(conv2d_4_tf1_tex(conv2d_4_tf1_pos)), 0.0))
|
||||
#define g_20 (max((conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_21 (max((conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_22 (max(-(conv2d_5_tf_tex(conv2d_5_tf_pos)), 0.0))
|
||||
#define g_23 (max(-(conv2d_5_tf1_tex(conv2d_5_tf1_pos)), 0.0))
|
||||
#define g_24 (max((conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_25 (max((conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
#define g_26 (max(-(conv2d_6_tf_tex(conv2d_6_tf_pos)), 0.0))
|
||||
#define g_27 (max(-(conv2d_6_tf1_tex(conv2d_6_tf1_pos)), 0.0))
|
||||
vec4 hook() {
|
||||
vec4 result = mat4(0.2006987, 0.17832398, 0.26342955, 0.23500517, -0.012297829, -0.009008417, -0.039950736, -0.039973143, 0.34800097, 0.32196492, 0.30505183, 0.29214156, -0.21410535, -0.21166423, -0.16437815, -0.19172792) * g_0;
|
||||
result += mat4(-0.008804151, -0.07085123, 0.013577994, -0.05192605, -0.08981402, -0.14702585, -0.09145975, -0.14835288, -0.15882517, -0.14785844, -0.2381482, -0.22867912, 0.010898514, 0.031957507, 0.040597558, 0.078252345) * g_1;
|
||||
result += mat4(-0.21658613, -0.1803885, -0.25954962, -0.20839214, -0.09597461, -0.09222647, -0.03909875, -0.03456191, -0.19723509, -0.16976605, -0.2041716, -0.1751425, 0.22901416, 0.24922715, 0.1800083, 0.23346905) * g_2;
|
||||
result += mat4(0.110020064, 0.103858806, 0.052446555, 0.061105963, 0.032901537, 0.07140097, 0.11518793, 0.13860466, 0.13930707, 0.12712196, 0.19071707, 0.18399614, -0.08036458, -0.07349171, 0.021504594, 0.0024937368) * g_3;
|
||||
result += mat4(0.059065036, 0.00698257, -0.099622436, -0.15676253, -0.10942482, -0.04869624, -0.13654554, -0.07341863, -0.014169851, -0.06390744, 0.016093008, -0.04540248, 0.29041344, 0.24451919, 0.26292154, 0.22136512) * g_4;
|
||||
result += mat4(0.107946776, 0.097849295, 0.10266876, 0.09360328, 0.08931344, 0.08896482, 0.046495322, 0.044040844, -0.020361643, -0.030911373, 0.026598722, 0.019815676, -0.072677925, -0.042410247, 0.14127749, 0.13434973) * g_5;
|
||||
result += mat4(-0.08809133, -0.03476601, 0.06420393, 0.14691353, 0.09296839, 0.06162562, 0.10992992, 0.0615685, 0.0168736, 0.06520281, 0.020010693, 0.046929173, -0.2219495, -0.21249783, -0.14622301, -0.14599061) * g_6;
|
||||
result += mat4(-0.13251069, -0.08977477, -0.08930347, -0.045490693, -0.10980218, -0.09510885, -0.07299872, -0.064053826, 0.011365247, 0.014091111, -0.054976214, -0.056936122, 0.10148144, 0.07451642, -0.08138598, -0.10161657) * g_7;
|
||||
result += mat4(-0.0075518745, -0.005738622, -0.007577811, -0.00032088626, 0.032614008, 0.04858922, 0.00054855715, 0.011565026, -0.022675224, -0.034442738, -0.03580643, -0.05069376, -0.0020376542, -0.01505518, 0.019388825, 0.03746554) * g_8;
|
||||
result += mat4(-0.011413172, -0.016877454, -0.048923567, -0.055012885, -0.007709447, -0.016109072, -0.047132388, -0.07146396, 0.002604099, 0.00014681708, 0.03429465, 0.043265607, 0.029014807, 0.03337814, 0.07582056, 0.041660666) * g_9;
|
||||
result += mat4(-0.020768544, -0.014378527, -0.01999972, -0.01385916, -0.012264676, -0.009959511, 0.0119015165, -0.016787319, 0.07266734, -0.0029914333, 0.08549183, 0.004367342, 0.008236065, 0.020370748, 0.0043428927, 0.007301017) * g_10;
|
||||
result += mat4(0.011654731, 0.025318999, -0.0029306612, 0.007426217, -0.00010868774, -0.020845588, 0.041991003, 0.024147986, -0.030741083, -0.012328637, -0.06617428, -0.06103115, 0.010491518, -0.013338451, -0.04666634, -0.046481613) * g_11;
|
||||
result += mat4(0.0268538, 0.043785956, -0.01799385, 0.008743307, -0.013197458, -0.015049436, -0.017189734, -0.0047999253, -0.00059730676, -0.0008936153, -0.016006093, -0.0073406673, 0.014875853, 0.011491735, 9.819833e-05, 0.0073417514) * g_12;
|
||||
result += mat4(0.019930955, 0.027112626, 0.01307941, 0.005268897, -0.060213763, -0.050415818, -0.069006495, -0.051405095, 0.0036414433, -0.008606397, 0.037427194, -0.0018103109, -0.037434716, 0.010187546, -0.026227329, -0.0033639795) * g_13;
|
||||
result += mat4(-0.03634798, 0.0007093891, -0.026819145, 0.009025687, -0.01750318, -0.020098133, -0.0063864207, -0.006606755, 0.0008565766, 0.028647956, -0.0024974607, 0.015250743, -0.048884176, -0.004310685, -0.0010757383, 0.00974984) * g_14;
|
||||
result += mat4(-0.031253602, -0.031743724, -0.009083253, 0.0145388115, 0.02048611, 0.0058071036, -0.0038228377, 0.00049654936, 0.0059105973, 0.03437731, -0.025785418, 0.004187733, 0.009980489, -4.08268e-05, 0.009384428, 0.0019492983) * g_15;
|
||||
result += mat4(0.012587245, -0.0032654977, 0.029739188, -0.009440694, -0.0018237908, -0.0080032, 0.010499013, 0.0012466761, 0.03461923, -0.0060207327, -0.008771263, -0.034545746, -0.015023473, -0.008901684, -0.011490296, -0.01976464) * g_16;
|
||||
result += mat4(-0.009444331, 0.020809013, 0.009985801, 0.020350901, 0.013234775, 0.004382635, -0.0007761826, -0.005247294, 0.034115106, 0.05190378, 0.039124765, 0.050993033, -0.0898732, -0.030428126, -0.044204578, -0.052484997) * g_17;
|
||||
result += mat4(-0.020434443, 0.053520404, 0.0007571144, 0.05895061, -0.018991265, -0.043982152, -0.004035192, -0.025452444, -0.012197152, -0.013770753, 0.0012919102, 0.003996682, 0.0056104586, 0.025686186, 0.05128293, 0.05105745) * g_18;
|
||||
result += mat4(0.030201769, 0.052521482, 0.029641917, 0.05559941, 0.0018870027, 0.020112835, -0.0043867202, 0.035877172, 0.02961142, 0.02163634, -0.027972858, -0.040669747, 0.03393723, 0.013455979, 0.03313782, 0.01968004) * g_19;
|
||||
result += mat4(0.034817442, 0.04045217, 0.054816365, 0.05092461, 0.06600807, 0.062576495, 0.09923777, 0.006663677, -0.039958935, -0.010009866, -0.041522443, -0.04959681, -0.020962957, 0.003845031, -0.04910384, -0.03233655) * g_20;
|
||||
result += mat4(0.015433112, 0.028965838, -0.0055138534, 0.042267464, -0.012690953, -0.009424165, 0.017896382, 0.01186686, 0.07231686, -0.038834292, 0.07033086, -0.052548733, 0.15721905, 0.09334892, 0.07676042, 0.06701375) * g_21;
|
||||
result += mat4(-0.09797534, -0.11201098, -0.0037222446, -0.008105951, -0.01152357, 0.012165641, -0.029051905, -0.021293389, -0.09600697, -0.028819272, -0.069084235, -0.035421908, 0.0054322914, 0.14168966, -0.0200274, 0.06505187) * g_22;
|
||||
result += mat4(-0.05034882, -0.06622497, -0.062471002, -0.100628324, 0.018115615, 0.019867867, -0.018836644, 0.007562053, -0.06317378, -0.034458403, -0.047243826, -0.009989589, -0.08270121, -0.018645251, -0.05160367, -0.023690399) * g_23;
|
||||
result += mat4(0.03897899, -0.10862529, -0.081805214, 0.1202324, -0.021866674, -0.00041882638, -0.018235246, 0.027227063, -0.0656312, -0.053432237, -0.0029235696, 0.03549672, -0.022848906, -0.057047505, 0.013400545, -0.0072439364) * g_24;
|
||||
result += mat4(0.06879516, -0.018637763, 0.058062725, 0.041045032, 0.011702424, -0.13693465, 0.05674195, -0.11679955, -0.022940686, -0.03856922, -0.07531371, -0.09692582, -0.019870926, -0.032572743, 0.026138868, 0.037639033) * g_25;
|
||||
result += mat4(-0.015270301, 0.06478719, 0.011016518, -0.04533957, 0.00688319, 0.024815995, 0.10159924, -0.08467507, 0.11939162, -0.01939453, -0.0058689644, -0.077881604, 0.118726775, 0.14489114, -0.10831982, -0.07972515) * g_26;
|
||||
result += mat4(-0.16734359, 0.10685446, -0.102714166, -0.010225307, 0.07306756, 0.07014447, 0.040464073, 0.04688462, -0.05489714, -0.01525318, 0.14690581, 0.17514132, -0.03250648, -0.03688211, 0.05047889, 0.03078089) * g_27;
|
||||
result += vec4(0.06614842, 0.045779686, 0.032838725, 0.017085627);
|
||||
return result;
|
||||
}
|
||||
//!DESC Anime4K-v3.2-Upscale-Denoise-CNN-x2-(VL)-Depth-to-Space
|
||||
//!HOOK MAIN
|
||||
//!BIND MAIN
|
||||
//!BIND conv2d_last_tf
|
||||
//!BIND conv2d_last_tf1
|
||||
//!BIND conv2d_last_tf2
|
||||
//!SAVE MAIN
|
||||
//!WIDTH conv2d_last_tf.w 2 *
|
||||
//!HEIGHT conv2d_last_tf.h 2 *
|
||||
//!WHEN OUTPUT.w MAIN.w / 1.200 > OUTPUT.h MAIN.h / 1.200 > *
|
||||
vec4 hook() {
|
||||
vec2 f0 = fract(conv2d_last_tf_pos * conv2d_last_tf_size);
|
||||
ivec2 i0 = ivec2(f0 * vec2(2.0));
|
||||
float c0 = conv2d_last_tf_tex((vec2(0.5) - f0) * conv2d_last_tf_pt + conv2d_last_tf_pos)[i0.y * 2 + i0.x];
|
||||
vec2 f1 = fract(conv2d_last_tf1_pos * conv2d_last_tf1_size);
|
||||
ivec2 i1 = ivec2(f1 * vec2(2.0));
|
||||
float c1 = conv2d_last_tf1_tex((vec2(0.5) - f1) * conv2d_last_tf1_pt + conv2d_last_tf1_pos)[i1.y * 2 + i1.x];
|
||||
vec2 f2 = fract(conv2d_last_tf2_pos * conv2d_last_tf2_size);
|
||||
ivec2 i2 = ivec2(f2 * vec2(2.0));
|
||||
float c2 = conv2d_last_tf2_tex((vec2(0.5) - f2) * conv2d_last_tf2_pt + conv2d_last_tf2_pos)[i2.y * 2 + i2.x];
|
||||
float c3 = c2;
|
||||
return vec4(c0, c1, c2, c3) + MAIN_tex(MAIN_pos);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 bloc97
|
||||
|
||||
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.
|
||||
@@ -1,29 +1,22 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
|
||||
import 'src/screens/connect_screen.dart';
|
||||
import 'src/screens/session_screen.dart';
|
||||
import 'src/screens/welcome_screen.dart';
|
||||
import 'src/state/session_state.dart';
|
||||
import 'src/screens/home/ui.dart';
|
||||
import 'src/shell/app_shell.dart';
|
||||
import 'src/widgets/app_keys.dart';
|
||||
import 'src/widgets/app_menu.dart';
|
||||
|
||||
class WatchTogetherApp extends StatelessWidget {
|
||||
const WatchTogetherApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final session = SessionState.instance;
|
||||
return MaterialApp(
|
||||
title: 'Watch Together',
|
||||
theme: ThemeData.dark(),
|
||||
home: SignalBuilder(
|
||||
builder: (context) {
|
||||
return switch (session.route.value) {
|
||||
AppRoute.welcome => const WelcomeScreen(),
|
||||
AppRoute.connect => const ConnectScreen(),
|
||||
AppRoute.session => const SessionScreen(),
|
||||
};
|
||||
},
|
||||
),
|
||||
title: appName,
|
||||
// Material's own menus (the player's track menus, sort) wear the
|
||||
// app menu's surface.
|
||||
theme: AppMenuStyle.theme(ThemeData.dark()),
|
||||
shortcuts: appShortcuts,
|
||||
home: const AppKeys(child: AppShell()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,30 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_ce_flutter/hive_flutter.dart';
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'app.dart';
|
||||
import 'src/state/session_state.dart';
|
||||
import 'src/update/updater.dart';
|
||||
import 'src/app/app_graph.dart';
|
||||
import 'src/files/thumbnails.dart' show thumbnailPlayers;
|
||||
import 'src/platform/app_log.dart';
|
||||
import 'src/platform/app_shutdown.dart' show closeAppWith;
|
||||
import 'src/platform/desktop/desktop_app_dirs.dart';
|
||||
import 'src/platform/desktop_entry.dart';
|
||||
import 'src/platform/smoke.dart';
|
||||
import 'src/screens/home/ui.dart';
|
||||
import 'src/session/app_events.dart' show UpdateAvailable;
|
||||
import 'src/state/settings.dart';
|
||||
import 'src/update/update_controller.dart' show UpdateController, UpdatePhase, launchArgs;
|
||||
|
||||
Future<void> main(List<String> args) async {
|
||||
launchArgs = List.unmodifiable(args);
|
||||
if (args.contains('--upgrade')) {
|
||||
exitCode = await runUpgrade();
|
||||
exit(exitCode);
|
||||
}
|
||||
initLogging();
|
||||
if (args.contains('--headless')) {
|
||||
await runHeadless(args);
|
||||
return;
|
||||
}
|
||||
FlutterError.onError = (details) {
|
||||
debugPrint('FLUTTER ERROR: ${details.exceptionAsString()}\n${details.stack}');
|
||||
FlutterError.presentError(details);
|
||||
@@ -38,32 +43,57 @@ Future<void> main(List<String> args) async {
|
||||
),
|
||||
);
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
await windowManager.ensureInitialized();
|
||||
const windowOptions = WindowOptions(
|
||||
size: Size(1280, 720),
|
||||
minimumSize: Size(160, 90),
|
||||
center: true,
|
||||
backgroundColor: Color(0xFF000000),
|
||||
titleBarStyle: TitleBarStyle.hidden,
|
||||
title: 'Watch Together',
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
final dirs = await const DesktopAppDirs().resolve();
|
||||
await startAppLogging(dirs);
|
||||
Hive.init(dirs.hive);
|
||||
await AppSettings.instance.ensureLoaded();
|
||||
// The composition root: every system, made once.
|
||||
final graph = AppGraph.build();
|
||||
final ports = graph.ports;
|
||||
// Close button / Alt+F4: the orderly close ([shutDownApp]), so others
|
||||
// see "left", your server shuts down and no player outlives the engine.
|
||||
final close = closeAppWith(graph);
|
||||
await ports.shell.start(
|
||||
title: dirs.profile == null ? appName : '$appName [${dirs.profile}]', onCloseRequest: () => close());
|
||||
// Focus, minimise and restore feed auto sit-out and the Notifier (in
|
||||
// the background, notices go out as system notifications).
|
||||
ports.shell.watchActivity((a) {
|
||||
graph.coordinator.windowActivity(a);
|
||||
graph.notifier.window = a;
|
||||
});
|
||||
await Hive.initFlutter();
|
||||
try {
|
||||
await SessionState.instance.loadForm();
|
||||
await graph.forms.load();
|
||||
} catch (e, st) {
|
||||
debugPrint('load connect form failed: $e\n$st');
|
||||
}
|
||||
MediaKit.ensureInitialized();
|
||||
runApp(const WatchTogetherApp());
|
||||
}
|
||||
|
||||
Future<void> runHeadless(List<String> args) async {
|
||||
final session = SessionState.instance;
|
||||
await session.startHeadless(args);
|
||||
await ProcessSignal.sigint.watch().first;
|
||||
await session.stopServer();
|
||||
// The library's matches, pins and offsets, and the watch history
|
||||
// (device-owned).
|
||||
unawaited(graph.library.ensureLoaded());
|
||||
unawaited(graph.watch.history.ensureLoaded());
|
||||
ports.players.init();
|
||||
thumbnailPlayers = ports.players;
|
||||
// yt-dlp for web page links: downloaded on first run, kept current.
|
||||
ports.links.warmUp();
|
||||
// Linux: the launcher entry and icon Wayland needs (release installs).
|
||||
unawaited(installDesktopEntry());
|
||||
// A found update is an event too (the band shows it).
|
||||
final updates = UpdateController.instance;
|
||||
updates.status.addListener(() {
|
||||
final s = updates.status.value;
|
||||
final version = s.manifest?.version;
|
||||
if (s.phase == UpdatePhase.available && version != null) {
|
||||
graph.notifier.notify(UpdateAvailable(version));
|
||||
}
|
||||
});
|
||||
runApp(AppScope(graph: graph, child: const WatchTogetherApp()));
|
||||
// CI's close smoke run: open a file, play, close (see smoke.dart).
|
||||
final smoke = smokeMedia;
|
||||
if (smoke != null) {
|
||||
unawaited(WidgetsBinding.instance.endOfFrame.then((_) => runSmoke(graph, smoke)));
|
||||
}
|
||||
// Home: your own server, quietly (only this app can reach it until
|
||||
// Invite).
|
||||
unawaited(graph.navigation.start());
|
||||
// The sound device opens once the window is up, not on the first sound.
|
||||
Future.delayed(const Duration(seconds: 2), graph.sfx.warmUp);
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import '../jellyfin/accounts.dart';
|
||||
import '../library/library_store.dart';
|
||||
import '../library/local_next.dart';
|
||||
import '../library/show_matcher.dart';
|
||||
import '../platform/app_log.dart' show appLogDir;
|
||||
import '../platform/desktop/desktop_ports.dart';
|
||||
import '../platform/ports/ports.dart';
|
||||
import '../schedule/anilist.dart';
|
||||
import '../schedule/animeflow.dart';
|
||||
import '../screens/home/health_probe.dart';
|
||||
import '../session/connection.dart' show Connection;
|
||||
import '../session/identity.dart' show ClientIdentity, Profile;
|
||||
import '../session/navigation.dart';
|
||||
import '../session/notifier.dart';
|
||||
import '../session/session_coordinator.dart';
|
||||
import '../session/your_server.dart';
|
||||
import '../sfx/sfx.dart';
|
||||
import '../sfx/sound_bank.dart';
|
||||
import '../sfx/synth_sfx.dart';
|
||||
import '../state/connect_prefs.dart';
|
||||
import '../state/settings.dart';
|
||||
import '../watch/watch_history.dart';
|
||||
import '../watch/watch_tracker.dart';
|
||||
|
||||
/// The composition root: builds the app's systems once (in `main`), wires
|
||||
/// them through their constructors and disposes them. No logic and no
|
||||
/// signals of its own. Widgets reach it through [AppScope].
|
||||
class AppGraph {
|
||||
/// The platform (window, links, folders, yt-dlp, notifications).
|
||||
final Ports ports;
|
||||
|
||||
/// Owns the app's audio device ([SynthSfx.dispose] on close).
|
||||
final SynthSfx sfx;
|
||||
|
||||
/// Every toast, sound, system notification and activity-log line.
|
||||
final Notifier notifier;
|
||||
|
||||
/// The link to whichever server this app is in.
|
||||
final Connection connection;
|
||||
|
||||
final SessionCoordinator coordinator;
|
||||
|
||||
/// The connect form and recent servers.
|
||||
final ConnectStore forms;
|
||||
|
||||
/// This app's own server, alive for the whole run.
|
||||
final YourServer yourServer;
|
||||
|
||||
/// Home (your server) or a friend's.
|
||||
final Navigation navigation;
|
||||
|
||||
/// The library's matches (L2): local shows to AniList, pins, offsets.
|
||||
final ShowMatcher library;
|
||||
|
||||
/// Watch tracking and the device's watch history (D3).
|
||||
final WatchTracker watch;
|
||||
|
||||
AppGraph._({
|
||||
required this.ports,
|
||||
required this.sfx,
|
||||
required this.notifier,
|
||||
required this.connection,
|
||||
required this.coordinator,
|
||||
required this.forms,
|
||||
required this.yourServer,
|
||||
required this.navigation,
|
||||
required this.library,
|
||||
required this.watch,
|
||||
});
|
||||
|
||||
/// The desktop app's graph. Tests pass their own [ports], [identity]
|
||||
/// (default: the install's stored one), [healthGet] and server starter.
|
||||
factory AppGraph.build({
|
||||
Ports? ports,
|
||||
ClientIdentity? identity,
|
||||
HealthGetter healthGet = defaultHealthGet,
|
||||
ServerStarter? serverStarter,
|
||||
JellyfinAccounts? jellyfin,
|
||||
ShowMatcher? library,
|
||||
WatchHistory? history,
|
||||
}) {
|
||||
final p = ports ?? desktopPorts();
|
||||
final settings = AppSettings.instance;
|
||||
final sfx = SynthSfx(
|
||||
volume: () => settings.soundVolume.peek(),
|
||||
// A nudge is an explicit poke: it ignores its switch (not the volume).
|
||||
enabled: (k) => k == SfxKind.nudge || !settings.soundsOff.peek().contains(k.name),
|
||||
presetFor: soundPresetFor,
|
||||
);
|
||||
final notifier = Notifier(
|
||||
sfx: sfx,
|
||||
attention: p.shell.requestAttention,
|
||||
system: p.notifications,
|
||||
focusWindow: p.shell.focus,
|
||||
prefs: () => settings.notifyPrefs,
|
||||
);
|
||||
final connection = Connection(notify: notifier.notify, identity: identity ?? ClientIdentity.stored());
|
||||
// Device-owned: the watch history box.
|
||||
final watch = WatchTracker(history: history ?? WatchHistory());
|
||||
final coordinator = SessionCoordinator(
|
||||
notifier: notifier,
|
||||
connection: connection,
|
||||
ytDlp: p.links,
|
||||
jellyfin: jellyfin,
|
||||
players: p.players,
|
||||
settings: settings,
|
||||
watch: watch);
|
||||
// Device-owned: the library box; AnimeFlow's runs when signed in.
|
||||
final matcher = library ??
|
||||
ShowMatcher(
|
||||
store: HiveLibraryStore(),
|
||||
aniList: AniListClient(),
|
||||
flow: AnimeFlowLookup(AnimeFlowClient.fromAccounts(coordinator.jellyfin)),
|
||||
);
|
||||
coordinator
|
||||
..fileRef = matcher.refForPath
|
||||
..nextFile = LocalNextFinder(matcher: matcher, scan: p.folders.scan).nextAfter;
|
||||
final forms = ConnectStore();
|
||||
final yourServer = YourServer(
|
||||
forms: forms,
|
||||
jellyfin: jellyfin,
|
||||
// The app's yt-dlp folder; '' (the server's own default) when the
|
||||
// app-support folder is not available.
|
||||
ytDlpDir: () async {
|
||||
try {
|
||||
return (await p.links.ytDlp).dir;
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
logDir: () => appLogDir,
|
||||
starter: serverStarter,
|
||||
);
|
||||
final navigation = Navigation(
|
||||
coordinator: coordinator,
|
||||
yourServer: yourServer,
|
||||
forms: forms,
|
||||
healthGet: healthGet,
|
||||
);
|
||||
// The profile keeps its name in the connect form and pushes changes
|
||||
// to whichever server this app is in.
|
||||
Profile.instance
|
||||
..forms = forms
|
||||
..push = ({String? name, String? avatar}) {
|
||||
if (navigation.online.peek()) coordinator.updateProfile(name: name, avatar: avatar);
|
||||
};
|
||||
return AppGraph._(
|
||||
ports: p,
|
||||
sfx: sfx,
|
||||
notifier: notifier,
|
||||
connection: connection,
|
||||
coordinator: coordinator,
|
||||
forms: forms,
|
||||
yourServer: yourServer,
|
||||
navigation: navigation,
|
||||
library: matcher,
|
||||
watch: watch,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
navigation.dispose();
|
||||
await coordinator.dispose();
|
||||
await watch.dispose();
|
||||
await yourServer.stop();
|
||||
await sfx.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// The sound set [kind] plays from: its own pick in Settings, else the
|
||||
/// overall one.
|
||||
SoundPreset soundPresetFor(SfxKind kind) {
|
||||
final s = AppSettings.instance;
|
||||
final name = s.soundPresetFor.peek()[kind.name] ?? s.soundPreset.peek();
|
||||
return SoundPreset.values.where((p) => p.name == name).firstOrNull ?? defaultPreset;
|
||||
}
|
||||
|
||||
/// Hands the [AppGraph] to every widget below: `AppScope.of(context)`.
|
||||
/// The graph never changes, so reading it registers no dependency (safe
|
||||
/// in `initState`).
|
||||
class AppScope extends InheritedWidget {
|
||||
final AppGraph graph;
|
||||
const AppScope({super.key, required this.graph, required super.child});
|
||||
|
||||
static AppGraph of(BuildContext context) {
|
||||
final scope = context.getInheritedWidgetOfExactType<AppScope>();
|
||||
assert(scope != null, 'no AppScope above this widget');
|
||||
return scope!.graph;
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(AppScope oldWidget) => !identical(graph, oldWidget.graph);
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sync_relay_core/core.dart' show JellyfinStreamType;
|
||||
|
||||
import '../jellyfin/track_prefs.dart' show MpvTrack;
|
||||
import '../playback/media_marks.dart';
|
||||
import '../shaders/shader_menu.dart';
|
||||
import '../shell/mark_problem.dart';
|
||||
import '../state/settings.dart';
|
||||
import '../widgets/app_menu.dart';
|
||||
import '../widgets/copy_open.dart';
|
||||
import 'frame.dart';
|
||||
import 'model/controls_layout.dart';
|
||||
import 'model/controls_model.dart';
|
||||
import 'player_settings.dart';
|
||||
|
||||
// The controls' menus, shared by both skins: the track and chapter lists
|
||||
// and the ⚙ menu, all on the app's menu (`showAppMenu`), anchored on the
|
||||
// button that opens them. Each keeps the controls up while open.
|
||||
|
||||
/// How many tracks of [type] there are.
|
||||
int trackCount(List<MpvTrack> tracks, JellyfinStreamType type) => tracks.where((t) => t.type == type).length;
|
||||
|
||||
/// The audio or subtitle tracks ("Japanese · E-AC3 2.0 · title"), mpv's
|
||||
/// selection checked; subtitles start with Off.
|
||||
List<AppMenuItem<TrackPick>> trackMenuItems(JellyfinStreamType type, List<MpvTrack> tracks) {
|
||||
final audio = type == JellyfinStreamType.audio;
|
||||
final list = tracks.where((t) => t.type == type).toList();
|
||||
return [
|
||||
if (!audio)
|
||||
AppMenuItem(
|
||||
key: const ValueKey('track-off'),
|
||||
value: (aid: null, sid: null, subtitlesOff: true),
|
||||
label: 'Off',
|
||||
checked: !list.any((t) => t.selected),
|
||||
),
|
||||
if (audio && list.isEmpty)
|
||||
const AppMenuItem(value: (aid: null, sid: null, subtitlesOff: false), label: 'None', enabled: false),
|
||||
for (final t in list)
|
||||
AppMenuItem(
|
||||
key: ValueKey('track-${t.type.name}-${t.id}'),
|
||||
value: audio ? (aid: t.id, sid: null, subtitlesOff: false) : (aid: null, sid: t.id, subtitlesOff: false),
|
||||
label: t.label,
|
||||
checked: t.selected,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/// Chapters with their start times, the playing one checked.
|
||||
List<AppMenuItem<MediaChapter>> chapterMenuItems(List<MediaChapter> chapters, int? current) => [
|
||||
for (final c in chapters)
|
||||
AppMenuItem(
|
||||
key: ValueKey('chapter-${c.index}'),
|
||||
value: c,
|
||||
label: c.title.isEmpty ? 'Chapter ${c.index + 1}' : c.title,
|
||||
hint: formatClock(c.start),
|
||||
checked: c.index == current,
|
||||
),
|
||||
];
|
||||
|
||||
Future<T?> _menu<T>(BuildContext context, PlayerControlsModel model, List<AppMenuItem<T>> items) async {
|
||||
model.menusOpen++;
|
||||
try {
|
||||
return await showAppMenu<T>(context, items: items);
|
||||
} finally {
|
||||
model.menusOpen--;
|
||||
}
|
||||
}
|
||||
|
||||
/// The audio or subtitle list; a pick is applied (and remembered).
|
||||
Future<void> openTrackMenu(BuildContext context, PlayerControlsModel model, JellyfinStreamType type) async {
|
||||
final pick = await _menu(context, model, trackMenuItems(type, model.tracks.peek()));
|
||||
if (pick != null) model.pickTrack(pick);
|
||||
}
|
||||
|
||||
/// The chapter list; a pick jumps there for everyone.
|
||||
Future<void> openChapterMenu(BuildContext context, PlayerControlsModel model) async {
|
||||
final pick = await _menu(context, model, chapterMenuItems(model.chapters.peek(), model.currentChapter.peek()));
|
||||
if (pick != null) model.pickChapter(pick);
|
||||
}
|
||||
|
||||
/// The ⚙ menu: every action that is not a bar button.
|
||||
Future<void> openControlsMenu(BuildContext context, PlayerControlsModel model) async {
|
||||
final s = AppSettings.instance;
|
||||
final shader = shaderShortLabel(s.shaderPreset.peek(), s.shaderQuality.peek()) ?? 'Off';
|
||||
final pick = await _menu(context, model, [
|
||||
for (final a in model.menu())
|
||||
AppMenuItem(
|
||||
key: ValueKey('controls-menu-${a.name}'),
|
||||
value: a,
|
||||
label: a.label,
|
||||
hint: a == ControlAction.shaders ? shader : a.hint,
|
||||
),
|
||||
]);
|
||||
if (pick != null && context.mounted) await runControlAction(context, model, pick);
|
||||
}
|
||||
|
||||
/// Runs a ⚙ menu action; [context] anchors what it opens next.
|
||||
Future<void> runControlAction(BuildContext context, PlayerControlsModel model, ControlAction action) async {
|
||||
switch (action) {
|
||||
case ControlAction.chapters:
|
||||
await openChapterMenu(context, model);
|
||||
case ControlAction.subtitles:
|
||||
await openTrackMenu(context, model, JellyfinStreamType.subtitle);
|
||||
case ControlAction.audio:
|
||||
await openTrackMenu(context, model, JellyfinStreamType.audio);
|
||||
case ControlAction.skipForward:
|
||||
model.skipForward();
|
||||
case ControlAction.shaders:
|
||||
model.menusOpen++;
|
||||
try {
|
||||
await ControlsFrame.holdWhile(
|
||||
context,
|
||||
() => showShaderMenu(context, renderMode: model.renderMode, onPick: model.pickShader),
|
||||
);
|
||||
} finally {
|
||||
model.menusOpen--;
|
||||
}
|
||||
case ControlAction.chat:
|
||||
model.toggleChat();
|
||||
case ControlAction.changeVideo:
|
||||
model.changeVideo();
|
||||
case ControlAction.copyLink:
|
||||
final link = model.link();
|
||||
if (link != null) await copyToClipboard(context, link, done: 'Link copied');
|
||||
case ControlAction.reload:
|
||||
model.reload();
|
||||
case ControlAction.markAllReady:
|
||||
model.markAllReady();
|
||||
case ControlAction.markProblem:
|
||||
await ControlsFrame.holdWhile(context, () => showMarkProblem(context));
|
||||
case ControlAction.playerSettings:
|
||||
await showPlayerSettings(context, renderMode: model.renderMode);
|
||||
case ControlAction.leave:
|
||||
model.leave();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// What keeps the player's controls up besides the mouse on them: the
|
||||
/// mouse on a floating element over the picture (a pill, a card, the
|
||||
/// status pill: [ControlsHoldRegion]) or an open popover. While anything
|
||||
/// holds, the controls stay up; on release they hide on their usual
|
||||
/// countdown. Both skins follow it (through `ControlsFrame`).
|
||||
class ControlsHold extends ChangeNotifier {
|
||||
final _by = <Object>{};
|
||||
bool _told = false;
|
||||
bool _queued = false;
|
||||
bool _disposed = false;
|
||||
|
||||
bool get held => _told;
|
||||
|
||||
/// [who] holds ([on]) or lets go. Listeners hear it in a microtask, never
|
||||
/// during a build or a dispose.
|
||||
void set(Object who, bool on) {
|
||||
if (on ? !_by.add(who) : !_by.remove(who)) return;
|
||||
if (_queued) return;
|
||||
_queued = true;
|
||||
scheduleMicrotask(() {
|
||||
_queued = false;
|
||||
if (_disposed) return;
|
||||
final now = _by.isNotEmpty;
|
||||
if (now == _told) return;
|
||||
_told = now;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// The mouse on [child] counts as the mouse on the controls: it holds
|
||||
/// [hold] while it is there.
|
||||
class ControlsHoldRegion extends StatefulWidget {
|
||||
final ControlsHold? hold;
|
||||
final Widget child;
|
||||
const ControlsHoldRegion({super.key, required this.hold, required this.child});
|
||||
|
||||
@override
|
||||
State<ControlsHoldRegion> createState() => _ControlsHoldRegionState();
|
||||
}
|
||||
|
||||
class _ControlsHoldRegionState extends State<ControlsHoldRegion> {
|
||||
@override
|
||||
void didUpdateWidget(ControlsHoldRegion oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.hold != widget.hold) oldWidget.hold?.set(this, false);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.hold?.set(this, false);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hold = widget.hold;
|
||||
if (hold == null) return widget.child;
|
||||
return MouseRegion(
|
||||
onEnter: (_) => hold.set(this, true),
|
||||
onExit: (_) => hold.set(this, false),
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/gestures.dart' show kPrimaryMouseButton;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'controls_probe.dart' show ControlsHold;
|
||||
|
||||
// The frame both control skins live in: when the controls are up, and the
|
||||
// double-click on the picture. Mouse movement shows them; [hideAfter]
|
||||
// without any (or the mouse leaving) hides them and the cursor. Holds keep
|
||||
// them up: a seek drag (no hover events arrive), an open menu (a route
|
||||
// takes the mouse), and the session's [ControlsHold] (the mouse on a
|
||||
// floating pill or card, the Up next popover).
|
||||
|
||||
class ControlsFrame extends StatefulWidget {
|
||||
/// Draws the controls; [visible] false while they are hidden.
|
||||
final Widget Function(BuildContext context, bool visible) builder;
|
||||
final VoidCallback? onDoubleClick;
|
||||
|
||||
/// Bands at the top and bottom where a double-click is the bars', not
|
||||
/// the picture's.
|
||||
final double barTop;
|
||||
final double barBottom;
|
||||
final Duration hideAfter;
|
||||
|
||||
/// Follows whether the controls are up (for overlays outside them).
|
||||
final ValueNotifier<bool>? shown;
|
||||
|
||||
/// Keeps them up while held.
|
||||
final ControlsHold? holdBy;
|
||||
const ControlsFrame({
|
||||
super.key,
|
||||
required this.builder,
|
||||
this.onDoubleClick,
|
||||
this.barTop = 0,
|
||||
this.barBottom = 0,
|
||||
this.hideAfter = const Duration(seconds: 3),
|
||||
this.shown,
|
||||
this.holdBy,
|
||||
});
|
||||
|
||||
/// The frame around [context], for widgets that keep it up (a drag, a
|
||||
/// menu).
|
||||
static ControlsFrameState? maybeOf(BuildContext context) => context.findAncestorStateOfType<ControlsFrameState>();
|
||||
|
||||
/// Runs [open] (a menu, a popover) with the controls around [context]
|
||||
/// held up, if there are any.
|
||||
static Future<T> holdWhile<T>(BuildContext context, Future<T> Function() open) {
|
||||
final frame = maybeOf(context);
|
||||
return frame == null ? open() : frame.holdDuring(open);
|
||||
}
|
||||
|
||||
/// The fade of the controls.
|
||||
static const fade = Duration(milliseconds: 150);
|
||||
|
||||
@override
|
||||
State<ControlsFrame> createState() => ControlsFrameState();
|
||||
}
|
||||
|
||||
class ControlsFrameState extends State<ControlsFrame> {
|
||||
bool _visible = true;
|
||||
int _holds = 0;
|
||||
bool _heldBy = false;
|
||||
Timer? _timer;
|
||||
|
||||
bool get visible => _visible;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.holdBy?.addListener(_holdByChanged);
|
||||
// Not during this build: an overlay listening to [shown] may be built.
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) widget.shown?.value = true;
|
||||
});
|
||||
_hideLater();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ControlsFrame oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.holdBy != widget.holdBy) {
|
||||
oldWidget.holdBy?.removeListener(_holdByChanged);
|
||||
widget.holdBy?.addListener(_holdByChanged);
|
||||
_holdByChanged();
|
||||
}
|
||||
if (oldWidget.hideAfter != widget.hideAfter && _visible) _hideLater();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.holdBy?.removeListener(_holdByChanged);
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _holdByChanged() {
|
||||
final on = widget.holdBy?.held ?? false;
|
||||
if (on == _heldBy || !mounted) return;
|
||||
_heldBy = on;
|
||||
hold(on);
|
||||
}
|
||||
|
||||
/// Show the controls and restart the hide countdown.
|
||||
void wake() {
|
||||
if (!_visible && mounted) {
|
||||
setState(() => _visible = true);
|
||||
widget.shown?.value = true;
|
||||
}
|
||||
_hideLater();
|
||||
}
|
||||
|
||||
/// Keep the controls up while [on] (paired calls).
|
||||
void hold(bool on) {
|
||||
_holds = on ? _holds + 1 : (_holds - 1).clamp(0, 1 << 20);
|
||||
wake();
|
||||
}
|
||||
|
||||
/// Runs [open] (a menu) with the controls held up.
|
||||
Future<T> holdDuring<T>(Future<T> Function() open) async {
|
||||
hold(true);
|
||||
try {
|
||||
return await open();
|
||||
} finally {
|
||||
if (mounted) hold(false);
|
||||
}
|
||||
}
|
||||
|
||||
void _hideLater() {
|
||||
_timer?.cancel();
|
||||
_timer = Timer(widget.hideAfter, _hide);
|
||||
}
|
||||
|
||||
void _hide() {
|
||||
if (!mounted || _holds > 0 || !_visible) return;
|
||||
setState(() => _visible = false);
|
||||
widget.shown?.value = false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MouseRegion(
|
||||
cursor: _visible ? SystemMouseCursors.basic : SystemMouseCursors.none,
|
||||
onEnter: (_) => wake(),
|
||||
onHover: (_) => wake(),
|
||||
onExit: (_) {
|
||||
_timer?.cancel();
|
||||
_hide();
|
||||
},
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
if (widget.onDoubleClick != null)
|
||||
Positioned.fill(
|
||||
child: DoubleClickListener(
|
||||
onDoubleClick: widget.onDoubleClick!,
|
||||
skipTop: _visible ? widget.barTop : 0,
|
||||
skipBottom: _visible ? widget.barBottom : 0,
|
||||
child: const ColoredBox(color: Color(0x00000000), child: SizedBox.expand()),
|
||||
),
|
||||
),
|
||||
widget.builder(context, _visible),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Double-click on the picture (not on the bars) without joining the
|
||||
/// gesture arena, so single clicks on buttons stay instant.
|
||||
class DoubleClickListener extends StatefulWidget {
|
||||
final VoidCallback onDoubleClick;
|
||||
final double skipTop, skipBottom;
|
||||
final Widget child;
|
||||
const DoubleClickListener({
|
||||
super.key,
|
||||
required this.onDoubleClick,
|
||||
this.skipTop = 0,
|
||||
this.skipBottom = 0,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<DoubleClickListener> createState() => _DoubleClickListenerState();
|
||||
}
|
||||
|
||||
class _DoubleClickListenerState extends State<DoubleClickListener> {
|
||||
DateTime? _last;
|
||||
Offset? _lastAt;
|
||||
|
||||
void _down(PointerDownEvent e) {
|
||||
if (e.buttons != kPrimaryMouseButton) return;
|
||||
final h = context.size?.height ?? 0;
|
||||
final y = e.localPosition.dy;
|
||||
if (y < widget.skipTop || y > h - widget.skipBottom) {
|
||||
_last = null;
|
||||
return;
|
||||
}
|
||||
final now = DateTime.now();
|
||||
final last = _last, at = _lastAt;
|
||||
if (last != null &&
|
||||
at != null &&
|
||||
now.difference(last) < const Duration(milliseconds: 400) &&
|
||||
(e.localPosition - at).distance < 24) {
|
||||
_last = null;
|
||||
widget.onDoubleClick();
|
||||
return;
|
||||
}
|
||||
_last = now;
|
||||
_lastAt = e.localPosition;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
Listener(behavior: HitTestBehavior.translucent, onPointerDown: _down, child: widget.child);
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
import 'package:sync_relay_core/core.dart' show JellyfinStreamType;
|
||||
|
||||
import '../../queue/queue_ui.dart';
|
||||
import '../../shell/now_playing_title.dart';
|
||||
import '../../state/settings.dart';
|
||||
import '../control_menus.dart';
|
||||
import '../controls_probe.dart' show ControlsHold;
|
||||
import '../frame.dart';
|
||||
import '../model/controls_layout.dart';
|
||||
import '../model/controls_model.dart';
|
||||
import '../model/controls_prefs.dart';
|
||||
import '../volume.dart';
|
||||
import 'style.dart';
|
||||
import 'timeline.dart';
|
||||
|
||||
// The Minimal skin (inspired by mpv's uosc): a timeline band across the
|
||||
// bottom that carries the clock, and above it the buttons in two glass
|
||||
// capsules, in the layout's order. Top: what plays, Up next and the window
|
||||
// controls. Hidden, the band shrinks to a thin progress line (unless
|
||||
// switched off).
|
||||
|
||||
class MinimalControls extends StatelessWidget {
|
||||
final PlayerControlsModel model;
|
||||
final bool visible;
|
||||
final double scale;
|
||||
final ControlsHold? hold;
|
||||
final Widget? windowButtons;
|
||||
const MinimalControls({
|
||||
super.key,
|
||||
required this.model,
|
||||
required this.visible,
|
||||
this.scale = 1,
|
||||
this.hold,
|
||||
this.windowButtons,
|
||||
});
|
||||
|
||||
static const _rowGap = 8.0;
|
||||
|
||||
/// The button row's height at [scale] (a capsule).
|
||||
static double rowHeight(double scale) => MinimalStyle.button * scale + 2 * MinimalStyle.capsulePad;
|
||||
|
||||
/// Buttons and timeline at [scale].
|
||||
static double bottomHeight(double scale) => rowHeight(scale) + _rowGap + MinimalTimeline.heightFor(scale);
|
||||
|
||||
/// The top bar's height.
|
||||
static const topHeight = 72.0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const fade = ControlsFrame.fade;
|
||||
Widget shown(Widget child, {Key? key}) => IgnorePointer(
|
||||
key: key,
|
||||
ignoring: !visible,
|
||||
child: AnimatedOpacity(duration: fade, opacity: visible ? 1 : 0, child: child),
|
||||
);
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
child: shown(
|
||||
key: const ValueKey('minimal-top'),
|
||||
DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Color(0x99000000), Color(0x00000000)],
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
height: topHeight + 24,
|
||||
child: Padding(padding: const EdgeInsets.fromLTRB(16, 0, 10, 24), child: _top()),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
shown(
|
||||
key: const ValueKey('minimal-buttons'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 0, 12, _rowGap),
|
||||
child: SizedBox(
|
||||
height: rowHeight(scale),
|
||||
child: SignalBuilder(
|
||||
builder: (context) {
|
||||
final s = model.snapshot.value;
|
||||
final layout = model.bar.value;
|
||||
// The clock lives on the timeline.
|
||||
List<Widget> cluster(List<BarControl> cs) => [
|
||||
for (final c in cs)
|
||||
if (c != BarControl.time) _control(context, c, s),
|
||||
];
|
||||
return Row(
|
||||
children: [
|
||||
MinimalCapsule(scale: scale, children: cluster(layout.left)),
|
||||
const Spacer(),
|
||||
MinimalCapsule(scale: scale, children: cluster(layout.right)),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SignalBuilder(
|
||||
builder: (context) {
|
||||
final line = AppSettings.instance.progressLine.value;
|
||||
return AnimatedOpacity(
|
||||
key: const ValueKey('minimal-timeline-wrap'),
|
||||
duration: fade,
|
||||
opacity: visible || line ? 1 : 0,
|
||||
child: MinimalTimeline(
|
||||
position: model.position.value,
|
||||
duration: model.duration.value,
|
||||
buffered: model.buffered.value,
|
||||
chapters: model.chapters.value,
|
||||
expanded: visible,
|
||||
remaining: model.settings.timeDisplay.value == TimeDisplay.remaining,
|
||||
scale: scale,
|
||||
onSeek: model.seek,
|
||||
onToggleTime: model.toggleTimeDisplay,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _top() {
|
||||
final m = model;
|
||||
return Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: Align(alignment: AlignmentDirectional.centerStart, child: NowPlayingTitle()),
|
||||
),
|
||||
UpNextButton(queue: m.queue, look: UpNextLook.minimal, hold: hold),
|
||||
const SizedBox(width: 4),
|
||||
SignalBuilder(
|
||||
builder: (context) {
|
||||
final full = m.fullscreen.value;
|
||||
return MinimalButton(
|
||||
key: const ValueKey('minimal-collapse'),
|
||||
icon: full ? Icons.fullscreen_exit_rounded : Icons.close_fullscreen_rounded,
|
||||
tooltip: full ? 'Exit fullscreen (Esc)' : 'Back to the library (keeps playing)',
|
||||
onPressed: full ? m.toggleFullscreen : m.collapse,
|
||||
);
|
||||
},
|
||||
),
|
||||
?windowButtons,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _control(BuildContext context, BarControl c, ControlsSnapshot s) {
|
||||
final m = model;
|
||||
final key = ValueKey('control-${c.name}');
|
||||
final enabled = controlEnabled(c, s);
|
||||
Widget button(VoidCallback? onPressed, {int? badge, bool accent = false}) => MinimalButton(
|
||||
key: key,
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
badge: badge,
|
||||
accent: accent,
|
||||
scale: scale,
|
||||
onPressed: enabled ? onPressed : null,
|
||||
);
|
||||
switch (c) {
|
||||
case BarControl.playPause:
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(right: 4 * scale),
|
||||
child: button(m.togglePlay, accent: true),
|
||||
);
|
||||
case BarControl.previous:
|
||||
return button(m.previous);
|
||||
case BarControl.next:
|
||||
return button(m.next);
|
||||
case BarControl.chapterPrevious:
|
||||
return button(() => m.stepChapter(-1));
|
||||
case BarControl.chapterNext:
|
||||
return button(() => m.stepChapter(1));
|
||||
case BarControl.volume:
|
||||
return SignalBuilder(
|
||||
key: key,
|
||||
builder: (context) => VolumeControl(
|
||||
volume: m.volume.value,
|
||||
onChanged: m.setVolume,
|
||||
onToggleMute: m.toggleMute,
|
||||
sliderColor: Theme.of(context).colorScheme.primary,
|
||||
trackColor: MinimalStyle.dim.withValues(alpha: 0.4),
|
||||
button: (context, i, color, tip, onPressed) =>
|
||||
MinimalButton(icon: i, tooltip: tip, color: color, scale: scale, onPressed: onPressed),
|
||||
),
|
||||
);
|
||||
case BarControl.time:
|
||||
return const SizedBox.shrink();
|
||||
case BarControl.subtitles || BarControl.audio:
|
||||
final type = c == BarControl.audio ? JellyfinStreamType.audio : JellyfinStreamType.subtitle;
|
||||
return SignalBuilder(
|
||||
key: key,
|
||||
builder: (context) => Builder(
|
||||
builder: (context) => MinimalButton(
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
badge: trackCount(m.tracks.value, type),
|
||||
scale: scale,
|
||||
onPressed: () => openTrackMenu(context, m, type),
|
||||
),
|
||||
),
|
||||
);
|
||||
case BarControl.settings:
|
||||
return Builder(
|
||||
key: key,
|
||||
builder: (context) => MinimalButton(
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
scale: scale,
|
||||
onPressed: () => openControlsMenu(context, m),
|
||||
),
|
||||
);
|
||||
case BarControl.chat:
|
||||
return SignalBuilder(
|
||||
key: key,
|
||||
builder: (context) => MinimalButton(
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
badge: m.unread.value,
|
||||
scale: scale,
|
||||
onPressed: m.toggleChat,
|
||||
),
|
||||
);
|
||||
case BarControl.fullscreen:
|
||||
return button(m.toggleFullscreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../widgets/app_menu.dart' show AppMenuStyle;
|
||||
|
||||
// The Minimal skin's look: the app's glass and accent (the theme's primary)
|
||||
// on a thick timeline band, with soft rounded buttons in two glass capsules.
|
||||
|
||||
abstract final class MinimalStyle {
|
||||
/// The timeline band (no blur: it spans the width over the picture).
|
||||
static const band = Color(0xCC0E0E12);
|
||||
|
||||
/// The capsules holding the buttons: the player pills' glass.
|
||||
static const capsule = AppMenuStyle.pillGlass;
|
||||
static const hover = Color(0x1FFFFFFF);
|
||||
static const text = Colors.white;
|
||||
static const dim = Color(0xB3FFFFFF);
|
||||
static const radius = 10.0;
|
||||
static const fontSize = 13.0;
|
||||
|
||||
/// The tooltips and the timeline's hover tip.
|
||||
static const tip = Color(0xEB18181C);
|
||||
|
||||
/// A button's box at scale 1.
|
||||
static const button = 38.0;
|
||||
|
||||
/// The capsules' padding around the buttons.
|
||||
static const capsulePad = 4.0;
|
||||
}
|
||||
|
||||
/// The Minimal skin's tooltip: the app's dark glass colour, above.
|
||||
class MinimalTooltip extends StatelessWidget {
|
||||
final String message;
|
||||
final Widget child;
|
||||
const MinimalTooltip({super.key, required this.message, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (message.isEmpty) return child;
|
||||
return Tooltip(
|
||||
message: message,
|
||||
preferBelow: false,
|
||||
verticalOffset: 28,
|
||||
waitDuration: const Duration(milliseconds: 300),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: MinimalStyle.tip,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppMenuStyle.border, width: 0.5),
|
||||
),
|
||||
textStyle: const TextStyle(color: MinimalStyle.text, fontSize: 12),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A Minimal button: a white icon on a rounded square that lights on hover
|
||||
/// ([accent]: filled with the theme's primary, the play button), an
|
||||
/// optional [label] and a count [badge]. Never takes focus.
|
||||
class MinimalButton extends StatefulWidget {
|
||||
final IconData icon;
|
||||
final String tooltip;
|
||||
final VoidCallback? onPressed;
|
||||
final String? label;
|
||||
final int? badge;
|
||||
final bool accent;
|
||||
final Color? color;
|
||||
final double scale;
|
||||
const MinimalButton({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.tooltip,
|
||||
required this.onPressed,
|
||||
this.label,
|
||||
this.badge,
|
||||
this.accent = false,
|
||||
this.color,
|
||||
this.scale = 1,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MinimalButton> createState() => _MinimalButtonState();
|
||||
}
|
||||
|
||||
class _MinimalButtonState extends State<MinimalButton> {
|
||||
bool _hover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final w = widget;
|
||||
final primary = Theme.of(context).colorScheme.primary;
|
||||
final onPrimary = Theme.of(context).colorScheme.onPrimary;
|
||||
final enabled = w.onPressed != null;
|
||||
final size = MinimalStyle.button * w.scale;
|
||||
final fg = !enabled
|
||||
? MinimalStyle.dim.withValues(alpha: 0.35)
|
||||
: w.accent
|
||||
? onPrimary
|
||||
: (w.color ?? MinimalStyle.text);
|
||||
final bg = w.accent
|
||||
? (_hover ? Color.lerp(primary, Colors.white, 0.18)! : primary)
|
||||
: (_hover && enabled ? MinimalStyle.hover : Colors.transparent);
|
||||
final badge = w.badge;
|
||||
return MinimalTooltip(
|
||||
message: w.tooltip,
|
||||
child: MouseRegion(
|
||||
cursor: enabled ? SystemMouseCursors.click : SystemMouseCursors.basic,
|
||||
onEnter: (_) => setState(() => _hover = true),
|
||||
onExit: (_) => setState(() => _hover = false),
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: w.onPressed,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 120),
|
||||
height: size,
|
||||
constraints: BoxConstraints(minWidth: size),
|
||||
padding: EdgeInsets.symmetric(horizontal: w.label == null ? 0 : 10 * w.scale),
|
||||
decoration: BoxDecoration(
|
||||
color: bg,
|
||||
borderRadius: BorderRadius.circular(w.accent ? size / 2 : MinimalStyle.radius * w.scale),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Icon(w.icon, color: fg, size: (w.accent ? 26 : 22) * w.scale),
|
||||
if (badge != null && badge > 0)
|
||||
Positioned(
|
||||
right: -7,
|
||||
top: -5,
|
||||
child: Container(
|
||||
key: const ValueKey('minimal-badge'),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
decoration: BoxDecoration(color: primary, borderRadius: BorderRadius.circular(999)),
|
||||
child: Text(
|
||||
'$badge',
|
||||
style: TextStyle(color: onPrimary, fontSize: 9, height: 1.35, fontWeight: FontWeight.w700),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (w.label != null) ...[
|
||||
SizedBox(width: 6 * w.scale),
|
||||
Text(
|
||||
w.label!,
|
||||
style: TextStyle(
|
||||
color: fg,
|
||||
fontSize: MinimalStyle.fontSize * w.scale,
|
||||
fontFeatures: const [FontFeature.tabularFigures()],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A glass capsule around a row of Minimal buttons.
|
||||
class MinimalCapsule extends StatelessWidget {
|
||||
final List<Widget> children;
|
||||
final double scale;
|
||||
const MinimalCapsule({super.key, required this.children, this.scale = 1});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final r = BorderRadius.circular(MinimalStyle.radius * scale + MinimalStyle.capsulePad);
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: MinimalStyle.capsule,
|
||||
borderRadius: r,
|
||||
border: Border.all(color: AppMenuStyle.border, width: 0.5),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(MinimalStyle.capsulePad),
|
||||
child: Row(mainAxisSize: MainAxisSize.min, spacing: 2, children: children),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,578 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../playback/media_marks.dart';
|
||||
import '../frame.dart';
|
||||
import 'style.dart';
|
||||
|
||||
// The Minimal skin's timeline: a band across the bottom with the played
|
||||
// part tinted in the accent and the position as a line, the part not
|
||||
// downloaded yet striped, chapter starts as dots on the top edge (click one
|
||||
// to jump), the elapsed time left and the total or the time left right,
|
||||
// the buffered seconds by the position while under a minute, and a tip
|
||||
// with the time (and the chapter title) under the mouse. Hidden, it shrinks
|
||||
// to a thin progress line.
|
||||
//
|
||||
// Inspired by the timeline of uosc (github.com/tomasklaen/uosc, LGPL-2.1,
|
||||
// by tomasklaen): the striped unbuffered part, the remaining time and the
|
||||
// thin line when hidden come from there. The drawing, geometry and values
|
||||
// here are our own.
|
||||
|
||||
/// Sizes at scale 1.
|
||||
abstract final class MinimalTimelineSpec {
|
||||
/// The band's height while the controls are up.
|
||||
static const size = 36.0;
|
||||
|
||||
/// What is left of it while they are hidden.
|
||||
static const lineSize = 3.0;
|
||||
|
||||
/// The position line.
|
||||
static const lineWidth = 2.0;
|
||||
static const fontSize = 15.0;
|
||||
|
||||
/// The times' inset from the ends.
|
||||
static const inset = 12.0;
|
||||
|
||||
/// A chapter dot's radius (doubled-ish while hovered).
|
||||
static const dot = 3.5;
|
||||
|
||||
/// The cache label shows while less than this is buffered ahead.
|
||||
static const bufferedThreshold = Duration(seconds: 60);
|
||||
|
||||
/// Collapse / grow.
|
||||
static const animation = Duration(milliseconds: 120);
|
||||
}
|
||||
|
||||
/// Fraction of [total] at [d], 0..1 (0 without a duration).
|
||||
double timelineFraction(Duration d, Duration total) {
|
||||
final t = total.inMicroseconds;
|
||||
if (t <= 0) return 0;
|
||||
return (d.inMicroseconds / t).clamp(0.0, 1.0);
|
||||
}
|
||||
|
||||
/// Where the part not downloaded yet starts (it runs to the end), as a
|
||||
/// fraction; null when nothing known is missing. We know only the end of
|
||||
/// mpv's cache ahead ([buffered]); a cache within half a second of the end
|
||||
/// leaves nothing.
|
||||
double? uncachedFrom({required Duration position, required Duration buffered, required Duration duration}) {
|
||||
if (duration <= Duration.zero || buffered <= Duration.zero) return null;
|
||||
final from = buffered > position ? buffered : position;
|
||||
if (duration - from <= const Duration(milliseconds: 500)) return null;
|
||||
return timelineFraction(from, duration);
|
||||
}
|
||||
|
||||
/// The cache label by the position ("12s"): the seconds buffered ahead,
|
||||
/// while under [MinimalTimelineSpec.bufferedThreshold] and the cache does
|
||||
/// not reach the end.
|
||||
String? cacheLabel({required Duration position, required Duration buffered, required Duration duration}) {
|
||||
if (duration <= Duration.zero || buffered <= Duration.zero) return null;
|
||||
if (duration - buffered <= const Duration(milliseconds: 500)) return null;
|
||||
final ahead = buffered > position ? buffered - position : Duration.zero;
|
||||
if (ahead >= MinimalTimelineSpec.bufferedThreshold) return null;
|
||||
return '${(ahead.inMilliseconds / 1000).round()}s';
|
||||
}
|
||||
|
||||
/// The band's height while it animates between hidden (0) and shown (1).
|
||||
double minimalBandSize(double visibility, double scale) =>
|
||||
MinimalTimelineSpec.lineSize +
|
||||
((MinimalTimelineSpec.size * scale - MinimalTimelineSpec.lineSize) * visibility).roundToDouble();
|
||||
|
||||
/// The Minimal timeline. [expanded] false (the controls hidden) shrinks it,
|
||||
/// animated, to the progress line. Seeks ([onSeek]) on press, on every drag
|
||||
/// move and on release; a press on a hovered chapter dot jumps to that
|
||||
/// chapter, one on the right-hand time switches it ([onToggleTime]).
|
||||
class MinimalTimeline extends StatefulWidget {
|
||||
final Duration position;
|
||||
final Duration duration;
|
||||
|
||||
/// End of the cached range.
|
||||
final Duration buffered;
|
||||
final List<MediaChapter> chapters;
|
||||
final bool expanded;
|
||||
|
||||
/// The right-hand time: the time left instead of the total.
|
||||
final bool remaining;
|
||||
final double scale;
|
||||
final ValueChanged<Duration> onSeek;
|
||||
final VoidCallback? onToggleTime;
|
||||
const MinimalTimeline({
|
||||
super.key,
|
||||
required this.position,
|
||||
required this.duration,
|
||||
this.buffered = Duration.zero,
|
||||
this.chapters = const [],
|
||||
this.expanded = true,
|
||||
this.remaining = true,
|
||||
this.scale = 1,
|
||||
required this.onSeek,
|
||||
this.onToggleTime,
|
||||
});
|
||||
|
||||
static double heightFor(double scale) => MinimalTimelineSpec.size * scale;
|
||||
static const collapsedHeight = MinimalTimelineSpec.lineSize;
|
||||
|
||||
@override
|
||||
State<MinimalTimeline> createState() => _MinimalTimelineState();
|
||||
}
|
||||
|
||||
class _MinimalTimelineState extends State<MinimalTimeline> {
|
||||
Offset? _hover;
|
||||
bool _dragging = false;
|
||||
double _dragFraction = 0;
|
||||
Duration? _lastSent;
|
||||
// A released seek, shown until the position catches up (else the line
|
||||
// jumps back to the old position for a moment).
|
||||
double? _pending;
|
||||
Timer? _pendingTimer;
|
||||
|
||||
double get _scale => widget.scale;
|
||||
Duration _at(double fraction) => widget.duration * fraction.clamp(0.0, 1.0);
|
||||
|
||||
void _send(Duration d) {
|
||||
if (d == _lastSent) return;
|
||||
_lastSent = d;
|
||||
widget.onSeek(d);
|
||||
}
|
||||
|
||||
void _drag(bool on) {
|
||||
if (_dragging == on) return;
|
||||
setState(() => _dragging = on);
|
||||
ControlsFrame.maybeOf(context)?.hold(on);
|
||||
}
|
||||
|
||||
void _settle(double fraction) {
|
||||
_pending = fraction;
|
||||
_pendingTimer?.cancel();
|
||||
_pendingTimer = Timer(const Duration(seconds: 2), () {
|
||||
if (mounted) setState(() => _pending = null);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(MinimalTimeline old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (!widget.expanded && old.expanded) _hover = null;
|
||||
final p = _pending;
|
||||
if (p != null && widget.duration > Duration.zero) {
|
||||
final off = (widget.position - _at(p)).abs();
|
||||
if (off < const Duration(milliseconds: 1500)) {
|
||||
_pending = null;
|
||||
_pendingTimer?.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pendingTimer?.cancel();
|
||||
// A drag cut short by a rebuild must not keep the controls up.
|
||||
if (_dragging) ControlsFrame.maybeOf(context)?.hold(false);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
double _dotRadius(bool hovered) => MinimalTimelineSpec.dot * _scale * (hovered ? 1.7 : 1);
|
||||
|
||||
/// The chapter whose dot is within reach of [at].
|
||||
int? _hoveredChapter(double width, List<MediaChapter> marks, Offset? at) {
|
||||
if (at == null || _dragging) return null;
|
||||
final reach = _dotRadius(false) * 2.5;
|
||||
int? best;
|
||||
var bestD = double.infinity;
|
||||
for (var i = 0; i < marks.length; i++) {
|
||||
final cx = width * timelineFraction(marks[i].start, widget.duration);
|
||||
final d = (Offset(cx, 0) - at).distance;
|
||||
if (d <= reach && d < bestD) {
|
||||
best = i;
|
||||
bestD = d;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
String? _rightText(Duration shown) {
|
||||
final d = widget.duration;
|
||||
if (d <= Duration.zero) return null;
|
||||
if (!widget.remaining) return formatClock(d);
|
||||
final left = d - shown;
|
||||
return '-${formatClock(left.isNegative ? Duration.zero : left)}';
|
||||
}
|
||||
|
||||
// The painter's text takes the app's font (a TextPainter does not
|
||||
// inherit it).
|
||||
String? _font;
|
||||
|
||||
TextStyle get _timeStyle => TextStyle(
|
||||
fontFamily: _font,
|
||||
color: MinimalStyle.text,
|
||||
fontSize: MinimalTimelineSpec.fontSize * _scale,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFeatures: const [FontFeature.tabularFigures()],
|
||||
);
|
||||
|
||||
/// Where the right-hand time sits (a press there switches it).
|
||||
bool _onRightTime(Offset at, double width, String? text) {
|
||||
if (text == null || widget.onToggleTime == null) return false;
|
||||
final tp = TextPainter(
|
||||
text: TextSpan(text: text, style: _timeStyle),
|
||||
textDirection: TextDirection.ltr,
|
||||
)..layout();
|
||||
return at.dx >= width - MinimalTimelineSpec.inset * _scale - tp.width - 6;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_font = DefaultTextStyle.of(context).style.fontFamily ?? Theme.of(context).textTheme.bodyMedium?.fontFamily;
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) => TweenAnimationBuilder<double>(
|
||||
tween: Tween(end: widget.expanded ? 1 : 0),
|
||||
duration: MinimalTimelineSpec.animation,
|
||||
builder: (context, visibility, _) => _band(context, constraints.maxWidth, visibility),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _band(BuildContext context, double width, double visibility) {
|
||||
final expanded = widget.expanded;
|
||||
final duration = widget.duration;
|
||||
final size = minimalBandSize(visibility, _scale);
|
||||
final progress = _dragging ? _dragFraction : (_pending ?? timelineFraction(widget.position, duration));
|
||||
final shown = _at(progress);
|
||||
final marks = duration > Duration.zero ? widget.chapters : const <MediaChapter>[];
|
||||
final hover = expanded ? _hover : null;
|
||||
final hovered = _hoveredChapter(width, marks, hover);
|
||||
final hoverFraction = hovered != null
|
||||
? timelineFraction(marks[hovered].start, duration)
|
||||
: (hover == null || duration <= Duration.zero || width <= 0 ? null : (hover.dx / width).clamp(0.0, 1.0));
|
||||
final hoverAt = hoverFraction == null ? null : _at(hoverFraction);
|
||||
final cursorX = hoverFraction == null ? null : width * hoverFraction;
|
||||
final hoverChapter = hoverAt == null ? null : chapterIndexAt(widget.chapters, hoverAt);
|
||||
final hoverTitle = hoverChapter == null ? '' : widget.chapters[hoverChapter].title;
|
||||
// Text fades out before it would overflow the shrinking band.
|
||||
final minText = MinimalTimelineSpec.fontSize * _scale;
|
||||
final textOpacity = ((size - minText) / (minText / 2)).clamp(0.0, 1.0);
|
||||
final right = _rightText(shown);
|
||||
final primary = Theme.of(context).colorScheme.primary;
|
||||
final painter = MinimalTimelinePainter(
|
||||
progress: progress,
|
||||
visibility: visibility,
|
||||
accent: primary,
|
||||
scale: _scale,
|
||||
uncached: uncachedFrom(position: widget.position, buffered: widget.buffered, duration: duration),
|
||||
chapters: [for (final c in marks) timelineFraction(c.start, duration)],
|
||||
hoveredChapter: hovered,
|
||||
hoverX: hovered == null ? cursorX : null,
|
||||
textOpacity: textOpacity,
|
||||
elapsed: duration > Duration.zero ? formatClock(shown) : null,
|
||||
right: right,
|
||||
cache: cacheLabel(position: widget.position, buffered: widget.buffered, duration: duration),
|
||||
timeStyle: _timeStyle,
|
||||
);
|
||||
final bar = SizedBox(
|
||||
key: const ValueKey('minimal-timeline'),
|
||||
width: width,
|
||||
height: size,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: RepaintBoundary(child: CustomPaint(painter: painter)),
|
||||
),
|
||||
if (hoverAt != null && cursorX != null)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: size + 8,
|
||||
height: 120,
|
||||
child: IgnorePointer(
|
||||
child: CustomMultiChildLayout(
|
||||
delegate: _TipLayout(x: cursorX),
|
||||
children: [
|
||||
LayoutId(
|
||||
id: #tip,
|
||||
child: _HoverTip(time: formatClock(hoverAt), chapter: hoverTitle, scale: _scale),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (!expanded) return IgnorePointer(child: bar);
|
||||
Offset clampTo(Offset p) => Offset(p.dx.clamp(0.0, width), p.dy);
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (e) => setState(() => _hover = clampTo(e.localPosition)),
|
||||
onHover: (e) => setState(() => _hover = clampTo(e.localPosition)),
|
||||
onExit: (_) {
|
||||
if (!_dragging) setState(() => _hover = null);
|
||||
},
|
||||
child: Listener(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onPointerDown: (e) {
|
||||
if (width <= 0) return;
|
||||
final at = clampTo(e.localPosition);
|
||||
if (_onRightTime(at, width, right)) {
|
||||
widget.onToggleTime?.call();
|
||||
return;
|
||||
}
|
||||
if (duration <= Duration.zero) return;
|
||||
final chapter = _hoveredChapter(width, marks, at);
|
||||
_lastSent = null;
|
||||
if (chapter != null) {
|
||||
_settle(timelineFraction(marks[chapter].start, duration));
|
||||
_send(marks[chapter].start);
|
||||
setState(() {});
|
||||
return;
|
||||
}
|
||||
_pending = null;
|
||||
_dragFraction = (at.dx / width).clamp(0.0, 1.0);
|
||||
_drag(true);
|
||||
_send(_at(_dragFraction));
|
||||
},
|
||||
onPointerMove: (e) {
|
||||
if (!_dragging) return;
|
||||
final at = clampTo(e.localPosition);
|
||||
setState(() {
|
||||
_hover = at;
|
||||
_dragFraction = (at.dx / width).clamp(0.0, 1.0);
|
||||
});
|
||||
_send(_at(_dragFraction));
|
||||
},
|
||||
onPointerUp: (e) {
|
||||
if (!_dragging) return;
|
||||
_send(_at(_dragFraction));
|
||||
_settle(_dragFraction);
|
||||
final p = e.localPosition;
|
||||
if (p.dx < 0 || p.dx > width || p.dy < 0 || p.dy > size) _hover = null;
|
||||
_drag(false);
|
||||
},
|
||||
onPointerCancel: (_) => _drag(false),
|
||||
child: bar,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _HoverTip extends StatelessWidget {
|
||||
final String time;
|
||||
final String chapter;
|
||||
final double scale;
|
||||
const _HoverTip({required this.time, required this.chapter, required this.scale});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
constraints: const BoxConstraints(maxWidth: 360),
|
||||
padding: EdgeInsets.symmetric(horizontal: 10 * scale, vertical: 5 * scale),
|
||||
decoration: BoxDecoration(
|
||||
color: MinimalStyle.tip,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: const Color(0x1FFFFFFF), width: 0.5),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (chapter.isNotEmpty)
|
||||
Text(
|
||||
chapter,
|
||||
key: const ValueKey('minimal-hover-chapter'),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: MinimalStyle.text, fontSize: 13 * scale, fontWeight: FontWeight.w600),
|
||||
),
|
||||
Text(
|
||||
time,
|
||||
key: const ValueKey('minimal-hover-time'),
|
||||
style: TextStyle(
|
||||
color: chapter.isEmpty ? MinimalStyle.text : MinimalStyle.dim,
|
||||
fontSize: 13 * scale,
|
||||
fontFeatures: const [FontFeature.tabularFigures()],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The hover tip centred on [x], kept inside the band's ends.
|
||||
class _TipLayout extends MultiChildLayoutDelegate {
|
||||
final double x;
|
||||
_TipLayout({required this.x});
|
||||
|
||||
@override
|
||||
void performLayout(Size size) {
|
||||
const gap = 4.0;
|
||||
final tip = layoutChild(#tip, BoxConstraints.loose(size));
|
||||
final left = (x - tip.width / 2).clamp(gap, math.max(gap, size.width - gap - tip.width)).toDouble();
|
||||
positionChild(#tip, Offset(left, size.height - tip.height));
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRelayout(_TipLayout old) => old.x != x;
|
||||
}
|
||||
|
||||
/// Paints the band: background, the played tint and the (white) position
|
||||
/// line, the stripes over the part not downloaded, chapter marks, the
|
||||
/// times, the hover line.
|
||||
class MinimalTimelinePainter extends CustomPainter {
|
||||
/// The playing position, 0..1.
|
||||
final double progress;
|
||||
|
||||
/// 0 hidden .. 1 shown.
|
||||
final double visibility;
|
||||
final Color accent;
|
||||
final double scale;
|
||||
|
||||
/// Start of the part not downloaded (to the end), as a fraction.
|
||||
final double? uncached;
|
||||
|
||||
/// Chapter starts, as fractions.
|
||||
final List<double> chapters;
|
||||
final int? hoveredChapter;
|
||||
final double? hoverX;
|
||||
final double textOpacity;
|
||||
final String? elapsed;
|
||||
final String? right;
|
||||
final String? cache;
|
||||
final TextStyle timeStyle;
|
||||
const MinimalTimelinePainter({
|
||||
required this.progress,
|
||||
this.visibility = 1,
|
||||
this.accent = Colors.white,
|
||||
this.scale = 1,
|
||||
this.uncached,
|
||||
this.chapters = const [],
|
||||
this.hoveredChapter,
|
||||
this.hoverX,
|
||||
this.textOpacity = 1,
|
||||
this.elapsed,
|
||||
this.right,
|
||||
this.cache,
|
||||
this.timeStyle = const TextStyle(fontSize: MinimalTimelineSpec.fontSize),
|
||||
});
|
||||
|
||||
/// x of the position line's centre.
|
||||
double lineX(double width) {
|
||||
final lw = MinimalTimelineSpec.lineWidth * scale;
|
||||
return (width * progress).clamp(lw / 2, math.max(lw / 2, width - lw / 2));
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final w = size.width, h = size.height;
|
||||
final x = lineX(w);
|
||||
final band = Offset.zero & size;
|
||||
// The band, darker as it grows; hidden, a faint track.
|
||||
canvas.drawRect(band, Paint()..color = Color.lerp(const Color(0x40FFFFFF), MinimalStyle.band, visibility)!);
|
||||
// Played: an accent tint, solid once the band is a line.
|
||||
canvas.drawRect(
|
||||
Rect.fromLTRB(0, 0, x, h),
|
||||
Paint()..color = accent.withValues(alpha: 0.28 + 0.72 * (1 - visibility)),
|
||||
);
|
||||
_stripes(canvas, w, h);
|
||||
_chapters(canvas, w, h);
|
||||
if (visibility > 0) {
|
||||
final lw = MinimalTimelineSpec.lineWidth * scale;
|
||||
canvas.drawRect(
|
||||
Rect.fromLTRB(x - lw / 2, 0, x + lw / 2, h),
|
||||
Paint()..color = Colors.white.withValues(alpha: visibility),
|
||||
);
|
||||
}
|
||||
if (textOpacity > 0) _times(canvas, w, h, x);
|
||||
final hx = hoverX;
|
||||
if (hx != null) {
|
||||
canvas.drawRect(Rect.fromLTRB(hx - 0.5, 0, hx + 0.5, h), Paint()..color = Colors.white.withValues(alpha: 0.45));
|
||||
}
|
||||
}
|
||||
|
||||
/// Thin 45° stripes over the part not downloaded yet.
|
||||
void _stripes(Canvas canvas, double w, double h) {
|
||||
final from = uncached;
|
||||
if (from == null) return;
|
||||
final ax = (w * from).floorToDouble();
|
||||
if (ax >= w) return;
|
||||
final period = 7.0 * scale;
|
||||
canvas.save();
|
||||
canvas.clipRect(Rect.fromLTRB(ax, 0, w, h));
|
||||
final paint = Paint()
|
||||
..color = Colors.white.withValues(alpha: 0.10 + 0.08 * (1 - visibility))
|
||||
..strokeWidth = 1.5 * scale;
|
||||
for (var c = (ax / period).floorToDouble() * period - h; c <= w; c += period) {
|
||||
canvas.drawLine(Offset(c, h), Offset(c + h, 0), paint);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
void _chapters(Canvas canvas, double w, double h) {
|
||||
final cut = Paint()..color = Colors.black.withValues(alpha: 0.55);
|
||||
for (final f in chapters) {
|
||||
if (f <= 0) continue;
|
||||
final cx = w * f;
|
||||
canvas.drawRect(Rect.fromLTRB(cx - 0.5, 0, cx + 0.5, h), cut);
|
||||
}
|
||||
if (visibility <= 0) return;
|
||||
final r = MinimalTimelineSpec.dot * scale * visibility;
|
||||
void dot(double f, double radius, Color fill) {
|
||||
final c = Offset(w * f, 0);
|
||||
canvas.drawCircle(c, radius + 1, Paint()..color = Colors.black.withValues(alpha: 0.7));
|
||||
canvas.drawCircle(c, radius, Paint()..color = fill);
|
||||
}
|
||||
|
||||
// Not at 0: the band's start says that already.
|
||||
for (var i = 0; i < chapters.length; i++) {
|
||||
if (i != hoveredChapter && chapters[i] > 0) dot(chapters[i], r, Colors.white.withValues(alpha: 0.9));
|
||||
}
|
||||
final hv = hoveredChapter;
|
||||
if (hv != null && hv < chapters.length) dot(chapters[hv], r * 1.7, accent);
|
||||
}
|
||||
|
||||
TextPainter _text(String s, TextStyle style) => TextPainter(
|
||||
text: TextSpan(text: s, style: style),
|
||||
textDirection: TextDirection.ltr,
|
||||
)..layout();
|
||||
|
||||
/// White text with a soft shadow, so it reads over the accent tint too.
|
||||
void _label(Canvas canvas, String s, TextStyle style, Offset at) {
|
||||
final o = textOpacity;
|
||||
_text(
|
||||
s,
|
||||
style.copyWith(
|
||||
color: (style.color ?? Colors.white).withValues(alpha: o),
|
||||
shadows: [Shadow(color: Colors.black.withValues(alpha: 0.8 * o), blurRadius: 3)],
|
||||
),
|
||||
).paint(canvas, at);
|
||||
}
|
||||
|
||||
void _times(Canvas canvas, double w, double h, double lineX) {
|
||||
final inset = MinimalTimelineSpec.inset * scale;
|
||||
final fs = timeStyle.fontSize ?? MinimalTimelineSpec.fontSize;
|
||||
final cy = h / 2;
|
||||
final e = elapsed, r = right;
|
||||
final ew = e == null ? 0.0 : _text(e, timeStyle).width;
|
||||
final rw = r == null ? 0.0 : _text(r, timeStyle).width;
|
||||
final c = cache;
|
||||
if (c != null) {
|
||||
final cs = timeStyle.copyWith(fontSize: fs * 0.8, color: MinimalStyle.dim);
|
||||
final cw = _text(c, cs).width;
|
||||
const margin = 6.0;
|
||||
var x = lineX + margin;
|
||||
final minX = inset + margin + ew, maxX = w - inset - margin - rw;
|
||||
if (x < minX) {
|
||||
x = minX;
|
||||
} else if (x + cw > maxX) {
|
||||
x = maxX - cw;
|
||||
}
|
||||
_label(canvas, c, cs, Offset(x, cy - fs * 0.4));
|
||||
}
|
||||
if (e != null) _label(canvas, e, timeStyle, Offset(inset, cy - fs / 2));
|
||||
if (r != null) _label(canvas, r, timeStyle, Offset(w - inset - rw, cy - fs / 2));
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(MinimalTimelinePainter old) => true;
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
import 'package:flutter/material.dart' show IconData, Icons;
|
||||
|
||||
import '../../playback/media_marks.dart' show formatClock;
|
||||
import 'controls_prefs.dart';
|
||||
|
||||
// The controls layout, defined once for both skins: which controls the
|
||||
// bottom bar has, in which order, which actions sit in the ⚙ menu instead,
|
||||
// and their icons, tooltips and labels. Pure: everything here is a
|
||||
// function of a [ControlsSnapshot] and the user's choices, so tests cover
|
||||
// it without a player.
|
||||
|
||||
/// What playback does as this viewer sees it. In a server "play" is being
|
||||
/// ready: the video plays once everyone is.
|
||||
enum PlayState {
|
||||
/// The video plays (the button pauses: you go unready).
|
||||
playing,
|
||||
|
||||
/// You are ready; the others are not yet (the button unreadies you).
|
||||
waiting,
|
||||
|
||||
/// You are not ready (the button readies you).
|
||||
paused,
|
||||
|
||||
/// The media ended.
|
||||
finished,
|
||||
}
|
||||
|
||||
/// A control in the bottom bar.
|
||||
enum BarControl {
|
||||
playPause,
|
||||
|
||||
/// Previous episode.
|
||||
previous,
|
||||
|
||||
/// Up next's first item, else the next episode.
|
||||
next,
|
||||
chapterPrevious,
|
||||
chapterNext,
|
||||
volume,
|
||||
time,
|
||||
subtitles,
|
||||
audio,
|
||||
|
||||
/// ⚙: everything that is not a bar button.
|
||||
settings,
|
||||
chat,
|
||||
fullscreen,
|
||||
}
|
||||
|
||||
/// An action in the ⚙ menu.
|
||||
enum ControlAction {
|
||||
chapters('Chapters…', null),
|
||||
subtitles('Subtitles…', null),
|
||||
audio('Audio…', null),
|
||||
skipForward('Skip 1:30', 'Shift+Right'),
|
||||
shaders('Upscaling shader…', 'Ctrl+0…6'),
|
||||
chat('Chat & activity', 'Tab'),
|
||||
changeVideo('Change video', null),
|
||||
copyLink('Copy link', null),
|
||||
reload('Reload video', 'Ctrl+R'),
|
||||
markAllReady('Mark everyone ready', null),
|
||||
markProblem('Mark a problem', 'Ctrl+Shift+B'),
|
||||
playerSettings('Player settings…', null),
|
||||
leave('Leave server', null);
|
||||
|
||||
final String label;
|
||||
final String? hint;
|
||||
const ControlAction(this.label, this.hint);
|
||||
}
|
||||
|
||||
/// The bar's order, left cluster then right cluster. The play button is
|
||||
/// always first and fullscreen always last; controls that do not apply
|
||||
/// (no episode, no chapters) or that the user hid are left out, the rest
|
||||
/// keep their order.
|
||||
abstract final class ControlsLayout {
|
||||
static const left = [
|
||||
BarControl.playPause,
|
||||
BarControl.previous,
|
||||
BarControl.next,
|
||||
BarControl.chapterPrevious,
|
||||
BarControl.chapterNext,
|
||||
BarControl.volume,
|
||||
BarControl.time,
|
||||
];
|
||||
static const right = [
|
||||
BarControl.subtitles,
|
||||
BarControl.audio,
|
||||
BarControl.settings,
|
||||
BarControl.chat,
|
||||
BarControl.fullscreen,
|
||||
];
|
||||
|
||||
/// The ⚙ menu's order.
|
||||
static const menu = ControlAction.values;
|
||||
}
|
||||
|
||||
/// What the layout depends on, at one moment.
|
||||
class ControlsSnapshot {
|
||||
final PlayState play;
|
||||
|
||||
/// The previous episode's label; null: none.
|
||||
final String? previousLabel;
|
||||
|
||||
/// Up next's first item's title, else the next episode's label; null:
|
||||
/// nothing next.
|
||||
final String? nextLabel;
|
||||
|
||||
/// [nextLabel] is Up next (not an episode).
|
||||
final bool nextIsUpNext;
|
||||
final bool hasChapters;
|
||||
|
||||
/// The media's length is known (seeks and skips make sense).
|
||||
final bool hasDuration;
|
||||
|
||||
/// Watching alone (no one to mark ready).
|
||||
final bool alone;
|
||||
|
||||
/// A link to copy (`SessionCoordinator.currentLink`).
|
||||
final bool hasLink;
|
||||
final bool fullscreen;
|
||||
final bool chatOpen;
|
||||
const ControlsSnapshot({
|
||||
this.play = PlayState.paused,
|
||||
this.previousLabel,
|
||||
this.nextLabel,
|
||||
this.nextIsUpNext = false,
|
||||
this.hasChapters = false,
|
||||
this.hasDuration = false,
|
||||
this.alone = false,
|
||||
this.hasLink = false,
|
||||
this.fullscreen = false,
|
||||
this.chatOpen = false,
|
||||
});
|
||||
}
|
||||
|
||||
/// The bar's two clusters for [s], in [ControlsLayout] order.
|
||||
({List<BarControl> left, List<BarControl> right}) barControls(ControlsSnapshot s, Set<OptionalControl> hidden) {
|
||||
bool on(BarControl c) => switch (c) {
|
||||
BarControl.previous => s.previousLabel != null,
|
||||
BarControl.next => s.nextLabel != null,
|
||||
BarControl.chapterPrevious || BarControl.chapterNext => s.hasChapters && !hidden.contains(OptionalControl.chapters),
|
||||
BarControl.subtitles => !hidden.contains(OptionalControl.subtitles),
|
||||
BarControl.audio => !hidden.contains(OptionalControl.audio),
|
||||
BarControl.chat => !hidden.contains(OptionalControl.chat),
|
||||
_ => true,
|
||||
};
|
||||
return (
|
||||
left: [
|
||||
for (final c in ControlsLayout.left)
|
||||
if (on(c)) c,
|
||||
],
|
||||
right: [
|
||||
for (final c in ControlsLayout.right)
|
||||
if (on(c)) c,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// The ⚙ menu for [s]: every action that applies, minus those the bar
|
||||
/// already shows.
|
||||
List<ControlAction> menuActions(ControlsSnapshot s, Set<OptionalControl> hidden) => [
|
||||
for (final a in ControlsLayout.menu)
|
||||
if (switch (a) {
|
||||
ControlAction.chapters => s.hasChapters,
|
||||
ControlAction.subtitles => hidden.contains(OptionalControl.subtitles),
|
||||
ControlAction.audio => hidden.contains(OptionalControl.audio),
|
||||
ControlAction.skipForward => s.hasDuration,
|
||||
ControlAction.chat => hidden.contains(OptionalControl.chat),
|
||||
ControlAction.copyLink => s.hasLink,
|
||||
ControlAction.markAllReady => !s.alone,
|
||||
_ => true,
|
||||
})
|
||||
a,
|
||||
];
|
||||
|
||||
/// Whether a bar control does something now (a skin dims it otherwise).
|
||||
bool controlEnabled(BarControl c, ControlsSnapshot s) => switch (c) {
|
||||
BarControl.chapterPrevious || BarControl.chapterNext => s.hasChapters && s.hasDuration,
|
||||
BarControl.previous => s.previousLabel != null,
|
||||
BarControl.next => s.nextLabel != null,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
/// The icon of a bar control (volume and the clock draw their own).
|
||||
IconData controlIcon(BarControl c, ControlsSnapshot s) => switch (c) {
|
||||
BarControl.playPause => switch (s.play) {
|
||||
PlayState.playing => Icons.pause_rounded,
|
||||
// Ready: the check says so; a click unreadies.
|
||||
PlayState.waiting => Icons.check_rounded,
|
||||
PlayState.finished => Icons.replay_rounded,
|
||||
PlayState.paused => Icons.play_arrow_rounded,
|
||||
},
|
||||
BarControl.previous => Icons.skip_previous_rounded,
|
||||
BarControl.next => Icons.skip_next_rounded,
|
||||
BarControl.chapterPrevious => Icons.chevron_left_rounded,
|
||||
BarControl.chapterNext => Icons.chevron_right_rounded,
|
||||
BarControl.volume => Icons.volume_up_rounded,
|
||||
BarControl.time => Icons.schedule_rounded,
|
||||
BarControl.subtitles => Icons.subtitles_outlined,
|
||||
BarControl.audio => Icons.graphic_eq_rounded,
|
||||
BarControl.settings => Icons.settings_outlined,
|
||||
BarControl.chat => s.chatOpen ? Icons.chat_bubble_rounded : Icons.chat_bubble_outline_rounded,
|
||||
BarControl.fullscreen => s.fullscreen ? Icons.fullscreen_exit_rounded : Icons.fullscreen_rounded,
|
||||
};
|
||||
|
||||
/// The tooltip of a bar control, with its key.
|
||||
String controlTooltip(BarControl c, ControlsSnapshot s) => switch (c) {
|
||||
BarControl.playPause => switch (s.play) {
|
||||
PlayState.playing => 'Pause for everyone (Space)',
|
||||
PlayState.waiting => 'Ready, waiting for the others (Space: not ready)',
|
||||
PlayState.paused => s.alone ? 'Play (Space)' : 'Ready: play when everyone is (Space)',
|
||||
PlayState.finished => 'Ready (Space)',
|
||||
},
|
||||
BarControl.previous => 'Previous: ${s.previousLabel ?? ''} (< or Shift+P)',
|
||||
BarControl.next => '${s.nextIsUpNext ? 'Up next' : 'Next'}: ${s.nextLabel ?? ''} (> or Shift+N)',
|
||||
BarControl.chapterPrevious => 'Previous chapter (PgUp)',
|
||||
BarControl.chapterNext => 'Next chapter (PgDn)',
|
||||
BarControl.volume => 'Volume (scroll, ↑ / ↓)',
|
||||
BarControl.time => 'Elapsed / remaining (click to switch)',
|
||||
BarControl.subtitles => 'Subtitles',
|
||||
BarControl.audio => 'Audio',
|
||||
BarControl.settings => 'Settings and more',
|
||||
BarControl.chat => 'Chat & activity (Tab)',
|
||||
BarControl.fullscreen => s.fullscreen ? 'Exit fullscreen (F, Esc)' : 'Fullscreen (F)',
|
||||
};
|
||||
|
||||
/// The bar's clock: "6:00 / 24:00", or the time left ("-18:00"); "0:00"
|
||||
/// parts while the length is unknown.
|
||||
String clockText(Duration position, Duration duration, TimeDisplay display) {
|
||||
if (display == TimeDisplay.remaining && duration > Duration.zero) {
|
||||
final left = duration - position;
|
||||
return '-${formatClock(left.isNegative ? Duration.zero : left)}';
|
||||
}
|
||||
return '${formatClock(position)} / ${formatClock(duration)}';
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
|
||||
import '../../jellyfin/track_prefs.dart' show MpvTrack;
|
||||
import '../../playback/media_marks.dart';
|
||||
import '../../playback/playback_controller.dart';
|
||||
import '../../queue/queue_controller.dart';
|
||||
import '../../session/session_coordinator.dart';
|
||||
import '../../shaders/shader_presets.dart';
|
||||
import '../../state/settings.dart';
|
||||
import '../player_settings.dart' show applyShaderChoice;
|
||||
import '../volume.dart' as vol;
|
||||
import 'controls_layout.dart';
|
||||
|
||||
/// A track pick from a track menu: audio id, subtitle id, or off.
|
||||
typedef TrackPick = ({int? aid, int? sid, bool subtitlesOff});
|
||||
|
||||
/// The player controls, independent of how they look: what the controls
|
||||
/// show (state, as signals) and what they do (actions), wired to the
|
||||
/// session once. Both skins only draw this and call its actions, so a
|
||||
/// control added here shows in both. Built by the session player per
|
||||
/// mount; [fullscreen], [chatOpen] and [unread] are the shell's, passed in.
|
||||
class PlayerControlsModel {
|
||||
final SessionCoordinator coord;
|
||||
final ReadonlySignal<bool> fullscreen;
|
||||
final ReadonlySignal<bool> chatOpen;
|
||||
final ReadonlySignal<int> unread;
|
||||
final VoidCallback _toggleFullscreen;
|
||||
final VoidCallback _toggleChat;
|
||||
final VoidCallback _changeVideo;
|
||||
final VoidCallback _collapse;
|
||||
final VoidCallback _leave;
|
||||
|
||||
PlayerControlsModel({
|
||||
required this.coord,
|
||||
required this.fullscreen,
|
||||
required this.chatOpen,
|
||||
required this.unread,
|
||||
required VoidCallback onToggleFullscreen,
|
||||
required VoidCallback onToggleChat,
|
||||
required VoidCallback onChangeVideo,
|
||||
required VoidCallback onCollapse,
|
||||
required VoidCallback onLeave,
|
||||
}) : _toggleFullscreen = onToggleFullscreen,
|
||||
_toggleChat = onToggleChat,
|
||||
_changeVideo = onChangeVideo,
|
||||
_collapse = onCollapse,
|
||||
_leave = onLeave;
|
||||
|
||||
PlaybackController get playback => coord.playback;
|
||||
QueueController get queue => coord.queue;
|
||||
AppSettings get settings => AppSettings.instance;
|
||||
|
||||
// ---------------------------------------------------------------- state
|
||||
|
||||
ReadonlySignal<Duration> get position => playback.position;
|
||||
ReadonlySignal<Duration> get duration => playback.duration;
|
||||
|
||||
/// End of the cached range ahead of the position.
|
||||
ReadonlySignal<Duration> get buffered => playback.buffered;
|
||||
ReadonlySignal<List<MediaChapter>> get chapters => playback.chapters;
|
||||
ReadonlySignal<int?> get currentChapter => playback.currentChapter;
|
||||
ReadonlySignal<List<MpvTrack>> get tracks => playback.tracks;
|
||||
|
||||
/// 0..`maxVolume`.
|
||||
ReadonlySignal<double> get volume => playback.volume;
|
||||
ReadonlySignal<SkipOffer?> get skipOffer => coord.skipOffer;
|
||||
ReadonlySignal<RenderMode> get renderMode => playback.renderMode;
|
||||
|
||||
/// Play / pause as the session sees it ([PlayState]).
|
||||
late final Computed<PlayState> play = computed(() {
|
||||
final r = coord.serverState.value;
|
||||
final self = coord.selfMember.value;
|
||||
return switch (r?.transport) {
|
||||
'playing' => PlayState.playing,
|
||||
'finished' => PlayState.finished,
|
||||
_ => (self?.ready ?? false) && (self?.inSet ?? false) ? PlayState.waiting : PlayState.paused,
|
||||
};
|
||||
});
|
||||
|
||||
/// Everything the layout depends on (not the position: that changes
|
||||
/// four times a second and only the timeline needs it).
|
||||
late final Computed<ControlsSnapshot> snapshot = computed(() {
|
||||
final queued = queue.items.value.firstOrNull;
|
||||
final continues = queue.continues.value;
|
||||
final next = coord.nextEpisode.value;
|
||||
return ControlsSnapshot(
|
||||
play: play.value,
|
||||
previousLabel: coord.previousEpisode.value?.label,
|
||||
// Up next's first item, else the next episode, else what continues
|
||||
// this (a file's next episode).
|
||||
nextLabel: queued?.title ?? next?.label ?? continues?.title,
|
||||
nextIsUpNext: queued != null,
|
||||
hasChapters: chapters.value.isNotEmpty,
|
||||
hasDuration: duration.value > Duration.zero,
|
||||
alone: coord.alone.value,
|
||||
// Not a signal: read again whenever the state changes.
|
||||
hasLink: coord.serverState.value != null && coord.currentLink() != null,
|
||||
fullscreen: fullscreen.value,
|
||||
chatOpen: chatOpen.value,
|
||||
);
|
||||
});
|
||||
|
||||
/// The bar's clusters, in the layout's order.
|
||||
late final Computed<({List<BarControl> left, List<BarControl> right})> bar = computed(
|
||||
() => barControls(snapshot.value, settings.hiddenControls.value),
|
||||
);
|
||||
|
||||
/// What the ⚙ menu lists now.
|
||||
List<ControlAction> menu() => menuActions(snapshot.peek(), settings.hiddenControls.peek());
|
||||
|
||||
/// Ticks on each wheel / key volume step: the skins flash the volume.
|
||||
final volumeFlash = ValueNotifier(0);
|
||||
|
||||
/// A menu of the controls is open (the player's Esc closes it).
|
||||
int menusOpen = 0;
|
||||
|
||||
void dispose() => volumeFlash.dispose();
|
||||
|
||||
// -------------------------------------------------------------- actions
|
||||
|
||||
/// Space: ready / not ready (being ready is "play" in a server).
|
||||
void togglePlay() => coord.toggleReady();
|
||||
|
||||
/// A seek bar's press or drag; through `player.seek`, the user-seek
|
||||
/// path, so everyone follows.
|
||||
void seek(Duration to) => playback.userSeek(to);
|
||||
|
||||
/// Arrow keys: ±[secs], relative to a seek still in flight.
|
||||
void nudge(double secs) => coord.nudge(secs);
|
||||
|
||||
/// +1:30 for everyone.
|
||||
void skipForward() => coord.skipForward();
|
||||
|
||||
/// A skip pill (Skip OP / ED / 1:30).
|
||||
void skip(SkipOffer offer) => coord.skip(offer);
|
||||
|
||||
/// PgDn (+1) / PgUp (-1). False when there is no chapter to go to.
|
||||
bool stepChapter(int delta) => coord.stepChapter(delta);
|
||||
|
||||
void pickChapter(MediaChapter c) => coord.seekTo(c.start.inMicroseconds / 1e6);
|
||||
|
||||
/// What plays next (Up next's first item, else the continuation), else
|
||||
/// the next episode. False when neither.
|
||||
bool next() {
|
||||
if (queue.head.peek() != null) {
|
||||
queue.skip();
|
||||
return true;
|
||||
}
|
||||
if (coord.nextEpisode.peek() == null) return false;
|
||||
coord.playNextEpisode();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// The previous episode. False without one.
|
||||
bool previous() {
|
||||
if (coord.previousEpisode.peek() == null) return false;
|
||||
coord.playPreviousEpisode();
|
||||
return true;
|
||||
}
|
||||
|
||||
void playNextEpisode() => coord.playNextEpisode();
|
||||
|
||||
void setVolume(double v) => playback.setVolume(v.clamp(0.0, vol.maxVolume));
|
||||
|
||||
/// One volume step up (+1) or down (-1) from the wheel or ↑ / ↓;
|
||||
/// flashes the volume readout.
|
||||
void stepVolume(int step) {
|
||||
setVolume(vol.stepVolume(volume.peek(), step * vol.volumeStep));
|
||||
volumeFlash.value++;
|
||||
}
|
||||
|
||||
double _beforeMute = 100;
|
||||
|
||||
/// The speaker: mute, or back to the volume before.
|
||||
void toggleMute() {
|
||||
final v = volume.peek();
|
||||
if (v > 0) {
|
||||
_beforeMute = v;
|
||||
setVolume(0);
|
||||
} else {
|
||||
setVolume(_beforeMute <= 0 ? 100 : _beforeMute);
|
||||
}
|
||||
}
|
||||
|
||||
void pickTrack(TrackPick p) => coord.selectTrack(aid: p.aid, sid: p.sid, subtitlesOff: p.subtitlesOff);
|
||||
|
||||
/// Saved as the choice and applied live; a null quality keeps the
|
||||
/// saved one.
|
||||
void pickShader(ShaderPreset preset, ShaderQuality? quality) => applyShaderChoice(coord, preset, quality);
|
||||
|
||||
void toggleTimeDisplay() => settings.setTimeDisplay(settings.timeDisplay.peek().toggled);
|
||||
|
||||
void toggleFullscreen() => _toggleFullscreen();
|
||||
|
||||
void toggleChat() {
|
||||
coord.markInput();
|
||||
_toggleChat();
|
||||
}
|
||||
|
||||
void changeVideo() => _changeVideo();
|
||||
|
||||
/// Back to the library (keeps playing in the mini player).
|
||||
void collapse() => _collapse();
|
||||
|
||||
/// Asks before leaving the server.
|
||||
void leave() => _leave();
|
||||
|
||||
void reload() {
|
||||
coord.markInput();
|
||||
coord.reloadVideo();
|
||||
}
|
||||
|
||||
void markAllReady() => coord.forcePlayAll();
|
||||
|
||||
String? link() => coord.currentLink();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// The player controls' user choices (Settings → Player, stored in
|
||||
// `AppSettings`). Plain values: the layout spec and both skins read them.
|
||||
|
||||
/// The controls' look. Both skins draw the same controls model in the same
|
||||
/// order ([ControlsLayout]); only the look differs.
|
||||
enum ControlsSkin {
|
||||
/// Material-style bar: a seek bar over a row of round icon buttons.
|
||||
standard('Standard'),
|
||||
|
||||
/// The app's own timeline skin (inspired by mpv's uosc): a thick band
|
||||
/// with the buffered part, chapters and times, flat glass buttons.
|
||||
minimal('Minimal');
|
||||
|
||||
final String label;
|
||||
const ControlsSkin(this.label);
|
||||
|
||||
/// A stored name; the old `mpvControls` flag (true: the uosc design)
|
||||
/// when there is none.
|
||||
static ControlsSkin fromStored(Object? name, {Object? legacyMpvControls}) {
|
||||
for (final s in values) {
|
||||
if (s.name == name) return s;
|
||||
}
|
||||
return legacyMpvControls == true ? minimal : standard;
|
||||
}
|
||||
}
|
||||
|
||||
/// The bar's clock: "6:00 / 24:00" or the time left ("-18:00").
|
||||
enum TimeDisplay {
|
||||
elapsed('Elapsed / total'),
|
||||
remaining('Remaining');
|
||||
|
||||
final String label;
|
||||
const TimeDisplay(this.label);
|
||||
|
||||
TimeDisplay get toggled => this == elapsed ? remaining : elapsed;
|
||||
}
|
||||
|
||||
/// Bar and button size.
|
||||
enum ControlsSize {
|
||||
normal('Normal', 1.0),
|
||||
large('Large', 1.25);
|
||||
|
||||
final String label;
|
||||
final double scale;
|
||||
const ControlsSize(this.label, this.scale);
|
||||
}
|
||||
|
||||
/// Bar buttons the user may hide; hidden ones are still in ⚙.
|
||||
enum OptionalControl {
|
||||
chapters('Chapter buttons', 'Previous / next chapter (PgUp / PgDn)'),
|
||||
subtitles('Subtitles', 'The subtitle track list'),
|
||||
audio('Audio', 'The audio track list'),
|
||||
chat('Chat', 'Chat & activity (Tab)');
|
||||
|
||||
final String label;
|
||||
final String help;
|
||||
const OptionalControl(this.label, this.help);
|
||||
}
|
||||
|
||||
/// The auto-hide delays offered (seconds).
|
||||
const controlsHideChoices = [2, 3, 5];
|
||||
|
||||
/// The default auto-hide delay (seconds).
|
||||
const defaultControlsHideSecs = 3;
|
||||
@@ -0,0 +1,468 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
import 'package:sync_relay_core/core.dart' show JellyfinStreamType;
|
||||
|
||||
import '../jellyfin/track_prefs.dart' show MpvTrack;
|
||||
import '../playback/playback_controller.dart' show PlaybackController, RenderMode;
|
||||
import '../session/session_coordinator.dart' show SessionCoordinator;
|
||||
import '../shaders/shader_presets.dart';
|
||||
import '../app/app_graph.dart';
|
||||
import '../shell/mark_problem.dart';
|
||||
import '../shell/motion.dart';
|
||||
import '../state/settings.dart';
|
||||
import '../widgets/app_menu.dart';
|
||||
import 'frame.dart';
|
||||
import 'model/controls_prefs.dart';
|
||||
|
||||
// Everything about the player, defined once: the rows of the player
|
||||
// settings card (⚙ → Player settings, both skins) and of Settings → Player. Each row reads and
|
||||
// writes [AppSettings] and applies to a running player right away.
|
||||
|
||||
/// One setting: a label, one line of help under it, the control at the
|
||||
/// right ([below]: an extra line under the row, e.g. a text field).
|
||||
class SettingRow extends StatelessWidget {
|
||||
final String label;
|
||||
final String? help;
|
||||
final Widget control;
|
||||
final Widget? below;
|
||||
const SettingRow({super.key, required this.label, this.help, required this.control, this.below});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final muted = Theme.of(context).colorScheme.onSurfaceVariant;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label),
|
||||
if (help != null) Text(help!, style: TextStyle(color: muted, fontSize: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
control,
|
||||
],
|
||||
),
|
||||
?below,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AppSelect<T> _dropdown<T>({
|
||||
required Key key,
|
||||
required T value,
|
||||
required List<(T, String)> items,
|
||||
required ValueChanged<T> onChanged,
|
||||
bool expanded = false,
|
||||
}) =>
|
||||
AppSelect<T>(key: key, value: value, items: items, onChanged: onChanged, expanded: expanded);
|
||||
|
||||
/// The controls' skin: Standard or Minimal. Live.
|
||||
class PlayerDesignSetting extends StatelessWidget {
|
||||
const PlayerDesignSetting({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(
|
||||
builder: (context) => SettingRow(
|
||||
label: 'Player design',
|
||||
help: 'Minimal has a thick timeline with chapters and what is downloaded yet',
|
||||
control: _dropdown<ControlsSkin>(
|
||||
key: const ValueKey('player-design'),
|
||||
value: s.controlsSkin.value,
|
||||
items: [for (final k in ControlsSkin.values) (k, k.label)],
|
||||
onChanged: s.setControlsSkin,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The bar's clock: elapsed / total or the time left. Live.
|
||||
class TimeDisplaySetting extends StatelessWidget {
|
||||
const TimeDisplaySetting({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(
|
||||
builder: (context) => SettingRow(
|
||||
label: 'Time display',
|
||||
help: 'Also switched by a click on the time',
|
||||
control: _dropdown<TimeDisplay>(
|
||||
key: const ValueKey('time-display'),
|
||||
value: s.timeDisplay.value,
|
||||
items: [for (final t in TimeDisplay.values) (t, t.label)],
|
||||
onChanged: s.setTimeDisplay,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Normal or large bar and buttons. Live.
|
||||
class ControlsSizeSetting extends StatelessWidget {
|
||||
const ControlsSizeSetting({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(
|
||||
builder: (context) => SettingRow(
|
||||
label: 'Controls size',
|
||||
help: 'Large makes the bar and its buttons a quarter bigger',
|
||||
control: _dropdown<ControlsSize>(
|
||||
key: const ValueKey('controls-size'),
|
||||
value: s.controlsSize.value,
|
||||
items: [for (final z in ControlsSize.values) (z, z.label)],
|
||||
onChanged: s.setControlsSize,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// How long the controls stay up without mouse movement. Live.
|
||||
class HideDelaySetting extends StatelessWidget {
|
||||
const HideDelaySetting({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(
|
||||
builder: (context) => SettingRow(
|
||||
label: 'Hide the controls after',
|
||||
help: 'Without mouse movement over the video',
|
||||
control: _dropdown<int>(
|
||||
key: const ValueKey('controls-hide'),
|
||||
value: s.controlsHideSecs.value,
|
||||
items: [for (final secs in controlsHideChoices) (secs, '$secs s')],
|
||||
onChanged: s.setControlsHideSecs,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// One optional bar button on or off (off: it is still in ⚙). Live.
|
||||
class BarButtonSetting extends StatelessWidget {
|
||||
final OptionalControl control;
|
||||
const BarButtonSetting({super.key, required this.control});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(
|
||||
builder: (context) => SettingRow(
|
||||
label: control.label,
|
||||
help: control.help,
|
||||
control: Switch(
|
||||
key: ValueKey('bar-${control.name}'),
|
||||
value: !s.hiddenControls.value.contains(control),
|
||||
onChanged: (on) => s.setControlShown(control, on),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The 2 px line at the bottom while the controls are hidden. Live.
|
||||
class ProgressLineSetting extends StatelessWidget {
|
||||
const ProgressLineSetting({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(
|
||||
builder: (context) => SettingRow(
|
||||
label: 'Progress line when hidden',
|
||||
help: 'A thin bar at the bottom of the video while the controls are hidden',
|
||||
control: Switch(
|
||||
key: const ValueKey('progress-line'),
|
||||
value: s.progressLine.value,
|
||||
onChanged: s.setProgressLine,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Saves a shader choice (also used on the next join) and puts it on the
|
||||
/// running player, if any; the player announces the result.
|
||||
void applyShaderChoice(SessionCoordinator coord, ShaderPreset preset, ShaderQuality? quality) {
|
||||
final s = AppSettings.instance;
|
||||
if (quality != null) s.setShaderQuality(quality);
|
||||
s.setShaderPreset(preset);
|
||||
coord.markInput();
|
||||
coord.playback.applyShaders(announce: true);
|
||||
}
|
||||
|
||||
/// Anime4K preset (or custom files) and HQ / Fast. Live.
|
||||
class ShaderPresetSetting extends StatelessWidget {
|
||||
/// The running player's render mode (in the player); else the last one.
|
||||
final ReadonlySignal<RenderMode>? renderMode;
|
||||
const ShaderPresetSetting({super.key, this.renderMode});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(builder: (context) {
|
||||
final preset = s.shaderPreset.value;
|
||||
final quality = s.shaderQuality.value;
|
||||
final hasCustom = s.customShaders.value.isNotEmpty;
|
||||
final mode = (renderMode ??
|
||||
context.getInheritedWidgetOfExactType<AppScope>()?.graph.ports.players.renderMode)
|
||||
?.value;
|
||||
final warning = switch (mode) {
|
||||
RenderMode.software => 'Software rendering: shaders have no effect',
|
||||
RenderMode.softwareGl => 'OpenGL on the CPU: shaders will be slow',
|
||||
_ => null,
|
||||
};
|
||||
return SettingRow(
|
||||
label: 'Upscaling shader',
|
||||
help: 'Anime4K sharpens anime on your GPU, only you see it. '
|
||||
'A for 1080p, B for 720p, C for 480p · Ctrl+1…6, Ctrl+0 off',
|
||||
control: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_dropdown<ShaderPreset>(
|
||||
key: const ValueKey('shader-preset'),
|
||||
value: preset,
|
||||
items: [
|
||||
for (final p in ShaderPreset.values)
|
||||
if (p != ShaderPreset.custom || hasCustom || preset == p) (p, p.label),
|
||||
],
|
||||
onChanged: (p) => applyShaderChoice(AppScope.of(context).coordinator, p, null),
|
||||
),
|
||||
if (preset.isAnime4k) ...[
|
||||
const SizedBox(width: 8),
|
||||
_dropdown<ShaderQuality>(
|
||||
key: const ValueKey('shader-quality'),
|
||||
value: quality,
|
||||
items: [for (final q in ShaderQuality.values) (q, q.label)],
|
||||
onChanged: (q) => applyShaderChoice(AppScope.of(context).coordinator, preset, q),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
below: warning == null
|
||||
? null
|
||||
: Text(warning, style: const TextStyle(fontSize: 12, color: Colors.orange)),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Puts the hwdec setting on the running player (mpv switches decoders
|
||||
/// on the fly). `SYNC_RELAY_HWDEC` wins, as at player start.
|
||||
Future<void> applyHwdecLive(PlaybackController playback) async {
|
||||
if ((Platform.environment['SYNC_RELAY_HWDEC'] ?? '').isNotEmpty) return;
|
||||
final p = playback.current;
|
||||
if (p == null) return;
|
||||
try {
|
||||
await p.setProperty('hwdec', AppSettings.instance.hwdec.peek());
|
||||
} catch (e) {
|
||||
debugPrint('live hwdec failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// mpv's `hwdec`: auto, off, or a custom value. Live.
|
||||
class HwdecSetting extends StatefulWidget {
|
||||
const HwdecSetting({super.key});
|
||||
|
||||
@override
|
||||
State<HwdecSetting> createState() => _HwdecSettingState();
|
||||
}
|
||||
|
||||
class _HwdecSettingState extends State<HwdecSetting> {
|
||||
final _s = AppSettings.instance;
|
||||
late final _custom = TextEditingController(text: _s.hwdecCustom.peek());
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_custom.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SignalBuilder(builder: (context) {
|
||||
final mode = _s.hwdecMode.value;
|
||||
return SettingRow(
|
||||
label: 'Hardware decoding',
|
||||
help: 'Decodes video on the GPU. Turn it off if the picture glitches or stays black',
|
||||
control: _dropdown<HwdecMode>(
|
||||
key: const ValueKey('hwdec'),
|
||||
value: mode,
|
||||
items: const [(HwdecMode.auto, 'Auto'), (HwdecMode.off, 'Off'), (HwdecMode.custom, 'Custom')],
|
||||
onChanged: (m) {
|
||||
_s.setHwdecMode(m);
|
||||
applyHwdecLive(AppScope.of(context).coordinator.playback);
|
||||
},
|
||||
),
|
||||
below: mode != HwdecMode.custom
|
||||
? null
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: TextField(
|
||||
controller: _custom,
|
||||
decoration: const InputDecoration(
|
||||
isDense: true,
|
||||
labelText: 'mpv hwdec value (Enter applies)',
|
||||
hintText: 'e.g. vaapi, nvdec, d3d11va, auto-safe',
|
||||
border: OutlineInputBorder(),
|
||||
),
|
||||
onChanged: _s.setHwdecCustom,
|
||||
onSubmitted: (_) => applyHwdecLive(AppScope.of(context).coordinator.playback),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Audio or subtitle track of the running player (in the player only).
|
||||
/// The pick is remembered for the next Jellyfin item.
|
||||
class TrackSetting extends StatelessWidget {
|
||||
final JellyfinStreamType type;
|
||||
const TrackSetting({super.key, required this.type});
|
||||
|
||||
bool get _audio => type == JellyfinStreamType.audio;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coord = AppScope.of(context).coordinator;
|
||||
return SignalBuilder(builder: (context) {
|
||||
final list = [
|
||||
for (final t in coord.playback.tracks.value)
|
||||
if (t.type == type) t,
|
||||
];
|
||||
// -1: subtitles off.
|
||||
final selected = list.where((t) => t.selected).firstOrNull?.id ?? (_audio ? null : -1);
|
||||
final items = <(int, String)>[
|
||||
if (!_audio) (-1, 'Off'),
|
||||
for (final MpvTrack t in list) (t.id, t.label),
|
||||
];
|
||||
return SettingRow(
|
||||
label: _audio ? 'Audio' : 'Subtitles',
|
||||
help: 'Remembered for the next episode',
|
||||
control: SizedBox(
|
||||
width: 190,
|
||||
child: items.isEmpty || selected == null
|
||||
? Text(items.isEmpty ? 'None' : 'Pick one…',
|
||||
key: ValueKey(_audio ? 'audio-track' : 'subtitle-track'), textAlign: TextAlign.end)
|
||||
: _dropdown<int>(
|
||||
key: ValueKey(_audio ? 'audio-track' : 'subtitle-track'),
|
||||
value: selected,
|
||||
expanded: true,
|
||||
items: items,
|
||||
onChanged: (id) {
|
||||
coord.markInput();
|
||||
if (id == -1) {
|
||||
coord.selectTrack(subtitlesOff: true);
|
||||
} else if (_audio) {
|
||||
coord.selectTrack(aid: id);
|
||||
} else {
|
||||
coord.selectTrack(sid: id);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// The controls' own choices (Settings → Player → Controls).
|
||||
List<Widget> controlsSettingRows() => [
|
||||
const TimeDisplaySetting(),
|
||||
const ControlsSizeSetting(),
|
||||
const HideDelaySetting(),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 10, bottom: 2),
|
||||
child: Text('Buttons in the bar (hidden ones stay in ⚙)', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
),
|
||||
for (final c in OptionalControl.values) BarButtonSetting(control: c),
|
||||
];
|
||||
|
||||
/// The player rows of Settings → Player and the player settings card, in
|
||||
/// order.
|
||||
List<Widget> playerSettingRows({ReadonlySignal<RenderMode>? renderMode}) => [
|
||||
const PlayerDesignSetting(),
|
||||
const ProgressLineSetting(),
|
||||
ShaderPresetSetting(renderMode: renderMode),
|
||||
const HwdecSetting(),
|
||||
];
|
||||
|
||||
/// The player settings card: every player setting, plus the running
|
||||
/// player's tracks.
|
||||
class PlayerSettingsCard extends StatelessWidget {
|
||||
final ReadonlySignal<RenderMode>? renderMode;
|
||||
/// Show the audio / subtitle pickers (a player is running).
|
||||
final bool tracks;
|
||||
const PlayerSettingsCard({super.key, this.renderMode, this.tracks = true});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// The app's glass, like the Up next popover and the menus.
|
||||
return AppGlass(
|
||||
key: const ValueKey('player-settings-card'),
|
||||
child: SizedBox(
|
||||
width: 420,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Text('Player', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 14)),
|
||||
const SizedBox(height: 4),
|
||||
...playerSettingRows(renderMode: renderMode),
|
||||
if (tracks) ...[
|
||||
const Divider(),
|
||||
const TrackSetting(type: JellyfinStreamType.subtitle),
|
||||
const TrackSetting(type: JellyfinStreamType.audio),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Controls layout and custom shaders: Settings → Player',
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant, fontSize: 12),
|
||||
),
|
||||
),
|
||||
const MarkProblemButton(),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens the player settings card over the player, near the controls'
|
||||
/// right end; the controls stay up while it is open.
|
||||
Future<void> showPlayerSettings(BuildContext context, {ReadonlySignal<RenderMode>? renderMode}) =>
|
||||
ControlsFrame.holdWhile(
|
||||
context,
|
||||
() => showPopover<void>(
|
||||
context,
|
||||
at: const Alignment(0.96, 0.5),
|
||||
child: PlayerSettingsCard(renderMode: renderMode),
|
||||
),
|
||||
);
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
|
||||
import '../state/settings.dart';
|
||||
import 'controls_probe.dart' show ControlsHold;
|
||||
import 'frame.dart';
|
||||
import 'minimal/minimal_controls.dart';
|
||||
import 'model/controls_model.dart';
|
||||
import 'model/controls_prefs.dart';
|
||||
import 'standard/standard_controls.dart';
|
||||
|
||||
// The session's controls: one [ControlsFrame] (when they are up) around the
|
||||
// skin the settings pick, both drawing the same [PlayerControlsModel].
|
||||
// Skin, size and the hide delay follow the settings live.
|
||||
|
||||
/// The bottom controls' height in [skin] at [size] (the player's floating
|
||||
/// pills sit just above it).
|
||||
double controlsBottomHeight(ControlsSkin skin, ControlsSize size) => switch (skin) {
|
||||
ControlsSkin.standard => StandardControls.bottomHeight(size.scale),
|
||||
ControlsSkin.minimal => MinimalControls.bottomHeight(size.scale),
|
||||
};
|
||||
|
||||
/// The top bar's height in [skin].
|
||||
double controlsTopHeight(ControlsSkin skin) => switch (skin) {
|
||||
ControlsSkin.standard => StandardControls.topHeight,
|
||||
ControlsSkin.minimal => MinimalControls.topHeight,
|
||||
};
|
||||
|
||||
class SessionControls extends StatelessWidget {
|
||||
final PlayerControlsModel model;
|
||||
|
||||
/// Follows whether the controls are up.
|
||||
final ValueNotifier<bool> shown;
|
||||
final ControlsHold hold;
|
||||
final VoidCallback onDoubleClick;
|
||||
final Widget? windowButtons;
|
||||
const SessionControls({
|
||||
super.key,
|
||||
required this.model,
|
||||
required this.shown,
|
||||
required this.hold,
|
||||
required this.onDoubleClick,
|
||||
this.windowButtons,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final s = AppSettings.instance;
|
||||
return SignalBuilder(
|
||||
builder: (context) {
|
||||
final skin = s.controlsSkin.value;
|
||||
final size = s.controlsSize.value;
|
||||
final scale = size.scale;
|
||||
return ControlsFrame(
|
||||
// A new frame per skin: each starts up, like a fresh mount.
|
||||
key: ValueKey(skin),
|
||||
shown: shown,
|
||||
holdBy: hold,
|
||||
hideAfter: Duration(seconds: s.controlsHideSecs.value),
|
||||
onDoubleClick: onDoubleClick,
|
||||
barTop: controlsTopHeight(skin),
|
||||
barBottom: controlsBottomHeight(skin, size),
|
||||
builder: (context, visible) => switch (skin) {
|
||||
ControlsSkin.standard => StandardControls(
|
||||
model: model,
|
||||
visible: visible,
|
||||
scale: scale,
|
||||
hold: hold,
|
||||
windowButtons: windowButtons,
|
||||
),
|
||||
ControlsSkin.minimal => MinimalControls(
|
||||
model: model,
|
||||
visible: visible,
|
||||
scale: scale,
|
||||
hold: hold,
|
||||
windowButtons: windowButtons,
|
||||
),
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../playback/media_marks.dart';
|
||||
import '../frame.dart';
|
||||
|
||||
// The Standard skin's seek bar: a Material-style track with the played and
|
||||
// buffered parts, chapter marks and a hover tip.
|
||||
|
||||
/// The seek bar: played / buffered track, a diamond at each chapter start
|
||||
/// (not the one at 0), and on hover the time with the chapter title above
|
||||
/// it. Like media_kit's bar it reports a seek on every drag move and on
|
||||
/// release ([onSeek]); the session routes those through the user-seek path
|
||||
/// (debounced, everyone follows).
|
||||
class ChapterSeekBar extends StatefulWidget {
|
||||
final Duration position;
|
||||
final Duration duration;
|
||||
final Duration buffer;
|
||||
final List<MediaChapter> chapters;
|
||||
final ValueChanged<Duration> onSeek;
|
||||
|
||||
/// The bar's height (its hit area); the track is centred in it.
|
||||
final double height;
|
||||
const ChapterSeekBar({
|
||||
super.key,
|
||||
required this.position,
|
||||
required this.duration,
|
||||
this.buffer = Duration.zero,
|
||||
this.chapters = const [],
|
||||
required this.onSeek,
|
||||
this.height = ChapterSeekBar.defaultHeight,
|
||||
});
|
||||
|
||||
static const defaultHeight = 28.0;
|
||||
|
||||
@override
|
||||
State<ChapterSeekBar> createState() => _ChapterSeekBarState();
|
||||
}
|
||||
|
||||
class _ChapterSeekBarState extends State<ChapterSeekBar> {
|
||||
double? _hoverX;
|
||||
bool _dragging = false;
|
||||
double _dragFraction = 0;
|
||||
|
||||
double _fraction(Duration d) {
|
||||
final total = widget.duration.inMicroseconds;
|
||||
if (total <= 0) return 0;
|
||||
return (d.inMicroseconds / total).clamp(0.0, 1.0);
|
||||
}
|
||||
|
||||
Duration _at(double fraction) => widget.duration * fraction.clamp(0.0, 1.0);
|
||||
|
||||
// A drag sends no hover events: the controls are held up through it.
|
||||
void _drag(bool on) {
|
||||
if (_dragging == on) return;
|
||||
setState(() => _dragging = on);
|
||||
ControlsFrame.maybeOf(context)?.hold(on);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_dragging) ControlsFrame.maybeOf(context)?.hold(false);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _seekTo(double x, double width) {
|
||||
if (widget.duration <= Duration.zero || width <= 0) return;
|
||||
_dragFraction = (x / width).clamp(0.0, 1.0);
|
||||
widget.onSeek(_at(_dragFraction));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final primary = Theme.of(context).colorScheme.primary;
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final width = constraints.maxWidth;
|
||||
final active = _hoverX != null || _dragging;
|
||||
final barHeight = active ? 5.0 : 3.0;
|
||||
final played = _dragging ? _dragFraction : _fraction(widget.position);
|
||||
final mid = widget.height / 2;
|
||||
final hoverX = _hoverX;
|
||||
final hoverAt = hoverX == null || width <= 0 ? null : _at(hoverX / width);
|
||||
final hoverChapter = hoverAt == null ? null : chapterIndexAt(widget.chapters, hoverAt);
|
||||
final hoverTitle = hoverChapter == null ? '' : widget.chapters[hoverChapter].title;
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (e) => setState(() => _hoverX = e.localPosition.dx.clamp(0, width)),
|
||||
onHover: (e) => setState(() => _hoverX = e.localPosition.dx.clamp(0, width)),
|
||||
onExit: (_) => setState(() => _hoverX = null),
|
||||
child: Listener(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onPointerDown: (e) {
|
||||
_dragFraction = width <= 0 ? 0 : (e.localPosition.dx / width).clamp(0.0, 1.0);
|
||||
_drag(true);
|
||||
},
|
||||
onPointerMove: (e) {
|
||||
setState(() => _hoverX = e.localPosition.dx.clamp(0, width));
|
||||
_seekTo(e.localPosition.dx, width);
|
||||
},
|
||||
onPointerUp: (e) {
|
||||
_seekTo(e.localPosition.dx, width);
|
||||
_drag(false);
|
||||
},
|
||||
onPointerCancel: (_) => _drag(false),
|
||||
child: SizedBox(
|
||||
key: const ValueKey('seek-bar'),
|
||||
width: width,
|
||||
height: widget.height,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: mid - barHeight / 2,
|
||||
height: barHeight,
|
||||
child: Container(color: Colors.white24),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: mid - barHeight / 2,
|
||||
height: barHeight,
|
||||
width: width * _fraction(widget.buffer),
|
||||
child: Container(color: Colors.white24),
|
||||
),
|
||||
if (hoverX != null && !_dragging)
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: mid - barHeight / 2,
|
||||
height: barHeight,
|
||||
width: hoverX,
|
||||
child: Container(color: Colors.white24),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: mid - barHeight / 2,
|
||||
height: barHeight,
|
||||
width: width * played,
|
||||
child: Container(color: primary),
|
||||
),
|
||||
for (final c in widget.chapters)
|
||||
if (c.start > Duration.zero && widget.duration > Duration.zero)
|
||||
Positioned(
|
||||
key: ValueKey('chapter-mark-${c.index}'),
|
||||
left: width * _fraction(c.start) - 4,
|
||||
top: mid - 4,
|
||||
width: 8,
|
||||
height: 8,
|
||||
child: IgnorePointer(
|
||||
child: Transform.rotate(
|
||||
angle: math.pi / 4,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(1),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(color: Colors.black54, width: 0.8),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (active)
|
||||
Positioned(
|
||||
left: width * played - 6,
|
||||
top: mid - 6,
|
||||
width: 12,
|
||||
height: 12,
|
||||
child: IgnorePointer(
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(color: primary, shape: BoxShape.circle),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hoverAt != null)
|
||||
Positioned(
|
||||
// Kept clear of the window edges (the tip is centred).
|
||||
left: hoverX!.clamp(math.min(60.0, width / 2), math.max(width - 60, width / 2)),
|
||||
bottom: widget.height - 2,
|
||||
child: IgnorePointer(
|
||||
child: FractionalTranslation(
|
||||
translation: const Offset(-0.5, 0),
|
||||
child: _HoverTip(title: hoverTitle, time: formatClock(hoverAt)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _HoverTip extends StatelessWidget {
|
||||
final String title;
|
||||
final String time;
|
||||
const _HoverTip({required this.title, required this.time});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
constraints: const BoxConstraints(maxWidth: 320),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(color: Colors.black.withValues(alpha: 0.8), borderRadius: BorderRadius.circular(6)),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (title.isNotEmpty)
|
||||
Text(
|
||||
title,
|
||||
key: const ValueKey('seek-hover-chapter'),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w600),
|
||||
),
|
||||
Text(
|
||||
time,
|
||||
key: const ValueKey('seek-hover-time'),
|
||||
style: const TextStyle(color: Colors.white70, fontSize: 11),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
import 'package:sync_relay_core/core.dart' show JellyfinStreamType;
|
||||
|
||||
import '../../queue/queue_ui.dart';
|
||||
import '../../shell/now_playing_title.dart';
|
||||
import '../../state/settings.dart';
|
||||
import '../control_menus.dart';
|
||||
import '../controls_probe.dart' show ControlsHold;
|
||||
import '../frame.dart';
|
||||
import '../model/controls_layout.dart';
|
||||
import '../model/controls_model.dart';
|
||||
import '../volume.dart';
|
||||
import 'seek_bar.dart';
|
||||
|
||||
// The Standard skin: Material-style bars over the picture. Top: what plays,
|
||||
// Up next and the window controls; bottom: the seek bar (chapter marks,
|
||||
// hover time) over a row of round icon buttons in the layout's order.
|
||||
// Hidden, a thin progress line stays (unless switched off).
|
||||
|
||||
class StandardControls extends StatelessWidget {
|
||||
final PlayerControlsModel model;
|
||||
final bool visible;
|
||||
final double scale;
|
||||
final ControlsHold? hold;
|
||||
|
||||
/// Right of the top bar's own buttons (the window buttons in fullscreen).
|
||||
final Widget? windowButtons;
|
||||
const StandardControls({
|
||||
super.key,
|
||||
required this.model,
|
||||
required this.visible,
|
||||
this.scale = 1,
|
||||
this.hold,
|
||||
this.windowButtons,
|
||||
});
|
||||
|
||||
/// The top bar: room for the cover (2:3, 60 px tall).
|
||||
static const topHeight = 72.0;
|
||||
static const _rowHeight = 56.0;
|
||||
|
||||
/// The bottom bar (seek bar and buttons) at [scale].
|
||||
static double bottomHeight(double scale) => (_rowHeight + ChapterSeekBar.defaultHeight) * scale;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const fade = ControlsFrame.fade;
|
||||
Widget bar(Widget child) => IgnorePointer(
|
||||
ignoring: !visible,
|
||||
child: AnimatedOpacity(duration: fade, opacity: visible ? 1 : 0, child: child),
|
||||
);
|
||||
// No button here takes focus (Space is the ready key); the top bar's
|
||||
// Up next keeps its own (its popover has a text field).
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 0,
|
||||
child: bar(
|
||||
DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Color(0x99000000), Color(0x00000000)],
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
key: const ValueKey('standard-top'),
|
||||
height: topHeight,
|
||||
child: Padding(padding: const EdgeInsets.only(left: 16, right: 8), child: _top()),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: bar(
|
||||
DecoratedBox(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Color(0x00000000), Color(0xB3000000)],
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 24 * scale),
|
||||
child: SizedBox(
|
||||
key: const ValueKey('standard-bottom'),
|
||||
height: bottomHeight(scale),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: SignalBuilder(
|
||||
builder: (context) => ChapterSeekBar(
|
||||
position: model.position.value,
|
||||
duration: model.duration.value,
|
||||
buffer: model.buffered.value,
|
||||
chapters: model.chapters.value,
|
||||
height: ChapterSeekBar.defaultHeight * scale,
|
||||
onSeek: model.seek,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: ExcludeFocus(
|
||||
child: SignalBuilder(
|
||||
builder: (context) {
|
||||
final s = model.snapshot.value;
|
||||
final layout = model.bar.value;
|
||||
return Row(
|
||||
key: const ValueKey('standard-buttons'),
|
||||
children: [
|
||||
for (final c in layout.left) _control(context, c, s),
|
||||
const Spacer(),
|
||||
for (final c in layout.right) _control(context, c, s),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Hidden: the thin progress line.
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: IgnorePointer(
|
||||
child: SignalBuilder(
|
||||
builder: (context) {
|
||||
if (visible || !AppSettings.instance.progressLine.value) return const SizedBox.shrink();
|
||||
final d = model.duration.value, p = model.position.value;
|
||||
final v = d.inMilliseconds == 0 ? 0.0 : (p.inMilliseconds / d.inMilliseconds).clamp(0.0, 1.0);
|
||||
return LinearProgressIndicator(
|
||||
key: const ValueKey('progress-line-standard'),
|
||||
value: v,
|
||||
minHeight: 2,
|
||||
backgroundColor: Colors.transparent,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _top() {
|
||||
final m = model;
|
||||
return Row(
|
||||
children: [
|
||||
const Expanded(child: NowPlayingTitle()),
|
||||
UpNextButton(queue: m.queue, look: UpNextLook.standard, hold: hold),
|
||||
SignalBuilder(
|
||||
builder: (context) {
|
||||
final full = m.fullscreen.value;
|
||||
return ExcludeFocus(
|
||||
child: _IconButton(
|
||||
key: const ValueKey('standard-collapse'),
|
||||
icon: full ? Icons.fullscreen_exit_rounded : Icons.close_fullscreen_rounded,
|
||||
tooltip: full ? 'Exit fullscreen (Esc)' : 'Back to the library (keeps playing)',
|
||||
onPressed: full ? m.toggleFullscreen : m.collapse,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
?windowButtons,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _control(BuildContext context, BarControl c, ControlsSnapshot s) {
|
||||
final m = model;
|
||||
final key = ValueKey('control-${c.name}');
|
||||
final enabled = controlEnabled(c, s);
|
||||
Widget icon(VoidCallback? onPressed, {int badge = 0, double size = 24, Color? color}) => _IconButton(
|
||||
key: key,
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
badge: badge,
|
||||
size: size * scale,
|
||||
color: color,
|
||||
onPressed: enabled ? onPressed : null,
|
||||
);
|
||||
switch (c) {
|
||||
case BarControl.playPause:
|
||||
final waiting = s.play == PlayState.waiting;
|
||||
return icon(m.togglePlay, size: 30, color: waiting ? Theme.of(context).colorScheme.primary : null);
|
||||
case BarControl.previous:
|
||||
return icon(m.previous);
|
||||
case BarControl.next:
|
||||
return icon(m.next);
|
||||
case BarControl.chapterPrevious:
|
||||
return icon(() => m.stepChapter(-1));
|
||||
case BarControl.chapterNext:
|
||||
return icon(() => m.stepChapter(1));
|
||||
case BarControl.volume:
|
||||
return SignalBuilder(
|
||||
key: key,
|
||||
builder: (context) => VolumeControl(
|
||||
volume: m.volume.value,
|
||||
onChanged: m.setVolume,
|
||||
onToggleMute: m.toggleMute,
|
||||
button: (context, i, color, tip, onPressed) =>
|
||||
_IconButton(icon: i, tooltip: tip, color: color, size: 24 * scale, onPressed: onPressed),
|
||||
),
|
||||
);
|
||||
case BarControl.time:
|
||||
return SignalBuilder(
|
||||
key: key,
|
||||
builder: (context) => _Clock(
|
||||
text: clockText(m.position.value, m.duration.value, m.settings.timeDisplay.value),
|
||||
tooltip: controlTooltip(c, s),
|
||||
scale: scale,
|
||||
onPressed: m.toggleTimeDisplay,
|
||||
),
|
||||
);
|
||||
case BarControl.subtitles || BarControl.audio:
|
||||
final type = c == BarControl.audio ? JellyfinStreamType.audio : JellyfinStreamType.subtitle;
|
||||
return SignalBuilder(
|
||||
key: key,
|
||||
builder: (context) => Builder(
|
||||
builder: (context) => _IconButton(
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
badge: trackCount(m.tracks.value, type),
|
||||
size: 22 * scale,
|
||||
onPressed: () => openTrackMenu(context, m, type),
|
||||
),
|
||||
),
|
||||
);
|
||||
case BarControl.settings:
|
||||
return Builder(
|
||||
key: key,
|
||||
builder: (context) => _IconButton(
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
size: 22 * scale,
|
||||
onPressed: () => openControlsMenu(context, m),
|
||||
),
|
||||
);
|
||||
case BarControl.chat:
|
||||
return SignalBuilder(
|
||||
key: key,
|
||||
builder: (context) => _IconButton(
|
||||
icon: controlIcon(c, s),
|
||||
tooltip: controlTooltip(c, s),
|
||||
badge: m.unread.value,
|
||||
size: 22 * scale,
|
||||
onPressed: m.toggleChat,
|
||||
),
|
||||
);
|
||||
case BarControl.fullscreen:
|
||||
return icon(m.toggleFullscreen, size: 26);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A round white icon button with an optional count badge (the Material
|
||||
/// look of media_kit's bar).
|
||||
class _IconButton extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String tooltip;
|
||||
final VoidCallback? onPressed;
|
||||
final int badge;
|
||||
final double size;
|
||||
final Color? color;
|
||||
const _IconButton({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.tooltip,
|
||||
required this.onPressed,
|
||||
this.badge = 0,
|
||||
this.size = 24,
|
||||
this.color,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
return IconButton(
|
||||
tooltip: tooltip,
|
||||
iconSize: size,
|
||||
color: color ?? Colors.white,
|
||||
disabledColor: Colors.white38,
|
||||
onPressed: onPressed,
|
||||
icon: Badge(
|
||||
isLabelVisible: badge > 0,
|
||||
backgroundColor: scheme.primary,
|
||||
textColor: scheme.onPrimary,
|
||||
label: Text('$badge'),
|
||||
child: Icon(icon),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The clock: "6:00 / 24:00" or "-18:00"; a click switches.
|
||||
class _Clock extends StatelessWidget {
|
||||
final String text;
|
||||
final String tooltip;
|
||||
final double scale;
|
||||
final VoidCallback onPressed;
|
||||
const _Clock({required this.text, required this.tooltip, required this.scale, required this.onPressed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Tooltip(
|
||||
message: tooltip,
|
||||
waitDuration: const Duration(milliseconds: 500),
|
||||
child: TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
padding: EdgeInsets.symmetric(horizontal: 10 * scale),
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(fontSize: 14 * scale, fontFeatures: const [FontFeature.tabularFigures()]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart' show ValueListenable;
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../playback/playback_controller.dart' show PlaybackController;
|
||||
import '../widgets/app_menu.dart' show AppGlass;
|
||||
|
||||
/// The player's top volume (mpv's `volume-max`): past 100 % mpv amplifies.
|
||||
const maxVolume = PlaybackController.maxVolume * 1.0;
|
||||
|
||||
/// The part of the volume bar above 100 %.
|
||||
const boostColor = Color(0xFFFFB74D);
|
||||
|
||||
/// One wheel notch or arrow key.
|
||||
const volumeStep = 5.0;
|
||||
|
||||
/// [volume] moved by [delta] (wheel, keys), kept within 0..[maxVolume].
|
||||
double stepVolume(double volume, double delta) => (volume + delta).clamp(0.0, maxVolume);
|
||||
|
||||
/// Turns wheel deltas into volume steps: a mouse notch (a big delta) is
|
||||
/// one step, small smooth-scroll deltas add up to one. Mostly horizontal
|
||||
/// scrolls (Shift+wheel, sideways pans) are no steps.
|
||||
class WheelSteps {
|
||||
// Flutter makes a notch 53 px on Linux, 60 on Windows (3 lines).
|
||||
static const _notch = 50.0;
|
||||
double _sum = 0;
|
||||
|
||||
/// Whether [e] is a vertical scroll (the only kind that steps).
|
||||
static bool vertical(PointerSignalEvent e) =>
|
||||
e is PointerScrollEvent && e.scrollDelta.dy != 0 && e.scrollDelta.dy.abs() > e.scrollDelta.dx.abs();
|
||||
|
||||
/// +1 louder (wheel up), -1 quieter, 0 not a step yet.
|
||||
int take(PointerScrollEvent e) {
|
||||
final dy = e.scrollDelta.dy;
|
||||
if (dy.abs() >= _notch) {
|
||||
_sum = 0;
|
||||
return dy < 0 ? 1 : -1;
|
||||
}
|
||||
if (_sum != 0 && _sum.sign != dy.sign) _sum = 0;
|
||||
_sum += dy;
|
||||
if (_sum.abs() < _notch) return 0;
|
||||
final step = _sum < 0 ? 1 : -1;
|
||||
_sum = 0;
|
||||
return step;
|
||||
}
|
||||
|
||||
/// Claims [e] if it is a vertical scroll that nothing under the mouse
|
||||
/// claimed first (a list, a menu), then calls [onStep] per step.
|
||||
void handle(PointerSignalEvent e, ValueChanged<int> onStep) {
|
||||
if (!vertical(e)) return;
|
||||
GestureBinding.instance.pointerSignalResolver.register(e, (event) {
|
||||
final step = take(event as PointerScrollEvent);
|
||||
if (step != 0) onStep(step);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// The wheel anywhere over [child] steps the volume ([onStep]: +1 / -1),
|
||||
/// unless something under the mouse scrolls (it claims the event first)
|
||||
/// or [enabled] is off.
|
||||
class VolumeWheel extends StatefulWidget {
|
||||
final ValueChanged<int> onStep;
|
||||
final bool enabled;
|
||||
final Widget child;
|
||||
const VolumeWheel({super.key, required this.onStep, this.enabled = true, required this.child});
|
||||
|
||||
@override
|
||||
State<VolumeWheel> createState() => _VolumeWheelState();
|
||||
}
|
||||
|
||||
class _VolumeWheelState extends State<VolumeWheel> {
|
||||
final _steps = WheelSteps();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Listener(
|
||||
onPointerSignal: (e) {
|
||||
if (widget.enabled) _steps.handle(e, widget.onStep);
|
||||
},
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
/// Shows [builder] for a second after each [trigger] tick (a wheel or
|
||||
/// key volume step), fading in and out; ignores the mouse.
|
||||
class VolumeFlash extends StatefulWidget {
|
||||
final ValueListenable<int> trigger;
|
||||
final WidgetBuilder builder;
|
||||
const VolumeFlash({super.key, required this.trigger, required this.builder});
|
||||
|
||||
/// How long the readout stays after the last step.
|
||||
static const hold = Duration(seconds: 1);
|
||||
|
||||
@override
|
||||
State<VolumeFlash> createState() => _VolumeFlashState();
|
||||
}
|
||||
|
||||
class _VolumeFlashState extends State<VolumeFlash> {
|
||||
bool _on = false;
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.trigger.addListener(_flash);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(VolumeFlash old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (old.trigger != widget.trigger) {
|
||||
old.trigger.removeListener(_flash);
|
||||
widget.trigger.addListener(_flash);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
widget.trigger.removeListener(_flash);
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _flash() {
|
||||
if (!mounted) return;
|
||||
setState(() => _on = true);
|
||||
_timer?.cancel();
|
||||
_timer = Timer(VolumeFlash.hold, () {
|
||||
if (mounted) setState(() => _on = false);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => IgnorePointer(
|
||||
child: AnimatedOpacity(
|
||||
duration: const Duration(milliseconds: 150),
|
||||
opacity: _on ? 1 : 0,
|
||||
child: _on || _timer != null ? widget.builder(context) : const SizedBox.shrink(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// The volume readout for [VolumeFlash] (both skins): a glass pill
|
||||
/// (the player's pill look) with the icon, a [VolumeBar] and the
|
||||
/// percentage.
|
||||
class VolumeReadout extends StatelessWidget {
|
||||
final double volume;
|
||||
const VolumeReadout({super.key, required this.volume});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final v = volume.clamp(0.0, maxVolume);
|
||||
return AppGlass.pill(
|
||||
key: const ValueKey('volume-readout'),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 4, 14, 4),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(volumeIcon(v), size: 20, color: v > 100 ? boostColor : Colors.white),
|
||||
const SizedBox(width: 8),
|
||||
VolumeBar(volume: v, onChanged: (_) {}, width: 96),
|
||||
const SizedBox(width: 10),
|
||||
SizedBox(
|
||||
width: 44,
|
||||
child: Text(
|
||||
'${v.round()} %',
|
||||
textAlign: TextAlign.right,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 13, fontFeatures: [FontFeature.tabularFigures()]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A thin volume track over 0..[maxVolume]: filled up to the volume, the
|
||||
/// part above 100 % in [boostColor], a tick at 100 %. Click or drag sets
|
||||
/// it.
|
||||
class VolumeBar extends StatelessWidget {
|
||||
final double volume;
|
||||
final ValueChanged<double> onChanged;
|
||||
final double width;
|
||||
final Color color;
|
||||
final Color trackColor;
|
||||
const VolumeBar({
|
||||
super.key,
|
||||
required this.volume,
|
||||
required this.onChanged,
|
||||
this.width = 64,
|
||||
this.color = Colors.white,
|
||||
this.trackColor = Colors.white30,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
void at(double x) => onChanged((x / width * maxVolume).clamp(0.0, maxVolume).roundToDouble());
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTapDown: (e) => at(e.localPosition.dx),
|
||||
onHorizontalDragUpdate: (e) => at(e.localPosition.dx),
|
||||
child: SizedBox(
|
||||
width: width,
|
||||
height: 24,
|
||||
child: CustomPaint(painter: _VolumePainter(volume.clamp(0.0, maxVolume), color, trackColor)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _VolumePainter extends CustomPainter {
|
||||
final double volume;
|
||||
final Color color, trackColor;
|
||||
_VolumePainter(this.volume, this.color, this.trackColor);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final y = size.height / 2;
|
||||
double x(double v) => size.width * v / maxVolume;
|
||||
final line = Paint()
|
||||
..strokeWidth = 3
|
||||
..strokeCap = StrokeCap.round;
|
||||
canvas.drawLine(Offset(0, y), Offset(size.width, y), line..color = trackColor);
|
||||
final full = x(100);
|
||||
canvas.drawLine(
|
||||
Offset(full, y - 5),
|
||||
Offset(full, y + 5),
|
||||
Paint()
|
||||
..color = trackColor
|
||||
..strokeWidth = 1.5,
|
||||
);
|
||||
if (volume > 0) canvas.drawLine(Offset(0, y), Offset(x(volume.clamp(0, 100)), y), line..color = color);
|
||||
if (volume > 100) canvas.drawLine(Offset(full, y), Offset(x(volume), y), line..color = boostColor);
|
||||
canvas.drawCircle(Offset(x(volume), y), 5, Paint()..color = volume > 100 ? boostColor : color);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(_VolumePainter old) => old.volume != volume || old.color != color || old.trackColor != trackColor;
|
||||
}
|
||||
|
||||
/// The speaker icon for [volume].
|
||||
IconData volumeIcon(double volume) =>
|
||||
volume <= 0 ? Icons.volume_off_rounded : (volume < 50 ? Icons.volume_down_rounded : Icons.volume_up_rounded);
|
||||
|
||||
/// Builds a skin's button for the [VolumeControl].
|
||||
typedef VolumeButtonBuilder = Widget Function(
|
||||
BuildContext context,
|
||||
IconData icon,
|
||||
Color? color,
|
||||
String tooltip,
|
||||
VoidCallback onPressed,
|
||||
);
|
||||
|
||||
/// The bar's volume, in both skins: the skin's speaker button (click
|
||||
/// mutes / unmutes), a [VolumeBar] sliding out on hover, the wheel on it
|
||||
/// stepping [volumeStep] (claimed, so the player's wheel skips it).
|
||||
class VolumeControl extends StatefulWidget {
|
||||
/// 0..[maxVolume].
|
||||
final double volume;
|
||||
final ValueChanged<double> onChanged;
|
||||
final VoidCallback onToggleMute;
|
||||
final VolumeButtonBuilder button;
|
||||
final Color sliderColor;
|
||||
final Color trackColor;
|
||||
final double sliderWidth;
|
||||
const VolumeControl({
|
||||
super.key,
|
||||
required this.volume,
|
||||
required this.onChanged,
|
||||
required this.onToggleMute,
|
||||
required this.button,
|
||||
this.sliderColor = Colors.white,
|
||||
this.trackColor = Colors.white30,
|
||||
this.sliderWidth = 72,
|
||||
});
|
||||
|
||||
@override
|
||||
State<VolumeControl> createState() => _VolumeControlState();
|
||||
}
|
||||
|
||||
class _VolumeControlState extends State<VolumeControl> {
|
||||
final _steps = WheelSteps();
|
||||
bool _hover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final v = widget.volume;
|
||||
return MouseRegion(
|
||||
onEnter: (_) => setState(() => _hover = true),
|
||||
onExit: (_) => setState(() => _hover = false),
|
||||
child: Listener(
|
||||
onPointerSignal: (e) => _steps.handle(e, (step) => widget.onChanged(stepVolume(v, step * volumeStep))),
|
||||
child: Row(
|
||||
key: const ValueKey('volume-control'),
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
widget.button(
|
||||
context,
|
||||
volumeIcon(v),
|
||||
v > 100 ? boostColor : null,
|
||||
'Volume ${v.round()} % (scroll, ↑ / ↓)',
|
||||
widget.onToggleMute,
|
||||
),
|
||||
AnimatedSize(
|
||||
duration: const Duration(milliseconds: 150),
|
||||
child: _hover
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(left: 4, right: 8),
|
||||
child: VolumeBar(
|
||||
key: const ValueKey('volume-bar'),
|
||||
volume: v,
|
||||
onChanged: widget.onChanged,
|
||||
width: widget.sliderWidth,
|
||||
color: widget.sliderColor,
|
||||
trackColor: widget.trackColor,
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
|
||||
// Files source state, one Hive box: the folders the user added and the
|
||||
// local files played last. Same shape as AppSettings: signals start empty,
|
||||
// take the stored values once [FolderStore.ensureLoaded] finishes, and
|
||||
// mutators write through.
|
||||
|
||||
const filesBoxName = 'files';
|
||||
|
||||
const _keyFolders = 'folders';
|
||||
const _keyRecent = 'recent';
|
||||
|
||||
/// Recent files kept, most recent first.
|
||||
const maxRecentFiles = 30;
|
||||
|
||||
class FolderStore {
|
||||
static final FolderStore instance = FolderStore();
|
||||
|
||||
/// Watched folders, in the order they were added.
|
||||
final folders = signal<List<String>>(const []);
|
||||
/// Local files played, most recent first, no duplicates.
|
||||
final recent = signal<List<String>>(const []);
|
||||
|
||||
Future<void>? _load;
|
||||
Box? _box;
|
||||
|
||||
Future<void> ensureLoaded() => _load ??= _loadNow();
|
||||
|
||||
Future<void> _loadNow() async {
|
||||
try {
|
||||
final box = _box = await Hive.openBox(filesBoxName);
|
||||
final f = box.get(_keyFolders);
|
||||
if (f is List) folders.value = List.unmodifiable(f.whereType<String>());
|
||||
final r = box.get(_keyRecent);
|
||||
if (r is List) {
|
||||
recent.value = List.unmodifiable(
|
||||
r.whereType<String>().toSet().take(maxRecentFiles));
|
||||
}
|
||||
} catch (e, st) {
|
||||
debugPrint('load files store failed: $e\n$st');
|
||||
}
|
||||
}
|
||||
|
||||
/// False when [dir] is already watched.
|
||||
bool addFolder(String dir) {
|
||||
if (folders.value.contains(dir)) return false;
|
||||
_setFolders([...folders.value, dir]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeFolder(String dir) =>
|
||||
_setFolders([...folders.value.where((d) => d != dir)]);
|
||||
|
||||
/// Moves [path] to the top of [recent].
|
||||
void addRecent(String path) => _setRecent(
|
||||
[path, ...recent.value.where((p) => p != path)].take(maxRecentFiles));
|
||||
|
||||
void removeRecent(String path) =>
|
||||
_setRecent(recent.value.where((p) => p != path));
|
||||
|
||||
void clearRecent() => _setRecent(const []);
|
||||
|
||||
void _setFolders(List<String> list) {
|
||||
folders.value = List.unmodifiable(list);
|
||||
_put(_keyFolders, [...list]);
|
||||
}
|
||||
|
||||
void _setRecent(Iterable<String> list) {
|
||||
recent.value = List.unmodifiable(list);
|
||||
_put(_keyRecent, [...recent.value]);
|
||||
}
|
||||
|
||||
Future<void> _put(String key, Object value) async {
|
||||
try {
|
||||
final box = _box ??
|
||||
(Hive.isBoxOpen(filesBoxName) ? Hive.box(filesBoxName) : null);
|
||||
await box?.put(key, value);
|
||||
} catch (e, st) {
|
||||
debugPrint('save files store $key failed: $e\n$st');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
export 'package:sync_relay_core/core.dart' show FileKind, LocalFile, kindOf, subtitleExtensions, videoExtensions;
|
||||
|
||||
// Folder scan for the Files source: the videos (grouped into shows by
|
||||
// core's `groupLocal`, L1), sidecar subtitles, everything else counted
|
||||
// and hidden. The walk is synchronous I/O, so it runs in its own isolate.
|
||||
|
||||
/// Files looked at per scan; past this the result is [FolderScan.truncated].
|
||||
const maxScannedFiles = 20000;
|
||||
|
||||
/// Samples and trailers under this size are hidden next to the real thing.
|
||||
const _sampleMaxBytes = 300 << 20;
|
||||
|
||||
class FolderScan {
|
||||
final List<LocalFile> videos;
|
||||
/// Non-video files and samples (subtitles and dot-entries not counted).
|
||||
final int hiddenCount;
|
||||
/// Up to 6 of the hidden file names, for "and N other files" hints.
|
||||
final List<String> hiddenExamples;
|
||||
/// Video path -> subtitle files next to it with the same base name
|
||||
/// (`Ep 01.mkv` -> `Ep 01.srt`, `Ep 01.en.ass`).
|
||||
final Map<String, List<String>> subtitles;
|
||||
/// Stopped after [maxScannedFiles] files.
|
||||
final bool truncated;
|
||||
|
||||
const FolderScan({
|
||||
required this.videos,
|
||||
required this.hiddenCount,
|
||||
required this.hiddenExamples,
|
||||
required this.subtitles,
|
||||
required this.truncated,
|
||||
});
|
||||
|
||||
static const empty = FolderScan(
|
||||
videos: [],
|
||||
hiddenCount: 0,
|
||||
hiddenExamples: [],
|
||||
subtitles: {},
|
||||
truncated: false,
|
||||
);
|
||||
}
|
||||
|
||||
/// Scans [dir] recursively off the UI isolate. Symlinks are not followed,
|
||||
/// hidden (dot) files and folders are skipped, unreadable subfolders are
|
||||
/// left out; never throws (a missing folder is [FolderScan.empty]).
|
||||
Future<FolderScan> scanFolder(String dir, {int maxFiles = maxScannedFiles}) =>
|
||||
Isolate.run(() => scanFolderSync(dir, maxFiles: maxFiles))
|
||||
.catchError((Object _) => FolderScan.empty);
|
||||
|
||||
/// The walk behind [scanFolder]; blocks, so call it from an isolate.
|
||||
FolderScan scanFolderSync(String dir, {int maxFiles = maxScannedFiles}) {
|
||||
final videos = <LocalFile>[];
|
||||
final subs = <String>[];
|
||||
final examples = <String>[];
|
||||
var hidden = 0, seen = 0;
|
||||
var truncated = false;
|
||||
final pending = [Directory(dir)];
|
||||
walk:
|
||||
while (pending.isNotEmpty) {
|
||||
final List<FileSystemEntity> entries;
|
||||
try {
|
||||
entries = pending.removeLast().listSync(followLinks: false);
|
||||
} catch (_) {
|
||||
continue;
|
||||
}
|
||||
entries.sort((a, b) => a.path.compareTo(b.path));
|
||||
for (final e in entries) {
|
||||
final name = _baseName(e.path);
|
||||
if (name.startsWith('.')) continue;
|
||||
if (e is Directory) {
|
||||
pending.add(e);
|
||||
continue;
|
||||
}
|
||||
if (e is! File) continue; // links
|
||||
if (++seen > maxFiles) {
|
||||
truncated = true;
|
||||
break walk;
|
||||
}
|
||||
final kind = kindOf(name);
|
||||
if (kind == FileKind.subtitle) {
|
||||
subs.add(e.path);
|
||||
continue;
|
||||
}
|
||||
FileStat? stat;
|
||||
if (kind == FileKind.video) {
|
||||
try {
|
||||
stat = e.statSync();
|
||||
} catch (_) {}
|
||||
}
|
||||
final size = stat?.size ?? 0;
|
||||
final lower = name.toLowerCase();
|
||||
final sample = kind == FileKind.video &&
|
||||
(lower.contains('sample') || lower.contains('trailer')) &&
|
||||
size < _sampleMaxBytes;
|
||||
if (kind != FileKind.video || sample) {
|
||||
hidden++;
|
||||
if (examples.length < 6) examples.add(name);
|
||||
continue;
|
||||
}
|
||||
videos.add(LocalFile(e.path, size, stat?.modified ?? DateTime.fromMillisecondsSinceEpoch(0)));
|
||||
}
|
||||
}
|
||||
return FolderScan(
|
||||
videos: videos,
|
||||
hiddenCount: hidden,
|
||||
hiddenExamples: examples,
|
||||
subtitles: _sidecars(videos, subs),
|
||||
truncated: truncated,
|
||||
);
|
||||
}
|
||||
|
||||
/// Subtitles in the same folder whose name is the video's base name,
|
||||
/// optionally followed by `.lang` / `.forced` style suffixes.
|
||||
Map<String, List<String>> _sidecars(List<LocalFile> videos, List<String> subs) {
|
||||
final byStem = <String, List<String>>{};
|
||||
for (final s in subs) {
|
||||
final stem = _stripExtension(s);
|
||||
byStem.putIfAbsent(stem, () => []).add(s);
|
||||
// `Ep 01.en.ass`, `Ep 01.en.forced.ass`: also index the shorter stems.
|
||||
var shorter = stem;
|
||||
for (var i = 0; i < 2; i++) {
|
||||
final dot = shorter.lastIndexOf('.');
|
||||
if (dot <= shorter.lastIndexOf(RegExp(r'[/\\]')) + 1) break;
|
||||
final suffix = shorter.substring(dot + 1);
|
||||
// Language / flag tags only (en, eng, pt-BR, forced, sdh): a suffix
|
||||
// with digits is part of the name (`Show.S01E01.srt` is not `Show`'s).
|
||||
if (!RegExp(r'^[A-Za-z]{2,8}(-[A-Za-z]{2,4})?$').hasMatch(suffix)) break;
|
||||
shorter = shorter.substring(0, dot);
|
||||
byStem.putIfAbsent(shorter, () => []).add(s);
|
||||
}
|
||||
}
|
||||
return {
|
||||
for (final v in videos)
|
||||
if (byStem[_stripExtension(v.path)] case final list?)
|
||||
v.path: (list.toSet().toList()..sort()),
|
||||
};
|
||||
}
|
||||
|
||||
String _baseName(String path) {
|
||||
final i = path.lastIndexOf(RegExp(r'[/\\]'));
|
||||
return i < 0 ? path : path.substring(i + 1);
|
||||
}
|
||||
|
||||
String _stripExtension(String path) {
|
||||
final dot = path.lastIndexOf('.');
|
||||
final sep = path.lastIndexOf(RegExp(r'[/\\]'));
|
||||
return dot > sep + 1 ? path.substring(0, dot) : path;
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import '../platform/desktop/media_kit_host.dart' show MediaKitHost;
|
||||
import '../platform/ports/player_host.dart';
|
||||
|
||||
// Poster frames for the Files source, made by mpv itself (no ffmpeg on
|
||||
// users' machines; Windows ships only libmpv). A hidden player per file
|
||||
// with `vo=null`: mpv still keeps the last decoded frame, so
|
||||
// `screenshot-to-file` encodes it with mpv's own JPEG writer. `start=25%`
|
||||
// makes the first decoded frame the one we want, `vf=scale` keeps it
|
||||
// small. Results (and failures) are cached on disk by path+size+mtime.
|
||||
|
||||
class Thumbnail {
|
||||
/// JPEG on disk, at most [thumbnailWidth] wide.
|
||||
final String imagePath;
|
||||
final Duration duration;
|
||||
const Thumbnail(this.imagePath, this.duration);
|
||||
}
|
||||
|
||||
const thumbnailWidth = 480;
|
||||
|
||||
/// The players thumbnails are made with (the app's host, set in `main`).
|
||||
PlayerHost thumbnailPlayers = MediaKitHost()..init();
|
||||
|
||||
/// Where thumbnails are cached; swapped in tests.
|
||||
Future<Directory> Function() thumbnailCacheRoot = getApplicationCacheDirectory;
|
||||
|
||||
/// Generations running at once: each is a full decoder.
|
||||
const _maxConcurrent = 2;
|
||||
const _timeout = Duration(seconds: 20);
|
||||
|
||||
int _running = 0;
|
||||
final _waiting = <Completer<void>>[];
|
||||
final _inFlight = <String, Future<Thumbnail?>>{};
|
||||
final _players = <HostedPlayer>{};
|
||||
bool _closed = false;
|
||||
|
||||
/// App close: no new thumbnails, running ones stop at their next check
|
||||
/// and dispose their player. Players still up after [deadline] are
|
||||
/// disposed here, so no mpv outlives the engine.
|
||||
Future<void> cancelAllThumbnails({
|
||||
Duration deadline = const Duration(milliseconds: 800),
|
||||
}) async {
|
||||
_closed = true;
|
||||
try {
|
||||
await Future.wait(_inFlight.values.toList()).timeout(deadline);
|
||||
} catch (_) {}
|
||||
for (final p in _players.toList()) {
|
||||
_players.remove(p);
|
||||
try {
|
||||
await thumbnailPlayers.dispose(p).timeout(deadline);
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
/// The cached or freshly made thumbnail of the video at [path], or null
|
||||
/// when it can't be made (not a video, unreadable, timed out, cancelled).
|
||||
/// Never throws. [cancelled] is checked while queued and before the
|
||||
/// expensive steps: a scrolled-away tile returns null without decoding.
|
||||
Future<Thumbnail?> thumbnailFor(String path, {bool Function()? cancelled}) {
|
||||
if (_closed) return Future.value(null);
|
||||
final existing = _inFlight[path];
|
||||
if (existing != null) return existing;
|
||||
final f = _thumbnailFor(path, () => _closed || (cancelled?.call() ?? false)).catchError((
|
||||
Object e,
|
||||
StackTrace st,
|
||||
) {
|
||||
debugPrint('thumbnail $path failed: $e\n$st');
|
||||
return null;
|
||||
});
|
||||
_inFlight[path] = f;
|
||||
f.whenComplete(() => _inFlight.remove(path));
|
||||
return f;
|
||||
}
|
||||
|
||||
/// Cache key: the same file at the same size and mtime reuses its frame.
|
||||
String thumbnailKey(String path, int size, DateTime modified) => sha1
|
||||
.convert(utf8.encode('$path|$size|${modified.millisecondsSinceEpoch}'))
|
||||
.toString();
|
||||
|
||||
Future<Thumbnail?> _thumbnailFor(String path, bool Function() cancelled) async {
|
||||
final stat = await File(path).stat();
|
||||
if (stat.type != FileSystemEntityType.file) return null;
|
||||
final dir = Directory(
|
||||
'${(await thumbnailCacheRoot()).path}${Platform.pathSeparator}thumbnails');
|
||||
await dir.create(recursive: true);
|
||||
final base =
|
||||
'${dir.path}${Platform.pathSeparator}${thumbnailKey(path, stat.size, stat.modified)}';
|
||||
final cached = await _readCache(base);
|
||||
if (cached != null) return cached.$1;
|
||||
|
||||
if (cancelled()) return null;
|
||||
await _acquire();
|
||||
try {
|
||||
if (cancelled()) return null;
|
||||
final made = await _generate(path, '$base.jpg', cancelled)
|
||||
.timeout(_timeout, onTimeout: () => null);
|
||||
if (made == null) {
|
||||
// Remember broken files, not cancellations.
|
||||
if (!cancelled()) await File('$base.json').writeAsString('{}');
|
||||
return null;
|
||||
}
|
||||
await File('$base.json')
|
||||
.writeAsString(jsonEncode({'ms': made.duration.inMilliseconds}));
|
||||
return made;
|
||||
} finally {
|
||||
_release();
|
||||
}
|
||||
}
|
||||
|
||||
/// (thumbnail or null for a remembered failure), or null when not cached.
|
||||
Future<(Thumbnail?,)?> _readCache(String base) async {
|
||||
try {
|
||||
final meta = File('$base.json');
|
||||
if (!await meta.exists()) return null;
|
||||
final ms = (jsonDecode(await meta.readAsString()) as Map)['ms'];
|
||||
if (ms is! int) return (null,);
|
||||
final jpg = File('$base.jpg');
|
||||
if (!await jpg.exists()) return null;
|
||||
return (Thumbnail(jpg.path, Duration(milliseconds: ms)),);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _acquire() async {
|
||||
if (_running < _maxConcurrent) {
|
||||
_running++;
|
||||
return;
|
||||
}
|
||||
final c = Completer<void>();
|
||||
_waiting.add(c);
|
||||
await c.future; // the releaser hands its slot over
|
||||
}
|
||||
|
||||
void _release() {
|
||||
if (_waiting.isNotEmpty) {
|
||||
_waiting.removeAt(0).complete();
|
||||
} else {
|
||||
_running--;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Thumbnail?> _generate(
|
||||
String path,
|
||||
String out,
|
||||
bool Function() cancelled,
|
||||
) async {
|
||||
final player = await thumbnailPlayers.create(PlayerRole.thumbnail);
|
||||
_players.add(player);
|
||||
try {
|
||||
final mpv = player;
|
||||
for (final (k, v) in [
|
||||
('ao', 'null'),
|
||||
('aid', 'no'),
|
||||
('sid', 'no'),
|
||||
('vid', 'auto'), // media_kit starts with vid=no
|
||||
('hwdec', 'no'),
|
||||
('cache', 'no'),
|
||||
('hr-seek', 'no'), // nearest keyframe is fine for a poster
|
||||
('start', '25%'),
|
||||
('vf', 'scale=w=$thumbnailWidth:h=-2'),
|
||||
('screenshot-format', 'jpg'),
|
||||
('screenshot-jpeg-quality', '85'),
|
||||
('screenshot-tag-colorspace', 'no'),
|
||||
]) {
|
||||
await mpv.setProperty(k, v);
|
||||
}
|
||||
await player.open(path);
|
||||
final target = File(out);
|
||||
final deadline = DateTime.now().add(_timeout);
|
||||
while (DateTime.now().isBefore(deadline)) {
|
||||
if (cancelled()) return null;
|
||||
// Unreadable or no video (with aid=no, audio-only stops too): mpv
|
||||
// drops the file and goes idle at once.
|
||||
if (await mpv.getProperty('idle-active') == 'yes') return null;
|
||||
// A frame is up once the video has a size and the seek is done.
|
||||
final w = await mpv.getProperty('video-params/w');
|
||||
final seeking = await mpv.getProperty('seeking');
|
||||
if (w.isNotEmpty && w != '0' && seeking != 'yes') {
|
||||
await mpv.command(['screenshot-to-file', out, 'video']);
|
||||
if (await target.exists() && await target.length() > 0) {
|
||||
final d = double.tryParse(await mpv.getProperty('duration')) ?? 0;
|
||||
return Thumbnail(out, Duration(milliseconds: (d * 1000).round()));
|
||||
}
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 50));
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
// [cancelAllThumbnails] may have taken it already.
|
||||
if (_players.remove(player)) await thumbnailPlayers.dispose(player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../../shell/avatar.dart';
|
||||
import 'thumb.dart';
|
||||
|
||||
// The Files page's rows and cards: an episode row (also used for Recent),
|
||||
// a loose-video card, and the empty states.
|
||||
|
||||
/// What a play control is doing right now.
|
||||
enum PlayState { idle, starting, playing }
|
||||
|
||||
/// Last path segment, ignoring trailing separators (`/media/anime/`).
|
||||
String baseName(String path) {
|
||||
final parts = path.split(RegExp(r'[/\\]')).where((p) => p.isNotEmpty).toList();
|
||||
return parts.isEmpty ? path : parts.last;
|
||||
}
|
||||
|
||||
/// Name of the folder [path] is in.
|
||||
String parentName(String path) => baseName(File(path).parent.path);
|
||||
|
||||
/// Cleaned title of a loose video: `Title (2019)`.
|
||||
String cleanTitle(ParsedName p) => p.year == null ? p.series : '${p.series} (${p.year})';
|
||||
|
||||
/// One file as a row: an episode on a show's page, or a Recent entry
|
||||
/// ([indent] off).
|
||||
class FileRow extends StatelessWidget {
|
||||
final String path;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
/// Size text; null while unknown.
|
||||
final String? size;
|
||||
final PlayState state;
|
||||
final ThumbCache thumbs;
|
||||
/// Null disables the row.
|
||||
final VoidCallback? onTap;
|
||||
final bool indent;
|
||||
final Widget? trailing;
|
||||
const FileRow({
|
||||
super.key,
|
||||
required this.path,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.size,
|
||||
required this.state,
|
||||
required this.thumbs,
|
||||
required this.onTap,
|
||||
this.indent = true,
|
||||
this.trailing,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final playing = state == PlayState.playing;
|
||||
final enabled = onTap != null;
|
||||
final muted = scheme.onSurfaceVariant;
|
||||
final icon = switch (state) {
|
||||
PlayState.starting => const SizedBox.square(
|
||||
dimension: 16, child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
PlayState.playing => Icon(Icons.graphic_eq, size: 20, color: scheme.primary),
|
||||
PlayState.idle => Icon(Icons.play_circle_outline,
|
||||
size: 20, color: enabled ? scheme.primary : scheme.onSurface.withValues(alpha: 0.38)),
|
||||
};
|
||||
return ThumbBuilder(
|
||||
cache: thumbs,
|
||||
path: path,
|
||||
builder: (context, t, _) {
|
||||
final duration = durationText(t);
|
||||
final meta = [?duration, ?size].join(' · ');
|
||||
return Material(
|
||||
color: playing ? scheme.primary.withValues(alpha: 0.08) : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(indent ? 20 : 4, 5, 8, 5),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: ThumbImage(t, width: 80, height: 45),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
SizedBox(width: 20, child: Center(child: icon)),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: playing ? scheme.primary : null,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (playing) ...[
|
||||
const SizedBox(width: 8),
|
||||
Pill('now playing', scheme.primary),
|
||||
],
|
||||
],
|
||||
),
|
||||
Text(subtitle,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: muted, fontSize: 12)),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (meta.isNotEmpty) ...[
|
||||
const SizedBox(width: 12),
|
||||
Text(meta, style: TextStyle(color: muted, fontSize: 12)),
|
||||
],
|
||||
?trailing,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Text under a [VideoCard]'s 16:9 frame (title up to two lines, size).
|
||||
const videoCardTextHeight = 66.0;
|
||||
|
||||
/// A loose video (movie, clip): 16:9 frame with its duration, then the
|
||||
/// cleaned title and size.
|
||||
class VideoCard extends StatelessWidget {
|
||||
final LocalEpisode video;
|
||||
final PlayState state;
|
||||
final ThumbCache thumbs;
|
||||
final VoidCallback? onTap;
|
||||
const VideoCard({
|
||||
super.key,
|
||||
required this.video,
|
||||
required this.state,
|
||||
required this.thumbs,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final playing = state == PlayState.playing;
|
||||
return ThumbBuilder(
|
||||
cache: thumbs,
|
||||
path: video.path,
|
||||
builder: (context, t, _) {
|
||||
final duration = durationText(t);
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: playing ? scheme.primary : Colors.transparent,
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
ThumbImage(t),
|
||||
if (duration != null)
|
||||
Positioned(right: 6, bottom: 6, child: _Badge(duration)),
|
||||
if (state != PlayState.idle)
|
||||
Container(
|
||||
color: Colors.black38,
|
||||
alignment: Alignment.center,
|
||||
child: state == PlayState.playing
|
||||
? const Icon(Icons.graphic_eq, color: Colors.white, size: 32)
|
||||
: const SizedBox.square(
|
||||
dimension: 28,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 3, color: Colors.white)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Flexible(
|
||||
child: Text(
|
||||
cleanTitle(video.parsed),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 13,
|
||||
color: playing ? scheme.primary : null,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(formatSize(video.file.size),
|
||||
style: TextStyle(color: scheme.onSurfaceVariant, fontSize: 12)),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Badge extends StatelessWidget {
|
||||
final String text;
|
||||
const _Badge(this.text);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 1),
|
||||
decoration: BoxDecoration(color: Colors.black87, borderRadius: BorderRadius.circular(4)),
|
||||
child: Text(text, style: const TextStyle(color: Colors.white, fontSize: 11)),
|
||||
);
|
||||
}
|
||||
|
||||
class FilesEmpty extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String title;
|
||||
final String detail;
|
||||
final Widget? action;
|
||||
const FilesEmpty(this.icon, this.title, this.detail, {super.key, this.action});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 60, bottom: 20),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(icon, size: 44, color: scheme.onSurfaceVariant),
|
||||
const SizedBox(height: 10),
|
||||
Text(title, style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center),
|
||||
const SizedBox(height: 4),
|
||||
Text(detail, style: TextStyle(color: scheme.onSurfaceVariant), textAlign: TextAlign.center),
|
||||
if (action != null) ...[const SizedBox(height: 14), action!],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,978 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../../library/show_matcher.dart';
|
||||
import '../../shell/motion.dart';
|
||||
import '../../platform/ports/folder_access.dart';
|
||||
import '../../app/app_graph.dart';
|
||||
import '../../watch/watch_history.dart';
|
||||
import '../../widgets/app_menu.dart';
|
||||
import '../folder_store.dart';
|
||||
import '../scanner.dart';
|
||||
import 'file_tiles.dart';
|
||||
import 'library_view.dart';
|
||||
import 'thumb.dart';
|
||||
|
||||
export 'thumb.dart' show ThumbnailLoader;
|
||||
|
||||
// The Files source as a library: the watched folders on the left (chips
|
||||
// on top when narrow): the Library (every folder together), Recent, then
|
||||
// each folder. A library is shows and movies as poster cards, grouped by
|
||||
// the library's L1 and named by its L2 match, plus the videos that are
|
||||
// neither; a show opens its own page. Folders are scanned when first
|
||||
// needed and on Rescan; scans, the open place and the open show are kept
|
||||
// for the app session. Playing goes through [onPlay].
|
||||
|
||||
/// Below this width the sidebar turns into chips above the list.
|
||||
const filesNarrowWidth = 700.0;
|
||||
|
||||
/// The place that shows every watched folder together.
|
||||
const libraryPlace = '\u0000library';
|
||||
|
||||
/// Scans kept for the app session, by folder.
|
||||
final _scans = <String, FolderScan>{};
|
||||
final _running = <String, Future<FolderScan>>{};
|
||||
String? _lastOpen = libraryPlace;
|
||||
/// The show open in each place (by show key) for the app session.
|
||||
final _openShows = <String, String>{};
|
||||
final _showRequests = ValueNotifier(0);
|
||||
|
||||
/// Opens [dir] (null: Recent; [libraryPlace]: the library) in the Files
|
||||
/// page: now if one is showing, else when it next opens.
|
||||
void showFilesFolder(String? dir) {
|
||||
_lastOpen = dir;
|
||||
_showRequests.value++;
|
||||
}
|
||||
|
||||
/// Forgets the session's scans, open shows and the open place.
|
||||
@visibleForTesting
|
||||
void resetFilesPageSession() {
|
||||
_scans.clear();
|
||||
_running.clear();
|
||||
_openShows.clear();
|
||||
_lastOpen = libraryPlace;
|
||||
}
|
||||
|
||||
class FilesPage extends StatefulWidget {
|
||||
/// Nobody else is in the server: no relay notice.
|
||||
final bool alone;
|
||||
/// The file will stream from this computer through the server.
|
||||
final bool relayed;
|
||||
/// Plays [path] in the session; returns an error text, or null.
|
||||
final Future<String?> Function(String path) onPlay;
|
||||
/// Adds [path] to Up next (right-click on a video); null: no server.
|
||||
final Future<String?> Function(String path, {bool next})? onAddToQueue;
|
||||
final String? nowPlayingPath;
|
||||
/// Defaults to [thumbnailFor].
|
||||
final ThumbnailLoader? thumbnails;
|
||||
/// Defaults to [FolderAccess.scan].
|
||||
final Future<FolderScan> Function(String dir)? scan;
|
||||
/// Defaults to [FolderStore.instance].
|
||||
final FolderStore? store;
|
||||
/// Defaults to the app's (`AppGraph.library`).
|
||||
final ShowMatcher? matcher;
|
||||
/// Default: the system folder / file dialogs.
|
||||
final Future<String?> Function()? pickFolder;
|
||||
final Future<String?> Function()? pickVideo;
|
||||
|
||||
const FilesPage({
|
||||
super.key,
|
||||
this.alone = false,
|
||||
required this.relayed,
|
||||
required this.onPlay,
|
||||
this.onAddToQueue,
|
||||
this.nowPlayingPath,
|
||||
this.thumbnails,
|
||||
this.scan,
|
||||
this.store,
|
||||
this.matcher,
|
||||
this.pickFolder,
|
||||
this.pickVideo,
|
||||
});
|
||||
|
||||
@override
|
||||
State<FilesPage> createState() => _FilesPageState();
|
||||
}
|
||||
|
||||
/// A place's scans grouped (L1), made once per set of scans.
|
||||
class _Library {
|
||||
final List<FolderScan> scans;
|
||||
final LocalLibrary lib;
|
||||
final Map<String, LocalEpisode> byPath;
|
||||
|
||||
_Library(this.scans, List<String> roots)
|
||||
: lib = groupLocal([for (final s in scans) ...s.videos], roots: roots),
|
||||
byPath = {} {
|
||||
for (final e in lib.files) {
|
||||
byPath[e.path] = e;
|
||||
}
|
||||
}
|
||||
|
||||
int get videos => scans.fold(0, (n, s) => n + s.videos.length);
|
||||
int get hidden => scans.fold(0, (n, s) => n + s.hiddenCount);
|
||||
int get subtitleFiles => {
|
||||
for (final s in scans)
|
||||
for (final l in s.subtitles.values) ...l
|
||||
}.length;
|
||||
bool get truncated => scans.any((s) => s.truncated);
|
||||
}
|
||||
|
||||
class _FilesPageState extends State<FilesPage> {
|
||||
FolderAccess get _folders => AppScope.of(context).ports.folders;
|
||||
ShowMatcher get _matcher => widget.matcher ?? AppScope.of(context).library;
|
||||
|
||||
late final ThumbCache _thumbs =
|
||||
widget.thumbnails == null ? ThumbCache.shared : ThumbCache(widget.thumbnails!);
|
||||
FolderStore get _store => widget.store ?? FolderStore.instance;
|
||||
WatchHistory get _history => AppScope.of(context).watch.history;
|
||||
|
||||
/// Null: Recent; [libraryPlace]: every folder.
|
||||
String? _open = _lastOpen;
|
||||
bool _showHidden = false;
|
||||
String? _starting;
|
||||
String? _error;
|
||||
final _libs = <String, _Library>{};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_showRequests.addListener(_shown);
|
||||
unawaited(_matcher.ensureLoaded());
|
||||
_store.ensureLoaded().then((_) {
|
||||
if (!mounted) return;
|
||||
final open = _open;
|
||||
if (open != null && open != libraryPlace && !_store.folders.value.contains(open)) {
|
||||
_select(libraryPlace);
|
||||
} else {
|
||||
_scanFor(open);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_showRequests.removeListener(_shown);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _shown() => _select(_lastOpen);
|
||||
|
||||
Future<FolderScan> _runScan(String dir) => (widget.scan ?? _folders.scan)(dir);
|
||||
|
||||
/// The folders a place needs scanned.
|
||||
List<String> _foldersOf(String? place) => place == null
|
||||
? const []
|
||||
: place == libraryPlace
|
||||
? _store.folders.peek()
|
||||
: [place];
|
||||
|
||||
void _scanFor(String? place) {
|
||||
for (final f in _foldersOf(place)) {
|
||||
if (!_scans.containsKey(f) && !_running.containsKey(f)) _scan(f);
|
||||
}
|
||||
}
|
||||
|
||||
void _select(String? place) {
|
||||
setState(() {
|
||||
_open = _lastOpen = place;
|
||||
_showHidden = false;
|
||||
});
|
||||
_scanFor(place);
|
||||
}
|
||||
|
||||
Future<void> _scan(String dir, {bool rescan = false}) async {
|
||||
var f = _running[dir];
|
||||
if (f == null || rescan) {
|
||||
f = _running[dir] = _runScan(dir);
|
||||
if (rescan) _thumbs.forget([for (final v in _scans[dir]?.videos ?? const <LocalFile>[]) v.path]);
|
||||
}
|
||||
if (mounted) setState(() {});
|
||||
FolderScan result;
|
||||
try {
|
||||
result = await f;
|
||||
} catch (_) {
|
||||
result = FolderScan.empty;
|
||||
}
|
||||
if (_running[dir] == f) {
|
||||
_running.remove(dir);
|
||||
_scans[dir] = result;
|
||||
}
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
/// The grouped library of [place], once its folders are scanned (the
|
||||
/// library: those scanned so far).
|
||||
_Library? _libraryOf(String place) {
|
||||
final folders = _foldersOf(place);
|
||||
final scans = [for (final f in folders) ?_scans[f]];
|
||||
if (place != libraryPlace && scans.isEmpty) return null;
|
||||
final known = _libs[place];
|
||||
if (known != null && known.scans.length == scans.length && _same(known.scans, scans)) return known;
|
||||
final lib = _libs[place] = _Library(scans, folders);
|
||||
_matcher.remember(lib.lib);
|
||||
return lib;
|
||||
}
|
||||
|
||||
static bool _same(List<FolderScan> a, List<FolderScan> b) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (!identical(a[i], b[i])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> _addFolder() async {
|
||||
String? dir;
|
||||
try {
|
||||
dir = await (widget.pickFolder ??
|
||||
() => _folders.pickFolder(dialogTitle: 'Add a folder with videos'))();
|
||||
} catch (e) {
|
||||
_showError('Folder dialog unavailable (${e.runtimeType})');
|
||||
}
|
||||
if (dir == null || !mounted) return;
|
||||
_store.addFolder(dir);
|
||||
_select(dir);
|
||||
}
|
||||
|
||||
Future<void> _browse() async {
|
||||
String? path;
|
||||
try {
|
||||
path = await (widget.pickVideo ?? _pickVideo)();
|
||||
} catch (e) {
|
||||
_showError('File dialog unavailable (${e.runtimeType})');
|
||||
}
|
||||
if (path != null && mounted) await _play(path);
|
||||
}
|
||||
|
||||
Future<String?> _pickVideo() async {
|
||||
final files = await _folders.pickFiles(dialogTitle: 'Pick a video', extensions: videoExtensions.toList());
|
||||
return files.firstOrNull;
|
||||
}
|
||||
|
||||
void _removeFolder(String dir) {
|
||||
_store.removeFolder(dir);
|
||||
_scans.remove(dir);
|
||||
if (_open == dir) _select(libraryPlace);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Future<void> _play(String path) async {
|
||||
if (_starting != null) return;
|
||||
setState(() {
|
||||
_starting = path;
|
||||
_error = null;
|
||||
});
|
||||
String? error;
|
||||
try {
|
||||
error = await widget.onPlay(path);
|
||||
} catch (e) {
|
||||
error = '$e';
|
||||
}
|
||||
if (error == null) _store.addRecent(path);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_starting = null;
|
||||
_error = error;
|
||||
});
|
||||
}
|
||||
|
||||
void _showError(String text) {
|
||||
if (mounted) setState(() => _error = text);
|
||||
}
|
||||
|
||||
PlayState _stateOf(String path) => path == _starting
|
||||
? PlayState.starting
|
||||
: path == widget.nowPlayingPath
|
||||
? PlayState.playing
|
||||
: PlayState.idle;
|
||||
|
||||
VoidCallback _tapOf(String path) => () => _play(path);
|
||||
|
||||
/// Right-click on a video ([context]: its tile): Put it up, Add to
|
||||
/// queue, Play next.
|
||||
Future<void> _menu(BuildContext context, String path) async {
|
||||
final add = widget.onAddToQueue;
|
||||
if (add == null) return;
|
||||
final pick = await showAppMenu<int>(context, items: [
|
||||
AppMenuItem(value: 0, label: widget.alone ? 'Play' : 'Put it up'),
|
||||
const AppMenuItem(value: 1, label: 'Add to queue'),
|
||||
const AppMenuItem(value: 2, label: 'Play next'),
|
||||
]);
|
||||
if (pick == null || !mounted) return;
|
||||
if (pick == 0) return _play(path);
|
||||
String? error;
|
||||
try {
|
||||
error = await add(path, next: pick == 2);
|
||||
} catch (e) {
|
||||
error = '$e';
|
||||
}
|
||||
if (error != null) _showError(error);
|
||||
}
|
||||
|
||||
/// [child] with the right-click menu (when there is a server).
|
||||
Widget _menuable(String path, Widget child) => widget.onAddToQueue == null
|
||||
? child
|
||||
: KeyedSubtree(
|
||||
key: ValueKey('menu:$path'),
|
||||
child: Builder(
|
||||
builder: (context) => GestureDetector(onSecondaryTap: () => _menu(context, path), child: child)));
|
||||
|
||||
late final _actions = FilesActions(
|
||||
play: (p) => unawaited(_play(p)),
|
||||
stateOf: _stateOf,
|
||||
menuable: _menuable,
|
||||
thumbs: _thumbs,
|
||||
);
|
||||
|
||||
/// The last episode of [show] watched here (the watch history: the
|
||||
/// newest one watched to the end), else the last one opened (Recent), by
|
||||
/// key.
|
||||
String? _lastPlayed(_Library lib, LocalShow show) {
|
||||
for (final (key, entry) in _history.entries) {
|
||||
if (!entry.played || !key.value.startsWith('file:')) continue;
|
||||
final e = lib.byPath[key.value.substring(5)];
|
||||
if (e != null && e.showKey == show.key && e.kind == LocalKind.episode) return e.key;
|
||||
}
|
||||
for (final p in _store.recent.value) {
|
||||
final e = lib.byPath[p];
|
||||
if (e != null && e.showKey == show.key && e.kind == LocalKind.episode) return e.key;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => LayoutBuilder(
|
||||
builder: (context, box) {
|
||||
final narrow = box.maxWidth < filesNarrowWidth;
|
||||
return SignalBuilder(builder: (context) {
|
||||
final folders = _store.folders.value;
|
||||
final recent = _store.recent.value;
|
||||
_matcher.revision.value;
|
||||
_history.revision.value;
|
||||
final open = _open == null || _open == libraryPlace || folders.contains(_open) ? _open : libraryPlace;
|
||||
final showKey = open == null ? null : _openShows[open];
|
||||
final main = fadeThrough(
|
||||
KeyedSubtree(
|
||||
key: ValueKey('${open ?? ''}\n${showKey ?? ''}'),
|
||||
child: _main(context, narrow, folders, recent, open, showKey),
|
||||
),
|
||||
);
|
||||
if (narrow) return main;
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(width: 260, child: _sidebar(context, folders, open)),
|
||||
Expanded(child: main),
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
Widget _browseButton(Widget Function(VoidCallback? onPressed) build) => build(_browse);
|
||||
|
||||
Widget _sidebar(BuildContext context, List<String> folders, String? open) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final shape = RoundedRectangleBorder(borderRadius: BorderRadius.circular(10));
|
||||
Widget? status(String? s) =>
|
||||
s == null ? null : Text(s, style: TextStyle(color: scheme.onSurfaceVariant, fontSize: 11));
|
||||
return ListView(
|
||||
padding: const EdgeInsets.fromLTRB(20, 20, 8, 20),
|
||||
children: [
|
||||
ListTile(
|
||||
key: const ValueKey('place:library'),
|
||||
dense: true,
|
||||
selected: open == libraryPlace,
|
||||
shape: shape,
|
||||
leading: const Icon(Icons.video_library_outlined, size: 18),
|
||||
title: const Text('Library'),
|
||||
subtitle: status(_libraryStatus(folders)),
|
||||
onTap: () => _select(libraryPlace),
|
||||
),
|
||||
ListTile(
|
||||
key: const ValueKey('place:recent'),
|
||||
dense: true,
|
||||
selected: open == null,
|
||||
shape: shape,
|
||||
leading: const Icon(Icons.history, size: 18),
|
||||
title: const Text('Recent'),
|
||||
onTap: () => _select(null),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const Text('Folders', style: TextStyle(fontWeight: FontWeight.w600)),
|
||||
const SizedBox(height: 8),
|
||||
for (final f in folders)
|
||||
ListTile(
|
||||
key: ValueKey('folder:$f'),
|
||||
dense: true,
|
||||
selected: open == f,
|
||||
shape: shape,
|
||||
leading: const Icon(Icons.folder_outlined, size: 18),
|
||||
title: Text(baseName(f), maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
subtitle: status(_folderStatus(f)),
|
||||
trailing: IconButton(
|
||||
tooltip: 'Remove folder',
|
||||
icon: const Icon(Icons.close, size: 16),
|
||||
onPressed: () => _removeFolder(f),
|
||||
),
|
||||
onTap: () => _select(f),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: TextButton.icon(
|
||||
onPressed: _addFolder,
|
||||
icon: const Icon(Icons.add, size: 18),
|
||||
label: const Text('Add folder'),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
_browseButton((onPressed) => OutlinedButton.icon(
|
||||
onPressed: onPressed,
|
||||
icon: const Icon(Icons.folder_open, size: 18),
|
||||
label: const Text('Browse…'),
|
||||
)),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
'The system file picker, for anything outside your folders.',
|
||||
style: TextStyle(color: scheme.onSurfaceVariant, fontSize: 11),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// "scanning…", "N videos", or null before the first scan.
|
||||
String? _folderStatus(String dir) {
|
||||
if (_running.containsKey(dir)) return 'scanning…';
|
||||
final n = _scans[dir]?.videos.length;
|
||||
return n == null ? null : '$n ${n == 1 ? 'video' : 'videos'}';
|
||||
}
|
||||
|
||||
String? _libraryStatus(List<String> folders) {
|
||||
if (folders.any(_running.containsKey)) return 'scanning…';
|
||||
if (folders.isEmpty || folders.any((f) => !_scans.containsKey(f))) return null;
|
||||
final n = _libraryOf(libraryPlace)?.lib.shows.length ?? 0;
|
||||
return '$n ${n == 1 ? 'show' : 'shows'}';
|
||||
}
|
||||
|
||||
List<Widget> _notices() => [
|
||||
if (!widget.alone && widget.relayed) const _RelayNotice(),
|
||||
AnimatedSize(
|
||||
duration: easeTime,
|
||||
curve: ease,
|
||||
alignment: Alignment.topLeft,
|
||||
child: _error == null
|
||||
? const SizedBox(width: double.infinity)
|
||||
: _ErrorBanner(_error!, onClose: () => setState(() => _error = null)),
|
||||
),
|
||||
];
|
||||
|
||||
Widget _main(
|
||||
BuildContext context,
|
||||
bool narrow,
|
||||
List<String> folders,
|
||||
List<String> recent,
|
||||
String? open,
|
||||
String? showKey,
|
||||
) {
|
||||
final lib = open == null ? null : _libraryOf(open);
|
||||
final show = showKey == null ? null : lib?.lib.show(showKey);
|
||||
if (open != null && lib != null && show != null) {
|
||||
return ShowPage(
|
||||
key: ValueKey('show:$open:${show.key}'),
|
||||
show: show,
|
||||
matcher: _matcher,
|
||||
actions: _actions,
|
||||
lastPlayed: _lastPlayed(lib, show),
|
||||
backLabel: open == libraryPlace ? 'Library' : baseName(open),
|
||||
onBack: () => setState(() => _openShows.remove(open)),
|
||||
top: [if (narrow) _chips(folders, open), ..._notices()],
|
||||
);
|
||||
}
|
||||
final scanning = _foldersOf(open).any(_running.containsKey);
|
||||
// A folder added elsewhere (a drop, the handoff) joins the library.
|
||||
if (open == libraryPlace && folders.any((f) => !_scans.containsKey(f) && !_running.containsKey(f))) {
|
||||
scheduleMicrotask(() {
|
||||
if (mounted) _scanFor(libraryPlace);
|
||||
});
|
||||
}
|
||||
final top = <Widget>[
|
||||
_header(context, open),
|
||||
if (narrow) _chips(folders, open),
|
||||
..._notices(),
|
||||
];
|
||||
final slivers = <Widget>[
|
||||
SliverList.list(children: top),
|
||||
if (open == null)
|
||||
..._recent(context, recent)
|
||||
else if (open == libraryPlace && folders.isEmpty)
|
||||
SliverToBoxAdapter(
|
||||
child: FilesEmpty(
|
||||
Icons.video_library_outlined,
|
||||
'Your library is empty',
|
||||
'Add a folder with your videos: shows, seasons and movies are found by their names.',
|
||||
action: FilledButton.icon(
|
||||
onPressed: _addFolder,
|
||||
icon: const Icon(Icons.create_new_folder_outlined),
|
||||
label: const Text('Add folder'),
|
||||
),
|
||||
),
|
||||
)
|
||||
else if (lib == null)
|
||||
const SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 60),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
)
|
||||
else
|
||||
..._library(context, open, lib, scanning),
|
||||
];
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.fromLTRB(narrow ? 20 : 12, 20, 20, 20),
|
||||
sliver: SliverMainAxisGroup(slivers: slivers),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _header(BuildContext context, String? open) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final (icon, title, sub) = switch (open) {
|
||||
null => (Icons.history, 'Recent', null),
|
||||
libraryPlace => (Icons.video_library, 'Library', null),
|
||||
final dir => (Icons.folder, baseName(dir), dir),
|
||||
};
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 14),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, color: scheme.primary),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
if (sub != null)
|
||||
Text(
|
||||
sub,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: scheme.onSurfaceVariant, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _chips(List<String> folders, String? open) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 14),
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
ChoiceChip(
|
||||
label: const Text('Library'),
|
||||
selected: open == libraryPlace,
|
||||
onSelected: (_) => _select(libraryPlace),
|
||||
),
|
||||
ChoiceChip(
|
||||
label: const Text('Recent'),
|
||||
selected: open == null,
|
||||
onSelected: (_) => _select(null),
|
||||
),
|
||||
for (final f in folders)
|
||||
// InputChip: selectable like the others, plus the remove x
|
||||
// the sidebar has.
|
||||
InputChip(
|
||||
key: ValueKey('chip:$f'),
|
||||
label: Text(baseName(f)),
|
||||
selected: open == f,
|
||||
onSelected: (_) => _select(f),
|
||||
onDeleted: () => _removeFolder(f),
|
||||
deleteButtonTooltipMessage: 'Remove folder',
|
||||
),
|
||||
ActionChip(
|
||||
avatar: const Icon(Icons.add, size: 16),
|
||||
label: const Text('Folder'),
|
||||
onPressed: _addFolder,
|
||||
),
|
||||
_browseButton((onPressed) => ActionChip(
|
||||
avatar: const Icon(Icons.folder_open, size: 16),
|
||||
label: const Text('Browse…'),
|
||||
onPressed: onPressed,
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
List<Widget> _recent(BuildContext context, List<String> recent) {
|
||||
if (recent.isEmpty) {
|
||||
return [
|
||||
SliverToBoxAdapter(
|
||||
child: FilesEmpty(
|
||||
Icons.video_library_outlined,
|
||||
'Nothing played yet',
|
||||
'Add a folder with your videos, or Browse for a single file.',
|
||||
action: FilledButton.icon(
|
||||
onPressed: _addFolder,
|
||||
icon: const Icon(Icons.create_new_folder_outlined),
|
||||
label: const Text('Add folder'),
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
return [
|
||||
SliverList.builder(
|
||||
itemCount: recent.length,
|
||||
itemBuilder: (context, i) {
|
||||
final path = recent[i];
|
||||
return _menuable(
|
||||
path,
|
||||
_RecentRow(
|
||||
key: ValueKey(path),
|
||||
path: path,
|
||||
matcher: _matcher,
|
||||
state: _stateOf(path),
|
||||
thumbs: _thumbs,
|
||||
onTap: _tapOf(path),
|
||||
onRemove: () => _store.removeRecent(path),
|
||||
));
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
Widget _section(BuildContext context, String title, {String? count}) => Padding(
|
||||
padding: const EdgeInsets.only(top: 22, bottom: 10),
|
||||
child: Row(children: [
|
||||
Text(title, style: Theme.of(context).textTheme.titleMedium),
|
||||
if (count != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
Text(count, style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Colors.grey)),
|
||||
],
|
||||
]),
|
||||
);
|
||||
|
||||
List<Widget> _library(BuildContext context, String place, _Library lib, bool scanning) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final l = lib.lib;
|
||||
final folderScan = place == libraryPlace ? null : _scans[place];
|
||||
String count(int n, String one, String many) => '$n ${n == 1 ? one : many}';
|
||||
final summary = [
|
||||
count(lib.videos, 'video', 'videos') +
|
||||
(l.shows.isEmpty ? '' : ' in ${count(l.shows.length, 'show', 'shows')}'),
|
||||
if (lib.hidden > 0) '${count(lib.hidden, 'other file', 'other files')} hidden',
|
||||
if (lib.subtitleFiles > 0) count(lib.subtitleFiles, 'subtitle file', 'subtitle files'),
|
||||
if (lib.truncated) 'stopped after $maxScannedFiles files',
|
||||
].join(' · ');
|
||||
final folders = _foldersOf(place);
|
||||
final movies = l.movies;
|
||||
final other = l.other;
|
||||
return [
|
||||
SliverToBoxAdapter(
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.filter_alt_outlined, size: 16, color: scheme.onSurfaceVariant),
|
||||
const SizedBox(width: 6),
|
||||
Text(summary, style: TextStyle(color: scheme.onSurfaceVariant, fontSize: 12)),
|
||||
if (folderScan != null && folderScan.hiddenCount > 0) ...[
|
||||
const SizedBox(width: 8),
|
||||
TextButton(
|
||||
onPressed: () => setState(() => _showHidden = !_showHidden),
|
||||
child: Text(_showHidden ? 'Hide them' : 'Show some'),
|
||||
),
|
||||
],
|
||||
TextButton.icon(
|
||||
onPressed: scanning
|
||||
? null
|
||||
: () {
|
||||
for (final f in folders) {
|
||||
_scan(f, rescan: true);
|
||||
}
|
||||
},
|
||||
icon: scanning
|
||||
? const SizedBox.square(dimension: 14, child: CircularProgressIndicator(strokeWidth: 2))
|
||||
: const Icon(Icons.refresh, size: 16),
|
||||
label: Text(scanning ? 'Scanning…' : 'Rescan'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (folderScan != null)
|
||||
SliverToBoxAdapter(
|
||||
child: AnimatedSize(
|
||||
duration: easeTime,
|
||||
curve: ease,
|
||||
alignment: Alignment.topLeft,
|
||||
child: !_showHidden
|
||||
? const SizedBox(width: double.infinity)
|
||||
: Column(
|
||||
children: [
|
||||
for (final f in folderScan.hiddenExamples)
|
||||
ListTile(
|
||||
dense: true,
|
||||
enabled: false,
|
||||
leading: const Icon(Icons.insert_drive_file_outlined, size: 18),
|
||||
title: Text(f, maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
trailing: Text(
|
||||
kindOf(f) == FileKind.video ? 'sample' : 'not a video',
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
if (folderScan.hiddenCount > folderScan.hiddenExamples.length)
|
||||
ListTile(
|
||||
dense: true,
|
||||
enabled: false,
|
||||
title: Text('and ${folderScan.hiddenCount - folderScan.hiddenExamples.length} more'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (lib.videos == 0)
|
||||
SliverToBoxAdapter(
|
||||
child: place == libraryPlace || _folders.folderExists(place)
|
||||
? const FilesEmpty(
|
||||
Icons.search_off,
|
||||
'No videos here',
|
||||
'Only video files are listed (mkv, mp4, webm…).',
|
||||
)
|
||||
: const FilesEmpty(
|
||||
Icons.folder_off_outlined,
|
||||
'Folder not found',
|
||||
'It may have been moved, renamed or be on a drive that is not connected.',
|
||||
),
|
||||
),
|
||||
if (l.shows.isNotEmpty) ...[
|
||||
SliverToBoxAdapter(child: _section(context, 'Shows', count: '${l.shows.length}')),
|
||||
SliverGrid.builder(
|
||||
gridDelegate: posterGrid(),
|
||||
itemCount: l.shows.length,
|
||||
itemBuilder: (context, i) => _showCard(place, lib, l.shows[i]),
|
||||
),
|
||||
],
|
||||
if (movies.isNotEmpty) ...[
|
||||
SliverToBoxAdapter(child: _section(context, 'Movies', count: '${movies.length}')),
|
||||
SliverGrid.builder(
|
||||
gridDelegate: posterGrid(),
|
||||
itemCount: movies.length,
|
||||
itemBuilder: (context, i) => _movieCard(movies[i]),
|
||||
),
|
||||
],
|
||||
if (other.isNotEmpty) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: _section(context, l.shows.isEmpty && movies.isEmpty ? 'Videos' : 'Other videos'),
|
||||
),
|
||||
SliverLayoutBuilder(builder: (context, c) {
|
||||
const gap = 12.0;
|
||||
final w = c.crossAxisExtent;
|
||||
final cols = (w / 240).floor().clamp(2, 8);
|
||||
final cardW = (w - gap * (cols - 1)) / cols;
|
||||
return SliverGrid.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: cols,
|
||||
mainAxisSpacing: gap,
|
||||
crossAxisSpacing: gap,
|
||||
mainAxisExtent: cardW * 9 / 16 + videoCardTextHeight,
|
||||
),
|
||||
itemCount: other.length,
|
||||
itemBuilder: (context, i) {
|
||||
final v = other[i];
|
||||
return _menuable(
|
||||
v.path,
|
||||
VideoCard(
|
||||
key: ValueKey(v.path),
|
||||
video: v,
|
||||
state: _stateOf(v.path),
|
||||
thumbs: _thumbs,
|
||||
onTap: _tapOf(v.path),
|
||||
));
|
||||
},
|
||||
);
|
||||
}),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
Widget _showCard(String place, _Library lib, LocalShow show) {
|
||||
final m = _matcher.showMatch(show);
|
||||
final last = _lastPlayed(lib, show);
|
||||
final String subtitle;
|
||||
if (last == null) {
|
||||
final n = show.episodeCount;
|
||||
subtitle = '$n ${n == 1 ? 'episode' : 'episodes'}';
|
||||
} else {
|
||||
final next = show.nextAfter(last);
|
||||
subtitle = next == null ? 'Watched to the end' : 'Next: ${episodeNumber(next.episode)}';
|
||||
}
|
||||
final playing = widget.nowPlayingPath != null && show.files.any((e) => e.path == widget.nowPlayingPath);
|
||||
return PosterCard(
|
||||
key: ValueKey('showcard:${show.key}'),
|
||||
title: m?.entry.title ?? show.title,
|
||||
subtitle: subtitle,
|
||||
coverUrl: m?.entry.cover,
|
||||
framePath: show.episodes.firstOrNull?.path,
|
||||
thumbs: _thumbs,
|
||||
playing: playing,
|
||||
onShown: () => _matcher.want(show),
|
||||
onTap: () => setState(() => _openShows[place] = show.key),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _movieCard(LocalEpisode movie) {
|
||||
final m = _matcher.seasonMatch(movie);
|
||||
return _menuable(
|
||||
movie.path,
|
||||
PosterCard(
|
||||
key: ValueKey('moviecard:${movie.path}'),
|
||||
title: m?.entry.title ?? (movie.parsed.year == null ? movie.title : '${movie.title} (${movie.parsed.year})'),
|
||||
subtitle: [
|
||||
if (movie.movieNumber != null) movie.label,
|
||||
if (m?.entry.year != null) '${m!.entry.year}' else if (movie.parsed.year != null) '${movie.parsed.year}',
|
||||
formatSize(movie.file.size),
|
||||
].join(' · '),
|
||||
coverUrl: m?.entry.cover,
|
||||
framePath: movie.path,
|
||||
thumbs: _thumbs,
|
||||
playing: _stateOf(movie.path) == PlayState.playing,
|
||||
onShown: () => _matcher.wantMovie(movie),
|
||||
onTap: _tapOf(movie.path),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// A Recent entry: `Show · E02` over the file name (the library's names
|
||||
/// when it knows the show), or the cleaned title over its folder; greyed
|
||||
/// when the file is gone.
|
||||
class _RecentRow extends StatefulWidget {
|
||||
final String path;
|
||||
final ShowMatcher matcher;
|
||||
final PlayState state;
|
||||
final ThumbCache thumbs;
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback onRemove;
|
||||
const _RecentRow({
|
||||
super.key,
|
||||
required this.path,
|
||||
required this.matcher,
|
||||
required this.state,
|
||||
required this.thumbs,
|
||||
required this.onTap,
|
||||
required this.onRemove,
|
||||
});
|
||||
|
||||
@override
|
||||
State<_RecentRow> createState() => _RecentRowState();
|
||||
}
|
||||
|
||||
class _RecentRowState extends State<_RecentRow> {
|
||||
FolderAccess get _folders => AppScope.of(context).ports.folders;
|
||||
|
||||
FileStat? _stat;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_folders.stat(widget.path).then((s) {
|
||||
if (mounted) setState(() => _stat = s);
|
||||
}, onError: (Object _) {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final path = widget.path;
|
||||
final e = widget.matcher.episodeAt(path) ??
|
||||
readLocalFile(LocalFile(path, 0, DateTime.fromMillisecondsSinceEpoch(0)));
|
||||
final missing = _stat?.type == FileSystemEntityType.notFound;
|
||||
final episode = e.kind == LocalKind.episode || e.kind == LocalKind.extra;
|
||||
final name = widget.matcher.seasonMatch(e)?.entry.title ?? e.title;
|
||||
return FileRow(
|
||||
path: path,
|
||||
title: episode ? '$name · ${e.label}' : (e.kind == LocalKind.other ? cleanTitle(e.parsed) : name),
|
||||
subtitle: missing ? 'File not found' : (episode ? baseName(path) : parentName(path)),
|
||||
size: _stat == null || missing ? null : formatSize(_stat!.size),
|
||||
state: widget.state,
|
||||
thumbs: widget.thumbs,
|
||||
onTap: missing ? null : widget.onTap,
|
||||
indent: false,
|
||||
trailing: IconButton(
|
||||
tooltip: 'Remove from recent',
|
||||
icon: const Icon(Icons.close, size: 16),
|
||||
onPressed: widget.onRemove,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RelayNotice extends StatelessWidget {
|
||||
const _RelayNotice();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.lightBlueAccent.withValues(alpha: 0.08),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Row(
|
||||
children: [
|
||||
Icon(Icons.cell_tower, size: 18, color: Colors.lightBlueAccent),
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Files stream from this computer through the server. '
|
||||
'Keep the app open while it plays.',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class _ErrorBanner extends StatelessWidget {
|
||||
final String text;
|
||||
final VoidCallback onClose;
|
||||
const _ErrorBanner(this.text, {required this.onClose});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(10, 4, 4, 4),
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: scheme.errorContainer,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.error_outline, size: 18, color: scheme.onErrorContainer),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: Text(text, style: TextStyle(color: scheme.onErrorContainer))),
|
||||
IconButton(
|
||||
tooltip: 'Dismiss',
|
||||
icon: Icon(Icons.close, size: 16, color: scheme.onErrorContainer),
|
||||
onPressed: onClose,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,712 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../../library/show_matcher.dart';
|
||||
import '../../schedule/anilist.dart' show AniListEntry;
|
||||
import '../../shell/avatar.dart' show Pill;
|
||||
import 'file_tiles.dart';
|
||||
import 'thumb.dart';
|
||||
|
||||
// The Files library: shows and movies as poster cards (like the Jellyfin
|
||||
// browser's), a show's own page (banner, the next episode with what is
|
||||
// missing on the way, seasons, extras, movies) and the corrections
|
||||
// ("Wrong show?", "Episode numbers…"). Names and art come from the
|
||||
// library's AniList match when there is one, else from the files.
|
||||
|
||||
/// What the page hands its views: playing, the right-click menu, the
|
||||
/// thumbnails, what plays now.
|
||||
class FilesActions {
|
||||
final void Function(String path) play;
|
||||
final PlayState Function(String path) stateOf;
|
||||
final Widget Function(String path, Widget child) menuable;
|
||||
final ThumbCache thumbs;
|
||||
const FilesActions({required this.play, required this.stateOf, required this.menuable, required this.thumbs});
|
||||
}
|
||||
|
||||
/// "66–107 aren't in your folders", "66 isn't in your folders".
|
||||
String missingText(EpisodeGap gap) =>
|
||||
gap.first == gap.last ? '${gap.label} isn\'t in your folders' : '${gap.label} aren\'t in your folders';
|
||||
|
||||
/// The next-episode prompt: "66–107 aren't in your folders — skip to
|
||||
/// 108?", or at the start "1–55 … — start at 56?"; null when nothing is
|
||||
/// skipped.
|
||||
String? skipPrompt(LocalNext next, {required bool started}) {
|
||||
final gap = next.skipped;
|
||||
if (gap == null) return null;
|
||||
final n = next.episode.episode;
|
||||
return started ? '${missingText(gap)} — skip to $n?' : '${missingText(gap)} — start at $n?';
|
||||
}
|
||||
|
||||
/// A show's label for an episode: `56`, `S3 E1`.
|
||||
String episodeNumber(LocalEpisode e) =>
|
||||
e.season == null ? '${e.episode}' : 'S${e.season} E${e.episode}';
|
||||
|
||||
/// The 2:3 picture of a show or movie: its AniList cover, else a frame of
|
||||
/// [framePath].
|
||||
class PosterImage extends StatelessWidget {
|
||||
final String? url;
|
||||
final String? framePath;
|
||||
final ThumbCache thumbs;
|
||||
const PosterImage({super.key, this.url, this.framePath, required this.thumbs});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final frame = framePath == null
|
||||
? const ThumbImage(null)
|
||||
: ThumbBuilder(cache: thumbs, path: framePath!, builder: (context, t, _) => ThumbImage(t));
|
||||
final u = url;
|
||||
if (u == null) return frame;
|
||||
return Image.network(
|
||||
u,
|
||||
fit: BoxFit.cover,
|
||||
gaplessPlayback: true,
|
||||
errorBuilder: (_, _, _) => frame,
|
||||
loadingBuilder: (context, child, progress) => progress == null ? child : frame,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// A show (or movie) as a poster card: picture, title, one line under it.
|
||||
class PosterCard extends StatefulWidget {
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final String? coverUrl;
|
||||
final String? framePath;
|
||||
final ThumbCache thumbs;
|
||||
final VoidCallback onTap;
|
||||
final bool playing;
|
||||
/// Called once when the card is first built (the library matches what
|
||||
/// is on screen).
|
||||
final VoidCallback? onShown;
|
||||
const PosterCard({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.thumbs,
|
||||
required this.onTap,
|
||||
this.coverUrl,
|
||||
this.framePath,
|
||||
this.playing = false,
|
||||
this.onShown,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PosterCard> createState() => _PosterCardState();
|
||||
}
|
||||
|
||||
class _PosterCardState extends State<PosterCard> {
|
||||
bool _hover = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.onShown?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final t = Theme.of(context).textTheme;
|
||||
return InkWell(
|
||||
onTap: widget.onTap,
|
||||
onHover: (h) => setState(() => _hover = h),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 150),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: widget.playing ? scheme.primary : (_hover ? scheme.onSurfaceVariant : Colors.transparent),
|
||||
width: 2,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: PosterImage(url: widget.coverUrl, framePath: widget.framePath, thumbs: widget.thumbs),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(widget.title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.titleSmall?.copyWith(color: widget.playing ? scheme.primary : null)),
|
||||
Text(widget.subtitle,
|
||||
maxLines: 1, overflow: TextOverflow.ellipsis, style: t.bodySmall?.copyWith(color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Title and meta lines under a [PosterCard]'s picture.
|
||||
const posterTextHeight = 46.0;
|
||||
|
||||
/// Poster cards in a grid: about 170 px wide each.
|
||||
SliverGridDelegate posterGrid() => const _PosterGrid();
|
||||
|
||||
class _PosterGrid extends SliverGridDelegate {
|
||||
const _PosterGrid();
|
||||
|
||||
@override
|
||||
SliverGridLayout getLayout(SliverConstraints constraints) {
|
||||
const gap = 12.0;
|
||||
final w = constraints.crossAxisExtent;
|
||||
final cols = (w / 170).floor().clamp(2, 12);
|
||||
final cardW = (w - gap * (cols - 1)) / cols;
|
||||
return SliverGridRegularTileLayout(
|
||||
crossAxisCount: cols,
|
||||
mainAxisStride: cardW * 1.5 + posterTextHeight + gap,
|
||||
crossAxisStride: cardW + gap,
|
||||
childMainAxisExtent: cardW * 1.5 + posterTextHeight,
|
||||
childCrossAxisExtent: cardW,
|
||||
reverseCrossAxis: false,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRelayout(covariant SliverGridDelegate oldDelegate) => false;
|
||||
}
|
||||
|
||||
/// One show's page: header (banner, proper name, what the files are,
|
||||
/// the match), the next episode with what is missing on the way, the
|
||||
/// season's episodes with their holes, extras and the show's movies.
|
||||
class ShowPage extends StatefulWidget {
|
||||
final LocalShow show;
|
||||
final ShowMatcher matcher;
|
||||
final FilesActions actions;
|
||||
/// The last episode of this show played here ([LocalEpisode.key]).
|
||||
final String? lastPlayed;
|
||||
final String backLabel;
|
||||
final VoidCallback onBack;
|
||||
/// Notices above the page (the relay notice, errors).
|
||||
final List<Widget> top;
|
||||
const ShowPage({
|
||||
super.key,
|
||||
required this.show,
|
||||
required this.matcher,
|
||||
required this.actions,
|
||||
required this.lastPlayed,
|
||||
required this.backLabel,
|
||||
required this.onBack,
|
||||
this.top = const [],
|
||||
});
|
||||
|
||||
@override
|
||||
State<ShowPage> createState() => _ShowPageState();
|
||||
}
|
||||
|
||||
class _ShowPageState extends State<ShowPage> {
|
||||
int? _season;
|
||||
bool _seasonPicked = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.matcher.want(widget.show);
|
||||
}
|
||||
|
||||
LocalShow get show => widget.show;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => SignalBuilder(builder: (context) {
|
||||
widget.matcher.revision.value;
|
||||
final busy = widget.matcher.busy.value.contains(show.key);
|
||||
final m = widget.matcher.showMatch(show);
|
||||
final next = show.nextAfter(widget.lastPlayed);
|
||||
final seasons = show.seasons;
|
||||
if (!_seasonPicked) _season = next?.episode.season ?? seasons.firstOrNull?.number;
|
||||
final season = show.season(_season) ?? seasons.firstOrNull;
|
||||
return CustomScrollView(
|
||||
key: PageStorageKey('show:${show.key}'),
|
||||
slivers: [
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(12, 12, 20, 24),
|
||||
sliver: SliverMainAxisGroup(slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: TextButton.icon(
|
||||
onPressed: widget.onBack,
|
||||
icon: const Icon(Icons.arrow_back, size: 18),
|
||||
label: Text(widget.backLabel),
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverList.list(children: widget.top),
|
||||
SliverToBoxAdapter(child: _header(context, m, next, busy)),
|
||||
if (seasons.length > 1)
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 14),
|
||||
child: Wrap(spacing: 8, runSpacing: 8, children: [
|
||||
for (final s in seasons)
|
||||
ChoiceChip(
|
||||
key: ValueKey('season:${s.number}'),
|
||||
label: Text(s.title),
|
||||
selected: identical(s, season),
|
||||
onSelected: (_) => setState(() {
|
||||
_season = s.number;
|
||||
_seasonPicked = true;
|
||||
}),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
if (season != null) ..._episodes(context, season),
|
||||
if (show.extras.isNotEmpty) ...[
|
||||
_section(context, 'Extras', show.extras.length),
|
||||
SliverList.list(children: [for (final e in show.extras) _row(e, e.label, e.name)]),
|
||||
],
|
||||
if (show.movies.isNotEmpty) ...[
|
||||
_section(context, show.movies.length == 1 ? 'Movie' : 'Movies', show.movies.length),
|
||||
SliverList.list(children: [for (final e in show.movies) _row(e, e.label, e.name)]),
|
||||
],
|
||||
]),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
Widget _section(BuildContext context, String title, int n) => SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 22, bottom: 6),
|
||||
child: Row(children: [
|
||||
Text(title, style: Theme.of(context).textTheme.titleMedium),
|
||||
const SizedBox(width: 8),
|
||||
Text('$n', style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Colors.grey)),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
Widget _row(LocalEpisode e, String title, String subtitle) => widget.actions.menuable(
|
||||
e.path,
|
||||
FileRow(
|
||||
key: ValueKey(e.path),
|
||||
path: e.path,
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
size: formatSize(e.file.size),
|
||||
state: widget.actions.stateOf(e.path),
|
||||
thumbs: widget.actions.thumbs,
|
||||
onTap: () => widget.actions.play(e.path),
|
||||
));
|
||||
|
||||
List<Widget> _episodes(BuildContext context, LocalSeason season) {
|
||||
final rows = <Widget>[];
|
||||
var expect = 1;
|
||||
for (final e in season.episodes) {
|
||||
final n = e.episode!;
|
||||
final gap = season.gaps.where((g) => g.first >= expect && g.last < n).firstOrNull;
|
||||
if (gap != null) rows.add(_GapRow(missingText(gap)));
|
||||
if (n >= expect) expect = n + 1;
|
||||
final offset = widget.matcher.offset(show.key, season.number);
|
||||
final shown = n + offset;
|
||||
final name = widget.matcher.episodeTitle(e);
|
||||
// Like the Jellyfin browser's rows: "12. Name", else "Episode 12".
|
||||
final title = name == null ? 'Episode $shown' : '$shown. $name';
|
||||
rows.add(_row(e, title, e.name));
|
||||
}
|
||||
final tail = season.gaps.where((g) => g.first >= expect).firstOrNull;
|
||||
if (tail != null) rows.add(_GapRow(missingText(tail)));
|
||||
return [
|
||||
_section(context, season.title, season.distinct.length),
|
||||
SliverList.list(children: rows),
|
||||
];
|
||||
}
|
||||
|
||||
Widget _header(BuildContext context, SeasonMatch? m, LocalNext? next, bool busy) {
|
||||
final theme = Theme.of(context);
|
||||
final t = theme.textTheme;
|
||||
final scheme = theme.colorScheme;
|
||||
final entry = m?.entry;
|
||||
final title = entry?.title ?? show.title;
|
||||
final count = show.episodeCount;
|
||||
final meta = [
|
||||
if (show.seasons.length > 1) '${show.seasons.length} seasons',
|
||||
'$count ${count == 1 ? 'episode' : 'episodes'}',
|
||||
if (show.extras.isNotEmpty) '${show.extras.length} ${show.extras.length == 1 ? 'extra' : 'extras'}',
|
||||
if (show.movies.isNotEmpty) '${show.movies.length} ${show.movies.length == 1 ? 'movie' : 'movies'}',
|
||||
?show.group,
|
||||
if (show.folders.length > 1) 'in ${show.folders.length} folders',
|
||||
].join(' · ');
|
||||
final String matchLine;
|
||||
if (entry != null) {
|
||||
final what = [
|
||||
if (entry.format.isNotEmpty) entry.format.replaceAll('_', ' '),
|
||||
if (entry.year != null) '${entry.year}',
|
||||
if (entry.episodes != null) '${entry.episodes} eps',
|
||||
].join(', ');
|
||||
matchLine = [
|
||||
'AniList: ${entry.romaji.isNotEmpty && entry.romaji != title ? entry.romaji : entry.title}'
|
||||
'${what.isEmpty ? '' : ' ($what)'}',
|
||||
if (title != show.title) 'files say "${show.title}"',
|
||||
].join(' · ');
|
||||
} else {
|
||||
matchLine = busy ? 'Looking it up on AniList…' : 'Not matched on AniList';
|
||||
}
|
||||
final started = widget.lastPlayed != null;
|
||||
final prompt = next == null ? null : skipPrompt(next, started: started);
|
||||
final nextLabel = next == null
|
||||
? 'Watched to the end'
|
||||
: next.skipped != null
|
||||
? (started ? 'Skip to ${next.episode.episode}' : 'Start at ${next.episode.episode}')
|
||||
: '${started ? 'Next' : 'Play'}: ${episodeNumber(next.episode)}';
|
||||
return LayoutBuilder(builder: (context, box) {
|
||||
final h = (box.maxWidth * 0.28).clamp(220.0, 340.0);
|
||||
final cover = entry?.cover;
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: SizedBox(
|
||||
height: h,
|
||||
child: Stack(fit: StackFit.expand, children: [
|
||||
PosterImage(
|
||||
url: entry?.banner ?? entry?.cover,
|
||||
framePath: show.episodes.firstOrNull?.path,
|
||||
thumbs: widget.actions.thumbs),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.centerLeft,
|
||||
end: Alignment.centerRight,
|
||||
colors: [
|
||||
scheme.surface.withValues(alpha: 0.96),
|
||||
scheme.surface.withValues(alpha: 0.8),
|
||||
scheme.surface.withValues(alpha: 0.15),
|
||||
],
|
||||
stops: const [0, 0.5, 1],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
if (cover != null && box.maxWidth > 560) ...[
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: SizedBox(
|
||||
width: (h - 40) / 1.5,
|
||||
child: PosterImage(url: cover, thumbs: widget.actions.thumbs),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 18),
|
||||
],
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Row(children: [
|
||||
Flexible(
|
||||
child: Text(title,
|
||||
maxLines: 2, overflow: TextOverflow.ellipsis, style: t.headlineMedium),
|
||||
),
|
||||
if (m?.pinned != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
Pill(m!.pinned == PinScope.folder ? 'pinned for this folder' : 'pinned', scheme.primary),
|
||||
],
|
||||
]),
|
||||
const SizedBox(height: 6),
|
||||
Text(meta, style: t.bodyMedium?.copyWith(color: Colors.grey)),
|
||||
const SizedBox(height: 2),
|
||||
Text(matchLine,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.bodySmall?.copyWith(color: scheme.onSurfaceVariant)),
|
||||
if (prompt != null) ...[
|
||||
const SizedBox(height: 10),
|
||||
Row(children: [
|
||||
Icon(Icons.info_outline, size: 16, color: scheme.tertiary),
|
||||
const SizedBox(width: 6),
|
||||
Flexible(child: Text(prompt, style: t.bodyMedium?.copyWith(color: scheme.tertiary))),
|
||||
]),
|
||||
],
|
||||
const SizedBox(height: 12),
|
||||
Wrap(spacing: 8, runSpacing: 8, children: [
|
||||
FilledButton.icon(
|
||||
key: const ValueKey('show-next'),
|
||||
onPressed: next == null ? null : () => widget.actions.play(next.episode.path),
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
label: Text(nextLabel),
|
||||
),
|
||||
OutlinedButton.icon(
|
||||
onPressed: () => showWrongShowDialog(context, show, widget.matcher),
|
||||
icon: const Icon(Icons.manage_search, size: 18),
|
||||
label: const Text('Wrong show?'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => showEpisodeNumbersDialog(context, show, widget.matcher),
|
||||
child: const Text('Episode numbers…'),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class _GapRow extends StatelessWidget {
|
||||
final String text;
|
||||
const _GapRow(this.text);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 6, 8, 6),
|
||||
child: Row(children: [
|
||||
Icon(Icons.more_vert, size: 18, color: scheme.onSurfaceVariant),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(text,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: scheme.onSurfaceVariant, fontStyle: FontStyle.italic, fontSize: 13)),
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// "Wrong show?": search AniList, pick the right entry, pin it for the
|
||||
/// show everywhere or for one of its folders.
|
||||
Future<void> showWrongShowDialog(BuildContext context, LocalShow show, ShowMatcher matcher) =>
|
||||
showDialog<void>(context: context, builder: (context) => WrongShowDialog(show: show, matcher: matcher));
|
||||
|
||||
class WrongShowDialog extends StatefulWidget {
|
||||
final LocalShow show;
|
||||
final ShowMatcher matcher;
|
||||
const WrongShowDialog({super.key, required this.show, required this.matcher});
|
||||
|
||||
@override
|
||||
State<WrongShowDialog> createState() => _WrongShowDialogState();
|
||||
}
|
||||
|
||||
class _WrongShowDialogState extends State<WrongShowDialog> {
|
||||
late final _query = TextEditingController(text: widget.show.title.replaceAll(RegExp(r'[._]+'), ' '));
|
||||
List<AniListEntry>? _hits;
|
||||
String? _error;
|
||||
bool _searching = false;
|
||||
/// Null: the whole show; else one of its folders.
|
||||
String? _folder;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_search();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_query.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _search() async {
|
||||
setState(() {
|
||||
_searching = true;
|
||||
_error = null;
|
||||
});
|
||||
try {
|
||||
final hits = await widget.matcher.search(_query.text);
|
||||
if (mounted) setState(() => _hits = hits);
|
||||
} catch (e) {
|
||||
if (mounted) setState(() => _error = 'AniList did not answer ($e)');
|
||||
} finally {
|
||||
if (mounted) setState(() => _searching = false);
|
||||
}
|
||||
}
|
||||
|
||||
void _pin(AniListEntry e) {
|
||||
final folder = _folder;
|
||||
folder == null ? widget.matcher.pinShow(widget.show.key, e) : widget.matcher.pinFolder(folder, e);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final show = widget.show;
|
||||
final m = widget.matcher;
|
||||
final showPin = m.showPin(show.key);
|
||||
final folderPins = [for (final f in show.folders) if (m.folderPin(f)?.folder == f) f];
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
return AlertDialog(
|
||||
title: const Text('Wrong show?'),
|
||||
content: SizedBox(
|
||||
width: 520,
|
||||
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Text('Search AniList and pick what "${show.title}" really is. '
|
||||
'A pin wins over the automatic match and survives rescans.',
|
||||
style: TextStyle(color: scheme.onSurfaceVariant)),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
controller: _query,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'Title on AniList',
|
||||
suffixIcon: IconButton(tooltip: 'Search', icon: const Icon(Icons.search), onPressed: _search),
|
||||
),
|
||||
onSubmitted: (_) => _search(),
|
||||
),
|
||||
if (show.folders.length > 1 || folderPins.isNotEmpty) ...[
|
||||
const SizedBox(height: 10),
|
||||
DropdownButton<String?>(
|
||||
value: _folder,
|
||||
isExpanded: true,
|
||||
items: [
|
||||
const DropdownMenuItem(value: null, child: Text('For this show everywhere')),
|
||||
for (final f in show.folders)
|
||||
DropdownMenuItem(value: f, child: Text('Only the folder "${baseName(f)}"', overflow: TextOverflow.ellipsis)),
|
||||
],
|
||||
onChanged: (v) => setState(() => _folder = v),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 8),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxHeight: 340),
|
||||
child: _searching && _hits == null
|
||||
? const Padding(padding: EdgeInsets.all(24), child: Center(child: CircularProgressIndicator()))
|
||||
: _error != null
|
||||
? Text(_error!, style: TextStyle(color: scheme.error))
|
||||
: (_hits ?? const []).isEmpty
|
||||
? const Padding(padding: EdgeInsets.all(12), child: Text('Nothing found'))
|
||||
: ListView(shrinkWrap: true, children: [
|
||||
for (final e in _hits!)
|
||||
ListTile(
|
||||
key: ValueKey('hit:${e.id}'),
|
||||
dense: true,
|
||||
leading: SizedBox(
|
||||
width: 32,
|
||||
height: 48,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: e.coverSmall == null
|
||||
? const ColoredBox(color: Colors.black26)
|
||||
: Image.network(e.coverSmall!,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (_, _, _) => const ColoredBox(color: Colors.black26)),
|
||||
),
|
||||
),
|
||||
title: Text(e.title, maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
subtitle: Text([
|
||||
if (e.romaji.isNotEmpty && e.romaji != e.title) e.romaji,
|
||||
if (e.format.isNotEmpty) e.format.replaceAll('_', ' '),
|
||||
if (e.year != null) '${e.year}',
|
||||
if (e.episodes != null) '${e.episodes} eps',
|
||||
].join(' · '), maxLines: 1, overflow: TextOverflow.ellipsis),
|
||||
onTap: () => _pin(e),
|
||||
),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
),
|
||||
actions: [
|
||||
if (showPin != null)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
m.unpinShow(show.key);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Remove the pin'),
|
||||
),
|
||||
for (final f in folderPins)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
m.unpinFolder(f);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('Unpin "${baseName(f)}"'),
|
||||
),
|
||||
TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel')),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// "Episode numbers…": which episode the first file of each season is
|
||||
/// ("these files are episodes N..M").
|
||||
Future<void> showEpisodeNumbersDialog(BuildContext context, LocalShow show, ShowMatcher matcher) =>
|
||||
showDialog<void>(context: context, builder: (context) => _EpisodeNumbersDialog(show: show, matcher: matcher));
|
||||
|
||||
class _EpisodeNumbersDialog extends StatefulWidget {
|
||||
final LocalShow show;
|
||||
final ShowMatcher matcher;
|
||||
const _EpisodeNumbersDialog({required this.show, required this.matcher});
|
||||
|
||||
@override
|
||||
State<_EpisodeNumbersDialog> createState() => _EpisodeNumbersDialogState();
|
||||
}
|
||||
|
||||
class _EpisodeNumbersDialogState extends State<_EpisodeNumbersDialog> {
|
||||
late final _fields = {
|
||||
for (final s in widget.show.seasons)
|
||||
s.number: TextEditingController(
|
||||
text: '${s.distinct.first.episode! + widget.matcher.offset(widget.show.key, s.number)}'),
|
||||
};
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (final c in _fields.values) {
|
||||
c.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _save() {
|
||||
for (final s in widget.show.seasons) {
|
||||
final first = s.distinct.first.episode!;
|
||||
final want = int.tryParse(_fields[s.number]!.text.trim());
|
||||
if (want != null && want > 0) widget.matcher.setOffset(widget.show.key, s.number, want - first);
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => AlertDialog(
|
||||
title: const Text('Episode numbers'),
|
||||
content: SizedBox(
|
||||
width: 420,
|
||||
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
const Text('When the files count differently from AniList, say which episode the first file is; '
|
||||
'the others follow.'),
|
||||
const SizedBox(height: 12),
|
||||
for (final s in widget.show.seasons)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Row(children: [
|
||||
Expanded(
|
||||
child: Text('${s.title}: the file numbered ${s.distinct.first.episode} is episode',
|
||||
maxLines: 2),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(
|
||||
width: 72,
|
||||
child: TextField(
|
||||
key: ValueKey('offset:${s.number}'),
|
||||
controller: _fields[s.number],
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(isDense: true, border: OutlineInputBorder()),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel')),
|
||||
FilledButton(onPressed: _save, child: const Text('Save')),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../shell/motion.dart';
|
||||
import '../thumbnails.dart';
|
||||
|
||||
// Lazy poster frames for the Files page. A tile asks for its frame only
|
||||
// after it has stayed on screen for a moment, so a fast scroll requests
|
||||
// nothing; tiles sharing a file share one request, and the request is
|
||||
// cancelled once no tile on screen wants it any more.
|
||||
|
||||
/// [thumbnailFor]'s shape; swapped in tests.
|
||||
typedef ThumbnailLoader = Future<Thumbnail?> Function(String path, {bool Function()? cancelled});
|
||||
|
||||
/// A tile waits this long on screen before asking for its frame.
|
||||
const thumbRequestDelay = Duration(milliseconds: 120);
|
||||
|
||||
/// Results of a [ThumbnailLoader] and who is waiting for them.
|
||||
class ThumbCache {
|
||||
final ThumbnailLoader load;
|
||||
ThumbCache(this.load);
|
||||
|
||||
final _done = <String, Thumbnail?>{};
|
||||
final _pending = <String, Future<Thumbnail?>>{};
|
||||
final _waiting = <String, int>{};
|
||||
|
||||
/// Shared by every page using [thumbnailFor].
|
||||
static final shared = ThumbCache(thumbnailFor);
|
||||
|
||||
bool has(String path) => _done.containsKey(path);
|
||||
Thumbnail? cached(String path) => _done[path];
|
||||
|
||||
/// Pair every call with one [release].
|
||||
Future<Thumbnail?> request(String path) {
|
||||
_waiting.update(path, (n) => n + 1, ifAbsent: () => 1);
|
||||
if (_done.containsKey(path)) return Future.value(_done[path]);
|
||||
return _pending[path] ??= _start(path);
|
||||
}
|
||||
|
||||
void release(String path) {
|
||||
final n = (_waiting[path] ?? 0) - 1;
|
||||
if (n > 0) {
|
||||
_waiting[path] = n;
|
||||
} else {
|
||||
_waiting.remove(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// Drops results, so the next request asks the loader again (rescan).
|
||||
void forget(Iterable<String> paths) {
|
||||
for (final p in paths) {
|
||||
_done.remove(p);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Thumbnail?> _start(String path) {
|
||||
var gaveUp = false;
|
||||
return load(path, cancelled: () => gaveUp = !_waiting.containsKey(path))
|
||||
.catchError((Object _) => null)
|
||||
.then((t) {
|
||||
if (t == null && gaveUp) {
|
||||
// Cancelled: not a result. Someone may have come back meanwhile.
|
||||
if (_waiting.containsKey(path)) return _start(path);
|
||||
_pending.remove(path);
|
||||
return null;
|
||||
}
|
||||
_pending.remove(path);
|
||||
_done[path] = t;
|
||||
return t;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds with the frame of [path] (null while loading or when there is
|
||||
/// none); [loaded] is false until the request finished.
|
||||
class ThumbBuilder extends StatefulWidget {
|
||||
final ThumbCache cache;
|
||||
final String path;
|
||||
final Widget Function(BuildContext context, Thumbnail? thumb, bool loaded) builder;
|
||||
const ThumbBuilder({super.key, required this.cache, required this.path, required this.builder});
|
||||
|
||||
@override
|
||||
State<ThumbBuilder> createState() => _ThumbBuilderState();
|
||||
}
|
||||
|
||||
class _ThumbBuilderState extends State<ThumbBuilder> {
|
||||
Thumbnail? _thumb;
|
||||
bool _loaded = false;
|
||||
Timer? _delay;
|
||||
// The request held right now: its path, and a token so a late answer to
|
||||
// an older request is ignored.
|
||||
String? _holding;
|
||||
Object? _token;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_begin();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ThumbBuilder old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (old.path != widget.path || old.cache != widget.cache) {
|
||||
_end(old.cache);
|
||||
_begin();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_end(widget.cache);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _begin() {
|
||||
final cache = widget.cache, path = widget.path;
|
||||
_loaded = cache.has(path);
|
||||
_thumb = cache.cached(path);
|
||||
if (_loaded) return;
|
||||
_delay = Timer(thumbRequestDelay, () {
|
||||
_delay = null;
|
||||
_holding = path;
|
||||
final token = _token = Object();
|
||||
cache.request(path).then((t) {
|
||||
if (_token != token) return;
|
||||
_holding = _token = null;
|
||||
cache.release(path);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_thumb = t;
|
||||
_loaded = true;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void _end(ThumbCache cache) {
|
||||
_delay?.cancel();
|
||||
_delay = null;
|
||||
final held = _holding;
|
||||
_holding = _token = null;
|
||||
if (held != null) cache.release(held);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => widget.builder(context, _thumb, _loaded);
|
||||
}
|
||||
|
||||
/// The frame, fading in over a placeholder.
|
||||
class ThumbImage extends StatelessWidget {
|
||||
final Thumbnail? thumb;
|
||||
final double? width, height;
|
||||
const ThumbImage(this.thumb, {super.key, this.width, this.height});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final placeholder = Container(
|
||||
width: width,
|
||||
height: height,
|
||||
color: scheme.surfaceContainerHighest,
|
||||
alignment: Alignment.center,
|
||||
child: Icon(Icons.movie_outlined, color: scheme.onSurfaceVariant, size: 20),
|
||||
);
|
||||
final t = thumb;
|
||||
if (t == null) return placeholder;
|
||||
final dpr = MediaQuery.devicePixelRatioOf(context);
|
||||
return Stack(
|
||||
fit: width == null ? StackFit.expand : StackFit.loose,
|
||||
children: [
|
||||
placeholder,
|
||||
Image.file(
|
||||
File(t.imagePath),
|
||||
width: width,
|
||||
height: height,
|
||||
fit: BoxFit.cover,
|
||||
cacheWidth: width == null ? null : (width! * dpr).round(),
|
||||
gaplessPlayback: true,
|
||||
errorBuilder: (_, _, _) => const SizedBox.shrink(),
|
||||
frameBuilder: (context, child, frame, sync) => sync
|
||||
? child
|
||||
: AnimatedOpacity(
|
||||
opacity: frame == null ? 0 : 1,
|
||||
duration: easeTime,
|
||||
curve: ease,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// `1:02:03` / `24:05`.
|
||||
String formatDuration(Duration d) {
|
||||
final h = d.inHours, m = d.inMinutes % 60, s = d.inSeconds % 60;
|
||||
String two(int n) => n.toString().padLeft(2, '0');
|
||||
return h > 0 ? '$h:${two(m)}:${two(s)}' : '${two(m)}:${two(s)}';
|
||||
}
|
||||
|
||||
/// `1.4 GB` / `350 MB` / `12 KB`.
|
||||
String formatSize(int bytes) {
|
||||
if (bytes >= 1 << 30) return '${(bytes / (1 << 30)).toStringAsFixed(1)} GB';
|
||||
if (bytes >= 1 << 20) return '${(bytes / (1 << 20)).toStringAsFixed(0)} MB';
|
||||
return '${(bytes / 1024).ceil()} KB';
|
||||
}
|
||||
|
||||
/// The frame's duration, or null when unknown (no frame, 0 length).
|
||||
String? durationText(Thumbnail? t) =>
|
||||
t == null || t.duration <= Duration.zero ? null : formatDuration(t.duration);
|
||||
@@ -0,0 +1,573 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../screens/home/picked_media.dart';
|
||||
|
||||
// Linked Jellyfin servers, one account per ServerId, in their own Hive box.
|
||||
//
|
||||
// Only tokens this app obtained itself (Quick Connect or password through
|
||||
// [JellyfinSignIn]) are ever stored or used: Jellyfin overwrites a token's
|
||||
// device name and app version with whatever header comes with it, so
|
||||
// borrowing another client's token would rename that client's device.
|
||||
|
||||
const jellyfinBoxName = 'jellyfin';
|
||||
const _keyDeviceId = 'deviceId';
|
||||
const _keyAccounts = 'accounts';
|
||||
const _keyDefault = 'defaultServer';
|
||||
const _keyLastPick = 'lastPick';
|
||||
const _keyBrowsePrefix = 'browse:';
|
||||
const _keyDismissedPrefix = 'dismissed:';
|
||||
|
||||
/// One signed-in user on one server.
|
||||
class JellyfinAccount {
|
||||
final String serverId;
|
||||
final String serverName;
|
||||
final String serverVersion;
|
||||
/// Addresses this server was reached at, preferred first.
|
||||
final List<String> urls;
|
||||
final String userId;
|
||||
final String userName;
|
||||
final String? userImageTag;
|
||||
final String token;
|
||||
const JellyfinAccount({
|
||||
required this.serverId,
|
||||
required this.serverName,
|
||||
this.serverVersion = '',
|
||||
required this.urls,
|
||||
required this.userId,
|
||||
required this.userName,
|
||||
this.userImageTag,
|
||||
required this.token,
|
||||
});
|
||||
|
||||
String get baseUrl => urls.first;
|
||||
|
||||
JellyfinUser get user =>
|
||||
JellyfinUser(id: userId, name: userName, serverId: serverId, primaryImageTag: userImageTag);
|
||||
|
||||
/// "Example Server" or the host when the server has no name.
|
||||
String get displayName =>
|
||||
serverName.isNotEmpty ? serverName : (Uri.tryParse(baseUrl)?.host ?? baseUrl);
|
||||
|
||||
JellyfinAccount copyWith({
|
||||
String? serverName,
|
||||
String? serverVersion,
|
||||
List<String>? urls,
|
||||
String? userName,
|
||||
String? userImageTag,
|
||||
}) =>
|
||||
JellyfinAccount(
|
||||
serverId: serverId,
|
||||
serverName: serverName ?? this.serverName,
|
||||
serverVersion: serverVersion ?? this.serverVersion,
|
||||
urls: urls ?? this.urls,
|
||||
userId: userId,
|
||||
userName: userName ?? this.userName,
|
||||
userImageTag: userImageTag ?? this.userImageTag,
|
||||
token: token,
|
||||
);
|
||||
|
||||
Map<String, Object?> toJson() => {
|
||||
'serverId': serverId,
|
||||
'serverName': serverName,
|
||||
'serverVersion': serverVersion,
|
||||
'urls': urls,
|
||||
'userId': userId,
|
||||
'userName': userName,
|
||||
'userImageTag': ?userImageTag,
|
||||
'token': token,
|
||||
};
|
||||
|
||||
static JellyfinAccount? fromJson(Object? j) {
|
||||
if (j is! Map) return null;
|
||||
final sid = j['serverId'], uid = j['userId'], token = j['token'], urls = j['urls'];
|
||||
if (sid is! String || uid is! String || token is! String || urls is! List) return null;
|
||||
final list = urls.whereType<String>().toList();
|
||||
if (sid.isEmpty || token.isEmpty || list.isEmpty) return null;
|
||||
String s(Object? v) => v is String ? v : '';
|
||||
return JellyfinAccount(
|
||||
serverId: sid,
|
||||
serverName: s(j['serverName']),
|
||||
serverVersion: s(j['serverVersion']),
|
||||
urls: list,
|
||||
userId: uid,
|
||||
userName: s(j['userName']),
|
||||
userImageTag: j['userImageTag'] is String ? j['userImageTag'] as String : null,
|
||||
token: token,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum JellyfinAccountStatus {
|
||||
/// Not checked yet this run.
|
||||
unknown,
|
||||
checking,
|
||||
online,
|
||||
/// Unreachable (network error); the token may still be fine.
|
||||
offline,
|
||||
/// The server rejected the token: sign in again ("Reconnect").
|
||||
expired,
|
||||
}
|
||||
|
||||
/// Key-value persistence behind [JellyfinAccounts]; tests use
|
||||
/// [MemoryJellyfinStore].
|
||||
abstract class JellyfinStore {
|
||||
Future<void> open();
|
||||
Object? get(String key);
|
||||
Future<void> put(String key, Object? value);
|
||||
}
|
||||
|
||||
class HiveJellyfinStore implements JellyfinStore {
|
||||
HiveJellyfinStore({this.boxName = jellyfinBoxName});
|
||||
final String boxName;
|
||||
Box? _box;
|
||||
|
||||
@override
|
||||
Future<void> open() async => _box ??= await Hive.openBox(boxName);
|
||||
|
||||
@override
|
||||
Object? get(String key) => _box?.get(key);
|
||||
|
||||
@override
|
||||
Future<void> put(String key, Object? value) async {
|
||||
final box = _box;
|
||||
if (box == null) return;
|
||||
value == null ? await box.delete(key) : await box.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
class MemoryJellyfinStore implements JellyfinStore {
|
||||
final Map<String, Object?> data;
|
||||
MemoryJellyfinStore([Map<String, Object?>? data]) : data = data ?? {};
|
||||
|
||||
@override
|
||||
Future<void> open() async {}
|
||||
@override
|
||||
Object? get(String key) => data[key];
|
||||
@override
|
||||
Future<void> put(String key, Object? value) async =>
|
||||
value == null ? data.remove(key) : data[key] = value;
|
||||
}
|
||||
|
||||
/// All linked Jellyfin servers, their live status and one authenticated
|
||||
/// [JellyfinClient] each. [ensureLoaded] reads the box and then checks every
|
||||
/// token in the background; a rejected token turns the account
|
||||
/// [JellyfinAccountStatus.expired] (shown as "Reconnect"), never a silent
|
||||
/// sign-out.
|
||||
class JellyfinAccounts extends ChangeNotifier {
|
||||
static final JellyfinAccounts instance = JellyfinAccounts();
|
||||
|
||||
JellyfinAccounts({
|
||||
JellyfinStore? store,
|
||||
this.httpFactory,
|
||||
this.deviceName,
|
||||
}) : _store = store ?? HiveJellyfinStore();
|
||||
|
||||
final JellyfinStore _store;
|
||||
/// Transport for every client made here; null = real HTTP. Tests fake it.
|
||||
final JellyfinHttp Function()? httpFactory;
|
||||
/// Device name sent to Jellyfin; null = the hostname.
|
||||
final String? deviceName;
|
||||
|
||||
List<JellyfinAccount> _accounts = const [];
|
||||
final _status = <String, JellyfinAccountStatus>{};
|
||||
final _errors = <String, String>{};
|
||||
final _clients = <String, JellyfinClient>{};
|
||||
final _memo = <String, ({DateTime at, Future<Object?> value})>{};
|
||||
String? _defaultServerId;
|
||||
String _deviceId = '';
|
||||
JellyfinMedia? _lastPick;
|
||||
Future<void>? _load;
|
||||
bool _loaded = false;
|
||||
bool _disposed = false;
|
||||
|
||||
List<JellyfinAccount> get accounts => _accounts;
|
||||
bool get loaded => _loaded;
|
||||
bool get isEmpty => _accounts.isEmpty;
|
||||
|
||||
JellyfinAccount? account(String serverId) =>
|
||||
_accounts.where((a) => a.serverId == serverId).firstOrNull;
|
||||
|
||||
/// [itemId]'s page in the web UI of linked server [serverId] ("Open in
|
||||
/// Jellyfin"); null when that server is not linked here.
|
||||
String? webUrlOf(String serverId, String itemId) {
|
||||
final a = account(serverId);
|
||||
return a == null ? null : jellyfinWebUrl(a.baseUrl, itemId, serverId: serverId);
|
||||
}
|
||||
|
||||
/// The chosen default, else the first linked server.
|
||||
JellyfinAccount? get defaultAccount =>
|
||||
(_defaultServerId == null ? null : account(_defaultServerId!)) ?? _accounts.firstOrNull;
|
||||
|
||||
String? get defaultServerId => defaultAccount?.serverId;
|
||||
|
||||
JellyfinAccountStatus statusOf(String serverId) =>
|
||||
_status[serverId] ?? JellyfinAccountStatus.unknown;
|
||||
|
||||
/// Last failure text for an offline account.
|
||||
String? errorOf(String serverId) => _errors[serverId];
|
||||
|
||||
/// The last Jellyfin pick put up, restored in the Library on the next start.
|
||||
JellyfinMedia? get lastPick => _lastPick;
|
||||
|
||||
/// Stable per install: Jellyfin keys devices and tokens by it.
|
||||
String get deviceId => _deviceId;
|
||||
|
||||
JellyfinClientInfo get clientInfo => JellyfinClientInfo(
|
||||
// The old name on purpose: Jellyfin lists devices under it.
|
||||
client: 'Watch Together',
|
||||
device: deviceName ?? _hostname(),
|
||||
deviceId: _deviceId.isEmpty ? 'unknown' : _deviceId,
|
||||
version: appVersion,
|
||||
);
|
||||
|
||||
static String _hostname() {
|
||||
try {
|
||||
final h = Platform.localHostname;
|
||||
return h.isEmpty ? 'Desktop' : h;
|
||||
} catch (_) {
|
||||
return 'Desktop';
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> ensureLoaded({bool validate = true}) =>
|
||||
_load ??= _loadNow(validate: validate);
|
||||
|
||||
Future<void> _loadNow({required bool validate}) async {
|
||||
try {
|
||||
await _store.open();
|
||||
final id = _store.get(_keyDeviceId);
|
||||
if (id is String && id.isNotEmpty) {
|
||||
_deviceId = id;
|
||||
} else {
|
||||
_deviceId = _newDeviceId();
|
||||
await _store.put(_keyDeviceId, _deviceId);
|
||||
}
|
||||
_accounts = _decodeAccounts(_store.get(_keyAccounts));
|
||||
final def = _store.get(_keyDefault);
|
||||
_defaultServerId = def is String ? def : null;
|
||||
final pick = _store.get(_keyLastPick);
|
||||
_lastPick = pick is String ? JellyfinMedia.fromJson(_tryJson(pick)) : null;
|
||||
} catch (e, st) {
|
||||
debugPrint('load jellyfin accounts failed: $e\n$st');
|
||||
if (_deviceId.isEmpty) _deviceId = _newDeviceId();
|
||||
}
|
||||
_loaded = true;
|
||||
_notify();
|
||||
if (validate) unawaited(validateAll());
|
||||
}
|
||||
|
||||
static String _newDeviceId() {
|
||||
final r = Random.secure();
|
||||
return [for (var i = 0; i < 16; i++) r.nextInt(256).toRadixString(16).padLeft(2, '0')].join();
|
||||
}
|
||||
|
||||
static Object? _tryJson(String s) {
|
||||
try {
|
||||
return jsonDecode(s);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static List<JellyfinAccount> _decodeAccounts(Object? raw) {
|
||||
if (raw is! String) return const [];
|
||||
final list = _tryJson(raw);
|
||||
if (list is! List) return const [];
|
||||
final out = <JellyfinAccount>[];
|
||||
for (final j in list) {
|
||||
final a = JellyfinAccount.fromJson(j);
|
||||
if (a != null && out.every((o) => o.serverId != a.serverId)) out.add(a);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
try {
|
||||
await _store.put(_keyAccounts, jsonEncode([for (final a in _accounts) a.toJson()]));
|
||||
await _store.put(_keyDefault, _defaultServerId);
|
||||
} catch (e, st) {
|
||||
debugPrint('save jellyfin accounts failed: $e\n$st');
|
||||
}
|
||||
}
|
||||
|
||||
void _notify() {
|
||||
if (!_disposed) notifyListeners();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------- clients
|
||||
|
||||
/// A client without a token, for probing an address and signing in.
|
||||
/// The caller closes it.
|
||||
JellyfinClient anonymousClient(String baseUrl) =>
|
||||
JellyfinClient(baseUrl: baseUrl, clientInfo: clientInfo, http: httpFactory?.call());
|
||||
|
||||
/// The signed-in client of a linked server (null if not linked). Shared;
|
||||
/// do not close it.
|
||||
JellyfinClient? clientFor(String serverId) {
|
||||
final a = account(serverId);
|
||||
if (a == null) return null;
|
||||
final c = _clients[serverId];
|
||||
if (c != null && c.baseUrl == a.baseUrl && c.accessToken == a.token) return c;
|
||||
c?.close();
|
||||
return _clients[serverId] = JellyfinClient(
|
||||
baseUrl: a.baseUrl,
|
||||
clientInfo: clientInfo,
|
||||
accessToken: a.token,
|
||||
userId: a.userId,
|
||||
http: httpFactory?.call(),
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------- validation
|
||||
|
||||
Future<void> validateAll() => Future.wait([for (final a in _accounts) validate(a.serverId)]);
|
||||
|
||||
/// Checks the saved token. Tries each known address in order and moves
|
||||
/// the first that answers to the front.
|
||||
Future<JellyfinAccountStatus> validate(String serverId) async {
|
||||
final start = account(serverId);
|
||||
if (start == null) return JellyfinAccountStatus.unknown;
|
||||
_status[serverId] = JellyfinAccountStatus.checking;
|
||||
_notify();
|
||||
Object? lastError;
|
||||
for (final url in start.urls) {
|
||||
final client = JellyfinClient(
|
||||
baseUrl: url,
|
||||
clientInfo: clientInfo,
|
||||
accessToken: start.token,
|
||||
userId: start.userId,
|
||||
http: httpFactory?.call(),
|
||||
);
|
||||
try {
|
||||
final user = await client.validateToken();
|
||||
if (user == null) return _setStatus(serverId, JellyfinAccountStatus.expired);
|
||||
final a = account(serverId);
|
||||
if (a == null) return JellyfinAccountStatus.unknown;
|
||||
_replace(a.copyWith(
|
||||
userName: user.name.isEmpty ? null : user.name,
|
||||
userImageTag: user.primaryImageTag,
|
||||
urls: [url, ...a.urls.where((u) => u != url)],
|
||||
));
|
||||
unawaited(_save());
|
||||
_errors.remove(serverId);
|
||||
return _setStatus(serverId, JellyfinAccountStatus.online);
|
||||
} catch (e) {
|
||||
lastError = e;
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
_errors[serverId] = _short(lastError);
|
||||
return _setStatus(serverId, JellyfinAccountStatus.offline);
|
||||
}
|
||||
|
||||
static String _short(Object? e) {
|
||||
final s = '$e'.replaceFirst('JellyfinException: ', '');
|
||||
return s.length > 160 ? '${s.substring(0, 160)}…' : s;
|
||||
}
|
||||
|
||||
JellyfinAccountStatus _setStatus(String serverId, JellyfinAccountStatus s) {
|
||||
_status[serverId] = s;
|
||||
_notify();
|
||||
return s;
|
||||
}
|
||||
|
||||
/// A browse call got 401: the token is gone, ask to reconnect.
|
||||
void markExpired(String serverId) {
|
||||
if (statusOf(serverId) == JellyfinAccountStatus.expired) return;
|
||||
_setStatus(serverId, JellyfinAccountStatus.expired);
|
||||
}
|
||||
|
||||
void _replace(JellyfinAccount a) {
|
||||
_accounts = [for (final o in _accounts) o.serverId == a.serverId ? a : o];
|
||||
}
|
||||
|
||||
// ------------------------------------------------------- link / unlink
|
||||
|
||||
/// Stores a sign-in made by this app. Signing in again to a linked server
|
||||
/// replaces its account (and best-effort revokes the old token).
|
||||
Future<JellyfinAccount> link({
|
||||
required String baseUrl,
|
||||
required JellyfinServerInfo server,
|
||||
required JellyfinAuthResult auth,
|
||||
}) async {
|
||||
await ensureLoaded(validate: false);
|
||||
final serverId = auth.serverId.isNotEmpty ? auth.serverId : server.id;
|
||||
final old = account(serverId);
|
||||
final a = JellyfinAccount(
|
||||
serverId: serverId,
|
||||
serverName: server.name,
|
||||
serverVersion: server.version,
|
||||
urls: [baseUrl, ...?old?.urls.where((u) => u != baseUrl)],
|
||||
userId: auth.user.id,
|
||||
userName: auth.user.name,
|
||||
userImageTag: auth.user.primaryImageTag,
|
||||
token: auth.accessToken,
|
||||
);
|
||||
if (old != null && old.token != a.token) unawaited(_revoke(old));
|
||||
_accounts = old == null ? [..._accounts, a] : [for (final o in _accounts) o.serverId == serverId ? a : o];
|
||||
_defaultServerId ??= serverId;
|
||||
_status[serverId] = JellyfinAccountStatus.online;
|
||||
_errors.remove(serverId);
|
||||
_clearMemo(serverId);
|
||||
await _save();
|
||||
_notify();
|
||||
return a;
|
||||
}
|
||||
|
||||
Future<void> _revoke(JellyfinAccount a) async {
|
||||
final c = JellyfinClient(
|
||||
baseUrl: a.baseUrl,
|
||||
clientInfo: clientInfo,
|
||||
accessToken: a.token,
|
||||
userId: a.userId,
|
||||
http: httpFactory?.call());
|
||||
try {
|
||||
await c.logout();
|
||||
} catch (_) {
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/// Revokes the token on the server (best effort: an offline server or an
|
||||
/// already dead token still unlinks) and forgets the account.
|
||||
Future<void> signOut(String serverId) async {
|
||||
final a = account(serverId);
|
||||
if (a == null) return;
|
||||
final c = _clients.remove(serverId);
|
||||
c?.close();
|
||||
await _revoke(a).timeout(const Duration(seconds: 8), onTimeout: () {});
|
||||
_accounts = [for (final o in _accounts) if (o.serverId != serverId) o];
|
||||
_status.remove(serverId);
|
||||
_errors.remove(serverId);
|
||||
_clearMemo(serverId);
|
||||
if (_defaultServerId == serverId) _defaultServerId = _accounts.firstOrNull?.serverId;
|
||||
if (_lastPick?.serverId == serverId) await rememberPick(null);
|
||||
await _save();
|
||||
_notify();
|
||||
}
|
||||
|
||||
Future<void> setDefault(String serverId) async {
|
||||
if (account(serverId) == null || _defaultServerId == serverId) return;
|
||||
_defaultServerId = serverId;
|
||||
_notify();
|
||||
await _save();
|
||||
}
|
||||
|
||||
Future<void> rememberPick(JellyfinMedia? pick) async {
|
||||
_lastPick = pick;
|
||||
try {
|
||||
await _store.put(_keyLastPick, pick == null ? null : jsonEncode(pick.toJson()));
|
||||
} catch (e) {
|
||||
debugPrint('save jellyfin pick failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// The browser's last location on [serverId] (encoded route stack, see
|
||||
/// `browse_scope.dart`), restored by every browser and across restarts.
|
||||
Object? browseLocation(String serverId) {
|
||||
try {
|
||||
final v = _store.get('$_keyBrowsePrefix$serverId');
|
||||
return v is String ? _tryJson(v) : null;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> saveBrowseLocation(String serverId, Object? location) async {
|
||||
try {
|
||||
await _store.put(
|
||||
'$_keyBrowsePrefix$serverId', location == null ? null : jsonEncode(location));
|
||||
} catch (e) {
|
||||
debugPrint('save browse location failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Continue-row entries removed by hand on [serverId] (key -> when), so a
|
||||
/// next-up series (which Jellyfin cannot drop) stays out until it is
|
||||
/// played again. Keys are `continueKey`s.
|
||||
Map<String, DateTime> continueDismissed(String serverId) {
|
||||
try {
|
||||
final v = _store.get('$_keyDismissedPrefix$serverId');
|
||||
final j = v is String ? _tryJson(v) : null;
|
||||
if (j is! Map) return const {};
|
||||
return {
|
||||
for (final e in j.entries)
|
||||
if (e.key is String && e.value is int)
|
||||
e.key as String: DateTime.fromMillisecondsSinceEpoch(e.value as int, isUtc: true),
|
||||
};
|
||||
} catch (_) {
|
||||
return const {};
|
||||
}
|
||||
}
|
||||
|
||||
/// Keeps [key] out of the Continue row on [serverId] until it is played
|
||||
/// after [at] (default now). The newest 200 are kept.
|
||||
Future<void> dismissContinue(String serverId, String key, {DateTime? at}) async {
|
||||
final all = {...continueDismissed(serverId), key: (at ?? DateTime.now()).toUtc()};
|
||||
final newest = all.entries.toList()..sort((a, b) => b.value.compareTo(a.value));
|
||||
try {
|
||||
await _store.put('$_keyDismissedPrefix$serverId', jsonEncode({
|
||||
for (final e in newest.take(200)) e.key: e.value.millisecondsSinceEpoch,
|
||||
}));
|
||||
} catch (e) {
|
||||
debugPrint('save dismissed continue failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------- cache
|
||||
|
||||
/// Short-lived memo for browse calls, so going back does not refetch.
|
||||
/// Failures are not kept; a 401 marks the account expired.
|
||||
Future<T> cached<T>(String serverId, String key, Future<T> Function() load,
|
||||
{Duration ttl = const Duration(minutes: 3)}) {
|
||||
final k = '$serverId|$key';
|
||||
final hit = _memo[k];
|
||||
if (hit != null && DateTime.now().difference(hit.at) < ttl) {
|
||||
return hit.value.then((v) => v as T);
|
||||
}
|
||||
final f = load();
|
||||
_memo[k] = (at: DateTime.now(), value: f);
|
||||
f.catchError((Object e) {
|
||||
if (identical(_memo[k]?.value, f)) _memo.remove(k);
|
||||
if (e is JellyfinException && e.isUnauthorized) markExpired(serverId);
|
||||
throw e;
|
||||
}).ignore();
|
||||
return f;
|
||||
}
|
||||
|
||||
void _clearMemo(String serverId) =>
|
||||
_memo.removeWhere((k, _) => k.startsWith('$serverId|'));
|
||||
|
||||
/// Drops cached browse results (refresh button, after a pick).
|
||||
void invalidate(String serverId) => _clearMemo(serverId);
|
||||
|
||||
final _watched = StreamController<String>.broadcast();
|
||||
|
||||
/// Server ids whose watched state this app just changed (a stop report):
|
||||
/// their cached lists are gone, and browse views reload.
|
||||
Stream<String> get watched => _watched.stream;
|
||||
|
||||
void watchedChanged(String serverId) {
|
||||
_clearMemo(serverId);
|
||||
_watched.add(serverId);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
for (final c in _clients.values) {
|
||||
c.close();
|
||||
}
|
||||
_clients.clear();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../screens/home/ui.dart';
|
||||
import 'accounts.dart';
|
||||
import 'browser.dart' show JellyfinAvatar, StatusDot, showReconnectDialog;
|
||||
import 'sign_in_panel.dart';
|
||||
|
||||
/// Integrations > Jellyfin: linked servers (avatar, status, default,
|
||||
/// reconnect, sign out) and the inline add-server flow.
|
||||
class JellyfinAccountsPanel extends StatefulWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final Duration pollInterval;
|
||||
const JellyfinAccountsPanel({
|
||||
super.key,
|
||||
required this.accounts,
|
||||
this.pollInterval = const Duration(seconds: 3),
|
||||
});
|
||||
|
||||
@override
|
||||
State<JellyfinAccountsPanel> createState() => _JellyfinAccountsPanelState();
|
||||
}
|
||||
|
||||
class _JellyfinAccountsPanelState extends State<JellyfinAccountsPanel> {
|
||||
bool _adding = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.accounts.ensureLoaded();
|
||||
}
|
||||
|
||||
Future<void> _signOut(JellyfinAccount a) async {
|
||||
final ok = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text('Sign out of ${a.displayName}?'),
|
||||
content: const Text(
|
||||
'This app\'s sign-in is revoked on the server and the server is unlinked. '
|
||||
'You can add it again any time.'),
|
||||
actions: [
|
||||
TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')),
|
||||
FilledButton(
|
||||
key: const ValueKey('jf-sign-out-confirm'),
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
child: const Text('Sign out')),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (ok == true) await widget.accounts.signOut(a.serverId);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
return ListenableBuilder(
|
||||
listenable: widget.accounts,
|
||||
builder: (context, _) {
|
||||
final list = widget.accounts.accounts;
|
||||
return Panel(
|
||||
key: const ValueKey('jf-accounts'),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.video_library_outlined,
|
||||
size: 32, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(width: kGap),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Jellyfin', style: t.titleMedium),
|
||||
const SizedBox(height: 4),
|
||||
const Text(
|
||||
'Browse your libraries in the Library tab and put up movies and episodes. '
|
||||
'Sign in with Quick Connect or your password; several servers are fine.',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: kGap),
|
||||
if (!_adding)
|
||||
FilledButton.icon(
|
||||
key: const ValueKey('jf-add-server'),
|
||||
onPressed: () => setState(() => _adding = true),
|
||||
icon: const Icon(Icons.add, size: 18),
|
||||
label: const Text('Add server'),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (list.isNotEmpty) const SizedBox(height: kGap),
|
||||
for (final a in list)
|
||||
_AccountTile(
|
||||
accounts: widget.accounts,
|
||||
account: a,
|
||||
isDefault: widget.accounts.defaultServerId == a.serverId,
|
||||
showDefault: list.length > 1,
|
||||
onSignOut: () => _signOut(a),
|
||||
),
|
||||
if (_adding) ...[
|
||||
const SizedBox(height: kGap),
|
||||
const Divider(height: 1),
|
||||
const SizedBox(height: kGap),
|
||||
JellyfinSignInPanel(
|
||||
accounts: widget.accounts,
|
||||
pollInterval: widget.pollInterval,
|
||||
onCancel: () => setState(() => _adding = false),
|
||||
onDone: (_) => setState(() => _adding = false),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AccountTile extends StatelessWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final JellyfinAccount account;
|
||||
final bool isDefault;
|
||||
final bool showDefault;
|
||||
final VoidCallback onSignOut;
|
||||
const _AccountTile({
|
||||
required this.accounts,
|
||||
required this.account,
|
||||
required this.isDefault,
|
||||
required this.showDefault,
|
||||
required this.onSignOut,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
final status = accounts.statusOf(account.serverId);
|
||||
final statusText = switch (status) {
|
||||
JellyfinAccountStatus.online => 'Connected',
|
||||
JellyfinAccountStatus.offline => 'Offline',
|
||||
JellyfinAccountStatus.expired => 'Sign-in expired',
|
||||
JellyfinAccountStatus.checking => 'Checking…',
|
||||
JellyfinAccountStatus.unknown => 'Not checked',
|
||||
};
|
||||
return Padding(
|
||||
key: ValueKey('jf-account-${account.serverId}'),
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
child: Row(
|
||||
children: [
|
||||
JellyfinAvatar(accounts: accounts, account: account),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('${account.userName} on ${account.displayName}', style: t.titleSmall),
|
||||
Row(children: [
|
||||
StatusDot(status: status),
|
||||
const SizedBox(width: 6),
|
||||
Flexible(
|
||||
child: Text(
|
||||
[
|
||||
statusText,
|
||||
if (account.serverVersion.isNotEmpty) 'Jellyfin ${account.serverVersion}',
|
||||
account.baseUrl,
|
||||
].join(' · '),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.bodySmall?.copyWith(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
]),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (showDefault)
|
||||
IconButton(
|
||||
key: ValueKey('jf-default-${account.serverId}'),
|
||||
tooltip: isDefault ? 'Default server' : 'Make default',
|
||||
onPressed: () => accounts.setDefault(account.serverId),
|
||||
icon: Icon(isDefault ? Icons.star : Icons.star_border,
|
||||
color: isDefault ? Theme.of(context).colorScheme.primary : null),
|
||||
),
|
||||
if (status == JellyfinAccountStatus.expired)
|
||||
FilledButton.tonal(
|
||||
key: ValueKey('jf-reconnect-${account.serverId}'),
|
||||
onPressed: () => showReconnectDialog(context, accounts, account),
|
||||
child: const Text('Reconnect'),
|
||||
)
|
||||
else if (status == JellyfinAccountStatus.offline)
|
||||
TextButton(
|
||||
onPressed: () => accounts.validate(account.serverId),
|
||||
child: const Text('Retry'),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
TextButton(
|
||||
key: ValueKey('jf-sign-out-${account.serverId}'),
|
||||
onPressed: onSignOut,
|
||||
child: const Text('Sign out'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,478 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'accounts.dart';
|
||||
import 'format.dart';
|
||||
import '../widgets/app_menu.dart';
|
||||
import '../widgets/copy_open.dart';
|
||||
|
||||
/// One level of the library browser's back stack.
|
||||
sealed class BrowseRoute {
|
||||
const BrowseRoute();
|
||||
String get label;
|
||||
/// Identity for keeping a page's state while it is in the stack.
|
||||
String get key;
|
||||
}
|
||||
|
||||
final class HomeRoute extends BrowseRoute {
|
||||
const HomeRoute();
|
||||
@override
|
||||
String get label => 'Home';
|
||||
@override
|
||||
String get key => 'home';
|
||||
}
|
||||
|
||||
/// A library or folder grid, optionally opened with a sort ("Show all"
|
||||
/// next to Latest opens it newest first).
|
||||
final class LibraryRoute extends BrowseRoute {
|
||||
final JellyfinItem folder;
|
||||
/// A `LibrarySort` name; null = by name.
|
||||
final String? sort;
|
||||
const LibraryRoute(this.folder, {this.sort});
|
||||
@override
|
||||
String get label => folder.name;
|
||||
@override
|
||||
String get key => sort == null ? 'lib:${folder.id}' : 'lib:${folder.id}:$sort';
|
||||
}
|
||||
|
||||
final class SeriesRoute extends BrowseRoute {
|
||||
final JellyfinItem series;
|
||||
/// Season to open on (from a season card or an episode's "open series").
|
||||
final String? seasonId;
|
||||
const SeriesRoute(this.series, {this.seasonId});
|
||||
@override
|
||||
String get label => series.name;
|
||||
@override
|
||||
String get key => 'series:${series.id}';
|
||||
}
|
||||
|
||||
/// A route stack as JSON for [JellyfinAccounts.saveBrowseLocation]: only
|
||||
/// ids, names and the fields the pages start from (each page loads the
|
||||
/// full item itself).
|
||||
List<Map<String, Object?>> encodeBrowseStack(List<BrowseRoute> stack) => [
|
||||
for (final r in stack)
|
||||
switch (r) {
|
||||
HomeRoute() => {'r': 'home'},
|
||||
LibraryRoute(:final folder, :final sort) => {'r': 'lib', ..._itemJson(folder), 'sort': ?sort},
|
||||
SeriesRoute(:final series, :final seasonId) => {
|
||||
'r': 'series',
|
||||
..._itemJson(series),
|
||||
'seasonId': ?seasonId,
|
||||
},
|
||||
}
|
||||
];
|
||||
|
||||
/// Inverse of [encodeBrowseStack]; always starts with Home. Null when
|
||||
/// [raw] is not a stack. Entries it no longer knows are skipped.
|
||||
List<BrowseRoute>? decodeBrowseStack(Object? raw) {
|
||||
if (raw is! List) return null;
|
||||
final out = <BrowseRoute>[const HomeRoute()];
|
||||
for (final e in raw) {
|
||||
if (e is! Map) return null;
|
||||
final item = _itemFrom(e);
|
||||
final route = switch (e['r']) {
|
||||
'lib' when item != null =>
|
||||
LibraryRoute(item, sort: e['sort'] is String ? e['sort'] as String : null),
|
||||
'series' when item != null =>
|
||||
SeriesRoute(item, seasonId: e['seasonId'] is String ? e['seasonId'] as String : null),
|
||||
_ => null,
|
||||
};
|
||||
if (route != null && out.every((r) => r.key != route.key)) out.add(route);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Map<String, Object?> _itemJson(JellyfinItem i) => {
|
||||
'id': i.id,
|
||||
'name': i.name,
|
||||
'type': i.type,
|
||||
if (i.isFolder) 'isFolder': true,
|
||||
'collectionType': ?i.collectionType,
|
||||
'seriesId': ?i.seriesId,
|
||||
'seriesName': ?i.seriesName,
|
||||
'seasonId': ?i.seasonId,
|
||||
'indexNumber': ?i.indexNumber,
|
||||
'parentIndexNumber': ?i.parentIndexNumber,
|
||||
};
|
||||
|
||||
JellyfinItem? _itemFrom(Map e) {
|
||||
String? s(String k) => e[k] is String && (e[k] as String).isNotEmpty ? e[k] as String : null;
|
||||
final id = s('id');
|
||||
if (id == null) return null;
|
||||
return JellyfinItem(
|
||||
id: id,
|
||||
name: s('name') ?? '',
|
||||
type: s('type') ?? '',
|
||||
isFolder: e['isFolder'] == true,
|
||||
collectionType: s('collectionType'),
|
||||
seriesId: s('seriesId'),
|
||||
seriesName: s('seriesName'),
|
||||
seasonId: e['r'] == 'series' ? null : s('seasonId'),
|
||||
indexNumber: e['indexNumber'] is int ? e['indexNumber'] as int : null,
|
||||
parentIndexNumber: e['parentIndexNumber'] is int ? e['parentIndexNumber'] as int : null,
|
||||
);
|
||||
}
|
||||
|
||||
/// Where a browser opens instead of the remembered location: a server and
|
||||
/// a route stack (e.g. the series of the episode playing).
|
||||
class BrowseStart {
|
||||
final String serverId;
|
||||
final List<BrowseRoute> stack;
|
||||
const BrowseStart(this.serverId, this.stack);
|
||||
|
||||
/// The series page of [episode] with its season selected.
|
||||
static BrowseStart? seriesOf(String serverId, JellyfinItem episode) {
|
||||
final sid = episode.seriesId;
|
||||
if (sid == null) return null;
|
||||
return BrowseStart(serverId, [
|
||||
const HomeRoute(),
|
||||
SeriesRoute(JellyfinItem(id: sid, name: episode.seriesName ?? '', type: 'Series'),
|
||||
seasonId: episode.seasonId),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/// The card selected in the library (details panel): an item on a server.
|
||||
/// [item] is what the card had, when known (the panel loads it in full).
|
||||
class JellyfinSelection {
|
||||
final String serverId;
|
||||
final String itemId;
|
||||
final JellyfinItem? item;
|
||||
const JellyfinSelection(this.serverId, this.itemId, [this.item]);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
other is JellyfinSelection && other.serverId == serverId && other.itemId == itemId;
|
||||
@override
|
||||
int get hashCode => Object.hash(serverId, itemId);
|
||||
}
|
||||
|
||||
/// Browser location shared by the browser, the library chips in the
|
||||
/// Library header and the details panel: the server shown, its route
|
||||
/// stack (saved per server on every move), a data version that bumps after
|
||||
/// watched-state changes (rows reload), and the keys in the Continue row.
|
||||
class BrowseController extends ChangeNotifier {
|
||||
final JellyfinAccounts accounts;
|
||||
/// Clock for the Continue row's age cut-off (tests pin it).
|
||||
final DateTime Function() now;
|
||||
BrowseController(this.accounts, {this.now = DateTime.now}) {
|
||||
// Back from watching: the rows show what was just watched.
|
||||
_watchedSub = accounts.watched.listen((id) {
|
||||
if (!_disposed && id == serverId) dataChanged();
|
||||
});
|
||||
}
|
||||
|
||||
late final StreamSubscription<String> _watchedSub;
|
||||
|
||||
String? _serverId;
|
||||
List<BrowseRoute> _stack = const [HomeRoute()];
|
||||
bool _started = false;
|
||||
int _version = 0;
|
||||
Set<String> _continueKeys = const {};
|
||||
|
||||
List<BrowseRoute> get stack => _stack;
|
||||
int get version => _version;
|
||||
/// [continueKey]s of the cards in the Continue row now.
|
||||
Set<String> get continueKeys => _continueKeys;
|
||||
|
||||
JellyfinAccount? get account =>
|
||||
(_serverId == null ? null : accounts.account(_serverId!)) ?? accounts.defaultAccount;
|
||||
String? get serverId => account?.serverId;
|
||||
|
||||
/// First use (accounts loaded): [start], else the server of [serverHint]
|
||||
/// at its remembered location, else the default server's.
|
||||
void start({BrowseStart? start, String? serverHint}) {
|
||||
if (_started) return;
|
||||
_started = true;
|
||||
if (start != null && accounts.account(start.serverId) != null) {
|
||||
_serverId = start.serverId;
|
||||
_stack = start.stack.isEmpty ? const [HomeRoute()] : start.stack;
|
||||
_remember();
|
||||
} else {
|
||||
_serverId = serverHint != null && accounts.account(serverHint) != null
|
||||
? serverHint
|
||||
: accounts.defaultServerId;
|
||||
_stack = _restored(_serverId);
|
||||
}
|
||||
}
|
||||
|
||||
List<BrowseRoute> _restored(String? serverId) =>
|
||||
(serverId == null ? null : decodeBrowseStack(accounts.browseLocation(serverId))) ??
|
||||
const [HomeRoute()];
|
||||
|
||||
void _remember() {
|
||||
final id = serverId;
|
||||
if (id != null) unawaited(accounts.saveBrowseLocation(id, encodeBrowseStack(_stack)));
|
||||
}
|
||||
|
||||
void switchServer(String serverId) {
|
||||
if (serverId == this.serverId) return;
|
||||
_serverId = serverId;
|
||||
_stack = _restored(serverId);
|
||||
_continueKeys = const {};
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void open(BrowseRoute route) {
|
||||
if (_stack.last.key == route.key) return;
|
||||
_stack = [..._stack, route];
|
||||
_remember();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Home, then [route] (library chips: a library is a top-level place).
|
||||
void openTop(BrowseRoute route) {
|
||||
_stack = [const HomeRoute(), route];
|
||||
_remember();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool back() {
|
||||
if (_stack.length <= 1) return false;
|
||||
_stack = _stack.sublist(0, _stack.length - 1);
|
||||
_remember();
|
||||
notifyListeners();
|
||||
return true;
|
||||
}
|
||||
|
||||
void popTo(int index) {
|
||||
_stack = _stack.sublist(0, index + 1);
|
||||
_remember();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Watched state changed on the server: drop its cached lists and let
|
||||
/// the rows reload.
|
||||
void dataChanged() {
|
||||
final id = serverId;
|
||||
if (id != null) accounts.invalidate(id);
|
||||
_version++;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
set continueKeys(Set<String> keys) {
|
||||
if (setEquals(keys, _continueKeys)) return;
|
||||
_continueKeys = keys;
|
||||
// Set while building a row: tell listeners after the frame.
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!_disposed) notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
bool _disposed = false;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
unawaited(_watchedSub.cancel());
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// An item's title to copy: an episode with its series ("Show · Name").
|
||||
String jellyfinCopyTitle(JellyfinItem item) {
|
||||
final series = item.seriesName;
|
||||
return item.kind == JellyfinItemKind.episode && series != null && series.isNotEmpty
|
||||
? '$series · ${item.name}'
|
||||
: item.name;
|
||||
}
|
||||
|
||||
/// What every browser page needs, provided by [JellyfinBrowser].
|
||||
class BrowseScope extends InheritedWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final JellyfinAccount account;
|
||||
final JellyfinClient client;
|
||||
final BrowseController controller;
|
||||
/// Item id of the selected card on this server, highlighted everywhere.
|
||||
final String? selectedItemId;
|
||||
/// Click: select (details panel).
|
||||
final ValueChanged<JellyfinItem> onSelect;
|
||||
/// Double-click: put it up (a series: its next episode).
|
||||
final ValueChanged<JellyfinItem> onPutUp;
|
||||
/// Adds it to Up next (with next: right after what plays); null: no
|
||||
/// server (the cards' menu then only copies and opens).
|
||||
final void Function(JellyfinItem item, {bool next})? onAddToQueue;
|
||||
/// Home shows the library chips itself (the Library tab has them in its
|
||||
/// header instead).
|
||||
final bool libraryStrip;
|
||||
|
||||
const BrowseScope({
|
||||
super.key,
|
||||
required this.accounts,
|
||||
required this.account,
|
||||
required this.client,
|
||||
required this.controller,
|
||||
required this.selectedItemId,
|
||||
required this.onSelect,
|
||||
required this.onPutUp,
|
||||
this.onAddToQueue,
|
||||
this.libraryStrip = true,
|
||||
required super.child,
|
||||
});
|
||||
|
||||
static BrowseScope of(BuildContext context) =>
|
||||
context.dependOnInheritedWidgetOfExactType<BrowseScope>()!;
|
||||
|
||||
void onOpen(BrowseRoute route) => controller.open(route);
|
||||
|
||||
/// Right-click on a card ([context]: the card): Put it up, Add to queue,
|
||||
/// Play next (playable, in a server), Copy title, Open in Jellyfin.
|
||||
Future<void> cardMenu(BuildContext context, JellyfinItem item) async {
|
||||
final queue = isSelectable(item) ? onAddToQueue : null;
|
||||
final pick = await showAppMenu<int>(context, items: [
|
||||
if (queue != null) ...const [
|
||||
AppMenuItem(value: 0, label: 'Put it up'),
|
||||
AppMenuItem(value: 1, label: 'Add to queue'),
|
||||
AppMenuItem(value: 2, label: 'Play next'),
|
||||
],
|
||||
const AppMenuItem(value: 3, label: ReuseText.copyTitle),
|
||||
const AppMenuItem(value: 4, label: ReuseText.openInJellyfin),
|
||||
]);
|
||||
switch (pick) {
|
||||
case 0:
|
||||
onPutUp(item);
|
||||
case 1:
|
||||
queue!(item);
|
||||
case 2:
|
||||
queue!(item, next: true);
|
||||
case 3:
|
||||
if (context.mounted) await copyToClipboard(context, jellyfinCopyTitle(item), done: 'Title copied');
|
||||
case 4:
|
||||
if (context.mounted) await openLink(context, jellyfinWebUrl(client.baseUrl, item.id, serverId: account.serverId));
|
||||
}
|
||||
}
|
||||
|
||||
/// Cached browse call on this server.
|
||||
Future<T> load<T>(String key, Future<T> Function(JellyfinClient c) fn) =>
|
||||
accounts.cached(account.serverId, key, () => fn(client));
|
||||
|
||||
/// Click / Enter on a card: series, movies and episodes are selected,
|
||||
/// seasons open their series, libraries and folders open.
|
||||
void activate(JellyfinItem item) {
|
||||
if (isSelectable(item)) {
|
||||
onSelect(item);
|
||||
return;
|
||||
}
|
||||
switch (item.kind) {
|
||||
case JellyfinItemKind.season:
|
||||
final sid = item.seriesId;
|
||||
if (sid != null) {
|
||||
onOpen(SeriesRoute(
|
||||
JellyfinItem(id: sid, name: item.seriesName ?? item.name, type: 'Series'),
|
||||
seasonId: item.id));
|
||||
}
|
||||
default:
|
||||
onOpen(LibraryRoute(item));
|
||||
}
|
||||
}
|
||||
|
||||
/// Opens the series of an episode.
|
||||
void openSeriesOf(JellyfinItem episode) {
|
||||
final sid = episode.seriesId;
|
||||
if (sid == null) return;
|
||||
onOpen(SeriesRoute(
|
||||
JellyfinItem(id: sid, name: episode.seriesName ?? '', type: 'Series'),
|
||||
seasonId: episode.seasonId));
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(BrowseScope old) =>
|
||||
old.selectedItemId != selectedItemId ||
|
||||
old.account != account ||
|
||||
old.client != client ||
|
||||
old.libraryStrip != libraryStrip;
|
||||
}
|
||||
|
||||
/// Runs [load] once (again on [retry] and when [version] changes) and
|
||||
/// shows [builder] with the result, a spinner meanwhile, and a compact
|
||||
/// error with Retry on failure. A reload for a new [version] keeps the old
|
||||
/// result on screen until the new one arrives.
|
||||
class Loader<T> extends StatefulWidget {
|
||||
final Future<T> Function() load;
|
||||
final Widget Function(BuildContext context, T data) builder;
|
||||
final Widget? loading;
|
||||
/// When false the error collapses to nothing (optional sections).
|
||||
final bool showError;
|
||||
final Object? version;
|
||||
const Loader({
|
||||
super.key,
|
||||
required this.load,
|
||||
required this.builder,
|
||||
this.loading,
|
||||
this.showError = true,
|
||||
this.version,
|
||||
});
|
||||
|
||||
@override
|
||||
State<Loader<T>> createState() => _LoaderState<T>();
|
||||
}
|
||||
|
||||
class _LoaderState<T> extends State<Loader<T>> {
|
||||
late Future<T> _future = widget.load();
|
||||
(T,)? _last;
|
||||
|
||||
void _retry() => setState(() => _future = widget.load());
|
||||
|
||||
@override
|
||||
void didUpdateWidget(Loader<T> old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (old.version != widget.version) _future = widget.load();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<T>(
|
||||
future: _future,
|
||||
builder: (context, snap) {
|
||||
if (snap.hasData || (snap.connectionState == ConnectionState.done && !snap.hasError)) {
|
||||
_last = (snap.data as T,);
|
||||
return widget.builder(context, snap.data as T);
|
||||
}
|
||||
if (snap.hasError) {
|
||||
if (!widget.showError) return const SizedBox.shrink();
|
||||
return LoadError(error: snap.error!, onRetry: _retry);
|
||||
}
|
||||
final last = _last;
|
||||
if (last != null) return widget.builder(context, last.$1);
|
||||
return widget.loading ??
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(32),
|
||||
child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LoadError extends StatelessWidget {
|
||||
final Object error;
|
||||
final VoidCallback onRetry;
|
||||
const LoadError({super.key, required this.error, required this.onRetry});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final e = error;
|
||||
final msg = e is JellyfinException
|
||||
? (e.isUnauthorized ? 'Sign-in expired' : e.message)
|
||||
: '$e';
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.cloud_off, size: 18, color: Theme.of(context).colorScheme.error),
|
||||
const SizedBox(width: 8),
|
||||
Flexible(
|
||||
child: Text(msg.length > 160 ? '${msg.substring(0, 160)}…' : msg,
|
||||
style: const TextStyle(color: Colors.grey)),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
TextButton(onPressed: onRetry, child: const Text('Retry')),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'accounts.dart';
|
||||
import 'browse_scope.dart';
|
||||
import 'home_page.dart';
|
||||
import 'library_page.dart';
|
||||
import 'search_results.dart';
|
||||
import 'series_page.dart';
|
||||
import 'sign_in_panel.dart';
|
||||
|
||||
/// Library browser for the linked Jellyfin servers: server switcher,
|
||||
/// breadcrumbs, search, and a back stack of pages (Home rows, library
|
||||
/// grids, series). Pages below the top stay alive, so going back keeps
|
||||
/// scroll position and loaded pages. Where it is lives in a
|
||||
/// [BrowseController] (shared with the Library header's library chips and
|
||||
/// the details panel; one of its own when none is given).
|
||||
///
|
||||
/// A click on a card selects it ([onSelect]; libraries and folders open),
|
||||
/// a double-click puts it up ([onPutUp]).
|
||||
///
|
||||
/// Keyboard: arrows move between cards, Enter selects / opens, Esc /
|
||||
/// Backspace / Alt+Left go back, / or Ctrl+F searches.
|
||||
class JellyfinBrowser extends StatefulWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final BrowseController? controller;
|
||||
/// Highlighted card.
|
||||
final JellyfinSelection? selected;
|
||||
final ValueChanged<JellyfinSelection> onSelect;
|
||||
final ValueChanged<JellyfinSelection> onPutUp;
|
||||
/// Right-click on a card: Add to queue / Play next; null: no server.
|
||||
final void Function(JellyfinSelection item, {bool next})? onAddToQueue;
|
||||
final VoidCallback? onOpenIntegrations;
|
||||
final Duration searchDebounce;
|
||||
/// Opens here instead of the remembered location (the series of the
|
||||
/// episode playing, after "Change video").
|
||||
final BrowseStart? start;
|
||||
/// Library chips on Home (off when the Library header shows them).
|
||||
final bool libraryStrip;
|
||||
const JellyfinBrowser({
|
||||
this.start,
|
||||
super.key,
|
||||
required this.accounts,
|
||||
required this.onSelect,
|
||||
required this.onPutUp,
|
||||
this.onAddToQueue,
|
||||
this.controller,
|
||||
this.selected,
|
||||
this.onOpenIntegrations,
|
||||
this.libraryStrip = true,
|
||||
this.searchDebounce = const Duration(milliseconds: 300),
|
||||
});
|
||||
|
||||
@override
|
||||
State<JellyfinBrowser> createState() => _JellyfinBrowserState();
|
||||
}
|
||||
|
||||
class _JellyfinBrowserState extends State<JellyfinBrowser> {
|
||||
BrowseController? _own;
|
||||
final _search = TextEditingController();
|
||||
final _searchFocus = FocusNode(debugLabel: 'jf-search');
|
||||
final _body = FocusScopeNode(debugLabel: 'jf-body');
|
||||
String _term = '';
|
||||
Timer? _debounce;
|
||||
int _refresh = 0;
|
||||
|
||||
JellyfinAccounts get _accounts => widget.accounts;
|
||||
BrowseController get _c => widget.controller ?? (_own ??= BrowseController(widget.accounts));
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_c.start(start: widget.start, serverHint: widget.selected?.serverId);
|
||||
_accounts.addListener(_changed);
|
||||
_c.addListener(_moved);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(JellyfinBrowser old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (old.accounts != widget.accounts) {
|
||||
old.accounts.removeListener(_changed);
|
||||
widget.accounts.addListener(_changed);
|
||||
}
|
||||
final was = old.controller ?? _own;
|
||||
if (was != _c) {
|
||||
was?.removeListener(_moved);
|
||||
_c.addListener(_moved);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_accounts.removeListener(_changed);
|
||||
_c.removeListener(_moved);
|
||||
_own?.dispose();
|
||||
_debounce?.cancel();
|
||||
_search.dispose();
|
||||
_searchFocus.dispose();
|
||||
_body.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _changed() {
|
||||
if (mounted) setState(() {});
|
||||
}
|
||||
|
||||
/// Any move (here, from the library chips or a server switch) ends a
|
||||
/// search.
|
||||
int _depth = 0;
|
||||
String? _server;
|
||||
void _moved() {
|
||||
if (!mounted) return;
|
||||
final moved = _c.stack.length != _depth || _c.serverId != _server;
|
||||
_depth = _c.stack.length;
|
||||
_server = _c.serverId;
|
||||
setState(() {
|
||||
if (moved) _clearSearch();
|
||||
});
|
||||
}
|
||||
|
||||
JellyfinAccount? get _account => _c.account;
|
||||
|
||||
// ------------------------------------------------------------- navigation
|
||||
|
||||
bool _back() {
|
||||
final ok = _c.back();
|
||||
if (ok) _body.requestFocus();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void _popTo(int index) {
|
||||
setState(_clearSearch);
|
||||
_c.popTo(index);
|
||||
_body.requestFocus();
|
||||
}
|
||||
|
||||
void _onSearchChanged(String text) {
|
||||
_debounce?.cancel();
|
||||
_debounce = Timer(widget.searchDebounce, () {
|
||||
if (mounted) setState(() => _term = text.trim());
|
||||
});
|
||||
}
|
||||
|
||||
void _clearSearch() {
|
||||
_debounce?.cancel();
|
||||
_search.clear();
|
||||
_term = '';
|
||||
}
|
||||
|
||||
KeyEventResult _onKey(FocusNode node, KeyEvent e) {
|
||||
if (e is! KeyDownEvent && e is! KeyRepeatEvent) return KeyEventResult.ignored;
|
||||
final keys = HardwareKeyboard.instance;
|
||||
final inField = FocusManager.instance.primaryFocus?.context
|
||||
?.findAncestorStateOfType<EditableTextState>() !=
|
||||
null;
|
||||
final k = e.logicalKey;
|
||||
if (k == LogicalKeyboardKey.escape) {
|
||||
if (_search.text.isNotEmpty || _term.isNotEmpty) {
|
||||
setState(_clearSearch);
|
||||
_body.requestFocus();
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
if (inField) {
|
||||
_body.requestFocus();
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
return _back() ? KeyEventResult.handled : KeyEventResult.ignored;
|
||||
}
|
||||
if (inField) return KeyEventResult.ignored;
|
||||
if (e.character == '/' || (keys.isControlPressed && k == LogicalKeyboardKey.keyF)) {
|
||||
_searchFocus.requestFocus();
|
||||
return KeyEventResult.handled;
|
||||
}
|
||||
if (k == LogicalKeyboardKey.backspace ||
|
||||
(keys.isAltPressed && k == LogicalKeyboardKey.arrowLeft) ||
|
||||
k == LogicalKeyboardKey.browserBack) {
|
||||
return _back() ? KeyEventResult.handled : KeyEventResult.ignored;
|
||||
}
|
||||
return KeyEventResult.ignored;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ build
|
||||
|
||||
Widget _page(BrowseRoute r) => switch (r) {
|
||||
HomeRoute() => const JellyfinHomePage(),
|
||||
LibraryRoute(:final folder, :final sort) => JellyfinLibraryPage(folder: folder, sort: sort),
|
||||
SeriesRoute(:final series, :final seasonId) =>
|
||||
JellyfinSeriesPage(series: series, seasonId: seasonId),
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final account = _account;
|
||||
if (account == null) {
|
||||
return const Center(child: Text('No Jellyfin server linked', style: TextStyle(color: Colors.grey)));
|
||||
}
|
||||
final client = _accounts.clientFor(account.serverId)!;
|
||||
final status = _accounts.statusOf(account.serverId);
|
||||
final sel = widget.selected;
|
||||
final searching = _term.isNotEmpty;
|
||||
final stack = _c.stack;
|
||||
|
||||
final pages = Stack(
|
||||
children: [
|
||||
for (var i = 0; i < stack.length; i++)
|
||||
Visibility(
|
||||
key: ValueKey('$_refresh:${account.serverId}:$i:${stack[i].key}'),
|
||||
visible: !searching && i == stack.length - 1,
|
||||
maintainState: true,
|
||||
child: _page(stack[i]),
|
||||
),
|
||||
if (searching) JellyfinSearchResults(key: ValueKey('$_refresh:$_term'), term: _term),
|
||||
],
|
||||
);
|
||||
|
||||
return BrowseScope(
|
||||
accounts: _accounts,
|
||||
account: account,
|
||||
client: client,
|
||||
controller: _c,
|
||||
selectedItemId: sel != null && sel.serverId == account.serverId ? sel.itemId : null,
|
||||
onSelect: (item) => widget.onSelect(JellyfinSelection(account.serverId, item.id, item)),
|
||||
onPutUp: (item) => widget.onPutUp(JellyfinSelection(account.serverId, item.id, item)),
|
||||
onAddToQueue: widget.onAddToQueue == null
|
||||
? null
|
||||
: (item, {next = false}) =>
|
||||
widget.onAddToQueue!(JellyfinSelection(account.serverId, item.id, item), next: next),
|
||||
libraryStrip: widget.libraryStrip,
|
||||
child: Focus(
|
||||
onKeyEvent: _onKey,
|
||||
child: Column(
|
||||
key: const ValueKey('jf-browser'),
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_header(context, account),
|
||||
if (status == JellyfinAccountStatus.expired || status == JellyfinAccountStatus.offline)
|
||||
_StatusBanner(accounts: _accounts, account: account, status: status),
|
||||
const SizedBox(height: 12),
|
||||
Expanded(child: FocusScope(node: _body, child: pages)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _header(BuildContext context, JellyfinAccount account) {
|
||||
final theme = Theme.of(context);
|
||||
final t = theme.textTheme;
|
||||
final stack = _c.stack;
|
||||
final crumbs = <Widget>[];
|
||||
for (var i = 0; i < stack.length; i++) {
|
||||
final last = i == stack.length - 1 && _term.isEmpty;
|
||||
if (i > 0) {
|
||||
crumbs.add(const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 2),
|
||||
child: Icon(Icons.chevron_right, size: 18, color: Colors.grey),
|
||||
));
|
||||
}
|
||||
final label = Text(
|
||||
stack[i].label,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.titleSmall?.copyWith(
|
||||
color: last ? theme.colorScheme.onSurface : theme.colorScheme.onSurfaceVariant,
|
||||
fontWeight: last ? FontWeight.w600 : null),
|
||||
);
|
||||
crumbs.add(Flexible(
|
||||
child: last
|
||||
? label
|
||||
: InkWell(
|
||||
key: ValueKey('crumb-$i'),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
onTap: () => _popTo(i),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4), child: label),
|
||||
),
|
||||
));
|
||||
}
|
||||
if (_term.isNotEmpty) {
|
||||
crumbs
|
||||
..add(const Icon(Icons.chevron_right, size: 18, color: Colors.grey))
|
||||
..add(Flexible(
|
||||
child: Text('Search “$_term”',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.titleSmall?.copyWith(fontWeight: FontWeight.w600))));
|
||||
}
|
||||
|
||||
return LayoutBuilder(builder: (context, box) {
|
||||
final narrow = box.maxWidth < 640;
|
||||
return Row(
|
||||
children: [
|
||||
_ServerSwitcher(
|
||||
accounts: _accounts,
|
||||
current: account,
|
||||
compact: narrow,
|
||||
onSelect: _c.switchServer,
|
||||
onOpenIntegrations: widget.onOpenIntegrations,
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Back (Esc)',
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: stack.length > 1 ? _back : null,
|
||||
icon: const Icon(Icons.arrow_back, size: 20),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Expanded(child: Row(children: crumbs)),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(
|
||||
width: narrow ? 170 : 260,
|
||||
child: TextField(
|
||||
key: const ValueKey('jf-search'),
|
||||
controller: _search,
|
||||
focusNode: _searchFocus,
|
||||
onChanged: _onSearchChanged,
|
||||
onSubmitted: (v) {
|
||||
_debounce?.cancel();
|
||||
setState(() => _term = v.trim());
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
hintText: 'Search ( / )',
|
||||
prefixIcon: const Icon(Icons.search, size: 18),
|
||||
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
|
||||
suffixIcon: ListenableBuilder(
|
||||
listenable: _search,
|
||||
builder: (context, _) => _search.text.isEmpty
|
||||
? const SizedBox.shrink()
|
||||
: IconButton(
|
||||
tooltip: 'Clear (Esc)',
|
||||
iconSize: 16,
|
||||
onPressed: () => setState(_clearSearch),
|
||||
icon: const Icon(Icons.close),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Refresh',
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () {
|
||||
_accounts.invalidate(account.serverId);
|
||||
setState(() => _refresh++);
|
||||
},
|
||||
icon: const Icon(Icons.refresh, size: 20),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Current server (avatar + name); a menu when several are linked.
|
||||
class _ServerSwitcher extends StatelessWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final JellyfinAccount current;
|
||||
final ValueChanged<String> onSelect;
|
||||
final VoidCallback? onOpenIntegrations;
|
||||
/// Narrow: the name is shorter.
|
||||
final bool compact;
|
||||
const _ServerSwitcher({
|
||||
required this.accounts,
|
||||
required this.current,
|
||||
required this.onSelect,
|
||||
this.onOpenIntegrations,
|
||||
this.compact = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
final chip = Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
StatusDot(status: accounts.statusOf(current.serverId)),
|
||||
const SizedBox(width: 8),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: compact ? 110 : 200),
|
||||
child: Text(current.displayName,
|
||||
maxLines: 1, overflow: TextOverflow.ellipsis, style: t.titleSmall),
|
||||
),
|
||||
],
|
||||
);
|
||||
if (accounts.accounts.length < 2 && onOpenIntegrations == null) {
|
||||
return Padding(padding: const EdgeInsets.symmetric(horizontal: 8), child: chip);
|
||||
}
|
||||
return MenuAnchor(
|
||||
menuChildren: [
|
||||
for (final a in accounts.accounts)
|
||||
MenuItemButton(
|
||||
key: ValueKey('server-${a.serverId}'),
|
||||
leadingIcon: StatusDot(status: accounts.statusOf(a.serverId)),
|
||||
trailingIcon: a.serverId == current.serverId ? const Icon(Icons.check, size: 18) : null,
|
||||
onPressed: () => onSelect(a.serverId),
|
||||
child: Text('${a.displayName} · ${a.userName}'),
|
||||
),
|
||||
if (onOpenIntegrations != null)
|
||||
MenuItemButton(
|
||||
leadingIcon: const Icon(Icons.add, size: 18),
|
||||
onPressed: onOpenIntegrations,
|
||||
child: const Text('Manage servers…'),
|
||||
),
|
||||
],
|
||||
builder: (context, menu, _) => TextButton(
|
||||
key: const ValueKey('jf-server-switch'),
|
||||
onPressed: () => menu.isOpen ? menu.close() : menu.open(),
|
||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
chip,
|
||||
const Icon(Icons.arrow_drop_down, size: 20),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StatusDot extends StatelessWidget {
|
||||
final JellyfinAccountStatus status;
|
||||
const StatusDot({super.key, required this.status});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = switch (status) {
|
||||
JellyfinAccountStatus.online => Colors.green,
|
||||
JellyfinAccountStatus.offline => Colors.orange,
|
||||
JellyfinAccountStatus.expired => Theme.of(context).colorScheme.error,
|
||||
_ => Colors.grey,
|
||||
};
|
||||
return Container(
|
||||
width: 8, height: 8, decoration: BoxDecoration(color: color, shape: BoxShape.circle));
|
||||
}
|
||||
}
|
||||
|
||||
class _StatusBanner extends StatelessWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final JellyfinAccount account;
|
||||
final JellyfinAccountStatus status;
|
||||
const _StatusBanner({required this.accounts, required this.account, required this.status});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final expired = status == JellyfinAccountStatus.expired;
|
||||
return Container(
|
||||
key: const ValueKey('jf-status-banner'),
|
||||
margin: const EdgeInsets.only(top: 8),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: (expired ? scheme.errorContainer : Colors.orange.shade900).withValues(alpha: 0.35),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(expired ? Icons.lock_clock : Icons.cloud_off, size: 18),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(expired
|
||||
? 'Sign-in to ${account.displayName} expired. Reconnect to keep browsing.'
|
||||
: "Can't reach ${account.displayName}: ${accounts.errorOf(account.serverId) ?? 'offline'}"),
|
||||
),
|
||||
if (expired)
|
||||
FilledButton.tonal(
|
||||
onPressed: () => showReconnectDialog(context, accounts, account),
|
||||
child: const Text('Reconnect'),
|
||||
)
|
||||
else
|
||||
TextButton(
|
||||
onPressed: () => accounts.validate(account.serverId),
|
||||
child: const Text('Retry'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign in again to an expired account (same server, new token).
|
||||
Future<void> showReconnectDialog(
|
||||
BuildContext context, JellyfinAccounts accounts, JellyfinAccount account) {
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => Dialog(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 520),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: JellyfinSignInPanel(
|
||||
accounts: accounts,
|
||||
reconnect: account,
|
||||
onDone: (_) => Navigator.of(context).pop(),
|
||||
onCancel: () => Navigator.of(context).pop(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Small helper for other screens: the user's avatar on a linked server.
|
||||
class JellyfinAvatar extends StatelessWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final JellyfinAccount account;
|
||||
final double radius;
|
||||
const JellyfinAvatar({super.key, required this.accounts, required this.account, this.radius = 18});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final initials = account.userName.isEmpty ? '?' : account.userName.characters.first.toUpperCase();
|
||||
final fallback = CircleAvatar(
|
||||
radius: radius,
|
||||
backgroundColor: scheme.primaryContainer,
|
||||
child: Text(initials, style: TextStyle(color: scheme.onPrimaryContainer)),
|
||||
);
|
||||
final client = accounts.clientFor(account.serverId);
|
||||
final url = client?.userImageUrl(account.user, maxWidth: (radius * 4).round());
|
||||
if (url == null) return fallback;
|
||||
return ClipOval(
|
||||
child: SizedBox(
|
||||
width: radius * 2,
|
||||
height: radius * 2,
|
||||
child: Image.network(url.toString(),
|
||||
fit: BoxFit.cover,
|
||||
cacheWidth: (radius * 4).round(),
|
||||
errorBuilder: (_, _, _) => fallback),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'browse_scope.dart';
|
||||
import 'format.dart';
|
||||
import 'images.dart';
|
||||
import '../shell/motion.dart' show HScroll;
|
||||
|
||||
enum CardShape {
|
||||
/// 2:3 poster (movies, series, latest).
|
||||
poster(2 / 3, 150),
|
||||
/// 16:9 thumbnail (continue watching, next up, episodes).
|
||||
thumb(16 / 9, 260);
|
||||
|
||||
/// Image width / height.
|
||||
final double aspect;
|
||||
/// Smallest card width; rows and grids add columns past it.
|
||||
final double minWidth;
|
||||
const CardShape(this.aspect, this.minWidth);
|
||||
}
|
||||
|
||||
/// Title + subtitle lines under a card image.
|
||||
const cardTextHeight = 46.0;
|
||||
const cardGap = 12.0;
|
||||
|
||||
/// Card image for [item] in [shape]: thumbs prefer the item's own
|
||||
/// screenshot / thumb / backdrop, posters the primary (series poster for
|
||||
/// episodes).
|
||||
JellyfinImageRef? cardImage(JellyfinItem item, CardShape shape) {
|
||||
if (shape == CardShape.poster) return item.image(JellyfinImageType.primary);
|
||||
final own = item.ownImage(JellyfinImageType.primary);
|
||||
final primaryIsWide = (item.primaryImageAspectRatio ?? 0) > 1.2 ||
|
||||
item.kind == JellyfinItemKind.episode ||
|
||||
item.kind == JellyfinItemKind.video;
|
||||
if (own != null && primaryIsWide) return own;
|
||||
return item.image(JellyfinImageType.thumb) ??
|
||||
item.image(JellyfinImageType.backdrop) ??
|
||||
item.image(JellyfinImageType.primary);
|
||||
}
|
||||
|
||||
IconData kindIcon(JellyfinItem item) => switch (item.kind) {
|
||||
JellyfinItemKind.series || JellyfinItemKind.season => Icons.live_tv_outlined,
|
||||
JellyfinItemKind.episode => Icons.tv_outlined,
|
||||
JellyfinItemKind.folder || JellyfinItemKind.collectionFolder => Icons.folder_outlined,
|
||||
JellyfinItemKind.boxSet => Icons.collections_bookmark_outlined,
|
||||
_ => Icons.movie_outlined,
|
||||
};
|
||||
|
||||
/// Two clicks on the same card within this time put it up.
|
||||
const doubleClickTime = Duration(milliseconds: 350);
|
||||
|
||||
/// Poster or thumb card: image with progress bar and state badges, title
|
||||
/// and one meta line. Click / Enter selects it (details panel; libraries
|
||||
/// and folders open), a second click soon after puts it up. [display]
|
||||
/// gives the picture and title when they are not [item]'s own (a series
|
||||
/// card for a new episode), [subtitle] replaces the meta line.
|
||||
class MediaCard extends StatefulWidget {
|
||||
final JellyfinItem item;
|
||||
final JellyfinItem? display;
|
||||
final String? subtitle;
|
||||
final CardShape shape;
|
||||
/// Rows mixing series (Continue): series name on top, "S2E3 · 12 min
|
||||
/// left" below.
|
||||
final bool seriesFirst;
|
||||
final bool autofocus;
|
||||
const MediaCard({
|
||||
super.key,
|
||||
required this.item,
|
||||
required this.shape,
|
||||
this.display,
|
||||
this.subtitle,
|
||||
this.seriesFirst = false,
|
||||
this.autofocus = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MediaCard> createState() => _MediaCardState();
|
||||
}
|
||||
|
||||
class _MediaCardState extends State<MediaCard> {
|
||||
bool _hover = false;
|
||||
bool _focus = false;
|
||||
DateTime? _lastTap;
|
||||
|
||||
JellyfinItem get item => widget.item;
|
||||
|
||||
void _tap(BrowseScope scope) {
|
||||
final now = DateTime.now();
|
||||
final last = _lastTap;
|
||||
_lastTap = now;
|
||||
if (last != null && now.difference(last) < doubleClickTime && isSelectable(item)) {
|
||||
_lastTap = null;
|
||||
scope.onPutUp(item);
|
||||
return;
|
||||
}
|
||||
scope.activate(item);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
final theme = Theme.of(context);
|
||||
final scheme = theme.colorScheme;
|
||||
final shown = widget.display ?? item;
|
||||
final selected = scope.selectedItemId == item.id;
|
||||
final played = item.userData.played;
|
||||
final progress = progressOf(item);
|
||||
final unplayed = shown.userData.unplayedItemCount;
|
||||
final ring = selected
|
||||
? scheme.primary
|
||||
: _focus
|
||||
? scheme.onSurface
|
||||
: Colors.transparent;
|
||||
|
||||
final image = AspectRatio(
|
||||
aspectRatio: widget.shape.aspect,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 160),
|
||||
curve: Curves.fastEaseInToSlowEaseOut,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: ring, width: 3),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
JellyfinImage(
|
||||
client: scope.client,
|
||||
image: cardImage(shown, widget.shape),
|
||||
icon: kindIcon(shown),
|
||||
),
|
||||
if (_hover || _focus)
|
||||
const ColoredBox(color: Color(0x22FFFFFF)),
|
||||
if (progress > 0)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: LinearProgressIndicator(
|
||||
value: progress,
|
||||
minHeight: 4,
|
||||
backgroundColor: Colors.black54,
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 6,
|
||||
right: 6,
|
||||
child: selected
|
||||
? _Badge(color: scheme.primary, child: Icon(Icons.check, size: 14, color: scheme.onPrimary))
|
||||
: played
|
||||
? const _Badge(color: Color(0xCC1B5E20), child: Icon(Icons.check, size: 14, color: Colors.white))
|
||||
: unplayed != null && unplayed > 0 && !isPlayable(shown) && widget.subtitle == null
|
||||
? _Badge(
|
||||
color: scheme.primaryContainer,
|
||||
child: Text('$unplayed',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: scheme.onPrimaryContainer)))
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final title = widget.display != null ? shown.name : cardTitle(item, seriesFirst: widget.seriesFirst);
|
||||
final sub = widget.subtitle ??
|
||||
(widget.seriesFirst && item.kind == JellyfinItemKind.episode
|
||||
? [cardSubtitle(item), item.name].where((s) => s.isNotEmpty).join(' · ')
|
||||
: cardSubtitle(item));
|
||||
return Semantics(
|
||||
button: true,
|
||||
selected: selected,
|
||||
label: title,
|
||||
child: InkWell(
|
||||
key: ValueKey('card-${item.id}'),
|
||||
autofocus: widget.autofocus,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
focusColor: Colors.transparent,
|
||||
hoverColor: Colors.transparent,
|
||||
onTap: () => _tap(scope),
|
||||
onSecondaryTap: () => scope.cardMenu(context, item),
|
||||
onHover: (h) => setState(() => _hover = h),
|
||||
onFocusChange: (f) => setState(() => _focus = f),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
image,
|
||||
const SizedBox(height: 6),
|
||||
SizedBox(
|
||||
height: cardTextHeight - 6,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: selected ? scheme.primary : null)),
|
||||
Text(sub,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: theme.textTheme.bodySmall?.copyWith(color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _Badge extends StatelessWidget {
|
||||
final Color color;
|
||||
final Widget child;
|
||||
const _Badge({required this.color, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Container(
|
||||
constraints: const BoxConstraints(minWidth: 22, minHeight: 22),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(11)),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
/// Columns and card width that fill [width] exactly with cards at least
|
||||
/// [minWidth] wide: no half-cut card at the edge, any window width.
|
||||
({int cols, double itemWidth}) fitColumns(double width, double minWidth, {double gap = cardGap}) {
|
||||
final cols = math.max(1, ((width + gap) / (minWidth + gap)).floor());
|
||||
return (cols: cols, itemWidth: (width - gap * (cols - 1)) / cols);
|
||||
}
|
||||
|
||||
/// Grid layout for cards: as many columns as fit, height = image + text.
|
||||
class CardGridDelegate extends SliverGridDelegate {
|
||||
final CardShape shape;
|
||||
final double minWidth;
|
||||
CardGridDelegate(this.shape, {double? minWidth}) : minWidth = minWidth ?? shape.minWidth;
|
||||
|
||||
@override
|
||||
SliverGridLayout getLayout(SliverConstraints constraints) {
|
||||
final fit = fitColumns(constraints.crossAxisExtent, minWidth);
|
||||
final h = fit.itemWidth / shape.aspect + cardTextHeight;
|
||||
return SliverGridRegularTileLayout(
|
||||
crossAxisCount: fit.cols,
|
||||
mainAxisStride: h + 18,
|
||||
crossAxisStride: fit.itemWidth + cardGap,
|
||||
childMainAxisExtent: h,
|
||||
childCrossAxisExtent: fit.itemWidth,
|
||||
reverseCrossAxis: false,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRelayout(CardGridDelegate old) => old.shape != shape || old.minWidth != minWidth;
|
||||
}
|
||||
|
||||
/// One card of a [MediaRow]: see [MediaCard].
|
||||
typedef CardEntry = ({JellyfinItem item, JellyfinItem? display, String? subtitle});
|
||||
|
||||
List<CardEntry> cardEntries(Iterable<JellyfinItem> items) =>
|
||||
[for (final i in items) (item: i, display: null, subtitle: null)];
|
||||
|
||||
/// A titled horizontal row of cards sized to fill the width; mouse drag
|
||||
/// and the wheel move it ([HScroll]), arrows (on hover) page through it.
|
||||
/// Lazy: only visible cards are built.
|
||||
class MediaRow extends StatefulWidget {
|
||||
final String title;
|
||||
final List<CardEntry> entries;
|
||||
final CardShape shape;
|
||||
final bool seriesFirst;
|
||||
final Widget? trailing;
|
||||
const MediaRow({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.entries,
|
||||
required this.shape,
|
||||
this.seriesFirst = false,
|
||||
this.trailing,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MediaRow> createState() => _MediaRowState();
|
||||
}
|
||||
|
||||
class _MediaRowState extends State<MediaRow> {
|
||||
final _scroll = ScrollController();
|
||||
bool _hover = false;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scroll.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _page(int dir, double width) {
|
||||
if (!_scroll.hasClients) return;
|
||||
final p = _scroll.position;
|
||||
final to = (p.pixels + dir * (width + cardGap)).clamp(0.0, p.maxScrollExtent);
|
||||
_scroll.animateTo(to, duration: const Duration(milliseconds: 280), curve: Curves.easeOutCubic);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final entries = widget.entries;
|
||||
return MouseRegion(
|
||||
onEnter: (_) => setState(() => _hover = true),
|
||||
onExit: (_) => setState(() => _hover = false),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SectionHeader(widget.title, count: '${entries.length}', trailing: widget.trailing),
|
||||
LayoutBuilder(builder: (context, box) {
|
||||
final fit = fitColumns(box.maxWidth, widget.shape.minWidth);
|
||||
final h = fit.itemWidth / widget.shape.aspect + cardTextHeight;
|
||||
final overflow = entries.length > fit.cols;
|
||||
return SizedBox(
|
||||
height: h,
|
||||
child: Stack(
|
||||
children: [
|
||||
HScroll(
|
||||
controller: _scroll,
|
||||
builder: (c) => ListView.separated(
|
||||
controller: c,
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: entries.length,
|
||||
separatorBuilder: (_, _) => const SizedBox(width: cardGap),
|
||||
itemBuilder: (context, i) => SizedBox(
|
||||
width: fit.itemWidth,
|
||||
child: MediaCard(
|
||||
item: entries[i].item,
|
||||
display: entries[i].display,
|
||||
subtitle: entries[i].subtitle,
|
||||
shape: widget.shape,
|
||||
seriesFirst: widget.seriesFirst,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (overflow && _hover) ...[
|
||||
_PageArrow(left: true, height: h - cardTextHeight, onTap: () => _page(-1, box.maxWidth)),
|
||||
_PageArrow(left: false, height: h - cardTextHeight, onTap: () => _page(1, box.maxWidth)),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PageArrow extends StatelessWidget {
|
||||
final bool left;
|
||||
final double height;
|
||||
final VoidCallback onTap;
|
||||
const _PageArrow({required this.left, required this.height, required this.onTap});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned(
|
||||
left: left ? 0 : null,
|
||||
right: left ? null : 0,
|
||||
top: 0,
|
||||
height: height,
|
||||
child: Center(
|
||||
child: ExcludeFocus(
|
||||
child: IconButton.filledTonal(
|
||||
tooltip: left ? 'Previous' : 'Next',
|
||||
onPressed: onTap,
|
||||
icon: Icon(left ? Icons.chevron_left : Icons.chevron_right),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Section heading used above grids and rows.
|
||||
class SectionHeader extends StatelessWidget {
|
||||
final String title;
|
||||
final String? count;
|
||||
final Widget? trailing;
|
||||
const SectionHeader(this.title, {super.key, this.count, this.trailing});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8, top: 4),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(title, maxLines: 1, overflow: TextOverflow.ellipsis, style: t.titleMedium),
|
||||
),
|
||||
if (count != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
Text(count!, style: t.bodySmall?.copyWith(color: Colors.grey)),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
?trailing,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,584 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../shell/motion.dart';
|
||||
import '../widgets/app_menu.dart';
|
||||
import '../widgets/copy_open.dart';
|
||||
import 'accounts.dart';
|
||||
import 'browse_scope.dart';
|
||||
import 'cards.dart' show doubleClickTime, kindIcon;
|
||||
import 'format.dart';
|
||||
import 'home_rows.dart' show continueKey;
|
||||
import 'images.dart';
|
||||
|
||||
/// Width of the details panel (docked or floating).
|
||||
const detailsPanelWidth = 400.0;
|
||||
|
||||
/// What putting up [item] plays: itself when playable; for a series its
|
||||
/// next episode (resume point or next up), else its first unwatched, else
|
||||
/// its first episode. Null when there is nothing to play.
|
||||
Future<JellyfinItem?> playableFor(JellyfinClient c, JellyfinItem item) async {
|
||||
if (isPlayable(item)) return item;
|
||||
if (item.kind != JellyfinItemKind.series) return null;
|
||||
final next = await c.nextUp(seriesId: item.id, limit: 1, enableResumable: true);
|
||||
if (next.isNotEmpty) return next.first;
|
||||
final eps = await c.episodes(item.id);
|
||||
return eps.where((e) => !e.userData.played).firstOrNull ?? eps.firstOrNull;
|
||||
}
|
||||
|
||||
typedef _Data = ({
|
||||
JellyfinItem item,
|
||||
JellyfinItem? series,
|
||||
List<JellyfinItem> seasons,
|
||||
JellyfinItem? next,
|
||||
});
|
||||
|
||||
/// The selected card's details, at the right of the library: banner,
|
||||
/// title, meta, "Put it up · S1E3" ("Play · S1E3" when watching
|
||||
/// [alone]), mark watched / unwatched, remove from Continue, overview and,
|
||||
/// for a series or an episode, the episode list (click picks which
|
||||
/// episode goes up, double-click puts it up). Reloads when the
|
||||
/// [controller]'s data version moves.
|
||||
class JellyfinDetailsPanel extends StatefulWidget {
|
||||
final BrowseController controller;
|
||||
final JellyfinSelection selection;
|
||||
/// Nobody else is in the server: the button says Play.
|
||||
final bool alone;
|
||||
/// Puts [item] (playable) up; returns an error text, or null when sent.
|
||||
final Future<String?> Function(JellyfinSelection item) onPutUp;
|
||||
/// Adds [item] to Up next (with next: right after what plays); null: no
|
||||
/// server, no queue actions.
|
||||
final Future<String?> Function(JellyfinSelection item, {bool next})? onAddToQueue;
|
||||
final VoidCallback onClose;
|
||||
const JellyfinDetailsPanel({
|
||||
super.key,
|
||||
required this.controller,
|
||||
required this.selection,
|
||||
required this.onPutUp,
|
||||
this.onAddToQueue,
|
||||
required this.onClose,
|
||||
this.alone = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<JellyfinDetailsPanel> createState() => _JellyfinDetailsPanelState();
|
||||
}
|
||||
|
||||
class _JellyfinDetailsPanelState extends State<JellyfinDetailsPanel> {
|
||||
String? _seasonId;
|
||||
String? _targetId;
|
||||
bool _busy = false;
|
||||
String? _error;
|
||||
DateTime? _lastTap;
|
||||
String? _lastTapId;
|
||||
|
||||
BrowseController get _c => widget.controller;
|
||||
JellyfinAccounts get _accounts => _c.accounts;
|
||||
String get _serverId => widget.selection.serverId;
|
||||
JellyfinClient? get _client => _accounts.clientFor(_serverId);
|
||||
|
||||
Future<T> _cached<T>(String key, Future<T> Function(JellyfinClient c) fn) {
|
||||
final c = _client;
|
||||
if (c == null) return Future.error(const JellyfinException('that Jellyfin server is not linked any more'));
|
||||
return _accounts.cached(_serverId, key, () => fn(c));
|
||||
}
|
||||
|
||||
Future<_Data> _load() async {
|
||||
await _accounts.ensureLoaded();
|
||||
final id = widget.selection.itemId;
|
||||
final item = await _cached('item:$id', (c) => c.item(id));
|
||||
final sid = item.kind == JellyfinItemKind.series ? item.id : item.seriesId;
|
||||
if (sid == null || (item.kind != JellyfinItemKind.series && item.kind != JellyfinItemKind.episode)) {
|
||||
return (item: item, series: null, seasons: const <JellyfinItem>[], next: null);
|
||||
}
|
||||
final r = await Future.wait<Object?>([
|
||||
item.kind == JellyfinItemKind.series ? Future.value(item) : _cached('item:$sid', (c) => c.item(sid)),
|
||||
_cached('seasons:$sid', (c) => c.seasons(sid)),
|
||||
_cached('next:$sid', (c) => c.nextUp(seriesId: sid, limit: 1, enableResumable: true))
|
||||
.then<List<JellyfinItem>?>((v) => v, onError: (_) => null),
|
||||
]);
|
||||
final next = r[2] as List<JellyfinItem>?;
|
||||
return (
|
||||
item: item,
|
||||
series: r[0] as JellyfinItem,
|
||||
seasons: r[1] as List<JellyfinItem>,
|
||||
next: next == null || next.isEmpty ? null : next.first,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<JellyfinItem>> _episodes(String seriesId, String seasonId) =>
|
||||
_cached('episodes:$seriesId:$seasonId', (c) => c.episodes(seriesId, seasonId: seasonId));
|
||||
|
||||
Future<void> _putUp(JellyfinItem target) async {
|
||||
if (_busy) return;
|
||||
setState(() {
|
||||
_busy = true;
|
||||
_error = null;
|
||||
});
|
||||
String? error;
|
||||
try {
|
||||
error = await widget.onPutUp(JellyfinSelection(_serverId, target.id, target));
|
||||
} catch (e) {
|
||||
error = '$e';
|
||||
}
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_busy = false;
|
||||
_error = error;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _queue(JellyfinItem target, {bool next = false}) async {
|
||||
final add = widget.onAddToQueue;
|
||||
if (add == null || _busy) return;
|
||||
setState(() {
|
||||
_busy = true;
|
||||
_error = null;
|
||||
});
|
||||
String? error;
|
||||
try {
|
||||
error = await add(JellyfinSelection(_serverId, target.id, target), next: next);
|
||||
} catch (e) {
|
||||
error = '$e';
|
||||
}
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_busy = false;
|
||||
_error = error;
|
||||
});
|
||||
}
|
||||
|
||||
/// Right-click on an episode ([context]: its row): Put it up, Add to
|
||||
/// queue, Play next (in a server), Copy title, Open in Jellyfin.
|
||||
Future<void> _episodeMenu(BuildContext context, JellyfinItem e) async {
|
||||
final queue = widget.onAddToQueue != null;
|
||||
if (queue) setState(() => _targetId = e.id);
|
||||
final client = _client;
|
||||
final pick = await showAppMenu<int>(context, items: [
|
||||
if (queue) ...[
|
||||
AppMenuItem(value: 0, label: widget.alone ? 'Play' : 'Put it up'),
|
||||
const AppMenuItem(value: 1, label: 'Add to queue'),
|
||||
const AppMenuItem(value: 2, label: 'Play next'),
|
||||
],
|
||||
const AppMenuItem(value: 3, label: ReuseText.copyTitle),
|
||||
if (client != null) const AppMenuItem(value: 4, label: ReuseText.openInJellyfin),
|
||||
]);
|
||||
switch (pick) {
|
||||
case 0:
|
||||
await _putUp(e);
|
||||
case 1:
|
||||
await _queue(e);
|
||||
case 2:
|
||||
await _queue(e, next: true);
|
||||
case 3:
|
||||
if (context.mounted) await copyToClipboard(context, jellyfinCopyTitle(e), done: 'Title copied');
|
||||
case 4:
|
||||
if (context.mounted) await openLink(context, jellyfinWebUrl(client!.baseUrl, e.id, serverId: _serverId));
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs a watched-state change, then lets every row reload.
|
||||
Future<void> _change(Future<void> Function(JellyfinClient c) action) async {
|
||||
final c = _client;
|
||||
if (c == null || _busy) return;
|
||||
setState(() {
|
||||
_busy = true;
|
||||
_error = null;
|
||||
});
|
||||
String? error;
|
||||
try {
|
||||
await action(c);
|
||||
} on JellyfinException catch (e) {
|
||||
if (e.isUnauthorized) _accounts.markExpired(_serverId);
|
||||
error = e.isUnauthorized ? 'Jellyfin sign-in expired' : e.message;
|
||||
} catch (e) {
|
||||
error = '$e';
|
||||
}
|
||||
_c.dataChanged();
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_busy = false;
|
||||
_error = error;
|
||||
});
|
||||
}
|
||||
|
||||
void _toggleWatched(JellyfinItem t) =>
|
||||
_change((c) => t.userData.played ? c.markUnplayed(t.id) : c.markPlayed(t.id));
|
||||
|
||||
void _removeFromContinue(JellyfinItem t) => _change((c) async {
|
||||
if (t.userData.isResumable) await c.clearResumePosition(t.id);
|
||||
await _accounts.dismissContinue(_serverId, continueKey(t));
|
||||
});
|
||||
|
||||
void _tapEpisode(JellyfinItem e) {
|
||||
final now = DateTime.now();
|
||||
final again = _lastTapId == e.id && _lastTap != null && now.difference(_lastTap!) < doubleClickTime;
|
||||
_lastTap = again ? null : now;
|
||||
_lastTapId = e.id;
|
||||
setState(() => _targetId = e.id);
|
||||
if (again) _putUp(e);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
return Material(
|
||||
key: const ValueKey('jf-details'),
|
||||
color: scheme.surfaceContainerLow,
|
||||
child: SizedBox(
|
||||
width: detailsPanelWidth,
|
||||
child: ListenableBuilder(
|
||||
listenable: _c,
|
||||
builder: (context, _) => Loader<_Data>(
|
||||
key: ValueKey('details-${widget.selection.serverId}-${widget.selection.itemId}'),
|
||||
version: _c.version,
|
||||
load: _load,
|
||||
loading: Stack(children: [
|
||||
const Center(child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
Positioned(right: 4, top: 4, child: _closeButton()),
|
||||
]),
|
||||
builder: (context, d) => _body(context, d),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _closeButton() => IconButton(
|
||||
key: const ValueKey('details-close'),
|
||||
tooltip: 'Close',
|
||||
onPressed: widget.onClose,
|
||||
icon: const Icon(Icons.close),
|
||||
);
|
||||
|
||||
Widget _body(BuildContext context, _Data d) {
|
||||
final series = d.series;
|
||||
if (series == null) return _view(context, d, null, null);
|
||||
final preferred = d.item.kind == JellyfinItemKind.episode ? d.item : null;
|
||||
final baseTarget = preferred ?? d.next;
|
||||
final seasons = d.seasons;
|
||||
final seasonId = (_seasonId != null && seasons.any((s) => s.id == _seasonId))
|
||||
? _seasonId
|
||||
: seasons.any((s) => s.id == baseTarget?.seasonId)
|
||||
? baseTarget!.seasonId
|
||||
: (seasons.where((s) => !s.userData.played).firstOrNull ?? seasons.firstOrNull)?.id;
|
||||
if (seasonId == null) return _view(context, d, baseTarget, const []);
|
||||
return Loader<List<JellyfinItem>>(
|
||||
key: ValueKey('details-episodes-$seasonId'),
|
||||
version: _c.version,
|
||||
load: () => _episodes(series.id, seasonId),
|
||||
loading: _view(context, d, baseTarget, null),
|
||||
builder: (context, eps) {
|
||||
final chosen = _targetId == null
|
||||
? null
|
||||
: eps.where((e) => e.id == _targetId).firstOrNull ??
|
||||
(baseTarget?.id == _targetId ? baseTarget : null);
|
||||
final fresh = baseTarget == null ? null : eps.where((e) => e.id == baseTarget.id).firstOrNull;
|
||||
final target = chosen ??
|
||||
fresh ??
|
||||
baseTarget ??
|
||||
eps.where((e) => !e.userData.played).firstOrNull ??
|
||||
eps.firstOrNull;
|
||||
return _view(context, d, target, eps, seasonId: seasonId);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// [episodes] null = loading, empty = none (or not a series).
|
||||
Widget _view(BuildContext context, _Data d, JellyfinItem? target, List<JellyfinItem>? episodes,
|
||||
{String? seasonId}) {
|
||||
final theme = Theme.of(context);
|
||||
final t = theme.textTheme;
|
||||
final scheme = theme.colorScheme;
|
||||
final client = _client;
|
||||
final shown = d.series ?? d.item;
|
||||
final isSeries = d.series != null;
|
||||
final playable = isSeries ? target : (isPlayable(d.item) ? d.item : null);
|
||||
final banner = shown.image(JellyfinImageType.backdrop) ??
|
||||
shown.image(JellyfinImageType.thumb) ??
|
||||
(d.item.kind == JellyfinItemKind.episode ? d.item.ownImage(JellyfinImageType.primary) : null) ??
|
||||
shown.image(JellyfinImageType.primary);
|
||||
final eps = shown.recursiveItemCount;
|
||||
final meta = [
|
||||
if (shown.productionYear != null) '${shown.productionYear}',
|
||||
if (isSeries && d.seasons.length > 1) '${d.seasons.length} seasons',
|
||||
if (isSeries && eps != null && eps > 0) '$eps episodes',
|
||||
if (!isSeries && shown.runTime != null) formatRuntime(shown.runTime!),
|
||||
?shown.officialRating,
|
||||
if (shown.communityRating != null) '★ ${shown.communityRating!.toStringAsFixed(1)}',
|
||||
if (!isSeries && shown.userData.played) 'Watched',
|
||||
].join(' · ');
|
||||
final verb = widget.alone ? 'Play' : 'Put it up';
|
||||
final label = playable != null && isSeries ? '$verb · ${playable.episodeLabel ?? playable.name}' : verb;
|
||||
final inContinue = playable != null &&
|
||||
(playable.userData.isResumable || _c.continueKeys.contains(continueKey(playable)));
|
||||
final left = playable == null ? null : timeLeft(playable);
|
||||
|
||||
return ListView(
|
||||
key: const ValueKey('details-list'),
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 180,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
if (client != null)
|
||||
JellyfinImage(client: client, image: banner, alignment: Alignment.topCenter, icon: kindIcon(shown))
|
||||
else
|
||||
ColoredBox(color: scheme.surfaceContainerHighest),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Colors.transparent, scheme.surfaceContainerLow],
|
||||
stops: const [0.55, 1],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(right: 4, top: 4, child: _closeButton()),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 4, 16, 16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SelectableText(shown.name, style: t.titleLarge),
|
||||
if (meta.isNotEmpty) Text(meta, style: t.bodyMedium?.copyWith(color: Colors.grey)),
|
||||
const SizedBox(height: 12),
|
||||
Wrap(
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
FilledButton.icon(
|
||||
key: const ValueKey('details-put-up'),
|
||||
onPressed: playable == null || _busy ? null : () => _putUp(playable),
|
||||
icon: _busy
|
||||
? const SizedBox.square(dimension: 16, child: CircularProgressIndicator(strokeWidth: 2))
|
||||
: const Icon(Icons.play_arrow),
|
||||
label: Text(label, overflow: TextOverflow.ellipsis),
|
||||
),
|
||||
if (playable != null && widget.onAddToQueue != null)
|
||||
GestureDetector(
|
||||
onSecondaryTap: _busy ? null : () => _queue(playable, next: true),
|
||||
child: IconButton(
|
||||
key: const ValueKey('details-add-queue'),
|
||||
onPressed: _busy ? null : () => _queue(playable),
|
||||
tooltip: 'Add to queue (right-click: play next)',
|
||||
icon: const Icon(Icons.playlist_add_rounded),
|
||||
),
|
||||
),
|
||||
if (playable != null)
|
||||
IconButton(
|
||||
key: const ValueKey('details-watched'),
|
||||
onPressed: _busy ? null : () => _toggleWatched(playable),
|
||||
tooltip: playable.userData.played ? 'Mark unwatched' : 'Mark watched',
|
||||
icon: Icon(playable.userData.played ? Icons.check_circle : Icons.check_circle_outline),
|
||||
),
|
||||
if (inContinue)
|
||||
IconButton(
|
||||
key: const ValueKey('details-remove-continue'),
|
||||
onPressed: _busy ? null : () => _removeFromContinue(playable),
|
||||
tooltip: 'Remove from Continue',
|
||||
icon: const Icon(Icons.remove_circle_outline),
|
||||
),
|
||||
if (isSeries)
|
||||
IconButton(
|
||||
key: const ValueKey('details-open-series'),
|
||||
tooltip: 'Open the series page',
|
||||
onPressed: () => _c.open(SeriesRoute(d.series!, seasonId: seasonId)),
|
||||
icon: const Icon(Icons.open_in_new),
|
||||
),
|
||||
if (client != null)
|
||||
IconButton(
|
||||
key: const ValueKey('details-open-jellyfin'),
|
||||
tooltip: ReuseText.openInJellyfin,
|
||||
onPressed: () => openLink(context, jellyfinWebUrl(client.baseUrl, shown.id, serverId: _serverId)),
|
||||
icon: const Icon(Icons.open_in_browser_rounded),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_error != null) ...[
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
_error!,
|
||||
key: const ValueKey('details-hint'),
|
||||
style: t.bodySmall?.copyWith(color: scheme.error),
|
||||
),
|
||||
],
|
||||
if (isSeries && playable != null) ...[
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
[playable.episodeLabel ?? '', playable.name].where((s) => s.isNotEmpty).join(' · '),
|
||||
style: t.titleSmall,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
if (left != null) ...[
|
||||
const SizedBox(height: 6),
|
||||
Row(children: [
|
||||
SizedBox(width: 160, child: LinearProgressIndicator(value: progressOf(playable!), minHeight: 3)),
|
||||
const SizedBox(width: 8),
|
||||
Text(left, style: t.bodySmall?.copyWith(color: Colors.grey)),
|
||||
]),
|
||||
],
|
||||
if (shown.overview != null) ...[
|
||||
const SizedBox(height: 12),
|
||||
Text(shown.overview!, style: t.bodyMedium),
|
||||
],
|
||||
if (!isSeries) ...[
|
||||
const SizedBox(height: 12),
|
||||
_Tracks(item: d.item),
|
||||
],
|
||||
if (isSeries) ...[
|
||||
const SizedBox(height: 16),
|
||||
_episodesHeader(context, d, seasonId),
|
||||
if (episodes == null)
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
)
|
||||
else if (episodes.isEmpty)
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
child: Text('No episodes', style: TextStyle(color: Colors.grey)),
|
||||
)
|
||||
else
|
||||
for (final e in episodes) _episodeRow(context, e, target?.id == e.id),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _episodesHeader(BuildContext context, _Data d, String? seasonId) {
|
||||
final seasons = d.seasons;
|
||||
return Row(
|
||||
children: [
|
||||
const Expanded(child: Text('Episodes', style: TextStyle(fontWeight: FontWeight.w600))),
|
||||
if (seasons.length > 1)
|
||||
Flexible(
|
||||
child: AppSelect<String?>(
|
||||
key: const ValueKey('details-season'),
|
||||
value: seasonId,
|
||||
items: [for (final s in seasons) (s.id, s.name)],
|
||||
onChanged: (id) => setState(() => _seasonId = id),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _episodeRow(BuildContext context, JellyfinItem e, bool isTarget) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final t = Theme.of(context).textTheme;
|
||||
final client = _client;
|
||||
final sub = e.userData.played ? 'watched' : timeLeft(e) ?? (e.runTime == null ? '' : formatRuntime(e.runTime!));
|
||||
return Material(
|
||||
color: isTarget ? scheme.primary.withValues(alpha: 0.10) : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
// The row's own context: its menu opens at the row.
|
||||
child: Builder(builder: (context) => InkWell(
|
||||
key: ValueKey('details-episode-${e.id}'),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
onTap: () => _tapEpisode(e),
|
||||
onSecondaryTap: () => _episodeMenu(context, e),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 4),
|
||||
child: Row(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: SizedBox(
|
||||
width: 64,
|
||||
height: 36,
|
||||
child: client == null
|
||||
? ColoredBox(color: scheme.surfaceContainerHighest)
|
||||
: JellyfinImage(
|
||||
client: client,
|
||||
image: e.ownImage(JellyfinImageType.primary) ?? e.image(JellyfinImageType.thumb),
|
||||
icon: Icons.tv_outlined,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
e.indexNumber == null ? e.name : 'E${e.indexNumber} · ${e.name}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.bodyMedium?.copyWith(
|
||||
color: isTarget ? scheme.primary : e.userData.played ? Colors.grey : null,
|
||||
fontWeight: isTarget ? FontWeight.w600 : null,
|
||||
),
|
||||
),
|
||||
if (sub.isNotEmpty) Text(sub, style: t.bodySmall?.copyWith(color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
),
|
||||
AnimatedOpacity(
|
||||
opacity: isTarget ? 1 : 0,
|
||||
duration: easeTime,
|
||||
child: Icon(Icons.play_circle, color: scheme.primary),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// What the file holds, one line per track kind.
|
||||
class _Tracks extends StatelessWidget {
|
||||
final JellyfinItem item;
|
||||
const _Tracks({required this.item});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
final source = item.mediaSources.firstOrNull;
|
||||
final streams = source?.mediaStreams.isNotEmpty == true ? source!.mediaStreams : item.mediaStreams;
|
||||
if (streams.isEmpty) return const SizedBox.shrink();
|
||||
String names(JellyfinStreamType type) => streams
|
||||
.where((s) => s.type == type)
|
||||
.map((s) => s.displayTitle ?? [s.language, s.codec].whereType<String>().join(' '))
|
||||
.join(' · ');
|
||||
final rows = [
|
||||
('Video', names(JellyfinStreamType.video)),
|
||||
('Audio', names(JellyfinStreamType.audio)),
|
||||
('Subtitles', names(JellyfinStreamType.subtitle)),
|
||||
if (source?.container != null || source?.size != null)
|
||||
('File', [
|
||||
?source?.container,
|
||||
if (source?.size != null) '${(source!.size! / (1 << 30)).toStringAsFixed(2)} GB',
|
||||
].join(' · ')),
|
||||
].where((r) => r.$2.isNotEmpty);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (final (label, value) in rows)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 6),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(width: 76, child: Text(label, style: t.bodySmall?.copyWith(color: Colors.grey))),
|
||||
Expanded(child: Text(value, style: t.bodySmall)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../library/media_refs.dart';
|
||||
import '../screens/home/picked_media.dart';
|
||||
import 'accounts.dart';
|
||||
|
||||
/// "1 h 42 min", "24 min", "45 s".
|
||||
String formatRuntime(Duration d) {
|
||||
final h = d.inHours, m = d.inMinutes % 60;
|
||||
if (h > 0) return m == 0 ? '$h h' : '$h h $m min';
|
||||
if (d.inMinutes > 0) return '${d.inMinutes} min';
|
||||
return '${d.inSeconds} s';
|
||||
}
|
||||
|
||||
/// Watched share of a resumable item, 0 when there is no resume point.
|
||||
double progressOf(JellyfinItem item) {
|
||||
final run = item.runTimeTicks;
|
||||
final pos = item.userData.playbackPositionTicks;
|
||||
if (run == null || run <= 0 || pos <= 0) return 0;
|
||||
return (pos / run).clamp(0.0, 1.0);
|
||||
}
|
||||
|
||||
/// "12 min left" for a resumable item, else null.
|
||||
String? timeLeft(JellyfinItem item) {
|
||||
final run = item.runTimeTicks;
|
||||
if (run == null || !item.userData.isResumable) return null;
|
||||
final left = ticksToDuration(run - item.userData.playbackPositionTicks);
|
||||
if (left.inMinutes < 1) return 'almost done';
|
||||
return '${formatRuntime(left)} left';
|
||||
}
|
||||
|
||||
bool isPlayable(JellyfinItem item) => switch (item.kind) {
|
||||
JellyfinItemKind.movie || JellyfinItemKind.episode || JellyfinItemKind.video => true,
|
||||
_ => !item.isFolder && item.mediaType == 'Video',
|
||||
};
|
||||
|
||||
/// Cards that select (details panel) on click: playable items and series.
|
||||
bool isSelectable(JellyfinItem item) => isPlayable(item) || item.kind == JellyfinItemKind.series;
|
||||
|
||||
/// Line under a card title: "S2E3 · 12 min left", "2019 · 24 eps", ...
|
||||
String cardSubtitle(JellyfinItem item, {bool withSeries = false}) {
|
||||
final parts = <String>[];
|
||||
switch (item.kind) {
|
||||
case JellyfinItemKind.episode:
|
||||
if (withSeries && item.seriesName != null) parts.add(item.seriesName!);
|
||||
parts.add(item.episodeLabel ?? item.seasonName ?? 'Episode');
|
||||
case JellyfinItemKind.series:
|
||||
if (item.productionYear != null) parts.add('${item.productionYear}');
|
||||
final eps = item.recursiveItemCount, seasons = item.childCount;
|
||||
if (eps != null && eps > 0) {
|
||||
parts.add('$eps eps');
|
||||
} else if (seasons != null && seasons > 0) {
|
||||
parts.add(seasons == 1 ? '1 season' : '$seasons seasons');
|
||||
}
|
||||
case JellyfinItemKind.season:
|
||||
final n = item.childCount ?? item.recursiveItemCount;
|
||||
if (n != null) parts.add('$n eps');
|
||||
default:
|
||||
if (item.productionYear != null) parts.add('${item.productionYear}');
|
||||
}
|
||||
final left = timeLeft(item);
|
||||
if (left != null) {
|
||||
parts.add(left);
|
||||
} else if (isPlayable(item) && item.runTime != null) {
|
||||
parts.add(formatRuntime(item.runTime!));
|
||||
}
|
||||
return parts.join(' · ');
|
||||
}
|
||||
|
||||
/// Title on a card: episodes in rows that mix series show the series name
|
||||
/// on top and the episode below.
|
||||
String cardTitle(JellyfinItem item, {bool seriesFirst = false}) =>
|
||||
seriesFirst && item.kind == JellyfinItemKind.episode && item.seriesName != null
|
||||
? item.seriesName!
|
||||
: item.name;
|
||||
|
||||
/// The selection for a playable [item] of [account].
|
||||
JellyfinMedia pickFor(JellyfinAccount account, JellyfinItem item) {
|
||||
final String subtitle;
|
||||
if (item.kind == JellyfinItemKind.episode) {
|
||||
subtitle = [?item.seriesName, ?item.episodeLabel].join(' · ');
|
||||
} else {
|
||||
subtitle = item.productionYear?.toString() ?? '';
|
||||
}
|
||||
return JellyfinMedia(
|
||||
serverId: account.serverId,
|
||||
baseUrl: account.baseUrl,
|
||||
itemId: item.id,
|
||||
mediaSourceId: item.mediaSources.length > 1 ? item.mediaSources.first.id : null,
|
||||
title: item.name,
|
||||
subtitle: subtitle,
|
||||
runtime: item.runTime,
|
||||
ref: jellyfinMediaRef(item),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:signals/signals_flutter.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../state/settings.dart';
|
||||
import '../widgets/app_menu.dart';
|
||||
import 'browse_scope.dart';
|
||||
import 'cards.dart';
|
||||
import 'home_rows.dart';
|
||||
|
||||
/// Libraries that hold videos; music, books, photos and playlists are left
|
||||
/// out of the browser.
|
||||
bool isVideoLibrary(JellyfinItem view) => switch (view.collectionType) {
|
||||
'movies' || 'tvshows' || 'homevideos' || 'boxsets' || 'mixed' || 'musicvideos' || null => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
IconData libraryIcon(JellyfinItem view) => switch (view.collectionType) {
|
||||
'movies' => Icons.movie_outlined,
|
||||
'tvshows' => Icons.live_tv_outlined,
|
||||
'boxsets' => Icons.collections_bookmark_outlined,
|
||||
'homevideos' => Icons.videocam_outlined,
|
||||
_ => Icons.folder_outlined,
|
||||
};
|
||||
|
||||
/// The video libraries of the scope's server (cached).
|
||||
Future<List<JellyfinItem>> videoLibraries(BrowseScope scope) =>
|
||||
scope.load('views', (c) => c.userViews()).then((all) => all.where(isVideoLibrary).toList());
|
||||
|
||||
/// Start page: (library shortcuts,) one Continue row (resume points and
|
||||
/// next up merged per series, see [mergeContinue]), then the newest
|
||||
/// additions of each library as series cards ([latestCards]). Each row
|
||||
/// loads on its own, so a slow library does not hold up the rest; rows
|
||||
/// reload when watched state changes ([BrowseController.dataChanged]).
|
||||
class JellyfinHomePage extends StatelessWidget {
|
||||
const JellyfinHomePage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
return Loader<List<JellyfinItem>>(
|
||||
key: ValueKey('views-${scope.account.serverId}'),
|
||||
load: () => videoLibraries(scope),
|
||||
builder: (context, views) => ListenableBuilder(
|
||||
listenable: scope.controller,
|
||||
builder: (context, _) {
|
||||
final v = scope.controller.version;
|
||||
return ListView(
|
||||
key: const PageStorageKey('jf-home'),
|
||||
padding: const EdgeInsets.fromLTRB(0, 4, 0, 24),
|
||||
children: [
|
||||
if (scope.libraryStrip) ...[
|
||||
LibraryStrip(views: views),
|
||||
const SizedBox(height: 20),
|
||||
] else if (views.isEmpty)
|
||||
const _NoLibraries(),
|
||||
_ContinueRow(version: v),
|
||||
for (final view in views) _LatestRow(key: ValueKey('row-latest-${view.id}'), view: view, version: v),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _NoLibraries extends StatelessWidget {
|
||||
const _NoLibraries();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => const Padding(
|
||||
padding: EdgeInsets.only(bottom: 20),
|
||||
child: Text('No video libraries on this server for your user.', style: TextStyle(color: Colors.grey)),
|
||||
);
|
||||
}
|
||||
|
||||
/// The libraries as chips; a click opens one.
|
||||
class LibraryStrip extends StatelessWidget {
|
||||
final List<JellyfinItem> views;
|
||||
const LibraryStrip({super.key, required this.views});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
if (views.isEmpty) return const _NoLibraries();
|
||||
return Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
for (final v in views)
|
||||
ActionChip(
|
||||
key: ValueKey('library-${v.id}'),
|
||||
avatar: Icon(libraryIcon(v), size: 18),
|
||||
label: Text(v.name),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
|
||||
onPressed: () => scope.controller.openTop(LibraryRoute(v)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ContinueRow extends StatelessWidget {
|
||||
final int version;
|
||||
const _ContinueRow({required this.version});
|
||||
|
||||
static const title = 'Continue';
|
||||
|
||||
Future<List<JellyfinItem>> _load(BrowseScope scope) async {
|
||||
final lists = await Future.wait([
|
||||
scope.load('resume', (c) => c.resume(limit: 40)),
|
||||
scope.load('nextup', (c) => c.nextUp(limit: 40)),
|
||||
// Only for ordering: a failure leaves the row as it is.
|
||||
scope
|
||||
.load('played', (c) => c.recentlyPlayed(limit: 150))
|
||||
.catchError((Object _) => const <JellyfinItem>[]),
|
||||
]);
|
||||
return mergeContinue(
|
||||
resume: lists[0],
|
||||
nextUp: lists[1],
|
||||
recentlyPlayed: lists[2],
|
||||
dismissed: scope.accounts.continueDismissed(scope.account.serverId),
|
||||
now: scope.controller.now(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
return Loader<List<JellyfinItem>>(
|
||||
version: version,
|
||||
load: () => _load(scope),
|
||||
showError: false,
|
||||
loading: const _RowSkeleton(title: title, shape: CardShape.thumb),
|
||||
builder: (context, items) {
|
||||
scope.controller.continueKeys = {for (final i in items) continueKey(i)};
|
||||
if (items.isEmpty) return const SizedBox.shrink();
|
||||
return Padding(
|
||||
key: const ValueKey('row-continue'),
|
||||
padding: const EdgeInsets.only(bottom: 24),
|
||||
child: MediaRow(
|
||||
title: title,
|
||||
entries: cardEntries(items),
|
||||
shape: CardShape.thumb,
|
||||
seriesFirst: true,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LatestRow extends StatelessWidget {
|
||||
final JellyfinItem view;
|
||||
final int version;
|
||||
const _LatestRow({super.key, required this.view, required this.version});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
final title = 'Latest in ${view.name}';
|
||||
final shape = view.collectionType == 'homevideos' ? CardShape.thumb : CardShape.poster;
|
||||
return Loader<List<JellyfinItem>>(
|
||||
version: version,
|
||||
load: () => scope.load('latest:${view.id}', (c) => c.latest(view.id, limit: 100, groupItems: false)),
|
||||
showError: false,
|
||||
loading: _RowSkeleton(title: title, shape: shape),
|
||||
builder: (context, items) => SignalBuilder(builder: (context) {
|
||||
final hide = AppSettings.instance.hideReReleases.value;
|
||||
final cards = latestCards(items, hideReReleases: hide);
|
||||
if (cards.isEmpty) return const SizedBox.shrink();
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 24),
|
||||
child: MediaRow(
|
||||
key: ValueKey('latest-${view.id}'),
|
||||
title: title,
|
||||
entries: [for (final c in cards) (item: c.item, display: c.display, subtitle: c.subtitle)],
|
||||
shape: shape,
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextButton(
|
||||
key: ValueKey('show-all-${view.id}'),
|
||||
// Newest first, like the row.
|
||||
onPressed: () => scope.onOpen(LibraryRoute(view, sort: 'added')),
|
||||
child: const Text('Show all'),
|
||||
),
|
||||
AppMenuButton<bool>(
|
||||
key: ValueKey('latest-menu-${view.id}'),
|
||||
tooltip: 'Row options',
|
||||
items: () => [
|
||||
AppMenuItem(
|
||||
key: const ValueKey('hide-rereleases'),
|
||||
value: !hide,
|
||||
checked: hide,
|
||||
label: 'Hide re-releases in Latest',
|
||||
),
|
||||
],
|
||||
onSelected: AppSettings.instance.setHideReReleases,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RowSkeleton extends StatelessWidget {
|
||||
final String title;
|
||||
final CardShape shape;
|
||||
const _RowSkeleton({required this.title, required this.shape});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 24),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SectionHeader(title),
|
||||
LayoutBuilder(builder: (context, box) {
|
||||
final fit = fitColumns(box.maxWidth, shape.minWidth);
|
||||
return Row(
|
||||
children: [
|
||||
for (var i = 0; i < fit.cols; i++) ...[
|
||||
if (i > 0) const SizedBox(width: cardGap),
|
||||
Expanded(child: SkeletonCard(shape: shape)),
|
||||
],
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SkeletonCard extends StatelessWidget {
|
||||
final CardShape shape;
|
||||
const SkeletonCard({super.key, required this.shape});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final c = Theme.of(context).colorScheme.surfaceContainerHigh.withValues(alpha: 0.6);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: shape.aspect,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(color: c, borderRadius: BorderRadius.circular(8))),
|
||||
),
|
||||
const SizedBox(height: cardTextHeight),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'format.dart';
|
||||
|
||||
// What the Jellyfin home rows show, as pure functions over the API lists
|
||||
// (tested without widgets).
|
||||
|
||||
/// Series not watched for longer than this leave the Continue row, unless
|
||||
/// nothing newer is left.
|
||||
const continueMaxAge = Duration(days: 60);
|
||||
|
||||
/// Added this long after it first aired: a re-release ([isReRelease]).
|
||||
const reReleaseAge = Duration(days: 30);
|
||||
|
||||
/// One Continue card per series: an episode's series, else the item itself.
|
||||
String continueKey(JellyfinItem item) => item.seriesId ?? item.id;
|
||||
|
||||
DateTime? _later(DateTime? a, DateTime? b) =>
|
||||
a == null ? b : b == null || !b.isAfter(a) ? a : b;
|
||||
|
||||
/// The Continue row: Continue watching ([resume]) and Next up ([nextUp])
|
||||
/// merged into one card per series, the series watched most recently first.
|
||||
/// A series shows its resume item when that was the last thing played in
|
||||
/// it, else its next-up episode. When a series was last played comes from
|
||||
/// the resume points and from [recentlyPlayed] (finished episodes, which
|
||||
/// next-up items do not carry). Series untouched for [maxAge] are left out
|
||||
/// unless nothing else is left; [dismissed] (key -> when) hides a series
|
||||
/// until it is played again after that.
|
||||
List<JellyfinItem> mergeContinue({
|
||||
required List<JellyfinItem> resume,
|
||||
required List<JellyfinItem> nextUp,
|
||||
List<JellyfinItem> recentlyPlayed = const [],
|
||||
Map<String, DateTime> dismissed = const {},
|
||||
required DateTime now,
|
||||
Duration maxAge = continueMaxAge,
|
||||
}) {
|
||||
final finished = <String, DateTime>{};
|
||||
for (final p in recentlyPlayed) {
|
||||
final at = p.userData.lastPlayedDate;
|
||||
if (at != null) finished[continueKey(p)] = _later(finished[continueKey(p)], at)!;
|
||||
}
|
||||
final resumeBy = <String, JellyfinItem>{};
|
||||
final nextBy = <String, JellyfinItem>{};
|
||||
final order = <String>[];
|
||||
for (final r in resume) {
|
||||
final k = continueKey(r);
|
||||
final had = resumeBy[k];
|
||||
if (had == null) order.add(k);
|
||||
final at = r.userData.lastPlayedDate;
|
||||
if (had == null || (at != null && at.isAfter(had.userData.lastPlayedDate ?? DateTime(0)))) {
|
||||
resumeBy[k] = r;
|
||||
}
|
||||
}
|
||||
for (final n in nextUp) {
|
||||
final k = continueKey(n);
|
||||
if (nextBy.containsKey(k)) continue;
|
||||
nextBy[k] = n;
|
||||
if (!resumeBy.containsKey(k)) order.add(k);
|
||||
}
|
||||
|
||||
final cards = <({JellyfinItem item, DateTime? at, int index})>[];
|
||||
for (final (i, k) in order.indexed) {
|
||||
final r = resumeBy[k], n = nextBy[k], done = finished[k];
|
||||
final resumedAt = r?.userData.lastPlayedDate;
|
||||
final JellyfinItem item;
|
||||
if (r != null && (n == null || (resumedAt != null && (done == null || !resumedAt.isBefore(done))))) {
|
||||
item = r;
|
||||
} else {
|
||||
item = n!;
|
||||
}
|
||||
final at = _later(resumedAt, done);
|
||||
final hiddenAt = dismissed[k];
|
||||
if (hiddenAt != null && (at == null || !at.isAfter(hiddenAt))) continue;
|
||||
cards.add((item: item, at: at, index: i));
|
||||
}
|
||||
cards.sort((a, b) {
|
||||
if (a.at == null || b.at == null) {
|
||||
return a.at == b.at ? a.index.compareTo(b.index) : (a.at == null ? 1 : -1);
|
||||
}
|
||||
final c = b.at!.compareTo(a.at!);
|
||||
return c != 0 ? c : a.index.compareTo(b.index);
|
||||
});
|
||||
final fresh = [for (final c in cards) if (c.at != null && now.difference(c.at!) <= maxAge) c.item];
|
||||
return fresh.isNotEmpty ? fresh : [for (final c in cards) c.item];
|
||||
}
|
||||
|
||||
/// Added to the library long ([age]) after it first aired: a re-upload or
|
||||
/// an old season added late, not news. Unknown dates are never re-releases.
|
||||
bool isReRelease(JellyfinItem item, {Duration age = reReleaseAge}) {
|
||||
final aired = item.premiereDate, added = item.dateCreated;
|
||||
return aired != null && added != null && added.difference(aired) > age;
|
||||
}
|
||||
|
||||
/// One card of a "Latest in X" row: [item] is what selecting or putting it
|
||||
/// up acts on, [display] gives the picture and title, [subtitle] the line
|
||||
/// under it.
|
||||
class LatestCard {
|
||||
final JellyfinItem item;
|
||||
final JellyfinItem display;
|
||||
final String subtitle;
|
||||
const LatestCard(this.item, this.display, this.subtitle);
|
||||
}
|
||||
|
||||
/// A series to show for [episode]: its id, name and poster.
|
||||
JellyfinItem seriesOf(JellyfinItem episode) => JellyfinItem(
|
||||
id: episode.seriesId!,
|
||||
name: episode.seriesName ?? episode.name,
|
||||
type: JellyfinItemType.series,
|
||||
isFolder: true,
|
||||
imageTags: {
|
||||
if (episode.seriesPrimaryImageTag != null)
|
||||
JellyfinImageType.primary.apiName: episode.seriesPrimaryImageTag!,
|
||||
},
|
||||
parentBackdropItemId: episode.parentBackdropItemId,
|
||||
parentBackdropImageTags: episode.parentBackdropImageTags,
|
||||
);
|
||||
|
||||
/// "Latest in X" from the library's newest items (ungrouped, newest
|
||||
/// first): episodes become one card per series (its poster and name,
|
||||
/// "S1E1" for a single new episode, else "N new"), in order of the newest
|
||||
/// episode; movies and other items stay as they are. With [hideReReleases]
|
||||
/// items that [isReRelease] are left out first.
|
||||
List<LatestCard> latestCards(List<JellyfinItem> items, {bool hideReReleases = true}) {
|
||||
final kept = hideReReleases ? items.where((i) => !isReRelease(i)) : items;
|
||||
final groups = <String, List<JellyfinItem>>{};
|
||||
final out = <Object>[]; // a JellyfinItem, or a series id (group)
|
||||
for (final i in kept) {
|
||||
final sid = i.seriesId;
|
||||
if (i.kind == JellyfinItemKind.episode && sid != null) {
|
||||
final g = groups[sid];
|
||||
if (g == null) {
|
||||
groups[sid] = [i];
|
||||
out.add(sid);
|
||||
} else {
|
||||
g.add(i);
|
||||
}
|
||||
} else {
|
||||
out.add(i);
|
||||
}
|
||||
}
|
||||
return [
|
||||
for (final o in out)
|
||||
if (o is JellyfinItem)
|
||||
LatestCard(
|
||||
o,
|
||||
o,
|
||||
o.kind == JellyfinItemKind.series && (o.childCount ?? 0) > 1
|
||||
? '${o.childCount} new'
|
||||
: cardSubtitle(o),
|
||||
)
|
||||
else
|
||||
_seriesCard(groups[o]!),
|
||||
];
|
||||
}
|
||||
|
||||
LatestCard _seriesCard(List<JellyfinItem> eps) {
|
||||
final series = seriesOf(eps.first);
|
||||
if (eps.length == 1) {
|
||||
final e = eps.single;
|
||||
return LatestCard(e, series, e.episodeLabel ?? e.name);
|
||||
}
|
||||
return LatestCard(series, series, '${eps.length} new');
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
/// Server-side scale steps: nearby sizes share one URL (and one cache
|
||||
/// entry) instead of fetching per-pixel variants on every resize.
|
||||
const _widthSteps = [160, 240, 320, 480, 640, 960, 1280, 1920, 2560];
|
||||
|
||||
int imageWidthStep(double physicalWidth) {
|
||||
for (final s in _widthSteps) {
|
||||
if (s >= physicalWidth) return s;
|
||||
}
|
||||
return _widthSteps.last;
|
||||
}
|
||||
|
||||
/// A Jellyfin image sized to its box. The URL carries the image tag and the
|
||||
/// width step, so Flutter's image cache (keyed by URL) reuses it until the
|
||||
/// image changes on the server; decode is capped at the same width. Shows
|
||||
/// [placeholder] (or a tinted box with [icon]) while loading and on error,
|
||||
/// and fades in when ready.
|
||||
class JellyfinImage extends StatelessWidget {
|
||||
final JellyfinClient client;
|
||||
final JellyfinImageRef? image;
|
||||
final BoxFit fit;
|
||||
final IconData icon;
|
||||
final Alignment alignment;
|
||||
final Widget? placeholder;
|
||||
const JellyfinImage({
|
||||
super.key,
|
||||
required this.client,
|
||||
required this.image,
|
||||
this.fit = BoxFit.cover,
|
||||
this.icon = Icons.movie_outlined,
|
||||
this.alignment = Alignment.center,
|
||||
this.placeholder,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ref = image;
|
||||
final fallback = placeholder ?? _Placeholder(icon: icon);
|
||||
if (ref == null) return fallback;
|
||||
return LayoutBuilder(builder: (context, box) {
|
||||
final dpr = MediaQuery.maybeDevicePixelRatioOf(context) ?? 1;
|
||||
final w = box.hasBoundedWidth ? box.maxWidth : 480.0;
|
||||
final step = imageWidthStep(w * dpr);
|
||||
final url = client.imageUrl(ref, maxWidth: step, quality: 85).toString();
|
||||
return Image.network(
|
||||
url,
|
||||
key: ValueKey(url),
|
||||
fit: fit,
|
||||
alignment: alignment,
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
cacheWidth: step,
|
||||
filterQuality: FilterQuality.medium,
|
||||
frameBuilder: (context, child, frame, sync) {
|
||||
if (sync) return child;
|
||||
return Stack(fit: StackFit.passthrough, children: [
|
||||
if (frame == null) fallback,
|
||||
AnimatedOpacity(
|
||||
opacity: frame == null ? 0 : 1,
|
||||
duration: const Duration(milliseconds: 180),
|
||||
child: child,
|
||||
),
|
||||
]);
|
||||
},
|
||||
errorBuilder: (context, _, _) => fallback,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class _Placeholder extends StatelessWidget {
|
||||
final IconData icon;
|
||||
const _Placeholder({required this.icon});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
return ColoredBox(
|
||||
color: scheme.surfaceContainerHigh,
|
||||
child: Center(
|
||||
child: Icon(icon, size: 28, color: scheme.onSurfaceVariant.withValues(alpha: 0.35)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'browse_scope.dart';
|
||||
import 'cards.dart';
|
||||
import 'home_page.dart' show SkeletonCard;
|
||||
|
||||
enum LibrarySort {
|
||||
name('Name', JellyfinSortBy.sortName, false),
|
||||
added('Date added', JellyfinSortBy.dateCreated, true),
|
||||
premiere('Release date', JellyfinSortBy.premiereDate, true),
|
||||
rating('Rating', JellyfinSortBy.communityRating, true),
|
||||
random('Random', JellyfinSortBy.random, false);
|
||||
|
||||
final String label;
|
||||
final String apiName;
|
||||
/// Natural direction: newest / best first.
|
||||
final bool descending;
|
||||
const LibrarySort(this.label, this.apiName, this.descending);
|
||||
}
|
||||
|
||||
/// Item types and recursion for a library: movie and show libraries list
|
||||
/// their titles flat; anything else is browsed folder by folder.
|
||||
({List<String> types, bool recursive}) libraryShape(JellyfinItem folder) =>
|
||||
switch (folder.collectionType) {
|
||||
'movies' => (types: const [JellyfinItemType.movie], recursive: true),
|
||||
'tvshows' => (types: const [JellyfinItemType.series], recursive: true),
|
||||
'boxsets' => (types: const [JellyfinItemType.boxSet], recursive: true),
|
||||
_ => (types: const <String>[], recursive: false),
|
||||
};
|
||||
|
||||
const libraryPageSize = 100;
|
||||
|
||||
/// One library (or folder) as a grid that fills the width, with sort,
|
||||
/// unplayed / favourite filters and infinite scroll. The scrollbar spans
|
||||
/// the full count from the start: not-yet-loaded cells are skeletons and
|
||||
/// pages load as they come near the viewport.
|
||||
class JellyfinLibraryPage extends StatefulWidget {
|
||||
final JellyfinItem folder;
|
||||
/// A [LibrarySort] name to start with (in its natural direction).
|
||||
final String? sort;
|
||||
const JellyfinLibraryPage({super.key, required this.folder, this.sort});
|
||||
|
||||
@override
|
||||
State<JellyfinLibraryPage> createState() => _JellyfinLibraryPageState();
|
||||
}
|
||||
|
||||
class _JellyfinLibraryPageState extends State<JellyfinLibraryPage> {
|
||||
late LibrarySort _sort =
|
||||
LibrarySort.values.where((s) => s.name == widget.sort).firstOrNull ?? LibrarySort.name;
|
||||
late bool _descending = _sort.descending;
|
||||
bool _unplayed = false;
|
||||
bool _favorites = false;
|
||||
|
||||
final _items = <JellyfinItem>[];
|
||||
int? _total;
|
||||
bool _loading = false;
|
||||
Object? _error;
|
||||
int _gen = 0;
|
||||
final _scroll = ScrollController();
|
||||
|
||||
BrowseScope? _scope;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
final scope = BrowseScope.of(context);
|
||||
final first = _scope == null;
|
||||
final changedServer = _scope != null && _scope!.client != scope.client;
|
||||
_scope = scope;
|
||||
if (first || changedServer) _reload();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scroll.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
JellyfinItemQuery get _query {
|
||||
final shape = libraryShape(widget.folder);
|
||||
return JellyfinItemQuery(
|
||||
parentId: widget.folder.id,
|
||||
includeItemTypes: shape.types,
|
||||
recursive: shape.recursive,
|
||||
sortBy: [
|
||||
// Folders first when browsing a folder tree.
|
||||
if (!shape.recursive && _sort == LibrarySort.name) 'IsFolder',
|
||||
_sort.apiName,
|
||||
if (_sort != LibrarySort.name) JellyfinSortBy.sortName,
|
||||
],
|
||||
descending: _descending,
|
||||
filters: [
|
||||
if (_unplayed) JellyfinFilter.isUnplayed,
|
||||
if (_favorites) JellyfinFilter.isFavorite,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _reload() {
|
||||
_gen++;
|
||||
_items.clear();
|
||||
_total = null;
|
||||
_error = null;
|
||||
_loading = false;
|
||||
if (_scroll.hasClients) _scroll.jumpTo(0);
|
||||
_loadMore();
|
||||
}
|
||||
|
||||
Future<void> _loadMore() async {
|
||||
final scope = _scope;
|
||||
if (scope == null || _loading) return;
|
||||
if (_total != null && _items.length >= _total!) return;
|
||||
final gen = _gen;
|
||||
setState(() {
|
||||
_loading = true;
|
||||
_error = null;
|
||||
});
|
||||
try {
|
||||
final page = await scope.client.items(_query.page(_items.length, libraryPageSize));
|
||||
if (gen != _gen || !mounted) return;
|
||||
setState(() {
|
||||
_items.addAll(page.items);
|
||||
// An empty page before the advertised end: the library shrank.
|
||||
_total = page.items.isEmpty ? _items.length : page.totalRecordCount;
|
||||
_loading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
if (gen != _gen || !mounted) return;
|
||||
if (e is JellyfinException && e.isUnauthorized) {
|
||||
scope.accounts.markExpired(scope.account.serverId);
|
||||
}
|
||||
setState(() {
|
||||
_loading = false;
|
||||
_error = e;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _setSort(LibrarySort s) {
|
||||
setState(() {
|
||||
_sort = s;
|
||||
_descending = s.descending;
|
||||
});
|
||||
_reload();
|
||||
}
|
||||
|
||||
CardShape get _shape =>
|
||||
widget.folder.collectionType == 'homevideos' ? CardShape.thumb : CardShape.poster;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
final total = _total;
|
||||
final toolbar = Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(widget.folder.name, style: t.titleLarge),
|
||||
const SizedBox(width: 4),
|
||||
Text(total == null ? '' : '$total ${total == 1 ? 'item' : 'items'}',
|
||||
key: const ValueKey('library-count'),
|
||||
style: t.bodySmall?.copyWith(color: Colors.grey)),
|
||||
const SizedBox(width: 12),
|
||||
_SortMenu(sort: _sort, onSelected: _setSort),
|
||||
if (_sort != LibrarySort.random)
|
||||
IconButton(
|
||||
tooltip: _descending ? 'Descending' : 'Ascending',
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () {
|
||||
setState(() => _descending = !_descending);
|
||||
_reload();
|
||||
},
|
||||
icon: Icon(_descending ? Icons.arrow_downward : Icons.arrow_upward, size: 18),
|
||||
)
|
||||
else
|
||||
IconButton(
|
||||
tooltip: 'Shuffle again',
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: _reload,
|
||||
icon: const Icon(Icons.shuffle, size: 18),
|
||||
),
|
||||
FilterChip(
|
||||
key: const ValueKey('filter-unplayed'),
|
||||
label: const Text('Unwatched'),
|
||||
selected: _unplayed,
|
||||
visualDensity: VisualDensity.compact,
|
||||
onSelected: (v) {
|
||||
setState(() => _unplayed = v);
|
||||
_reload();
|
||||
},
|
||||
),
|
||||
FilterChip(
|
||||
key: const ValueKey('filter-favorites'),
|
||||
label: const Text('Favorites'),
|
||||
selected: _favorites,
|
||||
visualDensity: VisualDensity.compact,
|
||||
onSelected: (v) {
|
||||
setState(() => _favorites = v);
|
||||
_reload();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final count = total ?? (_loading ? libraryPageSize ~/ 4 : 0);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Padding(padding: const EdgeInsets.only(bottom: 12), child: toolbar),
|
||||
if (_error != null && _items.isEmpty)
|
||||
LoadError(error: _error!, onRetry: _loadMore)
|
||||
else if (total == 0)
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(32),
|
||||
child: Center(child: Text('Nothing here', style: TextStyle(color: Colors.grey))),
|
||||
)
|
||||
else
|
||||
Expanded(
|
||||
child: Scrollbar(
|
||||
controller: _scroll,
|
||||
child: CustomScrollView(
|
||||
controller: _scroll,
|
||||
slivers: [
|
||||
SliverGrid(
|
||||
gridDelegate: CardGridDelegate(_shape),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, i) {
|
||||
if (i >= _items.length - 40 && _error == null) {
|
||||
// Near the loaded edge: fetch the next page.
|
||||
scheduleMicrotask(_loadMore);
|
||||
}
|
||||
if (i >= _items.length) return SkeletonCard(shape: _shape);
|
||||
return MediaCard(item: _items[i], shape: _shape);
|
||||
},
|
||||
childCount: count,
|
||||
),
|
||||
),
|
||||
if (_error != null && _items.isNotEmpty)
|
||||
SliverToBoxAdapter(child: LoadError(error: _error!, onRetry: _loadMore)),
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 24)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SortMenu extends StatelessWidget {
|
||||
final LibrarySort sort;
|
||||
final ValueChanged<LibrarySort> onSelected;
|
||||
const _SortMenu({required this.sort, required this.onSelected});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MenuAnchor(
|
||||
menuChildren: [
|
||||
for (final s in LibrarySort.values)
|
||||
MenuItemButton(
|
||||
key: ValueKey('sort-${s.name}'),
|
||||
leadingIcon: Icon(s == sort ? Icons.check : null, size: 18),
|
||||
onPressed: () => onSelected(s),
|
||||
child: Text(s.label),
|
||||
),
|
||||
],
|
||||
builder: (context, menu, _) => OutlinedButton.icon(
|
||||
key: const ValueKey('library-sort'),
|
||||
onPressed: () => menu.isOpen ? menu.close() : menu.open(),
|
||||
icon: const Icon(Icons.sort, size: 18),
|
||||
label: Text(sort.label),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../screens/home/ui.dart';
|
||||
import 'accounts.dart';
|
||||
import 'browse_scope.dart';
|
||||
import 'browser.dart';
|
||||
import 'sign_in_panel.dart';
|
||||
|
||||
/// The Library's Jellyfin source: the library browser once a server is
|
||||
/// linked, else [empty] (default: an inline add-server panel).
|
||||
class JellyfinPickerSource extends StatefulWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final BrowseController? controller;
|
||||
final JellyfinSelection? selected;
|
||||
final ValueChanged<JellyfinSelection> onSelect;
|
||||
final ValueChanged<JellyfinSelection> onPutUp;
|
||||
final void Function(JellyfinSelection item, {bool next})? onAddToQueue;
|
||||
final VoidCallback? onOpenIntegrations;
|
||||
final BrowseStart? start;
|
||||
final bool libraryStrip;
|
||||
/// Shown while no server is linked.
|
||||
final WidgetBuilder? empty;
|
||||
const JellyfinPickerSource({
|
||||
super.key,
|
||||
this.start,
|
||||
required this.accounts,
|
||||
required this.onSelect,
|
||||
required this.onPutUp,
|
||||
this.onAddToQueue,
|
||||
this.controller,
|
||||
this.selected,
|
||||
this.onOpenIntegrations,
|
||||
this.libraryStrip = true,
|
||||
this.empty,
|
||||
});
|
||||
|
||||
@override
|
||||
State<JellyfinPickerSource> createState() => _JellyfinPickerSourceState();
|
||||
}
|
||||
|
||||
class _JellyfinPickerSourceState extends State<JellyfinPickerSource> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
widget.accounts.ensureLoaded();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListenableBuilder(
|
||||
listenable: widget.accounts,
|
||||
builder: (context, _) {
|
||||
final a = widget.accounts;
|
||||
if (!a.loaded) {
|
||||
return const Center(child: CircularProgressIndicator(strokeWidth: 2));
|
||||
}
|
||||
if (a.isEmpty && widget.empty != null) return widget.empty!(context);
|
||||
if (a.isEmpty) return _LinkFirst(accounts: a, onOpenIntegrations: widget.onOpenIntegrations);
|
||||
return JellyfinBrowser(
|
||||
key: const ValueKey('media-jellyfin'),
|
||||
accounts: a,
|
||||
controller: widget.controller,
|
||||
selected: widget.selected,
|
||||
onSelect: widget.onSelect,
|
||||
onPutUp: widget.onPutUp,
|
||||
onAddToQueue: widget.onAddToQueue,
|
||||
onOpenIntegrations: widget.onOpenIntegrations,
|
||||
start: widget.start,
|
||||
libraryStrip: widget.libraryStrip,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LinkFirst extends StatelessWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final VoidCallback? onOpenIntegrations;
|
||||
const _LinkFirst({required this.accounts, this.onOpenIntegrations});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
key: const ValueKey('media-jellyfin'),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 560),
|
||||
child: Panel(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text('Link a Jellyfin server to browse it here. '
|
||||
'You can manage linked servers in Integrations.',
|
||||
style: TextStyle(color: Colors.grey)),
|
||||
const SizedBox(height: kGap),
|
||||
JellyfinSignInPanel(accounts: accounts),
|
||||
if (onOpenIntegrations != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: TextButton(
|
||||
onPressed: onOpenIntegrations, child: const Text('Open Integrations')),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
/// What the player shows, sampled about once a second. [aid] / [sid] are
|
||||
/// mpv track ids (null = none / subtitles off).
|
||||
class PlayerSnapshot {
|
||||
final double position;
|
||||
final bool paused;
|
||||
final int? aid;
|
||||
final int? sid;
|
||||
const PlayerSnapshot({required this.position, required this.paused, this.aid, this.sid});
|
||||
|
||||
@override
|
||||
String toString() => 'PlayerSnapshot($position, paused: $paused, aid: $aid, sid: $sid)';
|
||||
}
|
||||
|
||||
/// Playing / Progress / Stopped for one item played with this viewer's own
|
||||
/// account, so Jellyfin's watched state and Continue Watching follow what
|
||||
/// this viewer saw. Fed a [PlayerSnapshot] every tick ([update]); sends
|
||||
/// Progress every [interval] and at once on pause, resume, seek (a jump of
|
||||
/// more than 3 s from where playback should be) or a track change. Reports
|
||||
/// go out one after another; a failure is logged and handed to [onError]
|
||||
/// (the session shows one quiet toast) and never touches playback. A 401
|
||||
/// calls [onUnauthorized] and ends reporting.
|
||||
///
|
||||
/// Watched or not is [WatchSession]'s rule (time In, D3), not Jellyfin's
|
||||
/// position percentages (see ARCHITECTURE.md "Watch tracking"): the
|
||||
/// session's watch tracker feeds [watch] and this reporter only reads its
|
||||
/// verdict. An item played before ([playedBefore]) stays played
|
||||
/// (re-marked after Playing, Progress without a position, Stopped without
|
||||
/// one, then marked played again); otherwise Progress leaves the position
|
||||
/// out past [_noPositionFrom] of the runtime so Jellyfin cannot mark it
|
||||
/// played on its own, and Stopped carries what the rule says.
|
||||
class JellyfinProgressReporter {
|
||||
final JellyfinClient client;
|
||||
final String itemId;
|
||||
final JellyfinMediaSource source;
|
||||
final String playSessionId;
|
||||
final Duration interval;
|
||||
final DateTime Function() _clock;
|
||||
final void Function(Object error)? onError;
|
||||
final VoidCallback? onUnauthorized;
|
||||
|
||||
/// What this viewer watched of the item while it was open here (fed by
|
||||
/// the watch tracker, not by this reporter).
|
||||
final WatchSession watch;
|
||||
|
||||
JellyfinProgressReporter({
|
||||
required this.client,
|
||||
required this.itemId,
|
||||
required this.source,
|
||||
required this.playSessionId,
|
||||
bool playedBefore = false,
|
||||
int resumeTicksBefore = 0,
|
||||
this.interval = const Duration(seconds: 10),
|
||||
this.onError,
|
||||
this.onUnauthorized,
|
||||
this.onStopped,
|
||||
WatchSession? watch,
|
||||
DateTime Function()? clock,
|
||||
}) : _clock = clock ?? DateTime.now,
|
||||
_keepPlayed = playedBefore,
|
||||
_runtime = (source.runTimeTicks ?? 0) / jellyfinTicksPerSecond,
|
||||
watch = (watch ?? WatchSession())
|
||||
..playedBefore = playedBefore
|
||||
..resumeBefore = resumeTicksBefore / jellyfinTicksPerSecond;
|
||||
|
||||
/// Past this share of the runtime Progress carries no position: Jellyfin
|
||||
/// marks an item played past its "max resume" share (90 % by default).
|
||||
static const _noPositionFrom = 0.85;
|
||||
|
||||
/// After Stopped (and a mark played) went out: the item's watched
|
||||
/// state on the server may differ from what lists show.
|
||||
final void Function()? onStopped;
|
||||
|
||||
Future<void> _chain = Future.value();
|
||||
bool _playing = false;
|
||||
bool _dead = false;
|
||||
bool _keepPlayed;
|
||||
double _runtime;
|
||||
double? _endingStart;
|
||||
PlayerSnapshot? _last;
|
||||
DateTime? _lastAt;
|
||||
DateTime? _lastSentAt;
|
||||
|
||||
/// Between [start] and [stop].
|
||||
bool get active => _playing && !_dead;
|
||||
|
||||
/// The item counts as played here (before, or by the rule at a stop).
|
||||
bool get keepsPlayed => _keepPlayed;
|
||||
|
||||
/// The player's duration (used when Jellyfin gave no runtime) and where
|
||||
/// the ending starts (Outro segment / ED chapter), seconds.
|
||||
void timeline({double duration = 0, double? endingStart}) {
|
||||
if ((source.runTimeTicks ?? 0) <= 0 && duration > 0) _runtime = duration;
|
||||
_endingStart = endingStart;
|
||||
}
|
||||
|
||||
/// The report body for [s]: ticks, pause, and mpv's aid/sid mapped to
|
||||
/// Jellyfin stream indices (-1 = subtitles off).
|
||||
JellyfinPlaybackReport reportFor(PlayerSnapshot s, {bool withPosition = true}) => JellyfinPlaybackReport(
|
||||
itemId: itemId,
|
||||
mediaSourceId: source.id,
|
||||
playSessionId: playSessionId,
|
||||
positionTicks: withPosition ? _ticks(s.position) : null,
|
||||
isPaused: s.paused,
|
||||
audioStreamIndex: s.aid == null
|
||||
? null
|
||||
: source.jellyfinIndexForMpvTrack(JellyfinStreamType.audio, s.aid!),
|
||||
subtitleStreamIndex: s.sid == null
|
||||
? -1
|
||||
: source.jellyfinIndexForMpvTrack(JellyfinStreamType.subtitle, s.sid!),
|
||||
);
|
||||
|
||||
static int _ticks(double secs) => (secs * jellyfinTicksPerSecond).round();
|
||||
|
||||
/// Progress may carry the position: not for a played item, not without
|
||||
/// a runtime and not near the end (either would let Jellyfin decide).
|
||||
bool _progressPosition(double position) =>
|
||||
!_keepPlayed && _runtime > 0 && position < _noPositionFrom * _runtime;
|
||||
|
||||
/// Playing: once the media is open. Again after [stop] (played to the
|
||||
/// end, then someone seeked back) starts reporting anew. A played item
|
||||
/// is marked played again right after (Jellyfin up to 10.11 clears it
|
||||
/// on Playing).
|
||||
void start(PlayerSnapshot s) {
|
||||
if (_playing || _dead) return;
|
||||
_playing = true;
|
||||
_mark(s);
|
||||
_send('Playing', () => client.reportPlaybackStart(reportFor(s)));
|
||||
if (_keepPlayed) _send('played', () => client.markPlayed(itemId));
|
||||
}
|
||||
|
||||
/// Progress when due (see the class doc).
|
||||
void update(PlayerSnapshot s, {bool force = false}) {
|
||||
if (!_playing || _dead) return;
|
||||
final last = _last, lastAt = _lastAt, sentAt = _lastSentAt;
|
||||
final now = _clock();
|
||||
var due = force || last == null || lastAt == null || sentAt == null;
|
||||
if (!due) {
|
||||
final elapsed = now.difference(lastAt).inMilliseconds / 1000;
|
||||
final expected = last.position + (last.paused ? 0 : elapsed);
|
||||
due = s.paused != last.paused ||
|
||||
s.aid != last.aid ||
|
||||
s.sid != last.sid ||
|
||||
(s.position - expected).abs() > 3 ||
|
||||
now.difference(sentAt) >= interval;
|
||||
}
|
||||
_last = s;
|
||||
_lastAt = now;
|
||||
if (!due) return;
|
||||
_lastSentAt = now;
|
||||
final report = reportFor(s, withPosition: _progressPosition(s.position));
|
||||
_send('Progress', () => client.reportPlaybackProgress(report));
|
||||
}
|
||||
|
||||
/// Stopped (swap, leave, kick, window close, played to the end), as
|
||||
/// [WatchSession.verdict] says: played (or kept played) -> no position,
|
||||
/// then marked played; a peek -> the resume point from before; part way
|
||||
/// -> the position, held under [_noPositionFrom] of the runtime.
|
||||
/// Completes when it and everything before it went out.
|
||||
Future<void> stop(PlayerSnapshot s) {
|
||||
if (!_playing || _dead) return _chain;
|
||||
_playing = false;
|
||||
final v = _keepPlayed
|
||||
? const WatchVerdict(WatchOutcome.keepPlayed)
|
||||
: watch.verdict(runtime: _runtime, endingStart: _endingStart);
|
||||
debugPrint('jellyfin $itemId: $v (${watch.credited.round()} s In of ${_runtime.round()} s)');
|
||||
final int? ticks;
|
||||
switch (v.outcome) {
|
||||
case WatchOutcome.played || WatchOutcome.keepPlayed:
|
||||
_keepPlayed = true;
|
||||
ticks = null;
|
||||
case WatchOutcome.peek:
|
||||
ticks = _ticks(watch.resumeBefore);
|
||||
case WatchOutcome.partial:
|
||||
final at = v.resumeAt ?? s.position;
|
||||
ticks = _ticks(_runtime > 0 ? math.min(at, _noPositionFrom * _runtime) : at);
|
||||
}
|
||||
final report = JellyfinPlaybackReport(
|
||||
itemId: itemId, mediaSourceId: source.id, playSessionId: playSessionId, positionTicks: ticks);
|
||||
_send('Stopped', () => client.reportPlaybackStopped(report));
|
||||
if (ticks == null) {
|
||||
_send('played', () => client.markPlayed(itemId));
|
||||
// Marking played keeps a resume point Progress left (Continue would
|
||||
// still list it, "3 min left"): clear it.
|
||||
_send('resume cleared', () => client.clearResumePosition(itemId));
|
||||
}
|
||||
return _chain = _chain.then((_) => onStopped?.call());
|
||||
}
|
||||
|
||||
void _mark(PlayerSnapshot s) {
|
||||
_last = s;
|
||||
_lastAt = _lastSentAt = _clock();
|
||||
}
|
||||
|
||||
void _send(String what, Future<void> Function() call) {
|
||||
_chain = _chain.then((_) async {
|
||||
if (_dead) return;
|
||||
try {
|
||||
await call().timeout(const Duration(seconds: 10));
|
||||
} catch (e) {
|
||||
debugPrint('jellyfin $what report for $itemId failed: $e');
|
||||
if (e is JellyfinException && e.isUnauthorized) {
|
||||
_dead = true;
|
||||
onUnauthorized?.call();
|
||||
}
|
||||
onError?.call(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'browse_scope.dart';
|
||||
import 'cards.dart';
|
||||
|
||||
/// Search results grouped by kind: shows and movies as posters, episodes
|
||||
/// as thumbnails, each a grid that fills the width.
|
||||
class JellyfinSearchResults extends StatelessWidget {
|
||||
final String term;
|
||||
const JellyfinSearchResults({super.key, required this.term});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
return Loader<List<JellyfinItem>>(
|
||||
key: ValueKey('search-$term-${scope.account.serverId}'),
|
||||
load: () => scope.load('search:$term', (c) => c.search(term, limit: 80)),
|
||||
builder: (context, items) {
|
||||
if (items.isEmpty) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Center(
|
||||
child: Text('Nothing found for "$term"',
|
||||
key: const ValueKey('search-empty'),
|
||||
style: const TextStyle(color: Colors.grey)),
|
||||
),
|
||||
);
|
||||
}
|
||||
final groups = [
|
||||
('Shows', CardShape.poster, items.where((i) => i.kind == JellyfinItemKind.series).toList()),
|
||||
('Movies', CardShape.poster, items.where((i) => i.kind == JellyfinItemKind.movie).toList()),
|
||||
('Episodes', CardShape.thumb, items.where((i) => i.kind == JellyfinItemKind.episode).toList()),
|
||||
(
|
||||
'Other',
|
||||
CardShape.poster,
|
||||
items
|
||||
.where((i) => !const [
|
||||
JellyfinItemKind.series,
|
||||
JellyfinItemKind.movie,
|
||||
JellyfinItemKind.episode
|
||||
].contains(i.kind))
|
||||
.toList()
|
||||
),
|
||||
].where((g) => g.$3.isNotEmpty);
|
||||
return CustomScrollView(
|
||||
key: const ValueKey('search-results'),
|
||||
slivers: [
|
||||
for (final (title, shape, list) in groups) ...[
|
||||
SliverToBoxAdapter(child: SectionHeader(title, count: '${list.length}')),
|
||||
SliverGrid(
|
||||
gridDelegate: CardGridDelegate(shape),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, i) => MediaCard(
|
||||
item: list[i],
|
||||
shape: shape,
|
||||
seriesFirst: shape == CardShape.thumb,
|
||||
),
|
||||
childCount: list.length,
|
||||
),
|
||||
),
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 16)),
|
||||
],
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'browse_scope.dart';
|
||||
import 'cards.dart' show doubleClickTime;
|
||||
import 'format.dart';
|
||||
import 'images.dart';
|
||||
|
||||
/// Series page: backdrop + logo header with overview and the smart "next
|
||||
/// unwatched" button, a season selector and the season's episodes as dense
|
||||
/// rows (several columns on wide windows).
|
||||
class JellyfinSeriesPage extends StatefulWidget {
|
||||
final JellyfinItem series;
|
||||
final String? seasonId;
|
||||
const JellyfinSeriesPage({super.key, required this.series, this.seasonId});
|
||||
|
||||
@override
|
||||
State<JellyfinSeriesPage> createState() => _JellyfinSeriesPageState();
|
||||
}
|
||||
|
||||
typedef _SeriesData = ({JellyfinItem series, List<JellyfinItem> seasons, JellyfinItem? next});
|
||||
|
||||
class _JellyfinSeriesPageState extends State<JellyfinSeriesPage> {
|
||||
String? _seasonId;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_seasonId = widget.seasonId;
|
||||
}
|
||||
|
||||
Future<_SeriesData> _load(BrowseScope scope) async {
|
||||
final id = widget.series.id;
|
||||
final results = await Future.wait<Object?>([
|
||||
scope.load('item:$id', (c) => c.item(id)),
|
||||
scope.load('seasons:$id', (c) => c.seasons(id)),
|
||||
scope
|
||||
.load('next:$id', (c) => c.nextUp(seriesId: id, limit: 1, enableResumable: true))
|
||||
.then<List<JellyfinItem>?>((v) => v, onError: (_) => null),
|
||||
]);
|
||||
final next = results[2] as List<JellyfinItem>?;
|
||||
return (
|
||||
series: results[0] as JellyfinItem,
|
||||
seasons: results[1] as List<JellyfinItem>,
|
||||
next: next == null || next.isEmpty ? null : next.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Season to show first: the one holding the next episode, else the first
|
||||
/// with something unwatched, else the first.
|
||||
String? _defaultSeason(_SeriesData d) {
|
||||
if (d.seasons.isEmpty) return null;
|
||||
final nextSeason = d.next?.seasonId;
|
||||
if (nextSeason != null && d.seasons.any((s) => s.id == nextSeason)) return nextSeason;
|
||||
return (d.seasons.where((s) => !s.userData.played).firstOrNull ?? d.seasons.first).id;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
return Loader<_SeriesData>(
|
||||
key: ValueKey('series-${widget.series.id}-${scope.account.serverId}'),
|
||||
version: scope.controller.version,
|
||||
load: () => _load(scope),
|
||||
builder: (context, d) {
|
||||
final seasonId = (_seasonId != null && d.seasons.any((s) => s.id == _seasonId))
|
||||
? _seasonId
|
||||
: _defaultSeason(d);
|
||||
return CustomScrollView(
|
||||
key: PageStorageKey('series-${widget.series.id}'),
|
||||
slivers: [
|
||||
SliverToBoxAdapter(child: _SeriesHeader(data: d)),
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
for (final s in d.seasons)
|
||||
ChoiceChip(
|
||||
key: ValueKey('season-${s.id}'),
|
||||
label: Text(s.name),
|
||||
avatar: s.userData.played
|
||||
? const Icon(Icons.check, size: 16)
|
||||
: null,
|
||||
showCheckmark: false,
|
||||
selected: s.id == seasonId,
|
||||
onSelected: (_) => setState(() => _seasonId = s.id),
|
||||
tooltip: s.userData.unplayedItemCount != null
|
||||
? '${s.userData.unplayedItemCount} unwatched'
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (seasonId != null)
|
||||
_EpisodeList(
|
||||
key: ValueKey('episodes-$seasonId'),
|
||||
seriesId: widget.series.id,
|
||||
seasonId: seasonId,
|
||||
version: scope.controller.version,
|
||||
),
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 24)),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SeriesHeader extends StatefulWidget {
|
||||
final _SeriesData data;
|
||||
const _SeriesHeader({required this.data});
|
||||
|
||||
@override
|
||||
State<_SeriesHeader> createState() => _SeriesHeaderState();
|
||||
}
|
||||
|
||||
class _SeriesHeaderState extends State<_SeriesHeader> {
|
||||
bool _more = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
final theme = Theme.of(context);
|
||||
final t = theme.textTheme;
|
||||
final s = widget.data.series;
|
||||
final next = widget.data.next;
|
||||
final logo = s.image(JellyfinImageType.logo);
|
||||
final meta = [
|
||||
if (s.productionYear != null) '${s.productionYear}',
|
||||
if (s.officialRating != null) s.officialRating!,
|
||||
if (s.communityRating != null) '★ ${s.communityRating!.toStringAsFixed(1)}',
|
||||
if (widget.data.seasons.isNotEmpty)
|
||||
'${widget.data.seasons.length} ${widget.data.seasons.length == 1 ? 'season' : 'seasons'}',
|
||||
if ((s.userData.unplayedItemCount ?? 0) > 0) '${s.userData.unplayedItemCount} unwatched',
|
||||
].join(' · ');
|
||||
|
||||
final String nextLabel;
|
||||
if (next == null) {
|
||||
nextLabel = 'All watched';
|
||||
} else if (next.userData.isResumable) {
|
||||
nextLabel = 'Resume ${next.episodeLabel ?? next.name}';
|
||||
} else {
|
||||
nextLabel = 'Next up: ${next.episodeLabel ?? ''} ${next.name}'.trim();
|
||||
}
|
||||
final selectedNext = next != null && scope.selectedItemId == next.id;
|
||||
|
||||
return LayoutBuilder(builder: (context, box) {
|
||||
final h = (box.maxWidth * 0.28).clamp(220.0, 380.0);
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: SizedBox(
|
||||
height: h,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
JellyfinImage(
|
||||
client: scope.client,
|
||||
image: s.image(JellyfinImageType.backdrop),
|
||||
alignment: Alignment.topCenter,
|
||||
icon: Icons.live_tv_outlined,
|
||||
),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.centerLeft,
|
||||
end: Alignment.centerRight,
|
||||
colors: [
|
||||
theme.colorScheme.surface.withValues(alpha: 0.96),
|
||||
theme.colorScheme.surface.withValues(alpha: 0.75),
|
||||
theme.colorScheme.surface.withValues(alpha: 0.1),
|
||||
],
|
||||
stops: const [0, 0.45, 1],
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 720),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (logo != null)
|
||||
SizedBox(
|
||||
height: 72,
|
||||
width: 320,
|
||||
child: JellyfinImage(
|
||||
client: scope.client,
|
||||
image: logo,
|
||||
fit: BoxFit.contain,
|
||||
alignment: Alignment.centerLeft,
|
||||
placeholder: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(s.name, style: t.headlineMedium)),
|
||||
),
|
||||
)
|
||||
else
|
||||
Text(s.name, style: t.headlineMedium),
|
||||
const SizedBox(height: 8),
|
||||
Text(meta, style: t.bodyMedium?.copyWith(color: Colors.grey)),
|
||||
if (s.overview != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
GestureDetector(
|
||||
onTap: () => setState(() => _more = !_more),
|
||||
child: Text(s.overview!,
|
||||
maxLines: _more ? null : 3,
|
||||
overflow: _more ? null : TextOverflow.ellipsis,
|
||||
style: t.bodyMedium),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 14),
|
||||
Wrap(spacing: 8, runSpacing: 8, children: [
|
||||
FilledButton.icon(
|
||||
key: const ValueKey('series-next'),
|
||||
onPressed: next == null ? null : () => scope.onSelect(next),
|
||||
icon: Icon(selectedNext ? Icons.check : Icons.play_arrow),
|
||||
label: Text(nextLabel, overflow: TextOverflow.ellipsis),
|
||||
),
|
||||
]),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Episodes of one season as a lazy grid of rows: one column, more past
|
||||
/// ~760 px each.
|
||||
class _EpisodeList extends StatefulWidget {
|
||||
final String seriesId;
|
||||
final String seasonId;
|
||||
final int version;
|
||||
const _EpisodeList(
|
||||
{super.key, required this.seriesId, required this.seasonId, required this.version});
|
||||
|
||||
@override
|
||||
State<_EpisodeList> createState() => _EpisodeListState();
|
||||
}
|
||||
|
||||
class _EpisodeListState extends State<_EpisodeList> {
|
||||
Future<List<JellyfinItem>>? _future;
|
||||
List<JellyfinItem>? _last;
|
||||
|
||||
@override
|
||||
void didUpdateWidget(_EpisodeList old) {
|
||||
super.didUpdateWidget(old);
|
||||
if (old.version != widget.version) _future = null;
|
||||
}
|
||||
|
||||
void _load(BrowseScope scope) => _future = scope.load('episodes:${widget.seriesId}:${widget.seasonId}',
|
||||
(c) => c.episodes(widget.seriesId, seasonId: widget.seasonId));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
if (_future == null) _load(scope);
|
||||
return FutureBuilder<List<JellyfinItem>>(
|
||||
future: _future,
|
||||
builder: (context, snap) {
|
||||
if (snap.hasError) {
|
||||
return SliverToBoxAdapter(
|
||||
child: LoadError(error: snap.error!, onRetry: () => setState(() => _load(scope))));
|
||||
}
|
||||
final eps = snap.data ?? _last;
|
||||
if (snap.data != null) _last = snap.data;
|
||||
if (eps == null) {
|
||||
return const SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(32),
|
||||
child: Center(child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (eps.isEmpty) {
|
||||
return const SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Text('No episodes', style: TextStyle(color: Colors.grey)),
|
||||
),
|
||||
);
|
||||
}
|
||||
return SliverGrid(
|
||||
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: 760,
|
||||
mainAxisExtent: episodeTileHeight,
|
||||
crossAxisSpacing: 12,
|
||||
mainAxisSpacing: 8,
|
||||
),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, i) => EpisodeTile(episode: eps[i]),
|
||||
childCount: eps.length,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const episodeTileHeight = 6 + 176 * 9 / 16 + 6 + 2;
|
||||
|
||||
/// One episode: thumbnail with progress, number + title, runtime / air
|
||||
/// date, two lines of overview. Click selects it (details panel), a second
|
||||
/// click soon after puts it up.
|
||||
class EpisodeTile extends StatefulWidget {
|
||||
final JellyfinItem episode;
|
||||
const EpisodeTile({super.key, required this.episode});
|
||||
|
||||
@override
|
||||
State<EpisodeTile> createState() => _EpisodeTileState();
|
||||
}
|
||||
|
||||
class _EpisodeTileState extends State<EpisodeTile> {
|
||||
bool _focus = false;
|
||||
bool _hover = false;
|
||||
DateTime? _lastTap;
|
||||
|
||||
void _tap(BrowseScope scope) {
|
||||
final now = DateTime.now();
|
||||
final last = _lastTap;
|
||||
_lastTap = now;
|
||||
if (last != null && now.difference(last) < doubleClickTime) {
|
||||
_lastTap = null;
|
||||
scope.onPutUp(widget.episode);
|
||||
} else {
|
||||
scope.onSelect(widget.episode);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final scope = BrowseScope.of(context);
|
||||
final theme = Theme.of(context);
|
||||
final scheme = theme.colorScheme;
|
||||
final t = theme.textTheme;
|
||||
final e = widget.episode;
|
||||
final selected = scope.selectedItemId == e.id;
|
||||
final played = e.userData.played;
|
||||
final progress = progressOf(e);
|
||||
final meta = [
|
||||
?e.episodeLabel,
|
||||
?timeLeft(e),
|
||||
if (timeLeft(e) == null && e.runTime != null) formatRuntime(e.runTime!),
|
||||
if (e.premiereDate != null)
|
||||
'${e.premiereDate!.year}-${e.premiereDate!.month.toString().padLeft(2, '0')}-${e.premiereDate!.day.toString().padLeft(2, '0')}',
|
||||
].join(' · ');
|
||||
return Material(
|
||||
color: selected
|
||||
? scheme.primaryContainer.withValues(alpha: 0.35)
|
||||
: _hover || _focus
|
||||
? scheme.surfaceContainerHigh
|
||||
: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
side: BorderSide(
|
||||
color: selected ? scheme.primary : _focus ? scheme.onSurface : Colors.transparent,
|
||||
width: 1.5),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
key: ValueKey('episode-${e.id}'),
|
||||
focusColor: Colors.transparent,
|
||||
onTap: () => _tap(scope),
|
||||
onSecondaryTap: () => scope.cardMenu(context, widget.episode),
|
||||
onHover: (h) => setState(() => _hover = h),
|
||||
onFocusChange: (f) => setState(() => _focus = f),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 176,
|
||||
child: AspectRatio(
|
||||
aspectRatio: 16 / 9,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: Stack(fit: StackFit.expand, children: [
|
||||
JellyfinImage(
|
||||
client: scope.client,
|
||||
image: e.ownImage(JellyfinImageType.primary) ??
|
||||
e.image(JellyfinImageType.thumb) ??
|
||||
e.image(JellyfinImageType.backdrop),
|
||||
icon: Icons.tv_outlined,
|
||||
),
|
||||
if (progress > 0)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: LinearProgressIndicator(
|
||||
value: progress, minHeight: 3, backgroundColor: Colors.black54),
|
||||
),
|
||||
if (played || selected)
|
||||
Positioned(
|
||||
top: 4,
|
||||
right: 4,
|
||||
child: CircleAvatar(
|
||||
radius: 10,
|
||||
backgroundColor: selected ? scheme.primary : const Color(0xCC1B5E20),
|
||||
child: Icon(Icons.check,
|
||||
size: 13, color: selected ? scheme.onPrimary : Colors.white),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
e.indexNumber == null ? e.name : '${e.indexNumber}. ${e.name}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.titleSmall?.copyWith(
|
||||
color: selected ? scheme.primary : played ? Colors.grey : null,
|
||||
),
|
||||
),
|
||||
Text(meta, style: t.bodySmall?.copyWith(color: Colors.grey)),
|
||||
if (e.overview != null) ...[
|
||||
const SizedBox(height: 4),
|
||||
Text(e.overview!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: t.bodySmall?.copyWith(color: scheme.onSurfaceVariant)),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../screens/home/picked_media.dart';
|
||||
import 'accounts.dart';
|
||||
import 'format.dart';
|
||||
import '../library/media_refs.dart';
|
||||
|
||||
// Jellyfin media in a session: turning picks and pasted links into refs
|
||||
// (the wire carries only `{serverId, itemId, ...}`), the hosted server's
|
||||
// relay credential, and how this viewer plays a ref (own account, relay,
|
||||
// or neither).
|
||||
|
||||
/// The wire ref of a browser pick.
|
||||
JellyfinRef refForPick(JellyfinMedia m) => JellyfinRef(
|
||||
serverId: m.serverId,
|
||||
itemId: m.itemId,
|
||||
mediaSourceId: m.mediaSourceId,
|
||||
title: m.title,
|
||||
subtitle: m.subtitle.isEmpty ? null : m.subtitle,
|
||||
runtimeSecs: m.runtime == null ? null : m.runtime!.inMilliseconds / 1000,
|
||||
);
|
||||
|
||||
/// The `swap` media for a browser pick: a ref, never a URL.
|
||||
HelloMedia mediaForPick(JellyfinMedia m) => HelloMedia(
|
||||
name: m.title.isEmpty ? 'Jellyfin item' : m.title,
|
||||
size: 0,
|
||||
duration: 0,
|
||||
jellyfin: refForPick(m),
|
||||
ref: m.ref ?? jellyfinPickRef(m.title, m.subtitle));
|
||||
|
||||
/// The pick a ref stands for on a linked server (for highlighting it in
|
||||
/// the browser); null when this install has no account there.
|
||||
JellyfinMedia? pickForRef(JellyfinAccounts accounts, JellyfinRef ref) {
|
||||
final a = accounts.account(ref.serverId);
|
||||
if (a == null) return null;
|
||||
return JellyfinMedia(
|
||||
serverId: ref.serverId,
|
||||
baseUrl: a.baseUrl,
|
||||
itemId: ref.itemId,
|
||||
mediaSourceId: ref.mediaSourceId,
|
||||
title: ref.title,
|
||||
subtitle: ref.subtitle ?? '',
|
||||
runtime: ref.runtimeSecs == null
|
||||
? null
|
||||
: Duration(milliseconds: (ref.runtimeSecs! * 1000).round()),
|
||||
);
|
||||
}
|
||||
|
||||
/// The ref in a `state.media` map, or null for other media.
|
||||
JellyfinRef? refOfStateMedia(Map<String, Object?>? media) {
|
||||
final jf = media?['jellyfin'];
|
||||
if (jf is! Map) return null;
|
||||
try {
|
||||
final ref = JellyfinRef.fromJson(Map<String, Object?>.from(jf));
|
||||
return ref.serverId.isEmpty || ref.itemId.isEmpty ? null : ref;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Same item (server, item, source); titles may differ.
|
||||
bool sameJellyfinItem(JellyfinRef? a, JellyfinRef? b) =>
|
||||
a != null &&
|
||||
b != null &&
|
||||
a.serverId == b.serverId &&
|
||||
a.itemId == b.itemId &&
|
||||
a.mediaSourceId == b.mediaSourceId;
|
||||
|
||||
final _sourceId = RegExp(r'^[A-Za-z0-9-]{1,64}$');
|
||||
|
||||
/// What a pasted link becomes on the wire. A recognised Jellyfin item link
|
||||
/// (`parseJellyfinLink`) becomes a ref when its ServerId is known (in the
|
||||
/// link or from `/System/Info/Public`); its `api_key` is never shared then.
|
||||
/// Anything else, or a server that does not answer, stays a plain link.
|
||||
/// The title comes from this install's account on that server when there
|
||||
/// is one.
|
||||
Future<HelloMedia> mediaForLink(JellyfinAccounts accounts, String url,
|
||||
{Duration timeout = const Duration(seconds: 6)}) async {
|
||||
final name = linkName(url);
|
||||
final plain = HelloMedia(name: name, size: 0, duration: 0, url: url, ref: linkMediaRef(name));
|
||||
final link = parseJellyfinLink(url);
|
||||
if (link == null) return plain;
|
||||
await accounts.ensureLoaded();
|
||||
var serverId = link.serverId;
|
||||
if (serverId == null || serverId.isEmpty) {
|
||||
final probe = accounts.anonymousClient(link.baseUrl);
|
||||
try {
|
||||
serverId = (await probe.publicInfo().timeout(timeout)).id;
|
||||
} catch (e) {
|
||||
debugPrint('jellyfin link: no server id from ${link.baseUrl}: $e');
|
||||
return plain;
|
||||
} finally {
|
||||
probe.close();
|
||||
}
|
||||
if (serverId.isEmpty) return plain;
|
||||
}
|
||||
final src = Uri.tryParse(url)?.queryParameters['mediaSourceId'];
|
||||
var ref = JellyfinRef(
|
||||
serverId: serverId,
|
||||
itemId: link.itemId,
|
||||
mediaSourceId: src != null && _sourceId.hasMatch(src) && src != link.itemId ? src : null,
|
||||
);
|
||||
final account = accounts.account(serverId);
|
||||
final client = accounts.clientFor(serverId);
|
||||
MediaRef? what;
|
||||
if (account != null && client != null) {
|
||||
try {
|
||||
final pick = pickFor(account, await client.item(link.itemId).timeout(timeout));
|
||||
what = pick.ref;
|
||||
ref = refForPick(JellyfinMedia(
|
||||
serverId: serverId,
|
||||
baseUrl: account.baseUrl,
|
||||
itemId: link.itemId,
|
||||
mediaSourceId: ref.mediaSourceId,
|
||||
title: pick.title,
|
||||
subtitle: pick.subtitle,
|
||||
runtime: pick.runtime,
|
||||
));
|
||||
} catch (e) {
|
||||
if (e is JellyfinException && e.isUnauthorized) accounts.markExpired(serverId);
|
||||
}
|
||||
}
|
||||
return HelloMedia(
|
||||
name: ref.title.isEmpty ? 'Jellyfin item' : ref.title,
|
||||
size: 0,
|
||||
duration: 0,
|
||||
jellyfin: ref,
|
||||
ref: what ?? jellyfinPickRef(ref.title, ref.subtitle ?? ''));
|
||||
}
|
||||
|
||||
/// Display name for a link: last path segment, decoded, never the query
|
||||
/// (Jellyfin-style links carry api_key there and names are broadcast).
|
||||
String linkName(String url) {
|
||||
final uri = Uri.tryParse(url.trim());
|
||||
if (uri == null) return 'link';
|
||||
final segs = uri.pathSegments.where((s) => s.isNotEmpty).toList();
|
||||
if (segs.isNotEmpty) {
|
||||
try {
|
||||
return Uri.decodeComponent(segs.last);
|
||||
} catch (_) {
|
||||
return segs.last;
|
||||
}
|
||||
}
|
||||
return uri.host.isNotEmpty ? uri.host : 'link';
|
||||
}
|
||||
|
||||
/// The hosted server's relay logins: one per linked Jellyfin account
|
||||
/// whose token is not known to be expired (the default account first),
|
||||
/// so `/j` relays an item with its own server's login. The device fields
|
||||
/// are exactly the ones this app sends with those tokens
|
||||
/// ([JellyfinAccounts.clientInfo]): Jellyfin rewrites a token's device
|
||||
/// from the request header, so the relay must not differ.
|
||||
List<JellyfinCredential> relayCredentialsFor(JellyfinAccounts accounts) {
|
||||
final info = accounts.clientInfo;
|
||||
final first = accounts.defaultAccount;
|
||||
return [
|
||||
for (final a in [?first, ...accounts.accounts.where((a) => a.serverId != first?.serverId)])
|
||||
if (accounts.statusOf(a.serverId) != JellyfinAccountStatus.expired)
|
||||
JellyfinCredential(
|
||||
baseUrl: a.baseUrl,
|
||||
serverId: a.serverId,
|
||||
token: a.token,
|
||||
client: info.client,
|
||||
device: info.device,
|
||||
deviceId: info.deviceId,
|
||||
version: info.version,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/// `/j/...` URL of the current Jellyfin media on the host this client
|
||||
/// dialled, built like the `/m/...` one.
|
||||
String relayUrlFor(String host, int port, String token, String itemId) =>
|
||||
'http://$host:$port/j/default/$token/${Uri.encodeComponent(itemId)}';
|
||||
|
||||
// ---------------------------------------------------------------- playing
|
||||
|
||||
/// How this viewer plays a ref.
|
||||
sealed class JellyfinPlan {
|
||||
const JellyfinPlan();
|
||||
|
||||
/// `report.jf` for this plan; null when it plays nothing.
|
||||
bool? get jfAccess;
|
||||
}
|
||||
|
||||
/// Direct play with this install's account: the static stream, the token
|
||||
/// in [headers] (not in the URL), progress reported per [info].
|
||||
final class OwnPlay extends JellyfinPlan {
|
||||
final JellyfinClient client;
|
||||
final JellyfinAccount account;
|
||||
final JellyfinPlaybackInfo info;
|
||||
final JellyfinMediaSource source;
|
||||
/// Full item (series, episode numbers); null if that call failed.
|
||||
final JellyfinItem? item;
|
||||
final String url;
|
||||
final Map<String, String> headers;
|
||||
const OwnPlay({
|
||||
required this.client,
|
||||
required this.account,
|
||||
required this.info,
|
||||
required this.source,
|
||||
required this.item,
|
||||
required this.url,
|
||||
required this.headers,
|
||||
});
|
||||
|
||||
@override
|
||||
bool get jfAccess => true;
|
||||
}
|
||||
|
||||
/// Through the server: its own Jellyfin login (`/j/...`) or the member
|
||||
/// who put it up (`/r/...`).
|
||||
final class RelayPlay extends JellyfinPlan {
|
||||
final String url;
|
||||
const RelayPlay(this.url);
|
||||
|
||||
@override
|
||||
bool get jfAccess => false;
|
||||
}
|
||||
|
||||
/// Neither: no (usable) account here and nothing relays it.
|
||||
final class BlockedPlay extends JellyfinPlan {
|
||||
final String serverId;
|
||||
/// Known only when this install has (had) an account there.
|
||||
final String? serverName;
|
||||
/// Why the own account did not work, if there is one.
|
||||
final String? problem;
|
||||
const BlockedPlay({required this.serverId, this.serverName, this.problem});
|
||||
|
||||
@override
|
||||
bool? get jfAccess => null;
|
||||
|
||||
String get message {
|
||||
final where = serverName == null || serverName!.isEmpty ? 'that Jellyfin server' : serverName!;
|
||||
final base = 'No Jellyfin account here for $where, and nobody is passing it on';
|
||||
return problem == null ? base : '$base ($problem)';
|
||||
}
|
||||
}
|
||||
|
||||
/// Picks how to play [ref]: this install's account first (PlaybackInfo
|
||||
/// with its own user; a 401 marks the account expired), else the server's
|
||||
/// own Jellyfin login ([relay] = `state.relay`, [relayUrl] this member's
|
||||
/// `/j/...` URL), else the member who put it up ([memberRelayUrl], the
|
||||
/// `/r/...` URL when `media.relay` is set), else [BlockedPlay].
|
||||
Future<JellyfinPlan> resolveJellyfinRef(
|
||||
JellyfinAccounts accounts,
|
||||
JellyfinRef ref, {
|
||||
required bool relay,
|
||||
required String? relayUrl,
|
||||
String? memberRelayUrl,
|
||||
Duration timeout = const Duration(seconds: 15),
|
||||
}) async {
|
||||
await accounts.ensureLoaded();
|
||||
final account = accounts.account(ref.serverId);
|
||||
String? problem;
|
||||
if (account != null && accounts.statusOf(ref.serverId) == JellyfinAccountStatus.expired) {
|
||||
problem = 'your sign-in expired, reconnect it in Integrations';
|
||||
} else if (account != null) {
|
||||
final client = accounts.clientFor(ref.serverId)!;
|
||||
try {
|
||||
final infoF = client.playbackInfo(ref.itemId, mediaSourceId: ref.mediaSourceId).timeout(timeout);
|
||||
final itemF = client
|
||||
.item(ref.itemId)
|
||||
.timeout(timeout)
|
||||
.then<JellyfinItem?>((i) => i, onError: (Object _) => null);
|
||||
final info = await infoF;
|
||||
final item = await itemF;
|
||||
final source = (ref.mediaSourceId == null
|
||||
? null
|
||||
: info.mediaSources.where((s) => s.id == ref.mediaSourceId).firstOrNull) ??
|
||||
info.primarySource;
|
||||
if (source == null) throw const JellyfinException('no playable source');
|
||||
return OwnPlay(
|
||||
client: client,
|
||||
account: account,
|
||||
info: info,
|
||||
source: source,
|
||||
item: item,
|
||||
url: client.shareableStreamUrl(ref.itemId, mediaSourceId: source.id).toString(),
|
||||
headers: client.authHeaders,
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('jellyfin resolve ${ref.itemId} with own account failed: $e');
|
||||
if (e is JellyfinException && e.isUnauthorized) {
|
||||
accounts.markExpired(ref.serverId);
|
||||
problem = 'your sign-in expired, reconnect it in Integrations';
|
||||
} else if (e is JellyfinException && e.statusCode == 404) {
|
||||
problem = 'your account cannot see this item';
|
||||
} else {
|
||||
problem = 'could not reach it';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (relay && relayUrl != null && relayUrl.isNotEmpty) return RelayPlay(relayUrl);
|
||||
if (memberRelayUrl != null && memberRelayUrl.isNotEmpty) return RelayPlay(memberRelayUrl);
|
||||
return BlockedPlay(serverId: ref.serverId, serverName: account?.displayName, problem: problem);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ next episode
|
||||
|
||||
/// A neighbouring episode as this viewer can put it up.
|
||||
class EpisodeLink {
|
||||
final JellyfinItem item;
|
||||
final JellyfinMedia pick;
|
||||
const EpisodeLink(this.item, this.pick);
|
||||
|
||||
/// "S1E7 Battle with the Heroes".
|
||||
String get label => [?item.episodeLabel, item.name].join(' ');
|
||||
}
|
||||
|
||||
/// The episodes before and after the one [plan] plays, with its account.
|
||||
/// Both null for movies, at the ends of a series, or on failure.
|
||||
Future<({EpisodeLink? previous, EpisodeLink? next})> findAdjacentEpisodes(OwnPlay plan,
|
||||
{Duration timeout = const Duration(seconds: 15)}) async {
|
||||
const none = (previous: null, next: null);
|
||||
final item = plan.item;
|
||||
if (item == null || item.kind != JellyfinItemKind.episode || item.seriesId == null) return none;
|
||||
try {
|
||||
final around = await plan.client.adjacentEpisodes(item).timeout(timeout);
|
||||
EpisodeLink? link(JellyfinItem? i) => i == null ? null : EpisodeLink(i, pickFor(plan.account, i));
|
||||
return (previous: link(around.previous), next: link(around.next));
|
||||
} catch (e) {
|
||||
debugPrint('episode lookup failed: $e');
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
||||
/// Where the "Next episode" pill's window starts: at [endingStart] (the
|
||||
/// ED: Jellyfin Outro segment or ED-titled chapter, see `endingRange`)
|
||||
/// when one is known inside [runtime], else the last two minutes of
|
||||
/// [runtime] (all of it for shorter media). The pill shows only while the
|
||||
/// controls are up (`PillGate`), so a guessed window costs nothing.
|
||||
Duration nextPromptStart(JellyfinItem? item, Duration runtime, {Duration? endingStart}) {
|
||||
if (endingStart != null && endingStart > Duration.zero && endingStart < runtime) {
|
||||
return endingStart;
|
||||
}
|
||||
const lead = Duration(minutes: 2);
|
||||
return runtime > lead ? runtime - lead : Duration.zero;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'accounts.dart';
|
||||
|
||||
enum JellyfinSignInStep {
|
||||
/// Typing the server address.
|
||||
address,
|
||||
probing,
|
||||
/// Server found: choose Quick Connect or password.
|
||||
method,
|
||||
/// Code shown, polling until the user approves it in Jellyfin.
|
||||
quickConnect,
|
||||
password,
|
||||
signingIn,
|
||||
/// Linked; [JellyfinSignIn.linked] is the account.
|
||||
done,
|
||||
}
|
||||
|
||||
/// Add-server / reconnect flow: address -> /System/Info/Public -> Quick
|
||||
/// Connect (code + poll, cancellable) or username/password -> linked in
|
||||
/// [JellyfinAccounts]. UI-free so tests drive it with a fake transport.
|
||||
class JellyfinSignIn extends ChangeNotifier {
|
||||
JellyfinSignIn(this.accounts, {this.pollInterval = const Duration(seconds: 3), this.reconnect});
|
||||
|
||||
final JellyfinAccounts accounts;
|
||||
final Duration pollInterval;
|
||||
/// Set when re-signing an expired account: the address is prefilled.
|
||||
final JellyfinAccount? reconnect;
|
||||
|
||||
JellyfinSignInStep _step = JellyfinSignInStep.address;
|
||||
String? _error;
|
||||
JellyfinServerInfo? _server;
|
||||
bool _quickConnectAvailable = false;
|
||||
String? _code;
|
||||
JellyfinAccount? _linked;
|
||||
JellyfinClient? _client;
|
||||
int _gen = 0;
|
||||
bool _disposed = false;
|
||||
|
||||
JellyfinSignInStep get step => _step;
|
||||
String? get error => _error;
|
||||
JellyfinServerInfo? get server => _server;
|
||||
String? get baseUrl => _client?.baseUrl;
|
||||
bool get quickConnectAvailable => _quickConnectAvailable;
|
||||
/// The Quick Connect code to show.
|
||||
String? get code => _code;
|
||||
JellyfinAccount? get linked => _linked;
|
||||
bool get busy =>
|
||||
_step == JellyfinSignInStep.probing || _step == JellyfinSignInStep.signingIn;
|
||||
|
||||
void _set(JellyfinSignInStep s, {String? error}) {
|
||||
_step = s;
|
||||
_error = error;
|
||||
if (!_disposed) notifyListeners();
|
||||
}
|
||||
|
||||
/// Checks [input] is a Jellyfin server and whether Quick Connect is on.
|
||||
Future<void> probe(String input) async {
|
||||
final url = normalizeServerUrl(input);
|
||||
if (url == null) {
|
||||
_set(JellyfinSignInStep.address, error: 'Enter the server address, e.g. jellyfin.example.com');
|
||||
return;
|
||||
}
|
||||
final gen = ++_gen;
|
||||
_client?.close();
|
||||
final client = _client = accounts.anonymousClient(url);
|
||||
_set(JellyfinSignInStep.probing);
|
||||
try {
|
||||
final info = await client.publicInfo();
|
||||
if (gen != _gen) return;
|
||||
if (info.id.isEmpty) throw const JellyfinException('not a Jellyfin server');
|
||||
if (reconnect != null && info.id != reconnect!.serverId) {
|
||||
_set(JellyfinSignInStep.address,
|
||||
error: 'That address is a different Jellyfin server (${info.name}).');
|
||||
return;
|
||||
}
|
||||
var qc = false;
|
||||
try {
|
||||
qc = await client.quickConnectEnabled();
|
||||
} catch (_) {}
|
||||
if (gen != _gen) return;
|
||||
_server = info;
|
||||
_quickConnectAvailable = qc;
|
||||
_set(JellyfinSignInStep.method);
|
||||
} catch (e) {
|
||||
if (gen != _gen) return;
|
||||
_set(JellyfinSignInStep.address, error: 'No Jellyfin server at $url (${_short(e)})');
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts Quick Connect: shows the code, polls until approved, links.
|
||||
Future<void> startQuickConnect() async {
|
||||
final client = _client;
|
||||
if (client == null || _server == null) return;
|
||||
final gen = ++_gen;
|
||||
_code = null;
|
||||
_set(JellyfinSignInStep.quickConnect);
|
||||
try {
|
||||
final session = await client.quickConnectInitiate();
|
||||
if (gen != _gen) return;
|
||||
_code = session.code;
|
||||
_set(JellyfinSignInStep.quickConnect);
|
||||
final auth = await client.waitForQuickConnect(session,
|
||||
interval: pollInterval, isCancelled: () => gen != _gen || _disposed);
|
||||
if (auth == null || gen != _gen) return;
|
||||
await _finish(auth);
|
||||
} on TimeoutException {
|
||||
if (gen == _gen) _set(JellyfinSignInStep.method, error: 'The code expired. Try again.');
|
||||
} catch (e) {
|
||||
if (gen != _gen) return;
|
||||
final msg = e is JellyfinException && e.isUnauthorized
|
||||
? 'Quick Connect is turned off on this server. Use your password.'
|
||||
: e is JellyfinException && e.statusCode == 404
|
||||
? 'The code expired. Try again.'
|
||||
: 'Quick Connect failed: ${_short(e)}';
|
||||
_set(JellyfinSignInStep.method, error: msg);
|
||||
}
|
||||
}
|
||||
|
||||
/// Stops waiting for the Quick Connect code.
|
||||
void cancel() {
|
||||
_gen++;
|
||||
_code = null;
|
||||
_set(_server == null ? JellyfinSignInStep.address : JellyfinSignInStep.method);
|
||||
}
|
||||
|
||||
void usePassword() => _set(JellyfinSignInStep.password);
|
||||
|
||||
/// Back to the address field.
|
||||
void changeAddress() {
|
||||
_gen++;
|
||||
_server = null;
|
||||
_code = null;
|
||||
_set(JellyfinSignInStep.address);
|
||||
}
|
||||
|
||||
Future<void> signIn(String username, String password) async {
|
||||
final client = _client;
|
||||
if (client == null) return;
|
||||
if (username.trim().isEmpty) {
|
||||
_set(JellyfinSignInStep.password, error: 'Enter your Jellyfin username');
|
||||
return;
|
||||
}
|
||||
final gen = ++_gen;
|
||||
_set(JellyfinSignInStep.signingIn);
|
||||
try {
|
||||
final auth = await client.authenticateByName(username.trim(), password);
|
||||
if (gen != _gen) return;
|
||||
await _finish(auth);
|
||||
} catch (e) {
|
||||
if (gen != _gen) return;
|
||||
_set(JellyfinSignInStep.password,
|
||||
error: e is JellyfinException && e.isUnauthorized
|
||||
? 'Wrong username or password'
|
||||
: 'Sign-in failed: ${_short(e)}');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _finish(JellyfinAuthResult auth) async {
|
||||
final server = _server!;
|
||||
if (auth.accessToken.isEmpty) throw const JellyfinException('no token in the answer');
|
||||
_linked = await accounts.link(baseUrl: _client!.baseUrl, server: server, auth: auth);
|
||||
_code = null;
|
||||
_set(JellyfinSignInStep.done);
|
||||
}
|
||||
|
||||
static String _short(Object e) {
|
||||
final s = '$e'.replaceFirst(RegExp(r'^JellyfinException( \d+)?: '), '');
|
||||
return s.length > 140 ? '${s.substring(0, 140)}…' : s;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
_gen++;
|
||||
_client?.close();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../screens/home/ui.dart';
|
||||
import 'accounts.dart';
|
||||
import 'sign_in.dart';
|
||||
|
||||
/// Add a Jellyfin server (or reconnect an expired one): address, then Quick
|
||||
/// Connect (big code, approve it in Jellyfin) or username and password.
|
||||
class JellyfinSignInPanel extends StatefulWidget {
|
||||
final JellyfinAccounts accounts;
|
||||
final JellyfinAccount? reconnect;
|
||||
final ValueChanged<JellyfinAccount>? onDone;
|
||||
final VoidCallback? onCancel;
|
||||
final Duration pollInterval;
|
||||
const JellyfinSignInPanel({
|
||||
super.key,
|
||||
required this.accounts,
|
||||
this.reconnect,
|
||||
this.onDone,
|
||||
this.onCancel,
|
||||
this.pollInterval = const Duration(seconds: 3),
|
||||
});
|
||||
|
||||
@override
|
||||
State<JellyfinSignInPanel> createState() => _JellyfinSignInPanelState();
|
||||
}
|
||||
|
||||
class _JellyfinSignInPanelState extends State<JellyfinSignInPanel> {
|
||||
late final JellyfinSignIn _flow =
|
||||
JellyfinSignIn(widget.accounts, pollInterval: widget.pollInterval, reconnect: widget.reconnect);
|
||||
late final _address = TextEditingController(text: widget.reconnect?.baseUrl ?? '');
|
||||
late final _user = TextEditingController(text: widget.reconnect?.userName ?? '');
|
||||
final _password = TextEditingController();
|
||||
bool _reported = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_flow.addListener(_changed);
|
||||
if (widget.reconnect != null) _flow.probe(widget.reconnect!.baseUrl);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_flow.removeListener(_changed);
|
||||
_flow.dispose();
|
||||
_address.dispose();
|
||||
_user.dispose();
|
||||
_password.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _changed() {
|
||||
if (!mounted) return;
|
||||
setState(() {});
|
||||
final linked = _flow.linked;
|
||||
if (_flow.step == JellyfinSignInStep.done && linked != null && !_reported) {
|
||||
_reported = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => widget.onDone?.call(linked));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
final f = _flow;
|
||||
final body = switch (f.step) {
|
||||
JellyfinSignInStep.address || JellyfinSignInStep.probing => _addressStep(),
|
||||
JellyfinSignInStep.method => _methodStep(),
|
||||
JellyfinSignInStep.quickConnect => _quickConnectStep(),
|
||||
JellyfinSignInStep.password || JellyfinSignInStep.signingIn => _passwordStep(),
|
||||
JellyfinSignInStep.done => Row(children: [
|
||||
const Icon(Icons.check_circle, color: Colors.green),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text('Linked as ${f.linked?.userName} on ${f.linked?.displayName}',
|
||||
key: const ValueKey('jf-linked'))),
|
||||
]),
|
||||
};
|
||||
return Column(
|
||||
key: const ValueKey('jf-sign-in'),
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(widget.reconnect == null ? 'Add a Jellyfin server' : 'Reconnect ${widget.reconnect!.displayName}',
|
||||
style: t.titleMedium),
|
||||
const SizedBox(height: 12),
|
||||
if (f.server != null && f.step != JellyfinSignInStep.address && f.step != JellyfinSignInStep.done)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: _ServerLine(
|
||||
name: f.server!.name,
|
||||
version: f.server!.version,
|
||||
url: f.baseUrl ?? '',
|
||||
onChange: widget.reconnect == null ? f.changeAddress : null,
|
||||
),
|
||||
),
|
||||
body,
|
||||
if (f.error != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: Text(f.error!,
|
||||
key: const ValueKey('jf-sign-in-error'),
|
||||
style: TextStyle(color: Theme.of(context).colorScheme.error)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _cancelButton() => widget.onCancel == null
|
||||
? const SizedBox.shrink()
|
||||
: TextButton(onPressed: widget.onCancel, child: const Text('Cancel'));
|
||||
|
||||
Widget _addressStep() {
|
||||
final probing = _flow.step == JellyfinSignInStep.probing;
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
key: const ValueKey('jf-address'),
|
||||
controller: _address,
|
||||
autofocus: true,
|
||||
enabled: !probing,
|
||||
decoration: fieldDecoration('Server address', hint: 'jellyfin.example.com'),
|
||||
keyboardType: TextInputType.url,
|
||||
onSubmitted: (v) => _flow.probe(v),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
FilledButton(
|
||||
key: const ValueKey('jf-connect'),
|
||||
onPressed: probing ? null : () => _flow.probe(_address.text),
|
||||
child: probing
|
||||
? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2))
|
||||
: const Text('Connect'),
|
||||
),
|
||||
_cancelButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _methodStep() {
|
||||
return Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
if (_flow.quickConnectAvailable)
|
||||
FilledButton.icon(
|
||||
key: const ValueKey('jf-quick-connect'),
|
||||
onPressed: _flow.startQuickConnect,
|
||||
icon: const Icon(Icons.qr_code_2, size: 18),
|
||||
label: const Text('Quick Connect'),
|
||||
),
|
||||
if (_flow.quickConnectAvailable)
|
||||
OutlinedButton.icon(
|
||||
key: const ValueKey('jf-use-password'),
|
||||
onPressed: _flow.usePassword,
|
||||
icon: const Icon(Icons.password, size: 18),
|
||||
label: const Text('Username & password'),
|
||||
)
|
||||
else
|
||||
FilledButton.icon(
|
||||
key: const ValueKey('jf-use-password'),
|
||||
onPressed: _flow.usePassword,
|
||||
icon: const Icon(Icons.password, size: 18),
|
||||
label: const Text('Username & password'),
|
||||
),
|
||||
_cancelButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _quickConnectStep() {
|
||||
final scheme = Theme.of(context).colorScheme;
|
||||
final t = Theme.of(context).textTheme;
|
||||
final code = _flow.code;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (code == null)
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
else
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: scheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: SelectableText(
|
||||
code,
|
||||
key: const ValueKey('jf-qc-code'),
|
||||
style: t.displaySmall?.copyWith(
|
||||
fontFeatures: const [FontFeature.tabularFigures()],
|
||||
letterSpacing: 8,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
tooltip: 'Copy code',
|
||||
onPressed: () => Clipboard.setData(ClipboardData(text: code)),
|
||||
icon: const Icon(Icons.copy, size: 18),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const Text('Approve it in Jellyfin: Profile → Quick Connect, then enter this code.'),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
const SizedBox(width: 14, height: 14, child: CircularProgressIndicator(strokeWidth: 2)),
|
||||
const SizedBox(width: 10),
|
||||
const Text('Waiting for approval…', style: TextStyle(color: Colors.grey)),
|
||||
const SizedBox(width: 16),
|
||||
TextButton(
|
||||
key: const ValueKey('jf-qc-cancel'),
|
||||
onPressed: _flow.cancel,
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _passwordStep() {
|
||||
final busy = _flow.step == JellyfinSignInStep.signingIn;
|
||||
void submit() => _flow.signIn(_user.text, _password.text);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
TextField(
|
||||
key: const ValueKey('jf-username'),
|
||||
controller: _user,
|
||||
autofocus: true,
|
||||
enabled: !busy,
|
||||
decoration: fieldDecoration('Username'),
|
||||
onSubmitted: (_) => submit(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
TextField(
|
||||
key: const ValueKey('jf-password'),
|
||||
controller: _password,
|
||||
enabled: !busy,
|
||||
obscureText: true,
|
||||
decoration: fieldDecoration('Password'),
|
||||
onSubmitted: (_) => submit(),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
FilledButton(
|
||||
key: const ValueKey('jf-sign-in-submit'),
|
||||
onPressed: busy ? null : submit,
|
||||
child: busy
|
||||
? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2))
|
||||
: const Text('Sign in'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
if (_flow.quickConnectAvailable)
|
||||
TextButton(onPressed: _flow.cancel, child: const Text('Back')),
|
||||
_cancelButton(),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ServerLine extends StatelessWidget {
|
||||
final String name;
|
||||
final String version;
|
||||
final String url;
|
||||
final VoidCallback? onChange;
|
||||
const _ServerLine({required this.name, required this.version, required this.url, this.onChange});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Theme.of(context).textTheme;
|
||||
return Row(
|
||||
children: [
|
||||
Icon(Icons.dns_outlined, size: 20, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(name.isEmpty ? 'Jellyfin server' : name,
|
||||
key: const ValueKey('jf-server-name'), style: t.titleSmall),
|
||||
Text('Jellyfin $version · $url', style: t.bodySmall?.copyWith(color: Colors.grey)),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (onChange != null) TextButton(onPressed: onChange, child: const Text('Change')),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import 'accounts.dart';
|
||||
|
||||
// Per-viewer audio/subtitle carry-over: the last choice is kept per series
|
||||
// (and as a global fallback) and matched against the next Jellyfin item's
|
||||
// tracks with core's `matchTrack`. Local only; nothing goes on the wire.
|
||||
|
||||
const trackPrefsBoxName = 'track_prefs';
|
||||
const _keyGlobal = 'global';
|
||||
|
||||
/// One audio or subtitle track of the open file as mpv's `track-list`
|
||||
/// has it ([id] is mpv's `aid` / `sid`; [selected] is mpv's choice).
|
||||
class MpvTrack {
|
||||
final int id;
|
||||
final JellyfinStreamType type;
|
||||
final String? language;
|
||||
final String? title;
|
||||
final String? codec;
|
||||
final int? channels;
|
||||
final bool isDefault;
|
||||
final bool isForced;
|
||||
final bool isHearingImpaired;
|
||||
final bool isExternal;
|
||||
final bool selected;
|
||||
const MpvTrack({
|
||||
required this.id,
|
||||
required this.type,
|
||||
this.language,
|
||||
this.title,
|
||||
this.codec,
|
||||
this.channels,
|
||||
this.isDefault = false,
|
||||
this.isForced = false,
|
||||
this.isHearingImpaired = false,
|
||||
this.isExternal = false,
|
||||
this.selected = false,
|
||||
});
|
||||
|
||||
/// As a stream for [matchTrack]; its index is the mpv id.
|
||||
JellyfinMediaStream get asStream => JellyfinMediaStream(
|
||||
index: id,
|
||||
type: type,
|
||||
language: language,
|
||||
title: title,
|
||||
codec: codec,
|
||||
channels: channels,
|
||||
isDefault: isDefault,
|
||||
isForced: isForced,
|
||||
isHearingImpaired: isHearingImpaired);
|
||||
|
||||
/// Menu text: "Japanese · E-AC3 2.0 · Commentary", "Track 2 · ASS".
|
||||
String get label => [
|
||||
languageName(language) ?? 'Track $id',
|
||||
[?codecName(codec), ?channelLayoutName(channels)].join(' '),
|
||||
if (title != null && title != languageName(language)) title!,
|
||||
if (isForced) 'Forced',
|
||||
if (isHearingImpaired) 'SDH',
|
||||
].where((p) => p.isNotEmpty).join(' · ');
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
other is MpvTrack &&
|
||||
other.id == id &&
|
||||
other.type == type &&
|
||||
other.language == language &&
|
||||
other.title == title &&
|
||||
other.codec == codec &&
|
||||
other.channels == channels &&
|
||||
other.isDefault == isDefault &&
|
||||
other.isForced == isForced &&
|
||||
other.isHearingImpaired == isHearingImpaired &&
|
||||
other.isExternal == isExternal &&
|
||||
other.selected == selected;
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, type, language, title, codec, channels, isDefault, isForced,
|
||||
isHearingImpaired, isExternal, selected);
|
||||
|
||||
@override
|
||||
String toString() => 'MpvTrack(${type.name} $id ${selected ? '*' : ''}$label)';
|
||||
}
|
||||
|
||||
const _languages = {
|
||||
'jpn': 'Japanese', 'ja': 'Japanese', 'eng': 'English', 'en': 'English',
|
||||
'ger': 'German', 'deu': 'German', 'de': 'German', 'fre': 'French', 'fra': 'French',
|
||||
'fr': 'French', 'spa': 'Spanish', 'es': 'Spanish', 'ita': 'Italian', 'it': 'Italian',
|
||||
'por': 'Portuguese', 'pt': 'Portuguese', 'rus': 'Russian', 'ru': 'Russian',
|
||||
'chi': 'Chinese', 'zho': 'Chinese', 'zh': 'Chinese', 'kor': 'Korean', 'ko': 'Korean',
|
||||
'ara': 'Arabic', 'ar': 'Arabic', 'pol': 'Polish', 'pl': 'Polish', 'dut': 'Dutch',
|
||||
'nld': 'Dutch', 'nl': 'Dutch', 'swe': 'Swedish', 'sv': 'Swedish', 'fin': 'Finnish',
|
||||
'fi': 'Finnish', 'nor': 'Norwegian', 'no': 'Norwegian', 'dan': 'Danish', 'da': 'Danish',
|
||||
'tur': 'Turkish', 'tr': 'Turkish', 'hin': 'Hindi', 'hi': 'Hindi', 'tha': 'Thai',
|
||||
'th': 'Thai', 'vie': 'Vietnamese', 'vi': 'Vietnamese', 'ind': 'Indonesian', 'id': 'Indonesian',
|
||||
'may': 'Malay', 'msa': 'Malay', 'ms': 'Malay', 'heb': 'Hebrew', 'he': 'Hebrew',
|
||||
'gre': 'Greek', 'ell': 'Greek', 'el': 'Greek', 'cze': 'Czech', 'ces': 'Czech', 'cs': 'Czech',
|
||||
'hun': 'Hungarian', 'hu': 'Hungarian', 'ukr': 'Ukrainian', 'uk': 'Ukrainian',
|
||||
'rum': 'Romanian', 'ron': 'Romanian', 'ro': 'Romanian', 'und': 'Undetermined',
|
||||
};
|
||||
|
||||
/// "jpn" -> "Japanese"; other codes upper-cased, null for none.
|
||||
String? languageName(String? code) {
|
||||
if (code == null || code.isEmpty) return null;
|
||||
return _languages[code.toLowerCase()] ?? code.toUpperCase();
|
||||
}
|
||||
|
||||
const _codecs = {
|
||||
'eac3': 'E-AC3', 'ac3': 'AC3', 'aac': 'AAC', 'flac': 'FLAC', 'opus': 'Opus',
|
||||
'vorbis': 'Vorbis', 'mp3': 'MP3', 'truehd': 'TrueHD', 'dts': 'DTS', 'mlp': 'MLP',
|
||||
'alac': 'ALAC', 'ass': 'ASS', 'ssa': 'SSA', 'subrip': 'SRT', 'srt': 'SRT',
|
||||
'webvtt': 'VTT', 'mov_text': 'TX3G', 'hdmv_pgs_subtitle': 'PGS', 'pgssub': 'PGS',
|
||||
'dvd_subtitle': 'VobSub', 'dvdsub': 'VobSub', 'dvb_subtitle': 'DVB',
|
||||
};
|
||||
|
||||
/// mpv / Jellyfin codec name for menus: "eac3" -> "E-AC3", "subrip" -> "SRT".
|
||||
String? codecName(String? codec) {
|
||||
if (codec == null || codec.isEmpty) return null;
|
||||
final c = codec.toLowerCase();
|
||||
if (c.startsWith('pcm')) return 'PCM';
|
||||
return _codecs[c] ?? codec.toUpperCase();
|
||||
}
|
||||
|
||||
/// Channel count as a layout: 2 -> "2.0", 6 -> "5.1", 8 -> "7.1".
|
||||
String? channelLayoutName(int? channels) => switch (channels) {
|
||||
null || <= 0 => null,
|
||||
1 => '1.0',
|
||||
2 => '2.0',
|
||||
3 => '2.1',
|
||||
6 => '5.1',
|
||||
7 => '6.1',
|
||||
8 => '7.1',
|
||||
final n => '${n}ch',
|
||||
};
|
||||
|
||||
/// A viewer's audio/subtitle choice as traits (indices shift between
|
||||
/// files). [subtitlesOff] wins over [subtitle].
|
||||
class TrackChoice {
|
||||
final TrackPreference? audio;
|
||||
final TrackPreference? subtitle;
|
||||
final bool subtitlesOff;
|
||||
const TrackChoice({this.audio, this.subtitle, this.subtitlesOff = false});
|
||||
|
||||
Map<String, Object?> toJson() => {
|
||||
'audio': ?_prefToJson(audio),
|
||||
'subtitle': ?_prefToJson(subtitle),
|
||||
'subtitlesOff': subtitlesOff,
|
||||
};
|
||||
|
||||
static TrackChoice? fromJson(Object? j) {
|
||||
if (j is! Map) return null;
|
||||
return TrackChoice(
|
||||
audio: _prefFromJson(j['audio'], JellyfinStreamType.audio),
|
||||
subtitle: _prefFromJson(j['subtitle'], JellyfinStreamType.subtitle),
|
||||
subtitlesOff: j['subtitlesOff'] == true,
|
||||
);
|
||||
}
|
||||
|
||||
/// The choice behind mpv's [aid] / [sid] (null = none / off): traits from
|
||||
/// the Jellyfin [source] when this viewer has it (title, channels,
|
||||
/// forced/HI flags), else from mpv's [tracks].
|
||||
factory TrackChoice.of({
|
||||
required int? aid,
|
||||
required int? sid,
|
||||
JellyfinMediaSource? source,
|
||||
List<MpvTrack> tracks = const [],
|
||||
}) {
|
||||
TrackPreference? pref(JellyfinStreamType type, int? id) {
|
||||
if (id == null) return null;
|
||||
if (source != null) {
|
||||
final index = source.jellyfinIndexForMpvTrack(type, id);
|
||||
final s = index == null ? null : source.streamAt(index);
|
||||
if (s != null) return TrackPreference.fromStream(s);
|
||||
}
|
||||
final t = tracks.where((t) => t.type == type && t.id == id).firstOrNull;
|
||||
return t == null ? null : TrackPreference.fromStream(t.asStream);
|
||||
}
|
||||
|
||||
return TrackChoice(
|
||||
audio: pref(JellyfinStreamType.audio, aid),
|
||||
subtitle: pref(JellyfinStreamType.subtitle, sid),
|
||||
subtitlesOff: sid == null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object?>? _prefToJson(TrackPreference? p) => p == null
|
||||
? null
|
||||
: {
|
||||
'language': ?p.language,
|
||||
'title': ?p.title,
|
||||
'codec': ?p.codec,
|
||||
'channels': ?p.channels,
|
||||
if (p.isForced) 'forced': true,
|
||||
if (p.isHearingImpaired) 'hi': true,
|
||||
};
|
||||
|
||||
TrackPreference? _prefFromJson(Object? j, JellyfinStreamType type) {
|
||||
if (j is! Map) return null;
|
||||
String? s(Object? v) => v is String && v.isNotEmpty ? v : null;
|
||||
return TrackPreference(
|
||||
type: type,
|
||||
language: s(j['language']),
|
||||
title: s(j['title']),
|
||||
codec: s(j['codec']),
|
||||
channels: j['channels'] is int ? j['channels'] as int : null,
|
||||
isForced: j['forced'] == true,
|
||||
isHearingImpaired: j['hi'] == true,
|
||||
);
|
||||
}
|
||||
|
||||
/// mpv tracks to select for [choice] on a new item. Matches against the
|
||||
/// Jellyfin [source]'s streams when this viewer has them (mapped to mpv ids
|
||||
/// with [JellyfinMediaSource.mpvTrackId]), else against mpv's [tracks].
|
||||
/// Null fields keep the player's default; [subtitlesOff] turns them off.
|
||||
({int? aid, int? sid, bool subtitlesOff}) chooseTracks(TrackChoice choice,
|
||||
{JellyfinMediaSource? source, List<MpvTrack> tracks = const []}) {
|
||||
int? pick(TrackPreference? pref) {
|
||||
if (pref == null) return null;
|
||||
if (source != null) {
|
||||
final s = matchTrack(pref, source.mediaStreams);
|
||||
return s == null ? null : source.mpvTrackId(s.index);
|
||||
}
|
||||
return matchTrack(pref, [for (final t in tracks) t.asStream])?.index;
|
||||
}
|
||||
|
||||
return (
|
||||
aid: pick(choice.audio),
|
||||
sid: choice.subtitlesOff ? null : pick(choice.subtitle),
|
||||
subtitlesOff: choice.subtitlesOff,
|
||||
);
|
||||
}
|
||||
|
||||
/// The last choice per series and overall, in their own Hive box.
|
||||
class TrackPrefs {
|
||||
TrackPrefs({JellyfinStore? store}) : _store = store ?? HiveJellyfinStore(boxName: trackPrefsBoxName);
|
||||
final JellyfinStore _store;
|
||||
Future<void>? _open;
|
||||
|
||||
Future<void> _ready() => _open ??= _store.open().catchError((Object e) {
|
||||
debugPrint('open track prefs failed: $e');
|
||||
});
|
||||
|
||||
/// The series' choice, else the global one.
|
||||
Future<TrackChoice?> load({String? seriesId}) async {
|
||||
await _ready();
|
||||
try {
|
||||
Object? read(String key) {
|
||||
final v = _store.get(key);
|
||||
return v is String ? jsonDecode(v) : null;
|
||||
}
|
||||
|
||||
return (seriesId == null ? null : TrackChoice.fromJson(read('series:$seriesId'))) ??
|
||||
TrackChoice.fromJson(read(_keyGlobal));
|
||||
} catch (e) {
|
||||
debugPrint('read track prefs failed: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Saves [choice] as the global one and, with [seriesId], the series'.
|
||||
Future<void> save(TrackChoice choice, {String? seriesId}) async {
|
||||
await _ready();
|
||||
try {
|
||||
final v = jsonEncode(choice.toJson());
|
||||
await _store.put(_keyGlobal, v);
|
||||
if (seriesId != null) await _store.put('series:$seriesId', v);
|
||||
} catch (e) {
|
||||
debugPrint('save track prefs failed: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive_ce/hive.dart';
|
||||
|
||||
// Where the library's matches live (device-owned, one Hive box): AniList
|
||||
// entries seen, automatic matches, the user's pins and episode offsets.
|
||||
// Plain JSON-ish values under string keys; reads are synchronous once
|
||||
// loaded, writes go through.
|
||||
|
||||
const libraryBoxName = 'library';
|
||||
|
||||
abstract interface class LibraryStore {
|
||||
/// Loads the stored values (once).
|
||||
Future<void> ensureLoaded();
|
||||
Object? get(String key);
|
||||
void put(String key, Object value);
|
||||
void delete(String key);
|
||||
|
||||
/// Every key starting with [prefix].
|
||||
Iterable<String> keys(String prefix);
|
||||
}
|
||||
|
||||
/// For tests and as the fallback when Hive is not available.
|
||||
class MemoryLibraryStore implements LibraryStore {
|
||||
final Map<String, Object> values;
|
||||
MemoryLibraryStore([Map<String, Object>? values]) : values = values ?? {};
|
||||
|
||||
@override
|
||||
Future<void> ensureLoaded() async {}
|
||||
@override
|
||||
Object? get(String key) => values[key];
|
||||
@override
|
||||
void put(String key, Object value) => values[key] = value;
|
||||
@override
|
||||
void delete(String key) => values.remove(key);
|
||||
@override
|
||||
Iterable<String> keys(String prefix) => values.keys.where((k) => k.startsWith(prefix)).toList();
|
||||
}
|
||||
|
||||
/// The `library` box; until it opens (or when it cannot) it acts as an
|
||||
/// empty memory store, so matching still works for the run.
|
||||
class HiveLibraryStore implements LibraryStore {
|
||||
Box? _box;
|
||||
final _memory = MemoryLibraryStore();
|
||||
Future<void>? _load;
|
||||
|
||||
@override
|
||||
Future<void> ensureLoaded() => _load ??= () async {
|
||||
try {
|
||||
final box = _box = await Hive.openBox(libraryBoxName);
|
||||
// Writes made before the box opened.
|
||||
for (final e in _memory.values.entries) {
|
||||
await box.put(e.key, e.value);
|
||||
}
|
||||
_memory.values.clear();
|
||||
} catch (e, st) {
|
||||
debugPrint('open library store failed: $e\n$st');
|
||||
}
|
||||
}();
|
||||
|
||||
@override
|
||||
Object? get(String key) => _box?.get(key) ?? _memory.get(key);
|
||||
|
||||
@override
|
||||
void put(String key, Object value) {
|
||||
final box = _box;
|
||||
if (box == null) return _memory.put(key, value);
|
||||
box.put(key, value).catchError((Object e) => debugPrint('library store put $key: $e'));
|
||||
}
|
||||
|
||||
@override
|
||||
void delete(String key) {
|
||||
_memory.delete(key);
|
||||
_box?.delete(key).catchError((Object e) => debugPrint('library store delete $key: $e'));
|
||||
}
|
||||
|
||||
@override
|
||||
Iterable<String> keys(String prefix) => [
|
||||
...?_box?.keys.whereType<String>().where((k) => k.startsWith(prefix)),
|
||||
..._memory.keys(prefix),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../files/scanner.dart' show FolderScan;
|
||||
import 'show_matcher.dart';
|
||||
|
||||
// The next episode of a local show (the library's `nextAfter`, numbers
|
||||
// skipped on the way included): what continues a file this app put up
|
||||
// (see ARCHITECTURE.md "What's next").
|
||||
|
||||
/// [path]'s next episode: from the library the Files page saw this run
|
||||
/// ([ShowMatcher.showAt]), else from the file's own folder read now (one
|
||||
/// [scan], grouped by `groupLocal` with that folder's name as a hint). Null when there is none (the last
|
||||
/// episode, not an episode, an unreadable folder).
|
||||
class LocalNextFinder {
|
||||
final ShowMatcher matcher;
|
||||
final Future<FolderScan> Function(String dir) scan;
|
||||
LocalNextFinder({required this.matcher, required this.scan});
|
||||
|
||||
Future<LocalNext?> nextAfter(String path) async {
|
||||
var show = matcher.showAt(path);
|
||||
if (show == null) {
|
||||
final dir = File(path).parent.path;
|
||||
final found = await scan(dir);
|
||||
// The folder itself is a hint (a bare `01.mkv` in `Bleach`).
|
||||
final lib = groupLocal(found.videos, roots: [Directory(dir).parent.path]);
|
||||
show = lib.shows.where((s) => s.files.any((e) => e.path == path)).firstOrNull;
|
||||
}
|
||||
final at = show?.files.where((e) => e.path == path).firstOrNull;
|
||||
if (show == null || at == null || at.kind != LocalKind.episode) return null;
|
||||
return show.nextAfter(at.key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
// `media.ref` (PROTOCOL.md "Media identity") for each source: what a media
|
||||
// is, independent of where its bytes come from. Local files get theirs
|
||||
// from the library (`ShowMatcher.refFor`, L1 + L2); these are the other
|
||||
// two: Jellyfin items by their provider ids, links best effort from their
|
||||
// name.
|
||||
|
||||
/// A Jellyfin episode, movie or video: kind, series (or movie) title,
|
||||
/// season and episode as Jellyfin numbers them, and the AniList / TVDB ids
|
||||
/// its metadata plugins set ([series]' when given: an episode's own ids
|
||||
/// are the episode's, not the show's). Null for anything that is not
|
||||
/// played (series, seasons, folders).
|
||||
MediaRef? jellyfinMediaRef(JellyfinItem item, {JellyfinItem? series}) {
|
||||
final kind = switch (item.kind) {
|
||||
JellyfinItemKind.episode => 'episode',
|
||||
JellyfinItemKind.movie || JellyfinItemKind.video => 'movie',
|
||||
_ => null,
|
||||
};
|
||||
if (kind == null) return null;
|
||||
final episode = kind == 'episode';
|
||||
// An episode's Tvdb id names the episode; the show's comes from the
|
||||
// series item. AniList ids are only ever set on shows and movies.
|
||||
final owner = episode ? series : item;
|
||||
final special = episode && item.parentIndexNumber == 0;
|
||||
return MediaRef(
|
||||
kind: special ? 'extra' : kind,
|
||||
title: episode ? (item.seriesName ?? series?.name ?? item.name) : item.name,
|
||||
anilistId: owner?.providerId('AniList'),
|
||||
tvdbId: owner?.providerId('Tvdb'),
|
||||
season: episode && !special ? item.parentIndexNumber : null,
|
||||
ep: episode && !special ? item.indexNumber : null,
|
||||
);
|
||||
}
|
||||
|
||||
final _sxe = RegExp(r'S(\d{1,3})\s?E(\d{1,4})$', caseSensitive: false);
|
||||
|
||||
/// A picked Jellyfin item from its card's lines alone ([title], and
|
||||
/// [subtitle] "Series · S1E6" for episodes, the year for movies): kind,
|
||||
/// title and numbers, no ids.
|
||||
MediaRef jellyfinPickRef(String title, String subtitle) {
|
||||
final sub = subtitle.trim();
|
||||
final cut = sub.lastIndexOf(' · ');
|
||||
final label = cut < 0 ? sub : sub.substring(cut + 3).trim();
|
||||
final m = _sxe.firstMatch(label);
|
||||
if (m == null) return MediaRef(kind: 'movie', title: title);
|
||||
final season = int.parse(m.group(1)!);
|
||||
return MediaRef(
|
||||
kind: season == 0 ? 'extra' : 'episode',
|
||||
title: cut < 0 ? title : sub.substring(0, cut).trim(),
|
||||
season: season == 0 ? null : season,
|
||||
ep: season == 0 ? null : int.parse(m.group(2)!),
|
||||
);
|
||||
}
|
||||
|
||||
/// A link, best effort: its name read like a release name (`Show - 05`
|
||||
/// is an episode, `OP1` an extra); anything else a movie of that title.
|
||||
MediaRef linkMediaRef(String name) {
|
||||
final p = parseReleaseName(name);
|
||||
final title = p.series.trim().isEmpty ? name.trim() : p.series.trim();
|
||||
return switch (p.kind) {
|
||||
ReleaseKind.episode => MediaRef(
|
||||
kind: 'episode',
|
||||
title: title,
|
||||
season: p.season,
|
||||
ep: p.season == null ? null : p.episode,
|
||||
absolute: p.season == null ? p.episode : null),
|
||||
ReleaseKind.extra => MediaRef(kind: 'extra', title: title, season: p.season),
|
||||
ReleaseKind.movie || ReleaseKind.other => MediaRef(kind: 'movie', title: title),
|
||||
};
|
||||
}
|
||||
|
||||
/// The episode line a ref gives (`S3 E13`, `E108`), or null (movies;
|
||||
/// extras keep the name's own marker).
|
||||
String? refEpisodeLine(MediaRef ref) {
|
||||
if (ref.kind != 'episode') return null;
|
||||
if (ref.season != null && ref.ep != null) return 'S${ref.season} E${ref.ep}';
|
||||
final n = ref.absolute ?? ref.ep ?? ref.anilistEp;
|
||||
return n == null ? null : 'E$n';
|
||||
}
|
||||
@@ -0,0 +1,666 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart' show debugPrint, visibleForTesting;
|
||||
import 'package:signals/signals.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../schedule/anilist.dart';
|
||||
import '../schedule/animeflow.dart';
|
||||
import 'library_store.dart';
|
||||
|
||||
// L2 of the library (ARCHITECTURE.md "Media identity"): local shows (L1)
|
||||
// matched to AniList, device-owned and cached. A season of a show is
|
||||
// searched once (title and synonyms, the season's number or name as
|
||||
// hints) and the answer kept by show key, season and season name; its
|
||||
// episodes map onto AniList entries along the run (a season AniList
|
||||
// splits into cours continues on the SEQUEL entry), or onto AnimeFlow's
|
||||
// `anilist_map` when signed in. The user's pins (a show everywhere, or one
|
||||
// folder) and episode offsets override everything and survive rescans.
|
||||
// Requests are lazy (only for shows on screen), one at a time and spaced
|
||||
// out for AniList's rate limit; everything answers offline from the cache.
|
||||
|
||||
/// Where AnimeFlow places an AniList entry: the TVDB season runs of its
|
||||
/// series ([AniListRun]) and the series' TVDB id.
|
||||
class FlowShow {
|
||||
final List<AniListRun> runs;
|
||||
final int? tvdbId;
|
||||
const FlowShow(this.runs, {this.tvdbId});
|
||||
}
|
||||
|
||||
/// AnimeFlow's knowledge of a show, when signed in.
|
||||
abstract interface class FlowLookup {
|
||||
/// The series [anilistId] belongs to; null when AnimeFlow has none (or
|
||||
/// cannot be asked).
|
||||
Future<FlowShow?> forAniList(int anilistId);
|
||||
}
|
||||
|
||||
/// [FlowLookup] over the AnimeFlow app API (`/library`, `/series`), read
|
||||
/// once per app run.
|
||||
class AnimeFlowLookup implements FlowLookup {
|
||||
final AnimeFlowClient client;
|
||||
AnimeFlowLookup(this.client);
|
||||
|
||||
Future<(List<AnimeFlowLibraryItem>, List<AnimeFlowSeries>)>? _load;
|
||||
|
||||
Future<(List<AnimeFlowLibraryItem>, List<AnimeFlowSeries>)> _fetch() async =>
|
||||
(await client.library(), await client.series());
|
||||
|
||||
@override
|
||||
Future<FlowShow?> forAniList(int anilistId) async {
|
||||
final load = _load ??= _fetch();
|
||||
final (List<AnimeFlowLibraryItem>, List<AnimeFlowSeries>) data;
|
||||
try {
|
||||
data = await load;
|
||||
} catch (e) {
|
||||
_load = null;
|
||||
return null;
|
||||
}
|
||||
final (library, series) = data;
|
||||
for (final item in library) {
|
||||
final has = item.anilistMap.any((r) => r.anilistId == anilistId) || item.anilistIds.values.contains(anilistId);
|
||||
if (!has) continue;
|
||||
final s = series
|
||||
.where((s) =>
|
||||
(item.seriesId != null && s.seriesId == item.seriesId) ||
|
||||
(s.jellyfinSeriesId != null && s.jellyfinSeriesId == item.jellyfinSeriesId))
|
||||
.firstOrNull;
|
||||
return FlowShow(item.anilistMap, tvdbId: s?.tvdbId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// What a pin covers.
|
||||
enum PinScope { show, folder }
|
||||
|
||||
/// The AniList entry a season (or a movie, or an extra's show) is.
|
||||
class SeasonMatch {
|
||||
final AniListEntry entry;
|
||||
|
||||
/// Set by the user ("Wrong show?"), not by the search.
|
||||
final PinScope? pinned;
|
||||
const SeasonMatch(this.entry, {this.pinned});
|
||||
}
|
||||
|
||||
/// An episode on AniList.
|
||||
class EpisodeTarget {
|
||||
final int anilistId;
|
||||
final int? anilistEp;
|
||||
const EpisodeTarget(this.anilistId, this.anilistEp);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is EpisodeTarget && other.anilistId == anilistId && other.anilistEp == anilistEp;
|
||||
@override
|
||||
int get hashCode => Object.hash(anilistId, anilistEp);
|
||||
@override
|
||||
String toString() => 'EpisodeTarget($anilistId, $anilistEp)';
|
||||
}
|
||||
|
||||
/// The library's L2: see the file comment. Made by the composition root.
|
||||
class ShowMatcher {
|
||||
ShowMatcher({
|
||||
required this.store,
|
||||
required this.aniList,
|
||||
this.flow,
|
||||
this.spacing = const Duration(milliseconds: 800),
|
||||
this.retryNoneAfter = const Duration(days: 3),
|
||||
DateTime Function()? now,
|
||||
Future<void> Function(Duration)? delay,
|
||||
}) : _now = now ?? DateTime.now,
|
||||
_delay = delay ?? Future<void>.delayed;
|
||||
|
||||
final LibraryStore store;
|
||||
final AniListLookup aniList;
|
||||
final FlowLookup? flow;
|
||||
|
||||
/// Between two AniList requests.
|
||||
final Duration spacing;
|
||||
|
||||
/// A search that found nothing is asked again after this.
|
||||
final Duration retryNoneAfter;
|
||||
final DateTime Function() _now;
|
||||
final Future<void> Function(Duration) _delay;
|
||||
|
||||
/// Bumps whenever something new is known (a match, an entry, a pin).
|
||||
final revision = signal(0);
|
||||
|
||||
/// Shows being matched right now, by show key.
|
||||
final busy = signal<Set<String>>(const {});
|
||||
|
||||
// Files seen in scans this run, for refs of files put up.
|
||||
final _byPath = <String, LocalEpisode>{};
|
||||
final _showByPath = <String, LocalShow>{};
|
||||
final _entries = <int, AniListEntry>{};
|
||||
final _flows = <int, FlowShow?>{};
|
||||
final _jobs = <String, Future<void> Function()>{};
|
||||
final _failed = <String, DateTime>{};
|
||||
bool _pumping = false;
|
||||
DateTime? _lastRequest;
|
||||
DateTime? _pausedUntil;
|
||||
|
||||
/// Loads the cache (once); reads before it finishes see nothing.
|
||||
Future<void> ensureLoaded() => store.ensureLoaded().then((_) => _bump());
|
||||
|
||||
// ------------------------------------------------------------- keys
|
||||
|
||||
static String matchKey(String showKey, int? season, String? seasonName) =>
|
||||
'$showKey|${season ?? ''}|${normalizeSeries(seasonName ?? '')}';
|
||||
|
||||
static String _movieKey(LocalEpisode e) => '${e.showKey}|movie|${e.movieNumber ?? ''}';
|
||||
|
||||
String _keyOf(LocalEpisode e) =>
|
||||
e.kind == LocalKind.movie ? _movieKey(e) : matchKey(e.showKey, e.season, e.seasonName);
|
||||
|
||||
// ------------------------------------------------------------- reads
|
||||
|
||||
/// Remembers [library]'s files, so [refForPath] and [showAt] know
|
||||
/// their show.
|
||||
void remember(LocalLibrary library) {
|
||||
for (final e in library.files) {
|
||||
_byPath[e.path] = e;
|
||||
}
|
||||
for (final s in library.shows) {
|
||||
for (final e in s.files) {
|
||||
_showByPath[e.path] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The show the file at [path] belongs to, as seen in a scan this run.
|
||||
LocalShow? showAt(String path) => _showByPath[path];
|
||||
|
||||
AniListEntry? entry(int id) {
|
||||
final known = _entries[id];
|
||||
if (known != null) return known;
|
||||
final raw = store.get('entry:$id');
|
||||
final e = raw is Map ? AniListEntry.fromJson(raw['e']) : null;
|
||||
if (e != null) _entries[id] = e;
|
||||
return e;
|
||||
}
|
||||
|
||||
/// The user's pin for [showKey] (everywhere), if any.
|
||||
int? showPin(String showKey) => _int(store.get('pin:show:$showKey'));
|
||||
|
||||
/// The pin of [folder] or the nearest folder above it, if any.
|
||||
({String folder, int id})? folderPin(String folder) {
|
||||
var f = folder;
|
||||
while (f.isNotEmpty) {
|
||||
final id = _int(store.get('pin:folder:$f'));
|
||||
if (id != null) return (folder: f, id: id);
|
||||
final cut = f.lastIndexOf(RegExp(r'[/\\]'));
|
||||
if (cut <= 0) break;
|
||||
f = f.substring(0, cut);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// "These files are episodes N..": added to every file's number of
|
||||
/// [showKey]'s season [season].
|
||||
int offset(String showKey, int? season) => _int(store.get('offset:$showKey|${season ?? ''}')) ?? 0;
|
||||
|
||||
/// The entry [e]'s season (or movie, or the show of an extra) is: a
|
||||
/// folder pin, else the show's pin, else the search's answer.
|
||||
SeasonMatch? seasonMatch(LocalEpisode e) {
|
||||
if (e.kind == LocalKind.other) return null;
|
||||
final fp = folderPin(e.folder);
|
||||
if (fp != null) {
|
||||
final en = entry(fp.id);
|
||||
return en == null ? null : SeasonMatch(en, pinned: PinScope.folder);
|
||||
}
|
||||
final sp = showPin(e.showKey);
|
||||
if (sp != null) {
|
||||
final en = entry(sp);
|
||||
return en == null ? null : SeasonMatch(en, pinned: PinScope.show);
|
||||
}
|
||||
final auto = store.get('auto:${_keyOf(e)}');
|
||||
final id = auto is Map ? _int(auto['id']) : null;
|
||||
if (id == null) {
|
||||
// An extra of no matched season: the show's first one.
|
||||
if (e.kind == LocalKind.extra && e.season != null) {
|
||||
return seasonMatch(LocalEpisode(
|
||||
file: e.file, parsed: e.parsed, kind: LocalKind.extra, showKey: e.showKey, title: e.title, extra: e.extra));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final en = entry(id);
|
||||
return en == null ? null : SeasonMatch(en);
|
||||
}
|
||||
|
||||
/// What the show is as a whole: its first season's match (else a
|
||||
/// movie's or an extra's).
|
||||
SeasonMatch? showMatch(LocalShow show) {
|
||||
for (final e in [
|
||||
for (final s in show.seasons) s.episodes.first,
|
||||
...show.movies,
|
||||
...show.extras,
|
||||
]) {
|
||||
final m = seasonMatch(e);
|
||||
if (m != null) return m;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// The proper name of [show]: its match's title, else as found.
|
||||
String titleOf(LocalShow show) => showMatch(show)?.entry.title ?? show.title;
|
||||
|
||||
/// The AniList entry and episode [e] is; for extras and movies only the
|
||||
/// entry. Null before a match.
|
||||
EpisodeTarget? target(LocalEpisode e) {
|
||||
final m = seasonMatch(e);
|
||||
if (m == null) return null;
|
||||
if (e.kind != LocalKind.episode) return EpisodeTarget(m.entry.id, null);
|
||||
final n = e.episode! + offset(e.showKey, e.season);
|
||||
if (n < 1) return EpisodeTarget(m.entry.id, null);
|
||||
final fs = _flowOf(m.entry.id);
|
||||
if (fs != null && e.season != null) {
|
||||
final runs = fs.runs.where((r) => r.season == e.season && r.firstEpisode <= n).toList()
|
||||
..sort((a, b) => b.firstEpisode.compareTo(a.firstEpisode));
|
||||
if (runs.isNotEmpty) return EpisodeTarget(runs.first.anilistId, n - runs.first.offset);
|
||||
}
|
||||
// Along the run: past an entry's episodes, its sequel's.
|
||||
var cur = m.entry;
|
||||
var k = n;
|
||||
for (var hop = 0; hop < 30; hop++) {
|
||||
final count = cur.episodes;
|
||||
final next = cur.sequel;
|
||||
if (count == null || k <= count || next == null) break;
|
||||
k -= count;
|
||||
final nx = entry(next);
|
||||
if (nx == null) {
|
||||
_wantEntry(next);
|
||||
return EpisodeTarget(next, k);
|
||||
}
|
||||
cur = nx;
|
||||
}
|
||||
return EpisodeTarget(cur.id, k);
|
||||
}
|
||||
|
||||
/// AniList's title of [e]'s episode, when it knows one.
|
||||
String? episodeTitle(LocalEpisode e) {
|
||||
final t = target(e);
|
||||
final ep = t?.anilistEp;
|
||||
if (t == null || ep == null) return null;
|
||||
return entry(t.anilistId)?.episodeTitles[ep];
|
||||
}
|
||||
|
||||
/// What [e] is on the wire (`media.ref`): the match when there is one,
|
||||
/// else what L1 read (kind, title, numbers).
|
||||
MediaRef refFor(LocalEpisode e) {
|
||||
final m = seasonMatch(e);
|
||||
final t = target(e);
|
||||
final n = e.episode == null ? null : e.episode! + offset(e.showKey, e.season);
|
||||
final tvdb = m == null ? null : _flowOf(m.entry.id)?.tvdbId;
|
||||
return MediaRef(
|
||||
kind: switch (e.kind) {
|
||||
LocalKind.episode => 'episode',
|
||||
LocalKind.extra => 'extra',
|
||||
LocalKind.movie || LocalKind.other => 'movie',
|
||||
},
|
||||
title: m?.entry.title ?? e.title,
|
||||
anilistId: t?.anilistId ?? m?.entry.id,
|
||||
anilistEp: t?.anilistEp,
|
||||
tvdbId: tvdb,
|
||||
season: e.kind == LocalKind.episode ? e.season : null,
|
||||
ep: e.kind == LocalKind.episode && e.season != null ? n : null,
|
||||
absolute: e.kind == LocalKind.episode && e.season == null ? n : null,
|
||||
);
|
||||
}
|
||||
|
||||
/// [refFor] the file at [path]: as seen in a scan this run, else read
|
||||
/// from its name and folder alone.
|
||||
MediaRef refForPath(String path) =>
|
||||
refFor(_byPath[path] ?? readLocalFile(LocalFile(path, 0, DateTime.fromMillisecondsSinceEpoch(0))));
|
||||
|
||||
/// The library's reading of [path] (null: not seen in a scan this run).
|
||||
LocalEpisode? episodeAt(String path) => _byPath[path];
|
||||
|
||||
// ------------------------------------------------------------- matching
|
||||
|
||||
/// Matches [show]'s seasons and movies that have no answer yet, in the
|
||||
/// background (see the file comment).
|
||||
void want(LocalShow show) {
|
||||
final seen = <String>{};
|
||||
for (final e in [
|
||||
for (final s in show.seasons) s.episodes.first,
|
||||
...show.movies,
|
||||
if (show.seasons.isEmpty) ...show.extras.take(1),
|
||||
]) {
|
||||
final key = _keyOf(e);
|
||||
if (!seen.add(key)) continue;
|
||||
final pinned = folderPin(e.folder)?.id ?? showPin(e.showKey);
|
||||
if (pinned != null) {
|
||||
if (entry(pinned) == null) _wantEntry(pinned);
|
||||
continue;
|
||||
}
|
||||
_wantMatch(key, show, e);
|
||||
}
|
||||
final m = showMatch(show);
|
||||
if (m != null) _wantFlow(m.entry.id);
|
||||
}
|
||||
|
||||
/// [want] for each standalone movie of [library] and each of [shows].
|
||||
void wantMovie(LocalEpisode movie) {
|
||||
if (movie.kind != LocalKind.movie) return;
|
||||
_wantMatch(_movieKey(movie), null, movie);
|
||||
}
|
||||
|
||||
void _wantMatch(String key, LocalShow? show, LocalEpisode e) {
|
||||
final auto = store.get('auto:$key');
|
||||
if (auto is Map) {
|
||||
final id = _int(auto['id']);
|
||||
if (id != null) {
|
||||
if (entry(id) == null) _wantEntry(id);
|
||||
return;
|
||||
}
|
||||
final at = _int(auto['at']) ?? 0;
|
||||
if (_now().difference(DateTime.fromMillisecondsSinceEpoch(at)) < retryNoneAfter) return;
|
||||
}
|
||||
if (_recentlyFailed(key)) return;
|
||||
_enqueue('match:$key', () => _match(key, show?.title ?? e.title, e));
|
||||
_setBusy(e.showKey, true);
|
||||
}
|
||||
|
||||
void _wantEntry(int id) {
|
||||
if (_recentlyFailed('entry:$id')) return;
|
||||
_enqueue('entry:$id', () async {
|
||||
final en = await _ask(() => aniList.anime(id));
|
||||
if (en != null) _keepEntry(en);
|
||||
});
|
||||
}
|
||||
|
||||
void _wantFlow(int id) {
|
||||
final f = flow;
|
||||
if (f == null || _flows.containsKey(id)) return;
|
||||
final stored = store.get('flow:$id');
|
||||
if (stored is Map) {
|
||||
_flows[id] = _flowFromJson(stored);
|
||||
final at = _int(stored['at']) ?? 0;
|
||||
if (_now().difference(DateTime.fromMillisecondsSinceEpoch(at)) < const Duration(days: 1)) return;
|
||||
} else {
|
||||
_flows[id] = null;
|
||||
}
|
||||
unawaited(f.forAniList(id).then((fs) {
|
||||
if (fs == null) return;
|
||||
_flows[id] = fs;
|
||||
store.put('flow:$id', {
|
||||
'at': _now().millisecondsSinceEpoch,
|
||||
'tvdb': fs.tvdbId,
|
||||
'runs': [
|
||||
for (final r in fs.runs) [r.season, r.anilistId, r.firstEpisode, r.offset]
|
||||
],
|
||||
});
|
||||
_bump();
|
||||
}).catchError((Object e) => debugPrint('library: animeflow lookup $id: $e')));
|
||||
}
|
||||
|
||||
FlowShow? _flowOf(int id) {
|
||||
if (!_flows.containsKey(id)) {
|
||||
final stored = store.get('flow:$id');
|
||||
if (stored is Map) _flows[id] = _flowFromJson(stored);
|
||||
}
|
||||
return _flows[id];
|
||||
}
|
||||
|
||||
static FlowShow? _flowFromJson(Map j) {
|
||||
final runs = <AniListRun>[];
|
||||
final raw = j['runs'];
|
||||
if (raw is List) {
|
||||
for (final r in raw) {
|
||||
if (r is List && r.length == 4 && r.every((v) => v is int)) {
|
||||
runs.add(AniListRun(
|
||||
season: r[0] as int, anilistId: r[1] as int, firstEpisode: r[2] as int, offset: r[3] as int));
|
||||
}
|
||||
}
|
||||
}
|
||||
return runs.isEmpty ? null : FlowShow(runs, tvdbId: _int(j['tvdb']));
|
||||
}
|
||||
|
||||
/// One search for the season [e] stands for; keeps the best entry (or
|
||||
/// "none") under [key].
|
||||
Future<void> _match(String key, String title, LocalEpisode e) async {
|
||||
try {
|
||||
final plain = title.replaceAll(RegExp(r'[._]+'), ' ').replaceAll(RegExp(r'\s+'), ' ').trim();
|
||||
final movie = e.kind == LocalKind.movie;
|
||||
final season = movie ? null : e.season;
|
||||
final name = movie ? null : e.seasonName;
|
||||
final query = [
|
||||
plain,
|
||||
if (name != null) name else if (season != null && season > 1) 'season $season',
|
||||
].join(' ');
|
||||
var hits = await _ask(() => aniList.searchAnime(query));
|
||||
var best = pickMatch(hits, title: plain, season: season, seasonName: name, movie: movie);
|
||||
if (best == null && query != plain) {
|
||||
hits = await _ask(() => aniList.searchAnime(plain));
|
||||
best = pickMatch(hits, title: plain, season: season, seasonName: name, movie: movie);
|
||||
// Found the show but not the season: walk its sequels.
|
||||
if (best != null && season != null && season > 1 && name == null && seasonMarker(best) != season) {
|
||||
var cur = best;
|
||||
for (var hop = 1; hop < season; hop++) {
|
||||
final next = cur.sequel;
|
||||
if (next == null) break;
|
||||
final nx = entry(next) ?? await _ask(() => aniList.anime(next));
|
||||
if (nx == null) break;
|
||||
_keepEntry(nx);
|
||||
cur = nx;
|
||||
}
|
||||
best = cur;
|
||||
}
|
||||
}
|
||||
for (final h in hits) {
|
||||
if (h.id == best?.id) _keepEntry(h);
|
||||
}
|
||||
store.put('auto:$key', {'id': best?.id, 'at': _now().millisecondsSinceEpoch});
|
||||
if (best != null) _wantFlow(best.id);
|
||||
_bump();
|
||||
} finally {
|
||||
_setBusy(e.showKey, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// "Wrong show?": AniList's answers for [query], best first.
|
||||
Future<List<AniListEntry>> search(String query) async {
|
||||
final hits = await _ask(() => aniList.searchAnime(query));
|
||||
return hits;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------- corrections
|
||||
|
||||
/// Pins [showKey] to [e] everywhere (every folder, every rescan).
|
||||
void pinShow(String showKey, AniListEntry e) {
|
||||
_keepEntry(e);
|
||||
store.put('pin:show:$showKey', e.id);
|
||||
_wantFlow(e.id);
|
||||
_bump();
|
||||
}
|
||||
|
||||
/// Pins every video in [folder] (and below) to [e].
|
||||
void pinFolder(String folder, AniListEntry e) {
|
||||
_keepEntry(e);
|
||||
store.put('pin:folder:$folder', e.id);
|
||||
_wantFlow(e.id);
|
||||
_bump();
|
||||
}
|
||||
|
||||
void unpinShow(String showKey) {
|
||||
store.delete('pin:show:$showKey');
|
||||
_bump();
|
||||
}
|
||||
|
||||
void unpinFolder(String folder) {
|
||||
store.delete('pin:folder:$folder');
|
||||
_bump();
|
||||
}
|
||||
|
||||
/// "These files are episodes N..": [offset] is added to the file
|
||||
/// numbers of [showKey]'s season [season] (0 removes it).
|
||||
void setOffset(String showKey, int? season, int offset) {
|
||||
final key = 'offset:$showKey|${season ?? ''}';
|
||||
offset == 0 ? store.delete(key) : store.put(key, offset);
|
||||
_bump();
|
||||
}
|
||||
|
||||
/// Forgets the automatic match of [show] so it is searched again.
|
||||
void rematch(LocalShow show) {
|
||||
for (final k in store.keys('auto:${show.key}|').toList()) {
|
||||
store.delete(k);
|
||||
}
|
||||
want(show);
|
||||
_bump();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------- plumbing
|
||||
|
||||
void _keepEntry(AniListEntry e) {
|
||||
_entries[e.id] = e;
|
||||
store.put('entry:${e.id}', {'at': _now().millisecondsSinceEpoch, 'e': e.toJson()});
|
||||
_bump();
|
||||
}
|
||||
|
||||
void _bump() => revision.value++;
|
||||
|
||||
void _setBusy(String showKey, bool on) {
|
||||
final now = {...busy.peek()};
|
||||
if (on ? now.add(showKey) : now.remove(showKey)) busy.value = now;
|
||||
}
|
||||
|
||||
bool _recentlyFailed(String key) {
|
||||
final at = _failed[key];
|
||||
return at != null && _now().difference(at) < const Duration(minutes: 5);
|
||||
}
|
||||
|
||||
void _enqueue(String key, Future<void> Function() job) {
|
||||
if (_jobs.containsKey(key)) return;
|
||||
_jobs[key] = () => job().catchError((Object e) {
|
||||
_failed[key] = _now();
|
||||
debugPrint('library: $key failed: $e');
|
||||
if (e is AniListException && e.isRateLimited) _pausedUntil = _now().add(const Duration(minutes: 1));
|
||||
});
|
||||
if (!_pumping) unawaited(_pump());
|
||||
}
|
||||
|
||||
Future<void> _pump() async {
|
||||
_pumping = true;
|
||||
try {
|
||||
while (_jobs.isNotEmpty) {
|
||||
final key = _jobs.keys.first;
|
||||
final job = _jobs[key]!;
|
||||
await job();
|
||||
_jobs.remove(key);
|
||||
}
|
||||
} finally {
|
||||
_pumping = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// One AniList request, spaced from the last one (and after a rate
|
||||
/// limit's pause).
|
||||
Future<T> _ask<T>(Future<T> Function() request) async {
|
||||
final paused = _pausedUntil;
|
||||
if (paused != null && paused.isAfter(_now())) await _delay(paused.difference(_now()));
|
||||
final last = _lastRequest;
|
||||
if (last != null) {
|
||||
final wait = spacing - _now().difference(last);
|
||||
if (wait > Duration.zero) await _delay(wait);
|
||||
}
|
||||
_lastRequest = _now();
|
||||
return request();
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
bool get idle => _jobs.isEmpty && !_pumping;
|
||||
|
||||
static int? _int(Object? v) => v is int ? v : null;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ scoring
|
||||
|
||||
/// The season number an entry's names carry (`Season 2`, `2nd Season`,
|
||||
/// `Part 2` is not one); null when none does.
|
||||
int? seasonMarker(AniListEntry e) {
|
||||
for (final n in e.names) {
|
||||
final s = _seasonOf(normalizeSeries(n));
|
||||
if (s != null) return s;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final _seasonWords = RegExp(r'\b(?:season (\d{1,2})|(\d{1,2})(?:st|nd|rd|th) season|s(\d{1,2}))\b');
|
||||
final _roman = {'ii': 2, 'iii': 3, 'iv': 4, 'v': 5, 'vi': 6};
|
||||
|
||||
int? _seasonOf(String normalized) {
|
||||
final m = _seasonWords.firstMatch(normalized);
|
||||
if (m != null) return int.parse(m.group(1) ?? m.group(2) ?? m.group(3)!);
|
||||
final last = normalized.split(' ').last;
|
||||
return _roman[last];
|
||||
}
|
||||
|
||||
/// How alike two normalized titles are, 0..1.
|
||||
double titleSimilarity(String a, String b) {
|
||||
if (a.isEmpty || b.isEmpty) return 0;
|
||||
if (a == b) return 1;
|
||||
final short = a.length <= b.length ? a : b;
|
||||
final long = a.length <= b.length ? b : a;
|
||||
final ratio = short.length / long.length;
|
||||
if (long.startsWith('$short ')) return 0.8 + 0.2 * ratio;
|
||||
if (long.contains(' $short ') || long.endsWith(' $short')) return 0.6 + 0.2 * ratio;
|
||||
// Dice over letter pairs, spaces ignored.
|
||||
Set<String> pairs(String s) {
|
||||
final t = s.replaceAll(' ', '');
|
||||
return {for (var i = 0; i + 1 < t.length; i++) t.substring(i, i + 2)};
|
||||
}
|
||||
|
||||
final pa = pairs(a), pb = pairs(b);
|
||||
if (pa.isEmpty || pb.isEmpty) return 0;
|
||||
return 2 * pa.intersection(pb).length / (pa.length + pb.length);
|
||||
}
|
||||
|
||||
/// Scores [e] as the answer for a show called [title] (its season
|
||||
/// [season] or its season named [seasonName]; a [movie]); [rank]: its
|
||||
/// place in AniList's own order.
|
||||
double scoreMatch(AniListEntry e,
|
||||
{required String title, int? season, String? seasonName, bool movie = false, int rank = 0}) {
|
||||
final q = normalizeSeries(title);
|
||||
final full = seasonName == null ? q : normalizeSeries('$title $seasonName');
|
||||
var best = 0.0;
|
||||
for (final n in e.names) {
|
||||
final nn = normalizeSeries(n);
|
||||
final s = [titleSimilarity(nn, q), titleSimilarity(nn, full)].reduce((a, b) => a > b ? a : b);
|
||||
if (s > best) best = s;
|
||||
}
|
||||
var score = best;
|
||||
if (seasonName != null) {
|
||||
final sub = normalizeSeries(seasonName);
|
||||
if (e.names.any((n) => normalizeSeries(n).contains(sub))) score += 0.25;
|
||||
} else if (!movie) {
|
||||
final wanted = season ?? 1;
|
||||
final marker = seasonMarker(e);
|
||||
if (marker != null && marker == wanted) {
|
||||
score += 0.2;
|
||||
} else if (marker != null) {
|
||||
score -= 0.25;
|
||||
} else if (wanted > 1) {
|
||||
score -= 0.1;
|
||||
}
|
||||
}
|
||||
if (movie) {
|
||||
score += e.isMovie ? 0.15 : -0.25;
|
||||
} else {
|
||||
score += e.isSeries ? 0.05 : (e.isMovie ? -0.3 : -0.1);
|
||||
}
|
||||
return score - rank * 0.02;
|
||||
}
|
||||
|
||||
/// The best of [hits] for a show called [title], if any is good enough.
|
||||
AniListEntry? pickMatch(List<AniListEntry> hits,
|
||||
{required String title, int? season, String? seasonName, bool movie = false}) {
|
||||
AniListEntry? best;
|
||||
var bestScore = 0.55;
|
||||
for (var i = 0; i < hits.length; i++) {
|
||||
final s = scoreMatch(hits[i], title: title, season: season, seasonName: seasonName, movie: movie, rank: i);
|
||||
if (s > bestScore) {
|
||||
best = hits[i];
|
||||
bestScore = s;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
import '../screens/home/ui.dart' show appName, displayVersion;
|
||||
import 'ports/app_dirs.dart';
|
||||
import '../app/app_graph.dart';
|
||||
|
||||
// The app's log on disk (<app support>/logs/app-YYYY-MM-DD.log; core's
|
||||
// logging.dart writes, rotates and redacts it), debugPrint routed into it,
|
||||
// and the "Copy diagnostics" text of Settings → About.
|
||||
|
||||
final _appLog = createLogger('app');
|
||||
|
||||
/// The logs folder, once [startAppLogging] ran.
|
||||
String? appLogDir;
|
||||
|
||||
/// Opens the log files in [dirs]' log folder and routes `debugPrint` and
|
||||
/// uncaught errors into the log.
|
||||
Future<void> startAppLogging(AppDirs dirs) async {
|
||||
try {
|
||||
if (startLogFiles(dirs.logs) != null) appLogDir = dirs.logs;
|
||||
} catch (e) {
|
||||
_appLog.warning('no log files: $e');
|
||||
}
|
||||
// Everything the app prints for diagnosis lands in the file too (the
|
||||
// log's console output replaces the print).
|
||||
debugPrint = (String? message, {int? wrapWidth}) {
|
||||
if (message == null || message.isEmpty) return;
|
||||
final bad = RegExp(r'fail|error|crash|exception', caseSensitive: false).hasMatch(message);
|
||||
bad ? _appLog.warning(message) : _appLog.info(message);
|
||||
};
|
||||
PlatformDispatcher.instance.onError = (error, stack) {
|
||||
_appLog.severe('uncaught: $error', error, stack);
|
||||
return false;
|
||||
};
|
||||
_appLog.info('$appName ${displayVersion()} on ${Platform.operatingSystem} '
|
||||
'${Platform.operatingSystemVersion}, pid $pid, Dart ${Platform.version.split(' ').first}'
|
||||
'${dirs.profile == null ? '' : ', profile ${dirs.profile}'}');
|
||||
for (final line in dirs.migrated) {
|
||||
_appLog.info(line);
|
||||
}
|
||||
final bad = AppDirs.invalidProfile(Platform.environment);
|
||||
if (bad != null) _appLog.warning('$profileEnv="$bad" ignored: use letters, digits, - and _ (at most 32)');
|
||||
}
|
||||
|
||||
/// The text "Copy diagnostics" gives: versions, then the last [since] of
|
||||
/// the app log (its hosted server's records included), already redacted;
|
||||
/// with [sessionLog], the server's session log of the same hours after it
|
||||
/// (every member's shared lines and the server's, merged).
|
||||
Future<String> diagnosticsText(AppGraph graph, {Duration since = const Duration(hours: 6), bool sessionLog = false}) async {
|
||||
final b = StringBuffer()
|
||||
..writeln('$appName ${displayVersion()}')
|
||||
..writeln('OS: ${Platform.operatingSystem} ${Platform.operatingSystemVersion}')
|
||||
..writeln('Dart: ${Platform.version.split(' ').first}');
|
||||
try {
|
||||
final mpv = await graph.coordinator.playback.mpvVersion().timeout(const Duration(seconds: 2));
|
||||
b.writeln('mpv: ${mpv ?? 'no player yet'}');
|
||||
} catch (_) {
|
||||
b.writeln('mpv: unknown');
|
||||
}
|
||||
try {
|
||||
final y = await graph.ports.links.ytDlp.timeout(const Duration(seconds: 2));
|
||||
final cookies = y.cookies.read(count: false);
|
||||
b.writeln('yt-dlp: ${y.version ?? 'not ready'}${y.lastError == null ? '' : ' (${y.lastError})'}, '
|
||||
'cookies: ${cookies == null ? 'none' : 'set'}');
|
||||
} catch (_) {
|
||||
b.writeln('yt-dlp: unknown');
|
||||
}
|
||||
final files = logFiles;
|
||||
b.writeln('Log: ${files?.currentPath ?? 'none (console only)'}');
|
||||
b.writeln('--- last ${since.inHours} h of the log ---');
|
||||
b.write(files?.recent(since) ?? '');
|
||||
if (sessionLog) {
|
||||
final server = await graph.coordinator.sessionLog(hours: since.inHours);
|
||||
b
|
||||
..writeln()
|
||||
..writeln("--- last ${since.inHours} h of the server's session log ---")
|
||||
..write(server ?? "(none: the server keeps no session log, or it couldn't be reached)");
|
||||
}
|
||||
return redactLog(b.toString());
|
||||
}
|
||||
|
||||
/// Saves [text] next to the logs as `diagnostics-<time>.txt`; its path,
|
||||
/// or null when it could not be written.
|
||||
Future<String?> saveDiagnostics(String text) async {
|
||||
final dir = appLogDir;
|
||||
if (dir == null) return null;
|
||||
final t = DateTime.now();
|
||||
String two(int n) => n.toString().padLeft(2, '0');
|
||||
final path = '$dir${Platform.pathSeparator}diagnostics-${t.year}${two(t.month)}${two(t.day)}-'
|
||||
'${two(t.hour)}${two(t.minute)}${two(t.second)}.txt';
|
||||
try {
|
||||
// Older ones go after the log files' week.
|
||||
for (final e in Directory(dir).listSync()) {
|
||||
if (e is File &&
|
||||
e.uri.pathSegments.last.startsWith('diagnostics-') &&
|
||||
t.difference(e.statSync().modified) > const Duration(days: 7)) {
|
||||
e.deleteSync();
|
||||
}
|
||||
}
|
||||
await File(path).writeAsString(text);
|
||||
return path;
|
||||
} catch (e) {
|
||||
_appLog.warning('cannot save diagnostics: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../files/thumbnails.dart';
|
||||
import '../app/app_graph.dart';
|
||||
|
||||
// The one way out of the app (close button, Alt+F4, Update and restart).
|
||||
// Order matters: every mpv player goes before the engine does (a live one
|
||||
// calls a dead Dart callback), then the network goodbye, then the window
|
||||
// closes through the platform's normal path so the engine is torn down
|
||||
// inside the message loop. The runners end the process right after
|
||||
// (`linux/runner/main.cc`, `windows/runner/main.cpp`).
|
||||
|
||||
bool _shuttingDown = false;
|
||||
|
||||
/// True once [shutDownApp] started.
|
||||
bool get shuttingDown => _shuttingDown;
|
||||
|
||||
/// The systems the close stops; `main` hands them over once.
|
||||
AppGraph? _graph;
|
||||
|
||||
/// Makes [graph] the one [shutDownApp] stops and returns the close
|
||||
/// request handler for the window.
|
||||
Future<void> Function() closeAppWith(AppGraph graph) {
|
||||
_graph = graph;
|
||||
return shutDownApp;
|
||||
}
|
||||
|
||||
/// Hides the window, releases every player and the sound device, leaves
|
||||
/// (the `bye` goes out first, so others see "left" at once; then your
|
||||
/// server stops), runs [beforeQuit], then closes the window. [restart]
|
||||
/// (Update and restart) leaves without the `bye`: the member stays
|
||||
/// `gone`, and the restarted app, same client id, takes it back within
|
||||
/// the grace. Every step is bounded; a second call does nothing.
|
||||
Future<void> shutDownApp({Future<void> Function()? beforeQuit, bool restart = false}) async {
|
||||
final graph = _graph;
|
||||
if (_shuttingDown || graph == null) return;
|
||||
_shuttingDown = true;
|
||||
final shell = graph.ports.shell;
|
||||
final total = Stopwatch()..start();
|
||||
await _step('window save', shell.saveWindow(), const Duration(milliseconds: 500));
|
||||
await _step('hide', shell.hide(), const Duration(milliseconds: 500));
|
||||
await Future.wait([
|
||||
_step('players', graph.coordinator.releasePlayers(), const Duration(seconds: 3)),
|
||||
_step('thumbnails', cancelAllThumbnails(), const Duration(milliseconds: 1500)),
|
||||
_step('sounds', graph.sfx.dispose(), const Duration(milliseconds: 500)),
|
||||
]);
|
||||
// The host owns the disposal order: anything still alive goes now.
|
||||
await _step('all players', graph.ports.players.disposeAll(), const Duration(milliseconds: 1500));
|
||||
// Windows: media_kit_video frees a player's video output on a thread of
|
||||
// its own after dispose returns; it must be done before the engine
|
||||
// stops, or the plugin's teardown waits on it for good.
|
||||
if (Platform.isWindows) await Future.delayed(const Duration(milliseconds: 300));
|
||||
// Jellyfin stop report, last diagnostics, the bye (flushed), then your
|
||||
// server: 3 s in all.
|
||||
await _step('leave', graph.navigation.leave(bye: !restart), const Duration(milliseconds: 2500));
|
||||
await _step('server stop', graph.yourServer.stop(), const Duration(milliseconds: 500));
|
||||
if (beforeQuit != null) await _step('before quit', beforeQuit(), const Duration(seconds: 3));
|
||||
debugPrint('close: ready to quit after ${total.elapsedMilliseconds} ms');
|
||||
await shell.quit();
|
||||
// The engine stops with the window, so this only fires when the close
|
||||
// did not go through. A kill, not exit(): no exit handlers (NVIDIA's
|
||||
// EGL one segfaults, Windows DLL detach can hang).
|
||||
Timer(const Duration(seconds: 3), () {
|
||||
debugPrint('close: the window did not close; ending the process');
|
||||
Process.killPid(pid, ProcessSignal.sigkill);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _step(String what, Future<void>? f, Duration limit) async {
|
||||
if (f == null) return;
|
||||
final sw = Stopwatch()..start();
|
||||
try {
|
||||
await f.timeout(limit);
|
||||
} on TimeoutException {
|
||||
debugPrint('close: $what did not finish in ${limit.inMilliseconds} ms');
|
||||
} catch (e) {
|
||||
debugPrint('close: $what failed: $e');
|
||||
}
|
||||
if (sw.elapsedMilliseconds > 200) debugPrint('close: $what took ${sw.elapsedMilliseconds} ms');
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_soloud/flutter_soloud.dart';
|
||||
import 'package:sync_relay_core/core.dart';
|
||||
|
||||
final _log = createLogger('sound');
|
||||
|
||||
/// What [SoundEngine] needs from an audio library: [SoLoudBackend] in the
|
||||
/// app, a fake in tests. A sound handle is whatever [load] returns.
|
||||
abstract class AudioBackend {
|
||||
Future<void> init();
|
||||
/// Decodes [wav] (a whole WAV file) into memory under [name].
|
||||
Future<Object> load(String name, Uint8List wav);
|
||||
/// Starts one voice of [sound] at [volume] (linear gain, 0..1); voices
|
||||
/// overlap.
|
||||
void play(Object sound, double volume);
|
||||
Future<void> unload(Object sound);
|
||||
Future<void> deinit();
|
||||
}
|
||||
|
||||
/// flutter_soloud (SoLoud mixing into miniaudio's output device).
|
||||
class SoLoudBackend implements AudioBackend {
|
||||
SoLoud get _s => SoLoud.instance;
|
||||
|
||||
@override
|
||||
Future<void> init() => _s.init();
|
||||
|
||||
@override
|
||||
Future<Object> load(String name, Uint8List wav) => _s.loadMem(name, wav);
|
||||
|
||||
@override
|
||||
void play(Object sound, double volume) => _s.play(sound as AudioSource, volume: volume);
|
||||
|
||||
@override
|
||||
Future<void> unload(Object sound) => _s.disposeSource(sound as AudioSource);
|
||||
|
||||
@override
|
||||
Future<void> deinit() => _s.deinitAsync();
|
||||
}
|
||||
|
||||
/// The app's short in-memory sounds. The audio device opens on [warmUp] or
|
||||
/// the first [play]; if it can't (no device, a broken driver) the engine
|
||||
/// logs once and every play is silently dropped. Each sound is loaded once
|
||||
/// per slot from the WAV bytes its renderer gives; a new key in a slot
|
||||
/// replaces (and frees) what the slot held.
|
||||
class SoundEngine {
|
||||
final AudioBackend _backend;
|
||||
SoundEngine({AudioBackend? backend}) : _backend = backend ?? SoLoudBackend();
|
||||
|
||||
Future<bool>? _ready;
|
||||
var _disposed = false;
|
||||
/// Per slot: the loaded key and its sound (null: failed to load).
|
||||
final Map<String, (String, Future<Object?>)> _slots = {};
|
||||
/// Load names are unique: SoLoud hands back the old sound for a name it
|
||||
/// already holds, which would defeat a re-render.
|
||||
var _loads = 0;
|
||||
|
||||
/// Opens the audio device now, so the first sound has no wait.
|
||||
Future<bool> warmUp() => _ready ??= _init();
|
||||
|
||||
Future<bool> _init() async {
|
||||
if (_disposed) return false;
|
||||
try {
|
||||
await _backend.init();
|
||||
return true;
|
||||
} catch (e) {
|
||||
_log.warning('no sounds: audio init failed: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Plays the sound of [slot] at [volume] (linear gain). [key] names what
|
||||
/// [wav] renders: the same key reuses the loaded sound; another key, or
|
||||
/// [fresh], renders and loads it again.
|
||||
Future<void> play(String slot, String key, Future<Uint8List> Function() wav,
|
||||
{required double volume, bool fresh = false}) async {
|
||||
if (_disposed || volume <= 0) return;
|
||||
if (!await warmUp() || _disposed) return;
|
||||
var held = _slots[slot];
|
||||
if (held == null || held.$1 != key || fresh) {
|
||||
if (held != null) unawaited(_unload(held.$2));
|
||||
held = (key, _load(key, wav));
|
||||
_slots[slot] = held;
|
||||
}
|
||||
final sound = await held.$2;
|
||||
if (sound == null) {
|
||||
// Retry on the next play.
|
||||
if (identical(_slots[slot], held)) _slots.remove(slot);
|
||||
return;
|
||||
}
|
||||
if (_disposed || !identical(_slots[slot], held)) return;
|
||||
try {
|
||||
_backend.play(sound, volume.clamp(0.0, 1.0));
|
||||
} catch (e) {
|
||||
_log.warning('sound $key: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Object?> _load(String key, Future<Uint8List> Function() wav) async {
|
||||
try {
|
||||
return await _backend.load('$key#${_loads++}', await wav());
|
||||
} catch (e) {
|
||||
_log.warning('sound $key: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _unload(Future<Object?> sound) async {
|
||||
try {
|
||||
final s = await sound;
|
||||
if (s != null && !_disposed) await _backend.unload(s);
|
||||
} catch (e) {
|
||||
_log.fine('unload: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Frees every sound and closes the audio device. Plays after it are
|
||||
/// dropped.
|
||||
Future<void> dispose() async {
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
_slots.clear();
|
||||
final ready = _ready;
|
||||
if (ready == null || !await ready) return;
|
||||
try {
|
||||
// Deinit frees the loaded sounds with the engine.
|
||||
await _backend.deinit();
|
||||
} catch (e) {
|
||||
_log.warning('audio deinit: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
// First start of the renamed app (Starsync, app id dev.foxyz.starsync):
|
||||
// copy what the old names left, never move, so a 1.2.x install keeps
|
||||
// working next to it. Runs once (the marker file), then never again.
|
||||
|
||||
/// Written into the new support folder once the migration ran (whether or
|
||||
/// not anything was found): `migratedFrom` (the old support folder or
|
||||
/// null), `hiveFrom` (the folder the boxes came from or null), `boxes`,
|
||||
/// `files`.
|
||||
const migrationMarker = 'migration.json';
|
||||
|
||||
/// The Hive boxes the app opens, by name (settings, connect form, Files,
|
||||
/// Jellyfin sign-ins, track choices). Only these leave the documents
|
||||
/// folder, which other apps' boxes share.
|
||||
const appHiveBoxes = ['settings', 'connect_form', 'files', 'jellyfin', 'track_prefs'];
|
||||
|
||||
/// Support folders of the old names for the new [support] folder, the
|
||||
/// most likely first. Linux: `$XDG_DATA_HOME/moe.senkochan.watch_together`
|
||||
/// (the GTK application id up to 1.2.x), then `watch_together` (the
|
||||
/// executable name path_provider falls back to). Windows:
|
||||
/// `%APPDATA%\com.example\watch_together` (company and product name of
|
||||
/// the exe up to 1.2.x).
|
||||
List<String> legacySupportDirs(String support, {bool? windows}) {
|
||||
final win = windows ?? Platform.isWindows;
|
||||
final sep = win ? r'\' : '/';
|
||||
String parent(String p) {
|
||||
final norm = p.endsWith(sep) ? p.substring(0, p.length - 1) : p;
|
||||
final i = norm.lastIndexOf(sep);
|
||||
return i <= 0 ? norm : norm.substring(0, i);
|
||||
}
|
||||
|
||||
if (win) return ['${parent(parent(support))}${sep}com.example${sep}watch_together'];
|
||||
final share = parent(support);
|
||||
return ['$share${sep}moe.senkochan.watch_together', '$share${sep}watch_together'];
|
||||
}
|
||||
|
||||
/// Copies the first existing [oldSupport] folder into [support] and the
|
||||
/// [appHiveBoxes] (`.hive` and `.lock`) from [documents] into [hive],
|
||||
/// skipping anything already there; the originals stay. Once per support
|
||||
/// folder ([migrationMarker]). Returns one log line per thing copied
|
||||
/// (paths and counts, never contents); empty when it ran before.
|
||||
Future<List<String>> migrateLegacyData(
|
||||
{required String support, required String hive, required List<String> oldSupport, String? documents}) async {
|
||||
final sep = Platform.pathSeparator;
|
||||
final marker = File('$support$sep$migrationMarker');
|
||||
if (marker.existsSync()) return const [];
|
||||
final lines = <String>[];
|
||||
String? from;
|
||||
var files = 0;
|
||||
for (final old in oldSupport) {
|
||||
final dir = Directory(old);
|
||||
if (!dir.existsSync() || _same(old, support)) continue;
|
||||
files = await _copyTree(dir, Directory(support));
|
||||
from = old;
|
||||
lines.add('migration: copied $files files from $old to $support');
|
||||
break;
|
||||
}
|
||||
final boxes = <String>[];
|
||||
if (documents != null && Directory(documents).existsSync() && !_same(documents, hive)) {
|
||||
await Directory(hive).create(recursive: true);
|
||||
for (final box in appHiveBoxes) {
|
||||
for (final ext in const ['hive', 'lock']) {
|
||||
final src = File('$documents$sep$box.$ext');
|
||||
final dst = File('$hive$sep$box.$ext');
|
||||
if (!src.existsSync() || dst.existsSync()) continue;
|
||||
await src.copy(dst.path);
|
||||
if (ext == 'hive') boxes.add(box);
|
||||
}
|
||||
}
|
||||
if (boxes.isNotEmpty) {
|
||||
lines.add('migration: copied ${boxes.length} Hive boxes (${boxes.join(', ')}) from $documents to $hive');
|
||||
}
|
||||
}
|
||||
if (lines.isEmpty) lines.add('migration: no data from before the rename');
|
||||
await Directory(support).create(recursive: true);
|
||||
await marker.writeAsString(jsonEncode({
|
||||
'migratedFrom': from,
|
||||
'hiveFrom': boxes.isEmpty ? null : documents,
|
||||
'boxes': boxes,
|
||||
'files': files,
|
||||
}));
|
||||
return lines;
|
||||
}
|
||||
|
||||
bool _same(String a, String b) {
|
||||
try {
|
||||
return FileSystemEntity.identicalSync(a, b);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Files (File.copy keeps the mode on POSIX: cookies.txt stays 0600, yt-dlp
|
||||
// executable) and symlinks as they are; existing targets win.
|
||||
Future<int> _copyTree(Directory from, Directory to) async {
|
||||
var n = 0;
|
||||
await to.create(recursive: true);
|
||||
await for (final e in from.list(recursive: true, followLinks: false)) {
|
||||
final target = '${to.path}${e.path.substring(from.path.length)}';
|
||||
if (e is Directory) {
|
||||
await Directory(target).create(recursive: true);
|
||||
} else if (await FileSystemEntity.type(target, followLinks: false) != FileSystemEntityType.notFound) {
|
||||
continue;
|
||||
} else if (e is Link) {
|
||||
await Directory(File(target).parent.path).create(recursive: true);
|
||||
await Link(target).create(await e.target());
|
||||
} else if (e is File) {
|
||||
await Directory(File(target).parent.path).create(recursive: true);
|
||||
await e.copy(target);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
/// The runner's window channel (linux/runner/my_application.cc,
|
||||
/// windows/runner/flutter_window.cpp).
|
||||
const _window = MethodChannel('starsync/window');
|
||||
|
||||
/// Asks the desktop to point at the app's window (taskbar flash, urgency
|
||||
/// hint) when it is not focused; nothing when it is. The runner clears it
|
||||
/// once the window gets focus. Quietly nothing where the runner lacks it.
|
||||
Future<void> requestWindowAttention() async {
|
||||
try {
|
||||
await _window.invokeMethod<void>('attention');
|
||||
} on MissingPluginException {
|
||||
// Tests, other platforms.
|
||||
} catch (e) {
|
||||
debugPrint('window attention: $e');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import '../data_migration.dart';
|
||||
import '../ports/app_dirs.dart';
|
||||
|
||||
/// The desktop's [AppDirsPort]: the app support folder from path_provider
|
||||
/// (Linux `$XDG_DATA_HOME/dev.foxyz.starsync`, Windows
|
||||
/// `%APPDATA%\foxyz\Starsync`); on the first start it copies the data of
|
||||
/// the old names in ([migrateLegacyData]). Needs Flutter's binding.
|
||||
class DesktopAppDirs implements AppDirsPort {
|
||||
const DesktopAppDirs();
|
||||
|
||||
@override
|
||||
Future<AppDirs> resolve() async {
|
||||
final support = (await getApplicationSupportDirectory()).path;
|
||||
final base = AppDirs.fromEnv(support: support, env: const {});
|
||||
List<String> migrated;
|
||||
try {
|
||||
String? documents;
|
||||
try {
|
||||
// Where Hive.initFlutter() kept the boxes up to 1.2.x.
|
||||
documents = (await getApplicationDocumentsDirectory()).path;
|
||||
} catch (_) {}
|
||||
migrated = await migrateLegacyData(
|
||||
support: support, hive: base.hive, oldSupport: legacySupportDirs(support), documents: documents);
|
||||
} catch (e) {
|
||||
migrated = ['migration failed: $e'];
|
||||
}
|
||||
final dirs = AppDirs.fromEnv(support: support, env: Platform.environment, migrated: migrated);
|
||||
await Directory(dirs.hive).create(recursive: true);
|
||||
return dirs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
|
||||
import '../../files/scanner.dart';
|
||||
import '../ports/folder_access.dart';
|
||||
import '../ports/url_opener.dart';
|
||||
|
||||
/// [FolderAccess] on a desktop file system: file_picker's dialogs, the
|
||||
/// [scanFolder] walk, the file manager through [UrlOpener].
|
||||
class DesktopFolders implements FolderAccess {
|
||||
final UrlOpener urls;
|
||||
const DesktopFolders(this.urls);
|
||||
|
||||
@override
|
||||
Future<String?> pickFolder({required String dialogTitle}) => FilePicker.getDirectoryPath(dialogTitle: dialogTitle);
|
||||
|
||||
@override
|
||||
Future<List<String>> pickFiles({required String dialogTitle, required List<String> extensions}) async {
|
||||
final files = await FilePicker.pickFiles(
|
||||
dialogTitle: dialogTitle,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: extensions,
|
||||
);
|
||||
return [for (final f in files) ?f.path];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<FolderScan> scan(String dir) => scanFolder(dir);
|
||||
|
||||
@override
|
||||
bool folderExists(String dir) => Directory(dir).existsSync();
|
||||
|
||||
@override
|
||||
Future<FileStat> stat(String path) => File(path).stat();
|
||||
|
||||
// The file manager opens a folder path the way a browser opens a link.
|
||||
@override
|
||||
Future<bool> reveal(String dir) => urls.open(Uri.directory(dir).toString());
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
import '../desktop_entry.dart' show appId;
|
||||
import '../ports/system_notifications.dart';
|
||||
|
||||
/// [SystemNotifications] on the desktop, through flutter_local_notifications'
|
||||
/// platform plugins (used directly, not through its facade, so the platform
|
||||
/// is picked by the OS and not by Flutter's target platform):
|
||||
/// - Linux: `org.freedesktop.Notifications` over D-Bus (pure Dart), with the
|
||||
/// app's icon (the bundled PNG, else the launcher entry's icon by name);
|
||||
/// a click is the notification's default action.
|
||||
/// - Windows: toast notifications (WinRT), the app's name and icon, a click
|
||||
/// activates the app while it runs (an unpackaged app has no history).
|
||||
/// Silent: the app plays its own sound for the same notice. Anything that
|
||||
/// fails (no notification daemon, no session bus) is logged and dropped.
|
||||
class DesktopNotifications implements SystemNotifications {
|
||||
DesktopNotifications({this.appName = 'Starsync'});
|
||||
|
||||
final String appName;
|
||||
void Function(String payload)? _onClick;
|
||||
Future<bool>? _ready;
|
||||
LinuxFlutterLocalNotificationsPlugin? _linux;
|
||||
FlutterLocalNotificationsWindows? _windows;
|
||||
// Tag -> id, so a notification with the same tag replaces the last one.
|
||||
final _ids = <String, int>{};
|
||||
int _next = 1;
|
||||
|
||||
@override
|
||||
set onClick(void Function(String payload)? handler) => _onClick = handler;
|
||||
|
||||
void _clicked(NotificationResponse r) => _onClick?.call(r.payload ?? '');
|
||||
|
||||
/// The bundled 256 px icon next to the executable (a release or a
|
||||
/// `flutter run` build), else the icon the launcher entry installed.
|
||||
static LinuxNotificationIcon _linuxIcon() {
|
||||
final exe = File(Platform.resolvedExecutable).parent.path;
|
||||
final png = File('$exe/data/flutter_assets/assets/icon/icon_256.png');
|
||||
return png.existsSync() ? FilePathLinuxIcon(png.path) : ThemeLinuxIcon(appId);
|
||||
}
|
||||
|
||||
Future<bool> _init() => _ready ??= () async {
|
||||
try {
|
||||
if (Platform.isLinux) {
|
||||
final p = _linux = LinuxFlutterLocalNotificationsPlugin();
|
||||
return await p.initialize(
|
||||
settings: LinuxInitializationSettings(defaultActionName: 'Open', defaultIcon: _linuxIcon()),
|
||||
onDidReceiveNotificationResponse: _clicked,
|
||||
) ??
|
||||
false;
|
||||
}
|
||||
if (Platform.isWindows) {
|
||||
final exe = File(Platform.resolvedExecutable).parent.path;
|
||||
final icon = File('$exe/data/flutter_assets/assets/icon/icon_256.png');
|
||||
final p = _windows = FlutterLocalNotificationsWindows();
|
||||
return await p.initialize(
|
||||
settings: WindowsInitializationSettings(
|
||||
appName: appName,
|
||||
appUserModelId: 'Foxyz.Starsync',
|
||||
guid: '6c0f4b4e-3e8a-4b8e-9d0c-5a7f2b1e9c31',
|
||||
iconPath: icon.existsSync() ? icon.path : null,
|
||||
),
|
||||
onDidReceiveNotificationResponse: _clicked,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('system notifications unavailable: $e');
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
@override
|
||||
Future<void> show({required String title, required String body, String tag = '', String payload = ''}) async {
|
||||
if (!await _init()) return;
|
||||
final id = tag.isEmpty ? _next++ : _ids[tag] ??= _next++;
|
||||
try {
|
||||
if (_linux case final p?) {
|
||||
await p.show(
|
||||
id: id,
|
||||
title: title,
|
||||
body: body,
|
||||
payload: payload,
|
||||
notificationDetails: const LinuxNotificationDetails(suppressSound: true),
|
||||
);
|
||||
} else if (_windows case final p?) {
|
||||
await p.show(
|
||||
id: id,
|
||||
title: title,
|
||||
body: body,
|
||||
payload: payload,
|
||||
notificationDetails: WindowsNotificationDetails(audio: WindowsNotificationAudio.silent()),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('system notification failed: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import '../../playback/yt_dlp_app.dart';
|
||||
import '../ports/ports.dart';
|
||||
import 'desktop_folders.dart';
|
||||
import 'desktop_notifications.dart';
|
||||
import 'desktop_shell.dart';
|
||||
import 'desktop_urls.dart';
|
||||
import 'media_kit_host.dart';
|
||||
|
||||
/// The desktop's [Ports].
|
||||
Ports desktopPorts() {
|
||||
const urls = DesktopUrls();
|
||||
return Ports(
|
||||
shell: DesktopShell(),
|
||||
urls: urls,
|
||||
folders: const DesktopFolders(urls),
|
||||
links: AppYtDlp.instance,
|
||||
notifications: DesktopNotifications(),
|
||||
players: MediaKitHost(),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:fox_utils/fox_utils.dart' show ClipboardX, DesktopDropX, DropTarget;
|
||||
import 'package:hive_ce_flutter/hive_flutter.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../../state/settings.dart' show settingsBoxName;
|
||||
import 'attention.dart';
|
||||
import '../ports/shell_port.dart';
|
||||
import 'window_memory.dart';
|
||||
|
||||
/// [ShellPort] on Linux and Windows: window_manager for the window,
|
||||
/// [WindowMemory] for its size and place, the runner's channel for
|
||||
/// attention, fox_utils for drops and the clipboard.
|
||||
class DesktopShell implements ShellPort {
|
||||
WindowMemory? _memory;
|
||||
|
||||
@override
|
||||
Future<void> start({required String title, required Future<void> Function() onCloseRequest}) async {
|
||||
await windowManager.ensureInitialized();
|
||||
await windowManager.setPreventClose(true);
|
||||
final memory = _memory = WindowMemory(Hive.isBoxOpen(settingsBoxName) ? Hive.box(settingsBoxName) : null);
|
||||
windowManager.addListener(_CloseGuard(onCloseRequest));
|
||||
final windowOptions = WindowOptions(
|
||||
size: memory.size,
|
||||
minimumSize: const Size(160, 90),
|
||||
center: !memory.hasPosition,
|
||||
backgroundColor: const Color(0xFF000000),
|
||||
titleBarStyle: TitleBarStyle.hidden,
|
||||
title: title,
|
||||
);
|
||||
unawaited(windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await memory.restore();
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
}));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setFullScreen(bool on) => windowManager.setFullScreen(on);
|
||||
@override
|
||||
Future<void> minimize() => windowManager.minimize();
|
||||
@override
|
||||
Future<bool> isMaximized() => windowManager.isMaximized();
|
||||
@override
|
||||
Future<void> maximize() => windowManager.maximize();
|
||||
@override
|
||||
Future<void> unmaximize() => windowManager.unmaximize();
|
||||
|
||||
@override
|
||||
void Function() watchMaximized(void Function(bool maximized) onChange) {
|
||||
final l = _MaximizeWatch(onChange);
|
||||
windowManager.addListener(l);
|
||||
return () => windowManager.removeListener(l);
|
||||
}
|
||||
|
||||
final _activity = <void Function(WindowActivity)>{};
|
||||
|
||||
@override
|
||||
void Function() watchActivity(void Function(WindowActivity activity) onChange) {
|
||||
final l = _ActivityWatch(onChange);
|
||||
_activity.add(onChange);
|
||||
windowManager.addListener(l);
|
||||
return () {
|
||||
_activity.remove(onChange);
|
||||
windowManager.removeListener(l);
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startDragging() => windowManager.startDragging();
|
||||
|
||||
@override
|
||||
Future<void> requestClose() => windowManager.close();
|
||||
|
||||
@override
|
||||
Future<void> saveWindow() async => _memory?.save();
|
||||
|
||||
@override
|
||||
Future<void> hide() async {
|
||||
// window_manager has no hide event: tell the watchers here.
|
||||
for (final f in [..._activity]) {
|
||||
f(WindowActivity.hidden);
|
||||
}
|
||||
await windowManager.hide();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> quit() async {
|
||||
try {
|
||||
await windowManager.setPreventClose(false);
|
||||
await windowManager.close();
|
||||
} catch (e) {
|
||||
debugPrint('window close failed: $e');
|
||||
await windowManager.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> focus() async {
|
||||
try {
|
||||
if (await windowManager.isMinimized()) await windowManager.restore();
|
||||
if (!await windowManager.isVisible()) await windowManager.show();
|
||||
await windowManager.focus();
|
||||
} catch (e) {
|
||||
debugPrint('window focus failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> requestAttention() => requestWindowAttention();
|
||||
|
||||
@override
|
||||
Future<Paste> readPaste() async {
|
||||
var files = const <String>[];
|
||||
String? text;
|
||||
try {
|
||||
files = await ClipboardX.readFiles();
|
||||
} catch (_) {}
|
||||
if (files.isEmpty) {
|
||||
try {
|
||||
text = await ClipboardX.readText();
|
||||
} catch (_) {}
|
||||
}
|
||||
return (files: files, text: text);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget dropTarget({
|
||||
Key? key,
|
||||
bool enable = true,
|
||||
VoidCallback? onEnter,
|
||||
VoidCallback? onExit,
|
||||
required void Function(List<String> paths, Offset at) onDrop,
|
||||
required Widget child,
|
||||
}) =>
|
||||
DropTarget(
|
||||
key: key,
|
||||
enable: enable,
|
||||
onDragEntered: onEnter == null ? null : (_) => onEnter(),
|
||||
onDragExited: onExit == null ? null : (_) => onExit(),
|
||||
onDragDone: (d) => onDrop(DesktopDropX.pathsOf(d.files), d.localPosition),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
/// Close button / Alt+F4 run the orderly close instead.
|
||||
class _CloseGuard with WindowListener {
|
||||
final Future<void> Function() onClose;
|
||||
_CloseGuard(this.onClose);
|
||||
@override
|
||||
void onWindowClose() => unawaited(onClose());
|
||||
}
|
||||
|
||||
class _MaximizeWatch with WindowListener {
|
||||
final void Function(bool) onChange;
|
||||
_MaximizeWatch(this.onChange);
|
||||
@override
|
||||
void onWindowMaximize() => onChange(true);
|
||||
@override
|
||||
void onWindowUnmaximize() => onChange(false);
|
||||
}
|
||||
|
||||
/// Focus, blur, minimise and restore as [WindowActivity] (a restored
|
||||
/// window is shown; its focus event follows when it gets the keyboard).
|
||||
class _ActivityWatch with WindowListener {
|
||||
final void Function(WindowActivity) onChange;
|
||||
_ActivityWatch(this.onChange);
|
||||
@override
|
||||
void onWindowFocus() => onChange(WindowActivity.focused);
|
||||
@override
|
||||
void onWindowBlur() => onChange(WindowActivity.unfocused);
|
||||
@override
|
||||
void onWindowMinimize() => onChange(WindowActivity.minimised);
|
||||
@override
|
||||
void onWindowRestore() => onChange(WindowActivity.unfocused);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'dart:io';
|
||||
|
||||
import '../ports/url_opener.dart';
|
||||
|
||||
/// [UrlOpener] without url_launcher: `xdg-open`, `open` or Windows'
|
||||
/// `url.dll` handler.
|
||||
class DesktopUrls implements UrlOpener {
|
||||
const DesktopUrls();
|
||||
|
||||
@override
|
||||
Future<bool> open(String url) async {
|
||||
try {
|
||||
final ProcessResult r;
|
||||
if (Platform.isWindows) {
|
||||
r = await Process.run('rundll32', ['url.dll,FileProtocolHandler', url]);
|
||||
} else if (Platform.isMacOS) {
|
||||
r = await Process.run('open', [url]);
|
||||
} else {
|
||||
r = await Process.run('xdg-open', [url]);
|
||||
}
|
||||
return r.exitCode == 0;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi' show Int8;
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:ffi/ffi.dart' show StringUtf8Pointer, malloc;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:media_kit/media_kit.dart';
|
||||
import 'package:media_kit_video/media_kit_video.dart';
|
||||
import 'package:signals/signals.dart';
|
||||
import 'package:sync_relay_core/core.dart' show LogThrottle, createLogger;
|
||||
|
||||
import '../../state/settings.dart';
|
||||
import '../ports/player_host.dart';
|
||||
|
||||
// The desktop's players: media_kit over libmpv. Everything mpv-specific
|
||||
// that is not about one media lives here: the cache and HTTP pins, hwdec,
|
||||
// mpv's log level (media_kit has no API for it: `mpv_request_log_messages`
|
||||
// on its handle), the render-mode probe and its diagnostics, mpv's log into
|
||||
// the app log, and the order players are torn down in.
|
||||
|
||||
/// Read-ahead target: about two minutes rides out short outages and makes
|
||||
/// skipping an intro instant.
|
||||
const readAheadSecs = 150;
|
||||
|
||||
/// Forward demuxer cache of a session player. Holds [readAheadSecs] up to
|
||||
/// ~14 Mbit/s (a 1.4 GB / 24 min file is ~8); higher bitrates get less
|
||||
/// time. In RAM: `cache-on-disk=no` (media_kit sets it on without a
|
||||
/// cache-dir, and mpv warned "Failed to create file cache." per open).
|
||||
const sessionAheadBytes = 256 * 1024 * 1024;
|
||||
|
||||
/// Back buffer (media_kit sets it to bufferSize too): enough for a short
|
||||
/// seek back without holding another 256 MiB.
|
||||
const sessionBackBytes = 64 * 1024 * 1024;
|
||||
|
||||
/// The preload's forward cache: its first seconds and the container's
|
||||
/// index, at little memory. Raised to [sessionAheadBytes] when promoted.
|
||||
const preloadAheadBytes = 48 * 1024 * 1024;
|
||||
const preloadBackBytes = 8 * 1024 * 1024;
|
||||
|
||||
/// mpv's `volume-max` (its default is 130): the volume controls go this
|
||||
/// far, past 100 % amplified.
|
||||
const mpvMaxVolume = 150;
|
||||
|
||||
/// mpv's log level for session players. media_kit drains mpv's log on the
|
||||
/// UI thread one line at a time, so a chatty level (ffmpeg retrying a
|
||||
/// refused request logs every attempt) can starve the UI: warnings and
|
||||
/// errors only, except during the render-mode probe, which needs mpv's
|
||||
/// verbose GL init lines.
|
||||
const sessionLogLevel = 'warn';
|
||||
|
||||
/// ffmpeg's HTTP options (mpv `stream-lavf-o`, comma form): reconnect after
|
||||
/// a dropped connection, also on a streamed (growing) relay response, and a
|
||||
/// server error (5xx) while connecting; a refused request (4xx) fails at
|
||||
/// once. At most 3 tries per read, 4 s apart at most.
|
||||
const streamLavfOptions = 'reconnect_streamed=1,reconnect_on_http_error=5xx,'
|
||||
'reconnect_delay_max=4,reconnect_max_retries=3';
|
||||
|
||||
/// mpv echoes numbers in its own format (`150` reads back `150.000000`).
|
||||
bool pinMatches(String wanted, String got) {
|
||||
if (wanted == got) return true;
|
||||
final a = double.tryParse(wanted), b = double.tryParse(got);
|
||||
return a != null && b != null && a == b;
|
||||
}
|
||||
|
||||
/// The `VideoController` behind [video], for the `Video` widget (the only
|
||||
/// media_kit use outside this file).
|
||||
VideoController videoControllerOf(HostedVideo video) => (video as _MkVideo).controller;
|
||||
|
||||
final _mpvLog = createLogger('mpv');
|
||||
|
||||
class MediaKitHost implements PlayerHost {
|
||||
/// The hwdec setting ([AppSettings.hwdec] by default).
|
||||
final String? Function() _hwdecSetting;
|
||||
MediaKitHost({String? Function()? hwdecSetting})
|
||||
: _hwdecSetting = hwdecSetting ?? (() => AppSettings.instance.hwdec.peek());
|
||||
|
||||
final _live = <_MkPlayer>{};
|
||||
final _renderMode = signal(RenderMode.unknown);
|
||||
final _http = StreamController<String>.broadcast();
|
||||
final _throttle = LogThrottle(burst: 5);
|
||||
Future<void> _retiring = Future.value();
|
||||
var _closing = false;
|
||||
|
||||
@override
|
||||
final List<String> pinMismatches = [];
|
||||
|
||||
@override
|
||||
void init() => MediaKit.ensureInitialized();
|
||||
|
||||
@override
|
||||
ReadonlySignal<RenderMode> get renderMode => _renderMode;
|
||||
|
||||
@override
|
||||
Stream<String> get httpErrors => _http.stream;
|
||||
|
||||
@override
|
||||
int get live => _live.length;
|
||||
|
||||
@override
|
||||
Future<void> get retiring => _retiring;
|
||||
|
||||
@override
|
||||
String? get hwdec {
|
||||
final env = Platform.environment['SYNC_RELAY_HWDEC'];
|
||||
if (env != null && env.isNotEmpty) return env;
|
||||
return _hwdecSetting();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<HostedPlayer> create(PlayerRole role, {bool muted = false}) async {
|
||||
if (_closing) throw StateError('closing: no new players');
|
||||
final mk = _SyncPlayer(
|
||||
configuration: switch (role) {
|
||||
PlayerRole.session => PlayerConfiguration(
|
||||
bufferSize: sessionAheadBytes,
|
||||
libass: true,
|
||||
vo: Platform.environment['SYNC_RELAY_VO'],
|
||||
logLevel: MPVLogLevel.warn),
|
||||
PlayerRole.preload => PlayerConfiguration(
|
||||
bufferSize: preloadAheadBytes,
|
||||
libass: true,
|
||||
vo: Platform.environment['SYNC_RELAY_VO'],
|
||||
logLevel: MPVLogLevel.error),
|
||||
PlayerRole.thumbnail => const PlayerConfiguration(
|
||||
vo: 'null', muted: true, osc: false, libass: false, title: 'thumbnail', bufferSize: 4 << 20),
|
||||
});
|
||||
final p = _MkPlayer(this, mk, role);
|
||||
_live.add(p);
|
||||
if (role != PlayerRole.thumbnail) {
|
||||
p._logSub = p.logs.listen((l) => _route(p, l));
|
||||
final mismatches = <String>[];
|
||||
await _pinCache(p, role, mismatches);
|
||||
if (await p.pin('volume-max', '$mpvMaxVolume') case final m?) mismatches.add(m);
|
||||
if (muted || role == PlayerRole.preload) {
|
||||
if (await p.pin('mute', 'yes') case final m?) mismatches.add(m);
|
||||
}
|
||||
if (role == PlayerRole.session) {
|
||||
pinMismatches
|
||||
..clear()
|
||||
..addAll(mismatches);
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> promote(HostedPlayer p) async {
|
||||
final mk = p as _MkPlayer;
|
||||
mk._role = PlayerRole.session;
|
||||
mk.setLogLevel(sessionLogLevel);
|
||||
final mismatches = <String>[];
|
||||
if (await p.pin('mute', 'no') case final m?) mismatches.add(m);
|
||||
await _pinCache(mk, PlayerRole.session, mismatches);
|
||||
pinMismatches
|
||||
..clear()
|
||||
..addAll(mismatches);
|
||||
}
|
||||
|
||||
Future<void> _pinCache(_MkPlayer p, PlayerRole role, List<String> out) async {
|
||||
final session = role == PlayerRole.session;
|
||||
for (final (k, v) in [
|
||||
('demuxer-readahead-secs', '$readAheadSecs'),
|
||||
('cache-secs', '$readAheadSecs'),
|
||||
('demuxer-max-bytes', '${session ? sessionAheadBytes : preloadAheadBytes}'),
|
||||
('demuxer-max-back-bytes', '${session ? sessionBackBytes : preloadBackBytes}'),
|
||||
('cache-on-disk', 'no'),
|
||||
if (hwdec case final h?) ('hwdec', h),
|
||||
('stream-lavf-o', streamLavfOptions),
|
||||
// Pages are resolved by the app's own yt-dlp (the media pipeline):
|
||||
// mpv's Lua hook never runs one.
|
||||
('ytdl', 'no'),
|
||||
]) {
|
||||
if (await p.pin(k, v) case final m?) out.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
HostedVideo video(HostedPlayer player, {bool probe = false}) {
|
||||
final p = player as _MkPlayer;
|
||||
if (probe) {
|
||||
_logRenderEnv();
|
||||
p.setLogLevel('v'); // back to the session level at the probe's end
|
||||
}
|
||||
// media_kit's video output sets hwdec itself on attach ('auto' unless
|
||||
// configured), which used to override SYNC_RELAY_HWDEC.
|
||||
final controller = VideoController(p.mk, configuration: VideoControllerConfiguration(hwdec: hwdec));
|
||||
final v = _MkVideo(p, controller);
|
||||
// mpv gets `vo=libmpv` before the output's render context exists; a
|
||||
// media opened in between fails its video output ("No render context
|
||||
// set") and plays black. Opens wait for the output (seen on X11, where
|
||||
// the context comes up later, when joining with media already up).
|
||||
p._videoReady = controller.platform.future
|
||||
.then((_) {})
|
||||
.timeout(const Duration(seconds: 5), onTimeout: () {})
|
||||
.catchError((Object _) {});
|
||||
if (probe) unawaited(_probeRender(p, v));
|
||||
return v;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ the log
|
||||
|
||||
// mpv's warnings and errors to the app log, a few per kind at a time (a
|
||||
// refused request makes ffmpeg retry and warn on every try); ffmpeg's
|
||||
// HTTP status to [httpErrors]; the GL init lines while probing.
|
||||
void _route(_MkPlayer p, PlayerLogLine log) {
|
||||
if (log.prefix == 'ffmpeg') {
|
||||
final http = RegExp(r'HTTP error \d{3}.*').firstMatch(log.text);
|
||||
if (http != null) _http.add(http[0]!.trim());
|
||||
}
|
||||
if (log.prefix == 'libmpv_render') {
|
||||
if (_glInfo.hasMatch(log.text)) _mpvLog.info('render: [libmpv_render] ${log.text.trim()}');
|
||||
if (log.text.contains('suspected software renderer')) {
|
||||
_probeMode = RenderMode.softwareGl;
|
||||
_renderMode.value = RenderMode.softwareGl;
|
||||
} else if (log.text.startsWith('GL_VERSION') && p._probing && _probeMode == RenderMode.unknown) {
|
||||
_probeMode = RenderMode.gpu;
|
||||
_renderMode.value = RenderMode.gpu;
|
||||
}
|
||||
}
|
||||
final level = log.level;
|
||||
if (level != 'warn' && !log.isError) return;
|
||||
final text = log.text.trim();
|
||||
if (text.isEmpty) return;
|
||||
final who = p.role == PlayerRole.preload ? 'preload ' : '';
|
||||
final pass = _throttle.allow('$who${log.prefix} $level ${text.length > 40 ? text.substring(0, 40) : text}');
|
||||
if (pass == null) return;
|
||||
final line = '$pass$who[${log.prefix}] $text';
|
||||
level == 'warn' ? _mpvLog.info(line) : _mpvLog.warning(line);
|
||||
}
|
||||
|
||||
// mpv's GL init lines (`GL_VENDOR='...'`, `Detected desktop OpenGL 4.6.`).
|
||||
static final _glInfo =
|
||||
RegExp(r'^\s*(GL_(VENDOR|RENDERER|VERSION|SHADING_LANGUAGE_VERSION)=|Detected (GLES|desktop OpenGL))');
|
||||
|
||||
// Once per app start: what decides how media_kit and mpv render (the
|
||||
// display server, Flutter's and Mesa's overrides). Not secrets.
|
||||
static bool _renderEnvLogged = false;
|
||||
static void _logRenderEnv() {
|
||||
if (_renderEnvLogged || !Platform.isLinux) return;
|
||||
_renderEnvLogged = true;
|
||||
const names = [
|
||||
'XDG_SESSION_TYPE',
|
||||
'WAYLAND_DISPLAY',
|
||||
'DISPLAY',
|
||||
'GDK_BACKEND',
|
||||
'FLUTTER_LINUX_RENDERER',
|
||||
'LIBGL_ALWAYS_SOFTWARE',
|
||||
'__EGL_VENDOR_LIBRARY_FILENAMES',
|
||||
];
|
||||
final env = Platform.environment;
|
||||
_mpvLog.info('render env: ${[for (final n in names) '$n=${env[n] ?? '-'}'].join(' ')}');
|
||||
}
|
||||
|
||||
RenderMode _probeMode = RenderMode.unknown;
|
||||
|
||||
// media_kit's Linux/Windows video output creates mpv's render context
|
||||
// while the controller is created: OpenGL when it can, else the software
|
||||
// renderer, which never logs GL init (and ignores shaders). No GL line
|
||||
// within 1.5 s of the output being up means software.
|
||||
Future<void> _probeRender(_MkPlayer p, _MkVideo v) async {
|
||||
p._probing = true;
|
||||
_probeMode = RenderMode.unknown;
|
||||
try {
|
||||
await v.controller.platform.future;
|
||||
await Future.delayed(const Duration(milliseconds: 1500));
|
||||
} catch (_) {
|
||||
return;
|
||||
} finally {
|
||||
p._probing = false;
|
||||
if (!p.disposed) p.setLogLevel(sessionLogLevel);
|
||||
}
|
||||
if (p.disposed) return;
|
||||
final mode = _probeMode;
|
||||
if (mode != RenderMode.unknown) {
|
||||
_renderMode.value = mode;
|
||||
_mpvLog.info('render: ${mode.name} (${mode == RenderMode.gpu ? 'OpenGL on the GPU' : 'OpenGL on the CPU'})');
|
||||
return;
|
||||
}
|
||||
_renderMode.value = RenderMode.software;
|
||||
_mpvLog.info("render: software (no GL init logged: media_kit's own fallback; "
|
||||
'its reason is on stderr, "media_kit: VideoOutput: ..." when run from a terminal)');
|
||||
}
|
||||
|
||||
// Once per player, after its first frame: the decoder mpv picked; the
|
||||
// first time per app start also mpv's and ffmpeg's versions.
|
||||
static bool _versionsLogged = false;
|
||||
Future<void> _logFirstFrame(_MkPlayer p) async {
|
||||
try {
|
||||
final current = await p.getProperty('hwdec-current');
|
||||
final wanted = await p.getProperty('hwdec');
|
||||
_mpvLog.info('render: first frame ${p.state.width}x${p.state.height}, '
|
||||
'hwdec-current=${current.isEmpty ? 'no' : current} (hwdec=$wanted), mode ${_renderMode.peek().name}');
|
||||
if (!_versionsLogged) {
|
||||
_versionsLogged = true;
|
||||
_mpvLog.info('render: ${await versions(p)}');
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('first frame info: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> versions(HostedPlayer player) async {
|
||||
try {
|
||||
return '${await player.getProperty('mpv-version')}, ffmpeg ${await player.getProperty('ffmpeg-version')}';
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------- tear-down
|
||||
|
||||
@override
|
||||
Future<void> retire(HostedPlayer player) {
|
||||
final p = player as _MkPlayer;
|
||||
p._retired = true;
|
||||
unawaited(p.mk.pause().catchError((_) {}));
|
||||
return _retiring = () async {
|
||||
await _settleUi();
|
||||
await dispose(p);
|
||||
}();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> dispose(HostedPlayer player) async {
|
||||
final p = player as _MkPlayer;
|
||||
if (!_live.remove(p)) return;
|
||||
p._retired = true;
|
||||
await p._logSub?.cancel();
|
||||
try {
|
||||
await p.mk.dispose();
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> disposeAll({Duration each = const Duration(milliseconds: 1500)}) async {
|
||||
_closing = true;
|
||||
await Future.wait([
|
||||
for (final p in _live.toList()) dispose(p).timeout(each).catchError((Object _) {}),
|
||||
]);
|
||||
_closing = false;
|
||||
}
|
||||
|
||||
// Two frames: one may already be mid-build when the view drops the
|
||||
// output. Then the length of a route pop (the fullscreen route holds its
|
||||
// own `Video` and leaves animated). Bounded, since a hidden window
|
||||
// renders no frames; headless tests have no binding and skip it all.
|
||||
static Future<void> _settleUi() async {
|
||||
try {
|
||||
for (var i = 0; i < 2; i++) {
|
||||
await WidgetsBinding.instance.endOfFrame.timeout(const Duration(milliseconds: 300));
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 350));
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
||||
/// A [Player] whose public [seek] belongs to the user. media_kit's controls
|
||||
/// call `player.seek`; with [onUserSeek] set those calls become explicit
|
||||
/// events for the sync layer instead of moving mpv behind its back.
|
||||
class _SyncPlayer extends Player {
|
||||
_SyncPlayer({super.configuration});
|
||||
|
||||
void Function(Duration position)? onUserSeek;
|
||||
|
||||
@override
|
||||
Future<void> seek(Duration duration) async {
|
||||
final hook = onUserSeek;
|
||||
if (hook == null) return super.seek(duration);
|
||||
hook(duration);
|
||||
}
|
||||
|
||||
Future<void> syncSeek(Duration duration) => super.seek(duration);
|
||||
}
|
||||
|
||||
class _MkPlayer implements HostedPlayer {
|
||||
final MediaKitHost host;
|
||||
final _SyncPlayer mk;
|
||||
PlayerRole _role;
|
||||
_MkPlayer(this.host, this.mk, this._role) {
|
||||
_firstFrame = mk.stream.width.listen((w) {
|
||||
if (w == null || w <= 0 || _role == PlayerRole.thumbnail) return;
|
||||
unawaited(_firstFrame?.cancel());
|
||||
unawaited(host._logFirstFrame(this));
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription<PlayerLogLine>? _logSub;
|
||||
StreamSubscription<int?>? _firstFrame;
|
||||
bool _probing = false;
|
||||
bool _retired = false;
|
||||
Future<void>? _videoReady; // set once a video output is attached
|
||||
|
||||
dynamic get _mpv => mk.platform;
|
||||
|
||||
@override
|
||||
PlayerRole get role => _role;
|
||||
|
||||
@override
|
||||
bool get disposed => _retired;
|
||||
|
||||
@override
|
||||
HostedPlayerState get state {
|
||||
final s = mk.state;
|
||||
return HostedPlayerState(
|
||||
position: s.position,
|
||||
duration: s.duration,
|
||||
buffer: s.buffer,
|
||||
volume: s.volume,
|
||||
playing: s.playing,
|
||||
completed: s.completed,
|
||||
width: s.width,
|
||||
height: s.height,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<Duration> get positionStream => mk.stream.position;
|
||||
@override
|
||||
Stream<Duration> get durationStream => mk.stream.duration;
|
||||
@override
|
||||
Stream<Duration> get bufferStream => mk.stream.buffer;
|
||||
@override
|
||||
Stream<double> get volumeStream => mk.stream.volume;
|
||||
@override
|
||||
Stream<bool> get completedStream => mk.stream.completed;
|
||||
@override
|
||||
Stream<int?> get widthStream => mk.stream.width;
|
||||
@override
|
||||
Stream<PlayerLogLine> get logs => mk.stream.log.map((l) => PlayerLogLine(l.prefix, l.level, l.text));
|
||||
|
||||
@override
|
||||
void Function(Duration position)? get onUserSeek => mk.onUserSeek;
|
||||
@override
|
||||
set onUserSeek(void Function(Duration position)? f) => mk.onUserSeek = f;
|
||||
|
||||
@override
|
||||
Future<void> open(String url, {Map<String, String> headers = const {}, bool play = false}) async {
|
||||
if (_videoReady case final ready?) await ready;
|
||||
// An empty map, not null: media_kit caches headers per URI.
|
||||
await mk.open(Media(url, httpHeaders: headers), play: play);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> play() => mk.play();
|
||||
@override
|
||||
Future<void> pause() => mk.pause();
|
||||
@override
|
||||
Future<void> stop() => mk.stop();
|
||||
@override
|
||||
Future<void> seek(Duration position) => mk.seek(position);
|
||||
@override
|
||||
Future<void> syncSeek(Duration position) => mk.syncSeek(position);
|
||||
@override
|
||||
Future<void> setRate(double rate) => mk.setRate(rate);
|
||||
@override
|
||||
Future<void> setVolume(double volume) => mk.setVolume(volume);
|
||||
|
||||
// media_kit has no public property API: a guarded dynamic call on
|
||||
// `player.platform` (its NativePlayer).
|
||||
@override
|
||||
Future<void> setProperty(String name, String value) async => await _mpv?.setProperty(name, value);
|
||||
|
||||
@override
|
||||
Future<String> getProperty(String name) async => '${await _mpv?.getProperty(name)}';
|
||||
|
||||
@override
|
||||
Future<void> observeProperty(String name, Future<void> Function(String value) onChange) async =>
|
||||
await _mpv?.observeProperty(name, onChange);
|
||||
|
||||
@override
|
||||
Future<void> command(List<String> args) async => await _mpv?.command(args);
|
||||
|
||||
@override
|
||||
Future<String?> pin(String name, String value) async {
|
||||
try {
|
||||
await setProperty(name, value);
|
||||
final got = await getProperty(name);
|
||||
if (pinMatches(value, got)) return null;
|
||||
debugPrint('pin $name=$value not applied, mpv has "$got"');
|
||||
return '$name: $value -> $got';
|
||||
} catch (e) {
|
||||
debugPrint('pin $name=$value failed: $e');
|
||||
return '$name: $value -> error $e';
|
||||
}
|
||||
}
|
||||
|
||||
// mpv_request_log_messages on media_kit's handle.
|
||||
@override
|
||||
void setLogLevel(String level) {
|
||||
try {
|
||||
final dynamic platform = mk.platform;
|
||||
final name = level.toNativeUtf8();
|
||||
try {
|
||||
platform.mpv.mpv_request_log_messages(platform.ctx, name.cast<Int8>());
|
||||
} finally {
|
||||
malloc.free(name);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('mpv log level $level not set: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _MkVideo implements HostedVideo {
|
||||
@override
|
||||
final _MkPlayer player;
|
||||
final VideoController controller;
|
||||
_MkVideo(this.player, this.controller);
|
||||
|
||||
@override
|
||||
Future<void> get ready => controller.platform.future;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive_ce_flutter/hive_flutter.dart';
|
||||
import 'package:screen_retriever/screen_retriever.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
/// The window's size, position and maximized state across restarts (and
|
||||
/// hot restarts), in the settings box. The size and position kept are
|
||||
/// the normal (unmaximized) ones; fullscreen is never saved or restored.
|
||||
/// Wayland lets no app place its own window, so there only the size and
|
||||
/// maximized state come back (the compositor decides the position).
|
||||
class WindowMemory with WindowListener {
|
||||
static const _key = 'windowBounds';
|
||||
static const defaultSize = Size(1280, 720);
|
||||
|
||||
// Null when the settings box failed to open: defaults, nothing saved.
|
||||
final Box? _box;
|
||||
Timer? _save;
|
||||
WindowMemory(this._box);
|
||||
|
||||
static bool get _canPlace => !(Platform.isLinux && Platform.environment['WAYLAND_DISPLAY'] != null);
|
||||
|
||||
Map? get _saved => _box?.get(_key) is Map ? _box!.get(_key) as Map : null;
|
||||
|
||||
/// The size to open at: the last normal size, else [defaultSize].
|
||||
Size get size {
|
||||
final s = _saved;
|
||||
final w = s?['w'], h = s?['h'];
|
||||
return w is num && h is num && w >= 160 && h >= 90 ? Size(w.toDouble(), h.toDouble()) : defaultSize;
|
||||
}
|
||||
|
||||
/// Whether a saved position exists to place the window at (else center).
|
||||
bool get hasPosition => _canPlace && _saved?['x'] is num && _saved?['y'] is num;
|
||||
|
||||
/// After the window shows: back to the saved position when it still
|
||||
/// lands on a connected display, maximized when it was; then listens.
|
||||
Future<void> restore() async {
|
||||
final s = _saved;
|
||||
try {
|
||||
if (s != null && hasPosition) {
|
||||
final rect = Offset((s['x'] as num).toDouble(), (s['y'] as num).toDouble()) & size;
|
||||
if (await _onSomeDisplay(rect)) {
|
||||
await windowManager.setPosition(rect.topLeft);
|
||||
} else {
|
||||
await windowManager.center();
|
||||
}
|
||||
}
|
||||
if (s?['max'] == true) await windowManager.maximize();
|
||||
} catch (e) {
|
||||
debugPrint('window restore failed: $e');
|
||||
}
|
||||
windowManager.addListener(this);
|
||||
}
|
||||
|
||||
// At least a 100×50 corner of the title area on a display's visible area.
|
||||
static Future<bool> _onSomeDisplay(Rect r) async {
|
||||
final grip = Rect.fromLTWH(r.left, r.top, r.width.clamp(0, 100).toDouble(), 50);
|
||||
for (final d in await screenRetriever.getAllDisplays()) {
|
||||
final area = (d.visiblePosition ?? Offset.zero) & (d.visibleSize ?? d.size);
|
||||
if (area.overlaps(grip)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _later() {
|
||||
_save?.cancel();
|
||||
_save = Timer(const Duration(milliseconds: 400), () => unawaited(save()));
|
||||
}
|
||||
|
||||
/// Writes the current state now (also on close).
|
||||
Future<void> save() async {
|
||||
_save?.cancel();
|
||||
final box = _box;
|
||||
if (box == null) return;
|
||||
try {
|
||||
if (await windowManager.isFullScreen() || await windowManager.isMinimized()) return;
|
||||
final max = await windowManager.isMaximized();
|
||||
final s = Map<String, Object?>.of((_saved ?? const {}).cast<String, Object?>());
|
||||
s['max'] = max;
|
||||
if (!max) {
|
||||
final b = await windowManager.getBounds();
|
||||
s['w'] = b.width;
|
||||
s['h'] = b.height;
|
||||
if (_canPlace) {
|
||||
s['x'] = b.left;
|
||||
s['y'] = b.top;
|
||||
}
|
||||
}
|
||||
await box.put(_key, s);
|
||||
} catch (e) {
|
||||
debugPrint('window save failed: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onWindowResized() => _later();
|
||||
@override
|
||||
void onWindowMoved() => _later();
|
||||
@override
|
||||
void onWindowMaximize() => _later();
|
||||
@override
|
||||
void onWindowUnmaximize() => _later();
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sync_relay_core/core.dart' show findInstallRoot;
|
||||
|
||||
/// The app's id: GTK's application id, so the Wayland `app_id` the
|
||||
/// compositor matches to [desktopFileName] for the window's icon.
|
||||
const appId = 'dev.foxyz.starsync';
|
||||
const desktopFileName = '$appId.desktop';
|
||||
|
||||
/// The app id up to 1.2.x: its entry and icons are removed (only those
|
||||
/// exact files, which that version wrote).
|
||||
const legacyAppId = 'moe.senkochan.watch_together';
|
||||
|
||||
const _iconSizes = [16, 32, 48, 64, 128, 256, 512];
|
||||
|
||||
/// Linux release installs (an unpacked tarball) carry no launcher entry, so
|
||||
/// Wayland shows a generic icon. On start: write the `.desktop` file into
|
||||
/// `~/.local/share/applications` (Exec = this binary) and the icon into
|
||||
/// the hicolor theme, only when something changed (a moved install, a new
|
||||
/// icon). The entry and icons of [legacyAppId] go. Never in debug runs
|
||||
/// (unless [force], for tests); failures only log.
|
||||
Future<void> installDesktopEntry(
|
||||
{String? executable, String? dataHome, String? home, @visibleForTesting bool force = false}) async {
|
||||
if (!Platform.isLinux || (kDebugMode && !force)) return;
|
||||
try {
|
||||
final exe = executable ?? Platform.resolvedExecutable;
|
||||
final root = findInstallRoot(exe, windows: false);
|
||||
if (root == null) return;
|
||||
final share = dataHome ?? Platform.environment['XDG_DATA_HOME'] ??
|
||||
'${home ?? Platform.environment['HOME']}/.local/share';
|
||||
final icons = '${root.path}/data/flutter_assets/assets/icon';
|
||||
await _removeLegacy(share);
|
||||
for (final size in _iconSizes) {
|
||||
final src = File('$icons/icon_$size.png');
|
||||
if (!src.existsSync()) continue;
|
||||
final dst = File('$share/icons/hicolor/${size}x$size/apps/$appId.png');
|
||||
if (dst.existsSync() && dst.lengthSync() == src.lengthSync()) continue;
|
||||
await dst.parent.create(recursive: true);
|
||||
await src.copy(dst.path);
|
||||
}
|
||||
final entry = desktopEntryText(exe);
|
||||
final file = File('$share/applications/$desktopFileName');
|
||||
if (file.existsSync() && file.readAsStringSync() == entry) return;
|
||||
await file.parent.create(recursive: true);
|
||||
await file.writeAsString(entry);
|
||||
} catch (e) {
|
||||
debugPrint('desktop entry: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _removeLegacy(String share) async {
|
||||
for (final f in [
|
||||
File('$share/applications/$legacyAppId.desktop'),
|
||||
for (final size in _iconSizes) File('$share/icons/hicolor/${size}x$size/apps/$legacyAppId.png'),
|
||||
]) {
|
||||
if (!f.existsSync()) continue;
|
||||
try {
|
||||
await f.delete();
|
||||
debugPrint('desktop entry: removed ${f.path}');
|
||||
} catch (e) {
|
||||
debugPrint('desktop entry: cannot remove ${f.path}: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
String desktopEntryText(String exe) => '''[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Starsync
|
||||
Comment=Watch videos in sync with friends
|
||||
Exec="$exe"
|
||||
Icon=$appId
|
||||
StartupWMClass=$appId
|
||||
Categories=AudioVideo;Video;Player;Network;
|
||||
Terminal=false
|
||||
''';
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'dart:io';
|
||||
|
||||
/// The environment variable that picks a separate profile (DEVELOPMENT.md
|
||||
/// "Dev loop": two instances on one machine).
|
||||
const profileEnv = 'STARSYNC_PROFILE';
|
||||
|
||||
/// Where the app keeps its own files, resolved once in `main` through an
|
||||
/// [AppDirsPort] and handed on from there.
|
||||
///
|
||||
/// Everything lives in the app support folder: Hive's boxes in
|
||||
/// `<app support>/hive`, the logs in `<app support>/logs`. With
|
||||
/// `STARSYNC_PROFILE=<name>` (letters, digits, `-`, `_`; at most 32) the
|
||||
/// per-install data moves to `<app support>/profiles/<name>/`: the Hive
|
||||
/// boxes (settings and so the profile, connect form, window bounds,
|
||||
/// folders, Jellyfin sign-ins; the client id from restructure step 1 on)
|
||||
/// under `hive/`, the logs under `logs/`. Downloads and caches stay
|
||||
/// shared: yt-dlp and its cookies, the extracted shaders, thumbnails, the
|
||||
/// AniList cache.
|
||||
class AppDirs {
|
||||
/// The profile name; null for the normal app.
|
||||
final String? profile;
|
||||
/// The app support folder (yt-dlp, shaders; Hive and logs without a
|
||||
/// profile).
|
||||
final String support;
|
||||
/// Hive's folder.
|
||||
final String hive;
|
||||
/// The app's log folder.
|
||||
final String logs;
|
||||
/// What resolving copied over from before the rename, one line each
|
||||
/// (paths and counts), for the log once it is open.
|
||||
final List<String> migrated;
|
||||
|
||||
const AppDirs(
|
||||
{required this.profile,
|
||||
required this.support,
|
||||
required this.hive,
|
||||
required this.logs,
|
||||
this.migrated = const []});
|
||||
|
||||
/// The layout for [support] (the app support folder) and [env]; an
|
||||
/// invalid profile name is ignored ([invalidProfile] says which).
|
||||
static AppDirs fromEnv(
|
||||
{required String support, required Map<String, String> env, List<String> migrated = const []}) {
|
||||
final sep = Platform.pathSeparator;
|
||||
final name = validProfile(env[profileEnv]);
|
||||
final root = name == null ? support : '$support${sep}profiles$sep$name';
|
||||
return AppDirs(
|
||||
profile: name, support: support, hive: '$root${sep}hive', logs: '$root${sep}logs', migrated: migrated);
|
||||
}
|
||||
|
||||
/// [raw] when it is a usable profile name, else null.
|
||||
static String? validProfile(String? raw) {
|
||||
final v = raw?.trim() ?? '';
|
||||
return RegExp(r'^[A-Za-z0-9_-]{1,32}$').hasMatch(v) ? v : null;
|
||||
}
|
||||
|
||||
/// The env value when it is set but not a usable name (for a warning).
|
||||
static String? invalidProfile(Map<String, String> env) {
|
||||
final raw = env[profileEnv];
|
||||
return raw != null && raw.trim().isNotEmpty && validProfile(raw) == null ? raw : null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the app's folders on this platform (and, the first time, brings
|
||||
/// over the data of the names before the rename).
|
||||
abstract interface class AppDirsPort {
|
||||
/// The layout for this process; its Hive folder exists afterwards.
|
||||
Future<AppDirs> resolve();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'dart:io' show FileStat;
|
||||
|
||||
import '../../files/scanner.dart' show FolderScan;
|
||||
|
||||
/// The user's folders and files: picking them, listing videos, looking a
|
||||
/// path up. Paths for now; a platform without them (Android's tree URIs)
|
||||
/// brings its own implementation.
|
||||
abstract interface class FolderAccess {
|
||||
/// The system folder dialog; null when cancelled.
|
||||
Future<String?> pickFolder({required String dialogTitle});
|
||||
|
||||
/// The system file dialog limited to [extensions]; the picked paths
|
||||
/// (empty when cancelled).
|
||||
Future<List<String>> pickFiles({required String dialogTitle, required List<String> extensions});
|
||||
|
||||
/// The videos under [dir] (see [FolderScan]); never throws.
|
||||
Future<FolderScan> scan(String dir);
|
||||
|
||||
/// Whether the folder [dir] exists.
|
||||
bool folderExists(String dir);
|
||||
|
||||
/// Size and dates of [path]; throws when it is gone.
|
||||
Future<FileStat> stat(String path);
|
||||
|
||||
/// Shows the folder [dir] in the file manager; false when nothing
|
||||
/// opened it.
|
||||
Future<bool> reveal(String dir);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:sync_relay_core/core.dart' show LinkProbe, YtDlp;
|
||||
|
||||
/// Web page links: what they are and how they play, through the app's
|
||||
/// yt-dlp (a process on desktop).
|
||||
abstract interface class LinkResolver {
|
||||
/// The yt-dlp behind it (relaying a link, cookies, the hosted server's
|
||||
/// shared folder).
|
||||
Future<YtDlp> get ytDlp;
|
||||
|
||||
/// Gets it ready in the background (download on first run, updates).
|
||||
void warmUp();
|
||||
|
||||
/// This device opens web pages itself (the media plan's `resolve`
|
||||
/// capability). Desktop: always (yt-dlp is downloaded when first
|
||||
/// needed); a device without it gets pages passed on by someone else.
|
||||
bool get resolvesLinks;
|
||||
|
||||
/// What [url] is, remembered for a while ([keep]); [fresh] asks again.
|
||||
Future<LinkProbe> probe(String url, {Duration keep, bool fresh});
|
||||
|
||||
/// [url] no longer needs keeping longer than usual.
|
||||
void release(String url);
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:signals/signals.dart';
|
||||
|
||||
// The media players as the app sees them: mpv instances, their video
|
||||
// outputs, how the video is rendered, mpv's log and the order players are
|
||||
// torn down in. Desktop: media_kit over libmpv
|
||||
// (`platform/desktop/media_kit_host.dart`); nothing else in the app
|
||||
// touches media_kit except the `Video` widget glue.
|
||||
|
||||
/// How the video output renders (shaders need [gpu]).
|
||||
enum RenderMode {
|
||||
unknown,
|
||||
|
||||
/// OpenGL on a real GPU: shaders work.
|
||||
gpu,
|
||||
|
||||
/// OpenGL on a software rasterizer (llvmpipe): shaders crawl.
|
||||
softwareGl,
|
||||
|
||||
/// The video output's own software fallback: shaders are ignored.
|
||||
software,
|
||||
}
|
||||
|
||||
/// What a player is for: its cache, log level and log routing.
|
||||
enum PlayerRole {
|
||||
/// The session's player (and a fresh one per media): full cache, mpv log
|
||||
/// at `warn` into the app log.
|
||||
session,
|
||||
|
||||
/// The hidden player holding what plays next: small cache, muted, log
|
||||
/// at `error`.
|
||||
preload,
|
||||
|
||||
/// A poster frame for Files: no audio or video output, no cache, no log.
|
||||
thumbnail,
|
||||
}
|
||||
|
||||
/// One line of mpv's log.
|
||||
class PlayerLogLine {
|
||||
final String prefix;
|
||||
final String level;
|
||||
final String text;
|
||||
const PlayerLogLine(this.prefix, this.level, this.text);
|
||||
|
||||
bool get isError => level == 'error' || level == 'fatal';
|
||||
}
|
||||
|
||||
/// A snapshot of a player's state.
|
||||
class HostedPlayerState {
|
||||
final Duration position;
|
||||
final Duration duration;
|
||||
|
||||
/// End of the cached range (mpv `demuxer-cache-time`).
|
||||
final Duration buffer;
|
||||
final double volume;
|
||||
final bool playing;
|
||||
|
||||
/// At the end of the file.
|
||||
final bool completed;
|
||||
final int? width;
|
||||
final int? height;
|
||||
const HostedPlayerState({
|
||||
this.position = Duration.zero,
|
||||
this.duration = Duration.zero,
|
||||
this.buffer = Duration.zero,
|
||||
this.volume = 100,
|
||||
this.playing = false,
|
||||
this.completed = false,
|
||||
this.width,
|
||||
this.height,
|
||||
});
|
||||
}
|
||||
|
||||
/// One mpv player. Each media gets its own (see ARCHITECTURE "Player
|
||||
/// lifecycle"); [PlayerHost.retire] / [PlayerHost.disposeAll] end it.
|
||||
abstract interface class HostedPlayer {
|
||||
PlayerRole get role;
|
||||
HostedPlayerState get state;
|
||||
Stream<Duration> get positionStream;
|
||||
Stream<Duration> get durationStream;
|
||||
Stream<Duration> get bufferStream;
|
||||
Stream<double> get volumeStream;
|
||||
Stream<bool> get completedStream;
|
||||
Stream<int?> get widthStream;
|
||||
|
||||
/// mpv's log lines at the player's level.
|
||||
Stream<PlayerLogLine> get logs;
|
||||
|
||||
/// The player is gone (disposed or being disposed): commands do nothing.
|
||||
bool get disposed;
|
||||
|
||||
/// Seeks from the video widget's own controls land here instead of in
|
||||
/// mpv when set ([seek] goes through it too); [syncSeek] always moves
|
||||
/// mpv.
|
||||
void Function(Duration position)? onUserSeek;
|
||||
|
||||
/// Opens [url] (with [headers] on every request), paused unless [play].
|
||||
Future<void> open(String url, {Map<String, String> headers = const {}, bool play = false});
|
||||
Future<void> play();
|
||||
Future<void> pause();
|
||||
Future<void> stop();
|
||||
|
||||
/// A user seek: through [onUserSeek] when set, else [syncSeek].
|
||||
Future<void> seek(Duration position);
|
||||
|
||||
/// Moves mpv (sync corrections, scrub preview).
|
||||
Future<void> syncSeek(Duration position);
|
||||
Future<void> setRate(double rate);
|
||||
Future<void> setVolume(double volume);
|
||||
Future<void> setProperty(String name, String value);
|
||||
Future<String> getProperty(String name);
|
||||
Future<void> observeProperty(String name, Future<void> Function(String value) onChange);
|
||||
Future<void> command(List<String> args);
|
||||
|
||||
/// Sets [name] and reads it back: null when mpv took [value], else
|
||||
/// `name: value -> got` (mpv ignores invalid values silently).
|
||||
Future<String?> pin(String name, String value);
|
||||
|
||||
/// mpv's log level for this player (`warn`, `v`, ...).
|
||||
void setLogLevel(String level);
|
||||
}
|
||||
|
||||
/// A player's video output (a texture the `Video` widget shows).
|
||||
abstract interface class HostedVideo {
|
||||
HostedPlayer get player;
|
||||
|
||||
/// Completes once the output is up (its texture registered).
|
||||
Future<void> get ready;
|
||||
}
|
||||
|
||||
/// Creates, owns and disposes the app's players. One per app (the
|
||||
/// composition root's `Ports`); tests make their own.
|
||||
abstract interface class PlayerHost {
|
||||
/// Once at start, before any player.
|
||||
void init();
|
||||
|
||||
/// A new player for [role], set up before it is returned to the caller's
|
||||
/// first await: cache, pins ([pinMismatches]), hwdec, log level.
|
||||
Future<HostedPlayer> create(PlayerRole role, {bool muted = false});
|
||||
|
||||
/// [player] (a preload) becomes a session player: unmuted, the full
|
||||
/// cache pins, the session's log level.
|
||||
Future<void> promote(HostedPlayer player);
|
||||
|
||||
/// [player]'s video output, with the hwdec policy. [probe]: listen to
|
||||
/// mpv's render init to learn [renderMode] (the first output of an app
|
||||
/// start).
|
||||
HostedVideo video(HostedPlayer player, {bool probe = false});
|
||||
|
||||
/// How video renders, as last learned (kept after leaving).
|
||||
ReadonlySignal<RenderMode> get renderMode;
|
||||
|
||||
/// mpv `hwdec` for new players: env `SYNC_RELAY_HWDEC` wins over the
|
||||
/// setting (Windows' auto is `auto-copy`).
|
||||
String? get hwdec;
|
||||
|
||||
/// Pins that did not take on the last session player created.
|
||||
List<String> get pinMismatches;
|
||||
|
||||
/// ffmpeg's HTTP errors (`HTTP error 403 Forbidden`), from whichever
|
||||
/// player ffmpeg logs through (one per process).
|
||||
Stream<String> get httpErrors;
|
||||
|
||||
/// `mpv-version` and `ffmpeg-version` of [player], for diagnostics.
|
||||
Future<String?> versions(HostedPlayer player);
|
||||
|
||||
/// Ends [player] once the view let go of its texture (two frames and a
|
||||
/// route pop); at most one retiring player lingers, a new [create] of a
|
||||
/// session player waits for it ([retiring]).
|
||||
Future<void> retire(HostedPlayer player);
|
||||
|
||||
/// The last retire, until done.
|
||||
Future<void> get retiring;
|
||||
|
||||
/// Disposes [player] at once (no view showed it).
|
||||
Future<void> dispose(HostedPlayer player);
|
||||
|
||||
/// App close: every live player goes, each bounded by [each], before
|
||||
/// the engine does (a live mpv calls back into a dead isolate).
|
||||
Future<void> disposeAll({Duration each});
|
||||
|
||||
/// Live players, for tests and the close.
|
||||
int get live;
|
||||
}
|
||||
|
||||
/// [log] says the media could not be opened: before a [duration] is known,
|
||||
/// mpv's fatal "nothing to play" or a demuxer error.
|
||||
bool mpvLoadFailed(PlayerLogLine log, Duration duration) {
|
||||
return duration == Duration.zero &&
|
||||
((log.prefix == 'cplayer' && log.level == 'fatal') || (log.prefix == 'demux' && log.level == 'error'));
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import 'folder_access.dart';
|
||||
import 'link_resolver.dart';
|
||||
import 'player_host.dart';
|
||||
import 'shell_port.dart';
|
||||
import 'system_notifications.dart';
|
||||
import 'url_opener.dart';
|
||||
|
||||
export 'app_dirs.dart';
|
||||
export 'folder_access.dart';
|
||||
export 'link_resolver.dart';
|
||||
export 'player_host.dart';
|
||||
export 'shell_port.dart';
|
||||
export 'system_notifications.dart';
|
||||
export 'url_opener.dart';
|
||||
|
||||
/// The platform as the app sees it: one set, made in the composition
|
||||
/// root ([AppGraph]) and handed on from there.
|
||||
class Ports {
|
||||
final ShellPort shell;
|
||||
final UrlOpener urls;
|
||||
final FolderAccess folders;
|
||||
final LinkResolver links;
|
||||
final SystemNotifications notifications;
|
||||
/// The media players (mpv): created, rendered and disposed here.
|
||||
final PlayerHost players;
|
||||
const Ports({
|
||||
required this.shell,
|
||||
required this.urls,
|
||||
required this.folders,
|
||||
required this.links,
|
||||
required this.notifications,
|
||||
required this.players,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'window_activity.dart';
|
||||
|
||||
export 'window_activity.dart';
|
||||
|
||||
/// What the clipboard holds for a paste: its files, else its text.
|
||||
typedef Paste = ({List<String> files, String? text});
|
||||
|
||||
/// The app window and what the desktop hands it (drops, pastes). The
|
||||
/// desktop implementation wraps window_manager and fox_utils
|
||||
/// ([DesktopShell]); another platform brings its own.
|
||||
abstract interface class ShellPort {
|
||||
/// Before the first frame: the window shown at its remembered size and
|
||||
/// place; a close request (close button, Alt+F4) runs [onCloseRequest]
|
||||
/// instead of closing.
|
||||
Future<void> start({required String title, required Future<void> Function() onCloseRequest});
|
||||
|
||||
Future<void> setFullScreen(bool on);
|
||||
Future<void> minimize();
|
||||
Future<bool> isMaximized();
|
||||
Future<void> maximize();
|
||||
Future<void> unmaximize();
|
||||
|
||||
/// Calls [onChange] whenever the window is maximized or restored;
|
||||
/// returns the call that stops it.
|
||||
void Function() watchMaximized(void Function(bool maximized) onChange);
|
||||
|
||||
/// Calls [onChange] whenever the window gains or loses the focus, is
|
||||
/// minimised, restored or hidden; returns the call that stops it.
|
||||
void Function() watchActivity(void Function(WindowActivity activity) onChange);
|
||||
|
||||
/// Moves the window with the pointer (a press on the title area).
|
||||
Future<void> startDragging();
|
||||
|
||||
/// Asks to close the window: the same path as the close button.
|
||||
Future<void> requestClose();
|
||||
|
||||
/// The way out: remembers the window, hides it ([hide]), and later
|
||||
/// closes it for good ([quit]).
|
||||
Future<void> saveWindow();
|
||||
Future<void> hide();
|
||||
Future<void> quit();
|
||||
|
||||
/// Brings the window up and gives it the focus (restored when
|
||||
/// minimised, shown when hidden): a click on a system notification.
|
||||
Future<void> focus();
|
||||
|
||||
/// Points the desktop at the window when it is not focused (taskbar
|
||||
/// flash, urgency hint); nothing when it is.
|
||||
Future<void> requestAttention();
|
||||
|
||||
/// The clipboard's files, else its text (Ctrl+V outside a text field).
|
||||
Future<Paste> readPaste();
|
||||
|
||||
/// [child] taking dropped files ([onDrop]: their paths and where they
|
||||
/// landed); [enable] off lets drops through.
|
||||
Widget dropTarget({
|
||||
Key? key,
|
||||
bool enable = true,
|
||||
VoidCallback? onEnter,
|
||||
VoidCallback? onExit,
|
||||
required void Function(List<String> paths, Offset at) onDrop,
|
||||
required Widget child,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/// Notifications outside the window (the desktop's notification center,
|
||||
/// Android's shade). The Notifier decides what goes out here (see
|
||||
/// `noticeFor`); the port only shows them and reports clicks.
|
||||
abstract interface class SystemNotifications {
|
||||
/// Shows [title] / [body] with the app's name and icon; one with the
|
||||
/// same [tag] replaces it. [payload] comes back to [onClick].
|
||||
Future<void> show({required String title, required String body, String tag = '', String payload = ''});
|
||||
|
||||
/// Called with a notification's payload when the user clicks it (set
|
||||
/// once, by the Notifier).
|
||||
set onClick(void Function(String payload)? handler);
|
||||
}
|
||||
|
||||
/// Shows nothing (tests, platforms without one).
|
||||
class NoSystemNotifications implements SystemNotifications {
|
||||
const NoSystemNotifications();
|
||||
|
||||
@override
|
||||
Future<void> show({required String title, required String body, String tag = '', String payload = ''}) async {}
|
||||
|
||||
@override
|
||||
set onClick(void Function(String payload)? handler) {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/// Opens links outside the app.
|
||||
abstract interface class UrlOpener {
|
||||
/// Opens [url] with the system's handler (a browser for web links, the
|
||||
/// file manager for a `file:` folder); false when nothing opened it.
|
||||
Future<bool> open(String url);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/// Where the app window stands ([ShellPort.watchActivity]): auto sit-out
|
||||
/// and the Notifier (system notifications while it is not focused) read
|
||||
/// it. Pure Dart.
|
||||
enum WindowActivity {
|
||||
/// The window has the keyboard focus.
|
||||
focused,
|
||||
|
||||
/// Shown, but another window has the focus.
|
||||
unfocused,
|
||||
|
||||
/// Minimised to the taskbar.
|
||||
minimised,
|
||||
|
||||
/// Hidden (closing, or a platform that hides instead of minimising).
|
||||
hidden;
|
||||
|
||||
/// Not in front of the user: notices go out as system notifications.
|
||||
bool get background => this != focused;
|
||||
}
|
||||