From 87164bc06b3549899ad1df1824e2b5ebf5f0ccf8 Mon Sep 17 00:00:00 2001 From: kali-urs <839525988@qq.com> Date: Wed, 10 Jun 2026 20:56:07 +0800 Subject: [PATCH] fix: carry LED segment mask to GUI preview (FrameSent) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GUI simulated LED display was showing all segments lit because FrameSent only carried display_colors but not the on/off mask computed by compute_mask(). This meant the preview never knew which segments should actually be lit for segment-display styles (TEMP_LINKED, etc.). - Add field to FrameSent event (list of bool, default empty) - Pass mask from RenderLed.execute() when publishing FrameSent - Wire mask through TRCCApp._on_bus_frame_sent → LEDHandler.handle_frame - Add UCLedControl.set_led_colors() optional mask parameter - Add UCScreenLED.set_mask() to update on/off state per tick - Check _is_on in _paint_led_rects() so masked-off segments stay dim Fixes the GUI preview on macOS where all segments appeared lit regardless of the actual hardware mask. --- src/trcc/core/commands/led.py | 1 + src/trcc/core/events.py | 4 ++++ src/trcc/ui/gui/led_handler.py | 3 ++- src/trcc/ui/gui/trcc_app.py | 3 ++- src/trcc/ui/gui/uc_led_control.py | 4 +++- src/trcc/ui/gui/uc_screen_led.py | 9 +++++++++ 6 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/trcc/core/commands/led.py b/src/trcc/core/commands/led.py index 4daf2959..a449d4c7 100644 --- a/src/trcc/core/commands/led.py +++ b/src/trcc/core/commands/led.py @@ -320,6 +320,7 @@ def execute(self, app: App) -> LedColorsResult: # device (LCD carries a surface; LED carries the colors). app.events.publish(FrameSent( key=self.key, bytes_sent=len(colors), display_colors=colors, + mask=list(mask), )) return LedColorsResult( ok=ok, key=self.key, colors=colors, diff --git a/src/trcc/core/events.py b/src/trcc/core/events.py index b8b0dd50..66dad1c8 100644 --- a/src/trcc/core/events.py +++ b/src/trcc/core/events.py @@ -61,6 +61,10 @@ class FrameSent(Event): # LCD (one render → FrameSent → handle_frame → preview), not a parallel # one. Empty for LCD / pure-bytes sends. display_colors: list = field(default_factory=list) + # LED segment mask (list of bool) — determines which LEDs are + # lit vs off. Carried alongside display_colors so the GUI preview + # accurately mirrors the physical hardware for segment-display styles. + mask: list = field(default_factory=list) @dataclass(frozen=True, slots=True) diff --git a/src/trcc/ui/gui/led_handler.py b/src/trcc/ui/gui/led_handler.py index e9af92df..35069abd 100644 --- a/src/trcc/ui/gui/led_handler.py +++ b/src/trcc/ui/gui/led_handler.py @@ -329,9 +329,10 @@ def _on_test_mode_changed(self, on: bool) -> None: def handle_frame(self, image: Any) -> None: """Receive tick result — update LED color display on the panel.""" display_colors = image.get('display_colors') if isinstance(image, dict) else None + display_mask = image.get('mask') if isinstance(image, dict) else None log.debug("handle_frame: active=%s colors=%s", self._active, len(display_colors) if display_colors else None) if not self._active: return if display_colors is not None: - self._panel.set_led_colors(display_colors) + self._panel.set_led_colors(display_colors, display_mask) diff --git a/src/trcc/ui/gui/trcc_app.py b/src/trcc/ui/gui/trcc_app.py index bc27f3dc..fe4abf66 100644 --- a/src/trcc/ui/gui/trcc_app.py +++ b/src/trcc/ui/gui/trcc_app.py @@ -511,10 +511,11 @@ def _on_bus_frame_sent(self, event: Any) -> None: # FrameSent → handle_frame seam (the device's render IS the preview). surface = getattr(event, "surface", None) colors = getattr(event, "display_colors", None) + mask = getattr(event, "mask", None) if surface is not None: handler.handle_frame(surface) elif colors: - handler.handle_frame({"display_colors": list(colors)}) + handler.handle_frame({"display_colors": list(colors), "mask": list(mask) if mask else None}) else: handler.rebuild_preview() diff --git a/src/trcc/ui/gui/uc_led_control.py b/src/trcc/ui/gui/uc_led_control.py index 4d2996a3..d29c8c53 100644 --- a/src/trcc/ui/gui/uc_led_control.py +++ b/src/trcc/ui/gui/uc_led_control.py @@ -859,9 +859,11 @@ def initialize(self, style_id: int, segment_count: int, elif is_lf11: self._populate_disk_identity() - def set_led_colors(self, colors: list[tuple[int, int, int]]) -> None: + def set_led_colors(self, colors: list[tuple[int, int, int]], mask: list[bool] | None = None) -> None: """Update LED preview from controller tick.""" self._preview.set_colors(colors) + if mask is not None: + self._preview.set_mask(mask) def set_status(self, text: str) -> None: """Update status text.""" diff --git a/src/trcc/ui/gui/uc_screen_led.py b/src/trcc/ui/gui/uc_screen_led.py index 761f960f..0967b4c8 100644 --- a/src/trcc/ui/gui/uc_screen_led.py +++ b/src/trcc/ui/gui/uc_screen_led.py @@ -500,6 +500,13 @@ def set_colors(self, colors: list[tuple[int, int, int]]) -> None: self._colors.append((0, 0, 0)) self.update() + def set_mask(self, mask: list[bool]) -> None: + """Update LED on/off mask from controller tick.""" + self._is_on = list(mask[:len(self._is_on)]) + while len(self._is_on) < len(self._positions): + self._is_on.append(False) + self.update() + def set_segment_on(self, index: int, on: bool) -> None: """Toggle an individual segment.""" if 0 <= index < len(self._is_on): @@ -637,6 +644,8 @@ def _paint_led_rects(self, painter: QPainter) -> None: for i, pos in enumerate(self._positions): if i >= len(self._colors): break + if i < len(self._is_on) and not self._is_on[i]: + continue r, g, b = self._colors[i] if r == 0 and g == 0 and b == 0: continue