279 lines
9.4 KiB
JavaScript
279 lines
9.4 KiB
JavaScript
import {app} from "/scripts/app.js";
|
|
import {$el} from "/scripts/ui.js";
|
|
import {ComfyWidgets} from "/scripts/widgets.js";
|
|
|
|
function get_position_style(ctx, node_width, node_height, y, widget_height, isSingle) {
|
|
/* Create a transform that deals with all the scrolling and zooming */
|
|
const elRect = ctx.canvas.getBoundingClientRect();
|
|
if (isSingle) {
|
|
y = y - 86
|
|
y = y + Math.floor((node_height - y - widget_height) / 2)
|
|
}
|
|
const transform = new DOMMatrix()
|
|
.scaleSelf(
|
|
elRect.width / ctx.canvas.width,
|
|
elRect.height / ctx.canvas.height
|
|
)
|
|
.multiplySelf(ctx.getTransform())
|
|
.translateSelf(Math.floor((node_width - widget_height) / 2), y);
|
|
|
|
return {
|
|
transformOrigin: '0 0',
|
|
transform: transform,
|
|
left: '0',
|
|
top: '0',
|
|
cursor: 'pointer',
|
|
position: 'absolute',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
justifyContent: 'space-around',
|
|
zIndex: '0'
|
|
};
|
|
}
|
|
|
|
function createColorWidget(node, inputName, inputData, app, isSingle) {
|
|
// console.log(node)
|
|
const widget = {
|
|
type: inputData[0], // the type, CHEESE
|
|
name: inputName, // the name, slice
|
|
size: [64, 64], // a default size
|
|
draw(ctx, node, widget_width, y, H) {
|
|
// console.log(node.size[0], node.size[1], y, widget_width, H)
|
|
Object.assign(
|
|
this.div.style,
|
|
get_position_style(ctx, widget_width, node.size[1], y, this.div.clientHeight ? this.div.clientHeight : 0, isSingle)
|
|
);
|
|
},
|
|
computeSize(widget_width) {
|
|
// console.log(widget_width)
|
|
return [64, 64] // a method to compute the current size of the widget
|
|
},
|
|
async serializeValue(nodeId, widgetIndex) {
|
|
let hexa = widget.value || '#000000'
|
|
return hexa
|
|
}
|
|
}
|
|
// adds it to the node
|
|
node.addCustomWidget(widget)
|
|
widget.div = $el('div', {})
|
|
let inputColor = document.createElement('div')
|
|
inputColor.id = 'easyapi-color-picker'
|
|
widget.div.appendChild(inputColor);
|
|
document.body.appendChild(widget.div)
|
|
const picker = Pickr.create({
|
|
el: inputColor,
|
|
theme: 'classic',
|
|
default: '#000000',
|
|
swatches: [
|
|
'rgba(244, 67, 54, 1)',
|
|
'rgba(233, 30, 99, 0.95)',
|
|
'rgba(156, 39, 176, 0.9)',
|
|
'rgba(103, 58, 183, 0.85)',
|
|
'rgba(63, 81, 181, 0.8)',
|
|
'rgba(33, 150, 243, 0.75)',
|
|
'rgba(3, 169, 244, 0.7)',
|
|
'rgba(0, 188, 212, 0.7)',
|
|
'rgba(0, 150, 136, 0.75)',
|
|
'rgba(76, 175, 80, 0.8)',
|
|
'rgba(139, 195, 74, 0.85)',
|
|
'rgba(205, 220, 57, 0.9)',
|
|
'rgba(255, 235, 59, 0.95)',
|
|
'rgba(255, 193, 7, 1)'
|
|
],
|
|
components: {
|
|
// Main components
|
|
preview: true,
|
|
opacity: true,
|
|
hue: true,
|
|
// Input / output Options
|
|
interaction: {
|
|
hex: true,
|
|
rgba: true,
|
|
hsla: true,
|
|
hsva: true,
|
|
cmyk: true,
|
|
input: true,
|
|
clear: false,
|
|
save: true,
|
|
cancel: true
|
|
}
|
|
}
|
|
})
|
|
|
|
picker.on('init', instance => {
|
|
if (!!widget.value) {
|
|
instance.setColor(widget.value);
|
|
}
|
|
}).on('save', (color, instance) => {
|
|
try {
|
|
widget.value = color.toHEXA().toString()
|
|
picker && picker.hide()
|
|
} catch (error) {
|
|
}
|
|
}).on('cancel', instance => {
|
|
picker && picker.hide()
|
|
})
|
|
|
|
if (node.picker === undefined) {
|
|
node.picker = [picker]
|
|
} else {
|
|
node.picker.push(picker);
|
|
}
|
|
const handleMouseWheel = () => {
|
|
try {
|
|
if (!!node.picker) {
|
|
for (let idx in node.picker) {
|
|
node.picker[idx].hide()
|
|
}
|
|
}
|
|
} catch (error) {
|
|
}
|
|
}
|
|
// close selector
|
|
document.addEventListener('wheel', handleMouseWheel)
|
|
|
|
const onRemoved = node.onRemoved
|
|
node.onRemoved = () => {
|
|
try {
|
|
for (let idx in node.picker) {
|
|
if (!!node.picker[idx].widgets) {
|
|
for (let wIdx in node.picker[idx].widgets) {
|
|
node.picker[idx].widgets[wIdx].div && node.picker[idx].widgets[wIdx].div.remove()
|
|
}
|
|
}
|
|
node.picker[idx].destroyAndRemove();
|
|
}
|
|
node.picker = null
|
|
document.removeEventListener('wheel', handleMouseWheel)
|
|
} catch (error) {
|
|
console.log(error)
|
|
}
|
|
return onRemoved?.()
|
|
}
|
|
node.serialize_widgets = true
|
|
return widget;
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: "Comfy.EasyApi.custom",
|
|
async init(app) {
|
|
// Any initial setup to run as soon as the page loads
|
|
$el('link', {
|
|
rel: 'stylesheet',
|
|
href: '/extensions/comfyui-easyapi-nodes/css/classic.min.css',
|
|
parent: document.head
|
|
})
|
|
},
|
|
async setup(app) {
|
|
|
|
},
|
|
async addCustomNodeDefs(defs, app) {
|
|
// Add custom node definitions
|
|
// These definitions will be configured and registered automatically
|
|
// defs is a lookup core nodes, add yours into this
|
|
},
|
|
async getCustomWidgets(app) {
|
|
// Return custom widget types
|
|
// See ComfyWidgets for widget examples
|
|
return {
|
|
SINGLECOLORPICKER(node, inputName, inputData, app) {
|
|
return createColorWidget(node, inputName, inputData, app, true)
|
|
},
|
|
COLORPICKER(node, inputName, inputData, app) {
|
|
return createColorWidget(node, inputName, inputData, app, false)
|
|
}
|
|
}
|
|
},
|
|
|
|
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
|
// Allows the extension to add additional handling to the node before it is registered with LGraph
|
|
const onDrawForeground = nodeType.prototype.onDrawForeground;
|
|
nodeType.prototype.onDrawForeground = function (ctx) {
|
|
const r = onDrawForeground?.apply?.(this, arguments);
|
|
if (this.flags.collapsed) {
|
|
if (this.picker && this.widgets) {
|
|
for (const i in this.widgets) {
|
|
let w = this.widgets[i]
|
|
if (w.type == 'SINGLECOLORPICKER' || w.type == 'COLORPICKER') {
|
|
// hide it
|
|
w.div.style = "";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return r;
|
|
};
|
|
|
|
if (nodeData.name === "ShowString" || nodeData.name === "ShowInt" || nodeData.name === "ShowNumber" || nodeData.name === "ShowFloat" || nodeData.name === "ShowBoolean") {
|
|
const outSet = function (text) {
|
|
if (this.widgets) {
|
|
// if multiline is true, w.type will be customtext
|
|
// find the position of first "customtext"
|
|
const pos = this.widgets.findIndex((w) => w.type === "customtext");
|
|
if (pos !== -1) {
|
|
for (let i = pos; i < this.widgets.length; i++) {
|
|
this.widgets[i].onRemove?.();
|
|
}
|
|
this.widgets.length = pos;
|
|
}
|
|
}
|
|
|
|
if (Array.isArray(text)) {
|
|
for (const list of text) {
|
|
const w = ComfyWidgets.STRING(this, "text", ["STRING", {multiline: true}], app).widget;
|
|
w.inputEl.readOnly = true;
|
|
w.inputEl.style.opacity = "0.6";
|
|
w.value = list;
|
|
}
|
|
} else {
|
|
const w = ComfyWidgets.STRING(this, "text", ["STRING", {multiline: true}], app).widget;
|
|
w.inputEl.readOnly = true;
|
|
w.inputEl.style.opacity = "0.6";
|
|
w.value = text;
|
|
}
|
|
|
|
requestAnimationFrame(() => {
|
|
const sz = this.computeSize();
|
|
if (sz[0] < this.size[0]) {
|
|
sz[0] = this.size[0];
|
|
}
|
|
if (sz[1] < this.size[1]) {
|
|
sz[1] = this.size[1];
|
|
}
|
|
this.onResize?.(sz);
|
|
app.graph.setDirtyCanvas(true, false);
|
|
});
|
|
}
|
|
|
|
const onExecuted = nodeType.prototype.onExecuted;
|
|
nodeType.prototype.onExecuted = function (texts) {
|
|
onExecuted?.apply(this, arguments);
|
|
let show = texts[k]
|
|
outSet.call(this, show);
|
|
};
|
|
/*const onConfigure = nodeType.prototype.onConfigure;
|
|
nodeType.prototype.onConfigure = function (w) {
|
|
onConfigure?.apply(this, arguments);
|
|
if (w?.widgets_values?.length) {
|
|
outSet.call(this, w.widgets_values[0]);
|
|
}
|
|
};*/
|
|
}
|
|
},
|
|
async registerCustomNodes(app) {
|
|
// Register any custom node implementations here allowing for more flexability than a custom node def
|
|
// console.log("[logging]", "register custom nodes");
|
|
},
|
|
async loadedGraphNode(node, app) {
|
|
// Fires for each node when loading/dragging/etc a workflow json or png
|
|
// If you break something in the backend and want to patch workflows in the frontend
|
|
// This fires for every node on each load so only log once
|
|
// delete ext.loadedGraphNode;
|
|
|
|
},
|
|
async nodeCreated(node, app) {
|
|
// Fires every time a node is constructed
|
|
// You can modify widgets/add handlers/etc here
|
|
}
|
|
}) |