38 Commits
Author SHA1 Message Date
Robin Anderson 1259fc90be Number the release 1.1.0 2026-10-17 12:23:58 -04:00
Robin Anderson dbc01cd59a Let people choose what knocking twice or thrice does
Settings has a Knock actions screen with Knock twice and Knock thrice
side by side. Each lists four actions, and one press picks one: switch
passthrough, switch the style, show or hide SteamVR's performance graph,
or do nothing. The defaults stay the same, and the lists mark them with
(default).

config.json stores the actions under knock_actions, keyed by kind and
count, so each kind of knock can have its own actions and a new count
needs no format change. The screen sets every kind the same. The
performance graph is the SteamVR setting perfcheck.perfGraphInHMD. The
tour still teaches the default actions.
2026-10-17 12:18:18 -04:00
Robin Anderson ff3f150e00 Number the release 1.0.2 2026-10-16 20:03:12 -04:00
Robin Anderson de976ad256 Number the release 1.0.1 2026-10-16 16:29:04 -04:00
Robin Anderson abe798d798 Add a test hook that drives the app over SSH
Development builds read commands appended to
~/.config/knockthru/test-commands: open or close the panel, click a
panel pixel, press a button by name, feed a knock or a double or triple
knock, and save the panel as a PNG. Releases leave it out:
build-arm64.sh adds it only with KNOCKTHRU_TEST_HOOK=1, and the release
workflow never sets that. The host build always has it, so CI compiles it.

On the Frame it drove calibration, the bug report and its recording,
the factory reset and tour, and an update from 1.0.1 to a local
1.0.2-test release through Install and Restart.
2026-10-16 16:23:52 -04:00
Robin Anderson 5d0ac36d02 Remove scripts/analyze.py
Nothing referenced it, and it read only uncompressed CSV files while the
recordings are gzipped. detector_test with KNOCKTHRU_TEST_VERBOSE=1 prints
every knock in a recording.
2026-10-16 16:00:14 -04:00
Robin Anderson cef1a82ac7 Split the resident app out of main.cpp
run() was one 721-line function whose 15 lambdas shared its locals. It is
now an App class in app.cpp with one method per job: slow checks, panel
clicks, knocks, background jobs, and drawing. The shared SteamVR helpers,
pose sampling, haptics, the bug report, and install commands move to
their own files. main.cpp keeps the command-line commands.

