Closed general

open_3d_viewer needs the plugin-free fallback (UIA invoke) so show_3d_chip/show_3d_board work from cold

John Lauer · ·closed by John Lauer

Follow-up to #21 (closed) and #25: the 3D-viewer-open path still depends on the in-process plugin, which binds minutes-late in pcbnew/eeschema (the #21 late-bind). I fixed the lib-tree editors (symbol/footprint load) with a plugin-free win32 tier, but did NOT port that to open_3d_viewer, so kicad_show_3d_chip and kicad_show_3d_board reliably load the part/board but the final "pop the 3D window" step is flaky from cold.

Repro: cold box → kicad_show_3d_board {"filePath":"...kicad_pcb"}. The board opens (PCB Editor shows, verified via kicad_state), but the 3D viewer fails "did not open via the background (plugin) path" because pcbnew's plugin hasn't bound. Warm (plugin eventually up) it works.

Fix: give open_3d_viewer the same plugin-free fallback the editors got — a background UIA Invoke of the "3D Viewer" toolbar control on the live pcbnew/eeschema window (no focus, no cursor). The control exists in the running editor's UIA tree regardless of Python-plugin state; handlers/uia.uia_invoke(hwnd, contains="3D") is the same primitive open_footprint_editor already uses as its Tier 1.5. Then all seven kicad_show_* surfaces are solid from cold.

Also relevant: the relay's default 30s per-call timeout trips on cold 3D opens (board load + render can exceed it). The verbs accept a timeout arg for the bridge's own budget, but callers should pass a generous relay timeout for the 3D surfaces, or the bridge could return a fast "opening, poll kicad_state" instead of blocking.

Not user-facing-critical (5 of 7 show_* verbs are solid; the 3D pair get you to the right state, just not the final window), but it should close before the 3D surfaces are called "done".

2 Replies

John Lauer ·

Progress + an honest wall, after live investigation on AdomLapper.

What's fixed (0.9.95): the Footprint-Editor 3D path got the plugin-free UIA-invoke tier the PCB path already had, and the 3D-window detection now polls up to 9s (software-GL renders lag). The part/board LOAD half is fully solid: show_3d_chip loads the footprint (verified Resistor_SMD:R_0603_1608Metric cold via kicad_state), show_3d_board opens the board and waits for it.

The wall — opening the 3D WINDOW from cold has no clean plugin-free path on KiCad 10:

  • The in-process plugin (menu-id path) works but binds minutes-late in pcbnew/eeschema (#21).
  • The UIA-invoke path I added does NOT find a "3D Viewer" control: a live UIA walk of the Footprint Editor from an external process returns ZERO named toolbar buttons and no matching menu items — KiCad's wx toolbar/menu is opaque to an out-of-process UIA walk (yet uia_invoke(contains="Footprint Editor") works for OPENING the editor, so it's control-specific, the 3D toolbar button just isn't exposed).
  • Alt+3 works but requires foregrounding the window (focus theft — banned by the background contract).

So the honest state: show_3d_chip/show_3d_board reliably get the user to the loaded footprint / open board, but the final "pop the 3D window" is only reliable once the plugin has bound (warm), not from cold.

Two real options to actually close this (neither is a quick patch):

  1. Build a menu-UIA navigator (expand View menu → invoke "3D Viewer" MenuItem) — needs the menu-expand + item-invoke sequence, more robust than toolbar buttons.
  2. Trigger the editor's Python init early so the plugin binds in seconds not minutes (the #21 root), then the existing menu-id path just works.

Compounding blocker for CLI callers: every cold 3D attempt exceeds adom-bridge #73 (flat 30s CLI passthrough timeout vs AD's 130s bridge budget) — the verb keeps running server-side and completes, but a single CLI call returns "Request timed out". Until #73 is fixed, these long verbs are only observable via a follow-up kicad_state poll. A background/progress pattern (like kicad_demo #24) would sidestep it — worth doing for the 3D surfaces specifically.

Keeping this open. 5 of 7 show_* verbs are solid cold; these two need option 1 or 2, done properly, not another speculative patch.

John Lauer ·

SOLVED in 0.9.99, verified cold on both surfaces.

The fix was neither of the two options I'd guessed (menu-UIA navigator / fast plugin-bind) — it's simpler and fully plugin-free: wxFrame menus ARE native Win32 menus. New handlers/win_menu.py walks the editor window's real menu bar (GetMenu → GetSubMenu recursion), finds the "3D Viewer" item, reads its command id, and fires it with PostMessage(WM_COMMAND). No plugin (no late-bind wait), no focus, no cursor, no UIA. Wired as Tier 0 of open_3d_viewer for both the PCB and Footprint paths.

(My earlier "wx toolbar/menu is opaque to UIA" finding was real but a red herring — the menu is opaque to an out-of-process UIA walk, but perfectly enumerable via the Win32 menu API. The empty PowerShell probes were quoting-broken, not a real capability gap.)

Live verification from FULLY CLOSED:

  • kicad_show_3d_board {filePath:...kicad_pcb} -> PCB Editor + 3D Viewer both open (board in 3D).
  • kicad_show_3d_chip {footprintName:"R_0603_1608Metric", library:"Resistor_SMD"} -> Footprint Editor loads the part + 3D Viewer opens (R_0603 resistor rendered in 3D — screenshot confirmed).

So all 8 show_* surfaces are now solid cold. open_3d_viewer's plugin/UIA/Alt+3 tiers remain as fallbacks below the new Win32-menu Tier 0.

Note: cold 3D opens still exceed the 30s CLI passthrough cap (adom-bridge #73) on a single call — the verb completes server-side and the window opens; a CLI caller should poll kicad_state rather than treat the 30s timeout as failure, or use the background kicad_demo. That's an ab-core item, not this bridge.

John Lauer closed this ·

Log in to reply.