|
|
import { app } from "../../scripts/app.js"; |
|
|
import { ttN_CreateDropdown, ttN_RemoveDropdown } from "./ttNdropdown.js"; |
|
|
|
|
|
function generateNumList(dictionary) { |
|
|
const minimum = dictionary["min"] || 0; |
|
|
const maximum = dictionary["max"] || 0; |
|
|
const step = dictionary["step"] || 1; |
|
|
|
|
|
if (step === 0) { |
|
|
return []; |
|
|
} |
|
|
|
|
|
const result = []; |
|
|
let currentValue = minimum; |
|
|
|
|
|
while (currentValue <= maximum) { |
|
|
if (Number.isInteger(step)) { |
|
|
result.push(Math.round(currentValue) + '; '); |
|
|
} else { |
|
|
let formattedValue = currentValue.toFixed(3); |
|
|
if(formattedValue == -0.000){ |
|
|
formattedValue = '0.000'; |
|
|
} |
|
|
if (!/\.\d{3}$/.test(formattedValue)) { |
|
|
formattedValue += "0"; |
|
|
} |
|
|
result.push(formattedValue + "; "); |
|
|
} |
|
|
currentValue += step; |
|
|
} |
|
|
|
|
|
if (maximum >= 0 && minimum >= 0) { |
|
|
|
|
|
return result; |
|
|
} |
|
|
else { |
|
|
|
|
|
return result.reverse(); |
|
|
} |
|
|
} |
|
|
|
|
|
let plotDict = {}; |
|
|
let currentOptionsDict = {}; |
|
|
|
|
|
function getCurrentOptionLists(node, widget) { |
|
|
const nodeId = String(node.id); |
|
|
const widgetName = widget.name; |
|
|
const widgetValue = widget.value.replace(/^(loader|sampler):\s/, ''); |
|
|
|
|
|
if (!currentOptionsDict[nodeId] || !currentOptionsDict[nodeId][widgetName]) { |
|
|
currentOptionsDict[nodeId] = {...currentOptionsDict[nodeId], [widgetName]: plotDict[widgetValue]}; |
|
|
} else if (currentOptionsDict[nodeId][widgetName] != plotDict[widgetValue]) { |
|
|
currentOptionsDict[nodeId][widgetName] = plotDict[widgetValue]; |
|
|
} |
|
|
} |
|
|
|
|
|
function addGetSetters(node) { |
|
|
if (node.widgets) |
|
|
for (const w of node.widgets) { |
|
|
if (w.name === "x_axis" || |
|
|
w.name === "y_axis") { |
|
|
let widgetValue = w.value; |
|
|
|
|
|
|
|
|
Object.defineProperty(w, 'value', { |
|
|
|
|
|
get() { |
|
|
return widgetValue; |
|
|
}, |
|
|
set(newVal) { |
|
|
if (newVal !== widgetValue) { |
|
|
widgetValue = newVal; |
|
|
getCurrentOptionLists(node, w); |
|
|
} |
|
|
} |
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
function dropdownCreator(node) { |
|
|
if (node.widgets) { |
|
|
const widgets = node.widgets.filter( |
|
|
(n) => (n.type === "customtext" && n.dynamicPrompts !== false) || n.dynamicPrompts |
|
|
); |
|
|
|
|
|
for (const w of widgets) { |
|
|
function replaceOptionSegments(selectedOption, inputSegments, cursorSegmentIndex, optionsList) { |
|
|
if (selectedOption) { |
|
|
inputSegments[cursorSegmentIndex] = selectedOption; |
|
|
} |
|
|
|
|
|
return inputSegments.map(segment => verifySegment(segment, optionsList)) |
|
|
.filter(item => item !== '') |
|
|
.join(''); |
|
|
} |
|
|
|
|
|
function verifySegment(segment, optionsList) { |
|
|
segment = cleanSegment(segment); |
|
|
|
|
|
if (isInOptionsList(segment, optionsList)) { |
|
|
return segment + '; '; |
|
|
} |
|
|
|
|
|
let matchedOptions = findMatchedOptions(segment, optionsList); |
|
|
|
|
|
if (matchedOptions.length === 1 || matchedOptions.length === 2) { |
|
|
return matchedOptions[0]; |
|
|
} |
|
|
|
|
|
if (isInOptionsList(formatNumberSegment(segment), optionsList)) { |
|
|
return formatNumberSegment(segment) + '; '; |
|
|
} |
|
|
|
|
|
return ''; |
|
|
} |
|
|
|
|
|
function cleanSegment(segment) { |
|
|
return segment.replace(/(\n|;| )/g, ''); |
|
|
} |
|
|
|
|
|
function isInOptionsList(segment, optionsList) { |
|
|
return optionsList.includes(segment + '; '); |
|
|
} |
|
|
|
|
|
function findMatchedOptions(segment, optionsList) { |
|
|
return optionsList.filter(option => option.toLowerCase().includes(segment.toLowerCase())); |
|
|
} |
|
|
|
|
|
function formatNumberSegment(segment) { |
|
|
if (Number(segment)) { |
|
|
return Number(segment).toFixed(3); |
|
|
} |
|
|
|
|
|
if (['0', '0.', '0.0', '0.00', '00'].includes(segment)) { |
|
|
return '0.000'; |
|
|
} |
|
|
return segment; |
|
|
} |
|
|
|
|
|
|
|
|
const onInput = function () { |
|
|
const nodeId = node.id; |
|
|
const axisWidgetName = w.name[0] + '_axis'; |
|
|
|
|
|
let optionsList = currentOptionsDict[nodeId]?.[axisWidgetName] || []; |
|
|
if (optionsList.length === 0) {return} |
|
|
|
|
|
const inputText = w.inputEl.value; |
|
|
const cursorPosition = w.inputEl.selectionStart; |
|
|
|
|
|
let inputSegments = inputText.split('; '); |
|
|
|
|
|
const cursorSegmentIndex = inputText.substring(0, cursorPosition).split('; ').length - 1; |
|
|
const currentSegment = inputSegments[cursorSegmentIndex]; |
|
|
const currentSegmentLower = currentSegment.replace(/\n/g, '').toLowerCase(); |
|
|
|
|
|
const filteredOptionsList = optionsList.filter(option => option.toLowerCase().includes(currentSegmentLower)).map(option => option.replace(/; /g, '')); |
|
|
|
|
|
if (filteredOptionsList.length > 0) { |
|
|
ttN_CreateDropdown(w.inputEl, filteredOptionsList, (selectedOption) => { |
|
|
const verifiedText = replaceOptionSegments(selectedOption, inputSegments, cursorSegmentIndex, optionsList); |
|
|
w.inputEl.value = verifiedText; |
|
|
}); |
|
|
} |
|
|
else { |
|
|
ttN_RemoveDropdown(); |
|
|
const verifiedText = replaceOptionSegments(null, inputSegments, cursorSegmentIndex, optionsList); |
|
|
w.inputEl.value = verifiedText; |
|
|
} |
|
|
}; |
|
|
|
|
|
w.inputEl.removeEventListener('input', onInput); |
|
|
w.inputEl.addEventListener('input', onInput); |
|
|
w.inputEl.removeEventListener('mouseup', onInput); |
|
|
w.inputEl.addEventListener('mouseup', onInput); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
app.registerExtension({ |
|
|
name: "comfy.ttN.xyPlot", |
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) { |
|
|
if (nodeData.name === "ttN xyPlot") { |
|
|
plotDict = nodeData.input.hidden.plot_dict[0]; |
|
|
|
|
|
for (const key in plotDict) { |
|
|
const value = plotDict[key]; |
|
|
if (Array.isArray(value)) { |
|
|
let updatedValues = []; |
|
|
for (const v of value) { |
|
|
updatedValues.push(v + '; '); |
|
|
} |
|
|
plotDict[key] = updatedValues; |
|
|
} else if (typeof(value) === 'object') { |
|
|
plotDict[key] = generateNumList(value); |
|
|
} else { |
|
|
plotDict[key] = value + '; '; |
|
|
} |
|
|
} |
|
|
plotDict["None"] = []; |
|
|
plotDict["---------------------"] = []; |
|
|
} |
|
|
}, |
|
|
nodeCreated(node) { |
|
|
if (node.constructor.title === "xyPlot") { |
|
|
addGetSetters(node); |
|
|
dropdownCreator(node); |
|
|
|
|
|
} |
|
|
} |
|
|
}); |