# Conflicts: # CHANGELOG.md # example_workflows/LTX 2.3 Video Outpaint (AusBoss).json # js/input_preview/index.js
82 lines
3.3 KiB
JavaScript
82 lines
3.3 KiB
JavaScript
// Stand ComfyUI's own in-node previews down on nodes that draw their own.
|
|
//
|
|
// A node that returns a ui payload — or streams progress previews — gets a
|
|
// preview from the frontend automatically: an image one as the canvas widget
|
|
// named $$canvas-image-preview, a video one as the DOM widget named
|
|
// video-preview. Every AusBoss node here already presents that same result
|
|
// inside its own panel, so left alone the node shows it twice, once in the
|
|
// panel and once again underneath.
|
|
//
|
|
// The widgets are hidden rather than removed. The frontend re-adds a preview
|
|
// whenever it finds none and the node has images, so removing one just brings
|
|
// it back on the next frame; a hidden widget is still found by name and left
|
|
// alone. Its value is untouched either way, and neither serializes.
|
|
|
|
export const CORE_VIDEO_PREVIEW_WIDGET = "video-preview";
|
|
export const CORE_IMAGE_PREVIEW_WIDGET = "$$canvas-image-preview";
|
|
|
|
export function hideCanvasWidget(widget, element = null) {
|
|
if (!widget || widget.__ausbossHidden) return;
|
|
widget.__ausbossHidden = true;
|
|
widget.hidden = true;
|
|
widget._hidden = true;
|
|
widget.computeSize = () => [0, -4];
|
|
widget.computeLayoutSize = () => ({ minWidth: 0, minHeight: 0 });
|
|
widget.draw = () => {};
|
|
widget.mouse = () => false;
|
|
if (element) element.style.display = "none";
|
|
}
|
|
|
|
// Wrap one of the node's own add*Widget methods so the named widget is hidden
|
|
// the moment the frontend creates it, and sweep any copy already present.
|
|
function suppressWidget(node, flag, method, targetName, elementOf) {
|
|
if (!node || node[flag]) return;
|
|
node[flag] = true;
|
|
const prior = node[method];
|
|
if (typeof prior === "function") {
|
|
node[method] = function (...args) {
|
|
const widget = prior.apply(this, args);
|
|
if (widget?.name === targetName || args[0] === targetName) {
|
|
hideCanvasWidget(widget, elementOf(widget, args));
|
|
}
|
|
return widget;
|
|
};
|
|
}
|
|
for (const widget of node.widgets || []) {
|
|
if (widget?.name === targetName) hideCanvasWidget(widget, elementOf(widget, []));
|
|
}
|
|
}
|
|
|
|
export function suppressCoreVideoPreview(node) {
|
|
// Nodes 2.0 has no video-preview widget to hide: it draws the node's
|
|
// output under the widgets itself unless the node sets this flag (the
|
|
// classic renderer never reads it). Without it Save Video showed its clip
|
|
// twice there, once in the panel and once underneath.
|
|
if (node) node.hideOutputImages = true;
|
|
suppressWidget(
|
|
node,
|
|
"__ausbossCorePreviewSuppressed",
|
|
"addDOMWidget",
|
|
CORE_VIDEO_PREVIEW_WIDGET,
|
|
(widget, args) => args[2] || widget?.element || node.videoContainer,
|
|
);
|
|
}
|
|
|
|
export function suppressCoreImagePreview(node) {
|
|
// Nodes 2.0 draws its own copy of the node's output images under the
|
|
// widgets unless the node sets this flag (classic never reads it). That
|
|
// copy is also the only thing that fills node.imgs there, so a node that
|
|
// stands it down reads its result from app.nodeOutputs instead
|
|
// (js/input_preview).
|
|
if (node) node.hideOutputImages = true;
|
|
// The image preview arrives through addCustomWidget, not addDOMWidget: it
|
|
// is painted straight onto the graph canvas and owns no element.
|
|
suppressWidget(
|
|
node,
|
|
"__ausbossCoreImagePreviewSuppressed",
|
|
"addCustomWidget",
|
|
CORE_IMAGE_PREVIEW_WIDGET,
|
|
() => null,
|
|
);
|
|
}
|