120 lines
3.9 KiB
JavaScript
120 lines
3.9 KiB
JavaScript
/**
|
|
* Dynamic Widget Visibility for Multi-Backend Nodes
|
|
*
|
|
* Shows/hides widgets based on selected backend.
|
|
* Mappings are loaded from backend_mappings.json (generated by prestartup_script.py).
|
|
*/
|
|
import { app } from "../../../scripts/app.js";
|
|
|
|
console.log("[GeomPack DynamicWidgets] Loading extension...");
|
|
|
|
// Will be populated from JSON
|
|
let BACKEND_MAPPINGS = {};
|
|
let BACKEND_WIDGET_NAME = {};
|
|
|
|
/**
|
|
* Fetch mappings from generated JSON (try both casing for manager installs)
|
|
*/
|
|
async function loadMappings() {
|
|
const paths = [
|
|
"/extensions/ComfyUI-GeometryPack/js/backend_mappings.json",
|
|
"/extensions/comfyui-geometrypack/js/backend_mappings.json",
|
|
];
|
|
|
|
for (const path of paths) {
|
|
try {
|
|
const response = await fetch(path);
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
BACKEND_MAPPINGS = data.mappings || {};
|
|
BACKEND_WIDGET_NAME = data.backend_widgets || {};
|
|
console.log("[GeomPack DynamicWidgets] Loaded mappings from", path);
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
// Try next path
|
|
}
|
|
}
|
|
console.warn("[GeomPack DynamicWidgets] Could not load backend_mappings.json");
|
|
return false;
|
|
}
|
|
|
|
// Load mappings on startup
|
|
loadMappings();
|
|
|
|
/**
|
|
* Update widget visibility based on selected backend
|
|
*/
|
|
function updateWidgetVisibility(node, selectedBackend) {
|
|
const nodeClass = node.comfyClass;
|
|
const mapping = BACKEND_MAPPINGS[nodeClass];
|
|
if (!mapping) return;
|
|
|
|
const visibleWidgets = mapping[selectedBackend] || [];
|
|
const backendWidgetName = BACKEND_WIDGET_NAME[nodeClass];
|
|
|
|
console.log(`[GeomPack DynamicWidgets] ${nodeClass}: backend="${selectedBackend}", visible=[${visibleWidgets.join(', ')}]`);
|
|
|
|
let visibilityChanged = false;
|
|
|
|
for (const widget of node.widgets || []) {
|
|
// Skip the backend/method selector itself and the mesh input
|
|
if (widget.name === backendWidgetName || widget.name === "trimesh" || widget.name === "mesh") continue;
|
|
|
|
// Check if this widget should be visible for the current backend
|
|
const allWidgets = Object.values(mapping).flat();
|
|
const isBackendWidget = allWidgets.includes(widget.name);
|
|
|
|
if (isBackendWidget) {
|
|
const shouldShow = visibleWidgets.includes(widget.name);
|
|
const wasHidden = widget.hidden;
|
|
widget.hidden = !shouldShow;
|
|
|
|
if (wasHidden !== widget.hidden) {
|
|
visibilityChanged = true;
|
|
console.log(`[GeomPack DynamicWidgets] Widget "${widget.name}": hidden=${widget.hidden}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (visibilityChanged) {
|
|
node.setSize(node.computeSize());
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: "GeomPack.DynamicWidgets",
|
|
|
|
nodeCreated(node) {
|
|
const nodeClass = node.comfyClass;
|
|
if (!BACKEND_MAPPINGS[nodeClass]) return;
|
|
|
|
console.log(`[GeomPack DynamicWidgets] Setting up node: ${nodeClass}`);
|
|
|
|
const backendWidgetName = BACKEND_WIDGET_NAME[nodeClass];
|
|
const backendWidget = node.widgets?.find(w => w.name === backendWidgetName);
|
|
|
|
if (!backendWidget) {
|
|
console.log(`[GeomPack DynamicWidgets] No ${backendWidgetName} widget found`);
|
|
return;
|
|
}
|
|
|
|
// Store original callback
|
|
const originalCallback = backendWidget.callback;
|
|
|
|
// Override callback to update visibility on change
|
|
backendWidget.callback = function(value) {
|
|
if (originalCallback) originalCallback.call(this, value);
|
|
updateWidgetVisibility(node, value);
|
|
};
|
|
|
|
// Initial visibility update (with delay to ensure widgets are created)
|
|
setTimeout(() => {
|
|
updateWidgetVisibility(node, backendWidget.value);
|
|
}, 50);
|
|
}
|
|
});
|
|
|
|
console.log("[GeomPack DynamicWidgets] Extension registered");
|