fix(sim): clean restart on Run after agent + display body occludes crossing wires
Two issues from a real ESP32 7-segment clock the agent built. Run after the agent didn't work until a page reload --------------------------------------------------- The agent's run_simulation leaves the ESP32 board RUNNING (live QEMU WebSocket). Esp32Bridge.connect() is a no-op while the socket is non-CLOSED, so the user's subsequent Run click called startBoard() → connect() → did NOTHING. And if the backend QEMU session had since died while the frontend socket lingered (CONNECTING/OPEN/CLOSING), the user saw a dead sim that only a reload cleared — exactly the "di Run y no funcionó; recargué y sí" report. The Arduino/C++ QEMU path now stops a running board first (closing the WS), waits for it to settle, then boots fresh — the MicroPython path already did this for the same reason. Wires painted over the 7-segment digits ---------------------------------------- The agent bridges each segment strip to its resistor from a breadboard hole that is physically UNDER the seated display; on the flat canvas those wires (wire layer z 35) painted over the digits (component z 1) — "casi ni se ven los dígitos". A large-bodied display seated on a breadboard now renders ABOVE the wire layer, so its face occludes the wires crossing it exactly as the real part's body would (the wire passes behind it to reach the hole). Scoped to display bodies (7segment, matrix, oled, lcd, ili9341, led-ring…) and only when actually seated; thin parts and free-floating displays are untouched. The pin overlay + seated-pin markers share the display's stacking group, so they rise with it and wiring still works. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
d726139946
commit
9c26174c93
|
|
@ -811,6 +811,19 @@ export const EditorToolbar = ({
|
|||
// QEMU boards: auto-compile if no firmware available yet
|
||||
if (isQemuBoard) {
|
||||
console.log('[handleRun] QEMU path');
|
||||
// Clean restart when the board is already running. Esp32Bridge.connect()
|
||||
// is a no-op while the socket is non-CLOSED, so startBoard() on a live
|
||||
// session does NOTHING — and if the backend QEMU session has since died
|
||||
// but the frontend socket is still zombie (CONNECTING/OPEN/CLOSING), the
|
||||
// user sees a dead sim that only a page reload fixes. This is the exact
|
||||
// "el agente terminó, di Run y no funcionó; recargué y sí" report: the
|
||||
// agent's run_simulation left the board running, so the user's Run
|
||||
// no-op'd. Stop first (closes the WS), let it settle, then boot fresh —
|
||||
// mirrors what the MicroPython branch above already does.
|
||||
if (board?.running) {
|
||||
stopBoard(activeBoardId);
|
||||
await new Promise((resolve) => setTimeout(resolve, 300));
|
||||
}
|
||||
if (!board?.compiledProgram || codeChangedSinceLastCompile) {
|
||||
console.log('[handleRun] auto-compile + run');
|
||||
autoRunAfterCompile.current = true;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,16 @@ import './SimulatorCanvas.css';
|
|||
/** World-units of tolerance for alignment snap (scales with zoom). */
|
||||
const ALIGN_SNAP_PX = 6;
|
||||
|
||||
/**
|
||||
* Large-bodied display parts whose face should occlude wires when the part is
|
||||
* seated on a breadboard — the flat canvas has no depth, so bridge wires
|
||||
* routed to holes UNDER the body would otherwise paint over the readout.
|
||||
* Matches both the metadata ids (`7segment`, `ssd1306`, …) and the `wokwi-`/
|
||||
* `velxio-` element-name variants. Thin two-pin parts are deliberately absent.
|
||||
*/
|
||||
const DISPLAY_BODY_METADATA_RE =
|
||||
/(7segment|led-matrix|max7219|neopixel-matrix|ssd1306|oled|ili9341|lcd1602|lcd2004|led-ring)/i;
|
||||
|
||||
/** Long-press duration for touch context menu (ms). */
|
||||
const LONG_PRESS_MS = 500;
|
||||
|
||||
|
|
@ -2240,7 +2250,26 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
|
|||
// them — so they always sit at the very back: below boards (z 0), other
|
||||
// components (z 1/2) and wires (z 35). Selection doesn't raise them.
|
||||
const isBreadboard = String(component.metadataId).startsWith('breadboard');
|
||||
const groupZIndex = isBreadboard ? -1 : isSelected ? 2 : 1;
|
||||
// A large-bodied display seated on a breadboard physically sits ON the
|
||||
// board, so wires routed to holes UNDERNEATH it pass behind its body in
|
||||
// real life. On the flat canvas those bridge wires (segment strips whose
|
||||
// holes are literally under the display) otherwise paint OVER the digits
|
||||
// — the reported "los cables se ven superpuestos y casi ni se ven los
|
||||
// dígitos". Raise a seated display above the wire layer (z 35) so its
|
||||
// face occludes the wires crossing it, exactly as the real part would.
|
||||
// Scoped to occluding display bodies + only when actually seated, so
|
||||
// thin parts (resistors, LEDs) and free-floating displays are untouched.
|
||||
const isSeated = (seatedPinsByComponent.get(component.id)?.length ?? 0) > 0;
|
||||
const occludesWhenSeated = DISPLAY_BODY_METADATA_RE.test(String(component.metadataId));
|
||||
const groupZIndex = isBreadboard
|
||||
? -1
|
||||
: isSeated && occludesWhenSeated
|
||||
? isSelected
|
||||
? 37
|
||||
: 36
|
||||
: isSelected
|
||||
? 2
|
||||
: 1;
|
||||
|
||||
return (
|
||||
<React.Fragment key={component.id}>
|
||||
|
|
|
|||
Loading…
Reference in New Issue