VR keyboard controller bridge: no traffic while idle

The relay no longer enables the Runtime domain on systemui (bindings work
without it; it streamed the page's console and context events). Full-rate
frames only while a tip is within 10 cm of the keyboard or a trigger is
pulled (not for a laser resting on it); idle frames every 1 s instead of
250 ms. Nothing while the keyboard is hidden.
This commit is contained in:
Pierre Kisters committed 2026-10-01 03:33:07 +02:00
1 parent 224715d926
commit 63d589c261
4 files changed
+14 -12

No files matched your search

@@ -17,18 +17,18 @@
// the laser's hit on the keyboard (geometry.js), the trigger from the
// render model's animated "trigger" component (null without one).
// Frames go out through the CDP binding __sfuiCtlOut(json) at TICK_MS while
// a hand is relevant (tip within NEAR m of the keyboard, laser on it, or
// trigger pulled), else every IDLE_MS; one { keyboard: null } frame when the
// keyboard goes. Frame (hub.js adds page px):
// a hand is relevant (tip within NEAR m of the keyboard or trigger pulled),
// else every IDLE_MS; one { keyboard: null } frame when the keyboard goes.
// Nothing at all while the keyboard is hidden (one DOM lookup per POLL_MS). Frame (hub.js adds page px):
// { seq, t, moving, keyboard: { width } | null,
// hands: { left, right: null | { tip: { u, v, d }, ray: { u, v, dist } | null,
// trigger: 0..1 | null } } }
// Never touches SteamVR's input or the lasers. Debugging: __sfuiCtl.log,
// __sfuiCtl.last (the last frame).
((find, sigs, opts, hooks, GEO) => {
const VERSION = 2;
const VERSION = 3;
const G = window;
const TICK_MS = 11, IDLE_MS = 250, POLL_MS = 250, MOVE_QUIET_MS = 300, TIP_CACHE_MS = 5000;
const TICK_MS = 11, IDLE_MS = 1000, POLL_MS = 250, MOVE_QUIET_MS = 300, TIP_CACHE_MS = 5000;
const NEAR = 0.1; // m
const TRIGGER_DEG = 12.5; // frame controller: trigger component's full travel
const PROBE = 'sfui-ctl-keyboard';
@@ -136,7 +136,7 @@
return { tip: GEO.toKeyboard(pose.translation, S.kb), ray: GEO.rayHit(pose, S.kb), trigger: trigger(hand, m.rm) };
}
const relevant = (h) => !!h && ((Math.abs(h.tip.d) < NEAR && h.tip.u > -0.2 && h.tip.u < 1.2 && h.tip.v > -0.2 && h.tip.v < 0.7) ||
(h.ray && h.ray.u >= 0 && h.ray.u <= 1 && h.ray.v >= 0 && h.ray.v <= 0.6) || h.trigger >= 0.5);
h.trigger >= 0.5);
// ---- loops ---------------------------------------------------------------------
let active = false;
+2 -2
View File
@@ -8,8 +8,8 @@
// last the last frame (null: none / lost)
// Each frame's hand points (tip, ray) get the keyboard page's px: x, y
// (CSS px of the keyboard popup) and onKeyboard (inside the page), if the
// keyboard popup exists. Frames come every ~11 ms while a hand is near the
// keyboard, its laser on it or its trigger pulled, else every 250 ms, and
// keyboard popup exists. Frames come at up to ~90 Hz while a hand's tip is
// within 10 cm of the keyboard or its trigger is pulled, else every 1 s, and
// only while SteamVR shows the keyboard (then one with keyboard null).
(() => {
const VERSION = 1;
+3 -1
View File
@@ -46,7 +46,9 @@ async function connect(side) {
if (m.method === 'Runtime.bindingCalled' && m.params.name === cfg.binding) forward(m.params.payload);
};
const closed = new Promise((res) => { ws.onclose = res; });
if (cfg.binding) { send('Runtime.enable'); send('Runtime.addBinding', { name: cfg.binding }); }
// No Runtime.enable: bindings work without it, and it would stream the
// page's console and context events here.
if (cfg.binding) send('Runtime.addBinding', { name: cfg.binding });
live[side] = (expression) => send('Runtime.evaluate', { expression });
console.log(`${side}: connected`);
await closed;