Dual/VTK/Multi preview bars: layout+mode selectors, opacity gating, shared fullscreen

Preview Mesh Dual:
- New control bar with Layout (Side by side | Overlay | Slider) and Mode
  (Fields | Texture), two-way synced with the node widgets.
- side_by_side <-> slider reuse the SAME exported files, so that switch is
  CLIENT-SIDE: onExecuted was refactored into render(message, layoutOverride)
  and the last message is stored -- switching re-renders instantly, no re-run.
  Overlay needs the combined export and mode changes the export format, so
  those queue a re-run (same cost as editing the widget).
- opacity_1/opacity_2 widgets are hidden unless layout is Overlay (the
  hidden-type trick from preview_mesh_batch_render.js), restored when it is.

Preview Mesh (VTK): new bar with Mode (Fields | Texture | Texture (PBR)),
two-way synced, re-runs on change.

Fullscreen: new createFullscreenButton(container) in utils/uiComponents.js
(fullscreens the whole widget so bar controls stay usable; listeners on the
container only, isolation-clean). Wired into Dual, VTK, and Multi bars (in
Multi it sits outside the collapsible group so it survives collapse). The
batch node keeps its own earlier implementation with arrow-key nav.

Note: plain Preview Mesh (three.js, GeomPackPreviewMesh) has no mode input on
the Python side, so there is nothing to select there; the VTK preview is the
one with modes. comfy-3d-viewers was checked for fullscreen prior art -- its
"FullScreen" hits are VTK class names, not browser fullscreen; this is new.
This commit is contained in:
PozzettiAndrea
2026-08-14 14:01:37 +02:00
parent e9c7bbceaf
commit 6047a30e1b
4 changed files with 162 additions and 11 deletions
+27
View File
@@ -47,6 +47,33 @@ export function createIframe(src, options = {}) {
return iframe;
}
/**
* Create a fullscreen toggle button wired to a widget container.
*
* Fullscreens the WHOLE container (viewer iframe + any control bar), so the
* bar's buttons stay usable in fullscreen. All listeners are attached to the
* container itself (never document) to stay isolation-clean.
*
* @param {HTMLElement} container - The widget container to fullscreen
* @returns {HTMLButtonElement} The toggle button (append it to a bar)
*/
export function createFullscreenButton(container) {
const btn = document.createElement("button");
btn.textContent = "⛶";
btn.title = "Fullscreen";
btn.style.cssText = "padding:4px 10px;cursor:pointer;background:#333;color:#ccc;" +
"border:1px solid #555;border-radius:3px;font-size:13px;line-height:1;margin-left:auto;";
const isFs = () => (document.fullscreenElement || document.webkitFullscreenElement) === container;
btn.addEventListener("click", () => {
if (isFs()) {
(document.exitFullscreen || document.webkitExitFullscreen)?.call(document);
} else {
(container.requestFullscreen || container.webkitRequestFullscreen)?.call(container);
}
});
return btn;
}
/**
* Create an info panel for displaying mesh metadata
* @param {string} placeholder - Initial placeholder text