| |
| |
| |
| |
|
|
| import comfy.sd |
| import os |
| import sys |
| import folder_paths |
| from nodes import LoraLoader |
| from .functions import keyframe_scheduler, prompt_scheduler |
| from ..categories import icons |
|
|
| |
| |
| |
| |
| |
| class CR_ValueScheduler: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
| modes = ["Default Value", "Schedule"] |
| return {"required": {"mode": (modes,), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| "schedule_alias": ("STRING", {"default": "", "multiline": False}), |
| "default_value": ("FLOAT", {"default": 1.0, "min": -9999.0, "max": 9999.0, "step": 0.01,}), |
| "schedule_format": (["CR", "Deforum"],), |
| }, |
| "optional": {"schedule": ("SCHEDULE",), |
| } |
| } |
| |
| RETURN_TYPES = ("INT", "FLOAT", "STRING", ) |
| RETURN_NAMES = ("INT", "FLOAT", "show_help", ) |
| FUNCTION = "schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def schedule(self, mode, current_frame, schedule_alias, default_value, schedule_format, schedule=None): |
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-value-scheduler" |
|
|
| if mode == "Default Value": |
| print(f"[Info] CR Value Scheduler: Scheduler {schedule_alias} is disabled") |
| int_out, float_out = int(default_value), float(default_value) |
| return (int_out, float_out, show_help, ) |
|
|
| |
| params = keyframe_scheduler(schedule, schedule_alias, current_frame) |
|
|
| |
| if params == "": |
| if current_frame == 0: |
| print(f"[Warning] CR Value Scheduler. No frame 0 found in schedule. Starting with default value at frame 0") |
| int_out, float_out = int(default_value), float(default_value) |
| else: |
| |
| try: |
| value = float(params) |
| int_out, float_out = int(value), float(value) |
| except ValueError: |
| print(f"[Warning] CR Value Scheduler. Invalid params: {params}") |
| return() |
| return (int_out, float_out, show_help, ) |
|
|
| |
| class CR_TextScheduler: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
| modes = ["Default Text", "Schedule"] |
| return {"required": {"mode": (modes,), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| "schedule_alias": ("STRING", {"default": "", "multiline": False}), |
| "default_text": ("STRING", {"multiline": False, "default": "default text"}), |
| "schedule_format": (["CR", "Deforum"],), |
| }, |
| "optional": {"schedule": ("SCHEDULE",), |
| } |
| } |
| |
| RETURN_TYPES = ("STRING", "STRING", ) |
| RETURN_NAMES = ("STRING", "show_help", ) |
| FUNCTION = "schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def schedule(self, mode, current_frame, schedule_alias, default_text, schedule_format, schedule=None): |
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-text-scheduler" |
|
|
| if mode == "Default Text": |
| print(f"[Info] CR Text Scheduler: Scheduler {schedule_alias} is disabled") |
| text_out = default_text |
| return (text_out, show_help, ) |
|
|
| |
| params = keyframe_scheduler(schedule, schedule_alias, current_frame) |
| |
| |
| if params == "": |
| if current_frame == 0: |
| print(f"[Warning] CR Text Scheduler. No frame 0 found in schedule. Starting with default value at frame 0") |
| text_out = default_value, |
| else: |
| |
| try: |
| text_out = params |
| except ValueError: |
| print(f"[Warning] CR Text Scheduler. Invalid params: {params}") |
| return() |
| return (text_out, show_help, ) |
|
|
|
|
| |
| class CR_PromptScheduler: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
| modes = ["Default Prompt", "Keyframe List", "Schedule"] |
| return {"required": {"mode": (modes,), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| "default_prompt": ("STRING", {"multiline": False, "default": "default prompt"}), |
| "schedule_format": (["CR", "Deforum"],), |
| |
| "interpolate_prompt": (["Yes", "No"],), |
| }, |
| "optional": {"schedule": ("SCHEDULE",), |
| "schedule_alias": ("STRING", {"default prompt": "", "multiline": False}), |
| "keyframe_list": ("STRING", {"multiline": True, "default": "keyframe list"}), |
| "prepend_text": ("STRING", {"multiline": True, "default": "prepend text"}), |
| "append_text": ("STRING", {"multiline": True, "default": "append text"}), |
| } |
| } |
| |
| RETURN_TYPES = ("STRING", "STRING", "FLOAT", "STRING", ) |
| RETURN_NAMES = ("current_prompt", "next_prompt", "weight", "show_help", ) |
| FUNCTION = "schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def schedule(self, mode, prepend_text, append_text, current_frame, schedule_alias, default_prompt, schedule_format, interpolate_prompt, keyframe_list="", schedule=None): |
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-prompt-scheduler" |
|
|
| schedule_lines = list() |
| |
| if mode == "Default Prompt": |
| print(f"[Info] CR Prompt Scheduler: Scheduler {schedule_alias} is disabled") |
| return (default_prompt, default_prompt, 1.0, show_help, ) |
|
|
| if mode == "Keyframe List": |
| if keyframe_list == "": |
| print(f"[Error] CR Prompt Scheduler: No keyframe list found.") |
| return () |
| else: |
| lines = keyframe_list.split('\n') |
| for line in lines: |
| |
| if schedule_format == "Deforum": |
| line = line.replace(":", ",") |
| line = line.rstrip(',') |
| line = line.lstrip() |
| |
| if not line.strip(): |
| print(f"[Warning] CR Simple Prompt Scheduler. Skipped blank line at line {i}") |
| continue |
| schedule_lines.extend([(schedule_alias, line)]) |
| schedule = schedule_lines |
| |
| if mode == "Schedule": |
| if schedule is None: |
| print(f"[Error] CR Prompt Scheduler: No schedule found.") |
| return () |
| |
| if schedule_format == "Deforum": |
| for item in schedule: |
| alias, line = item |
| line = line.replace(":", ",") |
| line = line.rstrip(',') |
| schedule_lines.extend([(schedule_alias, line)]) |
| schedule = schedule_lines |
| |
| current_prompt, next_prompt, current_keyframe, next_keyframe = prompt_scheduler(schedule, schedule_alias, current_frame) |
|
|
| if current_prompt == "": |
| print(f"[Warning] CR Simple Prompt Scheduler. No prompt found for frame. Schedules should start at frame 0.") |
| else: |
| try: |
| current_prompt_out = prepend_text + ", " + str(current_prompt) + ", " + append_text |
| next_prompt_out = prepend_text + ", " + str(next_prompt) + ", " + append_text |
| from_index = int(current_keyframe) |
| to_index = int(next_keyframe) |
| except ValueError: |
| print(f"[Warning] CR Simple Text Scheduler. Invalid keyframe at frame {current_frame}") |
| |
| if from_index == to_index or interpolate_prompt == "No": |
| weight_out = 1.0 |
| else: |
| weight_out = (to_index - current_frame) / (to_index - from_index) |
|
|
| |
| |
| |
| |
| |
| |
| return (current_prompt_out, next_prompt_out, weight_out, show_help, ) |
|
|
| |
| class CR_SimplePromptScheduler: |
| |
| @classmethod |
| def INPUT_TYPES(s): |
| return {"required": {"keyframe_list": ("STRING", {"multiline": True, "default": "frame_number, text"}), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| "keyframe_format": (["CR", "Deforum"],), |
| }, |
| } |
| |
| RETURN_TYPES = ("STRING", "STRING", "FLOAT", "STRING", ) |
| RETURN_NAMES = ("current_prompt", "next_prompt", "weight", "show_help", ) |
| FUNCTION = "simple_schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def simple_schedule(self, keyframe_list, keyframe_format, current_frame): |
| |
| keyframes = list() |
| |
| if keyframe_list == "": |
| print(f"[Error] CR Simple Prompt Scheduler. No lines in keyframe list") |
| return () |
| lines = keyframe_list.split('\n') |
| for line in lines: |
| |
| if keyframe_format == "Deforum": |
| line = line.replace(":", ",") |
| line = line.rstrip(',') |
| if not line.strip(): |
| print(f"[Warning] CR Simple Prompt Scheduler. Skipped blank line at line {i}") |
| continue |
| keyframes.extend([("SIMPLE", line)]) |
| |
| |
| current_prompt, next_prompt, current_keyframe, next_keyframe = prompt_scheduler(keyframes, "SIMPLE", current_frame) |
|
|
| if current_prompt == "": |
| print(f"[Warning] CR Simple Prompt Scheduler. No prompt found for frame. Simple schedules must start at frame 0.") |
| else: |
| try: |
| current_prompt_out = str(current_prompt) |
| next_prompt_out = str(next_prompt) |
| from_index = int(current_keyframe) |
| to_index = int(next_keyframe) |
| except ValueError: |
| print(f"[Warning] CR Simple Text Scheduler. Invalid keyframe at frame {current_frame}") |
| |
| if from_index == to_index: |
| weight_out = 1.0 |
| else: |
| weight_out = (to_index - current_frame) / (to_index - from_index) |
| |
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-simple-prompt-scheduler" |
|
|
| return(current_prompt_out, next_prompt_out, weight_out, show_help, ) |
| |
| |
| class CR_SimpleValueScheduler: |
| |
| @classmethod |
| def INPUT_TYPES(s): |
| return {"required": {"schedule": ("STRING", {"multiline": True, "default": "frame_number, value"}), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| }, |
| } |
| |
| RETURN_TYPES = ("INT", "FLOAT", "STRING", ) |
| RETURN_NAMES = ("INT", "FLOAT", "show_help", ) |
| FUNCTION = "simple_schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def simple_schedule(self, schedule, current_frame): |
|
|
| schedule_lines = list() |
| |
| if schedule == "": |
| print(f"[Warning] CR Simple Value Scheduler. No lines in schedule") |
| return () |
| |
| lines = schedule.split('\n') |
| for line in lines: |
| schedule_lines.extend([("SIMPLE", line)]) |
| |
| params = keyframe_scheduler(schedule_lines, "SIMPLE", current_frame) |
|
|
| if params == "": |
| print(f"[Warning] CR Simple Value Scheduler. No schedule found for frame. Simple schedules must start at frame 0.") |
| else: |
| try: |
| int_out = int(params.split('.')[0]) |
| float_out = float(params) |
| except ValueError: |
| print(f"[Warning] CR Simple Value Scheduler. Invalid params {params} at frame {current_frame}") |
|
|
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-simple-value-scheduler" |
|
|
| return (int_out, float_out, show_help, ) |
| |
| |
| class CR_SimpleTextScheduler: |
| |
| @classmethod |
| def INPUT_TYPES(s): |
| return {"required": {"schedule": ("STRING", {"multiline": True, "default": "frame_number, text"}), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| }, |
| } |
| |
| RETURN_TYPES = ("STRING", "STRING", ) |
| RETURN_NAMES = ("STRING", "show_help", ) |
| FUNCTION = "simple_schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def simple_schedule(self, schedule, current_frame): |
| |
| schedule_lines = list() |
| |
| if schedule == "": |
| print(f"[Warning] CR Simple Text Scheduler. No lines in schedule") |
| return () |
| |
| lines = schedule.split('\n') |
| for line in lines: |
| schedule_lines.extend([("SIMPLE", line)]) |
| |
| params = keyframe_scheduler(schedule_lines, "SIMPLE", current_frame) |
|
|
| if params == "": |
| print(f"[Warning] CR Simple Text Scheduler. No schedule found for frame. Simple schedules must start at frame 0.") |
| else: |
| try: |
| text_out = str(params) |
| except ValueError: |
| print(f"[Warning] CR Simple Text Scheduler. Invalid params {params} at frame {current_frame}") |
|
|
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-simple-text-scheduler" |
|
|
| return(text_out, show_help, ) |
|
|
| |
| class CR_LoadScheduledModels: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
| |
| modes = ["Load default Model", "Schedule"] |
|
|
| return {"required": {"mode": (modes,), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| "schedule_alias": ("STRING", {"default": "", "multiline": False}), |
| "default_model": (folder_paths.get_filename_list("checkpoints"), ), |
| "schedule_format": (["CR", "Deforum"],) |
| }, |
| "optional": {"model_list": ("MODEL_LIST",), |
| "schedule": ("SCHEDULE",) |
| }, |
| } |
| |
| RETURN_TYPES = ("MODEL", "CLIP", "VAE", "STRING", ) |
| RETURN_NAMES = ("MODEL", "CLIP", "VAE", "show_help", ) |
| FUNCTION = "schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def schedule(self, mode, current_frame, schedule_alias, default_model, schedule_format, model_list=None, schedule=None): |
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-load-scheduled-models" |
|
|
| |
| |
| |
| if mode == "Load default Model": |
| ckpt_path = folder_paths.get_full_path("checkpoints", default_model) |
| out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings")) |
| print(f"[Debug] CR Load Scheduled Models. Loading default model.") |
| return (out[:3], show_help, ) |
| |
| |
| params = keyframe_scheduler(schedule, schedule_alias, current_frame) |
| |
| |
| if params == "": |
| print(f"[Warning] CR Load Scheduled Models. No model specified in schedule for frame {current_frame}. Using default model.") |
| ckpt_path = folder_paths.get_full_path("checkpoints", default_model) |
| out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings")) |
| return (out[:3], show_help, ) |
| else: |
| |
| try: |
| model_alias = str(params) |
| except ValueError: |
| print(f"[Warning] CR Load Scheduled Models. Invalid params: {params}") |
| return() |
|
|
| |
| for ckpt_alias, ckpt_name in model_list: |
| if ckpt_alias == model_alias: |
| model_name = ckpt_name |
| break |
| |
| |
| if model_name == "": |
| print(f"[Info] CR Load Scheduled Models. No model alias match found for {model_alias}. Frame {current_frame} will produce an error.") |
| return() |
| else: |
| print(f"[Info] CR Load Scheduled Models. Model alias {model_alias} matched to {model_name}") |
| |
| |
| ckpt_path = folder_paths.get_full_path("checkpoints", model_name) |
| out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings")) |
| print(f"[Info] CR Load Scheduled Models. Loading new checkpoint model {model_name}") |
| return (out[:3], show_help, ) |
| |
| |
| class CR_LoadScheduledLoRAs: |
|
|
| @classmethod |
| def INPUT_TYPES(s): |
| |
| modes = ["Off", "Load default LoRA", "Schedule"] |
|
|
| return {"required": {"mode": (modes,), |
| "model": ("MODEL",), |
| "clip": ("CLIP", ), |
| "current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 9999.0, "step": 1.0,}), |
| "schedule_alias": ("STRING", {"default": "", "multiline": False}), |
| "default_lora": (folder_paths.get_filename_list("loras"), ), |
| "strength_model": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}), |
| "strength_clip": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}), |
| "schedule_format": (["CR", "Deforum"],) |
| }, |
| "optional": {"lora_list": ("LORA_LIST",), |
| "schedule": ("SCHEDULE",) |
| }, |
| } |
| |
| RETURN_TYPES = ("MODEL", "CLIP", "STRING", ) |
| RETURN_NAMES = ("MODEL", "CLIP", "show_help", ) |
| FUNCTION = "schedule" |
| CATEGORY = icons.get("Comfyroll/Animation/Schedulers") |
|
|
| def schedule(self, mode, model, clip, current_frame, schedule_alias, default_lora, strength_model, strength_clip, schedule_format, lora_list=None, schedule=None): |
| show_help = "https://github.com/Suzie1/ComfyUI_Comfyroll_CustomNodes/wiki/Scheduler-Nodes#cr-load-scheduled-loras" |
| |
|
|
| |
| if mode == "Off": |
| print(f"[Info] CR Load Scheduled LoRAs. Disabled.") |
| return (model, clip, show_help, ) |
| |
| |
| if mode == "Load default LoRA": |
| if default_lora == None: |
| return (model, clip, show_help, ) |
| if strength_model == 0 and strength_clip == 0: |
| return (model, clip, show_help, ) |
| model, clip = LoraLoader().load_lora(model, clip, default_lora, strength_model, strength_clip) |
| print(f"[Info] CR Load Scheduled LoRAs. Loading default LoRA {lora_name}.") |
| return (model, clip, show_help, ) |
| |
| |
| params = keyframe_scheduler(schedule, schedule_alias, current_frame) |
| |
| |
| if params == "": |
| print(f"[Warning] CR Load Scheduled LoRAs. No LoRA specified in schedule for frame {current_frame}. Using default lora.") |
| if default_lora != None: |
| model, clip = LoraLoader().load_lora(model, clip, default_lora, strength_model, strength_clip) |
| return (model, clip, show_help, ) |
| else: |
| |
| parts = params.split(',') |
| if len(parts) == 3: |
| s_lora_alias = parts[0].strip() |
| s_strength_model = float(parts[1].strip()) |
| s_strength_clip = float(parts[1].strip()) |
| else: |
| print(f"[Warning] CR Simple Value Scheduler. Skipped invalid line: {line}") |
| return() |
|
|
| |
| for l_lora_alias, l_lora_name, l_strength_model, l_strength_clip in lora_list: |
| print(l_lora_alias, l_lora_name, l_strength_model, l_strength_clip) |
| if l_lora_alias == s_lora_alias: |
| print(f"[Info] CR Load Scheduled LoRAs. LoRA alias match found for {s_lora_alias}") |
| lora_name = l_lora_name |
| break |
| |
| |
| if lora_name == "": |
| print(f"[Info] CR Load Scheduled LoRAs. No LoRA alias match found for {s_lora_alias}. Frame {current_frame}.") |
| return() |
| else: |
| print(f"[Info] CR Load Scheduled LoRAs. LoRA {lora_name}") |
| |
| |
| model, clip = LoraLoader().load_lora(model, clip, lora_name, s_strength_model, s_strength_clip) |
| print(f"[Debug] CR Load Scheduled LoRAs. Loading new LoRA {lora_name}") |
| return (model, clip, show_help, ) |
| |
| |
| |
| |
| |
| |
| ''' |
| NODE_CLASS_MAPPINGS = { |
| ### Schedulers |
| "CR Simple Value Scheduler":CR_SimpleValueScheduler, |
| "CR Simple Text Scheduler":CR_SimpleTextScheduler, |
| "CR Simple Prompt Scheduler":CR_SimplePromptScheduler, |
| "CR Load Scheduled Models":CR_LoadScheduledModels, |
| "CR Load Scheduled LoRAs":CR_LoadScheduledLoRAs, |
| "CR Load Scheduled ControlNets":CR_LoadScheduledControlNets, |
| "CR Value Scheduler":CR_ValueScheduler, |
| "CR Text Scheduler":CR_TextScheduler, |
| "CR Prompt Scheduler":CR_PromptScheduler, |
| } |
| ''' |
|
|
|
|