swap index param for key in dynamic parse for multi-dynamics

purz node -- but not.
fonts should comp with rgbA was RGB
This commit is contained in:
Alexander G. Morano
2024-06-19 09:49:25 -07:00
parent bbfd120b65
commit 62cd748a25
9 changed files with 76 additions and 23 deletions
+4 -4
View File
@@ -326,6 +326,7 @@ The Binary Operation node executes binary operations like addition, subtraction,
results = []
A = parse_param(kw, Lexicon.IN_A, EnumConvertType.ANY, [None])
B = parse_param(kw, Lexicon.IN_B, EnumConvertType.ANY, [None])
print(A, '-', B)
a_x = parse_param(kw, Lexicon.X, EnumConvertType.FLOAT, 0)
a_xy = parse_param(kw, Lexicon.IN_A+"2", EnumConvertType.VEC2, [(0, 0)])
a_xyz = parse_param(kw, Lexicon.IN_A+"3", EnumConvertType.VEC3, [(0, 0, 0)])
@@ -750,7 +751,6 @@ class TickNode(JOVBaseNode):
CATEGORY = f"JOVIMETRIX 🔺🟩🔵/{JOV_CATEGORY}"
RETURN_TYPES = (WILDCARD, "FLOAT", "FLOAT", WILDCARD)
RETURN_NAMES = (Lexicon.VALUE, Lexicon.LINEAR, Lexicon.FPS, Lexicon.TRIGGER)
# OUTPUT_IS_LIST = (True, True, True, True)
DESCRIPTION = """
The `Tick` node acts as a timer and frame counter, emitting pulses or signals based on time intervals or BPM settings. It allows precise synchronization and control over animation sequences, with options to adjust FPS, BPM, and loop points. This node is useful for generating time-based events or driving animations with rhythmic precision.
"""
@@ -800,7 +800,7 @@ The `Tick` node acts as a timer and frame counter, emitting pulses or signals ba
self.__frame = parse_param(kw, Lexicon.VALUE, EnumConvertType.INT, self.__frame)[0]
if loop != 0:
self.__frame %= loop
self.__frame = max(0, self.__frame)
# start_frame = max(0, start_frame)
hold = parse_param(kw, Lexicon.WAIT, EnumConvertType.BOOLEAN, False)[0]
fps = parse_param(kw, Lexicon.FPS, EnumConvertType.INT, 24, 1)[0]
bpm = parse_param(kw, Lexicon.BPM, EnumConvertType.INT, 120, 1)[0]
@@ -809,7 +809,7 @@ The `Tick` node acts as a timer and frame counter, emitting pulses or signals ba
batch = parse_param(kw, Lexicon.BATCH, EnumConvertType.INT, 1, 1)[0]
step_fps = 1. / max(1., float(fps))
reset = parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0]
if parse_reset(ident) > 0 or reset:
if loop == 0 and (parse_reset(ident) > 0 or reset):
self.__frame = 0
trigger = None
results = Results()
@@ -832,7 +832,7 @@ The `Tick` node acts as a timer and frame counter, emitting pulses or signals ba
pbar.update_absolute(idx)
if batch < 2:
comfy_message(ident, "jovi-tick", {"i": self.__frame})
return results.frame, results.lin, results.fixed, results.trigger
return (results.frame, results.lin, results.fixed, results.trigger,)
class ValueNode(JOVBaseNode):
NAME = "VALUE (JOV) 🧬"
+2 -2
View File
@@ -584,7 +584,7 @@ Combine multiple input images into a single image by summing their pixel values.
return Lexicon._parse(d, cls)
def run(self, **kw) -> torch.Tensor:
pA = parse_dynamic(kw, 0, EnumConvertType.IMAGE, None)
pA = parse_dynamic(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None)
#pA = [item for sublist in pA for item in sublist]
if len(pA) == 0:
logger.error("no images to flatten")
@@ -809,7 +809,7 @@ Merge multiple input images into a single composite image by stacking them along
return Lexicon._parse(d, cls)
def run(self, **kw) -> Tuple[torch.Tensor, torch.Tensor]:
images = parse_dynamic(kw, 0, EnumConvertType.IMAGE, None)
images = parse_dynamic(kw, Lexicon.IMAGE, EnumConvertType.IMAGE, None)
if len(images) == 0:
logger.warning("no images to stack")
return
+32 -1
View File
@@ -206,7 +206,7 @@ The Text Generation node generates images containing text based on user-defined
Lexicon.FONT: (cls.FONT_NAMES, {"default": cls.FONT_NAMES[0]}),
Lexicon.LETTER: ("BOOLEAN", {"default": False}),
Lexicon.AUTOSIZE: ("BOOLEAN", {"default": False}),
Lexicon.RGBA_A: ("VEC3", {"default": (255, 255, 255, 255), "step": 1,
Lexicon.RGBA_A: ("VEC4", {"default": (255, 255, 255, 255), "step": 1,
"label": [Lexicon.R, Lexicon.G, Lexicon.B, Lexicon.A],
"rgb": True, "tooltip": "Color of the letters"}),
Lexicon.MATTE: ("VEC3", {"default": (0, 0, 0), "step": 1,
@@ -426,3 +426,34 @@ The Wave Graph node visualizes audio waveforms as bars. Adjust parameters like t
images.append(cv2tensor_full(img))
pbar.update_absolute(idx)
return [torch.cat(i, dim=0) for i in list(zip(*images))]
'''
class PurzNode(JOVBaseNode):
NAME = "PURZ (JOV) 🟪"
CATEGORY = f"JOVIMETRIX 🔺🟩🔵/PURZ"
RETURN_TYPES = ("IMAGE", "IMAGE", "MASK")
RETURN_NAMES = (Lexicon.IMAGE, Lexicon.RGB, Lexicon.MASK)
DESCRIPTION = """
"""
@classmethod
def INPUT_TYPES(cls) -> dict:
d = super().INPUT_TYPES()
d.update({
"optional": {
Lexicon.PIXEL: (WILDCARD, {"tooltip":"🫥 🥰 🫳 📍 😵‍💫 😃 🥲 🪯"}),
"🐪": (WILDCARD, {"tooltip": "🐪 🙋 💬 😀 🇧🇦 🤣 🥯 👣 🥴 😍 🅾️ 🧞 🙊"}),
Lexicon.WH: ("VEC2", {"default": (512, 512), "tooltip": "🥯 👣 🥰 🫳 💬 🥴 😀 📍"}),
"🙋": (["😍", "😀", "🤣", "🥴"], {"default": ["😍"]}),
"📍": ("INT", {"default": 256}),
"🧞": ("INT", {"default": 256}),
"🙊": ("VEC4", {"default": (255, 255, 255, 255), "step": 1, "rgb": True})
}
})
return Lexicon._parse(d, cls)
def run(self, **kw) -> Tuple[torch.Tensor, torch.Tensor]:
return ()
'''
+5 -2
View File
@@ -163,7 +163,7 @@ Processes a batch of data based on the selected mode, such as merging, picking,
self.__seed = None
def run(self, **kw) -> Tuple[int, list]:
data_list = parse_dynamic(kw, 0, EnumConvertType.ANY, None)
data_list = parse_dynamic(kw, Lexicon.UNKNOWN, EnumConvertType.ANY, None)
mode = parse_param(kw, Lexicon.BATCH_MODE, EnumConvertType.STRING, EnumBatchMode.MERGE.name)
index = parse_param(kw, Lexicon.INDEX, EnumConvertType.INT, EnumBatchMode.MERGE.name)
slice_range = parse_param(kw, Lexicon.RANGE, EnumConvertType.VEC3INT, [(0, 0, 1)])
@@ -395,10 +395,12 @@ The Graph node visualizes a series of data points over time. It accepts a dynami
if parse_reset(ident) > 0 or parse_param(kw, Lexicon.RESET, EnumConvertType.BOOLEAN, False)[0]:
self.__history = []
longest_edge = 0
dynamic = parse_dynamic(kw, 0, EnumConvertType.FLOAT, 0)
dynamic = parse_dynamic(kw, Lexicon.UNKNOWN, EnumConvertType.FLOAT, 0)
# each of the plugs
self.__ax.clear()
for idx, val in enumerate(dynamic):
logger.debug(idx)
logger.debug(val)
if isinstance(val, (set, tuple,)):
val = list(val)
if not isinstance(val, (list, )):
@@ -425,6 +427,7 @@ The Graph node visualizes a series of data points over time. It accepts a dynami
return (pil2tensor(image),)
'''
# OLD LOAD BATCH NODE -- add to queue?
def run(self, **kw) -> None:
q = parse_param(kw, Lexicon.QUEUE, EnumConvertType.STRING, "")
mode = parse_param(kw, Lexicon.MODE, EnumConvertType.STRING, EnumScaleMode.NONE.name)
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

+23 -9
View File
@@ -54,18 +54,32 @@ class EnumSwizzle(Enum):
# === SUPPORT ===
# =============================================================================
def parse_dynamic(data:dict, index:int, typ:EnumConvertType, default: Any) -> List[Any]:
def parse_dynamic(data:dict, prefix:str, typ:EnumConvertType, default: Any, with_prefix:bool=False) -> List[Any]:
"""Convert iterated input field(s) based on a s into a single compound list of entries.
The default will just look for all keys as integer:
#_<field name>
If prefix is non-null, then the format for the key entry is:
#_<prefix>_<field name>
This will return N entries in a list based on the prefix pattern or not.
"""
vals = []
count = index
for k in data:
name = k.split('_')
try: val = int(name[0])
except: continue
val = parse_param(data, k, typ, default)
if not isinstance(val, (list,)):
val = [val]
vals.extend(val)
count += 1
# do we need the prefix (in the case of more than one dynamic param)
if (not with_prefix and len(name)== 2) or (with_prefix and len(name) == 3 and name[1] != prefix):
# check the index is valid number
try: val = int(name[0])
except: continue
val = parse_param(data, k, typ, default)
#if not isinstance(val, (list,)):
# val = [val]
vals.append(val)
return vals
def parse_value(val:Any, typ:EnumConvertType, default: Any,
+1 -1
View File
@@ -23,7 +23,7 @@ app.registerExtension({
const onComputeSize = nodeType.prototype.computeSize;
nodeType.computeSize = () => {
const size = onComputeSize?.apply(this);
console.info(size);
// console.info(size);
return [0, 4];
}
@@ -26,7 +26,8 @@ app.registerExtension({
if (nodeData.name !== _id) {
return;
}
nodeType = node_add_dynamic(nodeType, _prefix, "*", 7);
nodeType = node_add_dynamic(nodeType, _prefix);
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = async function () {
const me = onNodeCreated?.apply(this);
@@ -49,8 +50,12 @@ app.registerExtension({
for (let i = 0; i < this.inputs.length; i++) {
const link_id = this.inputs[i].link;
const link = app.graph.links[link_id];
if(link && this.inputs[i].name.substring(0, _prefix.length) === _prefix) {
const nameParts = this.inputs[i].name.split('_');
const isInteger = nameParts.length > 1 && !isNaN(nameParts[0]) && Number.isInteger(parseFloat(nameParts[0]));
if (link && isInteger && nameParts[1].substring(0, _prefix.length) === _prefix) {
//if(link && this.inputs[i].name.substring(0, _prefix.length) === _prefix) {
link.type = `JOV_VG_${count}`;
console.info(count)
this.inputs[i].color_on = LGraphCanvas.link_type_colors[link.type];
count += 1;
}
+2 -2
View File
@@ -77,7 +77,7 @@ export function node_add_dynamic(nodeType, prefix, dynamic_type='*', index_start
let count = self.inputs.length;
while (idx < self.inputs.length-1 && count > 0) {
const slot = self.inputs[idx];
console.info(slot, count)
// console.info(slot, count)
if (slot) {
const parts = slot.name.split('_');
// a dynamic jovian slot prefix_
@@ -101,7 +101,7 @@ export function node_add_dynamic(nodeType, prefix, dynamic_type='*', index_start
}
count -= 1;
}
console.info(idx)
//console.info(idx)
}
index_start = Math.max(0, index_start);