Behavior is unchanged. The order of steps in the main loop is the same,
except that a finished recording is collected after the knocks of that
loop instead of before.
2026-10-16 15:50:21 -04:00
Robin Anderson 28c22a1b93 Number the first public release 1.0.0
The version defaults in CMakeLists.txt, build-arm64.sh, and package.mjs
say 1.0.0, and so do the README's manual install and build examples.
The README's update GIF goes from 1.0.0 to 1.1.0, not 0.1.0 to 0.2.0.
2026-10-16 13:59:30 -04:00
Robin Anderson cfea5e0bf4 Keep the red Reset label red in the README GIFs
The Reset label is too small to win an entry in the 127-color GIF palette,
so it came out mustard. An extra solid frame of the error red, seen only
by palettegen, gives it its own entry.
2026-10-16 13:05:35 -04:00
Robin Anderson 4b1021174d Name passthrough and its style one way, and give the GIFs rounded transparent corners at one panel size 2026-10-16 11:38:31 -04:00
Robin Anderson e8a8d28b77 End the calibration GIF on Done and hold the report card longer before the headset turns 2026-10-16 11:17:44 -04:00
Robin Anderson 8d8b700526 Document the no-PC and Frameloader installs and the new update flow, and blur the QR only while it shows 2026-10-16 11:08:58 -04:00
Robin Anderson 6bfa33d6c9 Turn the headset from front to lenses in the report GIF, rendered from Valve's CAD 2026-10-16 10:49:16 -04:00
Robin Anderson 4a6eecb30f Show the headset taken off and a phone scanning a lens in the report GIF 2026-10-16 10:49:16 -04:00
Robin Anderson 720c43817b Show reporting a problem as a GIF with the phone beside the panel 2026-10-16 10:49:16 -04:00
Robin Anderson 94aac0db2e Angle the README surface knock like the panel's 2026-10-16 10:49:16 -04:00
Robin Anderson 1e11b3e576 Document updates, bug reports, and purge in the README, with an update GIF and a report card still 2026-10-16 10:49:16 -04:00
Robin Anderson fa85d199fe Keep the calibration pointer on screen, loop it without a jump, and stop clipping the click ring 2026-10-16 10:49:16 -04:00
Robin Anderson e82c2a8198 Draw the calibration pointer like SteamVR's and move it on curves with hand-like timing 2026-10-16 10:49:16 -04:00
Robin Anderson 21b84386f2 Show a pointer in the calibration animation and skip from the second knock to the tenth 2026-10-16 10:49:16 -04:00
Robin Anderson 3f902c74a1 Add a README calibration animation rendered from the panel 2026-10-16 10:49:16 -04:00
Robin Anderson 162ac72330 Render the README panel images from the current panel and call every gesture a knock 2026-10-16 10:49:15 -04:00
Robin Anderson 81f4296fbe Switch the hero back to see-through before the last double knock 2026-10-16 10:49:15 -04:00
Robin Anderson befaee5421 Give the knock loops more rest and loop the hero without a cut 2026-10-16 10:49:15 -04:00
Robin Anderson 7e56e1ad32 Show a triple knock after the double in the How to knock animations 2026-10-16 10:49:15 -04:00
Robin Anderson 30a76b1a33 Tilt the headset-tap controller less so it stays inside its card 2026-10-16 10:49:15 -04:00
Robin Anderson c6cbb7478b Ease the README animations and keep them on one timeline
All three GIFs share one knock timeline: first knock at 0.5 s, 0.3 s
between knocks, and the action 0.4 s after the last knock. The knock
kinds and timing loops are both 2.4 s, so they stay in step.

Knocks move on eased keyframes: a small pull back, a speed-up into the
contact, a slowing rebound, and a settle with a slight overshoot. The
controllers swing from the wrist, bursts fly out behind them, and the
controllers buzz after the action. In the hero, the panel cross-fades and
the captions fade out, then rise in.

The timing strip now runs in real time with 0.1 s ticks. Its dots pop in,
labels fade in, the wait bracket grows with the playhead, and the strip
fades out before it loops.

The FrameDrop button moves into the second install step.
2026-10-16 10:49:15 -04:00
Robin Anderson 8b9cb36a6f Draw the README controllers and headset in the logo style
cad_sprites.py now traces the CAD the same way as the logo: a flat light
shape, a gap between the controller head and grip, the controls cut out,
and a blue thumbstick. The headset gets a gap around the visor and its
two front cameras cut out. The trace steps come from the logo work.

The headset knock now shows the left controller tapping the left side of
the headset. The hero and dashboard images pick up the new panel icon.
The README says how to pause or remove KnockThru, and ends with a line
about who it is made for.
2026-10-16 10:49:15 -04:00
Robin Anderson 215bffe0f5 Draw the README controllers and headset from Valve's CAD
scripts/cad_sprites.py renders the left and right Steam Frame controllers
and the headset core module from Valve's STEP files into shaded sprites in
images/cad/, in the panel's colors. readme_media.py places these sprites
in the hero and knock kinds animations instead of hand-drawn shapes.

The CAD is CC BY-NC-SA 4.0, so the sprites and the two GIFs that use them
carry that license. THIRD_PARTY_NOTICES.md and the README credits say so.
2026-10-16 10:49:15 -04:00
Robin Anderson 33920762ac Revamp the README for non-technical readers
The README now opens with an animation of the dashboard panel reacting
to knocks, then covers install, how to knock, the dashboard tab, and
troubleshooting in plain words. Settings, SSH calibration, commands,
manual install, and build move into collapsed sections at the bottom.

