import { app } from "../../scripts/app.js"; import { api } from "../../scripts/api.js"; import { DEFAULT_DIMENSIONS_LIST, DEFAULT_MODELS_ARCH_LIST, DEFAULT_CONTROLNET_CONDITIONING_LIST, RUNWARE_NODE_TYPES, MODEL_TYPES_TERMS, MODEL_LIST_TERMS } from "./types.js"; const TIMEOUT_RANGE = { min: 5, default: 90, max: 99 }; const OUTPUT_QUALITY_RANGE = { min: 20, default: 95, max: 99 }; const CACHE_SIZE_RANGE = { min: 30, default: 150, max: 4096 }; /** Must match `audioInferenceInputs.MAX_VIDEOS` in modules/audioInferenceInputs.py */ const AUDIO_INFERENCE_INPUTS_MAX_VIDEOS = 4; let openDialog = false; let lastTimeout = false; let lastOutputFormat = false; let lastOutputQuality = false; let lastEnableImagesCaching = null; let lastMinImageCacheSize = false; async function queryLocalAPI(endpoint, data) { try { const resp = await api.fetchApi(`/${endpoint}`, { method: "POST", headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); return await resp.json(); } catch (err) { return false; } } const runwareLocalAPI = { enhancePrompt: (userPrompt) => queryLocalAPI('promptEnhance', { userPrompt }), setAPIKey: (apiKey) => queryLocalAPI('setAPIKey', { apiKey }), setTimeout: (maxTimeout) => queryLocalAPI('setMaxTimeout', { maxTimeout }), setOutputFormat: (outputFormat) => queryLocalAPI('setOutputFormat', { outputFormat }), setOutputQuality: (outputQuality) => queryLocalAPI('setOutputQuality', { outputQuality }), setEnableImagesCaching: (enableCaching) => queryLocalAPI('setEnableImagesCaching', { enableCaching }), setMinImageCacheSize: (minCacheSize) => queryLocalAPI('setMinImageCacheSize', { minCacheSize }), modelSearch: (modelQuery = "", modelArch = "all", modelType = "base", modelCat = "checkpoint", condtioning = "") => queryLocalAPI('modelSearch', { modelQuery, modelArch, modelType, modelCat, condtioning }) }; function mediaUUIDHandler(msgEvent) { const mediaData = msgEvent.detail; const mediaUUID = mediaData.mediaUUID; const mediaNodeID = parseInt(mediaData.nodeID); if(mediaData.success) { const mediaNode = app.graph.getNodeById(mediaNodeID); if(mediaNode !== null && mediaNode !== undefined) { // Find the mediaUUID widget specifically const mediaUUIDWidget = mediaNode.widgets.find(widget => widget.name === "mediaUUID"); if(mediaUUIDWidget) { // Update both widget.value and inputEl.value for STRING widgets if(mediaUUIDWidget.value !== undefined) { mediaUUIDWidget.value = mediaUUID; } if(mediaUUIDWidget.inputEl) { mediaUUIDWidget.inputEl.value = mediaUUID; // Trigger change events to update the UI mediaUUIDWidget.inputEl.dispatchEvent(new Event('input', { bubbles: true })); mediaUUIDWidget.inputEl.dispatchEvent(new Event('change', { bubbles: true })); } } } } return false; } function save3DFilepathHandler(msgEvent) { const data = msgEvent.detail; const filepath = data.filepath; const nodeID = parseInt(data.nodeID, 10); if (Number.isNaN(nodeID)) return false; if(data.success && filepath) { const node = app.graph.getNodeById(nodeID); if(node !== null && node !== undefined) { const filepathWidget = node.widgets.find(widget => widget.name === "filepath"); if(filepathWidget) { if(filepathWidget.value !== undefined) { filepathWidget.value = filepath; } if(filepathWidget.inputEl) { filepathWidget.inputEl.value = filepath; filepathWidget.inputEl.dispatchEvent(new Event('input', { bubbles: true })); filepathWidget.inputEl.dispatchEvent(new Event('change', { bubbles: true })); } } } } return false; } function captionNodeHandler(msgEvent) { const captionData = msgEvent.detail; const captionText = captionData.captionText; const captionNodeID = parseInt(captionData.nodeID); if(captionData.success) { const captionNode = app.graph.getNodeById(captionNodeID); if(captionNode !== null && captionNode !== undefined) { // Find the imageCaption widget specifically const imageCaptionWidget = captionNode.widgets.find(widget => widget.name === "imageCaption"); if(imageCaptionWidget && imageCaptionWidget.inputEl) { imageCaptionWidget.inputEl.value = captionText; } } } return false; } function saveTextHandler(msgEvent) { const data = msgEvent.detail; const displayText = data.text; const nodeID = parseInt(data.nodeID, 10); if (!data.success || Number.isNaN(nodeID)) return false; const node = app.graph.getNodeById(nodeID); if (node === null || node === undefined) return false; const widgetName = data.widgetName || "text"; const textWidget = node.widgets.find((w) => w.name === widgetName); if (textWidget) { if (textWidget.value !== undefined) { textWidget.value = displayText; } if (textWidget.inputEl) { textWidget.inputEl.value = displayText; textWidget.inputEl.dispatchEvent(new Event("input", { bubbles: true })); textWidget.inputEl.dispatchEvent(new Event("change", { bubbles: true })); } } return false; } function videoTranscriptionHandler(msgEvent) { const transcriptionData = msgEvent.detail; const transcriptionText = transcriptionData.transcriptionText; const transcriptionNodeID = parseInt(transcriptionData.nodeID); if(transcriptionData.success) { const transcriptionNode = app.graph.getNodeById(transcriptionNodeID); if(transcriptionNode !== null && transcriptionNode !== undefined) { // Find the prompt widget (where transcription is displayed) const promptWidget = transcriptionNode.widgets.find(widget => widget.name === "prompt"); if(promptWidget && promptWidget.inputEl) { promptWidget.inputEl.value = transcriptionText; } } } return false; } function videoOutputsHandler(msgEvent) { const outputData = msgEvent.detail; const draftId = outputData.draftId || ""; const videoId = outputData.videoId || ""; const nodeID = outputData.nodeID; if(outputData.success && nodeID !== undefined && nodeID !== null) { const nodeIdInt = typeof nodeID === 'string' ? parseInt(nodeID) : nodeID; const outputNode = app.graph.getNodeById(nodeIdInt); if(outputNode !== null && outputNode !== undefined) { const draftIdWidget = outputNode.widgets.find(widget => widget.name === "draftId"); const videoIdWidget = outputNode.widgets.find(widget => widget.name === "videoId"); if(draftIdWidget) { if(draftIdWidget.value !== undefined) draftIdWidget.value = draftId; if(draftIdWidget.inputEl) { draftIdWidget.inputEl.value = draftId; draftIdWidget.inputEl.dispatchEvent(new Event('input', { bubbles: true })); draftIdWidget.inputEl.dispatchEvent(new Event('change', { bubbles: true })); } } if(videoIdWidget) { if(videoIdWidget.value !== undefined) videoIdWidget.value = videoId; if(videoIdWidget.inputEl) { videoIdWidget.inputEl.value = videoId; videoIdWidget.inputEl.dispatchEvent(new Event('input', { bubbles: true })); videoIdWidget.inputEl.dispatchEvent(new Event('change', { bubbles: true })); } } outputNode.setDirtyCanvas(true); } } return false; } function notifyUser(message, type="info", title = "Runware", life = 4.5) { app.extensionManager.toast.add({ severity: type, // 'info', 'success', 'warn', 'error' \\ summary: title, detail: message, life: Math.floor(life * 1000) }); } async function promptEnhanceHandler(e) { if(e.ctrlKey && e.altKey && e.key.toLowerCase() === 'e') { const userPrompt = e.target.value.trim(); if(userPrompt.length <= 1) { notifyUser("Prompt Is Too Short!", "error", "Runware Prompt Enhancer"); return; } else if(userPrompt.length > 300) { notifyUser("Prompt Must Not Exceed 300 Characters!", "error", "Runware Prompt Enhancer"); return; } const enhanceResults = await runwareLocalAPI.enhancePrompt(userPrompt); if(enhanceResults.success) { e.target.value = enhanceResults.enhancedPrompt; } else { notifyUser(enhanceResults.error, "error", "Runware Prompt Enhancer"); } } } function remNode(node) { app.graph.remove(node); app.graph.setDirtyCanvas(true,true); } async function APIKeyHandler(apiManagerNode) { const widgets = apiManagerNode.widgets; for(const widget of widgets) { if(widget.name === "API Key") { appendWidgetCB(widget, async function(...args) { if(openDialog) return; const apiKey = args[0].trim(); if(apiKey.length < 30) { notifyUser("Invalid API Key Set, Please Try Again!", "error", "Runware API Manager"); return; } const setAPIKeyResults = await runwareLocalAPI.setAPIKey(apiKey); if(setAPIKeyResults.success) { remNode(apiManagerNode); notifyUser("API Key Set Successfully!", "success", "Runware API Manager"); } else { notifyUser(setAPIKeyResults.error, "error", "Runware API Manager"); } }); } else if(widget.name === "Max Timeout") { if(lastTimeout) widget.value = lastTimeout; appendWidgetCB(widget, async function(...args) { const maxTimeout = parseInt(args[0]); if(isNaN(maxTimeout) || maxTimeout < TIMEOUT_RANGE.min || maxTimeout > TIMEOUT_RANGE.max) { notifyUser(`Invalid Timeout Value! Must be between ${TIMEOUT_RANGE.min} and ${TIMEOUT_RANGE.max} seconds.`, "error", "Runware API Manager"); widget.value = lastTimeout || TIMEOUT_RANGE.default; return; } const setTimeoutResults = await runwareLocalAPI.setTimeout(maxTimeout); if(setTimeoutResults.success) { notifyUser("Timeout Set Successfully!", "success", "Runware API Manager"); lastTimeout = maxTimeout; } else { widget.value = lastTimeout || TIMEOUT_RANGE.default; notifyUser(setTimeoutResults.error, "error", "Runware API Manager"); } }); } else if(widget.name === "Image Output Format") { if(lastOutputFormat) widget.value = lastOutputFormat; appendWidgetCB(widget, async function(...args) { const outputFormat = args[0].trim().toUpperCase(); const setFormatResults = await runwareLocalAPI.setOutputFormat(outputFormat); if(setFormatResults.success) { notifyUser("Default Image Output Format Set Successfully!", "success", "Runware API Manager"); lastOutputFormat = outputFormat; } else { notifyUser(setFormatResults.error, "error", "Runware API Manager"); } }); } else if(widget.name === "Image Output Quality") { if(lastOutputQuality) widget.value = lastOutputQuality; appendWidgetCB(widget, async function(...args) { const outputQuality = parseInt(args[0]); if(isNaN(outputQuality) || outputQuality < OUTPUT_QUALITY_RANGE.min || outputQuality > OUTPUT_QUALITY_RANGE.max) { notifyUser(`Invalid Quality Value! Must be between ${OUTPUT_QUALITY_RANGE.min} and ${OUTPUT_QUALITY_RANGE.max}.`, "error", "Runware API Manager"); widget.value = lastOutputQuality || OUTPUT_QUALITY_RANGE.default; return; } const setQualityResults = await runwareLocalAPI.setOutputQuality(outputQuality); if(setQualityResults.success) { notifyUser("Default Image Output Quality Set Successfully!", "success", "Runware API Manager"); lastOutputQuality = outputQuality; } else { widget.value = lastOutputQuality || OUTPUT_QUALITY_RANGE.default; notifyUser(setQualityResults.error, "error", "Runware API Manager"); } }); } else if(widget.name === "Enable Images Caching") { if(lastEnableImagesCaching !== null) widget.value = lastEnableImagesCaching; appendWidgetCB(widget, async function(...args) { const enableCaching = args[0]; const setCachingResults = await runwareLocalAPI.setEnableImagesCaching(enableCaching); if(setCachingResults.success) { notifyUser("Image Caching Setting Updated Successfully!", "success", "Runware API Manager"); lastEnableImagesCaching = enableCaching; } else { widget.value = lastEnableImagesCaching; notifyUser(setCachingResults.error, "error", "Runware API Manager"); } }); } else if(widget.name === "Min Image Cache Size") { if(lastMinImageCacheSize !== false) widget.value = lastMinImageCacheSize; appendWidgetCB(widget, async function(...args) { const minCacheSize = parseFloat(args[0]); if(isNaN(minCacheSize) || minCacheSize < CACHE_SIZE_RANGE.min || minCacheSize > CACHE_SIZE_RANGE.max) { notifyUser(`Invalid cache size! Must be between ${CACHE_SIZE_RANGE.min} KB and ${CACHE_SIZE_RANGE.max} KB.`, "error", "Runware API Manager"); widget.value = lastMinImageCacheSize || CACHE_SIZE_RANGE.default; return; } const setCacheSizeResults = await runwareLocalAPI.setMinImageCacheSize(minCacheSize); if(setCacheSizeResults.success) { notifyUser("Minimum Image Cache Size Updated Successfully!", "success", "Runware API Manager"); lastMinImageCacheSize = minCacheSize; } else { widget.value = lastMinImageCacheSize || CACHE_SIZE_RANGE.default; notifyUser(setCacheSizeResults.error, "error", "Runware API Manager"); } }); } } } function addTriggerWords(prompt, triggerWords) { if (!triggerWords?.trim()) return prompt; const cleanedTriggerWords = triggerWords .trim() .replace(/,\s*$/, '') .split(',') .map(word => word.trim()) .filter(word => word.length); if (!prompt?.trim()) return cleanedTriggerWords.join(', '); const wordsToAdd = cleanedTriggerWords.filter(word => !new RegExp(`\\b${word}\\b`, 'i').test(prompt) ); return wordsToAdd.length ? `${prompt}${prompt.endsWith(',') ? ' ' : ', '}${wordsToAdd.join(', ')}` : prompt; } function handleCustomErrors(errObj) { const errData = errObj.detail; const errCode = errData.errorCode; if(errCode === 401 && !openDialog) { const dialog = new comfyAPI.asyncDialog.ComfyAsyncDialog(); const htmlContent = `

Runware Inference Error

Your API Key is Invalid Or Undefined. You Need To Update It.

`; dialog.showModal(htmlContent).then(() => { openDialog = false; }); openDialog = true; dialog.element.addEventListener('close', () => { openDialog = false; }); const runwareAPIForm = document.getElementById("runwareAPIKey"); const apiKeyInput = document.getElementById("apiKey"); const getAPIKeyBTN = document.getElementById("getAPIKeyBTN"); const setAPIKeyBTN = document.getElementById("setAPIKeyBTN"); getAPIKeyBTN.onclick = (e) => { e.preventDefault(); window.open("https://my.runware.ai/keys?utm_source=comfyui&utm_medium=referral&utm_campaign=comfyui_api_key_creation", "_blank"); }; async function authUser(e) { e.preventDefault(); e.stopPropagation(); const apiKey = apiKeyInput.value.trim(); if(apiKey.length < 30) { runwareAPIForm.reportValidity(); return; // notifyUser("Invalid API Key Set, Please Try Again!", "error", "Runware API Manager"); // return; } else { const setAPIKeyResults = await runwareLocalAPI.setAPIKey(apiKey); if(setAPIKeyResults.success) { dialog.close(); openDialog = false; notifyUser("API Key Set Successfully!", "success", "Runware API Manager"); } else { notifyUser(setAPIKeyResults.error, "error", "Runware API Manager"); } } }; setAPIKeyBTN.onclick = async (e) => { authUser(e); }; runwareAPIForm.onsubmit = async (e) => { authUser(e); }; } } function appendWidgetCB(node, newCB) { const oldNodeCB = node.callback; if(typeof oldNodeCB === "function") { node.callback = function(...args) { oldNodeCB?.apply(this, args); newCB?.apply(this, args); } } else { node.callback = newCB; } } async function syncDimensionsNodeHandler(node, dimensionsWidget) { const nodeWidgets = node.widgets; let widthWidget = false, heightWidget = false; for(const nodeWidget of nodeWidgets) { const widgetName = nodeWidget.name; const widgetType = nodeWidget.type; if(widgetName === "width" && widgetType === "number") widthWidget = nodeWidget; if(widgetName === "height" && widgetType === "number") heightWidget = nodeWidget; } appendWidgetCB(dimensionsWidget, function(...args) { const chosenDimension = args[0]; if(chosenDimension === "Custom" || chosenDimension === "None") return; const dimensionValue = DEFAULT_DIMENSIONS_LIST[chosenDimension]; if(!dimensionValue) return; const [width, height] = dimensionValue.split("x"); widthWidget.callback(width, "customSetOperation"); heightWidget.callback(height, "customSetOperation"); }); if(widthWidget !== false) { appendWidgetCB(widthWidget, function(...args) { if(args[1] === "customSetOperation") return; dimensionsWidget.value = "Custom"; }); } if(heightWidget !== false) { appendWidgetCB(heightWidget, function(...args) { if(args[1] === "customSetOperation") return; dimensionsWidget.value = "Custom"; }); } } const shortenAirCode = input => !input || !input.startsWith('urn:air:') ? input : input.match(/urn:air:.*?:.*?(civitai:\d+@\d+)$/)?.[1] || input; async function searchNodeHandler(searchNode, searchInputWidget) { const searchNodeWidgets = searchNode.widgets; let modelArchWidget = false, modelTypeWidget = false, modelListWidget = false, defaultWidgetValues = {}, triggerWordsList = { "civitai:58390@62833": "", "civitai:82098@87153": "", "civitai:122359@135867": "", "civitai:14171@16677": "mix4", "civitai:13941@16576": "", "civitai:25995@32988": "full body, chibi" }, embeddingTriggerWordsList = { "civitai:7808@9208": "easynegative", "civitai:4629@5637": "ng_deepnegative_v1_75t", "civitai:56519@60938": "negative_hand", "civitai:72437@77169": "BadDream", "civitai:11772@25820": "verybadimagenegative_v1.3", "civitai:71961@94057": "FastNegativeV2", }; let isLora = false, isControlNet = false, isEmbedding = false, isVAE = false, modelTypeValue = false; if(searchNode.comfyClass === RUNWARE_NODE_TYPES.LORASEARCH) isLora = true; if(searchNode.comfyClass === RUNWARE_NODE_TYPES.CONTROLNET) isControlNet = true; if(searchNode.comfyClass === RUNWARE_NODE_TYPES.EMBEDDING) isEmbedding = true; if(searchNode.comfyClass === RUNWARE_NODE_TYPES.VAE) isVAE = true; for(const searchWidget of searchNodeWidgets) { const widgetName = searchWidget.name; const widgetType = searchWidget.type; if(widgetName === "Model Architecture" && widgetType === "combo") { modelArchWidget = searchWidget; defaultWidgetValues["modelArch"] = searchWidget.options.values; } if(MODEL_TYPES_TERMS.includes(widgetName) && widgetType === "combo") { modelTypeWidget = searchWidget; defaultWidgetValues["modelType"] = searchWidget.options.values; } if(MODEL_LIST_TERMS.includes(widgetName) && widgetType === "combo") { modelListWidget = searchWidget; defaultWidgetValues["modelList"] = searchWidget.options.values; } } function resetValues() { if(modelArchWidget) { modelArchWidget.options.values = defaultWidgetValues["modelArch"]; modelArchWidget.value = defaultWidgetValues["modelArch"][0]; } if(modelTypeWidget) { modelTypeWidget.options.values = defaultWidgetValues["modelType"]; modelTypeWidget.value = defaultWidgetValues["modelType"][0]; } if(modelListWidget) { modelListWidget.options.values = defaultWidgetValues["modelList"]; modelListWidget.value = defaultWidgetValues["modelList"][0]; } } async function searchModels(exactQuery = null, returnOutput = false) { let searchQuery; if(exactQuery) { searchQuery = exactQuery; } else { searchQuery = searchInputWidget.value.trim(); } searchQuery = shortenAirCode(searchQuery); const modelArchValue = DEFAULT_MODELS_ARCH_LIST[modelArchWidget.value]; if(isControlNet) { modelTypeValue = DEFAULT_CONTROLNET_CONDITIONING_LIST[modelTypeWidget.value]; } else { if(isEmbedding) { modelTypeValue = "embeddings"; } else if(isVAE) { modelTypeValue = "vae"; } else { modelTypeValue = modelTypeWidget.value.toLowerCase().replace("model", "").trim(); } } let modelSearchResults = null; if(isControlNet) { modelSearchResults = await runwareLocalAPI.modelSearch(searchQuery, modelArchValue, "", "controlnet", modelTypeValue); } else if(isLora || isEmbedding || isVAE) { modelSearchResults = await runwareLocalAPI.modelSearch(searchQuery, modelArchValue, "", modelTypeValue); } else { modelSearchResults = await runwareLocalAPI.modelSearch(searchQuery, modelArchValue, modelTypeValue); } if(modelSearchResults.success) { const modelListArray = []; modelSearchResults.modelList.forEach(modelObj => { if(isLora) triggerWordsList[modelObj.air] = modelObj.positiveTriggerWords?.trim() || false; if(isEmbedding) embeddingTriggerWordsList[modelObj.air] = modelObj.positiveTriggerWords?.trim() || false; modelListArray.push(`${modelObj.air} (${modelObj.name} ${modelObj.version})`); }); if(exactQuery) { const extraSearch = await searchModels(null, true); if(extraSearch) { const newModelList = [...new Set([...modelListArray, ...extraSearch])]; modelListWidget.options.values = newModelList; return; } } if(returnOutput) return modelListArray; modelListWidget.options.values = modelListArray; modelListWidget.value = modelListArray[0]; } else { if(returnOutput) return false; if(exactQuery) { notifyUser("Failed To Load Workflow's Model List Value!", "error", "Runware Search"); return; } notifyUser(modelSearchResults.error, "error", "Runware Search"); } } function findTargetWidget(currentNode, targetWidgetName, depth = 1) { try { if(depth < 0) return false; const nodeOutputs = currentNode.outputs; if(nodeOutputs.length === 0) return false; const outputLinks = nodeOutputs[0].links; if(outputLinks.length === 0) return false; for(const linkID of outputLinks) { const linkInfo = app.graph.links[linkID]; const linkNodeID = linkInfo.target_id; if(!linkNodeID) continue; const targetNode = app.graph.getNodeById(linkNodeID); let widgetFound = false; if(targetNode.widgets !== undefined && targetNode.widgets.length > 0){ widgetFound = targetNode.widgets.find(widget => widget.name === targetWidgetName) || false; } if(widgetFound) { return widgetFound; } else { return findTargetWidget(targetNode, targetWidgetName, depth - 1); } } } catch(e) { return false; } return false; } if(isLora) { const runwareButton = document.createElement("button"); runwareButton.textContent = "Add Lora To Prompt"; runwareButton.style = "max-height: 50px; background-color: #333; color: #ccc;"; searchNode.addDOMWidget("addLora", "custom", runwareButton, { selectOn: ['focus', 'click'], }); runwareButton.addEventListener("click", async () => { const chosenLora = modelListWidget.value.split(" ")[0]; if(!triggerWordsList.hasOwnProperty(chosenLora)) return; const triggerWords = triggerWordsList[chosenLora]; if(triggerWords.length > 0) { const positivePromptWidget = findTargetWidget(searchNode, "positivePrompt"); if(!positivePromptWidget) { notifyUser("Lora Node Is Not Linked To Any Runware Inference Node!", "error", "Runware Lora Connector"); return; } const positivePromptWithTrigger = addTriggerWords(positivePromptWidget.value, triggerWords); if(positivePromptWidget.value === positivePromptWithTrigger) { notifyUser("Trigger Words Already Exists", "info", "Runware Lora Connector"); return; } positivePromptWidget.value = positivePromptWithTrigger; notifyUser("Trigger Words Added Successfully!", "success", "Runware Lora Connector"); } else { notifyUser("No Trigger Words Found For This Lora!", "warn", "Runware Lora Connector"); } }); } else if(isEmbedding) { const runwareButton = document.createElement("button"); runwareButton.textContent = "Add Embedding To Negative Prompt"; runwareButton.style = "max-height: 50px; background-color: #333; color: #ccc;"; searchNode.addDOMWidget("addEmbedding", "custom", runwareButton, { selectOn: ['focus', 'click'], }); runwareButton.addEventListener("click", async () => { const chosenEmbedding = modelListWidget.value.split(" ")[0]; if (!embeddingTriggerWordsList.hasOwnProperty(chosenEmbedding)) return; const triggerWords = embeddingTriggerWordsList[chosenEmbedding]; if(triggerWords.length > 0) { const negativePromptWidget = findTargetWidget(searchNode, "negativePrompt"); if(!negativePromptWidget) { notifyUser("Embedding Node Is Not Linked To Any Runware Inference Node!", "error", "Runware Embedding Connector"); return; } const negativePromptWithTrigger = addTriggerWords(negativePromptWidget.value, triggerWords); if(negativePromptWidget.value === negativePromptWithTrigger) { notifyUser("Trigger Words Already Exists", "info", "Runware Embedding Connector"); return; } negativePromptWidget.value = negativePromptWithTrigger; notifyUser("Trigger Words Added Successfully!", "success", "Runware Embedding Connector"); } else { notifyUser("No Trigger Words Found For This Embedding!", "warn", "Runware Embedding Connector"); } }); } appendWidgetCB(searchInputWidget, async function(...args) { let searchQuery = args[0].trim(); const shortenSearchQuery = shortenAirCode(searchQuery); if(searchQuery !== shortenSearchQuery) { searchQuery = shortenSearchQuery; searchInputWidget.value = searchQuery; } if(searchQuery.length === 0) { resetValues(); } else if(searchQuery.length < 2) { notifyUser("Invalid Search Value, Search Query must be at least 2 characters!", "error", "Runware Search"); return; } else { await searchModels(); } }); appendWidgetCB(modelArchWidget, async function(...args) { await searchModels(); }); if(!isVAE && !isEmbedding) { appendWidgetCB(modelTypeWidget, async function(...args) { await searchModels(); }); } appendWidgetCB(searchNode, async function(...args) { try { let modelListValues = modelListWidget.options.values; if(modelListValues.length <= 0) return; modelListValues = modelListValues.map(model => model.split(" ")[0]); const modelListCRValue = modelListWidget.value.split(" ")[0]; if(!modelListValues.includes(modelListCRValue)) { searchModels(modelListCRValue); } } catch(e) {} }); } function toggleWidgetEnabled(widget, enabled, node) { if (!widget || !widget.name) return; // Use the same simple approach as videoInferenceDimensionsHandler // Set widget disabled property widget.disabled = !enabled; // Disable/enable widgets using inputEl if available (same pattern as videoInferenceDimensionsHandler) if (widget.inputEl) { widget.inputEl.disabled = !enabled; widget.inputEl.style.opacity = enabled ? "1" : "0.5"; widget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; widget.inputEl.readOnly = !enabled; } // For combo/dropdown widgets, also try to disable the options element if (widget.options && widget.options.element) { widget.options.element.disabled = !enabled; widget.options.element.style.opacity = enabled ? "1" : "0.5"; widget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } // Fallback: try to find inputs via DOM if inputEl is not available (same as videoInferenceDimensionsHandler) if (!widget.inputEl && node) { const nodeElement = node.htmlElements?.widgetsContainer || node.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${widget.name}"], textarea[name="${widget.name}"], select[name="${widget.name}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } } function videoUpscalerToggleHandler(videoUpscalerNode) { if (!videoUpscalerNode?.widgets) return; const useUpscaleFactorWidget = videoUpscalerNode.widgets.find(w => w && w.name === "useUpscaleFactor"); const upscaleFactorWidget = videoUpscalerNode.widgets.find(w => w && w.name === "upscaleFactor"); const useFpsWidget = videoUpscalerNode.widgets.find(w => w && w.name === "useFps"); const fpsWidget = videoUpscalerNode.widgets.find(w => w && w.name === "fps"); const useDimensionWidget = videoUpscalerNode.widgets.find(w => w && w.name === "useDimension"); const widthWidget = videoUpscalerNode.widgets.find(w => w && w.name === "width"); const heightWidget = videoUpscalerNode.widgets.find(w => w && w.name === "height"); function applyToggleState() { if (useUpscaleFactorWidget && upscaleFactorWidget) { const enabled = useUpscaleFactorWidget.value === true; toggleWidgetEnabled(upscaleFactorWidget, enabled, videoUpscalerNode); } if (useFpsWidget && fpsWidget) { const enabled = useFpsWidget.value === true; toggleWidgetEnabled(fpsWidget, enabled, videoUpscalerNode); } if (useDimensionWidget && widthWidget && heightWidget) { const enabled = useDimensionWidget.value === "custom"; toggleWidgetEnabled(widthWidget, enabled, videoUpscalerNode); toggleWidgetEnabled(heightWidget, enabled, videoUpscalerNode); } videoUpscalerNode.setDirtyCanvas(true); } // Initialize state once widgets are rendered setTimeout(applyToggleState, 100); if (useUpscaleFactorWidget) { appendWidgetCB(useUpscaleFactorWidget, () => { setTimeout(applyToggleState, 50); }); } if (useFpsWidget) { appendWidgetCB(useFpsWidget, () => { setTimeout(applyToggleState, 50); }); } if (useDimensionWidget) { appendWidgetCB(useDimensionWidget, () => { setTimeout(applyToggleState, 50); }); } } function useParameterToggleHandler(node) { // Prevent double registration if (node._useParameterToggleHandlerRegistered) return; node._useParameterToggleHandlerRegistered = true; // Define explicit mappings: "useParameterName" -> ["parameter1", "parameter2", ...] const parameterMappings = { // Image Inference "useSteps": ["steps"], "useSeed": ["seed"], "useCFGScale": ["cfgScale"], // Image inference uses lowercase cfgScale "useScheduler": ["scheduler"], "useClipSkip": ["clipSkip"], // Video Inference "useCustomDimensions": ["width", "height"], // Note: Also handled separately in videoInferenceDimensionsHandler "useDuration": ["duration"], "useFps": ["fps"], "useSchedulers": ["scheduler"], "useCFGScale": ["cfgScale"], // useSteps and useSeed are same as image inference, handled by fallback // Upscaler specific mappings (override for nodes that have CFGScale with capital C) "usePrompts": ["positivePrompt", "negativePrompt"], "useClarityParams": ["controlNetWeight", "strength", "scheduler"], "useCCSRParams": ["colorFix", "tileDiffusion"], "useLatentParams": ["clipSkip"], // Audio Inference "usePositivePrompt": ["positivePrompt"], "useSeed": ["seed"], "useSteps": ["steps"], "useStrength": ["strength"], // Accelerator Options "useCacheDistance": ["cacheDistance"], "useTeaCacheDistance": ["teaCacheDistance"], "useDeepCacheOptions": ["deepCacheInterval", "deepCacheBranchId"], "useCacheSteps": ["cacheStartStep", "cacheEndStep"], "useCachePercentageSteps": ["cacheStartStepPercentage", "cacheEndStepPercentage"], "useCacheMaxConsecutiveSteps": ["cacheMaxConsecutiveSteps"], // Bytedance Provider Settings "useCameraFixed": ["cameraFixed"], "useMaxSequentialImages": ["maxSequentialImages"], "useFastMode": ["fastMode"], // OpenAI Provider Settings (these are dropdowns, not booleans, but handle them anyway) "useBackground": ["background"], "useStyle": ["style"], // Mask Margin "Mask Margin": ["maskMargin"], }; // Node-specific overrides for parameters that have different names in different nodes // Format: nodeClass -> { "useParam": ["param1", "param2"] } const nodeSpecificMappings = { // Upscaler uses CFGScale (capital C) instead of cfgScale [RUNWARE_NODE_TYPES.UPSCALER]: { "useCFGScale": ["CFGScale"], }, // Audio Inference uses CFGScale (capital C) [RUNWARE_NODE_TYPES.AUDIOINFERENCE]: { "useCFGScale": ["CFGScale"], }, }; // Wait for widgets to be ready function initializeHandler() { if (!node.widgets || node.widgets.length === 0) { setTimeout(initializeHandler, 100); return; } // Find all "use" widgets and their corresponding parameter widgets upfront (like videoInferenceDimensionsHandler does) const togglePairs = []; // Find all "use" widgets node.widgets.forEach(widget => { if (!widget || !widget.name) return; const isUseWidget = widget.name.startsWith("use") && (widget.type === "BOOLEAN" || widget.type === "COMBO"); const isMaskMargin = widget.name === "Mask Margin" && widget.type === "BOOLEAN"; if (!isUseWidget && !isMaskMargin) return; const useParamName = widget.name; // Get corresponding parameters - check node-specific mappings first, then general mappings let paramNames = []; const nodeClass = node.comfyClass; if (nodeClass && nodeSpecificMappings[nodeClass] && nodeSpecificMappings[nodeClass][useParamName]) { paramNames = nodeSpecificMappings[nodeClass][useParamName]; } else { paramNames = parameterMappings[useParamName] || []; } // Handle special case: remove "use" prefix and lowercase first letter if (paramNames.length === 0) { const paramName = useParamName.replace(/^use/, "").replace(/^[A-Z]/, (match) => match.toLowerCase()); paramNames = [paramName]; } // Find the actual parameter widgets const paramWidgets = []; paramNames.forEach(paramName => { const paramWidget = node.widgets.find(w => w && w.name === paramName); if (paramWidget) { paramWidgets.push(paramWidget); } else { // If mapped parameter doesn't exist, try fallback auto-detection const fallbackParamName = useParamName.replace(/^use/, "").replace(/^[A-Z]/, (match) => match.toLowerCase()); if (fallbackParamName !== paramName) { const fallbackWidget = node.widgets.find(w => w && w.name === fallbackParamName); if (fallbackWidget) { paramWidgets.push(fallbackWidget); } } } }); if (paramWidgets.length > 0) { togglePairs.push({ useWidget: widget, paramWidgets: paramWidgets }); } }); // Create toggle functions for each pair (like toggleDimensionsEnabled in videoInferenceDimensionsHandler) togglePairs.forEach(pair => { const { useWidget, paramWidgets } = pair; function toggleEnabled() { // Determine if enabled based on widget type let enabled = false; if (useWidget.type === "BOOLEAN") { enabled = useWidget.value === true; } else if (useWidget.type === "COMBO") { enabled = useWidget.value === "enable" || useWidget.value === "Enable"; } // Apply to each parameter widget (exactly like toggleDimensionsEnabled does) paramWidgets.forEach(paramWidget => { if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = node.htmlElements?.widgetsContainer || node.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramWidget.name}"], textarea[name="${paramWidget.name}"], select[name="${paramWidget.name}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } }); node.setDirtyCanvas(true); } // Set up callback (exactly like videoInferenceDimensionsHandler does) appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 50); }); } // Start initialization setTimeout(initializeHandler, 200); } function upscalerToggleHandler(upscalerNode) { // Find all "use" parameter widgets for Upscaler const useUpscaleFactorWidget = upscalerNode.widgets.find(w => w.name === "useUpscaleFactor"); const upscaleFactorWidget = upscalerNode.widgets.find(w => w.name === "upscaleFactor"); const useStepsWidget = upscalerNode.widgets.find(w => w.name === "useSteps"); const stepsWidget = upscalerNode.widgets.find(w => w.name === "steps"); const useSeedWidget = upscalerNode.widgets.find(w => w.name === "useSeed"); const seedWidget = upscalerNode.widgets.find(w => w.name === "seed"); const useCFGScaleWidget = upscalerNode.widgets.find(w => w.name === "useCFGScale"); const cfgScaleWidget = upscalerNode.widgets.find(w => w.name === "CFGScale"); const usePromptsWidget = upscalerNode.widgets.find(w => w.name === "usePrompts"); const positivePromptWidget = upscalerNode.widgets.find(w => w.name === "positivePrompt"); const negativePromptWidget = upscalerNode.widgets.find(w => w.name === "negativePrompt"); const useClarityParamsWidget = upscalerNode.widgets.find(w => w.name === "useClarityParams"); const controlNetWeightWidget = upscalerNode.widgets.find(w => w.name === "controlNetWeight"); const strengthWidget = upscalerNode.widgets.find(w => w.name === "strength"); const schedulerWidget = upscalerNode.widgets.find(w => w.name === "scheduler"); const useCCSRParamsWidget = upscalerNode.widgets.find(w => w.name === "useCCSRParams"); const colorFixWidget = upscalerNode.widgets.find(w => w.name === "colorFix"); const tileDiffusionWidget = upscalerNode.widgets.find(w => w.name === "tileDiffusion"); const useLatentParamsWidget = upscalerNode.widgets.find(w => w.name === "useLatentParams"); const clipSkipWidget = upscalerNode.widgets.find(w => w.name === "clipSkip"); // Helper function to toggle widget enabled state (exact same pattern) function toggleWidgetState(useWidget, paramWidgets, paramNames) { if (!useWidget || !paramWidgets || paramWidgets.length === 0) return; function toggleEnabled() { const enabled = useWidget.value === true; // Apply to each parameter widget paramWidgets.forEach((paramWidget, idx) => { if (!paramWidget) return; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = upscalerNode.htmlElements?.widgetsContainer || upscalerNode.htmlElements; if (nodeElement && paramNames[idx]) { const input = nodeElement.querySelector(`input[name="${paramNames[idx]}"], textarea[name="${paramNames[idx]}"], select[name="${paramNames[idx]}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } }); upscalerNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (useUpscaleFactorWidget && upscaleFactorWidget) { toggleWidgetState(useUpscaleFactorWidget, [upscaleFactorWidget], ["upscaleFactor"]); } if (useStepsWidget && stepsWidget) { toggleWidgetState(useStepsWidget, [stepsWidget], ["steps"]); } if (useSeedWidget && seedWidget) { toggleWidgetState(useSeedWidget, [seedWidget], ["seed"]); } if (useCFGScaleWidget && cfgScaleWidget) { toggleWidgetState(useCFGScaleWidget, [cfgScaleWidget], ["CFGScale"]); } if (usePromptsWidget && positivePromptWidget && negativePromptWidget) { toggleWidgetState(usePromptsWidget, [positivePromptWidget, negativePromptWidget], ["positivePrompt", "negativePrompt"]); } if (useClarityParamsWidget && controlNetWeightWidget && strengthWidget && schedulerWidget) { toggleWidgetState(useClarityParamsWidget, [controlNetWeightWidget, strengthWidget, schedulerWidget], ["controlNetWeight", "strength", "scheduler"]); } if (useCCSRParamsWidget && colorFixWidget && tileDiffusionWidget) { toggleWidgetState(useCCSRParamsWidget, [colorFixWidget, tileDiffusionWidget], ["colorFix", "tileDiffusion"]); } if (useLatentParamsWidget && clipSkipWidget) { toggleWidgetState(useLatentParamsWidget, [clipSkipWidget], ["clipSkip"]); } const useTargetMegapixelsWidget = upscalerNode.widgets.find(w => w.name === "useTargetMegapixels"); const targetMegapixelsWidget = upscalerNode.widgets.find(w => w.name === "targetMegapixels"); if (useTargetMegapixelsWidget && targetMegapixelsWidget) { toggleWidgetState(useTargetMegapixelsWidget, [targetMegapixelsWidget], ["targetMegapixels"]); } } function imageUpscalerSettingsToggleHandler(settingsNode) { const useEnhanceDetailsWidget = settingsNode.widgets.find(w => w.name === "useEnhanceDetails"); const enhanceDetailsWidget = settingsNode.widgets.find(w => w.name === "enhanceDetails"); const useRealismWidget = settingsNode.widgets.find(w => w.name === "useRealism"); const realismWidget = settingsNode.widgets.find(w => w.name === "realism"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "pointer" : "not-allowed"; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = settingsNode.htmlElements?.widgetsContainer || settingsNode.htmlElements; if (nodeElement && paramName) { const input = nodeElement.querySelector( `input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]` ); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "pointer" : "not-allowed"; } } } settingsNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useEnhanceDetailsWidget && enhanceDetailsWidget) { toggleWidgetState(useEnhanceDetailsWidget, enhanceDetailsWidget, "enhanceDetails"); } if (useRealismWidget && realismWidget) { toggleWidgetState(useRealismWidget, realismWidget, "realism"); } } function audioInferenceToggleHandler(audioInferenceNode) { // Find all "use" parameter widgets for Audio Inference const usePositivePromptWidget = audioInferenceNode.widgets.find(w => w.name === "usePositivePrompt"); const positivePromptWidget = audioInferenceNode.widgets.find(w => w.name === "positivePrompt"); const useDurationWidget = audioInferenceNode.widgets.find(w => w.name === "useDuration"); const durationWidget = audioInferenceNode.widgets.find(w => w.name === "duration"); const useSampleRateWidget = audioInferenceNode.widgets.find(w => w.name === "useSampleRate"); const sampleRateWidget = audioInferenceNode.widgets.find(w => w.name === "sampleRate"); const useBitrateWidget = audioInferenceNode.widgets.find(w => w.name === "useBitrate"); const bitrateWidget = audioInferenceNode.widgets.find(w => w.name === "bitrate"); const useSeedWidget = audioInferenceNode.widgets.find(w => w.name === "useSeed"); const seedWidget = audioInferenceNode.widgets.find(w => w.name === "seed"); const useStepsWidget = audioInferenceNode.widgets.find(w => w.name === "useSteps"); const stepsWidget = audioInferenceNode.widgets.find(w => w.name === "steps"); const useStrengthWidget = audioInferenceNode.widgets.find(w => w.name === "useStrength"); const strengthWidget = audioInferenceNode.widgets.find(w => w.name === "strength"); const useCFGScaleWidget = audioInferenceNode.widgets.find(w => w.name === "useCFGScale"); const CFGScaleWidget = audioInferenceNode.widgets.find(w => w.name === "CFGScale"); const useChannelsWidget = audioInferenceNode.widgets.find(w => w.name === "useChannels"); const channelsWidget = audioInferenceNode.widgets.find(w => w.name === "channels"); // Helper function to toggle widget enabled state (exact same pattern) function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = audioInferenceNode.htmlElements?.widgetsContainer || audioInferenceNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } audioInferenceNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (usePositivePromptWidget && positivePromptWidget) { toggleWidgetState(usePositivePromptWidget, positivePromptWidget, "positivePrompt"); } if (useDurationWidget && durationWidget) { toggleWidgetState(useDurationWidget, durationWidget, "duration"); } if (useSampleRateWidget && sampleRateWidget) { toggleWidgetState(useSampleRateWidget, sampleRateWidget, "sampleRate"); } if (useBitrateWidget && bitrateWidget) { toggleWidgetState(useBitrateWidget, bitrateWidget, "bitrate"); } if (useSeedWidget && seedWidget) { toggleWidgetState(useSeedWidget, seedWidget, "seed"); } if (useStepsWidget && stepsWidget) { toggleWidgetState(useStepsWidget, stepsWidget, "steps"); } if (useStrengthWidget && strengthWidget) { toggleWidgetState(useStrengthWidget, strengthWidget, "strength"); } if (useCFGScaleWidget && CFGScaleWidget) { toggleWidgetState(useCFGScaleWidget, CFGScaleWidget, "CFGScale"); } if (useChannelsWidget && channelsWidget) { toggleWidgetState(useChannelsWidget, channelsWidget, "channels"); } } function audioSettingsToggleHandler(settingsNode) { if (!settingsNode?.widgets) return; const useTemperatureWidget = settingsNode.widgets.find(w => w && w.name === "useTemperature"); const temperatureWidget = settingsNode.widgets.find(w => w && w.name === "temperature"); const useLyricsWidget = settingsNode.widgets.find(w => w && w.name === "useLyrics"); const lyricsWidget = settingsNode.widgets.find(w => w && w.name === "lyrics"); const useGuidanceTypeWidget = settingsNode.widgets.find(w => w && w.name === "useGuidanceType"); const guidanceTypeWidget = settingsNode.widgets.find(w => w && w.name === "guidanceType"); const useLanguageBoostWidget = settingsNode.widgets.find(w => w && w.name === "useLanguageBoost"); const languageBoostWidget = settingsNode.widgets.find(w => w && w.name === "languageBoost"); const useTurboWidget = settingsNode.widgets.find(w => w && w.name === "useTurbo"); const turboWidget = settingsNode.widgets.find(w => w && w.name === "turbo"); const useTextNormalizationWidget = settingsNode.widgets.find(w => w && w.name === "useTextNormalization"); const textNormalizationWidget = settingsNode.widgets.find(w => w && w.name === "textNormalization"); const useBpmWidget = settingsNode.widgets.find(w => w && w.name === "useBpm"); const bpmWidget = settingsNode.widgets.find(w => w && w.name === "bpm"); const useKeyScaleWidget = settingsNode.widgets.find(w => w && w.name === "useKeyScale"); const keyScaleWidget = settingsNode.widgets.find(w => w && w.name === "keyScale"); const useTimeSignatureWidget = settingsNode.widgets.find(w => w && w.name === "useTimeSignature"); const timeSignatureWidget = settingsNode.widgets.find(w => w && w.name === "timeSignature"); const useVocalLanguageWidget = settingsNode.widgets.find(w => w && w.name === "useVocalLanguage"); const vocalLanguageWidget = settingsNode.widgets.find(w => w && w.name === "vocalLanguage"); const useCoverConditioningScaleWidget = settingsNode.widgets.find(w => w && w.name === "useCoverConditioningScale"); const coverConditioningScaleWidget = settingsNode.widgets.find(w => w && w.name === "coverConditioningScale"); const useRepaintingStartWidget = settingsNode.widgets.find(w => w && w.name === "useRepaintingStart"); const repaintingStartWidget = settingsNode.widgets.find(w => w && w.name === "repaintingStart"); const useRepaintingEndWidget = settingsNode.widgets.find(w => w && w.name === "useRepaintingEnd"); const repaintingEndWidget = settingsNode.widgets.find(w => w && w.name === "repaintingEnd"); const useXVectorOnlyWidget = settingsNode.widgets.find(w => w && w.name === "useXVectorOnly"); const xVectorOnlyWidget = settingsNode.widgets.find(w => w && w.name === "xVectorOnly"); const useMaxNewTokensWidget = settingsNode.widgets.find(w => w && w.name === "useMaxNewTokens"); const maxNewTokensWidget = settingsNode.widgets.find(w => w && w.name === "maxNewTokens"); const useTranscriptWidget = settingsNode.widgets.find(w => w && w.name === "useTranscript"); const transcriptWidget = settingsNode.widgets.find(w => w && w.name === "transcript"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function applyState() { const enabled = useWidget.value === true; toggleWidgetEnabled(paramWidget, enabled, settingsNode); if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } settingsNode.setDirtyCanvas(true); } setTimeout(applyState, 100); appendWidgetCB(useWidget, () => setTimeout(applyState, 50)); } if (useTemperatureWidget && temperatureWidget) toggleWidgetState(useTemperatureWidget, temperatureWidget, "temperature"); if (useLyricsWidget && lyricsWidget) toggleWidgetState(useLyricsWidget, lyricsWidget, "lyrics"); if (useGuidanceTypeWidget && guidanceTypeWidget) toggleWidgetState(useGuidanceTypeWidget, guidanceTypeWidget, "guidanceType"); if (useLanguageBoostWidget && languageBoostWidget) toggleWidgetState(useLanguageBoostWidget, languageBoostWidget, "languageBoost"); if (useTurboWidget && turboWidget) toggleWidgetState(useTurboWidget, turboWidget, "turbo"); if (useTextNormalizationWidget && textNormalizationWidget) toggleWidgetState(useTextNormalizationWidget, textNormalizationWidget, "textNormalization"); if (useBpmWidget && bpmWidget) toggleWidgetState(useBpmWidget, bpmWidget, "bpm"); if (useKeyScaleWidget && keyScaleWidget) toggleWidgetState(useKeyScaleWidget, keyScaleWidget, "keyScale"); if (useTimeSignatureWidget && timeSignatureWidget) toggleWidgetState(useTimeSignatureWidget, timeSignatureWidget, "timeSignature"); if (useVocalLanguageWidget && vocalLanguageWidget) toggleWidgetState(useVocalLanguageWidget, vocalLanguageWidget, "vocalLanguage"); if (useCoverConditioningScaleWidget && coverConditioningScaleWidget) toggleWidgetState(useCoverConditioningScaleWidget, coverConditioningScaleWidget, "coverConditioningScale"); if (useRepaintingStartWidget && repaintingStartWidget) toggleWidgetState(useRepaintingStartWidget, repaintingStartWidget, "repaintingStart"); if (useRepaintingEndWidget && repaintingEndWidget) toggleWidgetState(useRepaintingEndWidget, repaintingEndWidget, "repaintingEnd"); if (useXVectorOnlyWidget && xVectorOnlyWidget) toggleWidgetState(useXVectorOnlyWidget, xVectorOnlyWidget, "xVectorOnly"); if (useMaxNewTokensWidget && maxNewTokensWidget) toggleWidgetState(useMaxNewTokensWidget, maxNewTokensWidget, "maxNewTokens"); if (useTranscriptWidget && transcriptWidget) toggleWidgetState(useTranscriptWidget, transcriptWidget, "transcript"); } function textInferenceSettingsToggleHandler(settingsNode) { if (!settingsNode?.widgets) return; const useSystemPromptWidget = settingsNode.widgets.find(w => w && w.name === "useSystemPrompt"); const systemWidget = settingsNode.widgets.find(w => w && w.name === "system"); const useMaxTokensWidget = settingsNode.widgets.find(w => w && w.name === "useMaxTokens"); const maxTokensWidget = settingsNode.widgets.find(w => w && w.name === "maxTokens"); const useTemperatureWidget = settingsNode.widgets.find(w => w && w.name === "useTemperature"); const temperatureWidget = settingsNode.widgets.find(w => w && w.name === "temperature"); const useTopPWidget = settingsNode.widgets.find(w => w && w.name === "useTopP"); const topPWidget = settingsNode.widgets.find(w => w && w.name === "topP"); const useTopKWidget = settingsNode.widgets.find(w => w && w.name === "useTopK"); const topKWidget = settingsNode.widgets.find(w => w && w.name === "topK"); function toggleWidgetState(useWidget, paramWidget) { if (!useWidget || !paramWidget) return; function applyState() { const enabled = useWidget.value === true; toggleWidgetEnabled(paramWidget, enabled, settingsNode); if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } settingsNode.setDirtyCanvas(true); } setTimeout(applyState, 100); appendWidgetCB(useWidget, () => setTimeout(applyState, 50)); } if (useSystemPromptWidget && systemWidget) toggleWidgetState(useSystemPromptWidget, systemWidget); if (useMaxTokensWidget && maxTokensWidget) toggleWidgetState(useMaxTokensWidget, maxTokensWidget); if (useTemperatureWidget && temperatureWidget) toggleWidgetState(useTemperatureWidget, temperatureWidget); if (useTopPWidget && topPWidget) toggleWidgetState(useTopPWidget, topPWidget); if (useTopKWidget && topKWidget) toggleWidgetState(useTopKWidget, topKWidget); } function videoSettingsToggleHandler(settingsNode) { if (!settingsNode?.widgets) return; const useDraftWidget = settingsNode.widgets.find(w => w && w.name === "useDraft"); const draftWidget = settingsNode.widgets.find(w => w && w.name === "draft"); const useAudioWidget = settingsNode.widgets.find(w => w && w.name === "useAudio"); const audioWidget = settingsNode.widgets.find(w => w && w.name === "audio"); const usePromptUpsamplingWidget = settingsNode.widgets.find(w => w && w.name === "usePromptUpsampling"); const promptUpsamplingWidget = settingsNode.widgets.find(w => w && w.name === "promptUpsampling"); const useBackgroundColorWidget = settingsNode.widgets.find(w => w && w.name === "useBackgroundColor"); const backgroundColorWidget = settingsNode.widgets.find(w => w && w.name === "backgroundColor"); const useRemoveBackgroundWidget = settingsNode.widgets.find(w => w && w.name === "useRemoveBackground"); const removeBackgroundWidget = settingsNode.widgets.find(w => w && w.name === "removeBackground"); const useExpressivenessWidget = settingsNode.widgets.find(w => w && w.name === "useExpressiveness"); const expressivenessWidget = settingsNode.widgets.find(w => w && w.name === "expressiveness"); const useVoiceDescriptionWidget = settingsNode.widgets.find(w => w && w.name === "useVoiceDescription"); const voiceDescriptionWidget = settingsNode.widgets.find(w => w && w.name === "voiceDescription"); const useStyleWidget = settingsNode.widgets.find(w => w && w.name === "useStyle"); const styleWidget = settingsNode.widgets.find(w => w && w.name === "style"); const useThinkingWidget = settingsNode.widgets.find(w => w && w.name === "useThinking"); const thinkingWidget = settingsNode.widgets.find(w => w && w.name === "thinking"); const useMultiClipWidget = settingsNode.widgets.find(w => w && w.name === "useMultiClip"); const multiClipWidget = settingsNode.widgets.find(w => w && w.name === "multiClip"); const useShotTypeWidget = settingsNode.widgets.find(w => w && w.name === "useShotType"); const shotTypeWidget = settingsNode.widgets.find(w => w && w.name === "shotType"); const usePromptExtendWidget = settingsNode.widgets.find(w => w && w.name === "usePromptExtend"); const promptExtendWidget = settingsNode.widgets.find(w => w && w.name === "promptExtend"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function applyState() { const enabled = useWidget.value === true; toggleWidgetEnabled(paramWidget, enabled, settingsNode); if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } settingsNode.setDirtyCanvas(true); } setTimeout(applyState, 100); appendWidgetCB(useWidget, () => setTimeout(applyState, 50)); } if (useDraftWidget && draftWidget) toggleWidgetState(useDraftWidget, draftWidget, "draft"); if (useAudioWidget && audioWidget) toggleWidgetState(useAudioWidget, audioWidget, "audio"); if (usePromptUpsamplingWidget && promptUpsamplingWidget) toggleWidgetState(usePromptUpsamplingWidget, promptUpsamplingWidget, "promptUpsampling"); if (useBackgroundColorWidget && backgroundColorWidget) toggleWidgetState(useBackgroundColorWidget, backgroundColorWidget, "backgroundColor"); if (useRemoveBackgroundWidget && removeBackgroundWidget) toggleWidgetState(useRemoveBackgroundWidget, removeBackgroundWidget, "removeBackground"); if (useExpressivenessWidget && expressivenessWidget) toggleWidgetState(useExpressivenessWidget, expressivenessWidget, "expressiveness"); if (useVoiceDescriptionWidget && voiceDescriptionWidget) toggleWidgetState(useVoiceDescriptionWidget, voiceDescriptionWidget, "voiceDescription"); if (useStyleWidget && styleWidget) toggleWidgetState(useStyleWidget, styleWidget, "style"); if (useThinkingWidget && thinkingWidget) toggleWidgetState(useThinkingWidget, thinkingWidget, "thinking"); if (useMultiClipWidget && multiClipWidget) toggleWidgetState(useMultiClipWidget, multiClipWidget, "multiClip"); if (useShotTypeWidget && shotTypeWidget) toggleWidgetState(useShotTypeWidget, shotTypeWidget, "shotType"); if (usePromptExtendWidget && promptExtendWidget) toggleWidgetState(usePromptExtendWidget, promptExtendWidget, "promptExtend"); } function audioInferenceSpeechToggleHandler(speechNode) { if (!speechNode?.widgets) return; const useVoiceWidget = speechNode.widgets.find(w => w && w.name === "useVoice"); const voiceWidget = speechNode.widgets.find(w => w && w.name === "voice"); const useSpeedWidget = speechNode.widgets.find(w => w && w.name === "useSpeed"); const speedWidget = speechNode.widgets.find(w => w && w.name === "speed"); const useVolumeWidget = speechNode.widgets.find(w => w && w.name === "useVolume"); const volumeWidget = speechNode.widgets.find(w => w && w.name === "volume"); const usePitchWidget = speechNode.widgets.find(w => w && w.name === "usePitch"); const pitchWidget = speechNode.widgets.find(w => w && w.name === "pitch"); const useEmotionWidget = speechNode.widgets.find(w => w && w.name === "useEmotion"); const emotionWidget = speechNode.widgets.find(w => w && w.name === "emotion"); const useToneWidget = speechNode.widgets.find(w => w && w.name === "useTone"); const toneWidget = speechNode.widgets.find(w => w && w.name === "tone"); const useLanguageWidget = speechNode.widgets.find(w => w && w.name === "useLanguage"); const languageWidget = speechNode.widgets.find(w => w && w.name === "language"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function applyState() { const enabled = useWidget.value === true; toggleWidgetEnabled(paramWidget, enabled, speechNode); if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } speechNode.setDirtyCanvas(true); } setTimeout(applyState, 100); appendWidgetCB(useWidget, () => setTimeout(applyState, 50)); } if (useSpeedWidget && speedWidget) toggleWidgetState(useSpeedWidget, speedWidget, "speed"); if (useVolumeWidget && volumeWidget) toggleWidgetState(useVolumeWidget, volumeWidget, "volume"); if (usePitchWidget && pitchWidget) toggleWidgetState(usePitchWidget, pitchWidget, "pitch"); if (useEmotionWidget && emotionWidget) toggleWidgetState(useEmotionWidget, emotionWidget, "emotion"); if (useToneWidget && toneWidget) toggleWidgetState(useToneWidget, toneWidget, "tone"); if (useLanguageWidget && languageWidget) toggleWidgetState(useLanguageWidget, languageWidget, "language"); if (useVoiceWidget && voiceWidget) toggleWidgetState(useVoiceWidget, voiceWidget, "voice"); } function acceleratorOptionsToggleHandler(acceleratorNode) { // Find all "use" parameter widgets for Accelerator Options const useCacheDistanceWidget = acceleratorNode.widgets.find(w => w.name === "useCacheDistance"); const cacheDistanceWidget = acceleratorNode.widgets.find(w => w.name === "cacheDistance"); const useTeaCacheDistanceWidget = acceleratorNode.widgets.find(w => w.name === "useTeaCacheDistance"); const teaCacheDistanceWidget = acceleratorNode.widgets.find(w => w.name === "teaCacheDistance"); const useDeepCacheOptionsWidget = acceleratorNode.widgets.find(w => w.name === "useDeepCacheOptions"); const deepCacheIntervalWidget = acceleratorNode.widgets.find(w => w.name === "deepCacheInterval"); const deepCacheBranchIdWidget = acceleratorNode.widgets.find(w => w.name === "deepCacheBranchId"); const useCacheStepsWidget = acceleratorNode.widgets.find(w => w.name === "useCacheSteps"); const cacheStartStepWidget = acceleratorNode.widgets.find(w => w.name === "cacheStartStep"); const cacheEndStepWidget = acceleratorNode.widgets.find(w => w.name === "cacheEndStep"); const useCachePercentageStepsWidget = acceleratorNode.widgets.find(w => w.name === "useCachePercentageSteps"); const cacheStartStepPercentageWidget = acceleratorNode.widgets.find(w => w.name === "cacheStartStepPercentage"); const cacheEndStepPercentageWidget = acceleratorNode.widgets.find(w => w.name === "cacheEndStepPercentage"); const useCacheMaxConsecutiveStepsWidget = acceleratorNode.widgets.find(w => w.name === "useCacheMaxConsecutiveSteps"); const cacheMaxConsecutiveStepsWidget = acceleratorNode.widgets.find(w => w.name === "cacheMaxConsecutiveSteps"); // Helper function to toggle widget enabled state (exact same pattern) function toggleWidgetState(useWidget, paramWidgets, paramNames) { if (!useWidget || !paramWidgets || paramWidgets.length === 0) return; function toggleEnabled() { const enabled = useWidget.value === true; paramWidgets.forEach((paramWidget, idx) => { if (!paramWidget) return; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = acceleratorNode.htmlElements?.widgetsContainer || acceleratorNode.htmlElements; if (nodeElement && paramNames[idx]) { const input = nodeElement.querySelector(`input[name="${paramNames[idx]}"], textarea[name="${paramNames[idx]}"], select[name="${paramNames[idx]}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } }); acceleratorNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (useCacheDistanceWidget && cacheDistanceWidget) { toggleWidgetState(useCacheDistanceWidget, [cacheDistanceWidget], ["cacheDistance"]); } if (useTeaCacheDistanceWidget && teaCacheDistanceWidget) { toggleWidgetState(useTeaCacheDistanceWidget, [teaCacheDistanceWidget], ["teaCacheDistance"]); } if (useDeepCacheOptionsWidget && deepCacheIntervalWidget && deepCacheBranchIdWidget) { toggleWidgetState(useDeepCacheOptionsWidget, [deepCacheIntervalWidget, deepCacheBranchIdWidget], ["deepCacheInterval", "deepCacheBranchId"]); } if (useCacheStepsWidget && cacheStartStepWidget && cacheEndStepWidget) { toggleWidgetState(useCacheStepsWidget, [cacheStartStepWidget, cacheEndStepWidget], ["cacheStartStep", "cacheEndStep"]); } if (useCachePercentageStepsWidget && cacheStartStepPercentageWidget && cacheEndStepPercentageWidget) { toggleWidgetState(useCachePercentageStepsWidget, [cacheStartStepPercentageWidget, cacheEndStepPercentageWidget], ["cacheStartStepPercentage", "cacheEndStepPercentage"]); } if (useCacheMaxConsecutiveStepsWidget && cacheMaxConsecutiveStepsWidget) { toggleWidgetState(useCacheMaxConsecutiveStepsWidget, [cacheMaxConsecutiveStepsWidget], ["cacheMaxConsecutiveSteps"]); } } function bytedanceProviderSettingsToggleHandler(bytedanceNode) { // Find all "use" parameter widgets for Bytedance Provider Settings const useCameraFixedWidget = bytedanceNode.widgets.find(w => w.name === "useCameraFixed"); const cameraFixedWidget = bytedanceNode.widgets.find(w => w.name === "cameraFixed"); const useMaxSequentialImagesWidget = bytedanceNode.widgets.find(w => w.name === "useMaxSequentialImages"); const maxSequentialImagesWidget = bytedanceNode.widgets.find(w => w.name === "maxSequentialImages"); const useFastModeWidget = bytedanceNode.widgets.find(w => w.name === "useFastMode"); const fastModeWidget = bytedanceNode.widgets.find(w => w.name === "fastMode"); const useAudioWidget = bytedanceNode.widgets.find(w => w.name === "useAudio"); const audioWidget = bytedanceNode.widgets.find(w => w.name === "audio"); const useDraftWidget = bytedanceNode.widgets.find(w => w.name === "useDraft"); const draftWidget = bytedanceNode.widgets.find(w => w.name === "draft"); const useOptimizePromptModeWidget = bytedanceNode.widgets.find(w => w.name === "useOptimizePromptMode"); const optimizePromptModeWidget = bytedanceNode.widgets.find(w => w.name === "optimizePromptMode"); // Helper function to toggle widget enabled state (exact same pattern) function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } if (!paramWidget.inputEl) { const nodeElement = bytedanceNode.htmlElements?.widgetsContainer || bytedanceNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } bytedanceNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (useCameraFixedWidget && cameraFixedWidget) { toggleWidgetState(useCameraFixedWidget, cameraFixedWidget, "cameraFixed"); } if (useMaxSequentialImagesWidget && maxSequentialImagesWidget) { toggleWidgetState(useMaxSequentialImagesWidget, maxSequentialImagesWidget, "maxSequentialImages"); } if (useFastModeWidget && fastModeWidget) { toggleWidgetState(useFastModeWidget, fastModeWidget, "fastMode"); } if (useAudioWidget && audioWidget) { toggleWidgetState(useAudioWidget, audioWidget, "audio"); } if (useDraftWidget && draftWidget) { toggleWidgetState(useDraftWidget, draftWidget, "draft"); } if (useOptimizePromptModeWidget && optimizePromptModeWidget) { toggleWidgetState(useOptimizePromptModeWidget, optimizePromptModeWidget, "optimizePromptMode"); } } function ultralyticsProviderSettingsToggleHandler(ultralyticsNode) { const useParamPairs = [ ["useMaskBlur", "maskBlur"], ["useMaskPadding", "maskPadding"], ["useConfidence", "confidence"], ["usePositivePrompt", "positivePrompt"], ["useNegativePrompt", "negativePrompt"], ["useSteps", "steps"], ["useCFGScale", "CFGScale"], ["useStrength", "strength"], ]; function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } if (!paramWidget.inputEl) { const nodeElement = ultralyticsNode.htmlElements?.widgetsContainer || ultralyticsNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.pointerEvents = enabled ? "auto" : "none"; } } } ultralyticsNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } useParamPairs.forEach(([useName, paramName]) => { const useWidget = ultralyticsNode.widgets.find(w => w.name === useName); const paramWidget = ultralyticsNode.widgets.find(w => w.name === paramName); if (useWidget && paramWidget) { toggleWidgetState(useWidget, paramWidget, paramName); } }); } function xaiProviderSettingsToggleHandler(xaiNode) { const useQualityWidget = xaiNode.widgets.find(w => w.name === "useQuality"); const qualityWidget = xaiNode.widgets.find(w => w.name === "quality"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } if (!paramWidget.inputEl) { const nodeElement = xaiNode.htmlElements?.widgetsContainer || xaiNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.pointerEvents = enabled ? "auto" : "none"; } } } xaiNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useQualityWidget && qualityWidget) { toggleWidgetState(useQualityWidget, qualityWidget, "quality"); } } function viduProviderSettingsToggleHandler(viduNode) { const useAudioWidget = viduNode.widgets.find(w => w.name === "useAudio"); const audioWidget = viduNode.widgets.find(w => w.name === "audio"); const useBgmWidget = viduNode.widgets.find(w => w.name === "useBgm"); const bgmWidget = viduNode.widgets.find(w => w.name === "bgm"); const useStyleWidget = viduNode.widgets.find(w => w.name === "useStyle"); const styleWidget = viduNode.widgets.find(w => w.name === "style"); const useMovementAmplitudeWidget = viduNode.widgets.find(w => w.name === "useMovementAmplitude"); const movementAmplitudeWidget = viduNode.widgets.find(w => w.name === "movementAmplitude"); const useTemplateNameWidget = viduNode.widgets.find(w => w.name === "useTemplateName"); const templateNameWidget = viduNode.widgets.find(w => w.name === "templateName"); const useTemplateAreaWidget = viduNode.widgets.find(w => w.name === "useTemplateArea"); const templateAreaWidget = viduNode.widgets.find(w => w.name === "templateArea"); const useTemplateBeastWidget = viduNode.widgets.find(w => w.name === "useTemplateBeast"); const templateBeastWidget = viduNode.widgets.find(w => w.name === "templateBeast"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = viduNode.htmlElements?.widgetsContainer || viduNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.pointerEvents = enabled ? "auto" : "none"; } } } viduNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useAudioWidget && audioWidget) { toggleWidgetState(useAudioWidget, audioWidget, "audio"); } if (useBgmWidget && bgmWidget) { toggleWidgetState(useBgmWidget, bgmWidget, "bgm"); } if (useStyleWidget && styleWidget) { toggleWidgetState(useStyleWidget, styleWidget, "style"); } if (useMovementAmplitudeWidget && movementAmplitudeWidget) { toggleWidgetState(useMovementAmplitudeWidget, movementAmplitudeWidget, "movementAmplitude"); } if (useTemplateNameWidget && templateNameWidget) { toggleWidgetState(useTemplateNameWidget, templateNameWidget, "templateName"); } if (useTemplateAreaWidget && templateAreaWidget) { toggleWidgetState(useTemplateAreaWidget, templateAreaWidget, "templateArea"); } if (useTemplateBeastWidget && templateBeastWidget) { toggleWidgetState(useTemplateBeastWidget, templateBeastWidget, "templateBeast"); } } function sourcefulProviderSettingsToggleHandler(sourcefulNode) { const useTransparencyWidget = sourcefulNode.widgets.find(w => w.name === "useTransparency"); const transparencyWidget = sourcefulNode.widgets.find(w => w.name === "transparency"); const useEnhancePromptWidget = sourcefulNode.widgets.find(w => w.name === "useEnhancePrompt"); const enhancePromptWidget = sourcefulNode.widgets.find(w => w.name === "enhancePrompt"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = sourcefulNode.htmlElements?.widgetsContainer || sourcefulNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.pointerEvents = enabled ? "auto" : "none"; } } } sourcefulNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useTransparencyWidget && transparencyWidget) { toggleWidgetState(useTransparencyWidget, transparencyWidget, "transparency"); } if (useEnhancePromptWidget && enhancePromptWidget) { toggleWidgetState(useEnhancePromptWidget, enhancePromptWidget, "enhancePrompt"); } } function sourcefulProviderSettingsFontsToggleHandler(fontsNode) { const useFont1Widget = fontsNode.widgets.find(w => w.name === "useFont1"); const fontUrl1Widget = fontsNode.widgets.find(w => w.name === "fontUrl1"); const text1Widget = fontsNode.widgets.find(w => w.name === "text1"); const useFont2Widget = fontsNode.widgets.find(w => w.name === "useFont2"); const fontUrl2Widget = fontsNode.widgets.find(w => w.name === "fontUrl2"); const text2Widget = fontsNode.widgets.find(w => w.name === "text2"); function toggleFontGroup(useWidget, fontUrlWidget, textWidget, fontParamName, textParamName) { if (!useWidget || !fontUrlWidget || !textWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; [fontUrlWidget, textWidget].forEach(paramWidget => { if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; }); const nodeElement = fontsNode.htmlElements?.widgetsContainer || fontsNode.htmlElements; if (nodeElement) { [fontParamName, textParamName].forEach(paramName => { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.pointerEvents = enabled ? "auto" : "none"; } }); } fontsNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useFont1Widget && fontUrl1Widget && text1Widget) { toggleFontGroup(useFont1Widget, fontUrl1Widget, text1Widget, "fontUrl1", "text1"); } if (useFont2Widget && fontUrl2Widget && text2Widget) { toggleFontGroup(useFont2Widget, fontUrl2Widget, text2Widget, "fontUrl2", "text2"); } } function threeDInferenceToggleHandler(node) { const useOutputQualityWidget = node.widgets.find(w => w.name === "useOutputQuality"); const outputQualityWidget = node.widgets.find(w => w.name === "outputQuality"); if (!useOutputQualityWidget || !outputQualityWidget) return; function toggleEnabled() { const enabled = useOutputQualityWidget.value === true; toggleWidgetEnabled(outputQualityWidget, enabled, node); node.setDirtyCanvas(true); } appendWidgetCB(useOutputQualityWidget, () => setTimeout(toggleEnabled, 50)); setTimeout(toggleEnabled, 100); } function threeDInferenceSettingsToggleHandler(node) { const pairs = [ ["useTextureSize", "textureSize"], ["useDecimationTarget", "decimationTarget"], ["useRemesh", "remesh"], ["useResolution", "resolution"], ["useImageAutoFix", "imageAutoFix"], ["useFaceLimit", "faceLimit"], ["useTexture", "texture"], ["usePbr", "pbr"], ["useTextureSeed", "textureSeed"], ["useTextureAlignment", "textureAlignment"], ["useTextureQuality", "textureQuality"], ["useAutoSize", "autoSize"], ["useOrientation", "orientation"], ["useQuad", "quad"], ["useCompress", "compress"], ["useSmartLowPoly", "smartLowPoly"], ["useGenerateParts", "generateParts"], ["useExportUv", "exportUv"], ["useGeometryQuality", "geometryQuality"], ]; pairs.forEach(([useName, paramName]) => { const useW = node.widgets.find(w => w.name === useName); const paramW = node.widgets.find(w => w.name === paramName); if (!useW || !paramW) return; function toggleEnabled() { const enabled = useW.value === true; toggleWidgetEnabled(paramW, enabled, node); node.setDirtyCanvas(true); } appendWidgetCB(useW, () => setTimeout(toggleEnabled, 50)); setTimeout(toggleEnabled, 100); }); } function threeDInferenceSettingsLatToggleHandler(node) { const pairs = [ ["useGuidanceStrength", "guidanceStrength"], ["useGuidanceRescale", "guidanceRescale"], ["useSteps", "steps"], ["useRescaleT", "rescaleT"], ]; pairs.forEach(([useName, paramName]) => { const useW = node.widgets.find(w => w.name === useName); const paramW = node.widgets.find(w => w.name === paramName); if (!useW || !paramW) return; function toggleEnabled() { const enabled = useW.value === true; toggleWidgetEnabled(paramW, enabled, node); node.setDirtyCanvas(true); } appendWidgetCB(useW, () => setTimeout(toggleEnabled, 50)); setTimeout(toggleEnabled, 100); }); } function openaiProviderSettingsToggleHandler(openaiNode) { // Find all "use" parameter widgets for OpenAI Provider Settings (these are COMBO widgets) const useBackgroundWidget = openaiNode.widgets.find(w => w.name === "useBackground"); const backgroundWidget = openaiNode.widgets.find(w => w.name === "background"); const useStyleWidget = openaiNode.widgets.find(w => w.name === "useStyle"); const styleWidget = openaiNode.widgets.find(w => w.name === "style"); // Helper function to toggle widget enabled state (exact same pattern, but handles COMBO) function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { // For COMBO widgets, check if value is "enable" const enabled = useWidget.value === "enable" || useWidget.value === "Enable"; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Handle dropdown widgets if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = openaiNode.htmlElements?.widgetsContainer || openaiNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } openaiNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (useBackgroundWidget && backgroundWidget) { toggleWidgetState(useBackgroundWidget, backgroundWidget, "background"); } if (useStyleWidget && styleWidget) { toggleWidgetState(useStyleWidget, styleWidget, "style"); } } function pixverseProviderSettingsToggleHandler(pixverseNode) { // Find all "use" parameter widgets for Pixverse Provider Settings const useEffectWidget = pixverseNode.widgets.find(w => w.name === "useEffect"); const effectWidget = pixverseNode.widgets.find(w => w.name === "effect"); const useCameraMovementWidget = pixverseNode.widgets.find(w => w.name === "useCameraMovement"); const cameraMovementWidget = pixverseNode.widgets.find(w => w.name === "cameraMovement"); const useStyleWidget = pixverseNode.widgets.find(w => w.name === "useStyle"); const styleWidget = pixverseNode.widgets.find(w => w.name === "style"); const useMotionModeWidget = pixverseNode.widgets.find(w => w.name === "useMotionMode"); const motionModeWidget = pixverseNode.widgets.find(w => w.name === "motionMode"); const useSoundEffectSwitchWidget = pixverseNode.widgets.find(w => w.name === "useSoundEffectSwitch"); const soundEffectSwitchWidget = pixverseNode.widgets.find(w => w.name === "soundEffectSwitch"); const useSoundEffectContentWidget = pixverseNode.widgets.find(w => w.name === "useSoundEffectContent"); const soundEffectContentWidget = pixverseNode.widgets.find(w => w.name === "soundEffectContent"); const useAudioWidget = pixverseNode.widgets.find(w => w.name === "useAudio"); const audioWidget = pixverseNode.widgets.find(w => w.name === "audio"); const useMultiClipWidget = pixverseNode.widgets.find(w => w.name === "useMultiClip"); const multiClipWidget = pixverseNode.widgets.find(w => w.name === "multiClip"); const useThinkingWidget = pixverseNode.widgets.find(w => w.name === "useThinking"); const thinkingWidget = pixverseNode.widgets.find(w => w.name === "thinking"); // Helper function to toggle widget enabled state (exact same pattern) function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Handle dropdown widgets if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = pixverseNode.htmlElements?.widgetsContainer || pixverseNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } pixverseNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (useEffectWidget && effectWidget) { toggleWidgetState(useEffectWidget, effectWidget, "effect"); } if (useCameraMovementWidget && cameraMovementWidget) { toggleWidgetState(useCameraMovementWidget, cameraMovementWidget, "cameraMovement"); } if (useStyleWidget && styleWidget) { toggleWidgetState(useStyleWidget, styleWidget, "style"); } if (useMotionModeWidget && motionModeWidget) { toggleWidgetState(useMotionModeWidget, motionModeWidget, "motionMode"); } if (useSoundEffectSwitchWidget && soundEffectSwitchWidget) { toggleWidgetState(useSoundEffectSwitchWidget, soundEffectSwitchWidget, "soundEffectSwitch"); } if (useSoundEffectContentWidget && soundEffectContentWidget) { toggleWidgetState(useSoundEffectContentWidget, soundEffectContentWidget, "soundEffectContent"); } if (useAudioWidget && audioWidget) { toggleWidgetState(useAudioWidget, audioWidget, "audio"); } if (useMultiClipWidget && multiClipWidget) { toggleWidgetState(useMultiClipWidget, multiClipWidget, "multiClip"); } if (useThinkingWidget && thinkingWidget) { toggleWidgetState(useThinkingWidget, thinkingWidget, "thinking"); } } function lightricksProviderSettingsToggleHandler(lightricksNode) { const useStartTimeWidget = lightricksNode.widgets.find(w => w.name === "useStartTime"); const startTimeWidget = lightricksNode.widgets.find(w => w.name === "startTime"); const useDurationWidget = lightricksNode.widgets.find(w => w.name === "useDuration"); const durationWidget = lightricksNode.widgets.find(w => w.name === "duration"); const useModeWidget = lightricksNode.widgets.find(w => w.name === "useMode"); const modeWidget = lightricksNode.widgets.find(w => w.name === "mode"); const useGenerateAudioWidget = lightricksNode.widgets.find(w => w.name === "useGenerateAudio"); const generateAudioWidget = lightricksNode.widgets.find(w => w.name === "generateAudio"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = lightricksNode.htmlElements?.widgetsContainer || lightricksNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } lightricksNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useStartTimeWidget && startTimeWidget) { toggleWidgetState(useStartTimeWidget, startTimeWidget, "startTime"); } if (useDurationWidget && durationWidget) { toggleWidgetState(useDurationWidget, durationWidget, "duration"); } if (useModeWidget && modeWidget) { toggleWidgetState(useModeWidget, modeWidget, "mode"); } if (useGenerateAudioWidget && generateAudioWidget) { toggleWidgetState(useGenerateAudioWidget, generateAudioWidget, "generateAudio"); } } function imageInferenceToggleHandler(imageInferenceNode) { // Find all "use" parameter widgets for Image Inference const useStepsWidget = imageInferenceNode.widgets.find(w => w.name === "useSteps"); const stepsWidget = imageInferenceNode.widgets.find(w => w.name === "steps"); const useSeedWidget = imageInferenceNode.widgets.find(w => w.name === "useSeed"); const seedWidget = imageInferenceNode.widgets.find(w => w.name === "seed"); const useCFGScaleWidget = imageInferenceNode.widgets.find(w => w.name === "useCFGScale"); const cfgScaleWidget = imageInferenceNode.widgets.find(w => w.name === "cfgScale"); const useSchedulerWidget = imageInferenceNode.widgets.find(w => w.name === "useScheduler"); const schedulerWidget = imageInferenceNode.widgets.find(w => w.name === "scheduler"); const useClipSkipWidget = imageInferenceNode.widgets.find(w => w.name === "useClipSkip"); const clipSkipWidget = imageInferenceNode.widgets.find(w => w.name === "clipSkip"); const maskMarginWidget = imageInferenceNode.widgets.find(w => w.name === "Mask Margin"); const maskMarginValueWidget = imageInferenceNode.widgets.find(w => w.name === "maskMargin"); const useResolutionWidget = imageInferenceNode.widgets.find(w => w.name === "useResolution"); const resolutionWidget = imageInferenceNode.widgets.find(w => w.name === "resolution"); const dimensionsWidget = imageInferenceNode.widgets.find(w => w.name === "dimensions"); const widthWidget = imageInferenceNode.widgets.find(w => w.name === "width"); const heightWidget = imageInferenceNode.widgets.find(w => w.name === "height"); // Helper function to toggle widget enabled state (exact same pattern as videoInferenceDimensionsHandler) function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; // Disable/enable widgets using inputEl if available (exact same pattern) if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Also set widget property paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = imageInferenceNode.htmlElements?.widgetsContainer || imageInferenceNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } imageInferenceNode.setDirtyCanvas(true); } // Set up callback (exact same pattern as useCustomDimensions) appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (useStepsWidget && stepsWidget) { toggleWidgetState(useStepsWidget, stepsWidget, "steps"); } if (useSeedWidget && seedWidget) { toggleWidgetState(useSeedWidget, seedWidget, "seed"); } if (useCFGScaleWidget && cfgScaleWidget) { toggleWidgetState(useCFGScaleWidget, cfgScaleWidget, "cfgScale"); } if (useSchedulerWidget && schedulerWidget) { toggleWidgetState(useSchedulerWidget, schedulerWidget, "scheduler"); } if (useClipSkipWidget && clipSkipWidget) { toggleWidgetState(useClipSkipWidget, clipSkipWidget, "clipSkip"); } // Handle Mask Margin (BOOLEAN widget) if (maskMarginWidget && maskMarginValueWidget) { toggleWidgetState(maskMarginWidget, maskMarginValueWidget, "maskMargin"); } // Handle Resolution if (useResolutionWidget && resolutionWidget) { toggleWidgetState(useResolutionWidget, resolutionWidget, "resolution"); } // Handle Dimensions - disable width/height when dimensions is "None" if (dimensionsWidget && widthWidget && heightWidget) { function toggleDimensionsState() { const dimensionsValue = dimensionsWidget.value; const enabled = dimensionsValue !== "None"; // Toggle width widget if (widthWidget.inputEl) { widthWidget.inputEl.disabled = !enabled; widthWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; widthWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; widthWidget.inputEl.readOnly = !enabled; } widthWidget.disabled = !enabled; // Toggle height widget if (heightWidget.inputEl) { heightWidget.inputEl.disabled = !enabled; heightWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; heightWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; heightWidget.inputEl.readOnly = !enabled; } heightWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!widthWidget.inputEl || !heightWidget.inputEl) { const nodeElement = imageInferenceNode.htmlElements?.widgetsContainer || imageInferenceNode.htmlElements; if (nodeElement) { const widthInput = nodeElement.querySelector(`input[name="width"]`); const heightInput = nodeElement.querySelector(`input[name="height"]`); if (widthInput) { widthInput.disabled = !enabled; widthInput.style.opacity = enabled ? "1" : "0.5"; widthInput.style.cursor = enabled ? "text" : "not-allowed"; widthInput.readOnly = !enabled; } if (heightInput) { heightInput.disabled = !enabled; heightInput.style.opacity = enabled ? "1" : "0.5"; heightInput.style.cursor = enabled ? "text" : "not-allowed"; heightInput.readOnly = !enabled; } } } imageInferenceNode.setDirtyCanvas(true); } appendWidgetCB(dimensionsWidget, () => { setTimeout(toggleDimensionsState, 50); }); setTimeout(toggleDimensionsState, 100); } } function videoInferenceDimensionsHandler(videoInferenceNode) { // Find "use" parameter widgets for Video Inference const useDurationWidget = videoInferenceNode.widgets.find(w => w.name === "useDuration"); const durationWidget = videoInferenceNode.widgets.find(w => w.name === "duration"); const useFpsWidget = videoInferenceNode.widgets.find(w => w.name === "useFps"); const fpsWidget = videoInferenceNode.widgets.find(w => w.name === "fps"); const useSeedWidget = videoInferenceNode.widgets.find(w => w.name === "useSeed"); const seedWidget = videoInferenceNode.widgets.find(w => w.name === "seed"); const useStepsWidget = videoInferenceNode.widgets.find(w => w.name === "useSteps"); const stepsWidget = videoInferenceNode.widgets.find(w => w.name === "steps"); const useBatchSizeWidget = videoInferenceNode.widgets.find(w => w.name === "useBatchSize"); const batchSizeWidget = videoInferenceNode.widgets.find(w => w.name === "batchSize"); const useSchedulersWidget = videoInferenceNode.widgets.find(w => w.name === "useSchedulers"); const schedulerWidget = videoInferenceNode.widgets.find(w => w.name === "scheduler"); const useCFGScaleWidget = videoInferenceNode.widgets.find(w => w.name === "useCFGScale"); const cfgScaleWidget = videoInferenceNode.widgets.find(w => w.name === "cfgScale"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; // Disable/enable widgets using inputEl if available if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Also set widget property paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = videoInferenceNode.htmlElements?.widgetsContainer || videoInferenceNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } videoInferenceNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up all toggle handlers for "use" parameters if (useDurationWidget && durationWidget) { toggleWidgetState(useDurationWidget, durationWidget, "duration"); } if (useFpsWidget && fpsWidget) { toggleWidgetState(useFpsWidget, fpsWidget, "fps"); } if (useSeedWidget && seedWidget) { toggleWidgetState(useSeedWidget, seedWidget, "seed"); } if (useStepsWidget && stepsWidget) { toggleWidgetState(useStepsWidget, stepsWidget, "steps"); } if (useBatchSizeWidget && batchSizeWidget) { toggleWidgetState(useBatchSizeWidget, batchSizeWidget, "batchSize"); } if (useSchedulersWidget && schedulerWidget) { toggleWidgetState(useSchedulersWidget, schedulerWidget, "scheduler"); } if (useCFGScaleWidget && cfgScaleWidget) { toggleWidgetState(useCFGScaleWidget, cfgScaleWidget, "cfgScale"); } } function videoModelSearchFilterHandler(videoModelSearchNode) { const modelArchWidget = videoModelSearchNode.widgets.find(w => w.name === "Model Architecture"); const videoListWidget = videoModelSearchNode.widgets.find(w => w.name === "VideoList"); const widthWidget = videoModelSearchNode.widgets.find(w => w.name === "Width"); const heightWidget = videoModelSearchNode.widgets.find(w => w.name === "Height"); const useCustomDimensionsWidget = videoModelSearchNode.widgets.find(w => w.name === "useCustomDimensions"); const useResolutionWidget = videoModelSearchNode.widgets.find(w => w.name === "useResolution"); const resolutionWidget = videoModelSearchNode.widgets.find(w => w.name === "resolution"); if (!modelArchWidget || !videoListWidget) return; const VIDEO_MODELS = { "KlingAI": [ "klingai:1@2 (KlingAI V1.0 Pro)", "klingai:1@1 (KlingAI V1 Standard)", "klingai:2@2 (KlingAI V1.5 Pro)", "klingai:2@1 (KlingAI V1.5 Standard)", "klingai:3@1 (KlingAI V1.6 Standard)", "klingai:3@2 (KlingAI V1.6 Pro)", "klingai:4@3 (KlingAI V2.1 Master)", "klingai:5@1 (KlingAI V2.1 Standard (I2V))", "klingai:5@2 (KlingAI V2.1 Pro (I2V))", "klingai:5@3 (KlingAI V2.0 Master)", "klingai:6@1 (KlingAI 2.5 Turbo Pro)", "klingai:7@1 (KlingAI Lip-Sync)", "klingai:kling@o1 (Kling VIDEO O1)", "klingai:kling-video@2.6-pro (Kling VIDEO 2.6 Pro)", "klingai:kling-video@3-pro (Kling VIDEO 3.0 Pro)", "klingai:kling-video@3-standard (Kling VIDEO 3.0 Standard)", "klingai:kling-video@o3-pro (Kling VIDEO O3 Pro)", "klingai:kling-video@o3-standard (Kling VIDEO O3 Standard)", "klingai:avatar@2.0-standard (KlingAI Avatar 2.0 Standard)", "klingai:avatar@2.0-pro (KlingAI Avatar 2.0 Pro)", ], "Veo": [ "google:2@0 (Veo 2.0)", "google:3@0 (Veo 3.0)", "google:3@1 (Veo 3.0 Fast)", "google:3@2 (Veo 3.1)", "google:3@3 (Veo 3.1 Fast)", "google:veo@3.1-lite (Veo 3.1 Lite)", ], "Bytedance": [ "bytedance:2@1 (Seedance 1.0 Pro)", "bytedance:1@1 (Seedance 1.0 Lite)", "bytedance:5@1 (OmniHuman 1)", "bytedance:5@2 (OmniHuman 1.5)", "bytedance:seedance@1.5-pro (Seedance 1.5 Pro)", ], "MiniMax": [ "minimax:1@1 (MiniMax 01 Base)", "minimax:2@1 (MiniMax 01 Director)", "minimax:2@3 (MiniMax I2V 01 Live)", "minimax:3@1 (MiniMax 02 Hailuo)", "minimax:4@1 (MiniMax Hailuo 2.3)", "minimax:4@2 (MiniMax Hailuo 2.3 Fast)", ], "PixVerse": [ "pixverse:1@1 (PixVerse v3.5)", "pixverse:1@2 (PixVerse v4)", "pixverse:1@3 (PixVerse v4.5)", "pixverse:1@5-fast (PixVerse v5 Fast)", "pixverse:1@6 (PixVerse v5.5)", "pixverse:1@7 (PixVerse v5.6)", "pixverse:1@8 (PixVerse v6)", "pixverse:lipsync@1 (PixVerse LipSync)", ], "Vidu": [ "vidu:1@0 (Vidu Q1 Classic)", "vidu:1@1 (Vidu Q1)", "vidu:1@5 (Vidu 1.5)", "vidu:2@0 (Vidu 2.0)", "vidu:4@1 (Vidu Q3)", "vidu:4@2 (Vidu Q3 Turbo)", ], "Wan": [ "runware:200@1 (Wan 2.1 1.3B)", "runware:200@2 (Wan 2.1 14B)", "runware:200@6 (Wan 2.2)", "runware:200@8 (Wan 2.2 A14B Animate)", "alibaba:wan@2.6 (Wan 2.6)", "alibaba:wan@2.6-flash (Wan 2.6 Flash)", "alibaba:wan@2.7 (Wan 2.7)", ], "OpenAI": [ "openai:3@1 (OpenAI Sora 3.1)", "openai:3@0 (OpenAI Sora 3.0)", ], "Lightricks": [ "lightricks:2@0 (LTX Fast)", "lightricks:2@1 (LTX Pro)", "lightricks:3@1 (LTX-2 Retake)", "lightricks:ltx@2 (LTX-2)", "lightricks:ltx@2.3 (LTX 2.3)", "lightricks:ltx@2.3-fast (LTX 2.3 Fast)", ], "Ovi": [ "runware:190@1 (Ovi)", ], "Runway": [ "runway:2@1 (Runway Aleph)", "runway:1@1 (Runway Gen-4 Turbo)", "runway:1@2 (Runway Gen-4.5)", ], "Luma": [ "lumaai:1@1 (Luma Ray 1.6)", "lumaai:2@1 (Luma Ray 2)", "lumaai:2@2 (Luma Ray 2 Flash)", ], "Sync": [ "sync:lipsync-2@1 (Sync LipSync 2)", "sync:lipsync-2-pro@1 (Sync LipSync 2 Pro)", "sync:react-1@1 (Sync React-1)", ], "Bria": [ "bria:60@1 (Bria Video Eraser)", ], "Creatify": [ "creatify:aurora@fast (Creatify Aurora Avatar Model API (720p))", "creatify:aurora@0 (Creatify Aurora Avatar Model API (720p))", ], "HeyGen": [ "heygen:avatar@4 (HeyGen Avatar IV)", "heygen:video-agent@0 (HeyGen Video Agent)", ], "Hunyuan": [ "runware:hunyuanvideo@1.5 (HunyuanVideo-1.5)", ], "Kandinsky": [ "runware:210@1 (Kandinsky 5.0 Lite)", ], "xAI": [ "xai:grok-imagine@video (Grok Imagine Video)", ], "VEED": [ "veed:fabric@1.0 (VEED Fabric 1.0)", ], "Pruna": [ "prunaai:p-video@0 (P-Video)", ], }; const MODEL_DIMENSIONS = { "klingai:1@2": {"width": 1280, "height": 720}, "klingai:1@1": {"width": 1280, "height": 720}, "klingai:2@2": {"width": 1920, "height": 1080}, "klingai:2@1": {"width": 1280, "height": 720}, "klingai:3@1": {"width": 1280, "height": 720}, "klingai:3@2": {"width": 1920, "height": 1080}, "klingai:4@3": {"width": 1280, "height": 720}, "klingai:5@1": {"width": 1280, "height": 720}, "klingai:5@2": {"width": 1920, "height": 1080}, "klingai:5@3": {"width": 1920, "height": 1080}, "klingai:6@1": {"width": 1920, "height": 1080}, "klingai:7@1": {"width": 0, "height": 0}, "klingai:kling@o1": {"width": 1440, "height": 1440}, "klingai:kling-video@2.6-pro": {"width": 1920, "height": 1080}, "klingai:kling-video@3-pro": {"width": 1920, "height": 1080}, "klingai:kling-video@3-standard": {"width": 1920, "height": 1080}, "klingai:kling-video@o3-pro": {"width": 1920, "height": 1080}, "klingai:kling-video@o3-standard": {"width": 1920, "height": 1080}, "klingai:avatar@2.0-standard": {"width": 0, "height": 0}, "klingai:avatar@2.0-pro": {"width": 0, "height": 0}, "google:2@0": {"width": 1280, "height": 720}, "google:3@0": {"width": 1280, "height": 720}, "google:3@1": {"width": 1280, "height": 720}, "google:3@2": {"width": 1280, "height": 720}, "google:3@3": {"width": 1280, "height": 720}, "google:veo@3.1-lite": {"width": 1280, "height": 720}, "bytedance:2@1": {"width": 864, "height": 480}, "bytedance:1@1": {"width": 864, "height": 480}, "bytedance:5@1": {"width": 1024, "height": 1024}, "bytedance:5@2": {"width": 1024, "height": 1024}, "bytedance:seedance@1.5-pro": {"width": 864, "height": 496}, "minimax:1@1": {"width": 1366, "height": 768}, "minimax:2@1": {"width": 1366, "height": 768}, "minimax:2@3": {"width": 1366, "height": 768}, "minimax:3@1": {"width": 1366, "height": 768}, "minimax:4@1": {"width": 1366, "height": 768}, "minimax:4@2": {"width": 1366, "height": 768}, "pixverse:1@1": {"width": 640, "height": 360}, "pixverse:1@2": {"width": 640, "height": 360}, "pixverse:1@3": {"width": 640, "height": 360}, "pixverse:1@5-fast": {"width": 640, "height": 360}, "pixverse:1@6": {"width": 640, "height": 360}, "pixverse:1@7": {"width": 640, "height": 360}, "pixverse:1@8": {"width": 640, "height": 360}, "pixverse:lipsync@1": {"width": 640, "height": 360}, "vidu:1@0": {"width": 1920, "height": 1080}, "vidu:1@1": {"width": 1920, "height": 1080}, "vidu:1@5": {"width": 1920, "height": 1080}, "vidu:2@0": {"width": 1920, "height": 1080}, "vidu:4@1": {"width": 1920, "height": 1080}, "vidu:4@2": {"width": 1920, "height": 1080}, "runware:200@1": {"width": 853, "height": 480}, "runware:200@2": {"width": 853, "height": 480}, "runware:200@6": {"width": 1280, "height": 720}, "runware:200@8": {"width": 1104, "height": 832}, "alibaba:wan@2.6": {"width": 1280, "height": 720}, "alibaba:wan@2.6-flash": {"width": 1280, "height": 720}, "alibaba:wan@2.7": {"width": 1280, "height": 720}, "openai:3@1": {"width": 1280, "height": 720}, "openai:3@0": {"width": 1280, "height": 720}, "lightricks:2@0": {"width": 1920, "height": 1080}, "lightricks:2@1": {"width": 1920, "height": 1080}, "lightricks:3@1": {"width": 0, "height": 0}, "lightricks:ltx@2": {"width": 1024, "height": 1024}, "lightricks:ltx@2.3": {"width": 1920, "height": 1080}, "lightricks:ltx@2.3-fast": {"width": 1920, "height": 1080}, "runware:190@1": {"width": 0, "height": 0}, "runway:2@1": {"width": 1280, "height": 720}, "runway:1@1": {"width": 1280, "height": 720}, "runway:1@2": {"width": 1280, "height": 720}, "lumaai:1@1": {"width": 1080, "height": 720}, "lumaai:2@1": {"width": 1080, "height": 720}, "lumaai:2@2": {"width": 1080, "height": 720}, "sync:lipsync-2@1": {"width": 0, "height": 0}, "sync:lipsync-2-pro@1": {"width": 0, "height": 0}, "sync:react-1@1": {"width": 0, "height": 0}, "bria:60@1": {"width": 1280, "height": 720}, "creatify:aurora@fast": {"width": 1280, "height": 720}, "creatify:aurora@0": {"width": 1280, "height": 720}, "runware:hunyuanvideo@1.5": {"width": 848, "height": 480}, "runware:210@1": {"width": 512, "height": 512}, "xai:grok-imagine@video": {"width": 480, "height": 480}, "veed:fabric@1.0": {"width": 1280, "height": 720}, "prunaai:p-video@0": {"width": 1280, "height": 720}, "heygen:avatar@4": {"width": 1280, "height": 720}, "heygen:video-agent@0": {"width": 1280, "height": 720}, }; const MODEL_RESOLUTIONS = { "klingai:1@2": "720p", "klingai:1@1": "720p", "klingai:2@2": "1080p", "klingai:2@1": "720p", "klingai:3@1": "720p", "klingai:3@2": "1080p", "klingai:4@3": "720p", "klingai:5@1": "720p", "klingai:5@2": "1080p", "klingai:5@3": "1080p", "klingai:6@1": "1080p", "klingai:7@1": null, // No resolution support "klingai:kling@o1": null, // No standard resolution "klingai:kling-video@2.6-pro": "1080p", "klingai:kling-video@3-pro": "1080p", "klingai:kling-video@3-standard": "1080p", "klingai:kling-video@o3-pro": "1080p", "klingai:kling-video@o3-standard": "1080p", "klingai:avatar@2.0-standard": null, // No resolution support "klingai:avatar@2.0-pro": null, // No resolution support "google:2@0": "720p", "google:3@0": "720p", "google:3@1": "720p", "google:3@2": "720p", "google:3@3": "720p", "google:veo@3.1-lite": "720p", "bytedance:2@1": "480p", "bytedance:1@1": "480p", "bytedance:5@1": null, // No resolution support "bytedance:5@2": null, // No resolution support "bytedance:seedance@1.5-pro": "480p", "minimax:1@1": "768p", "minimax:2@1": "768p", "minimax:2@3": "768p", "minimax:3@1": "768p", "minimax:4@1": "768p", "minimax:4@2": "768p", "pixverse:1@1": "360p", "pixverse:1@2": "360p", "pixverse:1@3": "360p", "pixverse:1@5-fast": "360p", "pixverse:1@6": "360p", "pixverse:1@7": "360p", "pixverse:1@8": "360p", "pixverse:lipsync@1": "360p", "vidu:1@0": "1080p", "vidu:1@1": "1080p", "vidu:1@5": "1080p", "vidu:2@0": "1080p", "vidu:4@1": "1080p", "vidu:4@2": "1080p", "runware:200@1": "480p", "runware:200@2": "480p", "runware:200@6": "720p", "runware:200@8": "720p", "alibaba:wan@2.6": "720p", "alibaba:wan@2.6-flash": "720p", "alibaba:wan@2.7": "720p", "openai:3@1": "720p", "openai:3@0": "720p", "lightricks:2@0": "1080p", "lightricks:2@1": "1080p", "lightricks:3@1": null, // No resolution support "lightricks:ltx@2": null, // No resolution support (fixed 1024x1024) "lightricks:ltx@2.3": "1080p", "lightricks:ltx@2.3-fast": "1080p", "runware:190@1": null, // No resolution support "runway:2@1": "720p", "runway:1@1": "720p", "runway:1@2": "720p", "lumaai:1@1": "720p", "lumaai:2@1": "720p", "lumaai:2@2": "720p", "sync:lipsync-2@1": "720p", "sync:lipsync-2-pro@1": "720p", "sync:react-1@1": "720p", "bria:60@1": "720p", "creatify:aurora@fast": "720p", "creatify:aurora@0": "720p", "runware:hunyuanvideo@1.5": "480p", "runware:210@1": null, // No resolution support (fixed 512x512) "xai:grok-imagine@video": "480p", "veed:fabric@1.0": "720p", "prunaai:p-video@0": "720p", "heygen:avatar@4": "720p", "heygen:video-agent@0": "720p", }; const DEFAULT_DIMENSIONS = {"width": 1024, "height": 576}; function setWidthHeightEnabled(enabled) { if (!widthWidget || !heightWidget) return; [widthWidget, heightWidget].forEach(widget => { widget.disabled = !enabled; if (widget.inputEl) { widget.inputEl.disabled = !enabled; widget.inputEl.style.opacity = enabled ? "1" : "0.5"; widget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; widget.inputEl.readOnly = !enabled; } }); } function updateDimensions() { if (!widthWidget || !heightWidget || !videoListWidget) return; const selectedModel = videoListWidget.value; if (!selectedModel) return; const useCustomDimensionsValue = useCustomDimensionsWidget ? useCustomDimensionsWidget.value : "Model Default"; // Handle "Disabled" option - disable widgets and set to 0 (but Python will use None in dict) if (useCustomDimensionsValue === "Disabled") { setWidthHeightEnabled(false); if (widthWidget.callback) widthWidget.callback(0, "customSetOperation"); widthWidget.value = 0; if (heightWidget.callback) heightWidget.callback(0, "customSetOperation"); heightWidget.value = 0; videoModelSearchNode.setDirtyCanvas(true); return; } // Handle "Model Default" option - disable widgets and use model defaults if (useCustomDimensionsValue === "Model Default") { setWidthHeightEnabled(false); } else if (useCustomDimensionsValue === "Custom") { // Handle "Custom" option - enable widgets setWidthHeightEnabled(true); } const modelCode = selectedModel.split(" (")[0]; const dims = MODEL_DIMENSIONS[modelCode] || DEFAULT_DIMENSIONS; // Only update dimensions if "Model Default" is selected (widgets are disabled but we show the values) if (useCustomDimensionsValue === "Model Default") { if (dims.width === 0 && dims.height === 0) { // Set to None when dimensions are 0,0 if (widthWidget.callback) widthWidget.callback(null, "customSetOperation"); if (heightWidget.callback) heightWidget.callback(null, "customSetOperation"); videoModelSearchNode.setDirtyCanvas(true); } else if (dims.width !== 0 && dims.height !== 0) { if (widthWidget.callback) widthWidget.callback(dims.width, "customSetOperation"); if (heightWidget.callback) heightWidget.callback(dims.height, "customSetOperation"); videoModelSearchNode.setDirtyCanvas(true); } } // For "Custom" mode, don't update - let user set their own values // For "Disabled" mode, already handled above (set to None and disabled) // Update resolution based on selected model if (resolutionWidget && useResolutionWidget) { const modelCode = selectedModel.split(" (")[0]; const modelResolution = MODEL_RESOLUTIONS[modelCode]; // If model supports resolution if (modelResolution !== null && modelResolution !== undefined) { // Enable useResolution checkbox if (useResolutionWidget.inputEl) { useResolutionWidget.inputEl.disabled = false; useResolutionWidget.inputEl.style.opacity = "1"; } useResolutionWidget.disabled = false; // Only update resolution value if useResolution is enabled if (useResolutionWidget.value === true) { // Set resolution value to model's default if (resolutionWidget.callback) resolutionWidget.callback(modelResolution, "customSetOperation"); resolutionWidget.value = modelResolution; } } else { // Model doesn't support resolution, disable useResolution checkbox and resolution dropdown if (useResolutionWidget.callback) useResolutionWidget.callback(false, "customSetOperation"); useResolutionWidget.value = false; // Disable useResolution checkbox if (useResolutionWidget.inputEl) { useResolutionWidget.inputEl.disabled = true; useResolutionWidget.inputEl.style.opacity = "0.5"; } useResolutionWidget.disabled = true; // Disable resolution dropdown if (resolutionWidget.inputEl) { resolutionWidget.inputEl.disabled = true; resolutionWidget.inputEl.style.opacity = "0.5"; resolutionWidget.inputEl.style.cursor = "not-allowed"; } resolutionWidget.disabled = true; } videoModelSearchNode.setDirtyCanvas(true); } } function filterModelList() { const selectedArch = modelArchWidget.value; let filteredModels = []; if (selectedArch === "All") { Object.values(VIDEO_MODELS).forEach(models => filteredModels.push(...models)); } else if (VIDEO_MODELS[selectedArch]) { filteredModels = VIDEO_MODELS[selectedArch]; } if (filteredModels.length > 0) { const currentValue = videoListWidget.value; videoListWidget.options.values = filteredModels; if (!filteredModels.includes(currentValue)) { videoListWidget.value = filteredModels[0]; } updateDimensions(); videoModelSearchNode.setDirtyCanvas(true); } } appendWidgetCB(modelArchWidget, filterModelList); if (videoListWidget) { appendWidgetCB(videoListWidget, updateDimensions); } if (useCustomDimensionsWidget) { appendWidgetCB(useCustomDimensionsWidget, () => { updateDimensions(); }); } // Handle useResolution toggle if (useResolutionWidget && resolutionWidget) { function toggleResolutionState() { // Check if current model supports resolution const selectedModel = videoListWidget ? videoListWidget.value : null; if (!selectedModel) return; const modelCode = selectedModel.split(" (")[0]; const modelResolution = MODEL_RESOLUTIONS[modelCode]; // Only enable resolution if model supports it and useResolution is enabled const enabled = useResolutionWidget.value === true && modelResolution !== null && modelResolution !== undefined; if (resolutionWidget.inputEl) { resolutionWidget.inputEl.disabled = !enabled; resolutionWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; resolutionWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; } resolutionWidget.disabled = !enabled; // Fallback: try to find input via DOM if inputEl is not available if (!resolutionWidget.inputEl) { const nodeElement = videoModelSearchNode.htmlElements?.widgetsContainer || videoModelSearchNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`select[name="resolution"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.pointerEvents = enabled ? "auto" : "none"; } } } videoModelSearchNode.setDirtyCanvas(true); } appendWidgetCB(useResolutionWidget, () => { setTimeout(toggleResolutionState, 50); }); // Also update when model changes if (videoListWidget) { appendWidgetCB(videoListWidget, () => { setTimeout(toggleResolutionState, 50); }); } setTimeout(toggleResolutionState, 100); } filterModelList(); updateDimensions(); } function textModelSearchFilterHandler(textModelSearchNode) { const modelProviderWidget = textModelSearchNode.widgets.find(w => w.name === "Model Provider"); const textListWidget = textModelSearchNode.widgets.find(w => w.name === "TextList"); if (!modelProviderWidget || !textListWidget) return; const TEXT_MODELS = { "MiniMax": [ "minimax:m2.7@0 (MiniMax-M2.7)", "minimax:m2.7@highspeed (MiniMax-M2.7 Highspeed)", "minimax:m2.5@0 (MiniMax-M2.5)", ], "OpenAI": [ "openai:gpt@5.4 (GPT-5.4)", "openai:gpt@5.4-pro (GPT-5.4 Pro)", "openai:gpt@5.4-mini (GPT-5.4 Mini)", "openai:gpt@5.4-nano (GPT-5.4 Nano)", ], "Google": [ "google:gemini@3-flash (Gemini 3 Flash)", ], }; function filterModelList() { const selectedProvider = modelProviderWidget.value; let filteredModels = []; if (selectedProvider === "All") { Object.values(TEXT_MODELS).forEach(models => filteredModels.push(...models)); } else if (TEXT_MODELS[selectedProvider]) { filteredModels = TEXT_MODELS[selectedProvider]; } if (filteredModels.length > 0) { const currentValue = textListWidget.value; textListWidget.options.values = filteredModels; if (!filteredModels.includes(currentValue)) { textListWidget.value = filteredModels[0]; } textModelSearchNode.setDirtyCanvas(true); } } appendWidgetCB(modelProviderWidget, filterModelList); filterModelList(); } function audioModelSearchFilterHandler(audioModelSearchNode) { const modelProviderWidget = audioModelSearchNode.widgets.find(w => w.name === "Model Provider"); const audioListWidget = audioModelSearchNode.widgets.find(w => w.name === "AudioList"); if (!modelProviderWidget || !audioListWidget) return; const AUDIO_MODELS = { "ElevenLabs": [ "elevenlabs:1@1 (ElevenLabs Multilingual v2)", "elevenlabs:2@1 (ElevenLabs Multilingual v2 Turbo)", "elevenlabs:3@1 (ElevenLabs Monolingual v1)", ], "KlingAI": [ "klingai:8@1 (KlingAI Audio)", ], "Mirelo": [ "mirelo:1@1 (Mirelo SFX 1.5)", ], "Ace": [ "runware:ace-step@0 (ACE Step v1 3.5B)", "runware:ace-step@v1.5-base (ACE-Step v1.5 Base)", "runware:ace-step@v1.5-turbo (ACE-Step v1.5 Turbo)", ], "Alibaba": [ "alibaba:qwen@3-tts-1.7b-voicedesign (Qwen3 TTS 1.7B Voice Design)", "alibaba:qwen@3-tts-1.7b-customvoice (Qwen3 TTS 1.7B Custom Voice)", "alibaba:qwen@3-tts-1.7b-base (Qwen3 TTS 1.7B Base)", ], "Dia": [ "runware:dia@v1.0 (Dia 1.6B)", ], "xAI": [ "xai:voice@tts (xAI TTS)", ], "MiniMax": [ "minimax:speech@2.8 (MiniMax Speech 2.8)", ], "Inworld": [ "inworld:tts@1.5-mini (Inworld TTS-1.5 Mini)", "inworld:tts@1.5-max (Inworld TTS-1.5 Max)", ], }; function filterModelList() { const selectedProvider = modelProviderWidget.value; let filteredModels = []; if (selectedProvider === "All") { Object.values(AUDIO_MODELS).forEach(models => filteredModels.push(...models)); } else if (AUDIO_MODELS[selectedProvider]) { filteredModels = AUDIO_MODELS[selectedProvider]; } if (filteredModels.length > 0) { const currentValue = audioListWidget.value; audioListWidget.options.values = filteredModels; if (!filteredModels.includes(currentValue)) { audioListWidget.value = filteredModels[0]; } audioModelSearchNode.setDirtyCanvas(true); } } appendWidgetCB(modelProviderWidget, filterModelList); filterModelList(); } function vectorizeModelSearchFilterHandler(vectorizeNode) { const modelArchWidget = vectorizeNode.widgets.find(w => w.name === "Model Architecture"); const vectorListWidget = vectorizeNode.widgets.find(w => w.name === "Vector Model List"); if (!modelArchWidget || !vectorListWidget) return; const VECTORIZE_MODELS = { "Recraft": [ "recraft:1@1 (Recraft 1)", "recraft:v4-pro@vector (Recraft V4 Pro Vector)", "recraft:v4@vector (Recraft V4 Vector)", ], "Picsart": [ "picsart:1@1 (Picsart 1)", ], }; function filterModelList() { const selectedArch = modelArchWidget.value; let filteredModels = []; if (selectedArch === "All") { Object.values(VECTORIZE_MODELS).forEach(models => filteredModels.push(...models)); } else if (VECTORIZE_MODELS[selectedArch]) { filteredModels = VECTORIZE_MODELS[selectedArch]; } if (filteredModels.length > 0) { const currentValue = vectorListWidget.value; vectorListWidget.options.values = filteredModels; if (!filteredModels.includes(currentValue)) { vectorListWidget.value = filteredModels[0]; } vectorizeNode.setDirtyCanvas(true); } } appendWidgetCB(modelArchWidget, filterModelList); filterModelList(); } function vectorizeToggleHandler(vectorizeNode) { const usePositivePromptWidget = vectorizeNode.widgets.find(w => w.name === "Use positivePrompt"); const positivePromptWidget = vectorizeNode.widgets.find(w => w.name === "positivePrompt"); const dimensionsWidget = vectorizeNode.widgets.find(w => w.name === "dimensions"); const widthWidget = vectorizeNode.widgets.find(w => w.name === "width"); const heightWidget = vectorizeNode.widgets.find(w => w.name === "height"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function applyState() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; } } applyState(); appendWidgetCB(useWidget, applyState); } if (usePositivePromptWidget && positivePromptWidget) { toggleWidgetState(usePositivePromptWidget, positivePromptWidget, "positivePrompt"); } // Disable width/height when dimensions is "None" (same as image inference) if (dimensionsWidget && widthWidget && heightWidget) { function toggleDimensionsState() { const dimensionsValue = dimensionsWidget.value; const enabled = dimensionsValue !== "None"; if (widthWidget.inputEl) { widthWidget.inputEl.disabled = !enabled; widthWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; widthWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; widthWidget.inputEl.readOnly = !enabled; } widthWidget.disabled = !enabled; if (heightWidget.inputEl) { heightWidget.inputEl.disabled = !enabled; heightWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; heightWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; heightWidget.inputEl.readOnly = !enabled; } heightWidget.disabled = !enabled; vectorizeNode.setDirtyCanvas(true); } appendWidgetCB(dimensionsWidget, () => { setTimeout(toggleDimensionsState, 50); }); setTimeout(toggleDimensionsState, 100); } } function klingProviderSettingsToggleHandler(klingNode) { // Find all "use" parameter widgets for KlingAI Provider Settings (EXACT same pattern as imageInferenceToggleHandler) const useCameraControlWidget = klingNode.widgets.find(w => w.name === "useCameraControl"); const cameraControlWidget = klingNode.widgets.find(w => w.name === "cameraControl"); const useSoundVolumeWidget = klingNode.widgets.find(w => w.name === "useSoundVolume"); const soundVolumeWidget = klingNode.widgets.find(w => w.name === "soundVolume"); const useOriginalAudioVolumeWidget = klingNode.widgets.find(w => w.name === "useOriginalAudioVolume"); const originalAudioVolumeWidget = klingNode.widgets.find(w => w.name === "originalAudioVolume"); const useSoundEffectPromptWidget = klingNode.widgets.find(w => w.name === "useSoundEffectPrompt"); const soundEffectPromptWidget = klingNode.widgets.find(w => w.name === "soundEffectPrompt"); const useBgmPromptWidget = klingNode.widgets.find(w => w.name === "useBgmPrompt"); const bgmPromptWidget = klingNode.widgets.find(w => w.name === "bgmPrompt"); const useAsmrModeWidget = klingNode.widgets.find(w => w.name === "useAsmrMode"); const asmrModeWidget = klingNode.widgets.find(w => w.name === "asmrMode"); const useKeepOriginalSoundWidget = klingNode.widgets.find(w => w.name === "useKeepOriginalSound"); const keepOriginalSoundWidget = klingNode.widgets.find(w => w.name === "keepOriginalSound"); const useSoundWidget = klingNode.widgets.find(w => w.name === "useSound"); const soundWidget = klingNode.widgets.find(w => w.name === "sound"); const useCharacterOrientationWidget = klingNode.widgets.find(w => w.name === "useCharacterOrientation"); const characterOrientationWidget = klingNode.widgets.find(w => w.name === "characterOrientation"); const useMultipromptWidget = klingNode.widgets.find(w => w.name === "useMultiprompt"); // Helper function to toggle widget enabled state (EXACT same pattern as imageInferenceToggleHandler) // Callers guard with if (useX && xWidget) before invoking function toggleWidgetState(useWidget, paramWidget, paramName) { function toggleEnabled() { const enabled = useWidget.value === true; // Disable/enable widgets using inputEl if available (exact same pattern) if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Also set widget property paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = klingNode.htmlElements?.widgetsContainer || klingNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } klingNode.setDirtyCanvas(true); } // Set up callback (exact same pattern as imageInferenceToggleHandler) appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state (exact same pattern) setTimeout(toggleEnabled, 100); } // Set up all toggle handlers (exact same pattern as imageInferenceToggleHandler) if (useCameraControlWidget && cameraControlWidget) { toggleWidgetState(useCameraControlWidget, cameraControlWidget, "cameraControl"); } if (useSoundVolumeWidget && soundVolumeWidget) { toggleWidgetState(useSoundVolumeWidget, soundVolumeWidget, "soundVolume"); } if (useOriginalAudioVolumeWidget && originalAudioVolumeWidget) { toggleWidgetState(useOriginalAudioVolumeWidget, originalAudioVolumeWidget, "originalAudioVolume"); } if (useSoundEffectPromptWidget && soundEffectPromptWidget) { toggleWidgetState(useSoundEffectPromptWidget, soundEffectPromptWidget, "soundEffectPrompt"); } if (useBgmPromptWidget && bgmPromptWidget) { toggleWidgetState(useBgmPromptWidget, bgmPromptWidget, "bgmPrompt"); } if (useAsmrModeWidget && asmrModeWidget) { toggleWidgetState(useAsmrModeWidget, asmrModeWidget, "asmrMode"); } if (useKeepOriginalSoundWidget && keepOriginalSoundWidget) { toggleWidgetState(useKeepOriginalSoundWidget, keepOriginalSoundWidget, "keepOriginalSound"); } if (useSoundWidget && soundWidget) { toggleWidgetState(useSoundWidget, soundWidget, "sound"); } if (useCharacterOrientationWidget && characterOrientationWidget) { toggleWidgetState(useCharacterOrientationWidget, characterOrientationWidget, "characterOrientation"); } // Toggle MultiPrompt Segment input slots when useMultiprompt changes if (useMultipromptWidget) { function toggleMultipromptInputs() { const enabled = useMultipromptWidget.value === true; klingNode.inputs?.forEach(inp => { if (inp?.name?.startsWith("MultiPrompt Segment")) { inp.disabled = !enabled; if (inp.domElement) { inp.domElement.style.opacity = enabled ? "1" : "0.4"; inp.domElement.style.pointerEvents = enabled ? "auto" : "none"; } } }); klingNode.setDirtyCanvas(true); } appendWidgetCB(useMultipromptWidget, () => setTimeout(toggleMultipromptInputs, 50)); setTimeout(toggleMultipromptInputs, 100); } } function alibabaProviderSettingsToggleHandler(alibabaNode) { // Find all "use" parameter widgets for Alibaba Provider Settings const usePromptEnhancerWidget = alibabaNode.widgets.find(w => w.name === "usePromptEnhancer"); const promptEnhancerWidget = alibabaNode.widgets.find(w => w.name === "promptEnhancer"); const usePromptExtendWidget = alibabaNode.widgets.find(w => w.name === "usePromptExtend"); const promptExtendWidget = alibabaNode.widgets.find(w => w.name === "promptExtend"); const useAudioWidget = alibabaNode.widgets.find(w => w.name === "useAudio"); const audioWidget = alibabaNode.widgets.find(w => w.name === "audio"); const useShotTypeWidget = alibabaNode.widgets.find(w => w.name === "useShotType"); const shotTypeWidget = alibabaNode.widgets.find(w => w.name === "shotType"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = alibabaNode.htmlElements?.widgetsContainer || alibabaNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } alibabaNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Special handler for shotType - depends on both usePromptExtend AND promptExtend being true function toggleShotTypeEnabled() { if (!useShotTypeWidget || !shotTypeWidget || !usePromptExtendWidget || !promptExtendWidget) return; const usePromptExtendEnabled = usePromptExtendWidget.value === true; const promptExtendValue = promptExtendWidget.value === true; const useShotTypeEnabled = useShotTypeWidget.value === true; // shotType is enabled only if: useShotType is enabled AND usePromptExtend is enabled AND promptExtend is true const enabled = useShotTypeEnabled && usePromptExtendEnabled && promptExtendValue; if (shotTypeWidget.inputEl) { shotTypeWidget.inputEl.disabled = !enabled; shotTypeWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; shotTypeWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; shotTypeWidget.inputEl.readOnly = !enabled; } shotTypeWidget.disabled = !enabled; if (!shotTypeWidget.inputEl) { const nodeElement = alibabaNode.htmlElements?.widgetsContainer || alibabaNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="shotType"], select[name="shotType"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } alibabaNode.setDirtyCanvas(true); } // Set up toggle handlers if (usePromptEnhancerWidget && promptEnhancerWidget) { toggleWidgetState(usePromptEnhancerWidget, promptEnhancerWidget, "promptEnhancer"); } if (usePromptExtendWidget && promptExtendWidget) { toggleWidgetState(usePromptExtendWidget, promptExtendWidget, "promptExtend"); // Also listen to promptExtend value changes to update shotType appendWidgetCB(promptExtendWidget, () => { setTimeout(toggleShotTypeEnabled, 50); }); } if (useAudioWidget && audioWidget) { toggleWidgetState(useAudioWidget, audioWidget, "audio"); } if (useShotTypeWidget && shotTypeWidget) { // Listen to useShotType changes appendWidgetCB(useShotTypeWidget, () => { setTimeout(toggleShotTypeEnabled, 50); }); // Also listen to usePromptExtend changes if (usePromptExtendWidget) { appendWidgetCB(usePromptExtendWidget, () => { setTimeout(toggleShotTypeEnabled, 50); }); } // Initial state setTimeout(toggleShotTypeEnabled, 100); } } function mireloProviderSettingsToggleHandler(mireloNode) { // Find all "use" parameter widgets for Mirelo Provider Settings const useStartOffsetWidget = mireloNode.widgets.find(w => w.name === "useStartOffset"); const startOffsetWidget = mireloNode.widgets.find(w => w.name === "startOffset"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = mireloNode.htmlElements?.widgetsContainer || mireloNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } mireloNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up toggle handler if (useStartOffsetWidget && startOffsetWidget) { toggleWidgetState(useStartOffsetWidget, startOffsetWidget, "startOffset"); } } function lumaProviderSettingsToggleHandler(lumaNode) { // Find all "use" parameter widgets for Luma Provider Settings const useLoopWidget = lumaNode.widgets.find(w => w.name === "useLoop"); const loopWidget = lumaNode.widgets.find(w => w.name === "loop"); const useConcept1Widget = lumaNode.widgets.find(w => w.name === "useConcept1"); const concept1Widget = lumaNode.widgets.find(w => w.name === "concept1"); const useConcept2Widget = lumaNode.widgets.find(w => w.name === "useConcept2"); const concept2Widget = lumaNode.widgets.find(w => w.name === "concept2"); const useConcept3Widget = lumaNode.widgets.find(w => w.name === "useConcept3"); const concept3Widget = lumaNode.widgets.find(w => w.name === "concept3"); const useConcept4Widget = lumaNode.widgets.find(w => w.name === "useConcept4"); const concept4Widget = lumaNode.widgets.find(w => w.name === "concept4"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = lumaNode.htmlElements?.widgetsContainer || lumaNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } lumaNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useLoopWidget && loopWidget) { toggleWidgetState(useLoopWidget, loopWidget, "loop"); } if (useConcept1Widget && concept1Widget) { toggleWidgetState(useConcept1Widget, concept1Widget, "concept1"); } if (useConcept2Widget && concept2Widget) { toggleWidgetState(useConcept2Widget, concept2Widget, "concept2"); } if (useConcept3Widget && concept3Widget) { toggleWidgetState(useConcept3Widget, concept3Widget, "concept3"); } if (useConcept4Widget && concept4Widget) { toggleWidgetState(useConcept4Widget, concept4Widget, "concept4"); } } function briaProviderSettingsToggleHandler(briaNode) { // Find all "use" parameter widgets for Bria Provider Settings const useMediumWidget = briaNode.widgets.find(w => w.name === "useMedium"); const mediumWidget = briaNode.widgets.find(w => w.name === "medium"); const usePromptEnhancementWidget = briaNode.widgets.find(w => w.name === "usePromptEnhancement"); const promptEnhancementWidget = briaNode.widgets.find(w => w.name === "promptEnhancement"); const useEnhanceImageWidget = briaNode.widgets.find(w => w.name === "useEnhanceImage"); const enhanceImageWidget = briaNode.widgets.find(w => w.name === "enhanceImage"); const usePromptContentModerationWidget = briaNode.widgets.find(w => w.name === "usePromptContentModeration"); const promptContentModerationWidget = briaNode.widgets.find(w => w.name === "promptContentModeration"); const useContentModerationWidget = briaNode.widgets.find(w => w.name === "useContentModeration"); const contentModerationWidget = briaNode.widgets.find(w => w.name === "contentModeration"); const useIpSignalWidget = briaNode.widgets.find(w => w.name === "useIpSignal"); const ipSignalWidget = briaNode.widgets.find(w => w.name === "ipSignal"); const usePreserveAlphaWidget = briaNode.widgets.find(w => w.name === "usePreserveAlpha"); const preserveAlphaWidget = briaNode.widgets.find(w => w.name === "preserveAlpha"); const useModeWidget = briaNode.widgets.find(w => w.name === "useMode"); const modeWidget = briaNode.widgets.find(w => w.name === "mode"); const useEnhanceReferenceImagesWidget = briaNode.widgets.find(w => w.name === "useEnhanceReferenceImages"); const enhanceReferenceImagesWidget = briaNode.widgets.find(w => w.name === "enhanceReferenceImages"); const useRefinePromptWidget = briaNode.widgets.find(w => w.name === "useRefinePrompt"); const refinePromptWidget = briaNode.widgets.find(w => w.name === "refinePrompt"); const useOriginalQualityWidget = briaNode.widgets.find(w => w.name === "useOriginalQuality"); const originalQualityWidget = briaNode.widgets.find(w => w.name === "originalQuality"); const useForceBackgroundDetectionWidget = briaNode.widgets.find(w => w.name === "useForceBackgroundDetection"); const forceBackgroundDetectionWidget = briaNode.widgets.find(w => w.name === "forceBackgroundDetection"); const useAutoTrimWidget = briaNode.widgets.find(w => w.name === "useAutoTrim"); const autoTrimWidget = briaNode.widgets.find(w => w.name === "autoTrim"); const usePreserveAudioWidget = briaNode.widgets.find(w => w.name === "usePreserveAudio"); const preserveAudioWidget = briaNode.widgets.find(w => w.name === "preserveAudio"); const useSeasonWidget = briaNode.widgets.find(w => w.name === "useSeason"); const seasonWidget = briaNode.widgets.find(w => w.name === "season"); const useEditWidget = briaNode.widgets.find(w => w.name === "useEdit"); const editWidget = briaNode.widgets.find(w => w.name === "edit"); const useColorWidget = briaNode.widgets.find(w => w.name === "useColor"); const colorWidget = briaNode.widgets.find(w => w.name === "color"); const useLightDirectionWidget = briaNode.widgets.find(w => w.name === "useLightDirection"); const lightDirectionWidget = briaNode.widgets.find(w => w.name === "lightDirection"); const useLightTypeWidget = briaNode.widgets.find(w => w.name === "useLightType"); const lightTypeWidget = briaNode.widgets.find(w => w.name === "lightType"); // Helper function to toggle widget enabled state (exact same pattern) function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; // Disable/enable widgets using inputEl if available (exact same pattern) if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Handle dropdown widgets (for medium and mode) if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } // Also set widget property paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = briaNode.htmlElements?.widgetsContainer || briaNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } briaNode.setDirtyCanvas(true); } // Set up callback (exact same pattern) appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up all toggle handlers if (useMediumWidget && mediumWidget) { toggleWidgetState(useMediumWidget, mediumWidget, "medium"); } if (usePromptEnhancementWidget && promptEnhancementWidget) { toggleWidgetState(usePromptEnhancementWidget, promptEnhancementWidget, "promptEnhancement"); } if (useEnhanceImageWidget && enhanceImageWidget) { toggleWidgetState(useEnhanceImageWidget, enhanceImageWidget, "enhanceImage"); } if (usePromptContentModerationWidget && promptContentModerationWidget) { toggleWidgetState(usePromptContentModerationWidget, promptContentModerationWidget, "promptContentModeration"); } if (useContentModerationWidget && contentModerationWidget) { toggleWidgetState(useContentModerationWidget, contentModerationWidget, "contentModeration"); } if (useIpSignalWidget && ipSignalWidget) { toggleWidgetState(useIpSignalWidget, ipSignalWidget, "ipSignal"); } if (usePreserveAlphaWidget && preserveAlphaWidget) { toggleWidgetState(usePreserveAlphaWidget, preserveAlphaWidget, "preserveAlpha"); } if (useModeWidget && modeWidget) { toggleWidgetState(useModeWidget, modeWidget, "mode"); } if (useEnhanceReferenceImagesWidget && enhanceReferenceImagesWidget) { toggleWidgetState(useEnhanceReferenceImagesWidget, enhanceReferenceImagesWidget, "enhanceReferenceImages"); } if (useRefinePromptWidget && refinePromptWidget) { toggleWidgetState(useRefinePromptWidget, refinePromptWidget, "refinePrompt"); } if (useOriginalQualityWidget && originalQualityWidget) { toggleWidgetState(useOriginalQualityWidget, originalQualityWidget, "originalQuality"); } if (useForceBackgroundDetectionWidget && forceBackgroundDetectionWidget) { toggleWidgetState(useForceBackgroundDetectionWidget, forceBackgroundDetectionWidget, "forceBackgroundDetection"); } if (useAutoTrimWidget && autoTrimWidget) { toggleWidgetState(useAutoTrimWidget, autoTrimWidget, "autoTrim"); } if (usePreserveAudioWidget && preserveAudioWidget) { toggleWidgetState(usePreserveAudioWidget, preserveAudioWidget, "preserveAudio"); } if (useSeasonWidget && seasonWidget) { toggleWidgetState(useSeasonWidget, seasonWidget, "season"); } if (useEditWidget && editWidget) { toggleWidgetState(useEditWidget, editWidget, "edit"); } if (useColorWidget && colorWidget) { toggleWidgetState(useColorWidget, colorWidget, "color"); } if (useLightDirectionWidget && lightDirectionWidget) { toggleWidgetState(useLightDirectionWidget, lightDirectionWidget, "lightDirection"); } if (useLightTypeWidget && lightTypeWidget) { toggleWidgetState(useLightTypeWidget, lightTypeWidget, "lightType"); } } function audioInputToggleHandler(audioInputNode) { // Find "use" parameter widget and "id" widget for Audio Input const useIdWidget = audioInputNode.widgets.find(w => w.name === "useId"); const idWidget = audioInputNode.widgets.find(w => w.name === "id"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; // Disable/enable widgets using inputEl if available if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Also set widget property paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = audioInputNode.htmlElements?.widgetsContainer || audioInputNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } audioInputNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up toggle handler for "useId" parameter if (useIdWidget && idWidget) { toggleWidgetState(useIdWidget, idWidget, "id"); } } function speechInputToggleHandler(speechInputNode) { // Find "use" parameter widget and "id" widget for Speech Input const useIdWidget = speechInputNode.widgets.find(w => w.name === "useId"); const idWidget = speechInputNode.widgets.find(w => w.name === "id"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; // Disable/enable widgets using inputEl if available if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Also set widget property paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl) { const nodeElement = speechInputNode.htmlElements?.widgetsContainer || speechInputNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } speechInputNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up toggle handler for "useId" parameter if (useIdWidget && idWidget) { toggleWidgetState(useIdWidget, idWidget, "id"); } } function briaProviderMaskToggleHandler(maskNode) { // Helper function to toggle widget enabled state for multiple widgets function toggleWidgetState(useWidget, paramWidgets, paramNames) { if (!useWidget || !paramWidgets || paramWidgets.length === 0) return; function toggleEnabled() { const enabled = useWidget.value === true; paramWidgets.forEach((paramWidget, idx) => { if (!paramWidget) return; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Handle dropdown widgets (for Type fields) if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl && paramNames[idx]) { const nodeElement = maskNode.htmlElements?.widgetsContainer || maskNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramNames[idx]}"], textarea[name="${paramNames[idx]}"], select[name="${paramNames[idx]}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } }); maskNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up toggle handlers for foreground, prompt, frameIndex const useForegroundWidget = maskNode.widgets.find(w => w.name === "useForeground"); const foregroundWidget = maskNode.widgets.find(w => w.name === "foreground"); if (useForegroundWidget && foregroundWidget) { toggleWidgetState(useForegroundWidget, [foregroundWidget], ["foreground"]); } const usePromptWidget = maskNode.widgets.find(w => w.name === "usePrompt"); const promptWidget = maskNode.widgets.find(w => w.name === "prompt"); if (usePromptWidget && promptWidget) { toggleWidgetState(usePromptWidget, [promptWidget], ["prompt"]); } const useFrameIndexWidget = maskNode.widgets.find(w => w.name === "useFrameIndex"); const frameIndexWidget = maskNode.widgets.find(w => w.name === "frameIndex"); if (useFrameIndexWidget && frameIndexWidget) { toggleWidgetState(useFrameIndexWidget, [frameIndexWidget], ["frameIndex"]); } // Set up toggle handlers for all 6 key points for (let i = 1; i <= 6; i++) { const useWidget = maskNode.widgets.find(w => w.name === `use_${i}`); const xWidget = maskNode.widgets.find(w => w.name === `X${i}`); const yWidget = maskNode.widgets.find(w => w.name === `Y${i}`); const typeWidget = maskNode.widgets.find(w => w.name === `Type${i}`); if (useWidget && xWidget && yWidget && typeWidget) { toggleWidgetState(useWidget, [xWidget, yWidget, typeWidget], [`X${i}`, `Y${i}`, `Type${i}`]); } } } function wanAnimateAdvancedFeatureSettingsToggleHandler(wanAnimateNode) { // Find widgets const useModeWidget = wanAnimateNode.widgets.find(w => w.name === "useMode"); const modeWidget = wanAnimateNode.widgets.find(w => w.name === "mode"); const useRetargetPoseWidget = wanAnimateNode.widgets.find(w => w.name === "useRetargetPose"); const retargetPoseWidget = wanAnimateNode.widgets.find(w => w.name === "retargetPose"); const usePrevSegCondFramesWidget = wanAnimateNode.widgets.find(w => w.name === "usePrevSegCondFrames"); const prevSegCondFramesWidget = wanAnimateNode.widgets.find(w => w.name === "prevSegCondFrames"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } // Handle dropdown widgets (for mode field) if (paramWidget.options && paramWidget.options.element) { paramWidget.options.element.disabled = !enabled; paramWidget.options.element.style.opacity = enabled ? "1" : "0.5"; paramWidget.options.element.style.pointerEvents = enabled ? "auto" : "none"; } paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl && paramName) { const nodeElement = wanAnimateNode.htmlElements?.widgetsContainer || wanAnimateNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } wanAnimateNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up toggle handler for mode if (useModeWidget && modeWidget) { toggleWidgetState(useModeWidget, modeWidget, "mode"); } // Set up toggle handler for retargetPose (with mode dependency) if (useRetargetPoseWidget && retargetPoseWidget) { function toggleRetargetPoseEnabled() { const useRetargetPoseEnabled = useRetargetPoseWidget.value === true; const modeValue = modeWidget ? modeWidget.value : "animate"; // retargetPose is only supported for animate mode const enabled = useRetargetPoseEnabled && modeValue === "animate"; if (retargetPoseWidget.inputEl) { retargetPoseWidget.inputEl.disabled = !enabled; retargetPoseWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; retargetPoseWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; retargetPoseWidget.inputEl.readOnly = !enabled; } retargetPoseWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if (!retargetPoseWidget.inputEl) { const nodeElement = wanAnimateNode.htmlElements?.widgetsContainer || wanAnimateNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="retargetPose"], textarea[name="retargetPose"], select[name="retargetPose"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } wanAnimateNode.setDirtyCanvas(true); } // Set up callback for useRetargetPose toggle appendWidgetCB(useRetargetPoseWidget, () => { setTimeout(toggleRetargetPoseEnabled, 50); }); // Set up callback for mode change (to disable retargetPose when mode is "replace") if (modeWidget) { appendWidgetCB(modeWidget, () => { setTimeout(toggleRetargetPoseEnabled, 50); }); } // Initial call to set initial state setTimeout(toggleRetargetPoseEnabled, 100); } // Set up toggle handler for prevSegCondFrames if (usePrevSegCondFramesWidget && prevSegCondFramesWidget) { toggleWidgetState(usePrevSegCondFramesWidget, prevSegCondFramesWidget, "prevSegCondFrames"); } } function videoAdvancedFeatureInputsToggleHandler(advancedFeatureNode) { // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl && paramName) { const nodeElement = advancedFeatureNode.htmlElements?.widgetsContainer || advancedFeatureNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } advancedFeatureNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up toggle handlers for each parameter const useVideoCFGScaleWidget = advancedFeatureNode.widgets.find(w => w.name === "useVideoCFGScale"); const videoCFGScaleWidget = advancedFeatureNode.widgets.find(w => w.name === "videoCFGScale"); if (useVideoCFGScaleWidget && videoCFGScaleWidget) { toggleWidgetState(useVideoCFGScaleWidget, videoCFGScaleWidget, "videoCFGScale"); } const useAudioCFGScaleWidget = advancedFeatureNode.widgets.find(w => w.name === "useAudioCFGScale"); const audioCFGScaleWidget = advancedFeatureNode.widgets.find(w => w.name === "audioCFGScale"); if (useAudioCFGScaleWidget && audioCFGScaleWidget) { toggleWidgetState(useAudioCFGScaleWidget, audioCFGScaleWidget, "audioCFGScale"); } const useVideoNegativePromptWidget = advancedFeatureNode.widgets.find(w => w.name === "useVideoNegativePrompt"); const videoNegativePromptWidget = advancedFeatureNode.widgets.find(w => w.name === "videoNegativePrompt"); if (useVideoNegativePromptWidget && videoNegativePromptWidget) { toggleWidgetState(useVideoNegativePromptWidget, videoNegativePromptWidget, "videoNegativePrompt"); } const useAudioNegativePromptWidget = advancedFeatureNode.widgets.find(w => w.name === "useAudioNegativePrompt"); const audioNegativePromptWidget = advancedFeatureNode.widgets.find(w => w.name === "audioNegativePrompt"); if (useAudioNegativePromptWidget && audioNegativePromptWidget) { toggleWidgetState(useAudioNegativePromptWidget, audioNegativePromptWidget, "audioNegativePrompt"); } const useSlgLayerWidget = advancedFeatureNode.widgets.find(w => w.name === "useSlgLayer"); const slgLayerWidget = advancedFeatureNode.widgets.find(w => w.name === "slgLayer"); if (useSlgLayerWidget && slgLayerWidget) { toggleWidgetState(useSlgLayerWidget, slgLayerWidget, "slgLayer"); } } function imageInferenceAdvancedFeaturesToggleHandler(advancedFeaturesNode) { function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl && paramName) { const nodeElement = advancedFeaturesNode.htmlElements?.widgetsContainer || advancedFeaturesNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; } } } advancedFeaturesNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => setTimeout(toggleEnabled, 50)); setTimeout(toggleEnabled, 100); } const useLayerDiffuseWidget = advancedFeaturesNode.widgets.find(w => w.name === "useLayerDiffuse"); const layerDiffuseWidget = advancedFeaturesNode.widgets.find(w => w.name === "layerDiffuse"); if (useLayerDiffuseWidget && layerDiffuseWidget) toggleWidgetState(useLayerDiffuseWidget, layerDiffuseWidget, "layerDiffuse"); const useHiresFixWidget = advancedFeaturesNode.widgets.find(w => w.name === "useHiresFix"); const hiresFixWidget = advancedFeaturesNode.widgets.find(w => w.name === "hiresFix"); if (useHiresFixWidget && hiresFixWidget) toggleWidgetState(useHiresFixWidget, hiresFixWidget, "hiresFix"); } function watermarkAdvancedFeatureToggleHandler(watermarkNode) { if (!watermarkNode?.widgets) return; function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl && paramName) { const nodeElement = watermarkNode.htmlElements?.widgetsContainer || watermarkNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } watermarkNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } const pairs = [ ["useText", "text"], ["useImage", "image"], ["useDisplayPosition", "displayPosition"], ["useTiled", "tiled"], ["useOpacity", "opacity"], ["useFontColor", "fontColor"], ["useBgColor", "bgColor"], ]; for (const [useName, paramName] of pairs) { const useWidget = watermarkNode.widgets.find(w => w.name === useName); const paramWidget = watermarkNode.widgets.find(w => w.name === paramName); if (useWidget && paramWidget) { toggleWidgetState(useWidget, paramWidget, paramName); } } } function videoInferenceSpeechInputToggleHandler(speechInputNode) { if (!speechInputNode?.widgets) return; function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl && paramName) { const nodeElement = speechInputNode.htmlElements?.widgetsContainer || speechInputNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } speechInputNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } const pairs = [ ["useVoice", "voice"], ["useText", "text"], ["useSpeed", "speed"], ["usePitch", "pitch"], ["useLanguage", "language"], ]; for (const [useName, paramName] of pairs) { const useWidget = speechInputNode.widgets.find(w => w.name === useName); const paramWidget = speechInputNode.widgets.find(w => w.name === paramName); if (useWidget && paramWidget) { toggleWidgetState(useWidget, paramWidget, paramName); } } } function regionalPromptingRegionsToggleHandler(regionsNode) { if (!regionsNode?.widgets) return; function toggleWidgetState(useWidget, paramWidgets, paramNames) { if (!useWidget || !paramWidgets || paramWidgets.length === 0) return; function toggleEnabled() { const enabled = useWidget.value === true; for (let i = 0; i < paramWidgets.length; i++) { const paramWidget = paramWidgets[i]; const paramName = paramNames[i]; if (!paramWidget) continue; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl && paramName) { const nodeElement = regionsNode.htmlElements?.widgetsContainer || regionsNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } } regionsNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } for (let idx = 1; idx <= 4; idx++) { const useWidget = regionsNode.widgets.find(w => w.name === `useRegion${idx}`); const promptWidget = regionsNode.widgets.find(w => w.name === `region${idx}Prompt`); const x0Widget = regionsNode.widgets.find(w => w.name === `region${idx}_x0`); const y0Widget = regionsNode.widgets.find(w => w.name === `region${idx}_y0`); const x1Widget = regionsNode.widgets.find(w => w.name === `region${idx}_x1`); const y1Widget = regionsNode.widgets.find(w => w.name === `region${idx}_y1`); const paramWidgets = [promptWidget, x0Widget, y0Widget, x1Widget, y1Widget]; const paramNames = [ `region${idx}Prompt`, `region${idx}_x0`, `region${idx}_y0`, `region${idx}_x1`, `region${idx}_y1`, ]; if (useWidget) { toggleWidgetState(useWidget, paramWidgets, paramNames); } } } function audioInferenceInputsToggleHandler(audioInputsNode) { if (!audioInputsNode?.widgets) return; // Find widgets const useAudioWidget = audioInputsNode.widgets.find(w => w && w.name === "useAudio"); const audioWidget = audioInputsNode.widgets.find(w => w && w.name === "Audio"); const useVideoWidget = audioInputsNode.widgets.find(w => w && w.name === "useVideo"); const videoWidget = audioInputsNode.widgets.find(w => w && w.name === "Video"); const useVideosWidget = audioInputsNode.widgets.find(w => w && w.name === "useVideos"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if inputEl is not available if (!paramWidget.inputEl && paramName) { const nodeElement = audioInputsNode.htmlElements?.widgetsContainer || audioInputsNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } audioInputsNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); // Initial call to set initial state setTimeout(toggleEnabled, 100); } // Set up toggle handler for single audio if (useAudioWidget && audioWidget) { toggleWidgetState(useAudioWidget, audioWidget, "Audio"); } // Set up toggle handler for single video if (useVideoWidget && videoWidget) { toggleWidgetState(useVideoWidget, videoWidget, "Video"); } // Set up toggle handlers for multiple videos (Video1 … VideoN; N from widgets, fallback to AUDIO_INFERENCE_INPUTS_MAX_VIDEOS) if (useVideosWidget) { function getAudioInferenceVideoSlotCount() { let max = 0; for (const w of audioInputsNode.widgets) { if (!w?.name) continue; const m = /^Video(\d+)$/.exec(w.name); if (m) max = Math.max(max, parseInt(m[1], 10)); } return max > 0 ? max : AUDIO_INFERENCE_INPUTS_MAX_VIDEOS; } function toggleVideosEnabled() { const enabled = useVideosWidget.value === true; const slotCount = getAudioInferenceVideoSlotCount(); for (let i = 1; i <= slotCount; i++) { const videoWidget = audioInputsNode.widgets.find(w => w && w.name === `Video${i}`); if (videoWidget) { if (videoWidget.inputEl) { videoWidget.inputEl.disabled = !enabled; videoWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; videoWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; videoWidget.inputEl.readOnly = !enabled; } videoWidget.disabled = !enabled; // Fallback: try to find inputs via DOM if (!videoWidget.inputEl) { const nodeElement = audioInputsNode.htmlElements?.widgetsContainer || audioInputsNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="Video${i}"], textarea[name="Video${i}"], select[name="Video${i}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } } } audioInputsNode.setDirtyCanvas(true); } // Set up callback appendWidgetCB(useVideosWidget, () => { setTimeout(toggleVideosEnabled, 50); }); // Initial call to set initial state setTimeout(toggleVideosEnabled, 100); } } export { notifyUser, promptEnhanceHandler, syncDimensionsNodeHandler, searchNodeHandler, mediaUUIDHandler, save3DFilepathHandler, captionNodeHandler, saveTextHandler, videoTranscriptionHandler, videoOutputsHandler, handleCustomErrors, APIKeyHandler, videoInferenceDimensionsHandler, videoModelSearchFilterHandler, audioModelSearchFilterHandler, textModelSearchFilterHandler, vectorizeModelSearchFilterHandler, vectorizeToggleHandler, useParameterToggleHandler, imageInferenceToggleHandler, imageInferenceAdvancedFeaturesToggleHandler, watermarkAdvancedFeatureToggleHandler, videoInferenceSpeechInputToggleHandler, regionalPromptingRegionsToggleHandler, upscalerToggleHandler, imageUpscalerSettingsToggleHandler, videoUpscalerToggleHandler, audioInferenceToggleHandler, audioInferenceSpeechToggleHandler, audioSettingsToggleHandler, textInferenceSettingsToggleHandler, videoSettingsToggleHandler, acceleratorOptionsToggleHandler, bytedanceProviderSettingsToggleHandler, xaiProviderSettingsToggleHandler, viduProviderSettingsToggleHandler, sourcefulProviderSettingsToggleHandler, sourcefulProviderSettingsFontsToggleHandler, threeDInferenceToggleHandler, threeDInferenceSettingsToggleHandler, threeDInferenceSettingsLatToggleHandler, ultralyticsProviderSettingsToggleHandler, openaiProviderSettingsToggleHandler, lightricksProviderSettingsToggleHandler, klingProviderSettingsToggleHandler, lumaProviderSettingsToggleHandler, briaProviderSettingsToggleHandler, pixverseProviderSettingsToggleHandler, alibabaProviderSettingsToggleHandler, mireloProviderSettingsToggleHandler, googleProviderSettingsToggleHandler, syncProviderSettingsToggleHandler, syncSegmentToggleHandler, settingsToggleHandler, safetyInputsToggleHandler, imageInferenceSettingsColorPaletteToggleHandler, audioInputToggleHandler, speechInputToggleHandler, briaProviderMaskToggleHandler, wanAnimateAdvancedFeatureSettingsToggleHandler, videoAdvancedFeatureInputsToggleHandler, audioInferenceInputsToggleHandler, }; function googleProviderSettingsToggleHandler(googleNode) { // Find all "use" parameter widgets for Google Provider Settings const useGenerateAudioWidget = googleNode.widgets.find(w => w && w.name === "useGenerateAudio"); const generateAudioWidget = googleNode.widgets.find(w => w && w.name === "generateAudio"); const useEnhancePromptWidget = googleNode.widgets.find(w => w && w.name === "useEnhancePrompt"); const enhancePromptWidget = googleNode.widgets.find(w => w && w.name === "enhancePrompt"); const useSearchWidget = googleNode.widgets.find(w => w && w.name === "useSearch"); const searchWidget = googleNode.widgets.find(w => w && w.name === "search"); const useResizeModeWidget = googleNode.widgets.find(w => w && w.name === "useResizeMode"); const resizeModeWidget = googleNode.widgets.find(w => w && w.name === "resizeMode"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = googleNode.htmlElements?.widgetsContainer || googleNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } googleNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up toggle handlers if (useGenerateAudioWidget && generateAudioWidget) { toggleWidgetState(useGenerateAudioWidget, generateAudioWidget, "generateAudio"); } if (useEnhancePromptWidget && enhancePromptWidget) { toggleWidgetState(useEnhancePromptWidget, enhancePromptWidget, "enhancePrompt"); } if (useSearchWidget && searchWidget) { toggleWidgetState(useSearchWidget, searchWidget, "search"); } if (useResizeModeWidget && resizeModeWidget) { toggleWidgetState(useResizeModeWidget, resizeModeWidget, "resizeMode"); } } function settingsToggleHandler(settingsNode) { // Find all "use" parameter widgets for Settings const useTemperatureWidget = settingsNode.widgets.find(w => w.name === "useTemperature"); const temperatureWidget = settingsNode.widgets.find(w => w.name === "temperature"); const useSystemPromptWidget = settingsNode.widgets.find(w => w.name === "useSystemPrompt"); const systemPromptWidget = settingsNode.widgets.find(w => w.name === "systemPrompt"); const useTopPWidget = settingsNode.widgets.find(w => w.name === "useTopP"); const topPWidget = settingsNode.widgets.find(w => w.name === "topP"); const useLayersWidget = settingsNode.widgets.find(w => w.name === "useLayers"); const layersWidget = settingsNode.widgets.find(w => w.name === "layers"); const useTrueCFGScaleWidget = settingsNode.widgets.find(w => w.name === "useTrueCFGScale"); const trueCFGScaleWidget = settingsNode.widgets.find(w => w.name === "trueCFGScale"); const useQualityWidget = settingsNode.widgets.find(w => w.name === "useQuality"); const qualityWidget = settingsNode.widgets.find(w => w.name === "quality"); const usePromptExtendWidget = settingsNode.widgets.find(w => w.name === "usePromptExtend"); const promptExtendWidget = settingsNode.widgets.find(w => w.name === "promptExtend"); const useEditRegionsWidget = settingsNode.widgets.find(w => w.name === "useEditRegions"); const editRegionsWidget = settingsNode.widgets.find(w => w.name === "editRegions"); const useThinkingWidget = settingsNode.widgets.find(w => w.name === "useThinking"); const thinkingWidget = settingsNode.widgets.find(w => w.name === "thinking"); const useSequentialWidget = settingsNode.widgets.find(w => w.name === "useSequential"); const sequentialWidget = settingsNode.widgets.find(w => w.name === "sequential"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = settingsNode.htmlElements?.widgetsContainer || settingsNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } settingsNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up toggle handlers if (useTemperatureWidget && temperatureWidget) { toggleWidgetState(useTemperatureWidget, temperatureWidget, "temperature"); } if (useSystemPromptWidget && systemPromptWidget) { toggleWidgetState(useSystemPromptWidget, systemPromptWidget, "systemPrompt"); } if (useTopPWidget && topPWidget) { toggleWidgetState(useTopPWidget, topPWidget, "topP"); } if (useLayersWidget && layersWidget) { toggleWidgetState(useLayersWidget, layersWidget, "layers"); } if (useTrueCFGScaleWidget && trueCFGScaleWidget) { toggleWidgetState(useTrueCFGScaleWidget, trueCFGScaleWidget, "trueCFGScale"); } if (useQualityWidget && qualityWidget) { toggleWidgetState(useQualityWidget, qualityWidget, "quality"); } if (usePromptExtendWidget && promptExtendWidget) { toggleWidgetState(usePromptExtendWidget, promptExtendWidget, "promptExtend"); } if (useEditRegionsWidget && editRegionsWidget) { toggleWidgetState(useEditRegionsWidget, editRegionsWidget, "editRegions"); } if (useThinkingWidget && thinkingWidget) { toggleWidgetState(useThinkingWidget, thinkingWidget, "thinking"); } if (useSequentialWidget && sequentialWidget) { toggleWidgetState(useSequentialWidget, sequentialWidget, "sequential"); } } function safetyInputsToggleHandler(safetyNode) { const useModeWidget = safetyNode.widgets.find(w => w.name === "useMode"); const modeWidget = safetyNode.widgets.find(w => w.name === "mode"); const useToleranceWidget = safetyNode.widgets.find(w => w.name === "useTolerance"); const toleranceWidget = safetyNode.widgets.find(w => w.name === "tolerance"); const useCheckInputsWidget = safetyNode.widgets.find(w => w.name === "useCheckInputs"); const checkInputsWidget = safetyNode.widgets.find(w => w.name === "checkInputs"); const useCheckContentWidget = safetyNode.widgets.find(w => w.name === "useCheckContent"); const checkContentWidget = safetyNode.widgets.find(w => w.name === "checkContent"); function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = safetyNode.htmlElements?.widgetsContainer || safetyNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } safetyNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } if (useModeWidget && modeWidget) { toggleWidgetState(useModeWidget, modeWidget, "mode"); } if (useToleranceWidget && toleranceWidget) { toggleWidgetState(useToleranceWidget, toleranceWidget, "tolerance"); } if (useCheckInputsWidget && checkInputsWidget) { toggleWidgetState(useCheckInputsWidget, checkInputsWidget, "checkInputs"); } if (useCheckContentWidget && checkContentWidget) { toggleWidgetState(useCheckContentWidget, checkContentWidget, "checkContent"); } } function imageInferenceSettingsColorPaletteToggleHandler(paletteNode) { function applyParamState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = paletteNode.htmlElements?.widgetsContainer || paletteNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector( `input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]` ); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; } } } } function bindSlot(i) { const useW = paletteNode.widgets.find((w) => w.name === `use_${i}`); const hexW = paletteNode.widgets.find((w) => w.name === `hex_${i}`); const ratioW = paletteNode.widgets.find((w) => w.name === `ratio_${i}`); if (!useW || !hexW || !ratioW) return; function toggleSlot() { applyParamState(useW, hexW, `hex_${i}`); applyParamState(useW, ratioW, `ratio_${i}`); paletteNode.setDirtyCanvas(true); } appendWidgetCB(useW, () => { setTimeout(toggleSlot, 50); }); setTimeout(toggleSlot, 100); } for (let i = 1; i <= 8; i++) { bindSlot(i); } } function syncProviderSettingsToggleHandler(syncNode) { // Find all "use" parameter widgets for Sync Provider Settings const useEditRegionWidget = syncNode.widgets.find(w => w.name === "useEditRegion"); const editRegionWidget = syncNode.widgets.find(w => w.name === "editRegion"); const useEmotionPromptWidget = syncNode.widgets.find(w => w.name === "useEmotionPrompt"); const emotionPromptWidget = syncNode.widgets.find(w => w.name === "emotionPrompt"); const useTemperatureWidget = syncNode.widgets.find(w => w.name === "useTemperature"); const temperatureWidget = syncNode.widgets.find(w => w.name === "temperature"); const useActiveSpeakerDetectionWidget = syncNode.widgets.find(w => w.name === "useActiveSpeakerDetection"); const activeSpeakerDetectionWidget = syncNode.widgets.find(w => w.name === "activeSpeakerDetection"); const useOcclusionDetectionEnabledWidget = syncNode.widgets.find(w => w.name === "useOcclusionDetectionEnabled"); const occlusionDetectionEnabledWidget = syncNode.widgets.find(w => w.name === "occlusionDetectionEnabled"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = syncNode.htmlElements?.widgetsContainer || syncNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } syncNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up toggle handlers if (useEditRegionWidget && editRegionWidget) { toggleWidgetState(useEditRegionWidget, editRegionWidget, "editRegion"); } if (useEmotionPromptWidget && emotionPromptWidget) { toggleWidgetState(useEmotionPromptWidget, emotionPromptWidget, "emotionPrompt"); } if (useTemperatureWidget && temperatureWidget) { toggleWidgetState(useTemperatureWidget, temperatureWidget, "temperature"); } if (useActiveSpeakerDetectionWidget && activeSpeakerDetectionWidget) { toggleWidgetState(useActiveSpeakerDetectionWidget, activeSpeakerDetectionWidget, "activeSpeakerDetection"); } if (useOcclusionDetectionEnabledWidget && occlusionDetectionEnabledWidget) { toggleWidgetState(useOcclusionDetectionEnabledWidget, occlusionDetectionEnabledWidget, "occlusionDetectionEnabled"); } } function syncSegmentToggleHandler(syncSegmentNode) { // Find all "use" parameter widgets for Sync Segment const useAudioStartTimeWidget = syncSegmentNode.widgets.find(w => w.name === "useAudioStartTime"); const audioStartTimeWidget = syncSegmentNode.widgets.find(w => w.name === "audioStartTime"); const useAudioEndTimeWidget = syncSegmentNode.widgets.find(w => w.name === "useAudioEndTime"); const audioEndTimeWidget = syncSegmentNode.widgets.find(w => w.name === "audioEndTime"); // Helper function to toggle widget enabled state function toggleWidgetState(useWidget, paramWidget, paramName) { if (!useWidget || !paramWidget) return; function toggleEnabled() { const enabled = useWidget.value === true; if (paramWidget.inputEl) { paramWidget.inputEl.disabled = !enabled; paramWidget.inputEl.style.opacity = enabled ? "1" : "0.5"; paramWidget.inputEl.style.cursor = enabled ? "text" : "not-allowed"; paramWidget.inputEl.readOnly = !enabled; } paramWidget.disabled = !enabled; if (!paramWidget.inputEl) { const nodeElement = syncSegmentNode.htmlElements?.widgetsContainer || syncSegmentNode.htmlElements; if (nodeElement) { const input = nodeElement.querySelector(`input[name="${paramName}"], textarea[name="${paramName}"], select[name="${paramName}"]`); if (input) { input.disabled = !enabled; input.style.opacity = enabled ? "1" : "0.5"; input.style.cursor = enabled ? "text" : "not-allowed"; input.readOnly = !enabled; if (input.tagName === "SELECT") { input.style.pointerEvents = enabled ? "auto" : "none"; } } } } syncSegmentNode.setDirtyCanvas(true); } appendWidgetCB(useWidget, () => { setTimeout(toggleEnabled, 50); }); setTimeout(toggleEnabled, 100); } // Set up toggle handlers if (useAudioStartTimeWidget && audioStartTimeWidget) { toggleWidgetState(useAudioStartTimeWidget, audioStartTimeWidget, "audioStartTime"); } if (useAudioEndTimeWidget && audioEndTimeWidget) { toggleWidgetState(useAudioEndTimeWidget, audioEndTimeWidget, "audioEndTime"); } }