This commit is contained in:
JJ
2026-04-02 21:20:41 +01:00
parent 72165b72ac
commit 0c0cd1dca3
+177
View File
@@ -115,6 +115,140 @@ app.registerExtension({
return null;
};
/**
* Upload an image file to ComfyUI's input directory
*/
const uploadImageFile = async (file) => {
const formData = new FormData();
formData.append('image', file);
formData.append('type', 'input');
try {
const resp = await api.fetchApi('/upload/image', { method: 'POST', body: formData });
if (resp.ok || resp.status === 200) {
const data = await resp.json();
return data.name || data.filename || file.name;
}
} catch (err) {
console.error('[PowerLoadVideo] Image upload error:', err);
}
return null;
};
/**
* Create a LoadImage node at the given position and load an image into it
*/
const createLoadImageNodeWithImage = async (filename, pos) => {
// Check if LoadImage node type exists
if (!LiteGraph.registered_node_types['LoadImage']) {
console.error('[PowerLoadVideo] LoadImage node type not found!');
return null;
}
const node = LiteGraph.createNode('LoadImage');
if (!node) {
console.error('[PowerLoadVideo] Failed to create LoadImage node!');
return null;
}
// Set position centered at mouse
node.pos = [pos[0] - 150, pos[1] - 100];
// Add node to graph
app.canvas.graph.add(node);
// Wait for widgets to be created
await new Promise(resolve => setTimeout(resolve, 50));
// Find the image combo widget and set it to our uploaded filename
const imageWidget = node.widgets.find(w => w.name === 'image');
if (imageWidget) {
imageWidget.value = filename;
// Trigger value change to update the node display
if (imageWidget.callback) {
imageWidget.callback(filename);
}
}
// Select the new node
app.canvas.selectNodes([node]);
return node;
};
/**
* Load an image file into a LoadImage node by updating its widget
*/
const loadImageIntoNode = async (node, file) => {
// Upload the image first
const filename = await uploadImageFile(file);
if (!filename) {
console.error('[PowerLoadVideo] Failed to upload image!');
return false;
}
// Find the image combo widget and set it to our uploaded filename
const imageWidget = node.widgets.find(w => w.name === 'image');
if (imageWidget) {
imageWidget.value = filename;
// Trigger value change to update the node display
if (imageWidget.callback) {
imageWidget.callback(filename);
}
return true;
}
return false;
};
/**
* Check if a file is an image type
*/
const isImageFile = (file) => {
return file.type.startsWith('image/') ||
file.name.toLowerCase().match(/\.(png|jpg|jpeg|gif|webp|bmp)$/i);
};
/**
* Check if a point is inside a node's bounding box
*/
const isPointInNode = (pointX, pointY, node) => {
// Node position and size in graph coordinates
const nodeLeft = node.pos[0];
const nodeTop = node.pos[1];
const nodeRight = nodeLeft + node.size[0];
const nodeBottom = nodeTop + node.size[1];
return pointX >= nodeLeft && pointX <= nodeRight &&
pointY >= nodeTop && pointY <= nodeBottom;
};
/**
* Check if the drop target is over a LoadImage node
*/
const getLoadImageNodeAtPosition = (clientX, clientY) => {
// Get canvas rect for coordinate conversion
const rect = canvas.getBoundingClientRect();
const mouseX = clientX - rect.left;
const mouseY = clientY - rect.top;
// Convert to graph coordinates
const ds = app.canvas.ds || { scale: 1, offset: [0, 0] };
const graphX = mouseX / ds.scale - ds.offset[0];
const graphY = mouseY / ds.scale - ds.offset[1];
// Find all LoadImage nodes and check if mouse is over any of them
const loadImageNodes = app.canvas.graph.nodes.filter(
node => node.type === 'LoadImage'
);
for (const node of loadImageNodes) {
if (isPointInNode(graphX, graphY, node)) {
return node;
}
}
return null;
};
const handleDrop = async (e) => {
e.preventDefault();
e.stopPropagation();
@@ -143,6 +277,16 @@ app.registerExtension({
return;
}
// Check if dropping over a LoadImage node (for any image type)
if (isImageFile(file)) {
const loadImageNode = getLoadImageNodeAtPosition(e.clientX, e.clientY);
if (loadImageNode) {
// Drop onto existing LoadImage node - load image into it
await loadImageIntoNode(loadImageNode, file);
return;
}
}
// Check if it's a PNG image with embedded workflow
if (file.type === 'image/png') {
try {
@@ -158,6 +302,39 @@ app.registerExtension({
}
}
// If it's an image file without embedded workflow, create LoadImage node
if (isImageFile(file)) {
isHandlingDrop = true;
droppedFile = file;
try {
// Upload the image file
const filename = await uploadImageFile(file);
if (filename) {
// Wait a moment for node types to be registered
await new Promise(resolve => setTimeout(resolve, 100));
// Calculate mouse position in graph coordinates
const ds = app.canvas.ds || { scale: 1, offset: [0, 0] };
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
const graphX = mouseX / ds.scale - ds.offset[0];
const graphY = mouseY / ds.scale - ds.offset[1];
// Create LoadImage node at drop position
await createLoadImageNodeWithImage(filename, [graphX, graphY]);
} else {
console.error('[PowerLoadVideo] Image upload failed!');
}
} finally {
isHandlingDrop = false;
droppedFile = null;
}
return;
}
// Check if it's a video file
if (!file.type.startsWith('video/')) {
return;