From 62cd748a250e20092d3776f2d11ca0baaeb14dfd Mon Sep 17 00:00:00 2001 From: "Alexander G. Morano" Date: Wed, 19 Jun 2024 09:49:25 -0700 Subject: [PATCH] swap index param for key in dynamic parse for multi-dynamics purz node -- but not. fonts should comp with rgbA was RGB --- core/calc.py | 8 +++---- core/compose.py | 4 ++-- core/create.py | 33 +++++++++++++++++++++++++- core/utility.py | 7 ++++-- res/img/color-e.png | Bin 0 -> 3405 bytes sup/util.py | 32 ++++++++++++++++++------- web/nodes/akashic.js | 2 +- web/nodes/{valuegraph.js => graph.js} | 9 +++++-- web/util/util.js | 4 ++-- 9 files changed, 76 insertions(+), 23 deletions(-) create mode 100644 res/img/color-e.png rename web/nodes/{valuegraph.js => graph.js} (82%) diff --git a/core/calc.py b/core/calc.py index c166fa8..fed40a7 100644 --- a/core/calc.py +++ b/core/calc.py @@ -326,6 +326,7 @@ The Binary Operation node executes binary operations like addition, subtraction, results = [] A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, [None]) B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, [None]) + print(A, '-', B) a_x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, 0) a_xy = parse_param(kw, Lexicon.IN_A+"2", EnumConvertType.VEC2, [(0, 0)]) a_xyz = parse_param(kw, Lexicon.IN_A+"3", EnumConvertType.VEC3, [(0, 0, 0)]) @@ -750,7 +751,6 @@ class TickNode(JOVBaseNode): CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" RETURN_TYPES = (WILDCARD, "FLOAT", "FLOAT", WILDCARD) RETURN_NAMES = (Lexicon.VALUE, Lexicon.LINEAR, Lexicon.FPS, Lexicon.TRIGGER) - # OUTPUT_IS_LIST = (True, True, True, True) DESCRIPTION = """ The `Tick` node acts as a timer and frame counter, emitting pulses or signals based on time intervals or BPM settings. It allows precise synchronization and control over animation sequences, with options to adjust FPS, BPM, and loop points. This node is useful for generating time-based events or driving animations with rhythmic precision. """ @@ -800,7 +800,7 @@ The `Tick` node acts as a timer and frame counter, emitting pulses or signals ba self.__frame = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, self.__frame)[0] if loop != 0: self.__frame %= loop - self.__frame = max(0, self.__frame) + # start_frame = max(0, start_frame) hold = parse_param(kw, Lexicon.WAIT, EnumConvertType.BOOLEAN, False)[0] fps = parse_param(kw, Lexicon.FPS, EnumConvertType.INT, 24, 1)[0] bpm = parse_param(kw, Lexicon.BPM, EnumConvertType.INT, 120, 1)[0] @@ -809,7 +809,7 @@ The `Tick` node acts as a timer and frame counter, emitting pulses or signals ba batch = parse_param(kw, Lexicon.BATCH, EnumConvertType.INT, 1, 1)[0] step_fps = 1. / max(1., float(fps)) reset = parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0] - if parse_reset(ident) > 0 or reset: + if loop == 0 and (parse_reset(ident) > 0 or reset): self.__frame = 0 trigger = None results = Results() @@ -832,7 +832,7 @@ The `Tick` node acts as a timer and frame counter, emitting pulses or signals ba pbar.update_absolute(idx) if batch < 2: comfy_message(ident, "jovi-tick", {"i": self.__frame}) - return results.frame, results.lin, results.fixed, results.trigger + return (results.frame, results.lin, results.fixed, results.trigger,) class ValueNode(JOVBaseNode): NAME = "VALUE (JOV) 🧬" diff --git a/core/compose.py b/core/compose.py index 3ff43da..8bfb2f7 100644 --- a/core/compose.py +++ b/core/compose.py @@ -584,7 +584,7 @@ Combine multiple input images into a single image by summing their pixel values. return Lexicon._parse(d, cls) def run(self, **kw) -> torch.Tensor: - pA = parse_dynamic(kw, 0, EnumConvertType.IMAGE, None) + pA = parse_dynamic(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) #pA = [item for sublist in pA for item in sublist] if len(pA) == 0: logger.error("no images to flatten") @@ -809,7 +809,7 @@ Merge multiple input images into a single composite image by stacking them along return Lexicon._parse(d, cls) def run(self, **kw) -> Tuple[torch.Tensor, torch.Tensor]: - images = parse_dynamic(kw, 0, EnumConvertType.IMAGE, None) + images = parse_dynamic(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) if len(images) == 0: logger.warning("no images to stack") return diff --git a/core/create.py b/core/create.py index 8c07a91..5acdb4d 100644 --- a/core/create.py +++ b/core/create.py @@ -206,7 +206,7 @@ The Text Generation node generates images containing text based on user-defined Lexicon.FONT: (cls.FONT_NAMES, {"default": cls.FONT_NAMES[0]}), Lexicon.LETTER: ("BOOLEAN", {"default": False}), Lexicon.AUTOSIZE: ("BOOLEAN", {"default": False}), - Lexicon.RGBA_A: ("VEC3", {"default": (255, 255, 255, 255), "step": 1, + Lexicon.RGBA_A: ("VEC4", {"default": (255, 255, 255, 255), "step": 1, "label": [Lexicon.R, Lexicon.G, Lexicon.B, Lexicon.A], "rgb": True, "tooltip": "Color of the letters"}), Lexicon.MATTE: ("VEC3", {"default": (0, 0, 0), "step": 1, @@ -426,3 +426,34 @@ The Wave Graph node visualizes audio waveforms as bars. Adjust parameters like t images.append(cv2tensor_full(img)) pbar.update_absolute(idx) return [torch.cat(i, dim=0) for i in list(zip(*images))] + + +''' +class PurzNode(JOVBaseNode): + NAME = "PURZ (JOV) πŸŸͺ" + CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/PURZ" + RETURN_TYPES = ("IMAGE", "IMAGE", "MASK") + RETURN_NAMES = (Lexicon.IMAGE, Lexicon.RGB, Lexicon.MASK) + DESCRIPTION = """ +""" + + @classmethod + def INPUT_TYPES(cls) -> dict: + d = super().INPUT_TYPES() + d.update({ + "optional": { + Lexicon.PIXEL: (WILDCARD, {"tooltip":"πŸ«₯ πŸ₯° 🫳 πŸ“ πŸ˜΅β€πŸ’« πŸ˜ƒ πŸ₯² πŸͺ―"}), + "πŸͺ": (WILDCARD, {"tooltip": "πŸͺ πŸ™‹ πŸ’¬ πŸ˜€ πŸ‡§πŸ‡¦ 🀣 πŸ₯― πŸ‘£ πŸ₯΄ 😍 πŸ…ΎοΈ 🧞 πŸ™Š"}), + Lexicon.WH: ("VEC2", {"default": (512, 512), "tooltip": "πŸ₯― πŸ‘£ πŸ₯° 🫳 πŸ’¬ πŸ₯΄ πŸ˜€ πŸ“"}), + "πŸ™‹": (["😍", "πŸ˜€", "🀣", "πŸ₯΄"], {"default": ["😍"]}), + "πŸ“": ("INT", {"default": 256}), + "🧞": ("INT", {"default": 256}), + "πŸ™Š": ("VEC4", {"default": (255, 255, 255, 255), "step": 1, "rgb": True}) + + } + }) + return Lexicon._parse(d, cls) + + def run(self, **kw) -> Tuple[torch.Tensor, torch.Tensor]: + return () +''' \ No newline at end of file diff --git a/core/utility.py b/core/utility.py index f7555e0..bd50fb1 100644 --- a/core/utility.py +++ b/core/utility.py @@ -163,7 +163,7 @@ Processes a batch of data based on the selected mode, such as merging, picking, self.__seed = None def run(self, **kw) -> Tuple[int, list]: - data_list = parse_dynamic(kw, 0, EnumConvertType.ANY, None) + data_list = parse_dynamic(kw, Lexicon.UNKNOWN, EnumConvertType.ANY, None) mode = parse_param(kw, Lexicon.BATCH_MODE, EnumConvertType.STRING, EnumBatchMode.MERGE.name) index = parse_param(kw, Lexicon.INDEX, EnumConvertType.INT, EnumBatchMode.MERGE.name) slice_range = parse_param(kw, Lexicon.RANGE, EnumConvertType.VEC3INT, [(0, 0, 1)]) @@ -395,10 +395,12 @@ The Graph node visualizes a series of data points over time. It accepts a dynami if parse_reset(ident) > 0 or parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0]: self.__history = [] longest_edge = 0 - dynamic = parse_dynamic(kw, 0, EnumConvertType.FLOAT, 0) + dynamic = parse_dynamic(kw, Lexicon.UNKNOWN, EnumConvertType.FLOAT, 0) # each of the plugs self.__ax.clear() for idx, val in enumerate(dynamic): + logger.debug(idx) + logger.debug(val) if isinstance(val, (set, tuple,)): val = list(val) if not isinstance(val, (list, )): @@ -425,6 +427,7 @@ The Graph node visualizes a series of data points over time. It accepts a dynami return (pil2tensor(image),) ''' +# OLD LOAD BATCH NODE -- add to queue? def run(self, **kw) -> None: q = parse_param(kw, Lexicon.QUEUE, EnumConvertType.STRING, "") mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) diff --git a/res/img/color-e.png b/res/img/color-e.png new file mode 100644 index 0000000000000000000000000000000000000000..d27039df1f983dd4abaf57a1c8cf8e0d2cdc9096 GIT binary patch literal 3405 zcmeHKO>f*p7@nl95?VzVS3A=$T!XZspYPd0;ncX#6dtBSe zIsp!?!~r3G0H{caJ0Qf7LvsWnapiz|=nrW70|1GcU9YK76LR5#*3x=j+s{1j^M1@L z?Z=xNZ>*d>e-;3+(p~Rt0k9~{MX)TF_s_S#7RzJl`a3xQ=bn(i1@QT;rvNzfQ`Flo zwu84k!s7;}JY53yP(>7YJ`;ua4MiXf^GAw9lo~C=2rBs(H+-0=yZFOF+oQWr29Tr9EAv7M38{=k! zX9J|Wu8TAS83q&xnC~YAE@6^im@#x%PO>O1BAzIc5r=%Y@Kqso8bh4cv`Jp&Nn{L_ zI7NCxlQGSJL2x`Yj%##YtnCRemEK1Z=e_-up)Hp4-HfocJ(d&~X3i+7_olnqXc8$U zh>ch*V7U;c*RIkbFL*xWN5oNouA@o4cE)hQvmWQ8S*12-EQ(<@bmjSLQ9}7Re?cm$ zHn0vZn6HYenNYK#uJ`n&r#YVPKylZ!DKrp`KyiUj2Ie&C@1F!31YS4E3!D(v?f9w? z)rcbMwJ>%a%Qm3fVohj=rVU*~x1mExi|NF686y*2Vtm#j6^stCTwNnX2x2X0^i2zf zu0hoMVmx3dO$Ms+x0*H|@hsp}DvXanh`(t9YpAGfM<@ zCZ_M=7auMIu=HZLv)U_f-TU>smBUw;4-cRF{lOnkKYMZO183pPkKz3rw?8A_-u>-+ zAApxn1LaKszM3!d6wJHee{c}q`{m9v3r~J}>dT*(z~dJIxUx83<|&wW!4U@meKK77 Vv;64#UHONnySCB!=CyZk{spLE%-;Y2 literal 0 HcmV?d00001 diff --git a/sup/util.py b/sup/util.py index 792346c..1c4b92d 100644 --- a/sup/util.py +++ b/sup/util.py @@ -54,18 +54,32 @@ class EnumSwizzle(Enum): # === SUPPORT === # ============================================================================= -def parse_dynamic(data:dict, index:int, typ:EnumConvertType, default: Any) -> List[Any]: +def parse_dynamic(data:dict, prefix:str, typ:EnumConvertType, default: Any, with_prefix:bool=False) -> List[Any]: + """Convert iterated input field(s) based on a s into a single compound list of entries. + + The default will just look for all keys as integer: + + #_ + + If prefix is non-null, then the format for the key entry is: + + #__ + + This will return N entries in a list based on the prefix pattern or not. + + """ vals = [] - count = index for k in data: name = k.split('_') - try: val = int(name[0]) - except: continue - val = parse_param(data, k, typ, default) - if not isinstance(val, (list,)): - val = [val] - vals.extend(val) - count += 1 + # do we need the prefix (in the case of more than one dynamic param) + if (not with_prefix and len(name)== 2) or (with_prefix and len(name) == 3 and name[1] != prefix): + # check the index is valid number + try: val = int(name[0]) + except: continue + val = parse_param(data, k, typ, default) + #if not isinstance(val, (list,)): + # val = [val] + vals.append(val) return vals def parse_value(val:Any, typ:EnumConvertType, default: Any, diff --git a/web/nodes/akashic.js b/web/nodes/akashic.js index 60fd3be..a39bd72 100644 --- a/web/nodes/akashic.js +++ b/web/nodes/akashic.js @@ -23,7 +23,7 @@ app.registerExtension({ const onComputeSize = nodeType.prototype.computeSize; nodeType.computeSize = () => { const size = onComputeSize?.apply(this); - console.info(size); + // console.info(size); return [0, 4]; } diff --git a/web/nodes/valuegraph.js b/web/nodes/graph.js similarity index 82% rename from web/nodes/valuegraph.js rename to web/nodes/graph.js index 2581847..d89278f 100644 --- a/web/nodes/valuegraph.js +++ b/web/nodes/graph.js @@ -26,7 +26,8 @@ app.registerExtension({ if (nodeData.name !== _id) { return; } - nodeType = node_add_dynamic(nodeType, _prefix, "*", 7); + nodeType = node_add_dynamic(nodeType, _prefix); + const onNodeCreated = nodeType.prototype.onNodeCreated; nodeType.prototype.onNodeCreated = async function () { const me = onNodeCreated?.apply(this); @@ -49,8 +50,12 @@ app.registerExtension({ for (let i = 0; i < this.inputs.length; i++) { const link_id = this.inputs[i].link; const link = app.graph.links[link_id]; - if(link && this.inputs[i].name.substring(0, _prefix.length) === _prefix) { + const nameParts = this.inputs[i].name.split('_'); + const isInteger = nameParts.length > 1 && !isNaN(nameParts[0]) && Number.isInteger(parseFloat(nameParts[0])); + if (link && isInteger && nameParts[1].substring(0, _prefix.length) === _prefix) { + //if(link && this.inputs[i].name.substring(0, _prefix.length) === _prefix) { link.type = `JOV_VG_${count}`; + console.info(count) this.inputs[i].color_on = LGraphCanvas.link_type_colors[link.type]; count += 1; } diff --git a/web/util/util.js b/web/util/util.js index 845d61a..28477b8 100644 --- a/web/util/util.js +++ b/web/util/util.js @@ -77,7 +77,7 @@ export function node_add_dynamic(nodeType, prefix, dynamic_type='*', index_start let count = self.inputs.length; while (idx < self.inputs.length-1 && count > 0) { const slot = self.inputs[idx]; - console.info(slot, count) + // console.info(slot, count) if (slot) { const parts = slot.name.split('_'); // a dynamic jovian slot prefix_ @@ -101,7 +101,7 @@ export function node_add_dynamic(nodeType, prefix, dynamic_type='*', index_start } count -= 1; } - console.info(idx) + //console.info(idx) } index_start = Math.max(0, index_start);