* vectors now convert in-line

This commit is contained in:
Alexander G. Morano
2025-03-18 04:01:29 -04:00
parent 1d474faf6e
commit fcde3cd719
3 changed files with 107 additions and 45 deletions
+3
View File
@@ -46,6 +46,9 @@ Please consider sponsoring me if you enjoy the results of my work, code or docum
## UPDATES
**2025/03/18** @1.0.5:
* vectors now convert in-line
**2025/03/08** @1.0.3:
* removed security scanner failures for in-line http links
+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "jovi_capture"
description = "Capture Webcamera and URL media streams as ComfyUI images"
version = "1.0.3"
version = "1.0.5"
license = { file = "LICENSE" }
readme = "README.md"
authors = [{ name = "Alexander G. Morano", email = "amorano@gmail.com" }]
+103 -44
View File
@@ -1,12 +1,48 @@
/**
* File: widget_vector.js
*/
/**/
import { app } from "../../scripts/app.js"
import { $el } from "../../scripts/ui.js"
import { widgetToInput, widgetToWidget, domInnerValueChange } from './util_jov.js'
/** @import { IWidget, LGraphCanvas } from '../../types/litegraph/litegraph.d.ts' */
const GET_CONFIG = Symbol();
const TYPES = ['RGB', 'VEC2', 'VEC3', 'VEC4', 'VEC2INT', 'VEC3INT', 'VEC4INT']
const TYPES_ACCEPT = 'RGB, VEC2, VEC3, VEC4, VEC2INT, VEC3INT, VEC4INT, FLOAT, INT, BOOLEAN'
function convertToInput(node, widget) {
const input = node.addInput(widget.name, widget.type, {
// @ts-expect-error [GET_CONFIG] is not a valid property of IWidget
widget: { name: widget.name, [GET_CONFIG]: () => [
widget.type,
widget.options || {}
] },
...{ shape: LiteGraph.SlotShape.HollowCircle }
});
return input;
}
function removeConvertToWidgetEntries(menuArray, widgetNames) {
function recursiveFilter(menu) {
return menu.filter(item => {
// Keep non-matching items
if (!item || !item.content) return true;
// Remove this item
if (widgetNames.some(name => item.content === `Convert ${name} to Widget`)) {
return false;
}
// Recursively filter submenus if they exist
if (item.submenu && item.submenu.options) {
item.submenu.options = recursiveFilter(item.submenu.options);
}
return true;
});
}
return recursiveFilter(menuArray);
}
function isVersionLess(v1, v2) {
const parts1 = v1.split('.').map(Number);
const parts2 = v2.split('.').map(Number);
@@ -59,7 +95,7 @@ const VectorWidget = (app, inputName, options, initial, desc='') => {
widget.options.label = ['🟥', '🟩', '🟦', 'ALPHA'];
}
widget.options.precision = 4;
widget.options.precision = 3;
widget.options.step = 0.0075;
widget.options.round = 1 / 10 ** widget.options.step;
@@ -200,6 +236,7 @@ const VectorWidget = (app, inputName, options, initial, desc='') => {
}
if (!this.options?.rgb) return;
//const rgba = widget.value;
const rgba = Object.values(this?.value || []);
const color = colorRGB2Hex(rgba.slice(0, 3));
@@ -300,49 +337,71 @@ app.registerExtension({
}
},
async beforeRegisterNodeDef(nodeType, nodeData, app) {
const version = window.__COMFYUI_FRONTEND_VERSION__;
if (!isVersionLess(version, "1.10.3")) {
const inputTypes = nodeData.input;
if (inputTypes.length == 0) {
return;
}
const myTypes = ['RGB', 'VEC2', 'VEC3', 'VEC4', 'VEC2INT', 'VEC3INT', 'VEC4INT']
const inputTypes = nodeData.input;
if (inputTypes) {
const matchingTypes = ['required', 'optional']
.flatMap(type => Object.entries(inputTypes[type] || [])
.filter(([_, value]) => myTypes.includes(value[0]))
);
// CLEANUP ON REMOVE
if (matchingTypes.length > 0) {
// MENU CONVERSIONS
const getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
nodeType.prototype.getExtraMenuOptions = function (_, options) {
const me = getExtraMenuOptions?.apply(this, arguments);
const widgetToInputArray = [];
for (const [widgetName, additionalInfo] of matchingTypes) {
const widget = Object.values(this.widgets).find(m => m.name == widgetName);
if (myTypes.includes(widget.type) || widget.type.endsWith('-jov')) {
if (!widget.hidden) {
const widgetToInputObject = {
content: `Convert ${widgetName} to input`,
callback: () => widgetToInput(this, widget, additionalInfo)
};
widgetToInputArray.push(widgetToInputObject);
} else {
const widgetToInputObject = {
content: `Convert ${widgetName} to widget`,
callback: () => widgetToWidget(this, widget, additionalInfo)
};
widgetToInputArray.push(widgetToInputObject);
}
}
}
if (widgetToInputArray.length) {
options.push(...widgetToInputArray, null);
}
return me;
};
}
const matchingTypes = ['required', 'optional']
.flatMap(type => Object.entries(inputTypes[type] || [])
.filter(([_, value]) => TYPES.includes(value[0]))
);
if (matchingTypes.length == 0) {
return;
}
const getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
const version = window.__COMFYUI_FRONTEND_VERSION__;
if (!isVersionLess(version, "1.10.3")) {
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = async function () {
const me = onNodeCreated?.apply(this);
Object.entries(this.widgets).forEach(([key, widget]) => {
if (!TYPES.includes(widget.type)) {
return;
}
convertToInput(this, widget);
});
return me;
}
nodeType.prototype.getExtraMenuOptions = function (_, options) {
const me = getExtraMenuOptions?.apply(this, arguments);
const widgets = matchingTypes.map(item => item[0]);
options = removeConvertToWidgetEntries(options, widgets);
console.info(options)
return me;
}
return;
}
// MENU CONVERSIONS
nodeType.prototype.getExtraMenuOptions = function (_, options) {
const me = getExtraMenuOptions?.apply(this, arguments);
const widgetToInputArray = [];
for (const [widgetName, additionalInfo] of matchingTypes) {
const widget = Object.values(this.widgets).find(m => m.name == widgetName);
if (TYPES.includes(widget.type) || widget.type.endsWith('-jov')) {
if (!widget.hidden) {
const widgetToInputObject = {
content: `Convert ${widgetName} to input`,
callback: () => widgetToInput(this, widget, additionalInfo)
};
widgetToInputArray.push(widgetToInputObject);
} else {
const widgetToInputObject = {
content: `Convert ${widgetName} to widget`,
callback: () => widgetToWidget(this, widget, additionalInfo)
};
widgetToInputArray.push(widgetToInputObject);
}
}
}
if (widgetToInputArray.length) {
options.push(...widgetToInputArray, null);
}
return me;
};
}
})