From 2baba1e4c2e4ae5ef0ff485ce0c6cfd4fd6d7989 Mon Sep 17 00:00:00 2001 From: "Alexander G. Morano" Date: Sun, 4 May 2025 23:48:55 -0400 Subject: [PATCH] Lexicon updated to come from comfy_cozy --- core/__init__.py | 7 + core/anim.py | 117 +++++++------- core/calc.py | 335 +++++++++++++++++++---------------------- core/color.py | 224 ++++++++++++--------------- core/compose.py | 333 ++++++++++++++++++---------------------- core/create.py | 281 +++++++++++----------------------- core/trans.py | 205 ++++++++++++------------- core/utility/batch.py | 130 ++++++++-------- core/utility/info.py | 30 ++-- core/utility/io.py | 131 ++++++++-------- core/vars.py | 206 ++++++++++--------------- web/nodes/delay.js | 4 +- web/nodes/graph.js | 2 +- web/nodes/lerp.js | 8 +- web/nodes/op_binary.js | 4 +- web/nodes/op_unary.js | 2 +- web/nodes/queue.js | 12 +- web/nodes/tick.js | 4 +- web/nodes/value.js | 4 +- 19 files changed, 882 insertions(+), 1157 deletions(-) diff --git a/core/__init__.py b/core/__init__.py index e69de29..720bd12 100644 --- a/core/__init__.py +++ b/core/__init__.py @@ -0,0 +1,7 @@ + +from enum import Enum + +class EnumFillOperation(Enum): + DEFAULT = 0 + FILL_ZERO = 20 + FILL_ALL = 10 diff --git a/core/anim.py b/core/anim.py index 2db293c..a16fb3f 100644 --- a/core/anim.py +++ b/core/anim.py @@ -12,6 +12,9 @@ from cozy_comfyui import \ InputType, EnumConvertType, \ deep_merge, parse_param, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_ANY, \ CozyBaseNode @@ -61,47 +64,46 @@ A timer and frame counter, emitting pulses or signals based on time intervals. I d = deep_merge(d, { "optional": { # data to pass on a pulse of the loop - "TRIGGER": (COZY_TYPE_ANY, { + Lexicon.TRIGGER: (COZY_TYPE_ANY, { "default": None, - "tooltip":"Output to send when beat (BPM setting) is hit" + "tooltip": "Output to send when beat (BPM setting) is hit" }), # forces a MOD on CYCLE - "VALUE": ("INT", { + Lexicon.VALUE: ("INT", { "default": 0, "min": 0, "max": sys.maxsize, - "tooltip": "the current frame number of the tick" + "tooltip": "Current frame number of the tick" }), - "LOOP": ("INT", { + Lexicon.LOOP: ("INT", { "default": 0, "min": 0, "max": sys.maxsize, - "tooltip": "number of frames before looping starts. 0 means continuous playback (no loop point)" + "tooltip": "Number of frames before looping starts. 0 means continuous playback (no loop point)" }), - "FPS": ("INT", { - "default": 24, "min": 1, - "tooltip": "Fixed frame step rate based on FPS (1/FPS)" + Lexicon.FPS: ("INT", { + "default": 24, "min": 1 }), - "BPM": ("INT", { + Lexicon.BPM: ("INT", { "default": 120, "min": 1, "max": 60000, "tooltip": "BPM trigger rate to send the input. If input is empty, TRUE is sent on trigger" }), - "NOTE": ("INT", { + Lexicon.NOTE: ("INT", { "default": 4, "min": 1, "max": 256, - "tooltip":"Number of beats per measure. Quarter note is 4, Eighth is 8, 16 is 16, etc."}), + "tooltip": "Number of beats per measure. Quarter note is 4, Eighth is 8, 16 is 16, etc."}), # stick the current "count" - "HOLD": ("BOOLEAN", { + Lexicon.HOLD: ("BOOLEAN", { "default": False}), # manual total = 0 - "RESET": ("BOOLEAN", { + Lexicon.RESET: ("BOOLEAN", { "default": False}), # how many frames to dump.... - "BATCH": ("INT", { + Lexicon.BATCH: ("INT", { "default": 1, "min": 1, "max": 32767, "tooltip": "Number of frames wanted" }), - "STEP": ("INT", { + Lexicon.STEP: ("INT", { "default": 0, "min": 0, "max": sys.maxsize }), } }) - return d + return Lexicon._parse(d) def __init__(self, *arg, **kw) -> None: super().__init__(*arg, **kw) @@ -109,21 +111,21 @@ A timer and frame counter, emitting pulses or signals based on time intervals. I self.__frame = 0 def run(self, ident, **kw) -> tuple[int, float, float, Any]: - passthru = parse_param(kw, "TRIGGER", EnumConvertType.ANY, None)[0] - stride = parse_param(kw, "STEP", EnumConvertType.INT, 0, 0, sys.maxsize)[0] - loop = parse_param(kw, "LOOP", EnumConvertType.INT, 0, 0, sys.maxsize)[0] - self.__frame = parse_param(kw, "VALUE", EnumConvertType.INT, self.__frame, 0, sys.maxsize)[0] + passthru = parse_param(kw, Lexicon.TRIGGER, EnumConvertType.ANY, None)[0] + stride = parse_param(kw, Lexicon.STEP, EnumConvertType.INT, 0, 0, sys.maxsize)[0] + loop = parse_param(kw, Lexicon.LOOP, EnumConvertType.INT, 0, 0, sys.maxsize)[0] + self.__frame = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, self.__frame, 0, sys.maxsize)[0] if loop != 0: self.__frame %= loop # start_frame = max(0, start_frame) - hold = parse_param(kw, "HOLD", EnumConvertType.BOOLEAN, False)[0] - fps = parse_param(kw, "FPS", EnumConvertType.INT, 24, 1)[0] - bpm = parse_param(kw, "BPM", EnumConvertType.INT, 120, 1)[0] - divisor = parse_param(kw, "NOTE", EnumConvertType.INT, 4, 1)[0] + hold = parse_param(kw, Lexicon.HOLD, 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] + divisor = parse_param(kw, Lexicon.NOTE, EnumConvertType.INT, 4, 1)[0] beat = 60. / max(1., bpm) / divisor - batch = parse_param(kw, "BATCH", EnumConvertType.INT, 1, 1)[0] + batch = parse_param(kw, Lexicon.BATCH, EnumConvertType.INT, 1, 1)[0] step_fps = 1. / max(1., float(fps)) - reset = parse_param(kw, "RESET", EnumConvertType.BOOLEAN, False)[0] + reset = parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0] if loop == 0 and (parse_reset(ident) > 0 or reset): self.__frame = 0 trigger = None @@ -172,33 +174,33 @@ Value generator with normalized values based on based on time interval. d = deep_merge(d, { "optional": { # forces a MOD on CYCLE - "VALUE": ("INT", { + Lexicon.VALUE: ("INT", { "default": 0, "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "Starting value of the tick" }), # interval between frames - "STEP": ("FLOAT", { + Lexicon.STEP: ("FLOAT", { "default": 0, "min": -sys.maxsize, "max": sys.maxsize, "precision": 3, "tooltip": "Amount to add to each frame per tick" }), - "LOOP": ("INT", { + Lexicon.LOOP: ("INT", { "default": 0, "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "What value before looping starts. 0 means linear playback (no loop point)" }), # how many frames to dump.... - "BATCH": ("INT", { + Lexicon.BATCH: ("INT", { "default": 1, "min": 1, "max": 1500, "tooltip": "Total frames wanted" }), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[int, float|int]: - value = parse_param(kw, "VALUE", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize)[0] - step = parse_param(kw, "STEP", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)[0] - loop = parse_param(kw, "LOOP", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize)[0] - batch = parse_param(kw, "BATCH", EnumConvertType.INT, 1, 1, 1500)[0] + value = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize)[0] + step = parse_param(kw, Lexicon.STEP, EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize)[0] + loop = parse_param(kw, Lexicon.LOOP, EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize)[0] + batch = parse_param(kw, Lexicon.BATCH, EnumConvertType.INT, 1, 1, 1500)[0] if loop == 0: loop = batch @@ -230,38 +232,35 @@ Produce waveforms like sine, square, or sawtooth with adjustable frequency, ampl d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "WAVE": (EnumWave._member_names_, { + Lexicon.WAVE: (EnumWave._member_names_, { "default": EnumWave.SIN.name}), - "FREQ": ("FLOAT", { - "default": 1, "min": 0, "max": sys.maxsize, "step": 0.01, - "tooltip": "Frequency"}), - "AMP": ("FLOAT", { - "default": 1, "min": 0, "max": sys.maxsize, "step": 0.01, - "tooltip": "Amplitude"}), - "PHASE": ("FLOAT", { + Lexicon.FREQ: ("FLOAT", { + "default": 1, "min": 0, "max": sys.maxsize, "step": 0.01,}), + Lexicon.AMP: ("FLOAT", { + "default": 1, "min": 0, "max": sys.maxsize, "step": 0.01,}), + Lexicon.PHASE: ("FLOAT", { "default": 0, "min": 0.0, "max": 1.0, "step": 0.01}), - "OFFSET": ("FLOAT", { + Lexicon.OFFSET: ("FLOAT", { "default": 0, "min": 0.0, "max": 1.0, "step": 0.001}), - "TIME": ("FLOAT", { + Lexicon.TIME: ("FLOAT", { "default": 0, "min": 0, "max": sys.maxsize, "step": 0.0001}), - "INVERT": ("BOOLEAN", { + Lexicon.INVERT: ("BOOLEAN", { "default": False}), - "ABSOLUTE": ("BOOLEAN", { - "default": False, - "tooltips": "Return the absolute value of the input"}), + Lexicon.ABSOLUTE: ("BOOLEAN", { + "default": False,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[float, int]: - op = parse_param(kw, "WAVE", EnumWave, EnumWave.SIN.name) - freq = parse_param(kw, "FREQ", EnumConvertType.FLOAT, 1., 0.000001, sys.maxsize) - amp = parse_param(kw, "AMP", EnumConvertType.FLOAT, 1., 0., sys.maxsize) - phase = parse_param(kw, "PHASE", EnumConvertType.FLOAT, 0.) - shift = parse_param(kw, "OFFSET", EnumConvertType.FLOAT, 0.) - delta_time = parse_param(kw, "TIME", EnumConvertType.FLOAT, 0., 0., sys.maxsize) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) - absolute = parse_param(kw, "ABSOLUTE", EnumConvertType.BOOLEAN, False) + op = parse_param(kw, Lexicon.WAVE, EnumWave, EnumWave.SIN.name) + freq = parse_param(kw, Lexicon.FREQ, EnumConvertType.FLOAT, 1., 0.000001, sys.maxsize) + amp = parse_param(kw, Lexicon.AMP, EnumConvertType.FLOAT, 1., 0., sys.maxsize) + phase = parse_param(kw, Lexicon.PHASE, EnumConvertType.FLOAT, 0.) + shift = parse_param(kw, Lexicon.OFFSET, EnumConvertType.FLOAT, 0.) + delta_time = parse_param(kw, Lexicon.TIME, EnumConvertType.FLOAT, 0., 0., sys.maxsize) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) + absolute = parse_param(kw, Lexicon.ABSOLUTE, EnumConvertType.BOOLEAN, False) results = [] params = list(zip_longest_fill(op, freq, amp, phase, shift, delta_time, invert, absolute)) pbar = ProgressBar(len(params)) diff --git a/core/calc.py b/core/calc.py index efd7b97..4a1d6e7 100644 --- a/core/calc.py +++ b/core/calc.py @@ -8,7 +8,6 @@ from typing import Any, List from collections import Counter import torch -import numpy as np from scipy.special import gamma from comfy.utils import ProgressBar @@ -18,10 +17,16 @@ from cozy_comfyui import \ TensorType, InputType, EnumConvertType, \ deep_merge, parse_dynamic, parse_param, parse_value, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_ANY, COZY_TYPE_NUMERICAL, COZY_TYPE_FULL, \ CozyBaseNode +from . import \ + EnumFillOperation + from ..sup.anim import \ EnumEase, \ ease_op @@ -233,17 +238,22 @@ IMAGE and MASK will return a TRUE bit for any non-black pixel, as a stream of bi d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "VALUE": (COZY_TYPE_FULL, {"default": None, "tooltip":"the value to convert into bits"}), - "BITS": ("INT", {"default": 8, "min": 1, "max": 64, "tooltip":"number of output bits requested"}), - "MSB": ("BOOLEAN", {"default": False, "tooltip":"return the most signifigant bits (True) or least signifigant bits first"}) + Lexicon.VALUE: (COZY_TYPE_FULL, { + "default": None, + "tooltip": "Value to convert into bits"}), + Lexicon.BIT: ("INT", { + "default": 8, "min": 1, "max": 64, + "tooltip": "Number of output bits requested"}), + Lexicon.MSB: ("BOOLEAN", { + "default": False}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[List[int], List[bool]]: - value = parse_param(kw, "VALUE", EnumConvertType.ANY, 0) - bits = parse_param(kw, "BITS", EnumConvertType.INT, 8, 1, 64) - msb = parse_param(kw, "MSB", EnumConvertType.INT, False) + value = parse_param(kw, Lexicon.VALUE, EnumConvertType.ANY, 0) + bits = parse_param(kw, Lexicon.BIT, EnumConvertType.INT, 8, 1, 64) + msb = parse_param(kw, Lexicon.MSB, EnumConvertType.INT, False) params = list(zip_longest_fill(value, bits)) pbar = ProgressBar(len(params)) results = [] @@ -288,45 +298,44 @@ Evaluates two inputs (A and B) with a specified comparison operators and optiona d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "A": (COZY_TYPE_FULL, { + Lexicon.IN_A: (COZY_TYPE_FULL, { "default": 0, "tooltip":"First value to compare"}), - "B": (COZY_TYPE_FULL, { + Lexicon.IN_B: (COZY_TYPE_FULL, { "default": 0, "tooltip":"Second value to compare"}), - "PASS": (COZY_TYPE_ANY, { + Lexicon.SUCCESS: (COZY_TYPE_ANY, { "default": 0, - "tooltip": "Passed to OUT on a successful condition"}), - "FAIL": (COZY_TYPE_ANY, { + "tooltip": "Sent to OUT on a successful condition"}), + Lexicon.FAIL: (COZY_TYPE_ANY, { "default": 0, - "tooltip": "Passed to OUT on a failure condition"}), - "COMPARE": (EnumComparison._member_names_, { + "tooltip": "Sent to OUT on a failure condition"}), + Lexicon.FUNCTION: (EnumComparison._member_names_, { "default": EnumComparison.EQUAL.name, "tooltip": "Comparison function. Sends the data in PASS on successful comparison to OUT, otherwise sends the value in FAIL"}), - "FLIP": ("BOOLEAN", { + Lexicon.SWAP: ("BOOLEAN", { + "default": False,}), + Lexicon.INVERT: ("BOOLEAN", { "default": False, - "tooltip": "Reverse the inputs A and B"}), - "INVERT": ("BOOLEAN", { - "default": False, - "tooltip": "Reverse the successful and failure inputs"}), + "tooltip": "Reverse the PASS and FAIL inputs"}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[Any, Any]: - A = parse_param(kw, "A", EnumConvertType.ANY, 0) - B = parse_param(kw, "B", EnumConvertType.ANY, 0) - size = max(len(A), len(B)) - good = parse_param(kw, "PASS", EnumConvertType.ANY, 0)[:size] - fail = parse_param(kw, "FAIL", EnumConvertType.ANY, 0)[:size] - op = parse_param(kw, "COMPARE", EnumComparison, EnumComparison.EQUAL.name)[:size] - flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False)[:size] - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False)[:size] - params = list(zip_longest_fill(A, B, good, fail, op, flip, invert)) + in_a = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, 0) + in_b = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, 0) + size = max(len(in_a), len(in_b)) + good = parse_param(kw, Lexicon.SUCCESS, EnumConvertType.ANY, 0)[:size] + fail = parse_param(kw, Lexicon.FAIL, EnumConvertType.ANY, 0)[:size] + op = parse_param(kw, Lexicon.FUNCTION, EnumComparison, EnumComparison.EQUAL.name)[:size] + swap = parse_param(kw, Lexicon.SWAP, EnumConvertType.BOOLEAN, False)[:size] + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False)[:size] + params = list(zip_longest_fill(in_a, in_b, good, fail, op, swap, invert)) pbar = ProgressBar(len(params)) vals = [] results = [] - for idx, (A, B, good, fail, op, flip, invert) in enumerate(params): + for idx, (A, B, good, fail, op, swap, invert) in enumerate(params): if not isinstance(A, (tuple, list,)): A = [A] if not isinstance(B, (tuple, list,)): @@ -343,7 +352,7 @@ Evaluates two inputs (A and B) with a specified comparison operators and optiona if not isinstance(val_b, (list,)): val_b = [val_b] - if flip: + if swap: val_a, val_b = val_b, val_a match op: @@ -406,7 +415,7 @@ class LerpNode(CozyBaseNode): NAME = "LERP (JOV) 🔰" CATEGORY = JOV_CATEGORY RETURN_TYPES = (COZY_TYPE_ANY,) - RETURN_NAMES = ("🦄",) + RETURN_NAMES = ("❔",) OUTPUT_IS_LIST = (True,) OUTPUT_TOOLTIPS = ( f"Output can vary depending on the type chosen in the {"TYPE"} parameter" @@ -426,47 +435,40 @@ Additionally, you can specify the easing function (EASE) and the desired output names_convert = EnumConvertType._member_names_[:6] d = deep_merge(d, { "optional": { - "A": (COZY_TYPE_FULL, { - "tooltip": "Custom Start Point" - }), - "B": (COZY_TYPE_FULL, { - "tooltip": "Custom End Point" - }), - "ALPHA": ("VEC4", { - "default": (0.5, 0.5, 0.5, 0.5), "mij": 0., "maj": 1.0, - "tooltip": "Blend Amount. 0 = full A, 1 = full B" - }), - "AA": ("VEC4", { - "default": (0, 0, 0, 0), - "tooltip":"default value vector for A" - }), - "BB": ("VEC4", { - "default": (1,1,1,1), - "tooltip":"default value vector for B" - }), - "TYPE": (names_convert, { + Lexicon.IN_A: (COZY_TYPE_FULL, { + "tooltip": "Custom Start Point"}), + Lexicon.IN_B: (COZY_TYPE_FULL, { + "tooltip": "Custom End Point"}), + Lexicon.ALPHA: ("VEC4", { + "default": (0.5, 0.5, 0.5, 0.5), "mij": 0., "maj": 1.0,}), + Lexicon.TYPE: (names_convert, { "default": "FLOAT", - "tooltip":"Output type desired from resultant operation" - }), - "EASE": (["NONE"] + EnumEase._member_names_, { - "default": "NONE" - }), + "tooltip": "Output type desired from resultant operation"}), + Lexicon.EASE: (["NONE"] + EnumEase._member_names_, { + "default": "NONE"}), + Lexicon.DEFAULT_A: ("VEC4", { + "default": (0, 0, 0, 0)}), + Lexicon.DEFAULT_B: ("VEC4", { + "default": (1,1,1,1)}), + Lexicon.FILL: (EnumFillOperation._member_names_, { + "default": EnumFillOperation.DEFAULT.name}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[Any, Any]: - A = parse_param(kw, "A", EnumConvertType.ANY, 0) - B = parse_param(kw, "B", EnumConvertType.ANY, 0) - a_xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, (0, 0, 0, 0)) - b_xyzw = parse_param(kw, "BB", EnumConvertType.VEC4, (1, 1, 1, 1)) - alpha = parse_param(kw, "FLOAT",EnumConvertType.VEC4, (0.5,0.5,0.5,0.5), 0, 1) - op = parse_param(kw, "EASE", EnumEase, EnumEase.SIN_IN_OUT.name) - typ = parse_param(kw, "TYPE", EnumNumberType, EnumNumberType.FLOAT.name) + A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, 0) + B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, 0) + alpha = parse_param(kw, Lexicon.ALPHA,EnumConvertType.VEC4, (0.5,0.5,0.5,0.5), 0, 1) + typ = parse_param(kw, Lexicon.TYPE, EnumNumberType, EnumNumberType.FLOAT.name) + op = parse_param(kw, Lexicon.EASE, EnumEase, EnumEase.SIN_IN_OUT.name) + a_xyzw = parse_param(kw, Lexicon.DEFAULT_A, EnumConvertType.VEC4, (0, 0, 0, 0)) + b_xyzw = parse_param(kw, Lexicon.DEFAULT_B, EnumConvertType.VEC4, (1, 1, 1, 1)) + fill = parse_param(kw, Lexicon.FILL, EnumConvertType.BOOLEAN, False) values = [] - params = list(zip_longest_fill(A, B, a_xyzw, b_xyzw, alpha, op, typ)) + params = list(zip_longest_fill(A, B, alpha, typ, op, a_xyzw, b_xyzw, fill,)) pbar = ProgressBar(len(params)) - for idx, (A, B, a_xyzw, b_xyzw, alpha, op, typ) in enumerate(params): + for idx, (A, B, alpha, typ, op, a_xyzw, b_xyzw, fill,) in enumerate(params): size = int(typ.value / 10) if A is None: @@ -528,39 +530,36 @@ Perform single function operations like absolute value, mean, median, mode, magn typ = EnumConvertType._member_names_[:6] d = deep_merge(d, { "optional": { - "A": (COZY_TYPE_NUMERICAL, { + Lexicon.IN_A: (COZY_TYPE_NUMERICAL, { "default": None}), - "FUNCTION": (EnumUnaryOperation._member_names_, { + Lexicon.FUNCTION: (EnumUnaryOperation._member_names_, { "default": EnumUnaryOperation.ABS.name}), - "TYPE": (typ, { - "default": EnumConvertType.FLOAT.name, - "tooltip":"Take the input and convert it into the selected type"}), - "FILL": ("BOOLEAN", { - "default": False, - "tooltip":"If the value should fill the output type (VEC*)"}), + Lexicon.TYPE: (typ, { + "default": EnumConvertType.FLOAT.name,}), + Lexicon.DEFAULT_A: ("VEC4", { + "default": (0,0,0,0), + "label": ["X", "Y", "Z", "W"]}), + Lexicon.FILL: (EnumFillOperation._member_names_, { + "default": EnumFillOperation.DEFAULT.name}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[bool]: results = [] - A = parse_param(kw, "A", EnumConvertType.ANY, 0) - op = parse_param(kw, "FUNCTION", EnumUnaryOperation, EnumUnaryOperation.ABS.name) - out = parse_param(kw, "TYPE", EnumConvertType, EnumConvertType.FLOAT.name) - fill = parse_param(kw, "FILL", EnumConvertType.BOOLEAN, False) - params = list(zip_longest_fill(A, op, out, fill)) + A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, 0) + op = parse_param(kw, Lexicon.FUNCTION, EnumUnaryOperation, EnumUnaryOperation.ABS.name) + out = parse_param(kw, Lexicon.TYPE, EnumConvertType, EnumConvertType.FLOAT.name) + a_xyzw = parse_param(kw, Lexicon.DEFAULT_A, EnumConvertType.VEC4, (0, 0, 0, 0)) + fill = parse_param(kw, Lexicon.FILL, EnumConvertType.BOOLEAN, False) + params = list(zip_longest_fill(A, op, out, a_xyzw, fill)) pbar = ProgressBar(len(params)) - for idx, (A, op, out, fill) in enumerate(params): - typ = EnumConvertType.FLOAT - if isinstance(A, (bool, )): - typ = EnumConvertType.BOOLEAN - elif isinstance(A, (list, set, tuple,)): - typ = EnumConvertType(len(A) * 10) - - val = parse_value(A, typ, 0) - if not isinstance(val, (list, tuple, )): - val = [val] - val = [float(v) for v in val] + for idx, (A, op, out, a_xyzw, fill) in enumerate(params): + size = min(3, max(0 if not isinstance(A, (list,)) else len(A))) + best_type = [EnumConvertType.FLOAT, EnumConvertType.VEC2, EnumConvertType.VEC3, EnumConvertType.VEC4][size] + val = parse_value(A, best_type, a_xyzw) + val = parse_value(val, EnumConvertType.VEC4, a_xyzw) + # val = [float(v) for v in val] match op: case EnumUnaryOperation.MEAN: val = [sum(val) / len(val)] @@ -626,62 +625,57 @@ Execute binary operations like addition, subtraction, multiplication, division, d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "A": (COZY_TYPE_NUMERICAL, { - "default": None, - "tooltip":"Passes a raw value directly, or supplies defaults for any value inputs without connections"}), - "B": (COZY_TYPE_NUMERICAL, { - "default": None, - "tooltip":"Passes a raw value directly, or supplies defaults for any value inputs without connections"}), - "FUNCTION": (EnumBinaryOperation._member_names_, { - "default": EnumBinaryOperation.ADD.name, - "tooltip":"Arithmetic operation to perform"}), - "TYPE": (names_convert, { + Lexicon.IN_A: (COZY_TYPE_NUMERICAL, { + "default": None}), + Lexicon.IN_B: (COZY_TYPE_NUMERICAL, { + "default": None}), + Lexicon.FUNCTION: (EnumBinaryOperation._member_names_, { + "default": EnumBinaryOperation.ADD.name,}), + Lexicon.TYPE: (names_convert, { "default": names_convert[2], "tooltip":"Output type desired from resultant operation"}), - "FLIP": ("BOOLEAN", { + Lexicon.SWAP: ("BOOLEAN", { "default": False}), - "AA": ("VEC4", { + Lexicon.DEFAULT_A: ("VEC4", { "default": (0,0,0,0), - "label": ["X", "Y", "Z", "W"], - "tooltip":"value vector"}), - "BB": ("VEC4", { + "label": ["X", "Y", "Z", "W"]}), + Lexicon.DEFAULT_B: ("VEC4", { "default": (0,0,0,0), - "label": ["X", "Y", "Z", "W"], - "tooltip":"value vector"}), + "label": ["X", "Y", "Z", "W"]}), + Lexicon.FILL: (EnumFillOperation._member_names_, { + "default": EnumFillOperation.DEFAULT.name}), + } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[bool]: results = [] - A = parse_param(kw, "A", EnumConvertType.ANY, None) - B = parse_param(kw, "B", EnumConvertType.ANY, None) - a_xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, (0, 0, 0, 0)) - b_xyzw = parse_param(kw, "BB", EnumConvertType.VEC4, (0, 0, 0, 0)) - op = parse_param(kw, "FUNCTION", EnumBinaryOperation, EnumBinaryOperation.ADD.name) - typ = parse_param(kw, "TYPE", EnumConvertType, EnumConvertType.FLOAT.name) - flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False) - params = list(zip_longest_fill(A, B, a_xyzw, b_xyzw, op, typ, flip)) + A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, None) + B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, None) + op = parse_param(kw, Lexicon.FUNCTION, EnumBinaryOperation, EnumBinaryOperation.ADD.name) + typ = parse_param(kw, Lexicon.TYPE, EnumConvertType, EnumConvertType.FLOAT.name) + swap = parse_param(kw, Lexicon.SWAP, EnumConvertType.BOOLEAN, False) + a_xyzw = parse_param(kw, Lexicon.DEFAULT_A, EnumConvertType.VEC4, (0, 0, 0, 0)) + b_xyzw = parse_param(kw, Lexicon.DEFAULT_B, EnumConvertType.VEC4, (0, 0, 0, 0)) + fill = parse_param(kw, Lexicon.FILL, EnumConvertType.BOOLEAN, False) + params = list(zip_longest_fill(A, B, a_xyzw, b_xyzw, op, typ, swap, fill)) pbar = ProgressBar(len(params)) - for idx, (A, B, a_xyzw, b_xyzw, op, typ, flip) in enumerate(params): + for idx, (A, B, a_xyzw, b_xyzw, op, typ, swap, fill) in enumerate(params): size = min(3, max(0 if not isinstance(A, (list,)) else len(A), 0 if not isinstance(B, (list,)) else len(B))) best_type = [EnumConvertType.FLOAT, EnumConvertType.VEC2, EnumConvertType.VEC3, EnumConvertType.VEC4][size] - print(type(A), type(B), A, B, a_xyzw) val_a = parse_value(A, best_type, a_xyzw) - print(val_a) - return val_a = parse_value(val_a, EnumConvertType.VEC4, a_xyzw) val_b = parse_value(B, best_type, b_xyzw) val_b = parse_value(val_b, EnumConvertType.VEC4, b_xyzw) - print(val_a, val_b) - #val_a = parse_value(A, EnumConvertType.VEC4, A if A is not None else a_xyzw) #val_b = parse_value(B, EnumConvertType.VEC4, B if B is not None else b_xyzw) - if flip: + if swap: val_a, val_b = val_b, val_a - #size = max(1, int(typ.value / 10)) + + size = max(1, int(typ.value / 10)) val_a = val_a[:size+1] val_b = val_b[:size+1] @@ -756,10 +750,11 @@ Execute binary operations like addition, subtraction, multiplication, division, default = val if len(val) == 0: default = [0] + val = parse_value(val, typ, default) results.append(val) pbar.update_absolute(idx) - return results + return (results,) class StringerNode(CozyBaseNode): NAME = "STRINGER (JOV) 🪀" @@ -778,34 +773,32 @@ Manipulate strings through filtering d = deep_merge(d, { "optional": { # split, join, replace, trim/lift - "FUNCTION": (EnumConvertString._member_names_, { - "default": EnumConvertString.SPLIT.name, - "tooltip":"Operation to perform on the input string"}), - "KEY": ("STRING", { + Lexicon.FUNCTION: (EnumConvertString._member_names_, { + "default": EnumConvertString.SPLIT.name}), + Lexicon.KEY: ("STRING", { "default":"", "dynamicPrompt":False, - "tooltip":"Delimiter (SPLIT/JOIN) or string to use as search string (FIND/REPLACE)."}), - "REPLACE": ("STRING", { + "tooltip": "Delimiter (SPLIT/JOIN) or string to use as search string (FIND/REPLACE)."}), + Lexicon.REPLACE: ("STRING", { "default":"", "dynamicPrompt":False}), - "RANGE": ("VEC3", { + Lexicon.RANGE: ("VEC3", { "default":(0, -1, 1), "int": True, - "tooltip":"Start, End and Step. Values will clip to the actual list size(s)."}), + "tooltip": "Start, End and Step. Values will clip to the actual list size(s)."}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[TensorType, ...]: # turn any all inputs into the - data_list = parse_dynamic(kw, "STRING", EnumConvertType.ANY, "") + data_list = parse_dynamic(kw, Lexicon.STRING, EnumConvertType.ANY, "") if data_list is None: logger.warn("no data for list") return ([], 0) - op = parse_param(kw, "FUNCTION", EnumConvertString, EnumConvertString.SPLIT.name)[0] - key = parse_param(kw, "KEY", EnumConvertType.STRING, "")[0] - replace = parse_param(kw, "REPLACE", EnumConvertType.STRING, "")[0] - stenst = parse_param(kw, "RANGE", EnumConvertType.VEC3INT, (0, -1, 1))[0] + op = parse_param(kw, Lexicon.FUNCTION, EnumConvertString, EnumConvertString.SPLIT.name)[0] + key = parse_param(kw, Lexicon.KEY, EnumConvertType.STRING, "")[0] + replace = parse_param(kw, Lexicon.REPLACE, EnumConvertType.STRING, "")[0] + stenst = parse_param(kw, Lexicon.RANGE, EnumConvertType.VEC3INT, (0, -1, 1))[0] results = [] - print(data_list) match op: case EnumConvertString.SPLIT: results = data_list @@ -837,7 +830,7 @@ class SwizzleNode(CozyBaseNode): NAME = "SWIZZLE (JOV) 😵" CATEGORY = JOV_CATEGORY RETURN_TYPES = (COZY_TYPE_ANY,) - RETURN_NAMES = ("🦄",) + RETURN_NAMES = ("❔",) OUTPUT_IS_LIST = (True,) SORT = 40 DESCRIPTION = """ @@ -850,44 +843,32 @@ Swap components between two vectors based on specified swizzle patterns and valu names_convert = EnumConvertType._member_names_[3:6] d = deep_merge(d, { "optional": { - "A": (COZY_TYPE_NUMERICAL, {}), - "B": (COZY_TYPE_NUMERICAL, {}), - "TYPE": (names_convert, { - "default": names_convert[2], - "tooltip":"Output type desired from resultant operation" - }), - "SWAP_X": (EnumSwizzle._member_names_, { - "default": EnumSwizzle.A_X.name, - "tooltip": "Replace input Red channel with target channel or constant" - }), - "SWAP_Y": (EnumSwizzle._member_names_, { - "default": EnumSwizzle.A_Y.name, - "tooltip": "Replace input Green channel with target channel or constant" - }), - "SWAP_Z": (EnumSwizzle._member_names_, { - "default": EnumSwizzle.A_Z.name, - "tooltip": "Replace input Blue channel with target channel or constant" - }), - "SWAP_W": (EnumSwizzle._member_names_, { - "default": EnumSwizzle.A_W.name, - "tooltip": "Replace input W channel with target channel or constant" - }), - "VEC": ("VEC4", { - "default": (0,0,0,0), "mij": -sys.maxsize, "maj": sys.maxsize, - "tooltip": "Default values for missing channels" - }) + Lexicon.IN_A: (COZY_TYPE_NUMERICAL, {}), + Lexicon.IN_B: (COZY_TYPE_NUMERICAL, {}), + Lexicon.TYPE: (names_convert, { + "default": names_convert[2]}), + Lexicon.SWAP_X: (EnumSwizzle._member_names_, { + "default": EnumSwizzle.A_X.name,}), + Lexicon.SWAP_Y: (EnumSwizzle._member_names_, { + "default": EnumSwizzle.A_Y.name,}), + Lexicon.SWAP_Z: (EnumSwizzle._member_names_, { + "default": EnumSwizzle.A_Z.name,}), + Lexicon.SWAP_W: (EnumSwizzle._member_names_, { + "default": EnumSwizzle.A_W.name,}), + Lexicon.DEFAULT: ("VEC4", { + "default": (0,0,0,0), "mij": -sys.maxsize, "maj": sys.maxsize}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[TensorType, ...]: - pA = parse_param(kw, "A", EnumConvertType.VEC4, (0,0,0,0)) - pB = parse_param(kw, "B", EnumConvertType.VEC4, (0,0,0,0)) - swap_x = parse_param(kw, "SWAP_X", EnumSwizzle, EnumSwizzle.A_X.name) - swap_y = parse_param(kw, "SWAP_Y", EnumSwizzle, EnumSwizzle.A_Y.name) - swap_z = parse_param(kw, "SWAP_Z", EnumSwizzle, EnumSwizzle.A_W.name) - swap_w = parse_param(kw, "SWAP_W", EnumSwizzle, EnumSwizzle.A_Z.name) - default = parse_param(kw, "VEC", EnumConvertType.VEC4, 0, -sys.maxsize, sys.maxsize) + pA = parse_param(kw, Lexicon.IN_A, EnumConvertType.VEC4, (0,0,0,0)) + pB = parse_param(kw, Lexicon.IN_B, EnumConvertType.VEC4, (0,0,0,0)) + swap_x = parse_param(kw, Lexicon.SWAP_X, EnumSwizzle, EnumSwizzle.A_X.name) + swap_y = parse_param(kw, Lexicon.SWAP_Y, EnumSwizzle, EnumSwizzle.A_Y.name) + swap_z = parse_param(kw, Lexicon.SWAP_Z, EnumSwizzle, EnumSwizzle.A_W.name) + swap_w = parse_param(kw, Lexicon.SWAP_W, EnumSwizzle, EnumSwizzle.A_Z.name) + default = parse_param(kw, Lexicon.DEFAULT, EnumConvertType.VEC4, 0, -sys.maxsize, sys.maxsize) params = list(zip_longest_fill(pA, pB, swap_x, x, swap_y, y, swap_z, z, swap_w, w)) results = [] diff --git a/core/color.py b/core/color.py index dbb4cab..3fe6f03 100644 --- a/core/color.py +++ b/core/color.py @@ -13,6 +13,9 @@ from cozy_comfyui import \ InputType, RGBAMaskType, EnumConvertType, TensorType, \ deep_merge, parse_param, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_IMAGE, \ CozyBaseNode, CozyImageNode @@ -72,30 +75,22 @@ Simulate color blindness effects on images. You can select various types of colo d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "DEFICIENCY": (EnumCBDeficiency._member_names_, { - "default": EnumCBDeficiency.PROTAN.name, - "tooltip": "Type of color deficiency: Red (Protanopia), Green (Deuteranopia), Blue (Tritanopia)" - }), - "SIMULATOR": (EnumCBSimulator._member_names_, { - "default": EnumCBSimulator.AUTOSELECT.name, - "tooltip": "Solver to use when translating to new color space" - }), - "VAL": ("FLOAT", { - "default": 1, "min": 0, "max": 1, "step": 0.001, - "tooltip": "alpha blending" - }), + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.DEFICIENCY: (EnumCBDeficiency._member_names_, { + "default": EnumCBDeficiency.PROTAN.name,}), + Lexicon.SOLVER: (EnumCBSimulator._member_names_, { + "default": EnumCBSimulator.AUTOSELECT.name,}), + Lexicon.ALPHA: ("FLOAT", { + "default": 1, "min": 0, "max": 1, "step": 0.001,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - deficiency = parse_param(kw, "DEFICIENCY", EnumCBDeficiency, EnumCBDeficiency.PROTAN.name) - simulator = parse_param(kw, "SIMULATOR", EnumCBSimulator, EnumCBSimulator.AUTOSELECT.name) - severity = parse_param(kw, "VAL", EnumConvertType.FLOAT, 1) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + deficiency = parse_param(kw, Lexicon.DEFICIENCY, EnumCBDeficiency, EnumCBDeficiency.PROTAN.name) + simulator = parse_param(kw, Lexicon.SOLVER, EnumCBSimulator, EnumCBSimulator.AUTOSELECT.name) + severity = parse_param(kw, Lexicon.VALUE, EnumConvertType.FLOAT, 1) params = list(zip_longest_fill(pA, deficiency, simulator, severity)) images = [] pbar = ProgressBar(len(params)) @@ -118,55 +113,43 @@ Adjust the color scheme of one image to match another with the Color Match Node. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "SOURCE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "TARGET": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "MODE": (EnumColorMatchMode._member_names_, { + Lexicon.IMAGE_SOURCE: (COZY_TYPE_IMAGE, {}), + Lexicon.IMAGE_TARGET: (COZY_TYPE_IMAGE, {}), + Lexicon.MODE: (EnumColorMatchMode._member_names_, { "default": EnumColorMatchMode.REINHARD.name, - "tooltip": "Match colors from an image or built-in (LUT), Histogram lookups or Reinhard method" - }), - "MAP": (EnumColorMatchMap._member_names_, { - "default": EnumColorMatchMap.USER_MAP.name, - "tooltip": "Custom image that will be transformed into a LUT or a built-in cv2 LUT" - }), - "COLORMAP": (EnumColorMap._member_names_, { - "default": EnumColorMap.HSV.name, - "tooltip": "One of two dozen CV2 Built-in Colormap LUT (Look Up Table) Presets" - }), - "VAL": ("INT", { + "tooltip": "Match colors from an image or built-in (LUT), Histogram lookups or Reinhard method"}), + Lexicon.MAP: (EnumColorMatchMap._member_names_, { + "default": EnumColorMatchMap.USER_MAP.name, }), + Lexicon.COLORMAP: (EnumColorMap._member_names_, { + "default": EnumColorMap.HSV.name,}), + Lexicon.VALUE: ("INT", { "default": 255, "min": 0, "max": 255, "tooltip":"The number of colors to use from the LUT during the remap. Will quantize the LUT range."}), - "FLIP": ("BOOLEAN", { - "default": False, - "tooltip": "Flip the SOURCE and TARGET inputs"}), - "INVERT": ("BOOLEAN", { - "default": False, - "tooltip": "Invert the color match output"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}), + Lexicon.SWAP: ("BOOLEAN", { + "default": False,}), + Lexicon.INVERT: ("BOOLEAN", { + "default": False,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "SOURCE", EnumConvertType.IMAGE, None) - pB = parse_param(kw, "TARGET", EnumConvertType.IMAGE, None) - colormatch_mode = parse_param(kw, "MODE", EnumColorMatchMode, EnumColorMatchMode.REINHARD.name) - colormatch_map = parse_param(kw, f"MAP", EnumColorMatchMap, EnumColorMatchMap.USER_MAP.name) - colormap = parse_param(kw, "COLORMAP", EnumColorMap, EnumColorMap.HSV.name) - num_colors = parse_param(kw, "VAL", EnumConvertType.INT, 255) - flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4, (0, 0, 0, 255), 0, 255) - params = list(zip_longest_fill(pA, pB, colormap, colormatch_mode, colormatch_map, num_colors, flip, invert, matte)) + pA = parse_param(kw, Lexicon.IMAGE_SOURCE, EnumConvertType.IMAGE, None) + pB = parse_param(kw, Lexicon.IMAGE_TARGET, EnumConvertType.IMAGE, None) + mode = parse_param(kw, Lexicon.MODE, EnumColorMatchMode, EnumColorMatchMode.REINHARD.name) + cmap = parse_param(kw, Lexicon.MAP, EnumColorMatchMap, EnumColorMatchMap.USER_MAP.name) + colormap = parse_param(kw, Lexicon.COLORMAP, EnumColorMap, EnumColorMap.HSV.name) + num_colors = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 255) + swap = parse_param(kw, Lexicon.SWAP, EnumConvertType.BOOLEAN, False) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4, (0, 0, 0, 255), 0, 255) + params = list(zip_longest_fill(pA, pB, mode, cmap, colormap, num_colors, swap, invert, matte)) images = [] pbar = ProgressBar(len(params)) - for idx, (pA, pB, colormap, mode, cmap, num_colors, flip, invert, matte) in enumerate(params): - if flip == True: + for idx, (pA, pB, mode, cmap, colormap, num_colors, swap, invert, matte) in enumerate(params): + if swap == True: pA, pB = pB, pA mask = None @@ -223,35 +206,30 @@ The top-k colors ordered from most->least used as a strip, tonal palette and 3D d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "VAL": ("INT", { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.VALUE: ("INT", { "default": 12, "min": 1, "max": 255, - "tooltip":"The top K colors to select." - }), - "SIZE": ("INT", { + "tooltip": "The top K colors to select"}), + Lexicon.SIZE: ("INT", { "default": 32, "min": 1, "max": 256, - "tooltip":"Height of the tones in the strip. Width is based on input." - }), - "COUNT": ("INT", { + "tooltip": "Height of the tones in the strip. Width is based on input"}), + Lexicon.COUNT: ("INT", { "default": 33, "min": 3, "max": 256, - "tooltip":"Number of nodes to use in interpolation of full LUT (256 is every pixel)." - }), - "WH": ("VEC2", { + "tooltip": "Number of nodes to use in interpolation of full LUT (256 is every pixel)"}), + Lexicon.WH: ("VEC2", { "default": (256, 256), "mij":IMAGE_SIZE_MIN, "int": True, "label": ["W", "H"] }), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - kcolors = parse_param(kw, "VAL", EnumConvertType.INT, 12, 1, 255) - lut_height = parse_param(kw, "SIZE", EnumConvertType.INT, 32, 1, 256) - nodes = parse_param(kw, "COUNT", EnumConvertType.INT, 33, 1, 255) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (256, 256), IMAGE_SIZE_MIN) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + kcolors = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 12, 1, 255) + lut_height = parse_param(kw, Lexicon.SIZE, EnumConvertType.INT, 32, 1, 256) + nodes = parse_param(kw, Lexicon.COUNT, EnumConvertType.INT, 33, 1, 255) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (256, 256), IMAGE_SIZE_MIN) params = list(zip_longest_fill(pA, kcolors, nodes, lut_height, wihi)) top_colors = [] @@ -299,27 +277,23 @@ Users can customize the angle of separation for color calculations, offering fle d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "SCHEME": (EnumColorTheory._member_names_, { - "default": EnumColorTheory.COMPLIMENTARY.name - }), - "VAL": ("INT", { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.SCHEME: (EnumColorTheory._member_names_, { + "default": EnumColorTheory.COMPLIMENTARY.name}), + Lexicon.VALUE: ("INT", { "default": 45, "min": -90, "max": 90, - "tooltip": "Custom angle of separation to use when calculating colors" - }), - "INVERT": ("BOOLEAN", { + "tooltip": "Custom angle of separation to use when calculating colors"}), + Lexicon.INVERT: ("BOOLEAN", { "default": False}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[List[TensorType], List[TensorType]]: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - scheme = parse_param(kw, "SCHEME", EnumColorTheory, EnumColorTheory.COMPLIMENTARY.name) - user = parse_param(kw, "VAL", EnumConvertType.INT, 0, -180, 180) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + scheme = parse_param(kw, Lexicon.SCHEME, EnumColorTheory, EnumColorTheory.COMPLIMENTARY.name) + user = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 0, -180, 180) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) params = list(zip_longest_fill(pA, scheme, user, invert)) images = [] pbar = ProgressBar(len(params)) @@ -347,48 +321,38 @@ The gradient image will be translated into a single row lookup table. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip":"Image to remap with gradient input" - }), - "GRADIENT": (COZY_TYPE_IMAGE, { - "tooltip":f"Look up table (LUT) to remap the input image in `{"IMAGE"}`" - }), - "FLIP": ("BOOLEAN", { - "default":False, - "tooltip":"Reverse the gradient from left-to-right " - }), - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size" - }), - "WH": ("VEC2", { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, { + "tooltip": "Image to remap with gradient input"}), + Lexicon.GRADIENT: (COZY_TYPE_IMAGE, { + "tooltip": f"Look up table (LUT) to remap the input image in `{"IMAGE"}`"}), + Lexicon.REVERSE: ("BOOLEAN", { + "default": False, + "tooltip": "Reverse the gradient from left-to-right"}), + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name,}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, - "label": ["W", "H"] - }), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images" - }), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color" - }) + "label": ["W", "H"] }), + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - gradient = parse_param(kw, "GRADIENT", EnumConvertType.IMAGE, None) - flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False) - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + gradient = parse_param(kw, Lexicon.GRADIENT, EnumConvertType.IMAGE, None) + reverse = parse_param(kw, Lexicon.REVERSE, EnumConvertType.BOOLEAN, False) + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) images = [] - params = list(zip_longest_fill(pA, gradient, flip, mode, sample, wihi, matte)) + params = list(zip_longest_fill(pA, gradient, reverse, mode, sample, wihi, matte)) pbar = ProgressBar(len(params)) - for idx, (pA, gradient, flip, mode, sample, wihi, matte) in enumerate(params): + for idx, (pA, gradient, reverse, mode, sample, wihi, matte) in enumerate(params): pA = channel_solid(chan=EnumImageType.BGR) if pA is None else tensor_to_cv(pA) mask = None if pA.ndim == 3 and pA.shape[2] == 4: @@ -399,8 +363,10 @@ The gradient image will be translated into a single row lookup table. if mode != EnumScaleMode.MATTE: w, h = wihi pA = image_scalefit(pA, w, h, mode, sample) + if mask is not None: pA = image_mask_add(pA, mask) + images.append(cv_to_tensor_full(pA, matte)) pbar.update_absolute(idx) return image_stack(images) diff --git a/core/compose.py b/core/compose.py index d6fc90a..c597e05 100644 --- a/core/compose.py +++ b/core/compose.py @@ -10,6 +10,9 @@ from cozy_comfyui import \ InputType, RGBAMaskType, EnumConvertType, \ deep_merge, parse_param, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_IMAGE, \ CozyBaseNode, CozyImageNode @@ -62,57 +65,49 @@ Advanced options include pixelation, quantization, and morphological operations d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "MASK": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "FUNCTION": (EnumAdjustOP._member_names_, { - "default": EnumAdjustOP.BLUR.name, - "tooltip":"Type of adjustment (e.g., blur, sharpen, invert)"}), - "RADIUS": ("INT", { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.MASK: (COZY_TYPE_IMAGE, {}), + Lexicon.FUNCTION: (EnumAdjustOP._member_names_, { + "default": EnumAdjustOP.BLUR.name,}), + Lexicon.RADIUS: ("INT", { "default": 3, "min": 3}), - "VAL": ("FLOAT", { + Lexicon.VALUE: ("FLOAT", { "default": 1, "min": 0, "step": 0.01}), - "LoHi": ("VEC2", { + Lexicon.LOHI: ("VEC2", { "default": (0, 1), "mij": 0, "maj": 1, "label": ["Low", "HI"]}), - "LMH": ("VEC3", { + Lexicon.LMH: ("VEC3", { "default": (0, 0.5, 1), "mij": 0, "maj": 1, - "label": ["Low", "MID", "HI"], - "tooltip": "Low, Middle, High"}), - "HSV": ("VEC3",{ + "label": ["Low", "MID", "HI"],}), + Lexicon.HSV: ("VEC3",{ "default": (0, 1, 1), "mij": 0, "maj": 1, - "label": ["H", "S", "V"], - "tooltip": "Hue, Saturation and Value"}), - "CONTRAST": ("FLOAT", { + "label": ["H", "S", "V"],}), + Lexicon.CONTRAST: ("FLOAT", { "default": 0, "min": 0, "max": 1, "step": 0.01}), - "GAMMA": ("FLOAT", { + Lexicon.GAMMA: ("FLOAT", { "default": 1, "min": 0.00001, "max": 1, "step": 0.01}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}), - "INVERT": ("BOOLEAN", { + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}), + Lexicon.INVERT: ("BOOLEAN", { "default": False, "tooltip": "Invert the mask input"}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - mask = parse_param(kw, "MASK", EnumConvertType.IMAGE, None) - op = parse_param(kw, "FUNCTION", EnumAdjustOP, EnumAdjustOP.BLUR.name) - radius = parse_param(kw, "RADIUS", EnumConvertType.INT, 3, 3) - val = parse_param(kw, "VAL", EnumConvertType.FLOAT, 0, 0) - lohi = parse_param(kw, "LoHi", EnumConvertType.VEC2, (0, 1), 0, 1) - lmh = parse_param(kw, "LMH", EnumConvertType.VEC3, (0, 0.5, 1), 0, 1) - hsv = parse_param(kw, "HSV", EnumConvertType.VEC3, (0, 1, 1), 0, 1) - contrast = parse_param(kw, "CONTRAST", EnumConvertType.FLOAT, 1, 0, 1) - gamma = parse_param(kw, "GAMMA", EnumConvertType.FLOAT, 1, 0, 1) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + mask = parse_param(kw, Lexicon.MASK, EnumConvertType.IMAGE, None) + op = parse_param(kw, Lexicon.FUNCTION, EnumAdjustOP, EnumAdjustOP.BLUR.name) + radius = parse_param(kw, Lexicon.RADIUS, EnumConvertType.INT, 3, 3) + val = parse_param(kw, Lexicon.VALUE, EnumConvertType.FLOAT, 0, 0) + lohi = parse_param(kw, Lexicon.LOHI, EnumConvertType.VEC2, (0, 1), 0, 1) + lmh = parse_param(kw, Lexicon.LMH, EnumConvertType.VEC3, (0, 0.5, 1), 0, 1) + hsv = parse_param(kw, Lexicon.HSV, EnumConvertType.VEC3, (0, 1, 1), 0, 1) + contrast = parse_param(kw, Lexicon.CONTRAST, EnumConvertType.FLOAT, 1, 0, 1) + gamma = parse_param(kw, Lexicon.GAMMA, EnumConvertType.FLOAT, 1, 0, 1) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) params = list(zip_longest_fill(pA, mask, op, radius, val, lohi, lmh, hsv, contrast, gamma, matte, invert)) images = [] @@ -228,50 +223,43 @@ Combine two input images using various blending modes, such as normal, screen, m d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE_A": (COZY_TYPE_IMAGE, { - "tooltip": "Background Plate"}), - "IMAGE_B": (COZY_TYPE_IMAGE, { - "tooltip": "Image to Overlay on Background Plate"}), - "MASK": (COZY_TYPE_IMAGE, { + Lexicon.IMAGE_BACK: (COZY_TYPE_IMAGE, {}), + Lexicon.IMAGE_FORE: (COZY_TYPE_IMAGE, {}), + Lexicon.MASK: (COZY_TYPE_IMAGE, { "tooltip": "Optional Mask to use for Alpha Blend Operation. If empty, will use the ALPHA of B"}), - "FUNCTION": (EnumBlendType._member_names_, { - "default": EnumBlendType.NORMAL.name, - "tooltip": "Blending Operation"}), - "ALPHA": ("FLOAT", { - "default": 1, "min": 0, "max": 1, "step": 0.01, - "tooltip": "Amount of Blending to Perform on the Selected Operation"}), - "FLIP": ("BOOLEAN", { + Lexicon.FUNCTION: (EnumBlendType._member_names_, { + "default": EnumBlendType.NORMAL.name,}), + Lexicon.ALPHA: ("FLOAT", { + "default": 1, "min": 0, "max": 1, "step": 0.01,}), + Lexicon.FLIP: ("BOOLEAN", { "default": False}), - "INVERT": ("BOOLEAN", { + Lexicon.INVERT: ("BOOLEAN", { "default": False, "tooltip": "Invert the mask input"}), - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size"}), - "WH": ("VEC2", { + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name,}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, "label": ["W", "H"]}), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}) + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE_A", EnumConvertType.IMAGE, None) - pB = parse_param(kw, "IMAGE_B", EnumConvertType.IMAGE, None) - mask = parse_param(kw, "MASK", EnumConvertType.MASK, None) - func = parse_param(kw, "FUNCTION", EnumBlendType, EnumBlendType.NORMAL.name) - alpha = parse_param(kw, "ALPHA", EnumConvertType.FLOAT, 1, 0, 1) - flip = parse_param(kw, "FLIP", EnumConvertType.BOOLEAN, False) - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) + pA = parse_param(kw, Lexicon.IMAGE_BACK, EnumConvertType.IMAGE, None) + pB = parse_param(kw, Lexicon.IMAGE_FORE, EnumConvertType.IMAGE, None) + mask = parse_param(kw, Lexicon.MASK, EnumConvertType.MASK, None) + func = parse_param(kw, Lexicon.FUNCTION, EnumBlendType, EnumBlendType.NORMAL.name) + alpha = parse_param(kw, Lexicon.ALPHA, EnumConvertType.FLOAT, 1, 0, 1) + flip = parse_param(kw, Lexicon.FLIP, EnumConvertType.BOOLEAN, False) + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) params = list(zip_longest_fill(pA, pB, mask, func, alpha, flip, mode, wihi, sample, matte, invert)) images = [] pbar = ProgressBar(len(params)) @@ -335,33 +323,29 @@ Create masks based on specific color ranges within an image. Specify the color r d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "START": ("VEC3", { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.START: ("VEC3", { "default": (128, 128, 128), "rgb": True}), - "RANGE": ("BOOLEAN", { + Lexicon.RANGE: ("BOOLEAN", { "default": False, - "tooltip": "use an end point (start->end) when calculating the filter range"}), - "END": ("VEC3", { + "tooltip": "Use an end point (start->end) when calculating the filter range"}), + Lexicon.END: ("VEC3", { "default": (128, 128, 128), "rgb": True}), - "FUZZ": ("VEC3", { - "default": (0.5,0.5,0.5), "mij":0, "maj":1, - "tooltip": "the fuzziness use to extend the start and end range(s)"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}), + Lexicon.FUZZ: ("VEC3", { + "default": (0.5,0.5,0.5), "mij":0, "maj":1,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - start = parse_param(kw, "START", EnumConvertType.VEC3INT, (128,128,128), 0, 255) - use_range = parse_param(kw, "RANGE", EnumConvertType.BOOLEAN, False, 0, 255) - end = parse_param(kw, "END", EnumConvertType.VEC3INT, (128,128,128), 0, 255) - fuzz = parse_param(kw, "FUZZ", EnumConvertType.VEC3, (0.5,0.5,0.5), 0, 1) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + start = parse_param(kw, Lexicon.START, EnumConvertType.VEC3INT, (128,128,128), 0, 255) + use_range = parse_param(kw, Lexicon.RANGE, EnumConvertType.BOOLEAN, False, 0, 255) + end = parse_param(kw, Lexicon.END, EnumConvertType.VEC3INT, (128,128,128), 0, 255) + fuzz = parse_param(kw, Lexicon.FUZZ, EnumConvertType.VEC3, (0.5,0.5,0.5), 0, 1) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) params = list(zip_longest_fill(pA, start, use_range, end, fuzz, matte)) images = [] pbar = ProgressBar(len(params)) @@ -390,56 +374,41 @@ Combines individual color channels (red, green, blue) along with an optional mas d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "🟥": (COZY_TYPE_IMAGE, { - "tooltip": "Red" - }), - "🟩": (COZY_TYPE_IMAGE, { - "tooltip": "Green" - }), - "🟦": (COZY_TYPE_IMAGE, { - "tooltip": "Blue" - }), - "⬜": (COZY_TYPE_IMAGE, { - "tooltip": "Alpha" - }), - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size"}), - "WH": ("VEC2", { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.CHAN_RED: (COZY_TYPE_IMAGE, {}), + Lexicon.CHAN_GREEN: (COZY_TYPE_IMAGE, {}), + Lexicon.CHAN_BLUE: (COZY_TYPE_IMAGE, {}), + Lexicon.CHAN_ALPHA: (COZY_TYPE_IMAGE, {}), + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name,}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, - "label": ["W", "H"], - "tooltip": "Width and Height"}), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}), - "FLIP": ("VEC4", { + "label": ["W", "H"],}), + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}), + Lexicon.FLIP: ("VEC4", { "default": (0,0,0,0), "mij":0, "maj":1, "tooltip": "Invert specific input prior to merging. R, G, B, A."}), - "INVERT": ("BOOLEAN", { - "default": False, - "tooltip": "Invert the final merged output"}) + Lexicon.INVERT: ("BOOLEAN", { + "default": False,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - rgba = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - R = parse_param(kw, "🟥", EnumConvertType.MASK, None) - G = parse_param(kw, "🟩", EnumConvertType.MASK, None) - B = parse_param(kw, "🟦", EnumConvertType.MASK, None) - A = parse_param(kw, "⬜", EnumConvertType.MASK, None) - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) - flip = parse_param(kw, "FLIP", EnumConvertType.VEC4, (0, 0, 0, 0), 0., 1.) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) + rgba = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + R = parse_param(kw, Lexicon.CHAN_RED, EnumConvertType.MASK, None) + G = parse_param(kw, Lexicon.CHAN_GREEN, EnumConvertType.MASK, None) + B = parse_param(kw, Lexicon.CHAN_BLUE, EnumConvertType.MASK, None) + A = parse_param(kw, Lexicon.CHAN_ALPHA, EnumConvertType.MASK, None) + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + flip = parse_param(kw, Lexicon.FLIP, EnumConvertType.VEC4, (0, 0, 0, 0), 0., 1.) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) params = list(zip_longest_fill(rgba, R, G, B, A, mode, wihi, sample, matte, flip, invert)) images = [] pbar = ProgressBar(len(params)) @@ -498,16 +467,14 @@ Takes an input image and splits it into its individual color channels (red, gree d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }) + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: images = [] - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) pbar = ProgressBar(len(pA)) for idx, pA in enumerate(pA): pA = channel_solid(chan=EnumImageType.BGRA) if pA is None else tensor_to_cv(pA) @@ -528,39 +495,30 @@ Swap pixel values between two input images based on specified channel swizzle op d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE_A": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "IMAGE_B": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "SWAP_R": (EnumPixelSwizzle._member_names_, { - "default": EnumPixelSwizzle.RED_A.name, - "tooltip": "Replace input Red channel with target channel or constant"}), - "SWAP_G": (EnumPixelSwizzle._member_names_, { - "default": EnumPixelSwizzle.GREEN_A.name, - "tooltip": "Replace input Green channel with target channel or constant"}), - "SWAP_B": (EnumPixelSwizzle._member_names_, { - "default": EnumPixelSwizzle.BLUE_A.name, - "tooltip": "Replace input Blue channel with target channel or constant"}), - "SWAP_A": (EnumPixelSwizzle._member_names_, { - "default": EnumPixelSwizzle.ALPHA_A.name, - "tooltip": "Replace input Alpha channel with target channel or constant"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}) + Lexicon.IMAGE_SOURCE: (COZY_TYPE_IMAGE, {}), + Lexicon.IMAGE_TARGET: (COZY_TYPE_IMAGE, {}), + Lexicon.SWAP_R: (EnumPixelSwizzle._member_names_, { + "default": EnumPixelSwizzle.RED_A.name,}), + Lexicon.SWAP_G: (EnumPixelSwizzle._member_names_, { + "default": EnumPixelSwizzle.GREEN_A.name,}), + Lexicon.SWAP_B: (EnumPixelSwizzle._member_names_, { + "default": EnumPixelSwizzle.BLUE_A.name,}), + Lexicon.SWAP_A: (EnumPixelSwizzle._member_names_, { + "default": EnumPixelSwizzle.ALPHA_A.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE_A", EnumConvertType.IMAGE, None) - pB = parse_param(kw, "IMAGE_B", EnumConvertType.IMAGE, None) - swap_r = parse_param(kw, "SWAP_R", EnumPixelSwizzle, EnumPixelSwizzle.RED_A.name) - swap_g = parse_param(kw, "SWAP_G", EnumPixelSwizzle, EnumPixelSwizzle.GREEN_A.name) - swap_b = parse_param(kw, "SWAP_B", EnumPixelSwizzle, EnumPixelSwizzle.BLUE_A.name) - swap_a = parse_param(kw, "SWAP_A", EnumPixelSwizzle, EnumPixelSwizzle.ALPHA_A.name) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + pA = parse_param(kw, Lexicon.IMAGE_SOURCE, EnumConvertType.IMAGE, None) + pB = parse_param(kw, Lexicon.IMAGE_TARGET, EnumConvertType.IMAGE, None) + swap_r = parse_param(kw, Lexicon.SWAP_R, EnumPixelSwizzle, EnumPixelSwizzle.RED_A.name) + swap_g = parse_param(kw, Lexicon.SWAP_G, EnumPixelSwizzle, EnumPixelSwizzle.GREEN_A.name) + swap_b = parse_param(kw, Lexicon.SWAP_B, EnumPixelSwizzle, EnumPixelSwizzle.BLUE_A.name) + swap_a = parse_param(kw, Lexicon.SWAP_A, EnumPixelSwizzle, EnumPixelSwizzle.ALPHA_A.name) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) params = list(zip_longest_fill(pA, pB, swap_r, swap_g, swap_b, swap_a, matte)) images = [] pbar = ProgressBar(len(params)) @@ -602,32 +560,29 @@ Define a range and apply it to an image for segmentation and feature extraction. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "ADAPT": ( EnumThresholdAdapt._member_names_, { - "default": EnumThresholdAdapt.ADAPT_NONE.name, - "tooltip": "X-Men"}), - "FUNCTION": ( EnumThreshold._member_names_, { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.ADAPT: ( EnumThresholdAdapt._member_names_, { + "default": EnumThresholdAdapt.ADAPT_NONE.name,}), + Lexicon.FUNCTION: ( EnumThreshold._member_names_, { "default": EnumThreshold.BINARY.name}), - "THRESHOLD": ("FLOAT", { + Lexicon.THRESHOLD: ("FLOAT", { "default": 0.5, "min": 0, "max": 1, "step": 0.005}), - "SIZE": ("INT", { + Lexicon.SIZE: ("INT", { "default": 3, "min": 3, "max": 103}), - "INVERT": ("BOOLEAN", { + Lexicon.INVERT: ("BOOLEAN", { "default": False, "tooltip": "Invert the mask input"}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - mode = parse_param(kw, "FUNCTION", EnumThreshold, EnumThreshold.BINARY.name) - adapt = parse_param(kw, "ADAPT", EnumThresholdAdapt, EnumThresholdAdapt.ADAPT_NONE.name) - threshold = parse_param(kw, "THRESHOLD", EnumConvertType.FLOAT, 1, 0, 1) - block = parse_param(kw, "SIZE", EnumConvertType.INT, 3, 3) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + mode = parse_param(kw, Lexicon.FUNCTION, EnumThreshold, EnumThreshold.BINARY.name) + adapt = parse_param(kw, Lexicon.ADAPT, EnumThresholdAdapt, EnumThresholdAdapt.ADAPT_NONE.name) + threshold = parse_param(kw, Lexicon.THRESHOLD, EnumConvertType.FLOAT, 1, 0, 1) + block = parse_param(kw, Lexicon.SIZE, EnumConvertType.INT, 3, 3) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) params = list(zip_longest_fill(pA, mode, adapt, threshold, block, invert)) images = [] pbar = ProgressBar(len(params)) @@ -656,14 +611,14 @@ The Histogram Node generates a histogram representation of the input image, show d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { + Lexicon.IMAGE": (COZY_TYPE_IMAGE, { "tooltip": "Pixel Data (RGBA, RGB or Grayscale)"}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", None), EnumConvertType.IMAGE, None) + pA = parse_param(kw, Lexicon.IMAGE", None), EnumConvertType.IMAGE, None) params = list(zip_longest_fill(pA,)) images = [] pbar = ProgressBar(len(params)) diff --git a/core/create.py b/core/create.py index 448369f..196a006 100644 --- a/core/create.py +++ b/core/create.py @@ -11,6 +11,9 @@ from cozy_comfyui import \ InputType, EnumConvertType, RGBAMaskType, \ deep_merge, parse_param, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_IMAGE, \ CozyImageNode @@ -58,34 +61,31 @@ Generate a constant image or mask of a specified size and color. It can be used d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, { "tooltip":"Optional Image to Matte with Selected Color"}), - "MASK": (COZY_TYPE_IMAGE, { + Lexicon.MASK: (COZY_TYPE_IMAGE, { "tooltip":"Override Image mask"}), - "COLOR": ("VEC4", { + Lexicon.COLOR: ("VEC4", { "default": (0, 0, 0, 255), "rgb": True, "tooltip": "Constant Color to Output"}), - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size"}), - "WH": ("VEC2", { + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name,}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "int": True, - "label": ["W", "H"], - "tooltip": "Desired Width and Height of the Color Output"}), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images"}) + "label": ["W", "H"],}), + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - mask = parse_param(kw, "MASK", EnumConvertType.IMAGE, None) - matte = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name) - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + mask = parse_param(kw, Lexicon.MASK, EnumConvertType.IMAGE, None) + matte = parse_param(kw, Lexicon.COLOR, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name) + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name) images = [] params = list(zip_longest_fill(pA, mask, matte, wihi, mode, sample)) pbar = ProgressBar(len(params)) @@ -125,47 +125,43 @@ Create n-sided polygons. These shapes can be customized by adjusting parameters d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "SHAPE": (EnumShapes._member_names_, { + Lexicon.SHAPE: (EnumShapes._member_names_, { "default": EnumShapes.CIRCLE.name}), - "SIDES": ("INT", { + Lexicon.SIDES: ("INT", { "default": 3, "min": 3, "max": 100}), - "COLOR": ("VEC4", { + Lexicon.COLOR: ("VEC4", { "default": (255, 255, 255, 255), "rgb": True, "tooltip": "Main Shape Color"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}), - "WH": ("VEC2", { + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}), + Lexicon.WH: ("VEC2", { "default": (256, 256), "mij":IMAGE_SIZE_MIN, "int": True, - "label": ["W", "H"], - "tooltip": "Width and Height"}), - "XY": ("VEC2", { + "label": ["W", "H"],}), + Lexicon.XY: ("VEC2", { "default": (0, 0,), "label": ["X", "Y"]}), - "ANGLE": ("FLOAT", { - "default": 0, "min": -180, "max": 180, "step": 0.01, - "tooltip": "Rotation Angle"}), - "SIZE": ("VEC2", { + Lexicon.ANGLE: ("FLOAT", { + "default": 0, "min": -180, "max": 180, "step": 0.01,}), + Lexicon.SIZE: ("VEC2", { "default": (1., 1.), "label": ["X", "Y"]}), - "EDGE": (EnumEdge._member_names_, { + Lexicon.EDGE: (EnumEdge._member_names_, { "default": EnumEdge.CLIP.name}), - "BLUR": ("FLOAT", { - "default": 0, "min": 0, "step": 0.01, - "tooltip": "Edge blur amount (Gaussian blur)"}), + Lexicon.BLUR: ("FLOAT", { + "default": 0, "min": 0, "step": 0.01,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - shape = parse_param(kw, "SHAPE", EnumShapes, EnumShapes.CIRCLE.name) - sides = parse_param(kw, "SIDES", EnumConvertType.INT, 3, 3, 100) - angle = parse_param(kw, "ANGLE", EnumConvertType.FLOAT, 0) - edge = parse_param(kw, "EDGE", EnumEdge, EnumEdge.CLIP.name) - offset = parse_param(kw, "XY", EnumConvertType.VEC2, (0, 0)) - size = parse_param(kw, "SIZE", EnumConvertType.VEC2, (1, 1), zero=0.001) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (256, 256), IMAGE_SIZE_MIN) - color = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, (255, 255, 255, 255), 0, 255) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) - blur = parse_param(kw, "BLUR", EnumConvertType.FLOAT, 0) + shape = parse_param(kw, Lexicon.SHAPE, EnumShapes, EnumShapes.CIRCLE.name) + sides = parse_param(kw, Lexicon.SIDES, EnumConvertType.INT, 3, 3, 100) + angle = parse_param(kw, Lexicon.ANGLE, EnumConvertType.FLOAT, 0) + edge = parse_param(kw, Lexicon.EDGE, EnumEdge, EnumEdge.CLIP.name) + offset = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, (0, 0)) + size = parse_param(kw, Lexicon.SIZE, EnumConvertType.VEC2, (1, 1), zero=0.001) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (256, 256), IMAGE_SIZE_MIN) + color = parse_param(kw, Lexicon.COLOR, EnumConvertType.VEC4INT, (255, 255, 255, 255), 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + blur = parse_param(kw, Lexicon.BLUR, EnumConvertType.FLOAT, 0) params = list(zip_longest_fill(shape, sides, offset, angle, edge, size, wihi, color, matte, blur)) images = [] pbar = ProgressBar(len(params)) @@ -217,78 +213,71 @@ Generates images containing text based on parameters such as font, size, alignme d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "STRING": ("STRING", { + Lexicon.STRING: ("STRING", { "default": "jovimetrix", "multiline": True, "dynamicPrompts": False, "tooltip": "Your Message"}), - "FONT": (cls.FONT_NAMES, { + Lexicon.FONT: (cls.FONT_NAMES, { "default": cls.FONT_NAMES[0]}), - "LETTER": ("BOOLEAN", { - "default": False, - "tooltip": "If each letter be generated and output in a batch"}), - "AUTOSIZE": ("BOOLEAN", { + Lexicon.LETTER: ("BOOLEAN", { + "default": False,}), + Lexicon.AUTOSIZE: ("BOOLEAN", { "default": False, "tooltip": "Scale based on Width & Height"}), - "COLOR": ("VEC4", { + Lexicon.COLOR: ("VEC4", { "default": (255, 255, 255, 255), "rgb": True, "tooltip": "Color of the letters"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}), - "COLS": ("INT", { + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}), + Lexicon.COLUMNS: ("INT", { "default": 0, "min": 0}), # if auto on, hide these... - "SIZE": ("INT", { + Lexicon.SIZE: ("INT", { "default": 16, "min": 8}), - "ALIGN": (EnumAlignment._member_names_, { - "default": EnumAlignment.CENTER.name, - "tooltip": "Top, Center or Bottom alignment"}), - "JUSTIFY": (EnumJustify._member_names_, { - "default": EnumJustify.CENTER.name, - "tooltip": "How to align the text to the side margins of the canvas: Left, Right, or Centered"}), - "MARGIN": ("INT", { - "default": 0, "min": -1024, "max": 1024, - "tooltip": "Whitespace padding around canvas"}), - "SPACING": ("INT", { + Lexicon.ALIGN: (EnumAlignment._member_names_, { + "default": EnumAlignment.CENTER.name,}), + Lexicon.JUSTIFY: (EnumJustify._member_names_, { + "default": EnumJustify.CENTER.name,}), + Lexicon.MARGIN: ("INT", { + "default": 0, "min": -1024, "max": 1024,}), + Lexicon.SPACING: ("INT", { "default": 0, "min": -1024, "max": 1024}), - "WH": ("VEC2", { + Lexicon.WH: ("VEC2", { "default": (256, 256), "mij":IMAGE_SIZE_MIN, "int": True, - "label": ["W", "H"], - "tooltip": "Width and Height"}), - "XY": ("VEC2", { + "label": ["W", "H"],}), + Lexicon.XY: ("VEC2", { "default": (0, 0,), "mij": -1, "maj": 1, "label": ["X", "Y"], "tooltip":"Offset the position"}), - "ANGLE": ("FLOAT", { - "default": 0, "step": 0.01, - "tooltip": "Rotation Angle"}), - "EDGE": (EnumEdge._member_names_, { + Lexicon.ANGLE: ("FLOAT", { + "default": 0, "step": 0.01,}), + Lexicon.EDGE: (EnumEdge._member_names_, { "default": EnumEdge.CLIP.name}), - "INVERT": ("BOOLEAN", { + Lexicon.INVERT: ("BOOLEAN", { "default": False, "tooltip": "Invert the mask input"}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - full_text = parse_param(kw, "STRING", EnumConvertType.STRING, "jovimetrix") - font_idx = parse_param(kw, "FONT", EnumConvertType.STRING, self.FONT_NAMES[0]) - autosize = parse_param(kw, "AUTOSIZE", EnumConvertType.BOOLEAN, False) - letter = parse_param(kw, "LETTER", EnumConvertType.BOOLEAN, False) - color = parse_param(kw, "COLOR", EnumConvertType.VEC4INT, (255,255,255,255), 0, 255) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0,0,0,255), 0, 255) - columns = parse_param(kw, "COLS", EnumConvertType.INT, 0) - font_size = parse_param(kw, "SIZE", EnumConvertType.INT, 1) - align = parse_param(kw, "ALIGN", EnumAlignment, EnumAlignment.CENTER.name) - justify = parse_param(kw, "JUSTIFY", EnumJustify, EnumJustify.CENTER.name) - margin = parse_param(kw, "MARGIN", EnumConvertType.INT, 0) - line_spacing = parse_param(kw, "SPACING", EnumConvertType.INT, 0) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - pos = parse_param(kw, "XY", EnumConvertType.VEC2, (0, 0), -1, 1) - angle = parse_param(kw, "ANGLE", EnumConvertType.INT, 0) - edge = parse_param(kw, "EDGE", EnumEdge, EnumEdge.CLIP.name) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) + full_text = parse_param(kw, Lexicon.STRING, EnumConvertType.STRING, "jovimetrix") + font_idx = parse_param(kw, Lexicon.FONT, EnumConvertType.STRING, self.FONT_NAMES[0]) + autosize = parse_param(kw, Lexicon.AUTOSIZE, EnumConvertType.BOOLEAN, False) + letter = parse_param(kw, Lexicon.LETTER, EnumConvertType.BOOLEAN, False) + color = parse_param(kw, Lexicon.COLOR, EnumConvertType.VEC4INT, (255,255,255,255), 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0,0,0,255), 0, 255) + columns = parse_param(kw, Lexicon.COLUMNS, EnumConvertType.INT, 0) + font_size = parse_param(kw, Lexicon.SIZE, EnumConvertType.INT, 1) + align = parse_param(kw, Lexicon.ALIGN, EnumAlignment, EnumAlignment.CENTER.name) + justify = parse_param(kw, Lexicon.JUSTIFY, EnumJustify, EnumJustify.CENTER.name) + margin = parse_param(kw, Lexicon.MARGIN, EnumConvertType.INT, 0) + line_spacing = parse_param(kw, Lexicon.SPACING, EnumConvertType.INT, 0) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + pos = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, (0, 0), -1, 1) + angle = parse_param(kw, Lexicon.ANGLE, EnumConvertType.INT, 0) + edge = parse_param(kw, Lexicon.EDGE, EnumEdge, EnumEdge.CLIP.name) + invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) images = [] params = list(zip_longest_fill(full_text, font_idx, autosize, letter, color, matte, columns, font_size, align, justify, margin, @@ -328,101 +317,3 @@ Generates images containing text based on parameters such as font, size, alignme images.append(cv_to_tensor_full(img, matte)) pbar.update_absolute(idx) return image_stack(images) - -''' -class StereogramNode(CozyImageNode): - NAME = "STEREOGRAM (JOV) 📻" - CATEGORY = JOV_CATEGORY - DESCRIPTION = """ -Generates false perception 3D images from 2D input. Set tile divisions, noise, gamma, and shift parameters to control the stereogram's appearance. -""" - - @classmethod - def INPUT_TYPES(cls) -> InputType: - d = super().INPUT_TYPES() - d = deep_merge(d, { - "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "DEPTH": (COZY_TYPE_IMAGE, { - "tooltip": "Grayscale image representing a depth map" - }), - "TILE": ("INT", { - "default": 8, "min": 1}), - "NOISE": ("FLOAT", { - "default": 0.33, "min": 0, "max": 1, "step": 0.01}), - "GAMMA": ("FLOAT", { - "default": 0.33, "min": 0, "max": 1, "step": 0.01}), - "SHIFT": ("FLOAT", { - "default": 1., "min": -1, "max": 1, "step": 0.01}), - "INVERT": ("BOOLEAN", { - "default": False}), - } - }) - return d - - def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - depth = parse_param(kw, "DEPTH", EnumConvertType.IMAGE, None) - divisions = parse_param(kw, "TILE", EnumConvertType.INT, 1, 1, 8) - noise = parse_param(kw, "NOISE", EnumConvertType.FLOAT, 1, 0) - gamma = parse_param(kw, "GAMMA", EnumConvertType.FLOAT, 1, 0) - shift = parse_param(kw, "SHIFT", EnumConvertType.FLOAT, 0, 1, -1) - invert = parse_param(kw, "INVERT", EnumConvertType.BOOLEAN, False) - params = list(zip_longest_fill(pA, depth, divisions, noise, gamma, shift, invert)) - images = [] - pbar = ProgressBar(len(params)) - for idx, (pA, depth, divisions, noise, gamma, shift, invert) in enumerate(params): - pA = channel_solid(chan=EnumImageType.BGRA) if pA is None else tensor_to_cv(pA) - h, w = pA.shape[:2] - depth = channel_solid(w, h, chan=EnumImageType.BGRA) if depth is None else tensor_to_cv(depth) - if invert: - depth = image_invert(depth, 1.0) - pA = image_stereogram(pA, depth, divisions, noise, gamma, shift) - images.append(cv_to_tensor_full(pA)) - pbar.update_absolute(idx) - return image_stack(images) - -class StereoscopicNode(CozyBaseNode): - NAME = "STEREOSCOPIC (JOV) 🕶️" - CATEGORY = JOV_CATEGORY - RETURN_TYPES = ("IMAGE", ) - RETURN_NAMES = ("IMAGE", ) - DESCRIPTION = """ -Simulates depth perception in images by generating stereoscopic views. It accepts an optional input image for color matte. Adjust baseline and focal length for customized depth effects. -""" - @classmethod - def INPUT_TYPES(cls) -> InputType: - d = super().INPUT_TYPES() - d = deep_merge(d, { - "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip":"Optional Image to Matte with Selected Color"}), - "INT": ("FLOAT", { - "default": 0.1, "min": 0, "max": 1, "step": 0.01, - "tooltip":"Baseline"}), - "FOCAL": ("FLOAT", { - "default": 500, "min": 0, "step": 0.01}), - } - }) - return d - - def run(self, **kw) -> tuple[TensorType]: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - baseline = parse_param(kw, "INT", EnumConvertType.FLOAT, 0, 0.1, 1) - focal_length = parse_param(kw, "VAL", EnumConvertType.FLOAT, 500, 0) - images = [] - params = list(zip_longest_fill(pA, baseline, focal_length)) - pbar = ProgressBar(len(params)) - for idx, (pA, baseline, focal_length) in enumerate(params): - pA = tensor_to_cv(pA) if pA is not None else channel_solid(chan=EnumImageType.GRAYSCALE) - # Convert depth image to disparity map - disparity_map = np.divide(1.0, pA.astype(np.float32), where=pA!=0) - # Compute disparity values based on baseline and focal length - disparity_map *= baseline * focal_length - images.append(cv_to_tensor(pA)) - pbar.update_absolute(idx) - return torch.stack(images) - -''' \ No newline at end of file diff --git a/core/trans.py b/core/trans.py index 95b1eea..464c44f 100644 --- a/core/trans.py +++ b/core/trans.py @@ -10,6 +10,9 @@ from cozy_comfyui import \ InputType, RGBAMaskType, EnumConvertType, \ deep_merge, parse_param, parse_dynamic, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_IMAGE, \ CozyImageNode @@ -72,41 +75,36 @@ Extract a portion of an input image or resize it. It supports various cropping m d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "FUNCTION": (EnumCropMode._member_names_, { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.FUNCTION: (EnumCropMode._member_names_, { "default": EnumCropMode.CENTER.name}), - "XY": ("VEC2", { + Lexicon.XY: ("VEC2", { "default": (0, 0), "mij": 0.5, "maj": 0.5, "label": ["X", "Y"]}), - "WH": ("VEC2", { + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij": IMAGE_SIZE_MIN, "int": True, "label": ["W", "H"]}), - "TLTR": ("VEC4", { + Lexicon.TLTR: ("VEC4", { "default": (0, 0, 0, 1), "mij": 0, "maj": 1, - "label": ["TOP", "LEFT", "TOP", "RIGHT"], - "tooltip": "Top Left - Top Right"}), - "BLBR": ("VEC4", { + "label": ["TOP", "LEFT", "TOP", "RIGHT"],}), + Lexicon.BLBR: ("VEC4", { "default": (1, 0, 1, 1), "mij": 0, "maj": 1, - "label": ["BOTTOM", "LEFT", "BOTTOM", "RIGHT"], - "tooltip": "Bottom Left - Bottom Right"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}) + "label": ["BOTTOM", "LEFT", "BOTTOM", "RIGHT"],}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - func = parse_param(kw, "FUNCTION", EnumCropMode, EnumCropMode.CENTER.name) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + func = parse_param(kw, Lexicon.FUNCTION, EnumCropMode, EnumCropMode.CENTER.name) # if less than 1 then use as scalar, over 1 = int(size) - xy = parse_param(kw, "XY", EnumConvertType.VEC2, (0, 0,), 0, 1) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - tltr = parse_param(kw, "TLTR", EnumConvertType.VEC4, (0, 0, 0, 1,), 0, 1) - blbr = parse_param(kw, "BLBR", EnumConvertType.VEC4, (1, 0, 1, 1,), 0, 1) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + xy = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, (0, 0,), 0, 1) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + tltr = parse_param(kw, Lexicon.TLTR, EnumConvertType.VEC4, (0, 0, 0, 1,), 0, 1) + blbr = parse_param(kw, Lexicon.BLBR, EnumConvertType.VEC4, (1, 0, 1, 1,), 0, 1) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) params = list(zip_longest_fill(pA, func, xy, wihi, tltr, blbr, matte)) images = [] pbar = ProgressBar(len(params)) @@ -151,34 +149,31 @@ Combine multiple input images into a single image by summing their pixel values. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size"}), - "WH": ("VEC2", { + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name,}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, "label": ["W", "H"]}), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}) + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - imgs = parse_dynamic(kw, "IMAGE", EnumConvertType.IMAGE, None) + imgs = parse_dynamic(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) if imgs is None: logger.warning("no images to flatten") return () # be less dumb when merging pA = [tensor_to_cv(i) for i in imgs] - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) images = [] params = list(zip_longest_fill(mode, sample, wihi, matte)) @@ -206,41 +201,37 @@ The axis parameter allows for horizontal, vertical, or grid stacking of images, d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "AXIS": (EnumOrientation._member_names_, { - "default": EnumOrientation.GRID.name, - "tooltip":"Choose the direction in which to stack the images. Options include horizontal, vertical, or a grid layout"}), - "STEP": ("INT", { + Lexicon.AXIS: (EnumOrientation._member_names_, { + "default": EnumOrientation.GRID.name,}), + Lexicon.STEP: ("INT", { "default": 1, "min": 0, - "tooltip":"How many images are placed before a new row starts (stride)."}), - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size"}), - "WH": ("VEC2", { + "tooltip":"How many images are placed before a new row starts (stride)"}), + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name,}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, "label": ["W", "H"]}), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}) + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - images = parse_dynamic(kw, "IMAGE", EnumConvertType.IMAGE, None) + images = parse_dynamic(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) if len(images) == 0: logger.warning("no images to stack") return images = [tensor_to_cv(i) for i in images] - axis = parse_param(kw, "AXIS", EnumOrientation, EnumOrientation.GRID.name)[0] - stride = parse_param(kw, "STEP", EnumConvertType.INT, 1)[0] - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)[0] - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)[0] - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)[0] - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0] + axis = parse_param(kw, Lexicon.AXIS, EnumOrientation, EnumOrientation.GRID.name)[0] + stride = parse_param(kw, Lexicon.STEP, EnumConvertType.INT, 1)[0] + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name)[0] + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)[0] + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name)[0] + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0] img = image_stacker(images, axis, stride) #, matte) if mode != EnumScaleMode.MATTE: w, h = wihi @@ -261,76 +252,68 @@ Apply various geometric transformations to images, including translation, rotati d = super().INPUT_TYPES(prompt=True, dynprompt=True) d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "MASK": (COZY_TYPE_IMAGE, { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.MASK: (COZY_TYPE_IMAGE, { "tooltip": "Override Image mask"}), - "XY": ("VEC2", { + Lexicon.XY: ("VEC2", { "default": (0., 0.,), "mij": -1., "maj": 1., "label": ["X", "Y"]}), - "ANGLE": ("FLOAT", { - "default": 0, "step": 0.01, - "tooltip": "Rotation Angle"}), - "SIZE": ("VEC2", { + Lexicon.ANGLE: ("FLOAT", { + "default": 0, "step": 0.01,}), + Lexicon.SIZE: ("VEC2", { "default": (1., 1.), "mij": 0.001, "label": ["X", "Y"]}), - "TILE": ("VEC2", { + Lexicon.TILE: ("VEC2", { "default": (1., 1.), "mij": 1., "label": ["X", "Y"]}), - "EDGE": (EnumEdge._member_names_, { + Lexicon.EDGE: (EnumEdge._member_names_, { "default": EnumEdge.CLIP.name}), - "MIRROR": (EnumMirrorMode._member_names_, { + Lexicon.MIRROR: (EnumMirrorMode._member_names_, { "default": EnumMirrorMode.NONE.name}), - "PIVOT": ("VEC2", { + Lexicon.PIVOT: ("VEC2", { "default": (0.5, 0.5), "step": 0.005, "label": ["X", "Y"]}), - "PROJ": (EnumProjection._member_names_, { + Lexicon.PROJECTION: (EnumProjection._member_names_, { "default": EnumProjection.NORMAL.name}), - "TLTR": ("VEC4", { + Lexicon.TLTR: ("VEC4", { "default": (0., 0., 1., 0.), "mij": 0., "maj": 1., "step": 0.005, - "label": ["TOP", "LEFT", "TOP", "RIGHT"], - "tooltip": "Top Left - Top Right"}), - "BLBR": ("VEC4", { + "label": ["TOP", "LEFT", "TOP", "RIGHT"],}), + Lexicon.BLBR: ("VEC4", { "default": (0., 1., 1., 1.), "mij": 0., "maj": 1., "step": 0.005, - "label": ["BOTTOM", "LEFT", "BOTTOM", "RIGHT"], - "tooltip": "Bottom Left - Bottom Right"}), - "STRENGTH": ("FLOAT", { + "label": ["BOTTOM", "LEFT", "BOTTOM", "RIGHT"],}), + Lexicon.STRENGTH: ("FLOAT", { "default": 1, "min": 0, "step": 0.005}), - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size"}), - "WH": ("VEC2", { + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name,}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, "label": ["W", "H"]}), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background Color"}) + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> RGBAMaskType: - pA = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - mask = parse_param(kw, "MASK", EnumConvertType.IMAGE, None) - offset = parse_param(kw, "XY", EnumConvertType.VEC2, (0., 0.), -2.5, 2.5) - angle = parse_param(kw, "ANGLE", EnumConvertType.FLOAT, 0) - size = parse_param(kw, "SIZE", EnumConvertType.VEC2, (1., 1.), 0.001) - edge = parse_param(kw, "EDGE", EnumEdge, EnumEdge.CLIP.name) - mirror = parse_param(kw, "MIRROR", EnumMirrorMode, EnumMirrorMode.NONE.name) - mirror_pivot = parse_param(kw, "PIVOT", EnumConvertType.VEC2, (0.5, 0.5), 0, 1) - tile_xy = parse_param(kw, "TILE", EnumConvertType.VEC2, (1., 1.), 1) - proj = parse_param(kw, "PROJ", EnumProjection, EnumProjection.NORMAL.name) - tltr = parse_param(kw, "TLTR", EnumConvertType.VEC4, (0., 0., 1., 0.), 0, 1) - blbr = parse_param(kw, "BLBR", EnumConvertType.VEC4, (0., 1., 1., 1.), 0, 1) - strength = parse_param(kw, "STRENGTH", EnumConvertType.FLOAT, 1, 0, 1) - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name) - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + pA = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + mask = parse_param(kw, Lexicon.MASK, EnumConvertType.IMAGE, None) + offset = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, (0., 0.), -2.5, 2.5) + angle = parse_param(kw, Lexicon.ANGLE, EnumConvertType.FLOAT, 0) + size = parse_param(kw, Lexicon.SIZE, EnumConvertType.VEC2, (1., 1.), 0.001) + edge = parse_param(kw, Lexicon.EDGE, EnumEdge, EnumEdge.CLIP.name) + mirror = parse_param(kw, Lexicon.MIRROR, EnumMirrorMode, EnumMirrorMode.NONE.name) + mirror_pivot = parse_param(kw, Lexicon.PIVOT, EnumConvertType.VEC2, (0.5, 0.5), 0, 1) + tile_xy = parse_param(kw, Lexicon.TILE, EnumConvertType.VEC2, (1., 1.), 1) + proj = parse_param(kw, Lexicon.PROJECTION, EnumProjection, EnumProjection.NORMAL.name) + tltr = parse_param(kw, Lexicon.TLTR, EnumConvertType.VEC4, (0., 0., 1., 0.), 0, 1) + blbr = parse_param(kw, Lexicon.BLBR, EnumConvertType.VEC4, (0., 1., 1., 1.), 0, 1) + strength = parse_param(kw, Lexicon.STRENGTH, EnumConvertType.FLOAT, 1, 0, 1) + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN) + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) params = list(zip_longest_fill(pA, mask, offset, angle, size, edge, tile_xy, mirror, mirror_pivot, proj, strength, tltr, blbr, mode, wihi, sample, matte)) images = [] pbar = ProgressBar(len(params)) diff --git a/core/utility/batch.py b/core/utility/batch.py index 4424bd2..a26be8e 100644 --- a/core/utility/batch.py +++ b/core/utility/batch.py @@ -22,6 +22,9 @@ from cozy_comfyui import \ InputType, EnumConvertType, TensorType, \ deep_merge, parse_dynamic, parse_param +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_ANY, \ CozyBaseNode @@ -83,7 +86,7 @@ class ArrayNode(CozyBaseNode): ) SORT = 50 DESCRIPTION = """ -Processes a batch of data based on the selected mode. Merge, pick, slice, random select, or index items. Can reverse the order of items and divide the data into chunks. +Processes a batch of data based on the selected mode. Merge, pick, slice, random select, or index items. Can also reverse the order of items. """ @classmethod @@ -91,27 +94,26 @@ Processes a batch of data based on the selected mode. Merge, pick, slice, random d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "MODE": (EnumBatchMode._member_names_, { + Lexicon.MODE: (EnumBatchMode._member_names_, { "default": EnumBatchMode.MERGE.name, - "tooltip":"Select a single index, specific range, custom index list or randomized"}), - "RANGE": ("VEC3", { + "tooltip": "Select a single index, specific range, custom index list or randomized"}), + Lexicon.RANGE: ("VEC3", { "default": (0, 0, 1), "mij": 0, "int": True, - "tooltip":"The start, end and step for the range"}), - "INDEX": ("STRING", { + "tooltip": "The start, end and step for the range"}), + Lexicon.INDEX: ("STRING", { "default": "", - "tooltip":"Comma separated list of indicies to export"}), - "COUNT": ("INT", { + "tooltip": "Comma separated list of indicies to export"}), + Lexicon.COUNT: ("INT", { "default": 0, "min": 0, "max": sys.maxsize, - "tooltip":"How many items to return"}), - "REVERSE": ("BOOLEAN", { + "tooltip": "How many items to return"}), + Lexicon.REVERSE: ("BOOLEAN", { "default": False, - "tooltip":"reverse the calculated output list"}), - "SEED": ("INT", { - "default": 0, "min": 0, "max": sys.maxsize, - "tooltip":"Random seed value"}), + "tooltip": "Reverse the calculated output list"}), + Lexicon.SEED: ("INT", { + "default": 0, "min": 0, "max": sys.maxsize}), } }) - return d + return Lexicon._parse(d) @classmethod def batched(cls, iterable, chunk_size, expand:bool=False, fill:Any=None) -> List[Any]: @@ -121,13 +123,13 @@ Processes a batch of data based on the selected mode. Merge, pick, slice, random return [iterable[i: i + chunk_size] for i in range(0, len(iterable), chunk_size)] def run(self, **kw) -> tuple[int, list]: - data_list = parse_dynamic(kw, "❔", EnumConvertType.ANY, None) - mode = parse_param(kw, "MODE", EnumBatchMode, EnumBatchMode.MERGE.name)[0] - slice_range = parse_param(kw, "RANGE", EnumConvertType.VEC3INT, (0, 0, 1))[0] - index = parse_param(kw, "INDEX", EnumConvertType.STRING, "")[0] - count = parse_param(kw, "COUNT", EnumConvertType.INT, 0, 0, sys.maxsize)[0] - reverse = parse_param(kw, "REVERSE", EnumConvertType.BOOLEAN, False)[0] - seed = parse_param(kw, "SEED", EnumConvertType.INT, 0)[0] + data_list = parse_dynamic(kw, Lexicon.DYNAMIC, EnumConvertType.ANY, None) + mode = parse_param(kw, Lexicon.MODE, EnumBatchMode, EnumBatchMode.MERGE.name)[0] + slice_range = parse_param(kw, Lexicon.RANGE, EnumConvertType.VEC3INT, (0, 0, 1))[0] + index = parse_param(kw, Lexicon.INDEX, EnumConvertType.STRING, "")[0] + count = parse_param(kw, Lexicon.COUNT, EnumConvertType.INT, 0, 0, sys.maxsize)[0] + reverse = parse_param(kw, Lexicon.REVERSE, EnumConvertType.BOOLEAN, False)[0] + seed = parse_param(kw, Lexicon.SEED, EnumConvertType.INT, 0)[0] data = [] # track latents since they need to be added back to Dict['samples'] @@ -246,7 +248,7 @@ Processes a batch of data based on the selected mode. Merge, pick, slice, random class QueueBaseNode(CozyBaseNode): CATEGORY = JOV_CATEGORY RETURN_TYPES = (COZY_TYPE_ANY, COZY_TYPE_ANY, "STRING", "INT", "INT", "BOOLEAN") - RETURN_NAMES = ("🦄", "QUEUE", "CURRENT", "INDEX", "TOTAL", "TRIGGER", ) + RETURN_NAMES = ("❔", "QUEUE", "CURRENT", "INDEX", "TOTAL", "TRIGGER", ) #OUTPUT_IS_LIST = (True, True, True, True, True, True,) VIDEO_FORMATS = ['.wav', '.mp3', '.webm', '.mp4', '.avi', '.wmv', '.mkv', '.mov', '.mxf'] @@ -259,33 +261,33 @@ class QueueBaseNode(CozyBaseNode): d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "Q": ("STRING", { + Lexicon.QUEUE: ("STRING", { "default": "./res/img/test-a.png", "multiline": True, - "tooltip": "Current items to process during Queue iteration."}), - "RECURSE": ("BOOLEAN", { + "tooltip": "Current items to process during Queue iteration"}), + Lexicon.RECURSE: ("BOOLEAN", { "default": False, - "tooltip":"Recurse through all subdirectories found"}), - "BATCH": ("BOOLEAN", { + "tooltip": "Recurse through all subdirectories found"}), + Lexicon.BATCH: ("BOOLEAN", { "default": False, - "tooltip":"Load all items, if they are loadable items, i.e. batch load images from the Queue's list."}), - "SELECT": ("INT", { + "tooltip": "Load all items, if they are loadable items, i.e. batch load images from the Queue's list"}), + Lexicon.SELECT: ("INT", { "default": 0, "min": 0, - "tooltip": "What index to use for the current queue item. 0 will move to the next item each queue run"}), - "HOLD": ("BOOLEAN", { + "tooltip": "The index to use for the current queue item. 0 will move to the next item each queue run"}), + Lexicon.HOLD: ("BOOLEAN", { "default": False, - "tooltip":"Hold the item at the current queue index"}), - "STOP": ("BOOLEAN", { + "tooltip": "Hold the item at the current queue index"}), + Lexicon.STOP: ("BOOLEAN", { "default": False, - "tooltip":"When the Queue is out of items, send a `HALT` to ComfyUI."}), - "LOOP": ("BOOLEAN", { + "tooltip": "When the Queue is out of items, send a `HALT` to ComfyUI"}), + Lexicon.LOOP: ("BOOLEAN", { "default": True, - "tooltip":"If the queue should loop. If `False` and if there are more iterations, will send the previous image."}), - "RESET": ("BOOLEAN", { + "tooltip": "If the queue should loop. If `False` and if there are more iterations, will send the previous image"}), + Lexicon.RESET: ("BOOLEAN", { "default": False, - "tooltip":"Reset the queue back to index 1"}), + "tooltip": "Reset the queue back to index 1"}), } }) - return d + return Lexicon._parse(d) def __init__(self) -> None: self.__index = 0 @@ -368,26 +370,26 @@ class QueueBaseNode(CozyBaseNode): self.__ident = ident # should work headless as well - if (new_val := parse_param(kw, "SELECT", EnumConvertType.INT, 0)[0]) > 0: + if (new_val := parse_param(kw, Lexicon.SELECT, EnumConvertType.INT, 0)[0]) > 0: self.__index = new_val - 1 reset = parse_reset(ident) > 0 - if reset or parse_param(kw, "RESET", EnumConvertType.BOOLEAN, False)[0]: + if reset or parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0]: self.__q = None self.__index = 0 - mode = parse_param(kw, "MODE", EnumScaleMode, EnumScaleMode.MATTE.name)[0] - sample = parse_param(kw, "SAMPLE", EnumInterpolation, EnumInterpolation.LANCZOS4.name)[0] - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)[0] + mode = parse_param(kw, Lexicon.MODE, EnumScaleMode, EnumScaleMode.MATTE.name)[0] + sample = parse_param(kw, Lexicon.SAMPLE, EnumInterpolation, EnumInterpolation.LANCZOS4.name)[0] + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), IMAGE_SIZE_MIN)[0] w, h = wihi - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0] + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0] if self.__q is None: # process Q into ... # check if folder first, file, then string. # entry is: data, , - recurse = parse_param(kw, "RECURSE", EnumConvertType.BOOLEAN, False)[0] - q = parse_param(kw, "Q", EnumConvertType.STRING, "")[0] + recurse = parse_param(kw, Lexicon.RECURSE, EnumConvertType.BOOLEAN, False)[0] + q = parse_param(kw, Lexicon.QUEUE, EnumConvertType.STRING, "")[0] self.__q = self.__parseQ(q, recurse) self.__len = len(self.__q) self.__index_last = 0 @@ -396,17 +398,17 @@ class QueueBaseNode(CozyBaseNode): self.__previous = self.process(self.__previous) # make sure we have more to process if are a single fire queue - stop = parse_param(kw, "STOP", EnumConvertType.BOOLEAN, False)[0] + stop = parse_param(kw, Lexicon.STOP, EnumConvertType.BOOLEAN, False)[0] if stop and self.__index >= self.__len: comfy_api_post("jovi-queue-done", ident, self.status) interrupt_processing() return self.__previous, self.__q, self.__current, self.__index_last+1, self.__len - if (wait := parse_param(kw, "HOLD", EnumConvertType.BOOLEAN, False))[0] == True: + if (wait := parse_param(kw, Lexicon.HOLD, EnumConvertType.BOOLEAN, False))[0] == True: self.__index = self.__index_last # otherwise loop around the end - loop = parse_param(kw, "LOOP", EnumConvertType.BOOLEAN, False)[0] + loop = parse_param(kw, Lexicon.LOOP, EnumConvertType.BOOLEAN, False)[0] if loop == True: self.__index %= self.__len else: @@ -417,7 +419,7 @@ class QueueBaseNode(CozyBaseNode): self.__index_last = self.__index info = f"QUEUE #{ident} [{self.__current}] ({self.__index})" batched = False - if (batched := parse_param(kw, "BATCH", EnumConvertType.BOOLEAN, False)[0]) == True: + if (batched := parse_param(kw, Lexicon.BATCH, EnumConvertType.BOOLEAN, False)[0]) == True: data = [] mw, mh, mc = 0, 0, 0 for idx in range(self.__len): @@ -506,30 +508,26 @@ Manage a queue of specific items: media files. Supports various image and video d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "MODE": (EnumScaleMode._member_names_, { - "default": EnumScaleMode.MATTE.name, - "tooltip": "If the image should be resized to fit within given dimensions or keep the original size"}), - "WH": ("VEC2", { + Lexicon.MODE: (EnumScaleMode._member_names_, { + "default": EnumScaleMode.MATTE.name}), + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, - "label": ["W", "H"], - "tooltip": "Width and Height"}), - "SAMPLE": (EnumInterpolation._member_names_, { - "default": EnumInterpolation.LANCZOS4.name, - "tooltip": "Sampling method for resizing images"}), - "MATTE": ("VEC4", { - "default": (0, 0, 0, 255), "rgb": True, - "tooltip": "Background color for padding"}), + "label": ["W", "H"],}), + Lexicon.SAMPLE: (EnumInterpolation._member_names_, { + "default": EnumInterpolation.LANCZOS4.name,}), + Lexicon.MATTE: ("VEC4", { + "default": (0, 0, 0, 255), "rgb": True,}), }, "hidden": d.get("hidden", {}) }) - return d + return Lexicon._parse(d) def run(self, ident, **kw) -> tuple[TensorType, TensorType, TensorType, str, int, int, bool]: data, _, current, index, total, trigger = super().run(ident, **kw) if not isinstance(data, (TensorType, )): data = [None, None, None] else: - matte = parse_param(kw, "MATTE", EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0] + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255)[0] data = [tensor_to_cv(d) for d in data] data = [cv_to_tensor_full(d, matte) for d in data] data = [torch.stack(d) for d in zip(*data)] diff --git a/core/utility/info.py b/core/utility/info.py index 06ca3c1..5fb6fd8 100644 --- a/core/utility/info.py +++ b/core/utility/info.py @@ -14,6 +14,9 @@ from cozy_comfyui import \ InputType, EnumConvertType, TensorType, \ deep_merge, parse_dynamic, parse_param +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_IMAGE, \ CozyBaseNode @@ -155,19 +158,18 @@ Visualize a series of data points over time. It accepts a dynamic number of valu d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "RESET": ("BOOLEAN", { + Lexicon.RESET: ("BOOLEAN", { "default": False, "tooltip":"Clear the graph history"}), - "VAL": ("INT", { + Lexicon.VALUE: ("INT", { "default": 60, "min": 0, "tooltip":"Number of values to graph and display"}), - "WH": ("VEC2", { + Lexicon.WH: ("VEC2", { "default": (512, 512), "mij":IMAGE_SIZE_MIN, "int": True, - "label": ["W", "H"], - "tooltip":"Width and Height of the graph output"}), + "label": ["W", "H"]}), } }) - return d + return Lexicon._parse(d) @classmethod def IS_CHANGED(cls) -> float: @@ -179,12 +181,12 @@ Visualize a series of data points over time. It accepts a dynamic number of valu self.__fig, self.__ax = plt.subplots(figsize=(5.12, 5.12)) def run(self, ident, **kw) -> tuple[TensorType]: - slice = parse_param(kw, "VAL", EnumConvertType.INT, 60)[0] - wihi = parse_param(kw, "WH", EnumConvertType.VEC2INT, (512, 512), 1)[0] - if parse_reset(ident) > 0 or parse_param(kw, "RESET", EnumConvertType.BOOLEAN, False)[0]: + slice = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 60)[0] + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (512, 512), 1)[0] + if parse_reset(ident) > 0 or parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0]: self.__history = [] longest_edge = 0 - dynamic = parse_dynamic(kw, "❔", EnumConvertType.FLOAT, 0) + dynamic = parse_dynamic(kw, Lexicon.DYNAMIC, EnumConvertType.FLOAT, 0) dynamic = [i[0] for i in dynamic] self.__ax.clear() for idx, val in enumerate(dynamic): @@ -236,14 +238,12 @@ Exports and Displays immediate information about images. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "default": None, - "tooltip":"The image to examine"}) + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}) } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[int, list]: - image = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) + image = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) height, width, cc = image[0].shape return (len(image), width, height, cc, (width, height), (width, height, cc)) diff --git a/core/utility/io.py b/core/utility/io.py index 5eb1b9f..4ac5db1 100644 --- a/core/utility/io.py +++ b/core/utility/io.py @@ -20,6 +20,9 @@ from cozy_comfyui import \ InputType, EnumConvertType, \ deep_merge, parse_param, parse_param_list, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_IMAGE, COZY_TYPE_ANY, \ CozyBaseNode @@ -99,30 +102,30 @@ Introduce pauses in the workflow that accept an optional input to pass through a d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IN": (COZY_TYPE_ANY, { + Lexicon.PASS_IN: (COZY_TYPE_ANY, { "default": None, "tooltip":"The data that should be held until the timer completes."}), - "TIMER": ("INT", { + Lexicon.TIMER: ("INT", { "default" : 0, "min": -1, "tooltip":"How long to delay if enabled. 0 means no delay."}), - "ENABLE": ("BOOLEAN", { + Lexicon.ENABLE: ("BOOLEAN", { "default": True, "tooltip":"Enable or disable the screensaver."}) } }) - return d + return Lexicon._parse(d) @classmethod def IS_CHANGED(cls, **kw) -> float: return float("NaN") def run(self, ident, **kw) -> tuple[Any]: - delay = parse_param(kw, "TIMER", EnumConvertType.INT, -1, 0, JOV_DELAY_MAX)[0] + delay = parse_param(kw, Lexicon.TIMER, EnumConvertType.INT, -1, 0, JOV_DELAY_MAX)[0] if delay < 0: delay = JOV_DELAY_MAX if delay > JOV_DELAY_MIN: comfy_api_post("jovi-delay-user", ident, {"id": ident, "timeout": delay}) - # enable = parse_param(kw, "ENABLE", EnumConvertType.BOOLEAN, True) + # enable = parse_param(kw, Lexicon.ENABLE, EnumConvertType.BOOLEAN, True)[0] step = 1 pbar = ProgressBar(delay) @@ -139,7 +142,7 @@ Introduce pauses in the workflow that accept an optional input to pass through a logger.info(f"delay [continue] ({step}): {ident}") pbar.update_absolute(step) step += 1 - return kw["IN"], + return kw[Lexicon.PASS_IN], class ExportNode(CozyBaseNode): NAME = "EXPORT (JOV) 📽" @@ -156,52 +159,45 @@ Responsible for saving images or animations to disk. It supports various output d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "IMAGE": (COZY_TYPE_IMAGE, { - "tooltip": "Pixel Data (RGBA, RGB or Grayscale)" - }), - "OUT": ("STRING", { + Lexicon.IMAGE: (COZY_TYPE_IMAGE, {}), + Lexicon.PATH: ("STRING", { "default": get_output_directory(), - "default_top":"", - "tooltip":"Pass through another route node to pre-populate the outputs."}), - "FORMAT": (FORMATS, { - "default": FORMATS[0], - "tooltip":"Pass through another route node to pre-populate the outputs."}), - "PREFIX": ("STRING", { - "default": "jovi", - "tooltip":"Pass through another route node to pre-populate the outputs."}), - "OVERWRITE": ("BOOLEAN", { - "default": False, - "tooltip":"Pass through another route node to pre-populate the outputs."}), + "default_top": "",}), + Lexicon.FORMAT: (FORMATS, { + "default": FORMATS[0],}), + Lexicon.PREFIX: ("STRING", { + "default": "jovi",}), + Lexicon.OVERWRITE: ("BOOLEAN", { + "default": False,}), # GIF ONLY - "OPT": ("BOOLEAN", { - "default": False, - "tooltip":"Pass through another route node to pre-populate the outputs."}), + Lexicon.OPTIMIZE: ("BOOLEAN", { + "default": False,}), # GIFSKI ONLY - "QUALITY": ("INT", {"default": 90, "min": 1, "max": 100, - "tooltip":"Pass through another route node to pre-populate the outputs."}), - "QUALITY_M": ("INT", {"default": 100, "min": 1, "max": 100, - "tooltip":"Pass through another route node to pre-populate the outputs."}), + Lexicon.QUALITY: ("INT", { + "default": 90, "min": 1, "max": 100,}), + Lexicon.QUALITY_M: ("INT", { + "default": 100, "min": 1, "max": 100,}), # GIF OR GIFSKI - "FPS": ("INT", {"default": 24, "min": 1, "max": 60, - "tooltip":"Pass through another route node to pre-populate the outputs."}), + Lexicon.FPS: ("INT", { + "default": 24, "min": 1, "max": 60,}), # GIF OR GIFSKI - "LOOP": ("INT", {"default": 0, "min": 0, - "tooltip":"Pass through another route node to pre-populate the outputs."}), + Lexicon.LOOP: ("INT", { + "default": 0, "min": 0,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> None: - images = parse_param(kw, "IMAGE", EnumConvertType.IMAGE, None) - suffix = parse_param(kw, "PREFIX", EnumConvertType.STRING, uuid4().hex[:16])[0] - output_dir = parse_param(kw, "OUT", EnumConvertType.STRING, "")[0] - format = parse_param(kw, "FORMAT", EnumConvertType.STRING, "gif")[0] - overwrite = parse_param(kw, "OVERWRITE", EnumConvertType.BOOLEAN, False)[0] - optimize = parse_param(kw, "OPT", EnumConvertType.BOOLEAN, False)[0] - quality = parse_param(kw, "QUALITY", EnumConvertType.INT, 90, 0, 100)[0] - motion = parse_param(kw, "QUALITY_M", EnumConvertType.INT, 100, 0, 100)[0] - fps = parse_param(kw, "FPS", EnumConvertType.INT, 24, 1, 60)[0] - loop = parse_param(kw, "LOOP", EnumConvertType.INT, 0, 0)[0] + images = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + suffix = parse_param(kw, Lexicon.PREFIX, EnumConvertType.STRING, uuid4().hex[:16])[0] + output_dir = parse_param(kw, Lexicon.PATH, EnumConvertType.STRING, "")[0] + format = parse_param(kw, Lexicon.FORMAT, EnumConvertType.STRING, "gif")[0] + overwrite = parse_param(kw, Lexicon.OVERWRITE, EnumConvertType.BOOLEAN, False)[0] + optimize = parse_param(kw, Lexicon.OPTIMIZE, EnumConvertType.BOOLEAN, False)[0] + quality = parse_param(kw, Lexicon.QUALITY, EnumConvertType.INT, 90, 0, 100)[0] + motion = parse_param(kw, Lexicon.QUALITY_M, EnumConvertType.INT, 100, 0, 100)[0] + fps = parse_param(kw, Lexicon.FPS, EnumConvertType.INT, 24, 1, 60)[0] + loop = parse_param(kw, Lexicon.LOOP, EnumConvertType.INT, 0, 0)[0] output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) @@ -273,16 +269,17 @@ Routes the input data from the optional input ports to the output port, preservi d = super().INPUT_TYPES() e = { "optional": { - "ROUTE": ("BUS", {"default": None, "tooltip":"Pass through another route node to pre-populate the outputs."}), + Lexicon.ROUTE: ("BUS", { + "default": None,}), } } d = deep_merge(d, e) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[Any, ...]: - inout = parse_param(kw, "ROUTE", EnumConvertType.ANY, None) + inout = parse_param(kw, Lexicon.ROUTE, EnumConvertType.ANY, None) vars = kw.copy() - vars.pop("ROUTE", None) + vars.pop(Lexicon.ROUTE, None) vars.pop('ident', None) parsed = [] @@ -300,7 +297,7 @@ class SaveOutputNode(CozyBaseNode): RETURN_TYPES = () SORT = 85 DESCRIPTION = """ -Save the output image along with its metadata to the specified path. Supports saving additional user metadata and prompt information. +Save images with metadata to any specified path. Can save user metadata and prompt information. """ @classmethod @@ -308,31 +305,25 @@ Save the output image along with its metadata to the specified path. Supports sa d = super().INPUT_TYPES(True, True) d = deep_merge(d, { "optional": { - "IMAGE": ("IMAGE", { - "default": None, - "tooltip":""}), - "PATH": ("STRING", { - "default": "", "dynamicPrompts":False, - "tooltip":"Destination path to save the output"}), - "NAME": ("STRING", { - "default": "output", "dynamicPrompts":False, - "tooltip":"Filename of the output"}), - "META": ("JSON", { - "default": None, - "tooltip":"Extra metadata to save in the file"}), - "USER": ("STRING", { - "default": "", "multiline": True, "dynamicPrompts":False, - "tooltip":"Custom user metadat to save with the file"}), + Lexicon.IMAGE: ("IMAGE", {}), + Lexicon.PATH: ("STRING", { + "default": "", "dynamicPrompts":False}), + Lexicon.NAME: ("STRING", { + "default": "output", "dynamicPrompts":False,}), + Lexicon.META: ("JSON", { + "default": None,}), + Lexicon.USER: ("STRING", { + "default": "", "multiline": True, "dynamicPrompts":False,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> dict[str, Any]: - image = parse_param(kw, 'IMAGE', EnumConvertType.IMAGE, None) - path = parse_param(kw, 'PATH', EnumConvertType.STRING, "") - fname = parse_param(kw, 'NAME', EnumConvertType.STRING, "output") - metadata = parse_param(kw, 'META', EnumConvertType.DICT, {}) - usermeta = parse_param(kw, 'USER', EnumConvertType.DICT, {}) + image = parse_param(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None) + path = parse_param(kw, Lexicon.PATH, EnumConvertType.STRING, "") + fname = parse_param(kw, Lexicon.NAME, EnumConvertType.STRING, "output") + metadata = parse_param(kw, Lexicon.META, EnumConvertType.DICT, {}) + usermeta = parse_param(kw, Lexicon.USER, EnumConvertType.DICT, {}) prompt = parse_param(kw, 'prompt', EnumConvertType.STRING, "") pnginfo = parse_param(kw, 'extra_pnginfo', EnumConvertType.DICT, {}) params = list(zip_longest_fill(image, path, fname, metadata, usermeta, prompt, pnginfo)) diff --git a/core/vars.py b/core/vars.py index fc29d31..9426fc5 100644 --- a/core/vars.py +++ b/core/vars.py @@ -9,10 +9,16 @@ from cozy_comfyui import \ InputType, EnumConvertType, \ deep_merge, parse_param, parse_value, zip_longest_fill +from cozy_comfyui.lexicon import \ + Lexicon + from cozy_comfyui.node import \ COZY_TYPE_ANY, COZY_TYPE_NUMERICAL, COZY_TYPE_NUMBER, \ CozyBaseNode +from . import \ + EnumFillOperation + JOV_CATEGORY = "VARIABLE" # ============================================================================== @@ -23,7 +29,8 @@ class ValueNode(CozyBaseNode): NAME = "VALUE (JOV) 🧬" CATEGORY = JOV_CATEGORY RETURN_TYPES = (COZY_TYPE_ANY, COZY_TYPE_ANY, COZY_TYPE_ANY, COZY_TYPE_ANY, COZY_TYPE_ANY,) - RETURN_NAMES = ("🦄", "X", "Y", "Z", "W",) + RETURN_NAMES = ("❔", Lexicon.X, Lexicon.Y, Lexicon.Z, Lexicon.W,) + OUTPUT_IS_LIST = (True, True, True, True, True,) SORT = 5 DESCRIPTION = """ Supplies raw or default values for various data types, supporting vector input with components for X, Y, Z, and W. It also provides a string input option. @@ -36,55 +43,53 @@ Supplies raw or default values for various data types, supporting vector input w typ = EnumConvertType._member_names_[:6] d = deep_merge(d, { "optional": { - "A": (COZY_TYPE_ANY, { - "default": None, - "tooltip":"Passes a raw value directly, or supplies defaults for any value inputs without connections"}), - "TYPE": (typ, { - "default": EnumConvertType.BOOLEAN.name, - "tooltip":"Take the input and convert it into the selected type."}), - "X": (COZY_TYPE_NUMERICAL, { + Lexicon.IN_A: (COZY_TYPE_ANY, { + "default": None,}), + Lexicon.X: (COZY_TYPE_NUMERICAL, { "default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "forceInput": True}), - "Y": (COZY_TYPE_NUMERICAL, { + Lexicon.Y: (COZY_TYPE_NUMERICAL, { "default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "forceInput": True}), - "Z": (COZY_TYPE_NUMERICAL, { + Lexicon.Z: (COZY_TYPE_NUMERICAL, { "default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "forceInput": True}), - "W": (COZY_TYPE_NUMERICAL, { + Lexicon.W: (COZY_TYPE_NUMERICAL, { "default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "forceInput": True}), - "AA": ("VEC4", { + Lexicon.TYPE: (typ, { + "default": EnumConvertType.BOOLEAN.name}), + Lexicon.DEFAULT_A: ("VEC4", { "default": (0, 0, 0, 0), #"mij": -sys.maxsize, "maj": sys.maxsize, - "label": ["X", "Y"], - "tooltip":"default value vector for A"}), - "BB": ("VEC4", { + "label": [Lexicon.X, Lexicon.Y, Lexicon.Z, Lexicon.W]}), + Lexicon.DEFAULT_B: ("VEC4", { "default": (1,1,1,1), #"mij": -sys.maxsize, "maj": sys.maxsize, - "label": ["X", "Y", "Z", "W"], - "tooltip":"default value vector for B"}), - "SEED": ("INT", { + "label": [Lexicon.X, Lexicon.Y, Lexicon.Z, Lexicon.W]}), + Lexicon.FILL: (EnumFillOperation._member_names_, { + "default": EnumFillOperation.DEFAULT.name}), + Lexicon.SEED: ("INT", { "default": 0, "min": 0, "max": sys.maxsize}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[bool]: - raw = parse_param(kw, "A", EnumConvertType.ANY, 0) - r_x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - r_y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - r_z = parse_param(kw, "Z", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - r_w = parse_param(kw, "W", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - typ = parse_param(kw, "TYPE", EnumConvertType, EnumConvertType.BOOLEAN.name) - xyzw = parse_param(kw, "AA", EnumConvertType.VEC4, (0, 0, 0, 0)) - seed = parse_param(kw, "SEED", EnumConvertType.INT, 0, 0) - yyzw = parse_param(kw, "BB", EnumConvertType.VEC4, (1, 1, 1, 1)) - x_str = parse_param(kw, "STRING", EnumConvertType.STRING, "") - params = list(zip_longest_fill(raw, r_x, r_y, r_z, r_w, typ, xyzw, seed, yyzw, x_str)) + raw = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, 0) + r_x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + r_y = parse_param(kw, Lexicon.Y, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + r_z = parse_param(kw, Lexicon.Z, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + r_w = parse_param(kw, Lexicon.W, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + typ = parse_param(kw, Lexicon.TYPE, EnumConvertType, EnumConvertType.BOOLEAN.name) + xyzw = parse_param(kw, Lexicon.DEFAULT_A, EnumConvertType.VEC4, (0, 0, 0, 0)) + yyzw = parse_param(kw, Lexicon.DEFAULT_B, EnumConvertType.VEC4, (1, 1, 1, 1)) + fill = parse_param(kw, Lexicon.FILL, EnumConvertType.BOOLEAN, False) + seed = parse_param(kw, Lexicon.SEED, EnumConvertType.INT, 0, 0) + params = list(zip_longest_fill(raw, r_x, r_y, r_z, r_w, typ, xyzw, yyzw, fill, seed)) results = [] pbar = ProgressBar(len(params)) old_seed = -1 - for idx, (raw, r_x, r_y, r_z, r_w, typ, xyzw, seed, yyzw, x_str) in enumerate(params): - default = [x_str] + for idx, (raw, r_x, r_y, r_z, r_w, typ, xyzw, yyzw, fill, seed) in enumerate(params): + # default = [x_str] default2 = None a, b, c, d = xyzw a2, b2, c2, d2 = yyzw @@ -126,6 +131,7 @@ Supplies raw or default values for various data types, supporting vector input w items[i] = out[i] results.append([out, *items]) pbar.update_absolute(idx) + if len(results) < 2: return results[0] return *list(zip(*results)), @@ -149,34 +155,28 @@ Outputs a VECTOR2. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "X": (COZY_TYPE_NUMBER, { + Lexicon.X: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "X channel value"}), - "Y": (COZY_TYPE_NUMBER, { + Lexicon.Y: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "Y channel value"}), - "A": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default X channel value"}), - "B": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default Y channel value"}), + Lexicon.DEFAULT: ("VEC2", { + "default": 0, "min": -sys.maxsize, "max": sys.maxsize,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[tuple[float, ...], tuple[int, ...]]: - x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - a = parse_param(kw, "A", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) - b = parse_param(kw, "B", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) - + x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + y = parse_param(kw, Lexicon.Y, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + default = parse_param(kw, Lexicon.DEFAULT, EnumConvertType.VEC2, 0, -sys.maxsize, sys.maxsize) result = [] - params = list(zip_longest_fill(x, y, a, b)) + params = list(zip_longest_fill(x, y, default)) pbar = ProgressBar(len(params)) - for idx, (x, y, a, b) in enumerate(params): - x = round(a, 9) if x is None else round(x, 9) - y = round(b, 9) if y is None else round(y, 9) + for idx, (x, y, default) in enumerate(params): + x = round(default[0], 9) if x is None else round(x, 9) + y = round(default[1], 9) if y is None else round(y, 9) result.append((x, y,)) pbar.update_absolute(idx) return result, @@ -200,42 +200,34 @@ Outputs a VECTOR3. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "X": (COZY_TYPE_NUMBER, { + Lexicon.X: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "X channel value"}), - "Y": (COZY_TYPE_NUMBER, { + Lexicon.Y: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "Y channel value"}), - "Z": (COZY_TYPE_NUMBER, { + Lexicon.Z: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "Z channel value"}), - "A": ("FLOAT", { + Lexicon.DEFAULT: ("VEC3", { "default": 0, "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "Default X channel value"}), - "B": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default Y channel value"}), - "C": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default Z channel value"}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[tuple[float, ...], tuple[int, ...]]: - x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - z = parse_param(kw, "Z", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - a = parse_param(kw, "A", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) - b = parse_param(kw, "B", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) - c = parse_param(kw, "C", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) + x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + y = parse_param(kw, Lexicon.Y, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + z = parse_param(kw, Lexicon.Z, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + default = parse_param(kw, Lexicon.DEFAULT, EnumConvertType.VEC3, 0, -sys.maxsize, sys.maxsize) result = [] - params = list(zip_longest_fill(x, y, z, a, b, c)) + params = list(zip_longest_fill(x, y, z, default)) pbar = ProgressBar(len(params)) - for idx, (x, y, z, a, b, c) in enumerate(params): - x = round(a, 9) if x is None else round(x, 9) - y = round(b, 9) if y is None else round(y, 9) - z = round(c, 9) if z is None else round(z, 9) + for idx, (x, y, z, default) in enumerate(params): + x = round(default[0], 9) if x is None else round(x, 9) + y = round(default[1], 9) if y is None else round(y, 9) + z = round(default[2], 9) if z is None else round(z, 9) result.append((x, y, z,)) pbar.update_absolute(idx) return result, @@ -259,76 +251,38 @@ Outputs a VEC4. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "X": (COZY_TYPE_NUMBER, { + Lexicon.X: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "X channel value"}), - "Y": (COZY_TYPE_NUMBER, { + Lexicon.Y: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "Y channel value"}), - "Z": (COZY_TYPE_NUMBER, { + Lexicon.Z: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "Z channel value"}), - "W": (COZY_TYPE_NUMBER, { + Lexicon.W: (COZY_TYPE_NUMBER, { "min": -sys.maxsize, "max": sys.maxsize, "tooltip": "W channel value"}), - "A": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default X channel value"}), - "B": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default Y channel value"}), - "C": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default Z channel value"}), - "D": ("FLOAT", { - "default": 0, "min": -sys.maxsize, "max": sys.maxsize, - "tooltip": "Default W channel value"}), + Lexicon.DEFAULT: ("VEC4", { + "default": 0, "min": -sys.maxsize, "max": sys.maxsize,}), } }) - return d + return Lexicon._parse(d) def run(self, **kw) -> tuple[tuple[float, ...], tuple[int, ...]]: - x = parse_param(kw, "X", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - y = parse_param(kw, "Y", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - z = parse_param(kw, "Z", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - w = parse_param(kw, "W", EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) - a = parse_param(kw, "A", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) - b = parse_param(kw, "B", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) - c = parse_param(kw, "C", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) - d = parse_param(kw, "D", EnumConvertType.FLOAT, 0, -sys.maxsize, sys.maxsize) + x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + y = parse_param(kw, Lexicon.Y, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + z = parse_param(kw, Lexicon.Z, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + w = parse_param(kw, Lexicon.W, EnumConvertType.FLOAT, None, -sys.maxsize, sys.maxsize) + default = parse_param(kw, Lexicon.DEFAULT, EnumConvertType.VEC4, 0, -sys.maxsize, sys.maxsize) result = [] params = list(zip_longest_fill(x, y, z, w, a, b, c, d)) pbar = ProgressBar(len(params)) for idx, (x, y, z, w, a, b, c, d) in enumerate(params): - x = round(a, 9) if x is None else round(x, 9) - y = round(b, 9) if y is None else round(y, 9) - z = round(c, 9) if z is None else round(z, 9) - w = round(d, 9) if w is None else round(w, 9) + x = round(default[0], 9) if x is None else round(x, 9) + y = round(default[1], 9) if y is None else round(y, 9) + z = round(default[2], 9) if z is None else round(z, 9) + w = round(default[3], 9) if w is None else round(w, 9) result.append((x, y, z, w,)) pbar.update_absolute(idx) return result, - -''' -class ParameterNode(CozyBaseNode): - NAME = "PARAMETER (JOV) ⚙️" - CATEGORY = JOV_CATEGORY - RETURN_TYPES = () - RETURN_NAMES = () - SORT = 100 - DESCRIPTION = """ - -""" - - @classmethod - def INPUT_TYPES(cls) -> InputType: - d = super().INPUT_TYPES() - d = deep_merge(d, { - "optional": { - "IN": (COZY_TYPE_ANY, {"default": None}), - } - }) - return d - - def run(self, ident, **kw) -> tuple[Any]: - return kw["IN"], -''' \ No newline at end of file diff --git a/web/nodes/delay.js b/web/nodes/delay.js index 5915740..630b654 100644 --- a/web/nodes/delay.js +++ b/web/nodes/delay.js @@ -65,8 +65,8 @@ app.registerExtension({ const onNodeCreated = nodeType.prototype.onNodeCreated; nodeType.prototype.onNodeCreated = async function () { const me = onNodeCreated?.apply(this); - const widget_time = this.widgets.find(w => w.name == 'TIME'); - const widget_enable = this.widgets.find(w => w.name == 'ENABLE'); + const widget_time = this.widgets.find(w => w.name == 'time'); + const widget_enable = this.widgets.find(w => w.name == 'enable'); this.total_timeout = 0; let showing = false; let delay_modal; diff --git a/web/nodes/graph.js b/web/nodes/graph.js index 2aaa9b1..d6460a8 100644 --- a/web/nodes/graph.js +++ b/web/nodes/graph.js @@ -27,7 +27,7 @@ app.registerExtension({ nodeType.prototype.onNodeCreated = async function () { const me = onNodeCreated?.apply(this); const self = this; - const widget_reset = this.widgets.find(w => w.name == 'RESET'); + const widget_reset = this.widgets.find(w => w.name == 'reset'); widget_reset.callback = async() => { widget_reset.value = false; apiJovimetrix(self.id, "reset"); diff --git a/web/nodes/lerp.js b/web/nodes/lerp.js index 6a53042..c9c2a29 100644 --- a/web/nodes/lerp.js +++ b/web/nodes/lerp.js @@ -15,10 +15,10 @@ app.registerExtension({ const onNodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { const me = onNodeCreated?.apply(this); - const alpha = this.widgets.find(w => w.name == 'ALPHA'); - widgetHookControl(this, 'TYPE', alpha, true); - widgetHookValue(this, 'TYPE', 'AA'); - widgetHookValue(this, 'TYPE', 'BB'); + const alpha = this.widgets.find(w => w.name == 'alpha'); + widgetHookControl(this, 'type', alpha, true); + widgetHookValue(this, 'type', 'aa'); + widgetHookValue(this, 'type', 'bb'); return me; } return nodeType; diff --git a/web/nodes/op_binary.js b/web/nodes/op_binary.js index 3e5d3d6..caf3660 100644 --- a/web/nodes/op_binary.js +++ b/web/nodes/op_binary.js @@ -15,8 +15,8 @@ app.registerExtension({ const onNodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { const me = onNodeCreated?.apply(this); - widgetHookValue(this, 'TYPE', 'AA'); - widgetHookValue(this, 'TYPE', 'BB'); + widgetHookValue(this, 'type', 'aa'); + widgetHookValue(this, 'type', 'bb'); return me; } diff --git a/web/nodes/op_unary.js b/web/nodes/op_unary.js index bd2b711..9e7c4d6 100644 --- a/web/nodes/op_unary.js +++ b/web/nodes/op_unary.js @@ -16,7 +16,7 @@ app.registerExtension({ const onNodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { const me = onNodeCreated?.apply(this); - widgetHookValue(this, 'TYPE', 'AA'); + widgetHookValue(this, 'type', 'aa'); return me; } /* diff --git a/web/nodes/queue.js b/web/nodes/queue.js index 46678f2..05b7857 100644 --- a/web/nodes/queue.js +++ b/web/nodes/queue.js @@ -47,10 +47,10 @@ app.registerExtension({ this.widget_report.inputEl.readOnly = true; this.widget_report.serializeValue = async () => { }; - const widget_queue = this.widgets.find(w => w.name == 'Q'); - const widget_batch = this.widgets.find(w => w.name == 'BATCH'); - const widget_hold = this.widgets.find(w => w.name == 'HOLD'); - const widget_reset = this.widgets.find(w => w.name == 'RESET'); + const widget_queue = this.widgets.find(w => w.name == 'q'); + const widget_batch = this.widgets.find(w => w.name == 'batch'); + const widget_hold = this.widgets.find(w => w.name == 'hold'); + const widget_reset = this.widgets.find(w => w.name == 'reset'); widget_queue.inputEl.addEventListener('input', function () { const value = widget_queue.value.split('\n'); @@ -98,7 +98,7 @@ app.registerExtension({ if (outputIndex == 0 && inputType == "COMBO") { // can link the "same" list -- user breaks it past that, their problem atm. - const widget_queue = this.widgets.find(w => w.name == 'Q'); + const widget_queue = this.widgets.find(w => w.name == 'queue'); const widget = inputNode.widgets.find(w => w.name == inputSlot.name); const values = widget.options.values.join('\n'); if (this.outputs[0].name != _prefix && widget_queue.value != values) { @@ -129,7 +129,7 @@ app.registerExtension({ this.outputs[0].name = widget.name; if (widget?.origType == "combo" || widget.type == "COMBO") { const values = widget.options.values; - const widget_queue = this.widgets.find(w => w.name == 'Q'); + const widget_queue = this.widgets.find(w => w.name == 'queue'); // remove all connections that don't match the list? widget_queue.value = values.join('\n'); update_list(this, values); diff --git a/web/nodes/tick.js b/web/nodes/tick.js index 5302a31..25588c9 100644 --- a/web/nodes/tick.js +++ b/web/nodes/tick.js @@ -17,13 +17,13 @@ app.registerExtension({ nodeType.prototype.onNodeCreated = async function () { const me = onNodeCreated?.apply(this); const self = this; - const widget_reset = this.widgets.find(w => w.name == 'RESET'); + const widget_reset = this.widgets.find(w => w.name == 'reset'); widget_reset.callback = async() => { widget_reset.value = false; apiJovimetrix(self.id, "reset"); } - self.widget_count = this.widgets.find(w => w.name == 'VAL'); + self.widget_count = this.widgets.find(w => w.name == 'value'); async function python_tick(event) { if (event.detail.id != self.id) { return; diff --git a/web/nodes/value.js b/web/nodes/value.js index fb790ed..8b714d3 100644 --- a/web/nodes/value.js +++ b/web/nodes/value.js @@ -21,8 +21,8 @@ app.registerExtension({ this.outputs[3].type = "*"; this.outputs[4].type = "*"; - const ab_data = widgetHookValue(this, 'TYPE', 'AA'); - widgetHookValue(this, 'TYPE', 'BB'); + const ab_data = widgetHookValue(this, 'type', 'aa'); + widgetHookValue(this, 'type', 'bb'); const oldCallback = ab_data.callback; ab_data.callback = () => {