diff --git a/nodes.py b/nodes.py index 56fa2a9..c987adc 100644 --- a/nodes.py +++ b/nodes.py @@ -54,19 +54,22 @@ def highway_impl(_prompt, _id, _workflow, _way_in, _query, kwargs): # Time to let the magic play out - for param, key in zip(_type["in"], list(kwargs)): - name = param["name"][1:] - _way_in[("data", name)] = kwargs[key] - _way_in[("type", name)] = param["type"] + for key in kwargs: + param = next((param for param in _type["in"] if param["full_name"] == key), None) + _way_in[("data", param["name"][1:])] = kwargs[key] + _way_in[("type", param["name"][1:])] = param["type"] res = [] for elem in _type["out"]: name = elem["name"][1:] + if functools.reduce(lambda data, path: None if data is None else data.get(path, None), ["outputs", name, "links"], _prompt[_id]) is None: + continue + if ( - ("data", name) in _way_in and - elem["type"] == _way_in[("type", name)] # [TODO] Maybe relax the rule a bit? + ("data", name) in _way_in + # elem["type"] == _way_in[("type", name)] # [TODO] Maybe relax the rule a bit? ) or elem["type"] == "*": res.append(_way_in[("data", name)]) else: @@ -1349,12 +1352,12 @@ class ScriptImbue: case _: pass - return (pipe_in, ScriptData({ + return (pipe_in, None if pin_func is None else ScriptData({ "id": _id, "func": pin_func, "order": script_pin_order, "kind": "wrap" - }), ScriptData({ + }), None if res_func is None else ScriptData({ "id": _id, "func": res_func, "order": script_res_order, @@ -1372,10 +1375,6 @@ class ScriptPlan: "script_func": (["_"], ), "script_exec_mode": (["node", "func", "func_list"], ), "script_rule_mode": (["slice", "cycle"], ), - "script_chain_type": ("STRING", { - "default": "", - "multiline": False - }), }, "hidden": { "_id": "UNIQUE_ID", @@ -1537,13 +1536,16 @@ class Script: if _script_in[key](script=_script_in, inst=inst, pin=pin, res=None): inst["id"].append(_script_in[("script", "id", key[2])]) - _script_in[("script", "rule")]( - script=_script_in, inst=inst, pin=pin, res=res, - func=functools.partial( - _script_in.get(("script", "exec"), lambda *args, **kwargs: None), - script=_script_in, inst=inst + if ("script", "rule") in _script_in: + _script_in[("script", "rule")]( + script=_script_in, inst=inst, pin=pin, res=res, + func=functools.partial( + _script_in.get(("script", "exec"), lambda *args, **kwargs: None), + script=_script_in, inst=inst + ) ) - ) + else: + _script_in[("script", "exec")](script=_script_in, inst=inst, pin=pin, res=res) inst["id"].clear() inst["id"].append(_id) @@ -1566,84 +1568,6 @@ class Script: ###################################################################################### -def check_module(): - res = [] - if sys.modules["was-node-suite-comfyui.WAS_Node_Suite"] is not None: - res.extend([ - "-----[WAS Node Suite]-----", - "0246-Highway-Str | WAS-DB-Token-Str", - "WAS-DB-Token-Str | 0246-Highway-Str", - - "0246-Highway | WAS-DB", - "WAS-DB | 0246-Highway", - ]) - if sys.modules["ComfyUI-Inspire-Pack.inspire"] is not None: - res.extend([ - "-----[Inspire Pack]-----", - "0246-Highway | Inspire-Cache", - "Inspire-Cache | 0246-Highway", - "0246-Junction | Inspire-Cache", - "Inspire-Cache | 0246-Junction", - ]) - if sys.modules["ComfyUI-Impact-Pack"] is not None: - res.extend([ - "-----[Impact Pack]-----", - ]) - if sys.modules["ComfyUI_tinyterraNodes"] is not None: - res.extend([ - "-----[tinyterraNodes]-----", - ]) - - # PIPE_LINE - # PIPE_LINE_SDXL - # BASIC_PIPE - # DETAILER_PIPE - # RGTHREE PIPE - - if len(res) == 0: - res.append("UNKNOWN") - return res - -# [WIP] Some secret unfinished node -class Convert: - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "_func": (check_module(), ), - "_mode": (["batch", "pluck"], ), - }, - "optional": { - "_data_in": lib0246.ByPassTypeTuple(("*", )), - }, - "hidden": { - "_prompt": "PROMPT", - "_id": "UNIQUE_ID", - "_workflow": "EXTRA_PNGINFO" - } - } - - RETURN_TYPES = lib0246.ByPassTypeTuple(("*", )) - RETURN_NAMES = lib0246.ByPassTypeTuple(("_data_out", )) - INPUT_IS_LIST = True - FUNCTION = "execute" - CATEGORY = "0246" - - def execute(self, _func = None, _mode = None, **kwargs): - # inspire_module = sys.modules["ComfyUI-Inspire-Pack.inspire.backend_support"] - # print(id(inspire_module)) - # print(id(ext["insp"].inspire.backend_support.cache)) - # print(dir(inspire_module)) - - return { - "ui": { - "text": [""] - }, - "result": [sys.modules["was-node-suite-comfyui.WAS_Node_Suite"].WDB.getDict("custom_tokens")] - } - -###################################################################################### - class Hub: @classmethod def INPUT_TYPES(s): @@ -1682,6 +1606,96 @@ class Hub: "result": [res[i] for i in range(len(res))] } +###################################################################################### +######################################## TODO ######################################## +###################################################################################### + +def check_module(): + res = [] + if sys.modules["was-node-suite-comfyui.WAS_Node_Suite"] is not None: + res.extend([ + "-----[WAS Node Suite]-----", + "0246-Highway-Str | WAS-DB-Token-Str", + "WAS-DB-Token-Str | 0246-Highway-Str", + + "0246-Highway | WAS-DB", + "WAS-DB | 0246-Highway", + ]) + if sys.modules["ComfyUI-Inspire-Pack.inspire"] is not None: + res.extend([ + "-----[Inspire Pack]-----", + "0246-Highway | Inspire-Cache", + "Inspire-Cache | 0246-Highway", + "0246-Junction | Inspire-Cache", + "Inspire-Cache | 0246-Junction", + ]) + if sys.modules["ComfyUI-Impact-Pack"] is not None: + res.extend([ + "-----[Impact Pack]-----", + ]) + if sys.modules["ComfyUI_tinyterraNodes"] is not None: + res.extend([ + "-----[tinyterraNodes]-----", + ]) + + # PIPE_LINE + # PIPE_LINE_SDXL + # BASIC_PIPE + # DETAILER_PIPE + # RGTHREE PIPE + + if len(res) == 0: + res.append("UNKNOWN") + return res + +class Convert: + # [WIP] Some secret unfinished node + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "_func": (check_module(), ), + "_mode": (["batch", "pluck"], ), + }, + "optional": { + "_data_in": lib0246.ByPassTypeTuple(("*", )), + }, + "hidden": { + "_prompt": "PROMPT", + "_id": "UNIQUE_ID", + "_workflow": "EXTRA_PNGINFO" + } + } + + RETURN_TYPES = lib0246.ByPassTypeTuple(("*", )) + RETURN_NAMES = lib0246.ByPassTypeTuple(("_data_out", )) + INPUT_IS_LIST = True + FUNCTION = "execute" + CATEGORY = "0246" + + def execute(self, _func = None, _mode = None, **kwargs): + # inspire_module = sys.modules["ComfyUI-Inspire-Pack.inspire.backend_support"] + # print(id(inspire_module)) + # print(id(ext["insp"].inspire.backend_support.cache)) + # print(dir(inspire_module)) + + return { + "ui": { + "text": [""] + }, + "result": [sys.modules["was-node-suite-comfyui.WAS_Node_Suite"].WDB.getDict("custom_tokens")] + } + +###################################################################################### + +class ScriptPlanEnact: + # For things that require text-based expression, such as string combine, conditioning combine, etc. + # Which allows each operators to associate with a node or func. + # => Require 4 widgets: ops, node, add button, and current code. + # But how do we specify which parameters for which? + pass + ######################################################################################## ######################################## EXPORT ######################################## ######################################################################################## diff --git a/web/js/nodes.js b/web/js/nodes.js index f013cd4..9640967 100644 --- a/web/js/nodes.js +++ b/web/js/nodes.js @@ -3,6 +3,10 @@ import { api } from "../../../scripts/api.js"; import { ComfyWidgets } from "../../../scripts/widgets.js"; import { GroupNodeHandler } from "../../../extensions/core/groupNode.js"; +import { JSONEditor } from "https://cdn.jsdelivr.net/npm/vanilla-jsoneditor/standalone.js"; + +console.log(JSONEditor); + import * as lib0246 from "./utils.js"; const HELP = { @@ -197,7 +201,7 @@ const HELP = { `.replace(/[\t\n]+/g, ''), }; -let defs, type_defs = new Set(); +let defs, node_defs = [], type_defs = new Set(); (async () => { function rgthree_exec(name, ...args) { @@ -218,10 +222,12 @@ let defs, type_defs = new Set(); lib0246.hijack(app, "registerNodesFromDefs", async function (_defs) { defs = _defs; - for (let key in defs) + for (let key in defs) { + node_defs.push(key); for (let idx in defs[key].output) if (!Array.isArray(defs[key].output[idx])) type_defs.add(defs[key].output[idx]); + } type_defs = [...type_defs.values()]; }, () => {}); @@ -3095,7 +3101,8 @@ let defs, type_defs = new Set(); case "0246.Hub": { const Hub = nodeType, HUB_PARENT = Symbol("hub_parent"), - HUB_SOLE = 7; + HUB_SOLE = 7, + PIPE_COMBO = ["HIGHWAY_PIPE", "JUNCTION_PIPE"]; // [TODO] Force tracked node render by hijack app.canvas.computeVisibleNodes and // change getBounding of each nodes to be within app.canvas.visible_area @@ -3105,7 +3112,7 @@ let defs, type_defs = new Set(); const prim_widget = node.addWidget("combo", "base:prim", "INT", () => {}, { serialize: false, - values: ["INT", "FLOAT", "STRING", "BOOLEAN"] + values: ["INT", "FLOAT", "STRING", "BOOLEAN", "__PIPE__", "__BATCH__", "__SCRIPT_DATA__"] }); node.addWidget("button", "Add Sole Primitive Widget", null, () => { node.hubPushWidgetPrim(prim_widget.value); @@ -3133,7 +3140,7 @@ let defs, type_defs = new Set(); const node_widget = node.addWidget("combo", "base:node", "KSampler", () => {}, { serialize: false, - values: Object.keys(defs) + values: node_defs }); node.addWidget("button", "Add Sole Primitive Widgets from Node", null, () => { node.hubPushWidgetNode(node_widget.value); @@ -3205,23 +3212,33 @@ let defs, type_defs = new Set(); if (node.outputs && node.outputs.length > 0) { let count = 0, widget; for (let name in node.hub.data.sole_type) { - const proc_name = name.split(":"), - type_data = node.hub.data.sole_type[name].slice(3, 6); + const proc_name = node.hub.data.sole_type[name], // name.split(":"), + type_data = proc_name.slice(3, 6); switch (proc_name[2]) { case "int": { - widget = node.hubPushWidgetPrim("INT", ...type_data, name); + widget = node.hubPushWidgetPrim("INT", type_data, name); } break; case "float": { - widget = node.hubPushWidgetPrim("FLOAT", ...type_data, name); + widget = node.hubPushWidgetPrim("FLOAT", type_data, name); } break; case "string": { - widget = node.hubPushWidgetPrim("STRING", ...type_data, name); + widget = node.hubPushWidgetPrim("STRING", type_data, name); } break; case "boolean": { - widget = node.hubPushWidgetPrim("BOOLEAN", ...type_data, name); + widget = node.hubPushWidgetPrim("BOOLEAN", type_data, name); } break; case "combo": { - widget = node.hubPushWidgetCombo(...type_data, name); + switch (proc_name[3]) { + case "__PIPE__": { + widget = node.hubPushWidgetComboRaw(PIPE_COMBO, proc_name[3], type_data, name); + } break; + case "__SCRIPT_DATA__": { + widget = node.hubPushWidgetComboRaw(node_defs, proc_name[3], type_data, name); + } break; + default: { + widget = node.hubPushWidgetCombo(...type_data, name); + } break; + } } break; } widget.value = data.widgets_values[HUB_SOLE + 2 + (count ++)]; @@ -3329,19 +3346,27 @@ let defs, type_defs = new Set(); options: {} }, "boolean", "BOOLEAN", ...args); } break; + case "__PIPE__": { + return this.hubPushWidgetComboRaw(PIPE_COMBO, type, ...args); + } break; + case "__SCRIPT_DATA__": { + return this.hubPushWidgetComboRaw(node_defs, type, ...args); + } break; } }; Hub.prototype.hubPushWidgetCombo = function (node_name, part_name, pin_name, full_name) { - const combo_data = defs[node_name].input[part_name][pin_name][0]; + return this.hubPushWidgetComboRaw(defs[node_name].input[part_name][pin_name][0], "COMBO", [node_name, part_name, pin_name], full_name); + }; + Hub.prototype.hubPushWidgetComboRaw = function (combo_data, combo_type, extra_name, full_name) { return this.hubPushWidget({ type: "combo", value: combo_data[0], options: { values: combo_data }, - }, "combo", "COMBO", node_name, part_name, pin_name, full_name); + }, "combo", combo_type, extra_name, full_name); }; Hub.prototype.hubPushWidgetNode = function (node_name, full_name) { @@ -3355,7 +3380,7 @@ let defs, type_defs = new Set(); } }; - Hub.prototype.hubPushWidget = function (widget, id_type, pin_type, node_name, part_name, pin_name, full_name) { + Hub.prototype.hubPushWidget = function (widget, id_type, pin_type, extra_name = [], full_name = "") { if (!this.hub.sole_space) { this.hub.sole_space = SPACE_TITLE_WIDGET(); this.widgets.splice(HUB_SOLE + 1, 0, this.hub.sole_space); @@ -3364,14 +3389,14 @@ let defs, type_defs = new Set(); this.widgets.splice(HUB_SOLE + 2 + this.hub.sole_widget.length, 0, widget); this.hub.sole_widget.push(widget); - if (typeof full_name === "string") + if (full_name.length > 0) widget.name = full_name; else { this.hub.data.sole_name[id_type] = this.hub.data.sole_name[id_type] ?? 0; let list_name = [ "sole", String(this.hub.data.sole_name[id_type] ++), - id_type, node_name, part_name, pin_name, pin_type + id_type, ...extra_name, pin_type ]; full_name = list_name.reduce((a, b) => @@ -3564,4 +3589,4 @@ let defs, type_defs = new Set(); }); // var curr_node = LiteGraph.createNode(LiteGraph.getNodeTypesInCategory(LiteGraph.getNodeTypesCategories()[2])[2].type); -})(); +})(); \ No newline at end of file