From c30f3af0ba33ad1803169217bde6eb4eaf064df7 Mon Sep 17 00:00:00 2001 From: FizzleDorf <1fizzledorf@gmail.com> Date: Sat, 11 Nov 2023 16:05:01 -0500 Subject: [PATCH] initial commit --- BatchFuncs.py | 25 ++++++++++++++---------- HelperNodes.py | 24 +++++++++++++++++++++++ ScheduledNodes.py | 49 ++++++++++++++++++++++++++--------------------- __init__.py | 6 +++++- 4 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 HelperNodes.py diff --git a/BatchFuncs.py b/BatchFuncs.py index 1c4e9f9..b6f593e 100644 --- a/BatchFuncs.py +++ b/BatchFuncs.py @@ -62,7 +62,7 @@ def batch_split_weighted_subprompts(text, pre_text, app_text): neg[frame] = neg[frame][:-1] return pos, neg -def interpolate_prompt_series(animation_prompts, max_frames, pre_text, app_text, prompt_weight_1=[], +def interpolate_prompt_series(animation_prompts, max_frames, start_frame, pre_text, app_text, prompt_weight_1=[], prompt_weight_2=[], prompt_weight_3=[], prompt_weight_4=[], Is_print = False): max_f = max_frames # needed for numexpr even though it doesn't look like it's in use. @@ -160,17 +160,22 @@ def interpolate_prompt_series(animation_prompts, max_frames, pre_text, app_text, if isinstance(prompt_weight_4, int): prompt_weight_4 = tuple([prompt_weight_4] * max_frames) + index_offset = 0 # Evaluate the current and next prompt's expressions - for i in range(0,len(cur_prompt_series)): - cur_prompt_series[i] = prepare_batch_prompt(cur_prompt_series[i], max_frames, i, prompt_weight_1[i], - prompt_weight_2[i], prompt_weight_3[i], prompt_weight_4[i]) - nxt_prompt_series[i] = prepare_batch_prompt(nxt_prompt_series[i], max_frames, i, prompt_weight_1[i], - prompt_weight_2[i], prompt_weight_3[i], prompt_weight_4[i]) - if Is_print == True: - # Show the to/from prompts with evaluated expressions for transparency. - for i in range(len(cur_prompt_series)): - print("\n", "Max Frames: ", max_frames, "\n", "Current Prompt: ", cur_prompt_series[i], "\n", "Next Prompt: ", nxt_prompt_series[i], "\n", "Strength : ", weight_series[i], "\n") + for i in range(start_frame,len(cur_prompt_series)): + cur_prompt_series[index_offset] = prepare_batch_prompt(cur_prompt_series[i], max_frames, i, prompt_weight_1[i], + prompt_weight_2[i], prompt_weight_3[i], prompt_weight_4[i]) + nxt_prompt_series[index_offset] = prepare_batch_prompt(nxt_prompt_series[i], max_frames, i, prompt_weight_1[i], + prompt_weight_2[i], prompt_weight_3[i], prompt_weight_4[i]) + if Is_print == True: + # Show the to/from prompts with evaluated expressions for transparency. + print("\n", "Max Frames: ", max_frames, "\n", "frame index: ", index_offset, "\n", "Current Prompt: ", + cur_prompt_series[index_offset], "\n", "Next Prompt: ", nxt_prompt_series[index_offset], "\n", "Strength : ", + weight_series[i], "\n") + index_offset = index_offset+1 + + # Output methods depending if the prompts are the same or if the current frame is a keyframe. # if it is an in-between frame and the prompts differ, composable diffusion will be performed. diff --git a/HelperNodes.py b/HelperNodes.py new file mode 100644 index 0000000..cc4f803 --- /dev/null +++ b/HelperNodes.py @@ -0,0 +1,24 @@ + + +class CalculateLatentInterpFrameNumber: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "current_frame": ("INT", {"default": 0, "min": 0}), + "max_frames": ("INT", {"default": 18, "min": 0}), + "batch_size": ("INT", {"default": 4, "min": 0}), + } + } + RETURN_TYPES = ("INT", "INT" ,"INT" ,"INT", ) + FUNCTION = "assignFrameNum" + + CATEGORY = "FizzNodes 📅🅕🅝/FrameNodes" + + def assignFrameNum(self, current_frame, max_frames, batch_size): + if current_frame == 0: + return 0, 1, 2, 3 + else: + start_frame = (current_frame - 1) * (batch_size - 1) + 3 + print(tuple((start_frame + i) % max_frames for i in range(4))) + return tuple((start_frame + i) % max_frames for i in range(4)) \ No newline at end of file diff --git a/ScheduledNodes.py b/ScheduledNodes.py index c3a0de7..150f05e 100644 --- a/ScheduledNodes.py +++ b/ScheduledNodes.py @@ -74,16 +74,16 @@ class PromptSchedule: inputText = str("{" + text + "}") inputText = re.sub(r',\s*}', '}', inputText) animation_prompts = json.loads(inputText.strip()) - + start_frame = 0 pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) - pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, pre_text, app_text, pw_a, + pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) - pc = PoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame], clip, ) + pc = PoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame], clip) - neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, pre_text, app_text, pw_a, + neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) - nc = PoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame], clip, ) + nc = PoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame], clip) return (pc, nc,) @@ -97,6 +97,7 @@ class BatchPromptSchedule: # "forceInput": True}),}, "optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE" }), # "forceInput": True}), "app_text": ("STRING", {"multiline": True, "default": "APP" }), # "forceInput": True}), + "start_frame": ("INT", {"default": 0, "min": 0, "max": 9999, "step": 1, }), "pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }), # "forceInput": True }), "pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }), @@ -113,17 +114,17 @@ class BatchPromptSchedule: CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes" - def animate(self, text, max_frames, print_output, clip, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''): + def animate(self, text, max_frames, print_output, clip, start_frame, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''): inputText = str("{" + text + "}") inputText = re.sub(r',\s*}', '}', inputText) - + max_frames += start_frame animation_prompts = json.loads(inputText.strip()) pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) - pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) - pc = BatchPoolAnimConditioning( pos_cur_prompt, pos_nxt_prompt, weight, clip, ) + pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + pc = BatchPoolAnimConditioning( pos_cur_prompt, pos_nxt_prompt, weight, clip,) - neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) + neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) nc = BatchPoolAnimConditioning(neg_cur_prompt, neg_nxt_prompt, weight, clip, ) return (pc, nc, ) @@ -138,6 +139,7 @@ class BatchPromptScheduleLatentInput: # "forceInput": True}),}, "optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE", }), # "forceInput": True}), "app_text": ("STRING", {"multiline": True, "default": "APP", }), # "forceInput": True}), + "start_frame": ("INT", {"default": 0.0, "min": 0, "max": 9999, "step": 1, }), "pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }), # "forceInput": True }), "pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }), @@ -154,21 +156,21 @@ class BatchPromptScheduleLatentInput: CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes" - def animate(self, text, num_latents, print_output, clip, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''): + def animate(self, text, num_latents, print_output, clip, start_frame, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''): max_frames = sum(tensor.size(0) for tensor in num_latents.values()) - + max_frames += start_frame inputText = str("{" + text + "}") inputText = re.sub(r',\s*}', '}', inputText) animation_prompts = json.loads(inputText.strip()) pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) - pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, pre_text, + pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) pc = BatchPoolAnimConditioning(pos_cur_prompt, pos_nxt_prompt, weight, clip, ) - neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, pre_text, + neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) nc = BatchPoolAnimConditioning(neg_cur_prompt, neg_nxt_prompt, weight, clip, ) @@ -252,8 +254,9 @@ class BatchStringSchedule: def animate(self, text, max_frames, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text=''): inputText = str("{" + text + "}") inputText = re.sub(r',\s*}', '}', inputText) + start_frame = 0 animation_prompts = json.loads(inputText.strip()) - cur_prompt_series, nxt_prompt_series, weight_series = interpolate_prompt_series(animation_prompts, max_frames, pre_text, + cur_prompt_series, nxt_prompt_series, weight_series = interpolate_prompt_series(animation_prompts, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d) #c = PoolAnimConditioning(cur_prompt, nxt_prompt, weight, clip, ) return (cur_prompt_series,) @@ -430,19 +433,19 @@ class PromptScheduleNodeFlowEnd: text = text[:-1] if text[0] == ",": text = text[:0] - + start_frame = 0 inputText = str("{" + text + "}") inputText = re.sub(r',\s*}', '}', inputText) animation_prompts = json.loads(inputText.strip()) - + max_frames += start_frame pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) - pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, pre_text, app_text, pw_a, + pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) pc = PoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame], clip, ) - neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, pre_text, app_text, pw_a, + neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) nc = PoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame], clip, ) @@ -470,7 +473,7 @@ class BatchPromptScheduleNodeFlowEnd: CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes" - def animate(self, text, max_frames, print_output, clip, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', current_frame = 0, + def animate(self, text, max_frames, start_frame, print_output, clip, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', current_frame = 0, app_text=''): if text[-1] == ",": text = text[:-1] @@ -480,14 +483,16 @@ class BatchPromptScheduleNodeFlowEnd: inputText = re.sub(r',\s*}', '}', inputText) animation_prompts = json.loads(inputText.strip()) + max_frames += start_frame + pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text) - pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, pre_text, app_text, pw_a, + pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) pc = BatchPoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame], clip, ) - neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, pre_text, app_text, pw_a, + neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output) nc = BatchPoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame], clip, ) diff --git a/__init__.py b/__init__.py index c49f520..ddde147 100644 --- a/__init__.py +++ b/__init__.py @@ -61,6 +61,7 @@ from .ScheduledNodes import ( #, BatchPromptScheduleNodeFlowEnd #, BatchGLIGENSchedule ) from .FrameNodes import FrameConcatenate, InitNodeFrame, NodeFrame, StringConcatenate +from .HelperNodes import CalculateLatentInterpFrameNumber NODE_CLASS_MAPPINGS = { "Lerp": Lerp, @@ -93,6 +94,8 @@ NODE_CLASS_MAPPINGS = { "Init FizzFrame":InitNodeFrame, "FizzFrame":NodeFrame, "FizzFrameConcatenate":FrameConcatenate, + + "CalculateLatentInterpFrameNumber": CalculateLatentInterpFrameNumber } NODE_DISPLAY_NAME_MAPPINGS = { @@ -122,6 +125,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "BatchStringSchedule": "Batch String Schedule 📅🅕🅝", "BatchValueScheduleLatentInput": "Batch Value Schedule (Latent Input) 📅🅕🅝", "BatchPromptScheduleSDXLLatentInput": "Batch Prompt Schedule SDXL (Latent Input) 📅🅕🅝", - "BatchPromptScheduleLatentInput": "Batch Prompt Schedule (Latent Input)📅🅕🅝", + "BatchPromptScheduleLatentInput": "Batch Prompt Schedule (Latent Input) 📅🅕🅝", + "CalculateLatentInterpFrameNumber": "Calculate Frame Number (Latent Interp) 📅🅕🅝" } print('\033[34mFizzleDorf Custom Nodes: \033[92mLoaded\033[0m')