diff --git a/core/calc.py b/core/calc.py index fed40a7..28f5cd6 100644 --- a/core/calc.py +++ b/core/calc.py @@ -298,68 +298,34 @@ The Binary Operation node executes binary operations like addition, subtraction, Lexicon.TYPE: (names_convert, {"default": names_convert[2], "tooltip":"Output type desired from resultant operation"}), Lexicon.FLIP: ("BOOLEAN", {"default": False}), - Lexicon.X: ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "tooltip":"Single value input"}), - Lexicon.IN_A+"2": ("VEC2", {"default": (0,0), - "label": [Lexicon.X, Lexicon.Y], - "tooltip":"2-value vector"}), - Lexicon.IN_A+"3": ("VEC3", {"default": (0,0,0), - "label": [Lexicon.X, Lexicon.Y, Lexicon.Z], - "tooltip":"3-value vector"}), - Lexicon.IN_A+"4": ("VEC4", {"default": (0,0,0,0), + Lexicon.IN_A+Lexicon.IN_A: ("VEC4", {"default": (0,0,0,0), "label": [Lexicon.X, Lexicon.Y, Lexicon.Z, Lexicon.W], - "tooltip":"4-value vector"}), - Lexicon.Y: ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "tooltip":"Single value input"}), - Lexicon.IN_B+"2": ("VEC2", {"default": (0,0), - "label": [Lexicon.X, Lexicon.Y], - "tooltip":"2-value vector"}), - Lexicon.IN_B+"3": ("VEC3", {"default": (0,0,0), - "label": [Lexicon.X, Lexicon.Y, Lexicon.Z], - "tooltip":"3-value vector"}), - Lexicon.IN_B+"4": ("VEC4", {"default": (0,0,0,0), + "tooltip":"value vector"}), + Lexicon.IN_B+Lexicon.IN_B: ("VEC4", {"default": (0,0,0,0), "label": [Lexicon.X, Lexicon.Y, Lexicon.Z, Lexicon.W], - "tooltip":"4-value vector"}), + "tooltip":"value vector"}), } }) return Lexicon._parse(d, cls) def run(self, **kw) -> Tuple[bool]: results = [] - A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, [None]) - B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, [None]) + A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, None) + B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, None) print(A, '-', B) - a_x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, 0) - a_xy = parse_param(kw, Lexicon.IN_A+"2", EnumConvertType.VEC2, [(0, 0)]) - a_xyz = parse_param(kw, Lexicon.IN_A+"3", EnumConvertType.VEC3, [(0, 0, 0)]) - a_xyzw = parse_param(kw, Lexicon.IN_A+"4", EnumConvertType.VEC4, [(0, 0, 0, 0)]) - b_x = parse_param(kw, Lexicon.Y, EnumConvertType.FLOAT, 0) - b_xy = parse_param(kw, Lexicon.IN_B+"2", EnumConvertType.VEC2, [(0, 0)]) - b_xyz = parse_param(kw, Lexicon.IN_B+"3", EnumConvertType.VEC3, [(0, 0, 0)]) - b_xyzw = parse_param(kw, Lexicon.IN_B+"4", EnumConvertType.VEC4, [(0, 0, 0, 0)]) + a_xyzw = parse_param(kw, Lexicon.IN_A+Lexicon.IN_A, EnumConvertType.VEC4, (0, 0, 0, 0)) + b_xyzw = parse_param(kw, Lexicon.IN_B+Lexicon.IN_B, EnumConvertType.VEC4, (0, 0, 0, 0)) op = parse_param(kw, Lexicon.FUNC, EnumConvertType.STRING, EnumBinaryOperation.ADD.name) typ = parse_param(kw, Lexicon.TYPE, EnumConvertType.STRING, EnumConvertType.FLOAT.name) flip = parse_param(kw, Lexicon.FLIP, EnumConvertType.BOOLEAN, False) - params = list(zip_longest_fill(A, B, a_x, a_xy, a_xyz, a_xyzw, - b_x, b_xy, b_xyz, b_xyzw, op, typ, flip)) + params = list(zip_longest_fill(A, B, a_xyzw, b_xyzw, op, typ, flip)) pbar = ProgressBar(len(params)) - for idx, (A, B, a_x, a_xy, a_xyz, a_xyzw, - b_x, b_xy, b_xyz, b_xyzw, op, typ, flip) in enumerate(params): - - # logger.debug(f'val {A}, {B}, {a_x}, {b_x}') - # use everything as float for precision + for idx, (A, B, a_xyzw, b_xyzw, op, typ, flip) in enumerate(params): + logger.debug(f'val {A}, {B}, {a_xyzw}, {b_xyzw}') typ = EnumConvertType[typ] - if typ in [EnumConvertType.VEC2, EnumConvertType.VEC2INT]: - val_a = parse_value(A, EnumConvertType.VEC4, A if A is not None else a_xy) - val_b = parse_value(B, EnumConvertType.VEC4, B if B is not None else b_xy) - elif typ in [EnumConvertType.VEC3, EnumConvertType.VEC3INT]: - val_a = parse_value(A, EnumConvertType.VEC4, A if A is not None else a_xyz) - val_b = parse_value(B, EnumConvertType.VEC4, B if B is not None else b_xyz) - elif typ in [EnumConvertType.VEC4, EnumConvertType.VEC4INT]: - 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) - else: - val_a = parse_value(A, EnumConvertType.VEC4, A if A is not None else a_x) - val_b = parse_value(B, EnumConvertType.VEC4, B if B is not None else b_x) - # logger.debug(f'val {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) + logger.debug(f'val {val_a}, {val_b}') if flip: val_a, val_b = val_b, val_a size = max(1, int(typ.value / 10)) @@ -632,16 +598,16 @@ The Lerp Node calculates linear interpolation between two values or vectors base return Lexicon._parse(d, cls) def run(self, **kw) -> Tuple[Any, Any]: - A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, [(0,0,0,0)], 0, 1) - B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, [(1,1,1,1)], 0, 1) + A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, (0,0,0,0), 0, 1) + B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, (1,1,1,1), 0, 1) a_x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, 0) - a_xy = parse_param(kw, Lexicon.IN_A+"2", EnumConvertType.VEC2, [(0, 0)]) - a_xyz = parse_param(kw, Lexicon.IN_A+"3", EnumConvertType.VEC3, [(0, 0, 0)]) - a_xyzw = parse_param(kw, Lexicon.IN_A+"4", EnumConvertType.VEC4, [(0, 0, 0, 0)]) + a_xy = parse_param(kw, Lexicon.IN_A+"2", EnumConvertType.VEC2, (0, 0)) + a_xyz = parse_param(kw, Lexicon.IN_A+"3", EnumConvertType.VEC3, (0, 0, 0)) + a_xyzw = parse_param(kw, Lexicon.IN_A+"4", EnumConvertType.VEC4, (0, 0, 0, 0)) b_x = parse_param(kw, Lexicon.Y, EnumConvertType.FLOAT, 0) - b_xy = parse_param(kw, Lexicon.IN_B+"2", EnumConvertType.VEC2, [(0, 0)]) - b_xyz = parse_param(kw, Lexicon.IN_B+"3", EnumConvertType.VEC3, [(0, 0, 0)]) - b_xyzw = parse_param(kw, Lexicon.IN_B+"4", EnumConvertType.VEC4, [(0, 0, 0, 0)]) + b_xy = parse_param(kw, Lexicon.IN_B+"2", EnumConvertType.VEC2, (0, 0)) + b_xyz = parse_param(kw, Lexicon.IN_B+"3", EnumConvertType.VEC3, (0, 0, 0)) + b_xyzw = parse_param(kw, Lexicon.IN_B+"4", EnumConvertType.VEC4, (0, 0, 0, 0)) alpha = parse_param(kw, Lexicon.FLOAT,EnumConvertType.FLOAT, 0, 0, 1) op = parse_param(kw, Lexicon.EASE, EnumConvertType.STRING, "NONE") typ = parse_param(kw, Lexicon.TYPE, EnumConvertType.STRING, EnumNumberType.FLOAT.name) @@ -723,8 +689,8 @@ The Swap Node swaps components between two vectors based on specified swizzle pa return Lexicon._parse(d, cls) def run(self, **kw) -> Tuple[torch.Tensor, torch.Tensor]: - pA = parse_param(kw, Lexicon.IN_A, EnumConvertType.VEC4, [(0,0,0,0)], 0, 1) - pB = parse_param(kw, Lexicon.IN_B, EnumConvertType.VEC4, [(0,0,0,0)], 0, 1) + pA = parse_param(kw, Lexicon.IN_A, EnumConvertType.VEC4, (0,0,0,0), 0, 1) + pB = parse_param(kw, Lexicon.IN_B, EnumConvertType.VEC4, (0,0,0,0), 0, 1) swap_x = parse_param(kw, Lexicon.SWAP_X, EnumConvertType.STRING, EnumSwizzle.A_X.name) x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, 0) swap_y = parse_param(kw, Lexicon.SWAP_Y, EnumConvertType.STRING, EnumSwizzle.A_Y.name) @@ -910,14 +876,14 @@ The Value Node supplies raw or default values for various data types, supporting r_w = parse_param(kw, Lexicon.W, EnumConvertType.FLOAT, None) typ = parse_param(kw, Lexicon.TYPE, EnumConvertType.STRING, EnumConvertType.BOOLEAN.name) x = parse_param(kw, Lexicon.X_RAW, EnumConvertType.FLOAT, 0) - xy = parse_param(kw, Lexicon.IN_A+"2", EnumConvertType.VEC2, [(0, 0)]) - xyz = parse_param(kw, Lexicon.IN_A+"3", EnumConvertType.VEC3, [(0, 0, 0)]) - xyzw = parse_param(kw, Lexicon.IN_A+"4", EnumConvertType.VEC4, [(0, 0, 0, 0)]) + xy = parse_param(kw, Lexicon.IN_A+"2", EnumConvertType.VEC2, (0, 0)) + xyz = parse_param(kw, Lexicon.IN_A+"3", EnumConvertType.VEC3, (0, 0, 0)) + xyzw = parse_param(kw, Lexicon.IN_A+"4", EnumConvertType.VEC4, (0, 0, 0, 0)) seed = parse_param(kw, Lexicon.RANDOM, EnumConvertType.INT, 0, 0) y = parse_param(kw, Lexicon.Y_RAW, EnumConvertType.FLOAT, 0) - yy = parse_param(kw, Lexicon.IN_B+"2", EnumConvertType.VEC2, [(0, 0)]) - yyz = parse_param(kw, Lexicon.IN_B+"3", EnumConvertType.VEC3, [(0, 0, 0)]) - yyzw = parse_param(kw, Lexicon.IN_B+"4", EnumConvertType.VEC4, [(0, 0, 0, 0)]) + yy = parse_param(kw, Lexicon.IN_B+"2", EnumConvertType.VEC2, (0, 0)) + yyz = parse_param(kw, Lexicon.IN_B+"3", EnumConvertType.VEC3, (0, 0, 0)) + yyzw = parse_param(kw, Lexicon.IN_B+"4", EnumConvertType.VEC4, (0, 0, 0, 0)) x_str = parse_param(kw, Lexicon.STRING, EnumConvertType.STRING, "") params = list(zip_longest_fill(raw, r_x, r_y, r_z, r_w, typ, x, xy, xyz, xyzw, seed, y, yy, yyz, yyzw, x_str)) results = [] @@ -976,7 +942,7 @@ The Value Node supplies raw or default values for various data types, supporting ret.extend(extra) results.append(ret) pbar.update_absolute(idx) - return list(zip(*results)) + return *list(zip(*results)), class WaveGeneratorNode(JOVBaseNode): NAME = "WAVE GEN (JOV) 🌊" diff --git a/core/compose.py b/core/compose.py index 8bfb2f7..7b75e88 100644 --- a/core/compose.py +++ b/core/compose.py @@ -98,12 +98,12 @@ Enhance and modify images with various effects using the Adjust Node. Apply effe op = parse_param(kw, Lexicon.FUNC, EnumConvertType.STRING, EnumAdjustOP.BLUR.name) radius = parse_param(kw, Lexicon.RADIUS, EnumConvertType.INT, 3, 3) amt = parse_param(kw, Lexicon.VALUE, EnumConvertType.FLOAT, 0, 0, 1) - 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) + 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, 0) 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) + 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, amt, lohi, lmh, hsv, contrast, gamma, matte, invert)) @@ -242,9 +242,9 @@ Combines two input images using various blending modes, such as normal, screen, alpha = parse_param(kw, Lexicon.A, EnumConvertType.FLOAT, 1, 0, 1) flip = parse_param(kw, Lexicon.FLIP, EnumConvertType.BOOLEAN, False) mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC3INT, [(0, 0, 0)], 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC3INT, (0, 0, 0), 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 = [] @@ -376,7 +376,7 @@ Adjust the color scheme of one image to match another with the Color Match Node. num_colors = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 255) flip = parse_param(kw, Lexicon.FLIP, EnumConvertType.BOOLEAN, False) invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) params = list(zip_longest_fill(pA, pB, colormap, colormatch_mode, colormatch_map, num_colors, flip, invert, matte)) images = [] pbar = ProgressBar(len(params)) @@ -490,11 +490,11 @@ Extract a portion of an input image or resize it. It supports various cropping m pA = parse_param(kw, Lexicon.PIXEL, EnumConvertType.IMAGE, None) func = parse_param(kw, Lexicon.FUNC, EnumConvertType.STRING, EnumCropMode.CENTER.name) # if less than 1 then use as scalar, over 1 = int(size) - xy = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, [(0, 0,)], 1) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) - 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) - color = parse_param(kw, Lexicon.RGB, EnumConvertType.VEC3INT, [(0, 0, 0,)], 0, 255) + xy = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, (0, 0,), 1) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) + 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) + color = parse_param(kw, Lexicon.RGB, EnumConvertType.VEC3INT, (0, 0, 0,), 0, 255) params = list(zip_longest_fill(pA, func, xy, wihi, tltr, blbr, color)) images = [] pbar = ProgressBar(len(params)) @@ -544,11 +544,11 @@ Create masks based on specific color ranges within an image. Specify the color r def run(self, **kw) -> Tuple[Any, ...]: pA = parse_param(kw, Lexicon.PIXEL_A, EnumConvertType.IMAGE, None) - start = parse_param(kw, Lexicon.START, EnumConvertType.VEC3INT, [(128,128,128)], 0, 255) - use_range = parse_param(kw, Lexicon.BOOLEAN, EnumConvertType.VEC3, [(0,0,0)], 0, 255) - end = parse_param(kw, Lexicon.END, EnumConvertType.VEC3INT, [(128,128,128)], 0, 255) - fuzz = parse_param(kw, Lexicon.FLOAT, EnumConvertType.VEC3, [(0.5,0.5,0.5)], 0, 1) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255) + start = parse_param(kw, Lexicon.START, EnumConvertType.VEC3INT, (128,128,128), 0, 255) + use_range = parse_param(kw, Lexicon.BOOLEAN, EnumConvertType.VEC3, (0,0,0), 0, 255) + end = parse_param(kw, Lexicon.END, EnumConvertType.VEC3INT, (128,128,128), 0, 255) + fuzz = parse_param(kw, Lexicon.FLOAT, 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)) @@ -592,7 +592,7 @@ Combine multiple input images into a single image by summing their pixel values. pA = [image_convert(tensor2cv(img), 4) for img in pA] mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) images = [] params = list(zip_longest_fill(mode, sample, matte)) pbar = ProgressBar(len(params)) @@ -644,9 +644,9 @@ Combines individual color channels (red, green, blue) along with an optional mas B = parse_param(kw, Lexicon.B, EnumConvertType.IMAGE, None) A = parse_param(kw, Lexicon.A, EnumConvertType.IMAGE, None) mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC3INT, [(0, 0, 0)], 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC3INT, (0, 0, 0), 0, 255) if len(R)+len(B)+len(G)+len(A) == 0: img = channel_solid(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE, 0, EnumImageType.BGRA) return list(cv2tensor_full(img, matte)) @@ -816,9 +816,9 @@ Merge multiple input images into a single composite image by stacking them along axis = parse_param(kw, Lexicon.AXIS, EnumConvertType.STRING, EnumOrientation.GRID.name)[0] stride = parse_param(kw, Lexicon.STEP, EnumConvertType.INT, 1, 1)[0] mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name)[0] - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE)[0] + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE)[0] sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name)[0] - matte = parse_param(kw, Lexicon.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] images = [tensor2cv(img) for img in images] axis = EnumOrientation[axis] img = image_stack(images, axis, stride, matte) @@ -911,21 +911,21 @@ Applies various geometric transformations to images, including translation, rota def run(self, **kw) -> Tuple[torch.Tensor, torch.Tensor]: pA = parse_param(kw, Lexicon.PIXEL, EnumConvertType.IMAGE, None) - offset = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, [(0, 0)]) + offset = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, (0, 0)) angle = parse_param(kw, Lexicon.ANGLE, EnumConvertType.FLOAT, 0) - size = parse_param(kw, Lexicon.SIZE, EnumConvertType.VEC2, [(1, 1)], 0.001) + size = parse_param(kw, Lexicon.SIZE, EnumConvertType.VEC2, (1, 1), 0.001) edge = parse_param(kw, Lexicon.EDGE, EnumConvertType.STRING, EnumEdge.CLIP.name) mirror = parse_param(kw, Lexicon.MIRROR, EnumConvertType.STRING, 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.VEC2INT, [(1, 1)], 1) + mirror_pivot = parse_param(kw, Lexicon.PIVOT, EnumConvertType.VEC2, (0.5, 0.5), 0, 1) + tile_xy = parse_param(kw, Lexicon.TILE, EnumConvertType.VEC2INT, (1, 1), 1) proj = parse_param(kw, Lexicon.PROJECTION, EnumConvertType.STRING, 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) + 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, EnumConvertType.STRING, EnumScaleMode.NONE.name) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) params = list(zip_longest_fill(pA, 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/create.py b/core/create.py index 5acdb4d..a2a03bb 100644 --- a/core/create.py +++ b/core/create.py @@ -65,8 +65,8 @@ The Constant node generates constant images or masks of a specified size and col def run(self, **kw) -> Tuple[torch.Tensor, torch.Tensor]: pA = parse_param(kw, Lexicon.PIXEL, EnumConvertType.IMAGE, None) - matte = parse_param(kw, Lexicon.RGBA_A, EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) + matte = parse_param(kw, Lexicon.RGBA_A, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) images = [] @@ -130,11 +130,11 @@ The Shape Generation node creates images representing various shapes such as cir sides = parse_param(kw, Lexicon.SIDES, EnumConvertType.INT, 3, 3, 512) angle = parse_param(kw, Lexicon.ANGLE, EnumConvertType.FLOAT, 0) edge = parse_param(kw, Lexicon.EDGE, EnumConvertType.STRING, 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, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) - color = parse_param(kw, Lexicon.RGBA_A, EnumConvertType.VEC4INT, [(255, 255, 255, 255)], 0, 255) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255) + 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, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) + color = parse_param(kw, Lexicon.RGBA_A, 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 = [] @@ -236,16 +236,16 @@ The Text Generation node generates images containing text based on user-defined 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.RGBA_A, EnumConvertType.VEC4INT, [(255,255,255,255)], 0, 255) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC3INT, [(0,0,0)], 0, 255) + color = parse_param(kw, Lexicon.RGBA_A, EnumConvertType.VEC4INT, (255,255,255,255), 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC3INT, (0,0,0), 0, 255) columns = parse_param(kw, Lexicon.COLUMNS, EnumConvertType.INT, 0) font_size = parse_param(kw, Lexicon.FONT_SIZE, EnumConvertType.INT, 1) align = parse_param(kw, Lexicon.ALIGN, EnumConvertType.STRING, EnumAlignment.CENTER.name) justify = parse_param(kw, Lexicon.JUSTIFY, EnumConvertType.STRING, EnumJustify.CENTER.name) margin = parse_param(kw, Lexicon.MARGIN, EnumConvertType.INT, 0) line_spacing = parse_param(kw, Lexicon.SPACING, EnumConvertType.INT, 25) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) - pos = parse_param(kw, Lexicon.XY, EnumConvertType.VEC2, [(0, 0)], 1, -1) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) + 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, EnumConvertType.STRING, EnumEdge.CLIP.name) invert = parse_param(kw, Lexicon.INVERT, EnumConvertType.BOOLEAN, False) @@ -411,9 +411,9 @@ The Wave Graph node visualizes audio waveforms as bars. Adjust parameters like t wave = parse_param(kw, Lexicon.WAVE, EnumConvertType.ANY, None) bars = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 50, 1, 8192) thick = parse_param(kw, Lexicon.THICK, EnumConvertType.FLOAT, 0.75, 0, 1) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) - rgb_a = parse_param(kw, Lexicon.RGBA_A, EnumConvertType.VEC4INT, [(196, 0, 196)], 0, 255) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(42, 12, 42)], 0, 255) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) + rgb_a = parse_param(kw, Lexicon.RGBA_A, EnumConvertType.VEC4INT, (196, 0, 196), 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (42, 12, 42), 0, 255) params = list(zip_longest_fill(wave, bars, wihi, thick, rgb_a, matte)) images = [] pbar = ProgressBar(len(params)) diff --git a/core/device_stream.py b/core/device_stream.py index b5179cc..3eb7fe9 100644 --- a/core/device_stream.py +++ b/core/device_stream.py @@ -128,11 +128,11 @@ The Stream Reader node captures frames from various sources such as URLs, camera if wait: return self.__last images = [] - batch_size, rate = parse_param(kw, Lexicon.BATCH, EnumConvertType.VEC2INT, [(1, 30)], 1)[0] + batch_size, rate = parse_param(kw, Lexicon.BATCH, EnumConvertType.VEC2INT, (1, 30), 1)[0] pbar = ProgressBar(batch_size) rate = 1. / rate - width, height = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)])[0] - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0,0,0,255)], 0, 255)[0] + width, height = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE))[0] + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0,0,0,255), 0, 255)[0] mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name)[0] mode = EnumScaleMode[mode] sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name)[0] @@ -297,8 +297,8 @@ The Stream Writer node sends frames to a specified route, typically for live str def run(self, **kw) -> Tuple[torch.Tensor]: route = parse_param(kw, Lexicon.ROUTE, EnumConvertType.STRING, "/stream") images = parse_param(kw, Lexicon.PIXEL, EnumConvertType.IMAGE, None) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0,0,0,0)], 0, 255) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0,0,0,0), 0, 255) mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) params = list(zip_longest_fill(route, images, wihi, matte, mode, sample)) @@ -367,9 +367,9 @@ The Spout Writer node sends frames to a specified Spout receiver application for host = parse_param(kw, Lexicon.ROUTE, EnumConvertType.STRING, "") #fps = parse_param(kw, Lexicon.FPS, EnumConvertType.INT, 30) mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0,0,0,0)], 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0,0,0,0), 0, 255) # results = [] params = list(zip_longest_fill(images, host, mode, wihi, sample, matte)) pbar = ProgressBar(len(params)) diff --git a/core/utility.py b/core/utility.py index bd50fb1..cb0cd9d 100644 --- a/core/utility.py +++ b/core/utility.py @@ -166,7 +166,7 @@ Processes a batch of data based on the selected mode, such as merging, picking, data_list = parse_dynamic(kw, Lexicon.UNKNOWN, EnumConvertType.ANY, None) mode = parse_param(kw, Lexicon.BATCH_MODE, EnumConvertType.STRING, EnumBatchMode.MERGE.name) index = parse_param(kw, Lexicon.INDEX, EnumConvertType.INT, EnumBatchMode.MERGE.name) - slice_range = parse_param(kw, Lexicon.RANGE, EnumConvertType.VEC3INT, [(0, 0, 1)]) + slice_range = parse_param(kw, Lexicon.RANGE, EnumConvertType.VEC3INT, (0, 0, 1)) indices = parse_param(kw, Lexicon.STRING, EnumConvertType.STRING, "") seed = parse_param(kw, Lexicon.SEED, EnumConvertType.INT, 0) # print(seed) @@ -391,7 +391,7 @@ The Graph node visualizes a series of data points over time. It accepts a dynami def run(self, ident, **kw) -> Tuple[torch.Tensor]: slice = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, 60)[0] - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], 1)[0] + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), 1)[0] if parse_reset(ident) > 0 or parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0]: self.__history = [] longest_edge = 0 @@ -431,9 +431,9 @@ The Graph node visualizes a series of data points over time. It accepts a dynami def run(self, **kw) -> None: q = parse_param(kw, Lexicon.QUEUE, EnumConvertType.STRING, "") mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name) - wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, [(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE)], MIN_IMAGE_SIZE) + wihi = parse_param(kw, Lexicon.WH, EnumConvertType.VEC2INT, (MIN_IMAGE_SIZE, MIN_IMAGE_SIZE), MIN_IMAGE_SIZE) sample = parse_param(kw, Lexicon.SAMPLE, EnumConvertType.STRING, EnumInterpolation.LANCZOS4.name) - matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, [(0, 0, 0, 255)], 0, 255) + matte = parse_param(kw, Lexicon.MATTE, EnumConvertType.VEC4INT, (0, 0, 0, 255), 0, 255) params = list(zip_longest_fill(q, mode, wihi, sample, matte)) images = [] pbar = ProgressBar(len(params)) diff --git a/sup/util.py b/sup/util.py index 1c4b92d..64cc97f 100644 --- a/sup/util.py +++ b/sup/util.py @@ -180,7 +180,7 @@ def parse_value(val:Any, typ:EnumConvertType, default: Any, elif typ == EnumConvertType.IMAGE: # covert image into image? just skip if already an image if not isinstance(new_val, (torch.Tensor,)): - color = parse_value(new_val, EnumConvertType.VEC4INT, [(0,0,0,255)], 0, 255) + color = parse_value(new_val, EnumConvertType.VEC4INT, (0,0,0,255), 0, 255) color = torch.tensor(color, dtype=torch.int32).tolist() new_val = torch.empty((MIN_IMAGE_SIZE, MIN_IMAGE_SIZE, 4), dtype=torch.uint8) new_val[0,:,:] = color[0] @@ -213,7 +213,7 @@ def parse_param(data:dict, key:str, typ:EnumConvertType, default: Any, # latents.... if 'samples' in val: val = tuple(x for x in val["samples"]) - elif ('0' in val and '1' in val) or (0 in val and 1 in val): + elif ('0' in val) or (0 in val): val = tuple(val.get(i, val.get(str(i), 0)) for i in range(min(len(val), 4))) elif 'x' in val and 'y' in val: val = tuple(val.get(c, 0) for c in 'xyzw') diff --git a/web/nodes/calc_binary.js b/web/nodes/calc_binary.js index 7462515..e748f6d 100644 --- a/web/nodes/calc_binary.js +++ b/web/nodes/calc_binary.js @@ -20,65 +20,44 @@ app.registerExtension({ const onNodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { const me = onNodeCreated?.apply(this) + const widget_x4 = this.widgets.find(w => w.name === '🅰️🅰️'); + const widget_y4 = this.widgets.find(w => w.name === '🅱️🅱️'); + widget_x4.options.menu = false; + widget_y4.options.menu = false; + let bool_x = {0:false} + let bool_y = {0:false} + let track_xyzw = {0:0, 1:0, 2:0, 3:0}; + let track_yyzw = {0:0, 1:0, 2:0, 3:0}; const combo = this.widgets.find(w => w.name === '❓'); combo.callback = () => { - const widget_x = this.widgets.find(w => w.name === '🇽'); - const widget_xy = this.widgets.find(w => w.name === '🅰️2'); - const widget_xyz = this.widgets.find(w => w.name === '🅰️3'); - const widget_xyzw = this.widgets.find(w => w.name === '🅰️4'); - const widget_y = this.widgets.find(w => w.name === '🇾'); - const widget_yy = this.widgets.find(w => w.name === '🅱️2'); - const widget_yyz = this.widgets.find(w => w.name === '🅱️3'); - const widget_yyzw = this.widgets.find(w => w.name === '🅱️4'); - widget_x.options.menu = false; - widget_xy.options.menu = false; - widget_xyz.options.menu = false; - widget_xyzw.options.menu = false; - widget_y.options.menu = false; - widget_yy.options.menu = false; - widget_yyz.options.menu = false; - widget_yyzw.options.menu = false; - // - widget_hide(this, widget_x, "-jovi"); - widget_hide(this, widget_xy, "-jovi"); - widget_hide(this, widget_xyz, "-jovi"); - widget_hide(this, widget_xyzw, "-jovi"); - widget_hide(this, widget_y, "-jovi"); - widget_hide(this, widget_yy, "-jovi"); - widget_hide(this, widget_yyz, "-jovi"); - widget_hide(this, widget_yyzw, "-jovi"); - // - if (combo.value == "BOOLEAN") { - show_boolean(widget_x); - show_boolean(widget_y); - } else if (combo.value == "FLOAT") { - process_value(widget_x, 3); - process_value(widget_y, 3); - } else if (combo.value == "INT") { - process_value(widget_x); - process_value(widget_y); - } else if (combo.value == "VEC2INT") { - show_vector(widget_xy); - show_vector(widget_yy); - } else if (combo.value == "VEC2") { - show_vector(widget_xy, 3); - show_vector(widget_yy, 3); - } else if (combo.value == "VEC3INT") { - show_vector(widget_xyz); - show_vector(widget_yyz); - } else if (combo.value == "VEC3") { - show_vector(widget_xyz, 3); - show_vector(widget_yyz, 3); - } else if (combo.value == "VEC4INT") { - show_vector(widget_xyzw); - show_vector(widget_yyzw); - } else if (combo.value == "VEC4") { - show_vector(widget_xyzw, 3); - show_vector(widget_yyzw, 3); - } + const data_x = (combo.value === "BOOLEAN") ? bool_x : track_xyzw; + const data_y = (combo.value === "BOOLEAN") ? bool_y : track_yyzw; + show_vector(widget_x4, data_x, combo.value); + show_vector(widget_y4, data_y, combo.value); this.outputs[0].name = widget_type_name(combo.value); fitHeight(this); } + + widget_x4.callback = () => { + console.info('callback') + if (widget_x4.type === "toggle") { + bool_x[0] = widget_x4.value; + } else { + Object.keys(widget_x4.value).forEach((key) => { + track_xyzw[key] = widget_x4.value[key]; + }); + } + } + + widget_y4.callback = () => { + if (widget_y4.type === "toggle") { + bool_y[0] = widget_y4.value; + } else { + Object.keys(widget_y4.value).forEach((key) => { + track_yyzw[key] = widget_y4.value[key]; + }); + } + } setTimeout(() => { combo.callback(); }, 10); return me; } diff --git a/web/util/util_dom.js b/web/util/util_dom.js index 5186940..5c1e15b 100644 --- a/web/util/util_dom.js +++ b/web/util/util_dom.js @@ -29,7 +29,7 @@ export function foldableToggle(elementId, symbolId) { } } -export function inner_value_change(widget, value, event = undefined) { +export function inner_value_change(node, pos, widget, value, event=undefined) { const type = widget.type.includes("INT") ? Number : parseFloat widget.value = convertArrayToObject(value, Object.keys(value).length, type); if ( @@ -40,6 +40,7 @@ export function inner_value_change(widget, value, event = undefined) { node.setProperty(widget.options.property, widget.value) } if (widget.callback) { + widget.callback(widget.value, app.canvas, node, pos, event) } } diff --git a/web/util/util_widget.js b/web/util/util_widget.js index 0392bc9..3fa31dd 100644 --- a/web/util/util_widget.js +++ b/web/util/util_widget.js @@ -4,6 +4,8 @@ * */ +const regex = /\d/; + const my_map = { STRING: "📝", BOOLEAN: "🇴", @@ -105,17 +107,20 @@ export function widget_hide(node, widget, suffix = '') { export function widget_show(widget) { if (widget?.origType) { widget.type = widget.origType; + delete widget.origType; + } + if (widget?.origComputeSize) { + widget.computeSize = widget.origComputeSize; + delete widget.origComputeSize; + } + //widget.computeSize = (target_width) => [target_width, 20]; + if (widget?.origSerializeValue) { + widget.serializeValue = widget.origSerializeValue; + delete widget.origSerializeValue; } - widget.computeSize = widget.origComputeSize; - widget.computeSize = (target_width) => [target_width, 20]; - widget.serializeValue = widget.origSerializeValue; - delete widget.origType; - delete widget.origComputeSize; - delete widget.origSerializeValue; - widget.hidden = false; - // Hide any linked widgets, e.g. seed+seedControl - if (widget.linkedWidgets) { + widget.hidden = false; + if (widget?.linkedWidgets) { for (const w of widget.linkedWidgets) { widget_show(w) } @@ -128,17 +133,39 @@ export function show_boolean(widget_x) { widget_x.type = "toggle"; } -export function show_vector(widget, precision=0, size=4) { - widget_show(widget); - widget.origType = widget.type; - if (precision == 0) { - widget.options.step = 1; - widget.options.round = 1; - widget.options.precision = 0; +export function show_vector(widget, values={}, type=undefined, precision=6) { + if (["FLOAT", "INT"].includes(type)) { + type = "VEC1"; + } else if (type == "BOOLEAN") { + type = "toggle"; + type = "toggle"; + } + if (type !== undefined) { + widget.type = type; + } + if (widget.type == 'toggle') { + widget.value = values[0] > 0 ? true : false; } else { - widget.options.step = 1 / (10^Math.max(1, precision-2)); - widget.options.round = 1 / (10^Math.max(1, precision-1)); - widget.options.precision = precision; + let size = 1; + const match = regex.exec(widget.type); + if (match) { + size = match[0]; + } + if (widget.type.endsWith('INT')) { + widget.options.step = 1; + widget.options.round = 1; + widget.options.precision = 0; + } else { + widget.options.step = 1 / (10^Math.max(1, precision-2)); + widget.options.round = 1 / (10^Math.max(1, precision-1)); + widget.options.precision = precision; + } + widget.value = {}; + for (let i = 0; i < size; i++) { + console.info(widget.type.endsWith('INT')) + widget.value[i] = widget.type.endsWith('INT') ? Math.round(values[i]) : Number(values[i]); + //widget.value[i] = values[i] !== undefined ? k : 0; + } } } diff --git a/web/widget/widget_vector.js b/web/widget/widget_vector.js index 9dbf7c2..d044111 100644 --- a/web/widget/widget_vector.js +++ b/web/widget/widget_vector.js @@ -20,7 +20,10 @@ export const VectorWidget = (app, inputName, options, initial, desc='') => { } let isDragging; - let step = options[0].includes(['VEC', 'vec']) ? 0.01 : 1; + let step = 0.01; + if (options[0].endsWith('INT')) { + step = 1; + } widget.options.step = widget.options?.step || step; widget.options.rgb = widget.options?.rgb || false; @@ -32,7 +35,7 @@ export const VectorWidget = (app, inputName, options, initial, desc='') => { let picker; widget.draw = function(ctx, node, width, Y, height) { - if (this.type !== options[0] && app.canvas.ds.scale > 0.5) return + if ((!this.type.startsWith("VEC") && this.type != "COORD2D") && app.canvas.ds.scale > 0.5) return; const precision = widget.options?.precision !== undefined ? widget.options.precision : 0; ctx.save() ctx.beginPath() @@ -72,22 +75,22 @@ export const VectorWidget = (app, inputName, options, initial, desc='') => { // value ctx.fillStyle = LiteGraph.WIDGET_TEXT_COLOR - const it = this.value[idx.toString()] - const value = Number(it).toFixed(Math.min(2, precision)) + const it = this.value[idx.toString()]; + const value = Number(it).toFixed(Math.min(2, precision)); converted.push(value); - const text = value.toString() - ctx.fillText(text, x + element_width2 - text.length * 3.3, Y + height/2 + offset_y) - ctx.restore() - x += element_width + const text = value.toString(); + ctx.fillText(text, x + element_width2 - text.length * 3.3, Y + height/2 + offset_y); + ctx.restore(); + x += element_width; } if (this.options.rgb) { try { ctx.fillStyle = rgb2hex(converted); } catch (e) { - ctx.fillStyle = "#000" + ctx.fillStyle = "#000"; } - ctx.roundRect(width - 1.15 * widget_padding, Y, 0.65 * widget_padding, height, 16) + ctx.roundRect(width - 1.15 * widget_padding, Y, 0.65 * widget_padding, height, 16); ctx.fill() } ctx.restore() @@ -153,7 +156,7 @@ export const VectorWidget = (app, inputName, options, initial, desc='') => { clamp(this, v, idx) } else if (e.type === 'pointerup') { isDragging = undefined - if (e.click_time < 200 && delta == 0) { + if (e.click_time < 100 && delta == 0) { const label = this.options?.label ? this.name + '➖' + this.options.label?.[idx] : this.name; LGraphCanvas.active_canvas.prompt(label, this.value[idx], function(v) { if (/^[0-9+\-*/()\s]+|\d+\.\d+$/.test(v)) { @@ -165,7 +168,7 @@ export const VectorWidget = (app, inputName, options, initial, desc='') => { setTimeout( function () { clamp(this, v, idx) - inner_value_change(this, this.value, e) + inner_value_change(node, pos, this, this.value, e) }.bind(this), 20) } }.bind(this), e); @@ -174,13 +177,13 @@ export const VectorWidget = (app, inputName, options, initial, desc='') => { if (old_value != this.value) { setTimeout( function () { - //clamp(this, this.value[idx] || 0, idx) - inner_value_change(this, this.value, e) + inner_value_change(node, pos, this, this.value, e) }.bind(this), 20) } - app.canvas.setDirty(true) } + } + app.canvas.setDirty(true, true); } widget.computeSize = function (width) { @@ -188,11 +191,16 @@ export const VectorWidget = (app, inputName, options, initial, desc='') => { } widget.serializeValue = async () => { - if (typeof widget.value === 'object' && widget.value !== null && !Array.isArray(widget.value)) { + if (widget.value === null) { + return null; + } + if (typeof widget.value === 'object' && !Array.isArray(widget.value)) { // Check if widget.value is a dictionary return widget.value; + } else if (Array.isArray(widget.value)) { + return widget.value.reduce((acc, tuple, index) => ({ ...acc, [index]: tuple }), {}); } - return widget.value.reduce((acc, tuple, index) => ({ ...acc, [index]: tuple }), {}); + return widget.value; } widget.desc = desc @@ -210,7 +218,7 @@ app.registerExtension({ widget: node.addCustomWidget(VectorWidget(app, inputName, inputData, [0, 0, 0])), }), VEC4: (node, inputName, inputData, app) => ({ - widget: node.addCustomWidget(VectorWidget(app, inputName, inputData, [0, 0, 0, 1])), + widget: node.addCustomWidget(VectorWidget(app, inputName, inputData, [0, 0, 0, 0])), }) } },