commit 33d290cb92273ec62d4458266b4c8a87a49e0a35 Author: bmad4ever Date: Thu Dec 21 19:21:03 2023 +0000 1st commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..4005617 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +## Lists Cartesian Product ( [ComfyUI](https://github.com/comfyanonymous/ComfyUI) custom node ) + +Given a set of lists, the node adjusts them so that when used as input to another node all the possible argument permutations are computed. + +To update the input and output slots, **right-click the node and at the top select the option "update I/Os"**. + + +### Example + +Given the following lists as inputs: + +- ```Positive_Cond_List_: [ A, B, C]``` +- ```Negative_Cond_List_: [ a, b ]``` +- ```__________CFG_List_: [ 5, 7 ]``` + +The outputs are the following: + +- ```Positive_Cond_List_: [ A, A, A, A, B, B, B, B, C, C, C, C]``` +- ```Negative_Cond_List_: [ a, a, b, b, a, a, b, b, a, a, b, b]``` +- ```__________CFG_List_: [ 5, 7, 5, 7, 5, 7, 5, 7, 5, 7, 5, 7]``` + + +### Example Workflow + +*image has workflow embedded* + +![example workflow](/workflows/example.png) \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..ca665da --- /dev/null +++ b/__init__.py @@ -0,0 +1,3 @@ +from .node import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS +WEB_DIRECTORY = "js" +__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"] \ No newline at end of file diff --git a/js/any_cartesian_product.js b/js/any_cartesian_product.js new file mode 100644 index 0000000..e7fb1df --- /dev/null +++ b/js/any_cartesian_product.js @@ -0,0 +1 @@ +import{app as t}from"/scripts/app.js";t.registerExtension({name:"Comfy.Bmad.AnyCartesianProduct",async beforeRegisterNodeDef(t,e,i){if("AnyListCartesianProduct"!==e.name)return;let s=t.prototype.onNodeCreated;t.prototype.onNodeCreated=function(){let t=s?s.apply(this,arguments):void 0;for(let e=this.outputs.length-1;e>=0;e--)"*"===this.outputs[e].name&&this.removeOutput(e);return this.input_type="*",this.output_type="*",t};let p=t.prototype.getExtraMenuOptions;t.prototype.getExtraMenuOptions=function(t,e){let i=p?p.apply(this,arguments):void 0;return e.unshift({content:"update I/Os",callback:()=>{let t=this.widgets.find(t=>"inputs_len"===t.name).value,e=void 0===this.inputs?0:this.inputs.length,i=void 0===this.inputs?0:this.outputs.length;for(let s=0;s0){let p=this.inputs.splice(s,1)[0];console.log(p),this.inputs.splice(0,0,p),this.addInput("x",this.input_type),this.removeInput(this.inputs.length-1)}break}let n=e-1;for(let o=e;o>t;--o)this.removeInput(n--);for(let u=e;ut;--r)this.removeOutput(r-1);for(let h=i;h bool: + return False + + +class AnyListCartesianProduct: + RETURN_TYPES = tuple([AnyType("*") for _ in range(9)]) + FUNCTION = "cart_prod" + CATEGORY = "utils" + OUTPUT_IS_LIST = tuple([True for _ in range(9)]) + INPUT_IS_LIST = True + + @classmethod + def INPUT_TYPES(cls): + return {"required": { + "inputs_len": ("INT", {"default": 2, "min": 2, "max": 9}), + }} + + def cart_prod(self, inputs_len, **kwargs): + values = list(kwargs.values())[:inputs_len[0]] # ignore input names + cp_tuples = list(product(*values)) + return tuple([t[i] for t in cp_tuples] for i in range(inputs_len[0])) + + +NODE_CLASS_MAPPINGS = { + "AnyListCartesianProduct": AnyListCartesianProduct +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "AnyListCartesianProduct": "Lists Cartesian Product" +} diff --git a/workflows/example.png b/workflows/example.png new file mode 100644 index 0000000..d5a2505 Binary files /dev/null and b/workflows/example.png differ