Two paper cuts spotted while wiring LoadPLY through PreviewGaussians:
## 1. Hardcoded `type=output` in the /view fetch
Repro: LoadPLY hands /home/work/.../ComfyUI/input/apple.ply to
PreviewGaussians. The JS fetches `/view?filename=apple.ply&type=output
&subfolder=` and gets 404 because the file lives in input/, not
output/. PLYs produced by GaussianMerge/GaussianExport/LiToExportPLY
(under output/) worked because the hardcoded `type=output` matched.
Fix is two-sided:
- Python (nodes/preview_gaussian.py): new `_resolve_for_view()`
walks the abs path against folder_paths.get_{output,input}_directory()
and returns (filename, subfolder, folder_kind). The kind is shipped
as a new UI field `ply_type` ("input" | "output"), plus
`ply_subfolder` for nested locations.
- JS (web/js/gaussian_preview.js): reads `ply_type` / `ply_subfolder`
off the onExecuted message and substitutes them into both URLs —
`/view?type=<kind>&subfolder=<sub>` for raw PLY transport, and
`/gaussianpack/spz?type=<kind>&subfolder=<sub>` for the SPZ
transcode route. The Python SPZ route already accepts both
type=input and type=output (spz_route.py:53-56), so no server-side
change needed.
Files truly outside ComfyUI's input/output trees still 404 (the
fallback returns type=output + bare basename), which matches the
prior behavior — the previewer can't serve arbitrary disk paths.
## 2. Spark heartbeat log spam
Every 120 frames (~2 s) the iframe printed
"[Spark] heartbeat: N frames" to the console. Useful while bringing
up the rendering loop, noise now that everything works. Dropped the
line; the "first frame rendered" trace stays as the smoke test.