Add custom nodes, Civitai loras (LFS), and vast.ai setup script
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Some checks failed
Python Linting / Run Ruff (push) Has been cancelled
Python Linting / Run Pylint (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Has been cancelled
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Has been cancelled
Execution Tests / test (macos-latest) (push) Has been cancelled
Execution Tests / test (ubuntu-latest) (push) Has been cancelled
Execution Tests / test (windows-latest) (push) Has been cancelled
Test server launches without errors / test (push) Has been cancelled
Unit Tests / test (macos-latest) (push) Has been cancelled
Unit Tests / test (ubuntu-latest) (push) Has been cancelled
Unit Tests / test (windows-2022) (push) Has been cancelled
Includes 30 custom nodes committed directly, 7 Civitai-exclusive loras stored via Git LFS, and a setup script that installs all dependencies and downloads HuggingFace-hosted models on vast.ai. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
import { app } from "../../../../scripts/app.js";
|
||||
import {removeDropdown, createDropdown} from "../common/dropdown.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) {
|
||||
//low to high
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
//high to low
|
||||
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|preSampling):\s/, '');
|
||||
|
||||
if (!currentOptionsDict[widgetName]) {
|
||||
currentOptionsDict = {...currentOptionsDict, [widgetName]: plotDict[widgetValue]};
|
||||
} else if (currentOptionsDict[widgetName] != plotDict[widgetValue]) {
|
||||
currentOptionsDict[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;
|
||||
|
||||
// Define getters and setters for widget values
|
||||
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 axisWidgetName = w.name[0] + '_axis';
|
||||
let optionsList = currentOptionsDict?.[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) {
|
||||
createDropdown(w.inputEl, filteredOptionsList, (selectedOption) => {
|
||||
const verifiedText = replaceOptionSegments(selectedOption, inputSegments, cursorSegmentIndex, optionsList);
|
||||
w.inputEl.value = verifiedText;
|
||||
});
|
||||
}
|
||||
else {
|
||||
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.easy.xyPlot",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "easy 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') {
|
||||
if(key == 'seed'){
|
||||
plotDict[key] = value + '; ';
|
||||
}
|
||||
else {
|
||||
plotDict[key] = generateNumList(value);
|
||||
}
|
||||
} else {
|
||||
plotDict[key] = value + '; ';
|
||||
}
|
||||
}
|
||||
plotDict["None"] = [];
|
||||
plotDict["---------------------"] = [];
|
||||
}
|
||||
},
|
||||
nodeCreated(node) {
|
||||
if (node.comfyClass === "easy XYPlot") {
|
||||
addGetSetters(node);
|
||||
dropdownCreator(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user