scripts/readme_media.py makes the images: the hero and dashboard images
come from the real panel code through panel_preview --readme, and the
knock kinds and timing animations are drawn with Pillow. ffmpeg writes
the GIFs.
2026-10-16 10:49:15 -04:00
Robin Anderson aea7f0fd96 Add a one-line installer for people without a PC
scripts/install.sh downloads the latest release ZIP named in the FrameDrop
manifest, checks its SHA-256, unpacks it to ~/KnockThru, adds it to the Steam
library, and runs knockthru --install. The release workflow attaches it.
2026-10-16 10:17:36 -04:00
Robin Anderson 20b7cc75c5 Hand the full report to a phone through a page the headset serves
The report card's QR code now opens a page on the Frame, over the local
Wi-Fi, with the whole report. One button copies it and opens the
prefilled GitHub form, where it goes in the Report box. The page also
offers the report as a download. It needs a random token in the path and
stops when the card closes or after 15 minutes. SteamOS's firewall opens
TCP 1024 to 65535, and the kernel picks the port from that range.

Without a network, the QR code opens the GitHub form directly, as before.
2026-10-15 21:50:04 -04:00
Robin Anderson d421116efe Show a QR code that opens a GitHub issue from the report card
Report in Settings opens a card with a QR code. A phone held up to a lens
scans it and opens the bug form in .github/ISSUE_TEMPLATE/bug.yml, with
the KnockThru version, SteamVR version, and passthrough status filled in.
The full report still goes to ~/knockthru-report.txt.

Vendors nayuki/QR-Code-generator (MIT) to encode the code.
2026-10-15 21:38:42 -04:00
Robin Anderson 61121b3688 Add updates, bug reports, purge, and a Steam-update warning
--update installs the latest GitHub release over the running one and
restarts it. It reads the FrameDrop manifest, checks the ZIP's SHA-256,
and renames each new file over the old one. The resident app has the same
check and install behind CheckUpdate and InstallUpdate, for the panel.

--report writes ~/knockthru-report.txt with the KnockThru and SteamVR
versions, registration state, settings, and the end of both logs.

--uninstall --purge also deletes ~/.config/knockthru and SteamVR's
vrappconfig file for KnockThru.

A missing Room View button now throws DashboardChanged. The passthrough
tile then says a Steam update moved the button, and the log records the
SteamVR version once.
2026-10-15 21:20:02 -04:00
Robin Anderson ac8829b6ae Play Steam's switch sounds when a setting changes
A knock that turns passthrough on plays Steam's switch-on sound, and one that
turns it off plays the switch-off sound, like the Room View switch in the
quick settings. The style switch and the panel settings do the same, and the
calibration buttons play Steam's button sound. KnockThru plays the files from
the Steam install with pw-play, so it ships no audio. Set "sounds" to false
to turn them off.
2026-10-15 19:43:28 -04:00
Robin Anderson 1e7669c2d3 Walk calibration through five animated steps
Pick a kind, learn the knock, record single knocks, adjust sensitivity
on a notched slider, and try a double knock before saving. The knock
animations port the README timing and draw controllers and the headset
traced from the CAD sprites. The slider's middle notch keeps the old
60 percent rule. The tuning comes in a later change.
2026-10-15 15:16:56 -04:00
Robin Anderson d6bd54ef77 Add a KnockThru tab to the SteamVR dashboard
The tab has a passthrough button, a translucent or opaque switch,
switches to pause knocks, pick knock kinds, and turn knocks off in the
running game, and a calibration screen with step-by-step progress.

The panel draws into an RGBA image with stb_truetype and Noto Sans, and
shows it through two Vulkan textures that take turns. SetOverlayRaw made
the panel flash on every update. Calibration moved into a Calibrator
class shared by the panel and --calibrate. Panel changes write to the
user config.json. SteamVR also gets an app icon.
2026-10-15 13:18:08 -04:00
Robin Anderson 4a002fb8ed Add KnockThru: double knock toggles Steam Frame passthrough
A SteamVR overlay app for the Steam Frame. A double knock (controllers
together, a controller on a surface, or a tap on the headset) turns Room
View on or off. A triple knock switches translucent and opaque.

Includes the knock detector with replay tests on recorded poses, the
debug port client for the Room View button, per-game blocklist,
calibration, haptics, install and autostart, and FrameDrop packaging.
2026-10-15 13:18:08 -04:00