[Feature Request] - Optional Ctrl-enabled Selective Ancestral Branch Loading Upon PNG Drag & Drop Event
- Dominant language
- Python
- Stars
- 133k
- Forks
- 15.7k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 153
Description
Feature Request: Ability to Load Only Branch of Workflow
Background:
Currently, when loading a workflow from a dropped image, the entire workflow state is loaded, including all nodes. This poses challenges when trying to isolate and save specific branches from large workflows that contribute to desirable outputs. The purpose of this feature request is to add the ability to selectively load only the branch of a workflow associated with a dropped image by holding the Ctrl key during the drop action.
Current Status:
I am a beginner-novice coder and have attempted to implement this feature; however, I have encountered challenges and need assistance to determine if my implementation strategy is sound. At the moment, I am working with the latest Comfyui Portable for Windows distribution and integrating SDXL 0.9 stable diffusion model capabilities. I cannot yet get my proposed implementation strategy to work. The app will load, but the interface is blank and lost all interactivity or drop/capability.
Request for Collaboration:
I would greatly appreciate collaborating with someone experienced in this field to help me overcome the obstacles I'm facing and successfully implement this feature. I am open to working together, leveraging your expertise, and refining the implementation strategy to achieve the desired outcome.
VERSION INFO: I have modified the latest downloaded .7zip Comfyui Portable for Windows distribution to incorporate the SDXL 0.9 stable diffusion model capabilities. This feature request is part of my ongoing efforts to enhance the functionality of the application. I'm unsure if this would fit into the main ComfyUI repo as well.
If you are interested in collaborating on this project or have any suggestions, please reach out to me. I am eager to learn and contribute to the implementation process.
Implementation Planed Strategy:
Strategy:
Remove the redundant pngjs import and utilize the existing pnginfo.js functions for encoding and decoding PNG metadata.
Update pnginfo.js by adding the writeBranchData and getBranchData functions for writing and reading branch metadata.
In app.js, import getBranchData from pnginfo.js and use it in the handleFile method to check for branch data in PNG files.
If branch data is found, call the loadLineageBranch method to load the branch nodes. Otherwise, proceed with the existing logic to load the full workflow.
Implement the loadLineageBranch method to traverse the graph recursively starting from the root node of the branch. Collect the branch nodes and load only those nodes into the graph.
Updated Implementation:
pnginfo.js:
```
// Create/update the writeBranchData and getBranchData functions as follows:
function writeBranchData(png, branchJson) {
const md = getPngMetadata(png) || {};
md.brch = branchJson;
writePngMetadata(png, md);
}
function getBranchData(png) {
const md = getPngMetadata(png);
if (!md?.brch) return null;
return md.brch;
}
// Export the new functions
export {
writeBranchData,
getBranchData
};
```
app.js:
```
// Import getBranchData
import { getBranchData } from './pnginfo.js';
// Update the handleFile method
async handleFile(file) {
if (file.type === 'image/png') {
const pngInfo = await getPngMetadata(file);
if (pngInfo) {
const branchData = getBranchData(pngInfo); // Call getBranchData
if (branchData) {
loadLineageBranch(branchData.rootNodeId); // Call loadLineageBranch
} else if (pngInfo.workflow) {
this.loadGraphData(JSON.parse(pngInfo.workflow));
} else if (pngInfo.parameters) {
importA1111(this.graph, pngInfo.parameters);
}
}
} else if (file.type === 'application/json' || file.name?.endsWith('.json')) {
const reader = new FileReader();
reader.onload = () => {
this.loadGraphData(JSON.parse(reader.result));
};
reader.readAsText(file);
} else if (file.name?.endsWith('.latent') || file.name?.endsWith('.safetensors')) {
const info = await getLatentMetadata(file);
if (info.workflow) {
this.loadGraphData(JSON.parse(info.workflow));
}
}
}
// Implement the loadLineageBranch method
function loadLineageBranch(rootId) {
const nodes = [];
function traverse(node) {
nodes.push(node.serialize());
node.inputs.forEach(input => {
const origin = input.link?.origin;
if (origin) traverse(origin);
});
}
const root = graph.getNodeById(rootId);
traverse(root);
graph.configure({ nodes });
}
```
This final implementation incorporates the changes discussed in our conversation. It removes the redundant pngjs import and properly uses the existing pnginfo.js functions to encode and decode PNG metadata. The handleFile method now checks for branch data and calls the loadLineageBranch method accordingly. The loadLineageBranch method is implemented to traverse the graph and load the branch nodes.
In addition to the core implementation, I am open to exploring further enhancements such as:
Providing a user interface option to surface the branch loading feature.
Allowing users to specify the branch root node from the UI.
Exploring more efficient serialization techniques using node IDs instead of full objects.
Extending the functionality to support selectively saving branches to PNGs as well as loading.
Considering the possibility of loading branches across multiple PNGs to handle more complex workflows.
Contributor guide
Assessment
This issue has not been assessed yet.