From 6d43120c0a9f23ce2d4be3f5392a9d708a5dc95a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=27=C3=A9lectron=20rare?= <108685187+electron-rare@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:49:16 +0200 Subject: [PATCH] feat(viz): m key = matrix mode, fix test pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit m now stops the auto data-synth scene AND forces the openpos viz (matrix unaffected — it is not a scene). Repairs the two test pins the frozen pinch defaults broke (ext_min 1) and makes the skeleton path safe for __new__-built renderers (hand gate getattr). --- data_only_viz/main.py | 16 +++++++++++++++- data_only_viz/renderer.py | 5 ++++- .../tests/test_action_head_finger_emit.py | 2 +- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/data_only_viz/main.py b/data_only_viz/main.py index 50d11a7..2317c4c 100644 --- a/data_only_viz/main.py +++ b/data_only_viz/main.py @@ -621,7 +621,21 @@ class AppDelegate(NSObject): self._user_viz_lock_t = _t.monotonic() LOG.info("[video] viz -> %s (%d) (lock 8s)", name, idx) return None - # qsdfghjklm -> audio (scene SC) + # m = matrix performance mode: stop the auto data-synth scene AND + # force the openpos viz (the matrix is not a scene — it keeps + # playing). User request live 2026-07-02. + if k == "m": + self._scClient.send_message("/control/doScene", ["stop"]) + names = list(self._state.viz_mode_names) + idx = names.index("openpos") if "openpos" in names else 0 + with self._state.lock(): + self._state.viz_mode = idx + self._state.active_scene = "stop" + import time as _t + self._user_viz_lock_t = _t.monotonic() + LOG.info("[key] m -> scene stop + viz openpos (matrix mode)") + return None + # qsdfghjkl -> audio (scene SC) for kk, scene in KEYMAP_AUDIO: if k == kk: self._scClient.send_message("/control/doScene", [scene]) diff --git a/data_only_viz/renderer.py b/data_only_viz/renderer.py index b46aa03..2b11c35 100644 --- a/data_only_viz/renderer.py +++ b/data_only_viz/renderer.py @@ -407,7 +407,10 @@ class MetalRenderer(NSObject): # Gate called once per frame on the full persons_hands list. # Used for both the overlay loop and the side panels below. - _hand_draw_flags = self._hand_gate.step(s.persons_hands) + # getattr: unit tests build the renderer via __new__ (no Metal init). + _gate = getattr(self, "_hand_gate", None) + _hand_draw_flags = (_gate.step(s.persons_hands) if _gate is not None + else [True] * len(s.persons_hands)) if use_arkit: parents = s.arkit_parents diff --git a/data_only_viz/tests/test_action_head_finger_emit.py b/data_only_viz/tests/test_action_head_finger_emit.py index 8d02dd1..9ac2b48 100644 --- a/data_only_viz/tests/test_action_head_finger_emit.py +++ b/data_only_viz/tests/test_action_head_finger_emit.py @@ -141,7 +141,7 @@ def test_pinch_gate_env_defaults_are_strict(monkeypatch): monkeypatch.delenv(k, raising=False) pub = _pub_envs(monkeypatch, finger_piano="0", pinch_enable="1") assert pub._pinch_det.ext_ratio == 1.35 - assert pub._pinch_det.ext_min == 2 + assert pub._pinch_det.ext_min == 1 # 1 since 2026-07-02 (inner-finger fix) assert pub._pinch_det.debounce_frames == 3