From 6cf6c1861ba3a01a522fccc1114cc9d7447004fd Mon Sep 17 00:00:00 2001 From: "Alexander G. Morano" Date: Mon, 24 Feb 2025 02:18:24 -0500 Subject: [PATCH] removed duplicated nodes for vector INT* types better akashic outputs parse_param* ANY parse adjustment for all input --- __init__.py | 51 +++++----- core/calc.py | 233 ++++++++++++++----------------------------- core/utility/info.py | 21 ++-- node_list.json | 3 - sup/util.py | 7 +- web/nodes/akashic.js | 11 +- 6 files changed, 117 insertions(+), 209 deletions(-) diff --git a/__init__.py b/__init__.py index e4c1eff..8fa0eda 100644 --- a/__init__.py +++ b/__init__.py @@ -109,6 +109,29 @@ MARKDOWN = [ "MIDI-FILTER", "STREAM-WRITER" ] +# ============================================================================== +# === TYPE === +# ============================================================================== + +class AnyType(str): + """AnyType input wildcard trick taken from pythongossss's: + + https://github.com/pythongosssss/ComfyUI-Custom-Scripts + """ + def __ne__(self, __value: object) -> bool: + return False + +JOV_TYPE_ANY = AnyType("*") + +# want to make explicit entries; comfy only looks for single type +JOV_TYPE_NUMBER = "BOOLEAN,FLOAT,INT" +JOV_TYPE_VECTOR = "VEC2,VEC3,VEC4,VEC2INT,VEC3INT,VEC4INT,COORD2D,COORD3D" +JOV_TYPE_NUMERICAL = f"{JOV_TYPE_NUMBER},{JOV_TYPE_VECTOR}" +JOV_TYPE_IMAGE = "IMAGE,MASK" +JOV_TYPE_FULL = f"{JOV_TYPE_NUMBER},{JOV_TYPE_IMAGE}" + +JOV_TYPE_FULL = JOV_TYPE_ANY + # ============================================================================== # === LEXICON === # ============================================================================== @@ -406,12 +429,9 @@ class JOVBaseNode: NOT_IDEMPOTENT = True RETURN_TYPES = () FUNCTION = "run" - # instance map for caching - INSTANCE = {} @classmethod - def VALIDATE_INPUTS(cls, *arg, **kw) -> bool: - # logger.debug(f'validate -- {arg} {kw}') + def VALIDATE_INPUTS(cls, input_types) -> bool: return True @classmethod @@ -458,14 +478,6 @@ class DynamicInputType(dict): def __contains__(self, key: Any) -> Literal[True]: return True -class AnyType(str): - """AnyType input wildcard trick taken from pythongossss's: - - https://github.com/pythongosssss/ComfyUI-Custom-Scripts - """ - def __ne__(self, __value: object) -> bool: - return False - class DynamicOutputType(tuple): """A special class that will return additional "AnyType" strings beyond defined values. @@ -478,21 +490,6 @@ class DynamicOutputType(tuple): return AnyType("*") return super().__getitem__(index) -JOV_TYPE_ANY = AnyType("*") - -# want to make explicit entries; comfy only looks for single type -JOV_TYPE_COMFY = "BOOLEAN,FLOAT,INT" -JOV_TYPE_VECTOR = "VEC2,VEC3,VEC4,VEC2INT,VEC3INT,VEC4INT,COORD2D" -JOV_TYPE_NUMBER = f"{JOV_TYPE_COMFY},{JOV_TYPE_VECTOR}" -JOV_TYPE_IMAGE = "IMAGE,MASK" -JOV_TYPE_FULL = f"{JOV_TYPE_NUMBER},{JOV_TYPE_IMAGE}" - -JOV_TYPE_COMFY = JOV_TYPE_ANY -JOV_TYPE_VECTOR = JOV_TYPE_ANY -JOV_TYPE_NUMBER = JOV_TYPE_ANY -JOV_TYPE_IMAGE = JOV_TYPE_ANY -JOV_TYPE_FULL = JOV_TYPE_ANY - # ============================================================================== # === DOCUMENTATION SUPPORT # ============================================================================== diff --git a/core/calc.py b/core/calc.py index 185df5e..16e42e5 100644 --- a/core/calc.py +++ b/core/calc.py @@ -3,11 +3,12 @@ Jovimetrix - http://www.github.com/amorano/jovimetrix Calculation """ +import struct import sys import math import random from enum import Enum -from typing import Any, Dict, Tuple +from typing import Any, Dict, List, Tuple from collections import Counter import torch @@ -17,7 +18,7 @@ from loguru import logger from comfy.utils import ProgressBar -from .. import JOV_TYPE_ANY, JOV_TYPE_FULL, JOV_TYPE_NUMBER, JOV_TYPE_VECTOR, \ +from .. import JOV_TYPE_ANY, JOV_TYPE_FULL, JOV_TYPE_NUMBER, JOV_TYPE_NUMERICAL, \ Lexicon, JOVBaseNode, \ comfy_api_post, deep_merge, parse_reset @@ -31,7 +32,7 @@ from ..sup.anim import EnumWave, EnumEase, ease_op, wave_op JOV_CATEGORY = "CALC" # ============================================================================== -# === LAMBDA === +# === SUPPORT === # ============================================================================== LAMBDA_FLATTEN = lambda data: [item for sublist in data for item in sublist] @@ -42,6 +43,17 @@ def flatten(data): else: return [data] +def to_bits(value): + if isinstance(value, int): + return bin(value)[2:] + elif isinstance(value, float): + packed = struct.pack('>d', value) + return ''.join(f'{byte:08b}' for byte in packed) + elif isinstance(value, str): + return ''.join(f'{ord(c):08b}' for c in value) + else: + raise TypeError(f"Unsupported type: {type(value)}") + # ============================================================================== # === ENUMERATION === # ============================================================================== @@ -192,7 +204,7 @@ class ResultObject(object): class BitSplitNode(JOVBaseNode): NAME = "BIT SPLIT (JOV) β­„" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = (JOV_TYPE_NUMBER, "BOOLEAN",) + RETURN_TYPES = (JOV_TYPE_ANY, "BOOLEAN",) RETURN_NAMES = (Lexicon.BIT, Lexicon.BOOLEAN,) OUTPUT_TOOLTIPS = ( "Bits as Numerical output (0 or 1)", @@ -200,30 +212,55 @@ class BitSplitNode(JOVBaseNode): ) SORT = 10 DESCRIPTION = """ -Split an input into separate bits. `BOOL`, `INT` and `FLOAT` use their numbers, -`STRING` is treated as a list of `CHARACTER`. `IMAGE` and `MASK` will return a -`TRUE` bit for any non-black pixel, as a stream of bits for all pixels in the -image. +Split an input into separate bits. +BOOL, INT and FLOAT use their numbers, +STRING is treated as a list of CHARACTER. +IMAGE and MASK will return a TRUE bit for any non-black pixel, as a stream of bits for all pixels in the image. """ @classmethod def INPUT_TYPES(cls) -> Dict[str, str]: d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - Lexicon.UNKNOWN: (JOV_TYPE_FULL, {"default": None}), - Lexicon.VALUE: ("INT", {"default": 8, "min": 1, "max": 64, "tooltip":"Number of output bits requested."}) + "VALUE": (JOV_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"}) } }) return Lexicon._parse(d) - def run(self, **kw) -> Tuple[bool]: - - return (0,) + 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) + params = list(zip_longest_fill(value, bits)) + pbar = ProgressBar(len(params)) + results = [] + for idx, (value, bits) in enumerate(params): + bit_repr = to_bits(value) + if len(bit_repr) > bits: + if msb: + bit_repr = bit_repr[bits] + else: + bit_repr = bit_repr[-bits:] + elif msb: + bit_repr = bit_repr.zfill(bits) + else: + bit_repr = bit_repr.ljust(bits, '0') + int_bits = [] + bool_bits = [] + for b in bit_repr: + bit = int(b) + int_bits.append(bit) + bool_bits.append(bool(bit)) + results.append([int_bits, bool_bits]) + pbar.update_absolute(idx) + return *list(zip(*results)), class CalcUnaryOPNode(JOVBaseNode): NAME = "OP UNARY (JOV) 🎲" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = (JOV_TYPE_NUMBER,) + RETURN_TYPES = (JOV_TYPE_ANY,) RETURN_NAMES = (Lexicon.UNKNOWN,) OUTPUT_TOOLTIPS = ( "Output type will match the input type" @@ -324,7 +361,7 @@ Perform single function operations like absolute value, mean, median, mode, magn class CalcBinaryOPNode(JOVBaseNode): NAME = "OP BINARY (JOV) 🌟" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = (JOV_TYPE_NUMBER,) + RETURN_TYPES = (JOV_TYPE_ANY,) RETURN_NAMES = (Lexicon.UNKNOWN,) OUTPUT_TOOLTIPS = ( "Output type will match the input type" @@ -466,10 +503,10 @@ Execute binary operations like addition, subtraction, multiplication, division, class ComparisonNode(JOVBaseNode): NAME = "COMPARISON (JOV) πŸ•΅πŸ½" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = (JOV_TYPE_ANY, JOV_TYPE_NUMBER,) + RETURN_TYPES = (JOV_TYPE_ANY, JOV_TYPE_ANY,) RETURN_NAMES = (Lexicon.TRIGGER, Lexicon.VALUE,) OUTPUT_TOOLTIPS = ( - f"Outputs the input at {Lexicon.IN_A} or {Lexicon.IN_B} depending on which evaluated `TRUE`", + f"Outputs the input at {Lexicon.IN_A} or {Lexicon.IN_B} depending on which evaluated TRUE", "The comparison result value" ) SORT = 130 @@ -585,7 +622,7 @@ Evaluates two inputs (A and B) with a specified comparison operators and optiona class LerpNode(JOVBaseNode): NAME = "LERP (JOV) πŸ”°" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = (JOV_TYPE_FULL,) + RETURN_TYPES = (JOV_TYPE_ANY,) RETURN_NAMES = (Lexicon.ANY_OUT,) OUTPUT_TOOLTIPS = ( f"Output can vary depending on the type chosen in the {Lexicon.TYPE} parameter" @@ -742,7 +779,7 @@ Manipulate strings through filtering class SwizzleNode(JOVBaseNode): NAME = "SWIZZLE (JOV) 😡" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = (JOV_TYPE_VECTOR,) + RETURN_TYPES = (JOV_TYPE_ANY,) RETURN_NAMES = (Lexicon.ANY_OUT,) SORT = 40 DESCRIPTION = """ @@ -755,8 +792,8 @@ Swap components between two vectors based on specified swizzle patterns and valu names_convert = EnumConvertType._member_names_[3:10] d = deep_merge(d, { "optional": { - Lexicon.IN_A: (JOV_TYPE_VECTOR, {}), - Lexicon.IN_B: (JOV_TYPE_VECTOR, {}), + Lexicon.IN_A: (JOV_TYPE_NUMERICAL, {}), + Lexicon.IN_B: (JOV_TYPE_NUMERICAL, {}), Lexicon.TYPE: (names_convert, {"default": names_convert[2], "tooltip":"Output type desired from resultant operation"}), Lexicon.SWAP_X: (EnumSwizzle._member_names_, {"default": EnumSwizzle.A_X.name}), @@ -886,8 +923,7 @@ A timer and frame counter, emitting pulses or signals based on time intervals. I class ValueNode(JOVBaseNode): NAME = "VALUE (JOV) 🧬" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - # INPUT_IS_LIST = True - RETURN_TYPES = (JOV_TYPE_NUMBER, JOV_TYPE_NUMBER, JOV_TYPE_NUMBER, JOV_TYPE_NUMBER, JOV_TYPE_NUMBER,) + RETURN_TYPES = (JOV_TYPE_ANY, JOV_TYPE_ANY, JOV_TYPE_ANY, JOV_TYPE_ANY, JOV_TYPE_ANY,) RETURN_NAMES = (Lexicon.ANY_OUT, Lexicon.X, Lexicon.Y, Lexicon.Z, Lexicon.W) SORT = 5 DESCRIPTION = """ @@ -910,22 +946,24 @@ Supplies raw or default values for various data types, supporting vector input w "tooltip":"Passes a raw value directly, or supplies defaults for any value inputs without connections"}), Lexicon.TYPE: (typ, {"default": EnumConvertType.BOOLEAN.name, "tooltip":"Take the input and convert it into the selected type."}), - Lexicon.X: (JOV_TYPE_ANY, {"default": 0, "mij": -sys.maxsize, + Lexicon.X: (JOV_TYPE_NUMERICAL, {"default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "step": 0.01, "forceInput": True}), - Lexicon.Y: (JOV_TYPE_ANY, {"default": 0, "mij": -sys.maxsize, + Lexicon.Y: (JOV_TYPE_NUMERICAL, {"default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "step": 0.01, "forceInput": True}), - Lexicon.Z: (JOV_TYPE_ANY, {"default": 0, "mij": -sys.maxsize, + Lexicon.Z: (JOV_TYPE_NUMERICAL, {"default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "step": 0.01, "forceInput": True}), - Lexicon.W: (JOV_TYPE_ANY, {"default": 0, "mij": -sys.maxsize, + Lexicon.W: (JOV_TYPE_NUMERICAL, {"default": 0, "mij": -sys.maxsize, "maj": sys.maxsize, "step": 0.01, "forceInput": True}), Lexicon.IN_A+Lexicon.IN_A: ("VEC4", {"default": (0, 0, 0, 0), #"mij": -sys.maxsize, "maj": sys.maxsize, + "precision": 2, "step": 0.01, "label": [Lexicon.X, Lexicon.Y], "tooltip":"default value vector for A"}), Lexicon.SEED: ("INT", {"default": 0, "min": 0, "max": sys.maxsize}), Lexicon.IN_B+Lexicon.IN_B: ("VEC4", {"default": (1,1,1,1), #"mij": -sys.maxsize, "maj": sys.maxsize, + "precision": 2, "step": 0.01, "label": [Lexicon.X, Lexicon.Y, Lexicon.Z, Lexicon.W], "tooltip":"default value vector for B"}), @@ -1070,8 +1108,8 @@ Outputs a VEC2 or VEC2INT. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "X": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "1st channel value"}), - "Y": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "2nd channel value"}), + "X": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "1st channel value"}), + "Y": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "2nd channel value"}), } }) return Lexicon._parse(d) @@ -1089,44 +1127,6 @@ Outputs a VEC2 or VEC2INT. pbar.update_absolute(idx) return *list(zip(*results)), -class Vector2IntNode(JOVBaseNode): - NAME = "VECTOR2INT (JOV)" - CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = ("VEC2", "VEC2INT", ) - RETURN_NAMES = ("VEC2", "VEC2INT", ) - OUTPUT_TOOLTIPS = ( - "Vector2 with float values", - "Vector2 with integer values", - ) - SORT = 291 - DESCRIPTION = """ -Outputs a VEC2 or VEC2INT. -""" - - @classmethod - def INPUT_TYPES(cls) -> Dict[str, str]: - d = super().INPUT_TYPES() - d = deep_merge(d, { - "optional": { - "X": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "1st channel value"}), - "Y": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "2nd channel value"}), - } - }) - return Lexicon._parse(d) - - def run(self, **kw) -> Tuple[Tuple[float, ...], Tuple[int, ...]]: - x = parse_param(kw, "X", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - y = parse_param(kw, "Y", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - results = [] - params = list(zip_longest_fill(x, y)) - pbar = ProgressBar(len(params)) - for idx, (x, y) in enumerate(params): - x = round(x, 6) - y = round(y, 6) - results.append([(x, y,), (int(x), int(y),)]) - pbar.update_absolute(idx) - return *list(zip(*results)), - class Vector3Node(JOVBaseNode): NAME = "VECTOR3 (JOV)" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" @@ -1146,9 +1146,9 @@ Outputs a VEC3 or VEC3INT. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "X": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "1st channel value"}), - "Y": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "2nd channel value"}), - "Z": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "3rd channel value"}), + "X": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "1st channel value"}), + "Y": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "2nd channel value"}), + "Z": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "3rd channel value"}), } }) return Lexicon._parse(d) @@ -1168,47 +1168,6 @@ Outputs a VEC3 or VEC3INT. pbar.update_absolute(idx) return *list(zip(*results)), -class Vector3IntNode(JOVBaseNode): - NAME = "VECTOR3INT (JOV)" - CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = ("VEC3", "VEC3INT", ) - RETURN_NAMES = ("VEC3", "VEC3INT", ) - OUTPUT_TOOLTIPS = ( - "Vector3 with float values", - "Vector3 with integer values", - ) - SORT = 293 - DESCRIPTION = """ -Outputs a VEC3 or VEC3INT. -""" - - @classmethod - def INPUT_TYPES(cls) -> Dict[str, str]: - d = super().INPUT_TYPES() - d = deep_merge(d, { - "optional": { - "X": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "1st channel value"}), - "Y": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "2nd channel value"}), - "Z": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "3rd channel value"}), - } - }) - return Lexicon._parse(d) - - def run(self, **kw) -> Tuple[Tuple[float, ...], Tuple[int, ...]]: - x = parse_param(kw, "X", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - y = parse_param(kw, "Y", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - z = parse_param(kw, "Z", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - results = [] - params = list(zip_longest_fill(x, y, z)) - pbar = ProgressBar(len(params)) - for idx, (x, y, z) in enumerate(params): - x = round(x, 6) - y = round(y, 6) - z = round(z, 6) - results.append([(x, y, z,), (int(x), int(y), int(z),)]) - pbar.update_absolute(idx) - return *list(zip(*results)), - class Vector4Node(JOVBaseNode): NAME = "VECTOR4 (JOV)" CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" @@ -1228,10 +1187,10 @@ Outputs a VEC4 or VEC4INT. d = super().INPUT_TYPES() d = deep_merge(d, { "optional": { - "X": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "1st channel value"}), - "Y": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "2nd channel value"}), - "Z": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "3rd channel value"}), - "W": ("FLOAT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "4th channel value"}), + "X": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "1st channel value"}), + "Y": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "2nd channel value"}), + "Z": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "3rd channel value"}), + "W": (JOV_TYPE_NUMBER, {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 0.01, "tooltip": "4th channel value"}), } }) return Lexicon._parse(d) @@ -1253,50 +1212,6 @@ Outputs a VEC4 or VEC4INT. pbar.update_absolute(idx) return *list(zip(*results)), -class Vector4IntNode(JOVBaseNode): - NAME = "VECTOR4INT (JOV)" - CATEGORY = f"JOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/{JOV_CATEGORY}" - RETURN_TYPES = ("VEC4", "VEC4INT", ) - RETURN_NAMES = ("VEC4", "VEC4INT", ) - OUTPUT_TOOLTIPS = ( - "Vector4 with float values", - "Vector4 with integer values", - ) - SORT = 295 - DESCRIPTION = """ -Outputs a VEC4 or VEC4INT. -""" - - @classmethod - def INPUT_TYPES(cls) -> Dict[str, str]: - d = super().INPUT_TYPES() - d = deep_merge(d, { - "optional": { - "X": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "1st channel value"}), - "Y": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "2nd channel value"}), - "Z": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "3rd channel value"}), - "W": ("INT", {"default": 0, "min": -sys.maxsize, "max": sys.maxsize, "step": 1, "tooltip": "4th channel value"}), - } - }) - return Lexicon._parse(d) - - def run(self, **kw) -> Tuple[Tuple[float, ...], Tuple[int, ...]]: - x = parse_param(kw, "X", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - y = parse_param(kw, "Y", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - z = parse_param(kw, "Z", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - w = parse_param(kw, "W", EnumConvertType.INT, 0, -sys.maxsize, sys.maxsize) - results = [] - params = list(zip_longest_fill(x, y, z, w)) - pbar = ProgressBar(len(params)) - for idx, (x, y, z, w,) in enumerate(params): - x = round(x, 6) - y = round(y, 6) - z = round(z, 6) - w = round(w, 6) - results.append([(x, y, z, w,), (int(x), int(y), int(z), int(w),)]) - pbar.update_absolute(idx) - return *list(zip(*results)), - ''' class ParameterNode(JOVBaseNode): NAME = "PARAMETER (JOV) βš™οΈ" diff --git a/core/utility/info.py b/core/utility/info.py index 25952c8..185996f 100644 --- a/core/utility/info.py +++ b/core/utility/info.py @@ -64,7 +64,7 @@ Visualize data. It accepts various types of data, including images, text, and ot return output def __parse(val) -> str: - ret = val + ret = '' typ = ''.join(repr(type(val)).split("'")[1:2]) if isinstance(val, dict): # mixlab layer? @@ -95,11 +95,10 @@ Visualize data. It accepts various types of data, including images, text, and ot ret = json.dumps(val, indent=3, separators=(',', ': ')) except Exception as e: ret = str(e) - elif isinstance(val, (tuple, set, list,)): - ret = '' if (size := len(val)) > 0: - if type(val) == np.ndarray: + if isinstance(val, (np.ndarray,)): + ret = str(val) typ = "NUMPY ARRAY" elif isinstance(val[0], (torch.Tensor,)): ret = decode_tensor(val[0]) @@ -107,16 +106,20 @@ Visualize data. It accepts various types of data, including images, text, and ot elif size == 1 and isinstance(val[0], (list,)) and isinstance(val[0][0], (torch.Tensor,)): ret = decode_tensor(val[0][0]) typ = "CONDITIONING" - elif all(isinstance(i, list) for i in val): - # Serialize each inner list on a separate line - ret = [json.dumps(i, separators=(',', ': ')) for i in val] + elif all(isinstance(i, (tuple, set, list)) for i in val): + ret = "[\n" + ",\n".join(f" {row}" for row in val) + "\n]" + # ret = json.dumps(val, indent=4) + elif all(isinstance(i, (bool, int, float)) for i in val): + ret = ','.join([str(x) for x in val]) + else: + ret = str(val) elif isinstance(val, bool): ret = "True" if val else "False" elif isinstance(val, torch.Tensor): ret = decode_tensor(val) else: - ret = str(ret) - return json.dumps({typ: val}, separators=(',', ': ')) + ret = str(val) + return json.dumps({typ: ret}, separators=(',', ': ')) for x in o: output["ui"]["text"].append(__parse(x)) diff --git a/node_list.json b/node_list.json index ec7d39d..31d0c4a 100644 --- a/node_list.json +++ b/node_list.json @@ -61,10 +61,7 @@ "TRANSFORM (JOV) \ud83c\udfdd\ufe0f": "Apply various geometric transformations to images, including translation, rotation, scaling, mirroring, tiling and perspective projection", "VALUE (JOV) \ud83e\uddec": "Supplies raw or default values for various data types, supporting vector input with components for X, Y, Z, and W", "VECTOR2 (JOV)": "Outputs a VEC2 or VEC2INT", - "VECTOR2INT (JOV)": "Outputs a VEC2 or VEC2INT", "VECTOR3 (JOV)": "Outputs a VEC3 or VEC3INT", - "VECTOR3INT (JOV)": "Outputs a VEC3 or VEC3INT", "VECTOR4 (JOV)": "Outputs a VEC4 or VEC4INT", - "VECTOR4INT (JOV)": "Outputs a VEC4 or VEC4INT", "WAVE GEN (JOV) \ud83c\udf0a": "Produce waveforms like sine, square, or sawtooth with adjustable frequency, amplitude, phase, and offset" } \ No newline at end of file diff --git a/sup/util.py b/sup/util.py index b56e5f2..2d61816 100644 --- a/sup/util.py +++ b/sup/util.py @@ -277,10 +277,9 @@ def parse_param(data:dict, key:str, typ:EnumConvertType, default: Any, val = data.get(key, default) if typ == EnumConvertType.ANY: if val is None: - val = [default] - return val - elif isinstance(val, (list,)): - val = val[0] + return [default] + #elif isinstance(val, (list,)): + # val = val[0] if isinstance(val, (str,)): try: val = json.loads(val.replace("'", '"')) diff --git a/web/nodes/akashic.js b/web/nodes/akashic.js index a92fc31..1fbed57 100644 --- a/web/nodes/akashic.js +++ b/web/nodes/akashic.js @@ -38,13 +38,10 @@ app.registerExtension({ textWidget.inputEl.style.padding = "1px"; textWidget.inputEl.style.border = "1px"; textWidget.inputEl.style.backgroundColor = "#222"; - textWidget.value = this.inputs[i].name + "::\n"; - const msg = message["text"][i]; - if (!msg.split("],[").length > 1) { - textWidget.value += msg.split(",").join(",\n"); - } else { - textWidget.value += msg; - } + textWidget.value = this.inputs[i].name + " "; + textWidget.value += message["text"][i] + .replace(/\\n/g, '\n') + .replace(/"/g, ''); } } return me;