From ec111a2e2711ad6bd597a9a90112b5da990339df Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 22 May 2026 13:47:57 +0000 Subject: [PATCH] =?UTF-8?q?feat(cosmobiologia):=20GR=20=E2=80=94=20scrubbi?= =?UTF-8?q?ng=20live=20de=20la=20edad=20con=20el=20jog-dial?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tercer y último incremento del Sistema GR: en modo GR (direcciones primarias activas) el jog-dial deja de rotar el wheel y pasa a scrubear la edad en vivo. - canvas: CanvasState::gr_active() detecta el modo; on_jog_move emite CanvasEvent::GrAgeDelta (años por grado de jog, sensibilidad 0.1) en vez de rotar; on_jog_up no aplica snap de tiempo. - shell: scrub_gr_age acumula el delta sobre target_age_years del módulo primary_directions, clampa a [0,120], sincroniza el slider del panel y recompone — los glifos dirigidos y el HUD se mueven en vivo bajo el cursor. Con esto el Sistema GR queda completo: cómputo de triggers, resaltado de convergencias, HUD de rectificación y scrubbing live. Co-Authored-By: Claude Opus 4.7 --- crates/apps/cosmobiologia/src/shell.rs | 29 +++++++++++++ .../cosmobiologia-canvas/src/lib.rs | 42 +++++++++++++++++-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/crates/apps/cosmobiologia/src/shell.rs b/crates/apps/cosmobiologia/src/shell.rs index 96f31ec..52ce17f 100644 --- a/crates/apps/cosmobiologia/src/shell.rs +++ b/crates/apps/cosmobiologia/src/shell.rs @@ -1172,9 +1172,38 @@ impl Shell { CanvasEvent::ExportSvgRequested => { self.export_current_to_svg(); } + CanvasEvent::GrAgeDelta(delta) => { + self.scrub_gr_age(*delta, cx); + } } } + /// Scrubbing en vivo de la edad GR vía jog-dial. Acumula `delta` + /// sobre `target_age_years` del módulo `primary_directions`, + /// clampa a [0,120], sincroniza el slider del panel y recompone. + fn scrub_gr_age(&mut self, delta_years: f64, cx: &mut Context) { + if !module_enabled(&self.module_configs, "primary_directions") { + return; + } + let current = self.module_age_or_current("primary_directions"); + let next = (current + delta_years).clamp(0.0, 120.0); + if (next - current).abs() < 1e-6 { + return; + } + let entry = self + .module_configs + .entry("primary_directions".into()) + .or_insert_with(|| serde_json::json!({})); + if let serde_json::Value::Object(map) = entry { + map.insert("target_age_years".into(), serde_json::json!(next)); + } + self.panel.update(cx, |p, cx| { + p.set_slider("primary_directions", "target_age_years", next, cx) + }); + self.persist_module("primary_directions"); + self.render_current(cx); + } + /// Recompone la carta actual + escribe el SVG a un archivo en /// `$XDG_DATA_HOME/cosmobiologia/exports/