Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9257651221 | ||
|
|
50ea19fa90 | ||
|
|
2a12eaaec0 | ||
|
|
8a0e706567 | ||
|
|
13ed169c47 | ||
|
|
d0db79787d | ||
|
|
2dc014a33e | ||
|
|
d8d163cd90 | ||
|
|
8c277d92bd | ||
|
|
90fb133120 |
+7
-4
@@ -3,17 +3,20 @@ from .animatediff.logger import logger
|
||||
from .animatediff.utils_model import get_available_motion_models, Folders
|
||||
from .animatediff.model_injection import prepare_dinklink_register_definitions
|
||||
from .animatediff.motion_module_ad import prepare_dinklink_motion_module_ad
|
||||
from .animatediff.nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
||||
from .animatediff import documentation
|
||||
from .animatediff.nodes import AnimateDiffExtension
|
||||
from .animatediff.dinklink import init_dinklink
|
||||
|
||||
if len(get_available_motion_models()) == 0:
|
||||
logger.error(f"No motion models found. Please download one and place in: {folder_paths.get_folder_paths(Folders.ANIMATEDIFF_MODELS)}")
|
||||
|
||||
WEB_DIRECTORY = "./web"
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
||||
documentation.format_descriptions(NODE_CLASS_MAPPINGS)
|
||||
|
||||
__all__ = ["WEB_DIRECTORY"]
|
||||
|
||||
init_dinklink()
|
||||
prepare_dinklink_register_definitions()
|
||||
prepare_dinklink_motion_module_ad()
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> AnimateDiffExtension:
|
||||
return AnimateDiffExtension()
|
||||
|
||||
@@ -70,9 +70,9 @@ def load_hmreferenceadapter(model_name: str):
|
||||
else:
|
||||
ops = comfy.ops.manual_cast
|
||||
hmref = HMReferenceAdapter(ops=ops)
|
||||
hmref.to(comfy.model_management.unet_dtype())
|
||||
hmref.to(comfy.model_management.unet_offload_device())
|
||||
load_result = hmref.load_state_dict(state_dict, strict=True)
|
||||
hmref.to(comfy.model_management.unet_dtype())
|
||||
hmref_model = create_HMModelPatcher(model=hmref, load_device=comfy.model_management.get_torch_device(),
|
||||
offload_device=comfy.model_management.unet_offload_device())
|
||||
return hmref_model
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
from typing import Union
|
||||
|
||||
from .logger import logger
|
||||
|
||||
def image(src):
|
||||
return f'<img src={src} style="width: 0px; min-width: 100%">'
|
||||
def video(src):
|
||||
return f'<video src={src} autoplay muted loop controls controlslist="nodownload noremoteplayback noplaybackrate" style="width: 0px; min-width: 100%" class="VHS_loopedvideo">'
|
||||
def short_desc(desc):
|
||||
return f'<div id=VHS_shortdesc style="font-size: .8em">{desc}</div>'
|
||||
|
||||
def coll(text: str):
|
||||
return f"{text}_collapsed"
|
||||
|
||||
descriptions = {
|
||||
}
|
||||
|
||||
sizes = ['1.4','1.2','1']
|
||||
def as_html(entry, depth=0):
|
||||
if isinstance(entry, dict):
|
||||
size = 0.8 if depth < 2 else 1
|
||||
html = ''
|
||||
for k in entry:
|
||||
if k == "collapsed":
|
||||
continue
|
||||
collapse_single = k.endswith("_collapsed")
|
||||
if collapse_single:
|
||||
name = k[:-len("_collapsed")]
|
||||
else:
|
||||
name = k
|
||||
collapse_flag = ' VHS_precollapse' if entry.get("collapsed", False) or collapse_single else ''
|
||||
html += f'<div vhs_title=\"{name}\" style=\"display: flex; font-size: {size}em\" class=\"VHS_collapse{collapse_flag}\"><div style=\"color: #AAA; height: 1.5em;\">[<span style=\"font-family: monospace\">-</span>]</div><div style=\"width: 100%\">{name}: {as_html(entry[k], depth=depth+1)}</div></div>'
|
||||
return html
|
||||
if isinstance(entry, list):
|
||||
html = ''
|
||||
for i in entry:
|
||||
html += f'<div>{as_html(i, depth=depth)}</div>'
|
||||
return html
|
||||
return str(entry)
|
||||
|
||||
|
||||
def register_description(node_id: str, desc: Union[list, dict]):
|
||||
descriptions[node_id] = desc
|
||||
|
||||
|
||||
def format_descriptions(nodes):
|
||||
for k in descriptions:
|
||||
if k.endswith("_collapsed"):
|
||||
k = k[:-len("_collapsed")]
|
||||
nodes[k].DESCRIPTION = as_html(descriptions[k])
|
||||
# undocumented_nodes = []
|
||||
# for k in nodes:
|
||||
# if not hasattr(nodes[k], "DESCRIPTION"):
|
||||
# undocumented_nodes.append(k)
|
||||
# if len(undocumented_nodes) > 0:
|
||||
# logger.info(f"Undocumented nodes: {undocumented_nodes}")
|
||||
|
||||
|
||||
class DocHelper:
|
||||
def __init__(self):
|
||||
self.actual_dict = {}
|
||||
|
||||
def add(self, add_dict):
|
||||
self.actual_dict.update(add_dict)
|
||||
return self
|
||||
|
||||
def get(self):
|
||||
return self.actual_dict
|
||||
|
||||
@staticmethod
|
||||
def combine(*args):
|
||||
docs = DocHelper()
|
||||
for doc in args:
|
||||
docs.add(doc)
|
||||
return docs.get()
|
||||
@@ -841,9 +841,9 @@ def load_motion_module_gen1(model_name: str, model: ModelPatcher, motion_lora: M
|
||||
mm_state_dict = apply_mm_settings(model_dict=mm_state_dict, mm_settings=motion_model_settings)
|
||||
# initialize AnimateDiffModelWrapper
|
||||
ad_wrapper = AnimateDiffModel(mm_state_dict=mm_state_dict, mm_info=mm_info)
|
||||
ad_wrapper.to(model.model_dtype())
|
||||
ad_wrapper.to(model.offload_device)
|
||||
load_result = ad_wrapper.load_state_dict(mm_state_dict, strict=False)
|
||||
ad_wrapper.to(model.model_dtype())
|
||||
verify_load_result(load_result=load_result, mm_info=mm_info)
|
||||
# wrap motion_module into a ModelPatcher, to allow motion lora patches
|
||||
motion_model = create_MotionModelPatcher(model=ad_wrapper, load_device=model.load_device, offload_device=model.offload_device)
|
||||
@@ -865,9 +865,9 @@ def load_motion_module_gen2(model_name: str, motion_model_settings: AnimateDiffS
|
||||
mm_state_dict = apply_mm_settings(model_dict=mm_state_dict, mm_settings=motion_model_settings)
|
||||
# initialize AnimateDiffModelWrapper
|
||||
ad_wrapper = AnimateDiffModel(mm_state_dict=mm_state_dict, mm_info=mm_info)
|
||||
ad_wrapper.to(comfy.model_management.unet_dtype())
|
||||
ad_wrapper.to(comfy.model_management.unet_offload_device())
|
||||
load_result = ad_wrapper.load_state_dict(mm_state_dict, strict=False)
|
||||
ad_wrapper.to(comfy.model_management.unet_dtype())
|
||||
verify_load_result(load_result=load_result, mm_info=mm_info)
|
||||
# wrap motion_module into a ModelPatcher, to allow motion lora patches
|
||||
motion_model = create_MotionModelPatcher(model=ad_wrapper, load_device=comfy.model_management.get_torch_device(),
|
||||
@@ -907,34 +907,34 @@ def verify_load_result(load_result: IncompatibleKeys, mm_info: AnimateDiffInfo):
|
||||
|
||||
def create_fresh_motion_module(motion_model: MotionModelPatcher) -> MotionModelPatcher:
|
||||
ad_wrapper = AnimateDiffModel(mm_state_dict=motion_model.model.state_dict(), mm_info=motion_model.model.mm_info)
|
||||
ad_wrapper.to(comfy.model_management.unet_dtype())
|
||||
ad_wrapper.to(comfy.model_management.unet_offload_device())
|
||||
ad_wrapper.load_state_dict(motion_model.model.state_dict())
|
||||
ad_wrapper.to(comfy.model_management.unet_dtype())
|
||||
return create_MotionModelPatcher(model=ad_wrapper, load_device=comfy.model_management.get_torch_device(),
|
||||
offload_device=comfy.model_management.unet_offload_device())
|
||||
|
||||
|
||||
def create_fresh_encoder_only_model(motion_model: MotionModelPatcher) -> MotionModelPatcher:
|
||||
ad_wrapper = EncoderOnlyAnimateDiffModel(mm_state_dict=motion_model.model.state_dict(), mm_info=motion_model.model.mm_info)
|
||||
ad_wrapper.to(comfy.model_management.unet_dtype())
|
||||
ad_wrapper.to(comfy.model_management.unet_offload_device())
|
||||
ad_wrapper.load_state_dict(motion_model.model.state_dict(), strict=False)
|
||||
ad_wrapper.to(comfy.model_management.unet_dtype())
|
||||
return create_MotionModelPatcher(model=ad_wrapper, load_device=comfy.model_management.get_torch_device(),
|
||||
offload_device=comfy.model_management.unet_offload_device())
|
||||
|
||||
|
||||
def inject_img_encoder_into_model(motion_model: MotionModelPatcher, w_encoder: MotionModelPatcher):
|
||||
motion_model.model.init_img_encoder()
|
||||
motion_model.model.img_encoder.to(comfy.model_management.unet_dtype())
|
||||
motion_model.model.img_encoder.to(comfy.model_management.unet_offload_device())
|
||||
motion_model.model.img_encoder.load_state_dict(w_encoder.model.img_encoder.state_dict())
|
||||
motion_model.model.img_encoder.to(comfy.model_management.unet_dtype())
|
||||
|
||||
|
||||
def inject_pia_conv_in_into_model(motion_model: MotionModelPatcher, w_pia: MotionModelPatcher):
|
||||
motion_model.model.init_conv_in(w_pia.model.state_dict())
|
||||
motion_model.model.conv_in.to(comfy.model_management.unet_dtype())
|
||||
motion_model.model.conv_in.to(comfy.model_management.unet_offload_device())
|
||||
motion_model.model.conv_in.load_state_dict(w_pia.model.conv_in.state_dict())
|
||||
motion_model.model.conv_in.to(comfy.model_management.unet_dtype())
|
||||
motion_model.model.mm_info.mm_format = AnimateDiffFormat.PIA
|
||||
|
||||
|
||||
@@ -956,9 +956,9 @@ def inject_camera_encoder_into_model(motion_model: MotionModelPatcher, camera_ct
|
||||
# initialize CameraPoseEncoder on motion model, and load keys
|
||||
camera_encoder = CameraPoseEncoder(channels=motion_model.model.layer_channels, nums_rb=2, ops=motion_model.model.ops).to(
|
||||
device=comfy.model_management.unet_offload_device(),
|
||||
dtype=comfy.model_management.unet_dtype()
|
||||
)
|
||||
camera_encoder.load_state_dict(camera_state_dict)
|
||||
camera_encoder.to(dtype=comfy.model_management.unet_dtype())
|
||||
camera_encoder.temporal_pe_max_len = get_position_encoding_max_len(camera_state_dict, mm_name=camera_ctrl_name, mm_format=AnimateDiffFormat.ANIMATEDIFF)
|
||||
motion_model.model.set_camera_encoder(camera_encoder=camera_encoder)
|
||||
# initialize qkv_merge on specific attention blocks, and load keys
|
||||
|
||||
+324
-411
@@ -1,415 +1,328 @@
|
||||
import comfy.sample as comfy_sample
|
||||
from comfy_api.latest import ComfyExtension, io
|
||||
|
||||
from .nodes_gen1 import (AnimateDiffLoaderGen1,)
|
||||
from .nodes_gen2 import (UseEvolvedSamplingNode, ApplyAnimateDiffModelNode, ApplyAnimateDiffModelBasicNode, ADKeyframeNode,
|
||||
LoadAnimateDiffModelNode)
|
||||
from .nodes_animatelcmi2v import (ApplyAnimateLCMI2VModel, LoadAnimateLCMI2VModelNode, LoadAnimateDiffAndInjectI2VNode, UpscaleAndVaeEncode)
|
||||
from .nodes_cameractrl import (LoadAnimateDiffModelWithCameraCtrl, ApplyAnimateDiffWithCameraCtrl, CameraCtrlADKeyframeNode,
|
||||
LoadCameraPosesFromFile, LoadCameraPosesFromPath,
|
||||
CameraCtrlPoseBasic, CameraCtrlPoseCombo, CameraCtrlPoseAdvanced, CameraCtrlManualAppendPose,
|
||||
CameraCtrlReplaceCameraParameters, CameraCtrlSetOriginalAspectRatio)
|
||||
from .nodes_motionctrl import (LoadMotionCtrlCMCM, LoadMotionCtrlOMCM, ApplyAnimateDiffMotionCtrlModel, LoadMotionCtrlCameraPosesFromFile)
|
||||
from .nodes_pia import (ApplyAnimateDiffPIAModel, LoadAnimateDiffAndInjectPIANode, InputPIA_MultivalNode, InputPIA_PaperPresetsNode, PIA_ADKeyframeNode)
|
||||
from .nodes_fancyvideo import (ApplyAnimateDiffFancyVideo,)
|
||||
from .nodes_hellomeme import (TestHMRefNetInjection,)
|
||||
from .nodes_multival import MultivalDynamicNode, MultivalScaledMaskNode, MultivalDynamicFloatInputNode, MultivalDynamicFloatsNode, MultivalConvertToMaskNode
|
||||
from .nodes_conditioning import (CreateLoraHookKeyframeInterpolationDEPR,
|
||||
MaskableLoraLoaderDEPR, MaskableLoraLoaderModelOnlyDEPR, MaskableSDModelLoaderDEPR, MaskableSDModelLoaderModelOnlyDEPR,
|
||||
SetModelLoraHookDEPR, SetClipLoraHookDEPR,
|
||||
CombineLoraHooksDEPR, CombineLoraHookFourOptionalDEPR, CombineLoraHookEightOptionalDEPR,
|
||||
PairedConditioningSetMaskHookedDEPR, ConditioningSetMaskHookedDEPR,
|
||||
PairedConditioningSetMaskAndCombineHookedDEPR, ConditioningSetMaskAndCombineHookedDEPR,
|
||||
PairedConditioningSetUnmaskedAndCombineHookedDEPR, ConditioningSetUnmaskedAndCombineHookedDEPR,
|
||||
PairedConditioningCombineDEPR, ConditioningCombineDEPR,
|
||||
ConditioningTimestepsNodeDEPR, SetLoraHookKeyframesDEPR,
|
||||
CreateLoraHookKeyframeDEPR, CreateLoraHookKeyframeFromStrengthListDEPR)
|
||||
from .nodes_sample import (FreeInitOptionsNode, NoiseLayerAddWeightedNode, NoiseLayerNormalizedSumNode, SampleSettingsNode, NoiseLayerAddNode, NoiseLayerReplaceNode, IterationOptionsNode,
|
||||
CustomCFGNode, CustomCFGSimpleNode, CustomCFGKeyframeNode, CustomCFGKeyframeSimpleNode, CustomCFGKeyframeInterpolationNode, CustomCFGKeyframeFromListNode,
|
||||
CFGExtrasPAGNode, CFGExtrasPAGSimpleNode, CFGExtrasRescaleCFGNode, CFGExtrasRescaleCFGSimpleNode,
|
||||
NoisedImageInjectionNode, NoisedImageInjectOptionsNode, NoiseCalibrationNode, AncestralOptionsNode)
|
||||
from .nodes_sigma_schedule import (SigmaScheduleNode, RawSigmaScheduleNode, WeightedAverageSigmaScheduleNode, InterpolatedWeightedAverageSigmaScheduleNode, SplitAndCombineSigmaScheduleNode, SigmaScheduleToSigmasNode)
|
||||
from .nodes_context import (LegacyLoopedUniformContextOptionsNode, LoopedUniformContextOptionsNode, LoopedUniformViewOptionsNode, StandardUniformContextOptionsNode, StandardStaticContextOptionsNode, BatchedContextOptionsNode,
|
||||
StandardStaticViewOptionsNode, StandardUniformViewOptionsNode, ViewAsContextOptionsNode,
|
||||
VisualizeContextOptionsK, VisualizeContextOptionsKAdv, VisualizeContextOptionsSCustom)
|
||||
from .nodes_context_extras import (SetContextExtrasOnContextOptions, ContextExtras_NaiveReuse, ContextExtras_ContextRef,
|
||||
ContextRef_ModeFirst, ContextRef_ModeSliding, ContextRef_ModeIndexes,
|
||||
ContextRef_TuneAttn, ContextRef_TuneAttnAdain,
|
||||
ContextRef_KeyframeMultivalNode, ContextRef_KeyframeInterpolationNode, ContextRef_KeyframeFromListNode,
|
||||
NaiveReuse_KeyframeMultivalNode, NaiveReuse_KeyframeInterpolationNode, NaiveReuse_KeyframeFromListNode)
|
||||
from .nodes_ad_settings import (AnimateDiffSettingsNode, ManualAdjustPENode, SweetspotStretchPENode, FullStretchPENode,
|
||||
WeightAdjustAllAddNode, WeightAdjustAllMultNode, WeightAdjustIndivAddNode, WeightAdjustIndivMultNode,
|
||||
WeightAdjustIndivAttnAddNode, WeightAdjustIndivAttnMultNode)
|
||||
from .nodes_scheduling import (ConditionExtractionNode, PromptSchedulingNode, PromptSchedulingLatentsNode, ValueSchedulingNode, ValueSchedulingLatentsNode,
|
||||
AddValuesReplaceNode, FloatToFloatsNode)
|
||||
from .nodes_per_block import (ADBlockComboNode, ADBlockIndivNode, PerBlockHighLevelNode,
|
||||
PerBlock_SD15_LowLevelNode, PerBlock_SD15_MidLevelNode, PerBlock_SD15_FromFloatsNode,
|
||||
PerBlock_SDXL_LowLevelNode, PerBlock_SDXL_MidLevelNode, PerBlock_SDXL_FromFloatsNode)
|
||||
from .nodes_extras import AnimateDiffUnload, EmptyLatentImageLarge, CheckpointLoaderSimpleWithNoiseSelect, PerturbedAttentionGuidanceMultival, RescaleCFGMultival
|
||||
from .nodes_deprecated import (AnimateDiffLoaderDEPR, AnimateDiffLoaderAdvancedDEPR, LegacyAnimateDiffLoaderWithContextDEPR, AnimateDiffCombineDEPR,
|
||||
AnimateDiffModelSettingsDEPR, AnimateDiffModelSettingsSimpleDEPR, AnimateDiffModelSettingsAdvancedDEPR, AnimateDiffModelSettingsAdvancedAttnStrengthsDEPR)
|
||||
from .nodes_ad_settings import (
|
||||
AnimateDiffSettingsNode,
|
||||
FullStretchPENode,
|
||||
ManualAdjustPENode,
|
||||
SweetspotStretchPENode,
|
||||
WeightAdjustAllAddNode,
|
||||
WeightAdjustAllMultNode,
|
||||
WeightAdjustIndivAddNode,
|
||||
WeightAdjustIndivAttnAddNode,
|
||||
WeightAdjustIndivAttnMultNode,
|
||||
WeightAdjustIndivMultNode,
|
||||
)
|
||||
from .nodes_animatelcmi2v import (
|
||||
ApplyAnimateLCMI2VModel,
|
||||
LoadAnimateDiffAndInjectI2VNode,
|
||||
LoadAnimateLCMI2VModelNode,
|
||||
UpscaleAndVaeEncode,
|
||||
)
|
||||
from .nodes_cameractrl import (
|
||||
ApplyAnimateDiffWithCameraCtrl,
|
||||
CameraCtrlADKeyframeNode,
|
||||
CameraCtrlManualAppendPose,
|
||||
CameraCtrlPoseAdvanced,
|
||||
CameraCtrlPoseBasic,
|
||||
CameraCtrlPoseCombo,
|
||||
CameraCtrlReplaceCameraParameters,
|
||||
CameraCtrlSetOriginalAspectRatio,
|
||||
LoadAnimateDiffModelWithCameraCtrl,
|
||||
LoadCameraPosesFromFile,
|
||||
LoadCameraPosesFromPath,
|
||||
)
|
||||
from .nodes_conditioning import (
|
||||
CombineLoraHookEightOptionalDEPR,
|
||||
CombineLoraHookFourOptionalDEPR,
|
||||
CombineLoraHooksDEPR,
|
||||
ConditioningCombineDEPR,
|
||||
ConditioningSetMaskAndCombineHookedDEPR,
|
||||
ConditioningSetMaskHookedDEPR,
|
||||
ConditioningSetUnmaskedAndCombineHookedDEPR,
|
||||
ConditioningTimestepsNodeDEPR,
|
||||
CreateLoraHookKeyframeDEPR,
|
||||
CreateLoraHookKeyframeFromStrengthListDEPR,
|
||||
CreateLoraHookKeyframeInterpolationDEPR,
|
||||
MaskableLoraLoaderDEPR,
|
||||
MaskableLoraLoaderModelOnlyDEPR,
|
||||
MaskableSDModelLoaderDEPR,
|
||||
MaskableSDModelLoaderModelOnlyDEPR,
|
||||
PairedConditioningCombineDEPR,
|
||||
PairedConditioningSetMaskAndCombineHookedDEPR,
|
||||
PairedConditioningSetMaskHookedDEPR,
|
||||
PairedConditioningSetUnmaskedAndCombineHookedDEPR,
|
||||
SetClipLoraHookDEPR,
|
||||
SetLoraHookKeyframesDEPR,
|
||||
SetModelLoraHookDEPR,
|
||||
)
|
||||
from .nodes_context import (
|
||||
BatchedContextOptionsNode,
|
||||
LegacyLoopedUniformContextOptionsNode,
|
||||
LoopedUniformContextOptionsNode,
|
||||
LoopedUniformViewOptionsNode,
|
||||
StandardStaticContextOptionsNode,
|
||||
StandardStaticViewOptionsNode,
|
||||
StandardUniformContextOptionsNode,
|
||||
StandardUniformViewOptionsNode,
|
||||
ViewAsContextOptionsNode,
|
||||
VisualizeContextOptionsK,
|
||||
VisualizeContextOptionsKAdv,
|
||||
VisualizeContextOptionsSCustom,
|
||||
)
|
||||
from .nodes_context_extras import (
|
||||
ContextExtras_ContextRef,
|
||||
ContextExtras_NaiveReuse,
|
||||
ContextRef_KeyframeFromListNode,
|
||||
ContextRef_KeyframeInterpolationNode,
|
||||
ContextRef_KeyframeMultivalNode,
|
||||
ContextRef_ModeFirst,
|
||||
ContextRef_ModeIndexes,
|
||||
ContextRef_ModeSliding,
|
||||
ContextRef_TuneAttn,
|
||||
ContextRef_TuneAttnAdain,
|
||||
NaiveReuse_KeyframeFromListNode,
|
||||
NaiveReuse_KeyframeInterpolationNode,
|
||||
NaiveReuse_KeyframeMultivalNode,
|
||||
SetContextExtrasOnContextOptions,
|
||||
)
|
||||
from .nodes_deprecated import (
|
||||
AnimateDiffCombineDEPR,
|
||||
AnimateDiffLoaderAdvancedDEPR,
|
||||
AnimateDiffLoaderDEPR,
|
||||
AnimateDiffModelSettingsAdvancedAttnStrengthsDEPR,
|
||||
AnimateDiffModelSettingsAdvancedDEPR,
|
||||
AnimateDiffModelSettingsDEPR,
|
||||
AnimateDiffModelSettingsSimpleDEPR,
|
||||
LegacyAnimateDiffLoaderWithContextDEPR,
|
||||
)
|
||||
from .nodes_extras import (
|
||||
AnimateDiffUnload,
|
||||
CheckpointLoaderSimpleWithNoiseSelect,
|
||||
EmptyLatentImageLarge,
|
||||
PerturbedAttentionGuidanceMultival,
|
||||
RescaleCFGMultival,
|
||||
)
|
||||
from .nodes_gen1 import AnimateDiffLoaderGen1
|
||||
from .nodes_gen2 import (
|
||||
ADKeyframeNode,
|
||||
ApplyAnimateDiffModelBasicNode,
|
||||
ApplyAnimateDiffModelNode,
|
||||
LoadAnimateDiffModelNode,
|
||||
UseEvolvedSamplingNode,
|
||||
)
|
||||
from .nodes_lora import AnimateDiffLoraLoader
|
||||
|
||||
from .logger import logger
|
||||
from .nodes_multival import (
|
||||
MultivalConvertToMaskNode,
|
||||
MultivalDynamicFloatInputNode,
|
||||
MultivalDynamicFloatsNode,
|
||||
MultivalDynamicNode,
|
||||
MultivalScaledMaskNode,
|
||||
)
|
||||
from .nodes_per_block import (
|
||||
ADBlockComboNode,
|
||||
ADBlockIndivNode,
|
||||
PerBlockHighLevelNode,
|
||||
PerBlock_SD15_FromFloatsNode,
|
||||
PerBlock_SD15_LowLevelNode,
|
||||
PerBlock_SD15_MidLevelNode,
|
||||
PerBlock_SDXL_FromFloatsNode,
|
||||
PerBlock_SDXL_LowLevelNode,
|
||||
PerBlock_SDXL_MidLevelNode,
|
||||
)
|
||||
from .nodes_pia import (
|
||||
ApplyAnimateDiffPIAModel,
|
||||
InputPIA_MultivalNode,
|
||||
InputPIA_PaperPresetsNode,
|
||||
LoadAnimateDiffAndInjectPIANode,
|
||||
PIA_ADKeyframeNode,
|
||||
)
|
||||
from .nodes_sample import (
|
||||
AncestralOptionsNode,
|
||||
CFGExtrasPAGNode,
|
||||
CFGExtrasPAGSimpleNode,
|
||||
CFGExtrasRescaleCFGNode,
|
||||
CFGExtrasRescaleCFGSimpleNode,
|
||||
CustomCFGKeyframeFromListNode,
|
||||
CustomCFGKeyframeInterpolationNode,
|
||||
CustomCFGKeyframeNode,
|
||||
CustomCFGKeyframeSimpleNode,
|
||||
CustomCFGNode,
|
||||
CustomCFGSimpleNode,
|
||||
FreeInitOptionsNode,
|
||||
IterationOptionsNode,
|
||||
NoisedImageInjectionNode,
|
||||
NoisedImageInjectOptionsNode,
|
||||
NoiseLayerAddNode,
|
||||
NoiseLayerAddWeightedNode,
|
||||
NoiseLayerNormalizedSumNode,
|
||||
NoiseLayerReplaceNode,
|
||||
SampleSettingsNode,
|
||||
)
|
||||
from .nodes_scheduling import (
|
||||
AddValuesReplaceNode,
|
||||
ConditionExtractionNode,
|
||||
FloatToFloatsNode,
|
||||
PromptSchedulingLatentsNode,
|
||||
PromptSchedulingNode,
|
||||
ValueSchedulingLatentsNode,
|
||||
ValueSchedulingNode,
|
||||
)
|
||||
from .nodes_sigma_schedule import (
|
||||
InterpolatedWeightedAverageSigmaScheduleNode,
|
||||
RawSigmaScheduleNode,
|
||||
SigmaScheduleNode,
|
||||
SigmaScheduleToSigmasNode,
|
||||
SplitAndCombineSigmaScheduleNode,
|
||||
WeightedAverageSigmaScheduleNode,
|
||||
)
|
||||
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
# Unencapsulated
|
||||
"ADE_AnimateDiffLoRALoader": AnimateDiffLoraLoader,
|
||||
"ADE_AnimateDiffSamplingSettings": SampleSettingsNode,
|
||||
"ADE_AnimateDiffKeyframe": ADKeyframeNode,
|
||||
# Multival Nodes
|
||||
"ADE_MultivalDynamic": MultivalDynamicNode,
|
||||
"ADE_MultivalDynamicFloatInput": MultivalDynamicFloatInputNode,
|
||||
"ADE_MultivalDynamicFloats": MultivalDynamicFloatsNode,
|
||||
"ADE_MultivalScaledMask": MultivalScaledMaskNode,
|
||||
"ADE_MultivalConvertToMask": MultivalConvertToMaskNode,
|
||||
###############################################################################
|
||||
#------------------------------------------------------------------------------
|
||||
# Context Opts
|
||||
"ADE_StandardStaticContextOptions": StandardStaticContextOptionsNode,
|
||||
"ADE_StandardUniformContextOptions": StandardUniformContextOptionsNode,
|
||||
"ADE_LoopedUniformContextOptions": LoopedUniformContextOptionsNode,
|
||||
"ADE_ViewsOnlyContextOptions": ViewAsContextOptionsNode,
|
||||
"ADE_BatchedContextOptions": BatchedContextOptionsNode,
|
||||
"ADE_AnimateDiffUniformContextOptions": LegacyLoopedUniformContextOptionsNode, # Legacy/Deprecated
|
||||
"ADE_VisualizeContextOptionsK": VisualizeContextOptionsK,
|
||||
"ADE_VisualizeContextOptionsKAdv": VisualizeContextOptionsKAdv,
|
||||
"ADE_VisualizeContextOptionsSCustom": VisualizeContextOptionsSCustom,
|
||||
# View Opts
|
||||
"ADE_StandardStaticViewOptions": StandardStaticViewOptionsNode,
|
||||
"ADE_StandardUniformViewOptions": StandardUniformViewOptionsNode,
|
||||
"ADE_LoopedUniformViewOptions": LoopedUniformViewOptionsNode,
|
||||
# Context Extras
|
||||
"ADE_ContextExtras_Set": SetContextExtrasOnContextOptions,
|
||||
"ADE_ContextExtras_ContextRef": ContextExtras_ContextRef,
|
||||
"ADE_ContextExtras_ContextRef_ModeFirst": ContextRef_ModeFirst,
|
||||
"ADE_ContextExtras_ContextRef_ModeSliding": ContextRef_ModeSliding,
|
||||
"ADE_ContextExtras_ContextRef_ModeIndexes": ContextRef_ModeIndexes,
|
||||
"ADE_ContextExtras_ContextRef_TuneAttn": ContextRef_TuneAttn,
|
||||
"ADE_ContextExtras_ContextRef_TuneAttnAdain": ContextRef_TuneAttnAdain,
|
||||
"ADE_ContextExtras_ContextRef_Keyframe": ContextRef_KeyframeMultivalNode,
|
||||
"ADE_ContextExtras_ContextRef_KeyframeInterpolation": ContextRef_KeyframeInterpolationNode,
|
||||
"ADE_ContextExtras_ContextRef_KeyframeFromList": ContextRef_KeyframeFromListNode,
|
||||
"ADE_ContextExtras_NaiveReuse": ContextExtras_NaiveReuse,
|
||||
"ADE_ContextExtras_NaiveReuse_Keyframe": NaiveReuse_KeyframeMultivalNode,
|
||||
"ADE_ContextExtras_NaiveReuse_KeyframeInterpolation": NaiveReuse_KeyframeInterpolationNode,
|
||||
"ADE_ContextExtras_NaiveReuse_KeyframeFromList": NaiveReuse_KeyframeFromListNode,
|
||||
#------------------------------------------------------------------------------
|
||||
###############################################################################
|
||||
# Iteration Opts
|
||||
"ADE_IterationOptsDefault": IterationOptionsNode,
|
||||
"ADE_IterationOptsFreeInit": FreeInitOptionsNode,
|
||||
# Conditioning
|
||||
# Conditioning (DEPRECATED)
|
||||
"ADE_RegisterLoraHook": MaskableLoraLoaderDEPR,
|
||||
"ADE_RegisterLoraHookModelOnly": MaskableLoraLoaderModelOnlyDEPR,
|
||||
"ADE_RegisterModelAsLoraHook": MaskableSDModelLoaderDEPR,
|
||||
"ADE_RegisterModelAsLoraHookModelOnly": MaskableSDModelLoaderModelOnlyDEPR,
|
||||
"ADE_CombineLoraHooks": CombineLoraHooksDEPR,
|
||||
"ADE_CombineLoraHooksFour": CombineLoraHookFourOptionalDEPR,
|
||||
"ADE_CombineLoraHooksEight": CombineLoraHookEightOptionalDEPR,
|
||||
"ADE_SetLoraHookKeyframe": SetLoraHookKeyframesDEPR,
|
||||
"ADE_AttachLoraHookToCLIP": SetClipLoraHookDEPR,
|
||||
"ADE_LoraHookKeyframe": CreateLoraHookKeyframeDEPR,
|
||||
"ADE_LoraHookKeyframeInterpolation": CreateLoraHookKeyframeInterpolationDEPR,
|
||||
"ADE_LoraHookKeyframeFromStrengthList": CreateLoraHookKeyframeFromStrengthListDEPR,
|
||||
"ADE_AttachLoraHookToConditioning": SetModelLoraHookDEPR,
|
||||
"ADE_PairedConditioningSetMask": PairedConditioningSetMaskHookedDEPR,
|
||||
"ADE_ConditioningSetMask": ConditioningSetMaskHookedDEPR,
|
||||
"ADE_PairedConditioningSetMaskAndCombine": PairedConditioningSetMaskAndCombineHookedDEPR,
|
||||
"ADE_ConditioningSetMaskAndCombine": ConditioningSetMaskAndCombineHookedDEPR,
|
||||
"ADE_PairedConditioningSetUnmaskedAndCombine": PairedConditioningSetUnmaskedAndCombineHookedDEPR,
|
||||
"ADE_ConditioningSetUnmaskedAndCombine": ConditioningSetUnmaskedAndCombineHookedDEPR,
|
||||
"ADE_PairedConditioningCombine": PairedConditioningCombineDEPR,
|
||||
"ADE_ConditioningCombine": ConditioningCombineDEPR,
|
||||
"ADE_TimestepsConditioning": ConditioningTimestepsNodeDEPR,
|
||||
# Noise Layer Nodes
|
||||
"ADE_NoiseLayerAdd": NoiseLayerAddNode,
|
||||
"ADE_NoiseLayerAddWeighted": NoiseLayerAddWeightedNode,
|
||||
"ADE_NoiseLayerNormalizedSum": NoiseLayerNormalizedSumNode,
|
||||
"ADE_NoiseLayerReplace": NoiseLayerReplaceNode,
|
||||
# AnimateDiff Settings
|
||||
"ADE_AnimateDiffSettings": AnimateDiffSettingsNode,
|
||||
"ADE_AdjustPESweetspotStretch": SweetspotStretchPENode,
|
||||
"ADE_AdjustPEFullStretch": FullStretchPENode,
|
||||
"ADE_AdjustPEManual": ManualAdjustPENode,
|
||||
"ADE_AdjustWeightAllAdd": WeightAdjustAllAddNode,
|
||||
"ADE_AdjustWeightAllMult": WeightAdjustAllMultNode,
|
||||
"ADE_AdjustWeightIndivAdd": WeightAdjustIndivAddNode,
|
||||
"ADE_AdjustWeightIndivMult": WeightAdjustIndivMultNode,
|
||||
"ADE_AdjustWeightIndivAttnAdd": WeightAdjustIndivAttnAddNode,
|
||||
"ADE_AdjustWeightIndivAttnMult": WeightAdjustIndivAttnMultNode,
|
||||
# Sample Settings
|
||||
"ADE_CustomCFGSimple": CustomCFGSimpleNode,
|
||||
"ADE_CustomCFG": CustomCFGNode,
|
||||
"ADE_CustomCFGKeyframeSimple": CustomCFGKeyframeSimpleNode,
|
||||
"ADE_CustomCFGKeyframe": CustomCFGKeyframeNode,
|
||||
"ADE_CustomCFGKeyframeInterpolation": CustomCFGKeyframeInterpolationNode,
|
||||
"ADE_CustomCFGKeyframeFromList": CustomCFGKeyframeFromListNode,
|
||||
"ADE_CFGExtrasPAGSimple": CFGExtrasPAGSimpleNode,
|
||||
"ADE_CFGExtrasPAG": CFGExtrasPAGNode,
|
||||
"ADE_CFGExtrasRescaleCFGSimple": CFGExtrasRescaleCFGSimpleNode,
|
||||
"ADE_CFGExtrasRescaleCFG": CFGExtrasRescaleCFGNode,
|
||||
"ADE_SigmaSchedule": SigmaScheduleNode,
|
||||
"ADE_RawSigmaSchedule": RawSigmaScheduleNode,
|
||||
"ADE_SigmaScheduleWeightedAverage": WeightedAverageSigmaScheduleNode,
|
||||
"ADE_SigmaScheduleWeightedAverageInterp": InterpolatedWeightedAverageSigmaScheduleNode,
|
||||
"ADE_SigmaScheduleSplitAndCombine": SplitAndCombineSigmaScheduleNode,
|
||||
"ADE_SigmaScheduleToSigmas": SigmaScheduleToSigmasNode,
|
||||
"ADE_NoisedImageInjection": NoisedImageInjectionNode,
|
||||
"ADE_NoisedImageInjectOptions": NoisedImageInjectOptionsNode,
|
||||
"ADE_AncestralOptions": AncestralOptionsNode,
|
||||
#"ADE_NoiseCalibration": NoiseCalibrationNode,
|
||||
# Scheduling
|
||||
PromptSchedulingNode.NodeID: PromptSchedulingNode,
|
||||
PromptSchedulingLatentsNode.NodeID: PromptSchedulingLatentsNode,
|
||||
ValueSchedulingNode.NodeID: ValueSchedulingNode,
|
||||
ValueSchedulingLatentsNode.NodeID: ValueSchedulingLatentsNode,
|
||||
ConditionExtractionNode.NodeID: ConditionExtractionNode,
|
||||
AddValuesReplaceNode.NodeID: AddValuesReplaceNode,
|
||||
FloatToFloatsNode.NodeID: FloatToFloatsNode,
|
||||
# Per-Block
|
||||
ADBlockComboNode.NodeID: ADBlockComboNode,
|
||||
ADBlockIndivNode.NodeID: ADBlockIndivNode,
|
||||
PerBlockHighLevelNode.NodeID: PerBlockHighLevelNode,
|
||||
PerBlock_SD15_MidLevelNode.NodeID: PerBlock_SD15_MidLevelNode,
|
||||
PerBlock_SD15_LowLevelNode.NodeID: PerBlock_SD15_LowLevelNode,
|
||||
PerBlock_SD15_FromFloatsNode.NodeID: PerBlock_SD15_FromFloatsNode,
|
||||
PerBlock_SDXL_MidLevelNode.NodeID: PerBlock_SDXL_MidLevelNode,
|
||||
PerBlock_SDXL_LowLevelNode.NodeID: PerBlock_SDXL_LowLevelNode,
|
||||
PerBlock_SDXL_FromFloatsNode.NodeID: PerBlock_SDXL_FromFloatsNode,
|
||||
# Extras Nodes
|
||||
"ADE_AnimateDiffUnload": AnimateDiffUnload,
|
||||
"ADE_EmptyLatentImageLarge": EmptyLatentImageLarge,
|
||||
"CheckpointLoaderSimpleWithNoiseSelect": CheckpointLoaderSimpleWithNoiseSelect,
|
||||
"ADE_PerturbedAttentionGuidanceMultival": PerturbedAttentionGuidanceMultival,
|
||||
"ADE_RescaleCFGMultival": RescaleCFGMultival,
|
||||
# Gen1 Nodes
|
||||
"ADE_AnimateDiffLoaderGen1": AnimateDiffLoaderGen1,
|
||||
# Gen2 Nodes
|
||||
"ADE_UseEvolvedSampling": UseEvolvedSamplingNode,
|
||||
"ADE_ApplyAnimateDiffModelSimple": ApplyAnimateDiffModelBasicNode,
|
||||
"ADE_ApplyAnimateDiffModel": ApplyAnimateDiffModelNode,
|
||||
"ADE_LoadAnimateDiffModel": LoadAnimateDiffModelNode,
|
||||
# AnimateLCM-I2V Nodes
|
||||
"ADE_ApplyAnimateLCMI2VModel": ApplyAnimateLCMI2VModel,
|
||||
"ADE_LoadAnimateLCMI2VModel": LoadAnimateLCMI2VModelNode,
|
||||
"ADE_UpscaleAndVAEEncode": UpscaleAndVaeEncode,
|
||||
"ADE_InjectI2VIntoAnimateDiffModel": LoadAnimateDiffAndInjectI2VNode,
|
||||
# MotionCtrl Nodes
|
||||
#LoadMotionCtrlCMCM.NodeID: LoadMotionCtrlCMCM,
|
||||
#LoadMotionCtrlOMCM.NodeID: LoadMotionCtrlOMCM,
|
||||
#ApplyAnimateDiffMotionCtrlModel.NodeID: ApplyAnimateDiffMotionCtrlModel,
|
||||
#LoadMotionCtrlCameraPosesFromFile.NodeID: LoadMotionCtrlCameraPosesFromFile,
|
||||
# CameraCtrl Nodes
|
||||
"ADE_ApplyAnimateDiffModelWithCameraCtrl": ApplyAnimateDiffWithCameraCtrl,
|
||||
"ADE_LoadAnimateDiffModelWithCameraCtrl": LoadAnimateDiffModelWithCameraCtrl,
|
||||
"ADE_CameraCtrlAnimateDiffKeyframe": CameraCtrlADKeyframeNode,
|
||||
"ADE_LoadCameraPoses": LoadCameraPosesFromFile,
|
||||
"ADE_LoadCameraPosesFromPath": LoadCameraPosesFromPath,
|
||||
"ADE_CameraPoseBasic": CameraCtrlPoseBasic,
|
||||
"ADE_CameraPoseCombo": CameraCtrlPoseCombo,
|
||||
"ADE_CameraPoseAdvanced": CameraCtrlPoseAdvanced,
|
||||
"ADE_CameraManualPoseAppend": CameraCtrlManualAppendPose,
|
||||
"ADE_ReplaceCameraParameters": CameraCtrlReplaceCameraParameters,
|
||||
"ADE_ReplaceOriginalPoseAspectRatio": CameraCtrlSetOriginalAspectRatio,
|
||||
# PIA Nodes
|
||||
"ADE_ApplyAnimateDiffModelWithPIA": ApplyAnimateDiffPIAModel,
|
||||
"ADE_InputPIA_Multival": InputPIA_MultivalNode,
|
||||
"ADE_InputPIA_PaperPresets": InputPIA_PaperPresetsNode,
|
||||
"ADE_PIA_AnimateDiffKeyframe": PIA_ADKeyframeNode,
|
||||
"ADE_InjectPIAIntoAnimateDiffModel": LoadAnimateDiffAndInjectPIANode,
|
||||
# FancyVideo
|
||||
#ApplyAnimateDiffFancyVideo.NodeID: ApplyAnimateDiffFancyVideo,
|
||||
# HelloMeme
|
||||
#TestHMRefNetInjection.NodeID: TestHMRefNetInjection,
|
||||
# Deprecated Nodes
|
||||
"ADE_AnimateDiffLoaderWithContext": LegacyAnimateDiffLoaderWithContextDEPR,
|
||||
"AnimateDiffLoaderV1": AnimateDiffLoaderDEPR,
|
||||
"ADE_AnimateDiffLoaderV1Advanced": AnimateDiffLoaderAdvancedDEPR,
|
||||
"ADE_AnimateDiffCombine": AnimateDiffCombineDEPR,
|
||||
"ADE_AnimateDiffModelSettings_Release": AnimateDiffModelSettingsDEPR,
|
||||
"ADE_AnimateDiffModelSettingsSimple": AnimateDiffModelSettingsSimpleDEPR,
|
||||
"ADE_AnimateDiffModelSettings": AnimateDiffModelSettingsAdvancedDEPR,
|
||||
"ADE_AnimateDiffModelSettingsAdvancedAttnStrengths": AnimateDiffModelSettingsAdvancedAttnStrengthsDEPR,
|
||||
}
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
# Unencapsulated
|
||||
"ADE_AnimateDiffLoRALoader": "Load AnimateDiff LoRA 🎭🅐🅓",
|
||||
"ADE_AnimateDiffSamplingSettings": "Sample Settings 🎭🅐🅓",
|
||||
"ADE_AnimateDiffKeyframe": "AnimateDiff Keyframe 🎭🅐🅓",
|
||||
# Multival Nodes
|
||||
"ADE_MultivalDynamic": "Multival 🎭🅐🅓",
|
||||
"ADE_MultivalDynamicFloatInput": "Multival [Float List] 🎭🅐🅓",
|
||||
"ADE_MultivalDynamicFloats": "Multival [Floats] 🎭🅐🅓",
|
||||
"ADE_MultivalScaledMask": "Multival Scaled Mask 🎭🅐🅓",
|
||||
"ADE_MultivalConvertToMask": "Multival to Mask 🎭🅐🅓",
|
||||
###############################################################################
|
||||
#------------------------------------------------------------------------------
|
||||
# Context Opts
|
||||
"ADE_StandardStaticContextOptions": "Context Options◆Standard Static 🎭🅐🅓",
|
||||
"ADE_StandardUniformContextOptions": "Context Options◆Standard Uniform 🎭🅐🅓",
|
||||
"ADE_LoopedUniformContextOptions": "Context Options◆Looped Uniform 🎭🅐🅓",
|
||||
"ADE_ViewsOnlyContextOptions": "Context Options◆Views Only [VRAM⇈] 🎭🅐🅓",
|
||||
"ADE_BatchedContextOptions": "Context Options◆Batched [Non-AD] 🎭🅐🅓",
|
||||
"ADE_AnimateDiffUniformContextOptions": "Context Options◆Looped Uniform 🎭🅐🅓", # Legacy/Deprecated
|
||||
"ADE_VisualizeContextOptionsK": "Visualize Context Options (K.) 🎭🅐🅓",
|
||||
"ADE_VisualizeContextOptionsKAdv": "Visualize Context Options (K.Adv.) 🎭🅐🅓",
|
||||
"ADE_VisualizeContextOptionsSCustom": "Visualize Context Options (S.Cus.) 🎭🅐🅓",
|
||||
# View Opts
|
||||
"ADE_StandardStaticViewOptions": "View Options◆Standard Static 🎭🅐🅓",
|
||||
"ADE_StandardUniformViewOptions": "View Options◆Standard Uniform 🎭🅐🅓",
|
||||
"ADE_LoopedUniformViewOptions": "View Options◆Looped Uniform 🎭🅐🅓",
|
||||
# Context Extras
|
||||
"ADE_ContextExtras_Set": "Set Context Extras 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef": "Context Extras◆ContextRef 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_ModeFirst": "ContextRef Mode◆First 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_ModeSliding": "ContextRef Mode◆Sliding 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_ModeIndexes": "ContextRef Mode◆Indexes 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_TuneAttn": "ContextRef Tune◆Attn 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_TuneAttnAdain": "ContextRef Tune◆Attn+Adain 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_Keyframe": "ContextRef Keyframe 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_KeyframeInterpolation": "ContextRef Keyframes Interp. 🎭🅐🅓",
|
||||
"ADE_ContextExtras_ContextRef_KeyframeFromList": "ContextRef Keyframes From List 🎭🅐🅓",
|
||||
"ADE_ContextExtras_NaiveReuse": "Context Extras◆NaiveReuse 🎭🅐🅓",
|
||||
"ADE_ContextExtras_NaiveReuse_Keyframe": "NaiveReuse Keyframe 🎭🅐🅓",
|
||||
"ADE_ContextExtras_NaiveReuse_KeyframeInterpolation": "NaiveReuse Keyframes Interp. 🎭🅐🅓",
|
||||
"ADE_ContextExtras_NaiveReuse_KeyframeFromList": "NaiveReuse Keyframes From List 🎭🅐🅓",
|
||||
#------------------------------------------------------------------------------
|
||||
###############################################################################
|
||||
# Iteration Opts
|
||||
"ADE_IterationOptsDefault": "Default Iteration Options 🎭🅐🅓",
|
||||
"ADE_IterationOptsFreeInit": "FreeInit Iteration Options 🎭🅐🅓",
|
||||
# Conditioning
|
||||
# Conditioning (DEPRECATED)
|
||||
"ADE_RegisterLoraHook": "Register LoRA Hook 🎭🅐🅓",
|
||||
"ADE_RegisterLoraHookModelOnly": "Register LoRA Hook (Model Only) 🎭🅐🅓",
|
||||
"ADE_RegisterModelAsLoraHook": "Register Model as LoRA Hook 🎭🅐🅓",
|
||||
"ADE_RegisterModelAsLoraHookModelOnly": "Register Model as LoRA Hook (MO) 🎭🅐🅓",
|
||||
"ADE_CombineLoraHooks": "Combine LoRA Hooks [2] 🎭🅐🅓",
|
||||
"ADE_CombineLoraHooksFour": "Combine LoRA Hooks [4] 🎭🅐🅓",
|
||||
"ADE_CombineLoraHooksEight": "Combine LoRA Hooks [8] 🎭🅐🅓",
|
||||
"ADE_SetLoraHookKeyframe": "Set LoRA Hook Keyframes 🎭🅐🅓",
|
||||
"ADE_AttachLoraHookToCLIP": "Set CLIP LoRA Hook 🎭🅐🅓",
|
||||
"ADE_LoraHookKeyframe": "LoRA Hook Keyframe 🎭🅐🅓",
|
||||
"ADE_LoraHookKeyframeInterpolation": "LoRA Hook Keyframes Interp. 🎭🅐🅓",
|
||||
"ADE_LoraHookKeyframeFromStrengthList": "LoRA Hook Keyframes From List 🎭🅐🅓",
|
||||
"ADE_AttachLoraHookToConditioning": "Set Model LoRA Hook 🎭🅐🅓",
|
||||
"ADE_PairedConditioningSetMask": "Set Props on Conds 🎭🅐🅓",
|
||||
"ADE_ConditioningSetMask": "Set Props on Cond 🎭🅐🅓",
|
||||
"ADE_PairedConditioningSetMaskAndCombine": "Set Props and Combine Conds 🎭🅐🅓",
|
||||
"ADE_ConditioningSetMaskAndCombine": "Set Props and Combine Cond 🎭🅐🅓",
|
||||
"ADE_PairedConditioningSetUnmaskedAndCombine": "Set Unmasked Conds 🎭🅐🅓",
|
||||
"ADE_ConditioningSetUnmaskedAndCombine": "Set Unmasked Cond 🎭🅐🅓",
|
||||
"ADE_PairedConditioningCombine": "Manual Combine Conds 🎭🅐🅓",
|
||||
"ADE_ConditioningCombine": "Manual Combine Cond 🎭🅐🅓",
|
||||
"ADE_TimestepsConditioning": "Timesteps Conditioning 🎭🅐🅓",
|
||||
# Noise Layer Nodes
|
||||
"ADE_NoiseLayerAdd": "Noise Layer [Add] 🎭🅐🅓",
|
||||
"ADE_NoiseLayerAddWeighted": "Noise Layer [Add Weighted] 🎭🅐🅓",
|
||||
"ADE_NoiseLayerNormalizedSum": "Noise Layer [Normalized Sum] 🎭🅐🅓",
|
||||
"ADE_NoiseLayerReplace": "Noise Layer [Replace] 🎭🅐🅓",
|
||||
# AnimateDiff Settings
|
||||
"ADE_AnimateDiffSettings": "AnimateDiff Settings 🎭🅐🅓",
|
||||
"ADE_AdjustPESweetspotStretch": "Adjust PE [Sweetspot] 🎭🅐🅓",
|
||||
"ADE_AdjustPEFullStretch": "Adjust PE [Full Stretch] 🎭🅐🅓",
|
||||
"ADE_AdjustPEManual": "Adjust PE [Manual] 🎭🅐🅓",
|
||||
"ADE_AdjustWeightAllAdd": "Adjust Weight [All◆Add] 🎭🅐🅓",
|
||||
"ADE_AdjustWeightAllMult": "Adjust Weight [All◆Mult] 🎭🅐🅓",
|
||||
"ADE_AdjustWeightIndivAdd": "Adjust Weight [Indiv◆Add] 🎭🅐🅓",
|
||||
"ADE_AdjustWeightIndivMult": "Adjust Weight [Indiv◆Mult] 🎭🅐🅓",
|
||||
"ADE_AdjustWeightIndivAttnAdd": "Adjust Weight [Indiv-Attn◆Add] 🎭🅐🅓",
|
||||
"ADE_AdjustWeightIndivAttnMult": "Adjust Weight [Indiv-Attn◆Mult] 🎭🅐🅓",
|
||||
# Sample Settings
|
||||
"ADE_CustomCFGSimple": "Custom CFG 🎭🅐🅓",
|
||||
"ADE_CustomCFG": "Custom CFG [Multival] 🎭🅐🅓",
|
||||
"ADE_CustomCFGKeyframeSimple": "Custom CFG Keyframe 🎭🅐🅓",
|
||||
"ADE_CustomCFGKeyframe": "Custom CFG Keyframe [Multival] 🎭🅐🅓",
|
||||
"ADE_CustomCFGKeyframeInterpolation": "Custom CFG Keyframes Interp. 🎭🅐🅓",
|
||||
"ADE_CustomCFGKeyframeFromList": "Custom CFG Keyframes From List 🎭🅐🅓",
|
||||
"ADE_CFGExtrasPAGSimple": "CFG Extras◆PAG 🎭🅐🅓",
|
||||
"ADE_CFGExtrasPAG": "CFG Extras◆PAG [Multival] 🎭🅐🅓",
|
||||
"ADE_CFGExtrasRescaleCFGSimple": "CFG Extras◆RescaleCFG 🎭🅐🅓",
|
||||
"ADE_CFGExtrasRescaleCFG": "CFG Extras◆RescaleCFG [Multival] 🎭🅐🅓",
|
||||
"ADE_SigmaSchedule": "Create Sigma Schedule 🎭🅐🅓",
|
||||
"ADE_RawSigmaSchedule": "Create Raw Sigma Schedule 🎭🅐🅓",
|
||||
"ADE_SigmaScheduleWeightedAverage": "Sigma Schedule Weighted Mean 🎭🅐🅓",
|
||||
"ADE_SigmaScheduleWeightedAverageInterp": "Sigma Schedule Interp. Mean 🎭🅐🅓",
|
||||
"ADE_SigmaScheduleSplitAndCombine": "Sigma Schedule Split Combine 🎭🅐🅓",
|
||||
"ADE_SigmaScheduleToSigmas": "Sigma Schedule To Sigmas 🎭🅐🅓",
|
||||
"ADE_NoisedImageInjection": "Image Injection 🎭🅐🅓",
|
||||
"ADE_NoisedImageInjectOptions": "Image Injection Options 🎭🅐🅓",
|
||||
"ADE_NoiseCalibration": "Noise Calibration 🎭🅐🅓",
|
||||
"ADE_AncestralOptions": "Ancestral Options 🎭🅐🅓",
|
||||
# Scheduling
|
||||
PromptSchedulingNode.NodeID: PromptSchedulingNode.NodeName,
|
||||
PromptSchedulingLatentsNode.NodeID: PromptSchedulingLatentsNode.NodeName,
|
||||
ValueSchedulingNode.NodeID: ValueSchedulingNode.NodeName,
|
||||
ValueSchedulingLatentsNode.NodeID: ValueSchedulingLatentsNode.NodeName,
|
||||
ConditionExtractionNode.NodeID: ConditionExtractionNode.NodeName,
|
||||
AddValuesReplaceNode.NodeID: AddValuesReplaceNode.NodeName,
|
||||
FloatToFloatsNode.NodeID:FloatToFloatsNode.NodeName,
|
||||
# Per-Block
|
||||
ADBlockComboNode.NodeID: ADBlockComboNode.NodeName,
|
||||
ADBlockIndivNode.NodeID: ADBlockIndivNode.NodeName,
|
||||
PerBlockHighLevelNode.NodeID: PerBlockHighLevelNode.NodeName,
|
||||
PerBlock_SD15_MidLevelNode.NodeID: PerBlock_SD15_MidLevelNode.NodeName,
|
||||
PerBlock_SD15_LowLevelNode.NodeID: PerBlock_SD15_LowLevelNode.NodeName,
|
||||
PerBlock_SD15_FromFloatsNode.NodeID: PerBlock_SD15_FromFloatsNode.NodeName,
|
||||
PerBlock_SDXL_MidLevelNode.NodeID: PerBlock_SDXL_MidLevelNode.NodeName,
|
||||
PerBlock_SDXL_LowLevelNode.NodeID: PerBlock_SDXL_LowLevelNode.NodeName,
|
||||
PerBlock_SDXL_FromFloatsNode.NodeID: PerBlock_SDXL_FromFloatsNode.NodeName,
|
||||
# Extras Nodes
|
||||
"ADE_AnimateDiffUnload": "AnimateDiff Unload 🎭🅐🅓",
|
||||
"ADE_EmptyLatentImageLarge": "Empty Latent Image (Big Batch) 🎭🅐🅓",
|
||||
"CheckpointLoaderSimpleWithNoiseSelect": "Load Checkpoint w/ Noise Select 🎭🅐🅓",
|
||||
"ADE_PerturbedAttentionGuidanceMultival": "PerturbedAttnGuide [Multival] 🎭🅐🅓",
|
||||
"ADE_RescaleCFGMultival": "RescaleCFG [Multival] 🎭🅐🅓",
|
||||
# Gen1 Nodes
|
||||
"ADE_AnimateDiffLoaderGen1": "AnimateDiff Loader 🎭🅐🅓①",
|
||||
# Gen2 Nodes
|
||||
"ADE_UseEvolvedSampling": "Use Evolved Sampling 🎭🅐🅓②",
|
||||
"ADE_ApplyAnimateDiffModelSimple": "Apply AnimateDiff Model 🎭🅐🅓②",
|
||||
"ADE_ApplyAnimateDiffModel": "Apply AnimateDiff Model (Adv.) 🎭🅐🅓②",
|
||||
"ADE_LoadAnimateDiffModel": "Load AnimateDiff Model 🎭🅐🅓②",
|
||||
# AnimateLCM-I2V Nodes
|
||||
"ADE_ApplyAnimateLCMI2VModel": "Apply AnimateLCM-I2V Model 🎭🅐🅓②",
|
||||
"ADE_LoadAnimateLCMI2VModel": "Load AnimateLCM-I2V Model 🎭🅐🅓②",
|
||||
"ADE_UpscaleAndVAEEncode": "Scale Ref Image and VAE Encode 🎭🅐🅓②",
|
||||
"ADE_InjectI2VIntoAnimateDiffModel": "🧪Inject I2V into AnimateDiff Model 🎭🅐🅓②",
|
||||
# MotionCtrl Nodes
|
||||
LoadMotionCtrlCMCM.NodeID: LoadMotionCtrlCMCM.NodeName,
|
||||
LoadMotionCtrlOMCM.NodeID: LoadMotionCtrlOMCM.NodeName,
|
||||
ApplyAnimateDiffMotionCtrlModel.NodeID: ApplyAnimateDiffMotionCtrlModel.NodeName,
|
||||
# CameraCtrl Nodes
|
||||
"ADE_ApplyAnimateDiffModelWithCameraCtrl": "Apply AnimateDiff+CameraCtrl Model 🎭🅐🅓②",
|
||||
"ADE_LoadAnimateDiffModelWithCameraCtrl": "Load AnimateDiff+CameraCtrl Model 🎭🅐🅓②",
|
||||
"ADE_CameraCtrlAnimateDiffKeyframe": "AnimateDiff+CameraCtrl Keyframe 🎭🅐🅓",
|
||||
"ADE_LoadCameraPoses": "Load CameraCtrl Poses (File) 🎭🅐🅓②",
|
||||
"ADE_LoadCameraPosesFromPath": "Load CameraCtrl Poses (Path) 🎭🅐🅓②",
|
||||
"ADE_CameraPoseBasic": "Create CameraCtrl Poses 🎭🅐🅓②",
|
||||
"ADE_CameraPoseCombo": "Create CameraCtrl Poses (Combo) 🎭🅐🅓②",
|
||||
"ADE_CameraPoseAdvanced": "Create CameraCtrl Poses (Adv.) 🎭🅐🅓②",
|
||||
"ADE_CameraManualPoseAppend": "Manual Append CameraCtrl Poses 🎭🅐🅓②",
|
||||
"ADE_ReplaceCameraParameters": "Replace Camera Parameters 🎭🅐🅓②",
|
||||
"ADE_ReplaceOriginalPoseAspectRatio": "Replace Orig. Pose Aspect Ratio 🎭🅐🅓②",
|
||||
# PIA Nodes
|
||||
"ADE_ApplyAnimateDiffModelWithPIA": "Apply AnimateDiff-PIA Model 🎭🅐🅓②",
|
||||
"ADE_InputPIA_Multival": "PIA Input [Multival] 🎭🅐🅓②",
|
||||
"ADE_InputPIA_PaperPresets": "PIA Input [Paper Presets] 🎭🅐🅓②",
|
||||
"ADE_PIA_AnimateDiffKeyframe": "AnimateDiff-PIA Keyframe 🎭🅐🅓",
|
||||
"ADE_InjectPIAIntoAnimateDiffModel": "🧪Inject PIA into AnimateDiff Model 🎭🅐🅓②",
|
||||
# FancyVideo
|
||||
ApplyAnimateDiffFancyVideo.NodeID: ApplyAnimateDiffFancyVideo.NodeName,
|
||||
# HelloMeme
|
||||
TestHMRefNetInjection.NodeID: TestHMRefNetInjection.NodeName,
|
||||
# Deprecated Nodes
|
||||
"ADE_AnimateDiffLoaderWithContext": "AnimateDiff Loader [Legacy] 🎭🅐🅓①",
|
||||
"AnimateDiffLoaderV1": "🚫AnimateDiff Loader [DEPRECATED] 🎭🅐🅓",
|
||||
"ADE_AnimateDiffLoaderV1Advanced": "🚫AnimateDiff Loader (Advanced) [DEPRECATED] 🎭🅐🅓",
|
||||
"ADE_AnimateDiffCombine": "🚫AnimateDiff Combine [DEPRECATED, Use Video Combine (VHS) Instead!] 🎭🅐🅓",
|
||||
"ADE_AnimateDiffModelSettings_Release": "🚫[DEPR] Motion Model Settings 🎭🅐🅓①",
|
||||
"ADE_AnimateDiffModelSettingsSimple": "🚫[DEPR] Motion Model Settings (Simple) 🎭🅐🅓①",
|
||||
"ADE_AnimateDiffModelSettings": "🚫[DEPR] Motion Model Settings (Advanced) 🎭🅐🅓①",
|
||||
"ADE_AnimateDiffModelSettingsAdvancedAttnStrengths": "🚫[DEPR] Motion Model Settings (Adv. Attn) 🎭🅐🅓①",
|
||||
}
|
||||
class AnimateDiffExtension(ComfyExtension):
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
AnimateDiffLoraLoader,
|
||||
SampleSettingsNode,
|
||||
ADKeyframeNode,
|
||||
MultivalDynamicNode,
|
||||
MultivalDynamicFloatInputNode,
|
||||
MultivalDynamicFloatsNode,
|
||||
MultivalScaledMaskNode,
|
||||
MultivalConvertToMaskNode,
|
||||
StandardStaticContextOptionsNode,
|
||||
StandardUniformContextOptionsNode,
|
||||
LoopedUniformContextOptionsNode,
|
||||
ViewAsContextOptionsNode,
|
||||
BatchedContextOptionsNode,
|
||||
LegacyLoopedUniformContextOptionsNode,
|
||||
VisualizeContextOptionsK,
|
||||
VisualizeContextOptionsKAdv,
|
||||
VisualizeContextOptionsSCustom,
|
||||
StandardStaticViewOptionsNode,
|
||||
StandardUniformViewOptionsNode,
|
||||
LoopedUniformViewOptionsNode,
|
||||
SetContextExtrasOnContextOptions,
|
||||
ContextExtras_ContextRef,
|
||||
ContextRef_ModeFirst,
|
||||
ContextRef_ModeSliding,
|
||||
ContextRef_ModeIndexes,
|
||||
ContextRef_TuneAttn,
|
||||
ContextRef_TuneAttnAdain,
|
||||
ContextRef_KeyframeMultivalNode,
|
||||
ContextRef_KeyframeInterpolationNode,
|
||||
ContextRef_KeyframeFromListNode,
|
||||
ContextExtras_NaiveReuse,
|
||||
NaiveReuse_KeyframeMultivalNode,
|
||||
NaiveReuse_KeyframeInterpolationNode,
|
||||
NaiveReuse_KeyframeFromListNode,
|
||||
IterationOptionsNode,
|
||||
FreeInitOptionsNode,
|
||||
MaskableLoraLoaderDEPR,
|
||||
MaskableLoraLoaderModelOnlyDEPR,
|
||||
MaskableSDModelLoaderDEPR,
|
||||
MaskableSDModelLoaderModelOnlyDEPR,
|
||||
CombineLoraHooksDEPR,
|
||||
CombineLoraHookFourOptionalDEPR,
|
||||
CombineLoraHookEightOptionalDEPR,
|
||||
SetLoraHookKeyframesDEPR,
|
||||
SetClipLoraHookDEPR,
|
||||
CreateLoraHookKeyframeDEPR,
|
||||
CreateLoraHookKeyframeInterpolationDEPR,
|
||||
CreateLoraHookKeyframeFromStrengthListDEPR,
|
||||
SetModelLoraHookDEPR,
|
||||
PairedConditioningSetMaskHookedDEPR,
|
||||
ConditioningSetMaskHookedDEPR,
|
||||
PairedConditioningSetMaskAndCombineHookedDEPR,
|
||||
ConditioningSetMaskAndCombineHookedDEPR,
|
||||
PairedConditioningSetUnmaskedAndCombineHookedDEPR,
|
||||
ConditioningSetUnmaskedAndCombineHookedDEPR,
|
||||
PairedConditioningCombineDEPR,
|
||||
ConditioningCombineDEPR,
|
||||
ConditioningTimestepsNodeDEPR,
|
||||
NoiseLayerAddNode,
|
||||
NoiseLayerAddWeightedNode,
|
||||
NoiseLayerNormalizedSumNode,
|
||||
NoiseLayerReplaceNode,
|
||||
AnimateDiffSettingsNode,
|
||||
SweetspotStretchPENode,
|
||||
FullStretchPENode,
|
||||
ManualAdjustPENode,
|
||||
WeightAdjustAllAddNode,
|
||||
WeightAdjustAllMultNode,
|
||||
WeightAdjustIndivAddNode,
|
||||
WeightAdjustIndivMultNode,
|
||||
WeightAdjustIndivAttnAddNode,
|
||||
WeightAdjustIndivAttnMultNode,
|
||||
CustomCFGSimpleNode,
|
||||
CustomCFGNode,
|
||||
CustomCFGKeyframeSimpleNode,
|
||||
CustomCFGKeyframeNode,
|
||||
CustomCFGKeyframeInterpolationNode,
|
||||
CustomCFGKeyframeFromListNode,
|
||||
CFGExtrasPAGSimpleNode,
|
||||
CFGExtrasPAGNode,
|
||||
CFGExtrasRescaleCFGSimpleNode,
|
||||
CFGExtrasRescaleCFGNode,
|
||||
SigmaScheduleNode,
|
||||
RawSigmaScheduleNode,
|
||||
WeightedAverageSigmaScheduleNode,
|
||||
InterpolatedWeightedAverageSigmaScheduleNode,
|
||||
SplitAndCombineSigmaScheduleNode,
|
||||
SigmaScheduleToSigmasNode,
|
||||
NoisedImageInjectionNode,
|
||||
NoisedImageInjectOptionsNode,
|
||||
AncestralOptionsNode,
|
||||
PromptSchedulingNode,
|
||||
PromptSchedulingLatentsNode,
|
||||
ValueSchedulingNode,
|
||||
ValueSchedulingLatentsNode,
|
||||
ConditionExtractionNode,
|
||||
AddValuesReplaceNode,
|
||||
FloatToFloatsNode,
|
||||
ADBlockComboNode,
|
||||
ADBlockIndivNode,
|
||||
PerBlockHighLevelNode,
|
||||
PerBlock_SD15_MidLevelNode,
|
||||
PerBlock_SD15_LowLevelNode,
|
||||
PerBlock_SD15_FromFloatsNode,
|
||||
PerBlock_SDXL_MidLevelNode,
|
||||
PerBlock_SDXL_LowLevelNode,
|
||||
PerBlock_SDXL_FromFloatsNode,
|
||||
AnimateDiffUnload,
|
||||
EmptyLatentImageLarge,
|
||||
CheckpointLoaderSimpleWithNoiseSelect,
|
||||
PerturbedAttentionGuidanceMultival,
|
||||
RescaleCFGMultival,
|
||||
AnimateDiffLoaderGen1,
|
||||
UseEvolvedSamplingNode,
|
||||
ApplyAnimateDiffModelBasicNode,
|
||||
ApplyAnimateDiffModelNode,
|
||||
LoadAnimateDiffModelNode,
|
||||
ApplyAnimateLCMI2VModel,
|
||||
LoadAnimateLCMI2VModelNode,
|
||||
UpscaleAndVaeEncode,
|
||||
LoadAnimateDiffAndInjectI2VNode,
|
||||
ApplyAnimateDiffWithCameraCtrl,
|
||||
LoadAnimateDiffModelWithCameraCtrl,
|
||||
CameraCtrlADKeyframeNode,
|
||||
LoadCameraPosesFromFile,
|
||||
LoadCameraPosesFromPath,
|
||||
CameraCtrlPoseBasic,
|
||||
CameraCtrlPoseCombo,
|
||||
CameraCtrlPoseAdvanced,
|
||||
CameraCtrlManualAppendPose,
|
||||
CameraCtrlReplaceCameraParameters,
|
||||
CameraCtrlSetOriginalAspectRatio,
|
||||
ApplyAnimateDiffPIAModel,
|
||||
InputPIA_MultivalNode,
|
||||
InputPIA_PaperPresetsNode,
|
||||
PIA_ADKeyframeNode,
|
||||
LoadAnimateDiffAndInjectPIANode,
|
||||
LegacyAnimateDiffLoaderWithContextDEPR,
|
||||
AnimateDiffLoaderDEPR,
|
||||
AnimateDiffLoaderAdvancedDEPR,
|
||||
AnimateDiffCombineDEPR,
|
||||
AnimateDiffModelSettingsDEPR,
|
||||
AnimateDiffModelSettingsSimpleDEPR,
|
||||
AnimateDiffModelSettingsAdvancedDEPR,
|
||||
AnimateDiffModelSettingsAdvancedAttnStrengthsDEPR,
|
||||
]
|
||||
|
||||
+216
-224
@@ -1,55 +1,55 @@
|
||||
from comfy_api.latest import io
|
||||
from .ad_settings import AdjustPE, AdjustWeight, AdjustGroup, AnimateDiffSettings
|
||||
from .utils_model import BIGMAX
|
||||
|
||||
|
||||
class AnimateDiffSettingsNode:
|
||||
class AnimateDiffSettingsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"optional": {
|
||||
"pe_adjust": ("PE_ADJUST",),
|
||||
"weight_adjust": ("WEIGHT_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AD_SETTINGS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings"
|
||||
FUNCTION = "get_ad_settings"
|
||||
|
||||
def get_ad_settings(self, pe_adjust: AdjustGroup=None, weight_adjust: AdjustGroup=None):
|
||||
return (AnimateDiffSettings(adjust_pe=pe_adjust, adjust_weight=weight_adjust),)
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AnimateDiffSettings',
|
||||
display_name='AnimateDiff Settings 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings',
|
||||
inputs=[
|
||||
io.Custom("PE_ADJUST").Input('pe_adjust', optional=True),
|
||||
io.Custom("WEIGHT_ADJUST").Input('weight_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("AD_SETTINGS").Output('AD_SETTINGS'),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class ManualAdjustPENode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"cap_initial_pe_length": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"interpolate_pe_to_length": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"initial_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"final_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
|
||||
},
|
||||
"optional": {
|
||||
"prev_pe_adjust": ("PE_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PE_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/pe adjust"
|
||||
FUNCTION = "get_pe_adjust"
|
||||
def execute(cls, pe_adjust: AdjustGroup=None, weight_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
return io.NodeOutput(AnimateDiffSettings(adjust_pe=pe_adjust, adjust_weight=weight_adjust))
|
||||
|
||||
def get_pe_adjust(self, cap_initial_pe_length: int, interpolate_pe_to_length: int,
|
||||
|
||||
class ManualAdjustPENode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustPEManual',
|
||||
display_name='Adjust PE [Manual] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/pe adjust',
|
||||
inputs=[
|
||||
io.Int.Input('cap_initial_pe_length', default=0, min=0, step=1),
|
||||
io.Int.Input('interpolate_pe_to_length', default=0, min=0, step=1),
|
||||
io.Int.Input('initial_pe_idx_offset', default=0, min=0, step=1),
|
||||
io.Int.Input('final_pe_idx_offset', default=0, min=0, step=1),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("PE_ADJUST").Input('prev_pe_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("PE_ADJUST").Output('PE_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@classmethod
|
||||
def execute(cls, cap_initial_pe_length: int, interpolate_pe_to_length: int,
|
||||
initial_pe_idx_offset: int, final_pe_idx_offset: int, print_adjustment: bool,
|
||||
prev_pe_adjust: AdjustGroup=None):
|
||||
prev_pe_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_pe_adjust is None:
|
||||
prev_pe_adjust = AdjustGroup()
|
||||
prev_pe_adjust = prev_pe_adjust.clone()
|
||||
@@ -57,91 +57,88 @@ class ManualAdjustPENode:
|
||||
initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset,
|
||||
print_adjustment=print_adjustment)
|
||||
prev_pe_adjust.add(adjust)
|
||||
return (prev_pe_adjust,)
|
||||
return io.NodeOutput(prev_pe_adjust)
|
||||
|
||||
|
||||
class SweetspotStretchPENode:
|
||||
class SweetspotStretchPENode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"sweetspot": ("INT", {"default": 16, "min": 0, "max": BIGMAX},),
|
||||
"new_sweetspot": ("INT", {"default": 16, "min": 0, "max": BIGMAX},),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_pe_adjust": ("PE_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PE_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/pe adjust"
|
||||
FUNCTION = "get_pe_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustPESweetspotStretch',
|
||||
display_name='Adjust PE [Sweetspot] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/pe adjust',
|
||||
inputs=[
|
||||
io.Int.Input('sweetspot', default=16, max=9007199254740991, min=0),
|
||||
io.Int.Input('new_sweetspot', default=16, max=9007199254740991, min=0),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("PE_ADJUST").Input('prev_pe_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("PE_ADJUST").Output('PE_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_pe_adjust(self, sweetspot: int, new_sweetspot: int, print_adjustment: bool, prev_pe_adjust: AdjustGroup=None):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, sweetspot: int, new_sweetspot: int, print_adjustment: bool, prev_pe_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_pe_adjust is None:
|
||||
prev_pe_adjust = AdjustGroup()
|
||||
prev_pe_adjust = prev_pe_adjust.clone()
|
||||
adjust = AdjustPE(cap_initial_pe_length=sweetspot, interpolate_pe_to_length=new_sweetspot,
|
||||
print_adjustment=print_adjustment)
|
||||
prev_pe_adjust.add(adjust)
|
||||
return (prev_pe_adjust,)
|
||||
return io.NodeOutput(prev_pe_adjust)
|
||||
|
||||
|
||||
class FullStretchPENode:
|
||||
class FullStretchPENode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"pe_stretch": ("INT", {"default": 0, "min": 0, "max": BIGMAX},),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_pe_adjust": ("PE_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PE_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/pe adjust"
|
||||
FUNCTION = "get_pe_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustPEFullStretch',
|
||||
display_name='Adjust PE [Full Stretch] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/pe adjust',
|
||||
inputs=[
|
||||
io.Int.Input('pe_stretch', default=0, max=9007199254740991, min=0),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("PE_ADJUST").Input('prev_pe_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("PE_ADJUST").Output('PE_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_pe_adjust(self, pe_stretch: int, print_adjustment: bool, prev_pe_adjust: AdjustGroup=None):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, pe_stretch: int, print_adjustment: bool, prev_pe_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_pe_adjust is None:
|
||||
prev_pe_adjust = AdjustGroup()
|
||||
prev_pe_adjust = prev_pe_adjust.clone()
|
||||
adjust = AdjustPE(motion_pe_stretch=pe_stretch,
|
||||
print_adjustment=print_adjustment)
|
||||
prev_pe_adjust.add(adjust)
|
||||
return (prev_pe_adjust,)
|
||||
return io.NodeOutput(prev_pe_adjust)
|
||||
|
||||
|
||||
class WeightAdjustAllAddNode:
|
||||
class WeightAdjustAllAddNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"all_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_weight_adjust": ("WEIGHT_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("WEIGHT_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/weight adjust"
|
||||
FUNCTION = "get_weight_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustWeightAllAdd',
|
||||
display_name='Adjust Weight [All◆Add] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/weight adjust',
|
||||
inputs=[
|
||||
io.Float.Input('all_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("WEIGHT_ADJUST").Input('prev_weight_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("WEIGHT_ADJUST").Output('WEIGHT_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_weight_adjust(self, all_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, all_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_weight_adjust is None:
|
||||
prev_weight_adjust = AdjustGroup()
|
||||
prev_weight_adjust = prev_weight_adjust.clone()
|
||||
@@ -150,30 +147,29 @@ class WeightAdjustAllAddNode:
|
||||
print_adjustment=print_adjustment
|
||||
)
|
||||
prev_weight_adjust.add(adjust)
|
||||
return (prev_weight_adjust,)
|
||||
return io.NodeOutput(prev_weight_adjust)
|
||||
|
||||
|
||||
class WeightAdjustAllMultNode:
|
||||
class WeightAdjustAllMultNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"all_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_weight_adjust": ("WEIGHT_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("WEIGHT_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/weight adjust"
|
||||
FUNCTION = "get_weight_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustWeightAllMult',
|
||||
display_name='Adjust Weight [All◆Mult] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/weight adjust',
|
||||
inputs=[
|
||||
io.Float.Input('all_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("WEIGHT_ADJUST").Input('prev_weight_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("WEIGHT_ADJUST").Output('WEIGHT_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_weight_adjust(self, all_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, all_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_weight_adjust is None:
|
||||
prev_weight_adjust = AdjustGroup()
|
||||
prev_weight_adjust = prev_weight_adjust.clone()
|
||||
@@ -182,32 +178,31 @@ class WeightAdjustAllMultNode:
|
||||
print_adjustment=print_adjustment
|
||||
)
|
||||
prev_weight_adjust.add(adjust)
|
||||
return (prev_weight_adjust,)
|
||||
return io.NodeOutput(prev_weight_adjust)
|
||||
|
||||
|
||||
class WeightAdjustIndivAddNode:
|
||||
class WeightAdjustIndivAddNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"pe_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"other_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_weight_adjust": ("WEIGHT_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("WEIGHT_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/weight adjust"
|
||||
FUNCTION = "get_weight_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustWeightIndivAdd',
|
||||
display_name='Adjust Weight [Indiv◆Add] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/weight adjust',
|
||||
inputs=[
|
||||
io.Float.Input('pe_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('attn_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('other_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("WEIGHT_ADJUST").Input('prev_weight_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("WEIGHT_ADJUST").Output('WEIGHT_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_weight_adjust(self, pe_ADD: float, attn_ADD: float, other_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, pe_ADD: float, attn_ADD: float, other_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_weight_adjust is None:
|
||||
prev_weight_adjust = AdjustGroup()
|
||||
prev_weight_adjust = prev_weight_adjust.clone()
|
||||
@@ -218,32 +213,31 @@ class WeightAdjustIndivAddNode:
|
||||
print_adjustment=print_adjustment
|
||||
)
|
||||
prev_weight_adjust.add(adjust)
|
||||
return (prev_weight_adjust,)
|
||||
return io.NodeOutput(prev_weight_adjust)
|
||||
|
||||
|
||||
class WeightAdjustIndivMultNode:
|
||||
class WeightAdjustIndivMultNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"pe_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"other_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_weight_adjust": ("WEIGHT_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("WEIGHT_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/weight adjust"
|
||||
FUNCTION = "get_weight_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustWeightIndivMult',
|
||||
display_name='Adjust Weight [Indiv◆Mult] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/weight adjust',
|
||||
inputs=[
|
||||
io.Float.Input('pe_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('attn_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('other_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("WEIGHT_ADJUST").Input('prev_weight_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("WEIGHT_ADJUST").Output('WEIGHT_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_weight_adjust(self, pe_MULT: float, attn_MULT: float, other_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, pe_MULT: float, attn_MULT: float, other_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_weight_adjust is None:
|
||||
prev_weight_adjust = AdjustGroup()
|
||||
prev_weight_adjust = prev_weight_adjust.clone()
|
||||
@@ -254,40 +248,39 @@ class WeightAdjustIndivMultNode:
|
||||
print_adjustment=print_adjustment
|
||||
)
|
||||
prev_weight_adjust.add(adjust)
|
||||
return (prev_weight_adjust,)
|
||||
return io.NodeOutput(prev_weight_adjust)
|
||||
|
||||
|
||||
class WeightAdjustIndivAttnAddNode:
|
||||
class WeightAdjustIndivAttnAddNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"pe_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_q_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_k_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_v_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_out_weight_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_out_bias_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"other_ADD": ("FLOAT", {"default": 0.0, "min": -2.0, "max": 2.0, "step": 0.000001}),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_weight_adjust": ("WEIGHT_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("WEIGHT_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/weight adjust"
|
||||
FUNCTION = "get_weight_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustWeightIndivAttnAdd',
|
||||
display_name='Adjust Weight [Indiv-Attn◆Add] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/weight adjust',
|
||||
inputs=[
|
||||
io.Float.Input('pe_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('attn_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('attn_q_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('attn_k_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('attn_v_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('attn_out_weight_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('attn_out_bias_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Float.Input('other_ADD', default=0.0, max=2.0, min=-2.0, step=1e-06),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("WEIGHT_ADJUST").Input('prev_weight_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("WEIGHT_ADJUST").Output('WEIGHT_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_weight_adjust(self, pe_ADD: float, attn_ADD: float,
|
||||
|
||||
@classmethod
|
||||
def execute(cls, pe_ADD: float, attn_ADD: float,
|
||||
attn_q_ADD: float, attn_k_ADD: float, attn_v_ADD: float,
|
||||
attn_out_weight_ADD: float, attn_out_bias_ADD: float,
|
||||
other_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None):
|
||||
other_ADD: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_weight_adjust is None:
|
||||
prev_weight_adjust = AdjustGroup()
|
||||
prev_weight_adjust = prev_weight_adjust.clone()
|
||||
@@ -303,40 +296,39 @@ class WeightAdjustIndivAttnAddNode:
|
||||
print_adjustment=print_adjustment
|
||||
)
|
||||
prev_weight_adjust.add(adjust)
|
||||
return (prev_weight_adjust,)
|
||||
return io.NodeOutput(prev_weight_adjust)
|
||||
|
||||
|
||||
class WeightAdjustIndivAttnMultNode:
|
||||
class WeightAdjustIndivAttnMultNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"pe_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_q_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_k_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_v_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_out_weight_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"attn_out_bias_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"other_MULT": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.000001}),
|
||||
"print_adjustment": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_weight_adjust": ("WEIGHT_ADJUST",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("WEIGHT_ADJUST",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/ad settings/weight adjust"
|
||||
FUNCTION = "get_weight_adjust"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AdjustWeightIndivAttnMult',
|
||||
display_name='Adjust Weight [Indiv-Attn◆Mult] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/ad settings/weight adjust',
|
||||
inputs=[
|
||||
io.Float.Input('pe_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('attn_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('attn_q_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('attn_k_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('attn_v_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('attn_out_weight_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('attn_out_bias_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('other_MULT', default=1.0, max=2.0, min=0.0, step=1e-06),
|
||||
io.Boolean.Input('print_adjustment', default=False),
|
||||
io.Custom("WEIGHT_ADJUST").Input('prev_weight_adjust', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("WEIGHT_ADJUST").Output('WEIGHT_ADJUST'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_weight_adjust(self, pe_MULT: float, attn_MULT: float,
|
||||
|
||||
@classmethod
|
||||
def execute(cls, pe_MULT: float, attn_MULT: float,
|
||||
attn_q_MULT: float, attn_k_MULT: float, attn_v_MULT: float,
|
||||
attn_out_weight_MULT: float, attn_out_bias_MULT: float,
|
||||
other_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None):
|
||||
other_MULT: float, print_adjustment: bool, prev_weight_adjust: AdjustGroup=None) -> io.NodeOutput:
|
||||
if prev_weight_adjust is None:
|
||||
prev_weight_adjust = AdjustGroup()
|
||||
prev_weight_adjust = prev_weight_adjust.clone()
|
||||
@@ -352,4 +344,4 @@ class WeightAdjustIndivAttnMultNode:
|
||||
print_adjustment=print_adjustment
|
||||
)
|
||||
prev_weight_adjust.add(adjust)
|
||||
return (prev_weight_adjust,)
|
||||
return io.NodeOutput(prev_weight_adjust)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from comfy_api.latest import io
|
||||
from typing import Union
|
||||
import torch
|
||||
|
||||
@@ -16,43 +17,42 @@ from .motion_module_ad import AnimateDiffFormat
|
||||
from .nodes_gen2 import ApplyAnimateDiffModelNode
|
||||
|
||||
|
||||
class ApplyAnimateLCMI2VModel:
|
||||
class ApplyAnimateLCMI2VModel(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"motion_model": ("MOTION_MODEL_ADE",),
|
||||
"ref_latent": ("LATENT",),
|
||||
"ref_drift": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 10.0, "step": 0.001}),
|
||||
"apply_ref_when_disabled": ("BOOLEAN", {"default": False}),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
},
|
||||
"optional": {
|
||||
"motion_lora": ("MOTION_LORA",),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"ad_keyframes": ("AD_KEYFRAMES",),
|
||||
"prev_m_models": ("M_MODELS",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ApplyAnimateLCMI2VModel',
|
||||
display_name='Apply AnimateLCM-I2V Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V',
|
||||
inputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Input('motion_model'),
|
||||
io.Latent.Input('ref_latent'),
|
||||
io.Float.Input('ref_drift', default=0.0, max=10.0, min=0.0, step=0.001),
|
||||
io.Boolean.Input('apply_ref_when_disabled', default=False),
|
||||
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Custom("MOTION_LORA").Input('motion_lora', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("AD_KEYFRAMES").Input('ad_keyframes', optional=True),
|
||||
io.Custom("M_MODELS").Input('prev_m_models', optional=True),
|
||||
io.Custom("PER_BLOCK").Input('per_block', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("M_MODELS").Output('M_MODELS'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("M_MODELS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V"
|
||||
FUNCTION = "apply_motion_model"
|
||||
|
||||
def apply_motion_model(self, motion_model: MotionModelPatcher, ref_latent: dict, ref_drift: float=0.0, apply_ref_when_disabled=False, start_percent: float=0.0, end_percent: float=1.0,
|
||||
@classmethod
|
||||
def execute(cls, motion_model: MotionModelPatcher, ref_latent: dict, ref_drift: float=0.0, apply_ref_when_disabled=False, start_percent: float=0.0, end_percent: float=1.0,
|
||||
motion_lora: MotionLoraList=None, ad_keyframes: ADKeyframeGroup=None,
|
||||
scale_multival=None, effect_multival=None, per_block=None,
|
||||
prev_m_models: MotionModelGroup=None,):
|
||||
new_m_models = ApplyAnimateDiffModelNode.apply_motion_model(self, motion_model, start_percent=start_percent, end_percent=end_percent,
|
||||
new_m_models = ApplyAnimateDiffModelNode.execute( motion_model, start_percent=start_percent, end_percent=end_percent,
|
||||
motion_lora=motion_lora, ad_keyframes=ad_keyframes,
|
||||
scale_multival=scale_multival, effect_multival=effect_multival, per_block=per_block,
|
||||
prev_m_models=prev_m_models)
|
||||
prev_m_models=prev_m_models).args
|
||||
# most recent added model will always be first in list;
|
||||
curr_model = new_m_models[0].models[0]
|
||||
# confirm that model contains img_encoder
|
||||
@@ -62,27 +62,29 @@ class ApplyAnimateLCMI2VModel:
|
||||
attachment.orig_img_latents = ref_latent["samples"]
|
||||
attachment.orig_ref_drift = ref_drift
|
||||
attachment.orig_apply_ref_when_disabled = apply_ref_when_disabled
|
||||
return new_m_models
|
||||
return io.NodeOutput(*new_m_models)
|
||||
|
||||
|
||||
class LoadAnimateLCMI2VModelNode:
|
||||
class LoadAnimateLCMI2VModelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (get_available_motion_models(),),
|
||||
},
|
||||
"optional": {
|
||||
"ad_settings": ("AD_SETTINGS",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_LoadAnimateLCMI2VModel',
|
||||
display_name='Load AnimateLCM-I2V Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V',
|
||||
inputs=[
|
||||
io.Combo.Input('model_name', options=get_available_motion_models()),
|
||||
io.Custom("AD_SETTINGS").Input('ad_settings', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Output('MOTION_MODEL'),
|
||||
io.Custom("MOTION_MODEL_ADE").Output('encoder_only'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MOTION_MODEL_ADE", "MOTION_MODEL_ADE")
|
||||
RETURN_NAMES = ("MOTION_MODEL", "encoder_only")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V"
|
||||
FUNCTION = "load_motion_model"
|
||||
|
||||
def load_motion_model(self, model_name: str, ad_settings: AnimateDiffSettings=None):
|
||||
@classmethod
|
||||
def execute(cls, model_name: str, ad_settings: AnimateDiffSettings=None):
|
||||
# load motion module and motion settings, if included
|
||||
motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings)
|
||||
# make sure model is an AnimateLCM-I2V model
|
||||
@@ -92,61 +94,66 @@ class LoadAnimateLCMI2VModelNode:
|
||||
raise Exception(f"Motion model '{motion_model.model.mm_info.mm_name}' is not an AnimateLCM-I2V model; selected model IS AnimateLCM, but does NOT contain an img_encoder.")
|
||||
# create encoder-only motion model
|
||||
encoder_only_motion_model = create_fresh_encoder_only_model(motion_model=motion_model)
|
||||
return (motion_model, encoder_only_motion_model)
|
||||
return io.NodeOutput(motion_model, encoder_only_motion_model)
|
||||
|
||||
|
||||
class LoadAnimateDiffAndInjectI2VNode:
|
||||
class LoadAnimateDiffAndInjectI2VNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (get_available_motion_models(),),
|
||||
"motion_model": ("MOTION_MODEL_ADE",),
|
||||
},
|
||||
"optional": {
|
||||
"ad_settings": ("AD_SETTINGS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Experimental. Don't expect to work.", "warn_type": "experimental", "color": "#CFC"}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_InjectI2VIntoAnimateDiffModel',
|
||||
display_name='🧪Inject I2V into AnimateDiff Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V/🧪experimental',
|
||||
inputs=[
|
||||
io.Combo.Input('model_name', options=get_available_motion_models()),
|
||||
io.Custom("MOTION_MODEL_ADE").Input('motion_model'),
|
||||
io.Custom("AD_SETTINGS").Input('ad_settings', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Output('MOTION_MODEL'),
|
||||
],
|
||||
is_experimental=True,
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MOTION_MODEL_ADE",)
|
||||
RETURN_NAMES = ("MOTION_MODEL",)
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V/🧪experimental"
|
||||
FUNCTION = "load_motion_model"
|
||||
|
||||
def load_motion_model(self, model_name: str, motion_model: MotionModelPatcher, ad_settings: AnimateDiffSettings=None):
|
||||
@classmethod
|
||||
def execute(cls, model_name: str, motion_model: MotionModelPatcher, ad_settings: AnimateDiffSettings=None):
|
||||
# make sure model w/ encoder actually has encoder
|
||||
if motion_model.model.img_encoder is None:
|
||||
raise Exception("Passed-in motion model was expected to have an img_encoder, but did not.")
|
||||
# load motion module and motion settings, if included
|
||||
loaded_motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings)
|
||||
inject_img_encoder_into_model(motion_model=loaded_motion_model, w_encoder=motion_model)
|
||||
return (loaded_motion_model,)
|
||||
return io.NodeOutput(loaded_motion_model,)
|
||||
|
||||
|
||||
class UpscaleAndVaeEncode:
|
||||
class UpscaleAndVaeEncode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"vae": ("VAE",),
|
||||
"latent_size": ("LATENT",),
|
||||
"scale_method": (ScaleMethods._LIST_IMAGE,),
|
||||
"crop": (CropMethods._LIST, {"default": CropMethods.CENTER},),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_UpscaleAndVAEEncode',
|
||||
display_name='Scale Ref Image and VAE Encode 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V',
|
||||
inputs=[
|
||||
io.Image.Input('image'),
|
||||
io.Vae.Input('vae'),
|
||||
io.Latent.Input('latent_size'),
|
||||
io.Combo.Input('scale_method', options=['nearest-exact', 'bilinear', 'area', 'bicubic', 'lanczos']),
|
||||
io.Combo.Input('crop', options=['disabled', 'center'], default='center'),
|
||||
],
|
||||
outputs=[
|
||||
io.Latent.Output('LATENT'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
FUNCTION = "preprocess_images"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/AnimateLCM-I2V"
|
||||
|
||||
def preprocess_images(self, image: torch.Tensor, vae: VAE, latent_size: torch.Tensor, scale_method: str, crop: str):
|
||||
@classmethod
|
||||
def execute(cls, image: torch.Tensor, vae: VAE, latent_size: torch.Tensor, scale_method: str, crop: str):
|
||||
b, c, h, w = latent_size["samples"].size()
|
||||
image = image.movedim(-1,1)
|
||||
image = comfy.utils.common_upscale(samples=image, width=w*8, height=h*8, upscale_method=scale_method, crop=crop)
|
||||
image = image.movedim(1,-1)
|
||||
# now that images are the expected size, VAEEncode them
|
||||
return ({"samples": vae_encode_raw_batched(vae, image)},)
|
||||
return io.NodeOutput({"samples": vae_encode_raw_batched(vae, image)},)
|
||||
|
||||
+236
-213
@@ -1,3 +1,4 @@
|
||||
from comfy_api.latest import io
|
||||
from typing import Union
|
||||
import os
|
||||
import torch
|
||||
@@ -218,38 +219,40 @@ def poses_to_ndarray(poses: list[list[float]]) -> np.ndarray:
|
||||
return RT
|
||||
|
||||
|
||||
class ApplyAnimateDiffWithCameraCtrl:
|
||||
class ApplyAnimateDiffWithCameraCtrl(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"motion_model": ("MOTION_MODEL_ADE",),
|
||||
"cameractrl_poses": ("CAMERACTRL_POSES",),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
},
|
||||
"optional": {
|
||||
"motion_lora": ("MOTION_LORA",),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"cameractrl_multival": ("MULTIVAL",),
|
||||
"ad_keyframes": ("AD_KEYFRAMES",),
|
||||
"prev_m_models": ("M_MODELS",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ApplyAnimateDiffModelWithCameraCtrl',
|
||||
display_name='Apply AnimateDiff+CameraCtrl Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl',
|
||||
inputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Input('motion_model'),
|
||||
io.Custom("CAMERACTRL_POSES").Input('cameractrl_poses'),
|
||||
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Custom("MOTION_LORA").Input('motion_lora', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('cameractrl_multival', optional=True),
|
||||
io.Custom("AD_KEYFRAMES").Input('ad_keyframes', optional=True),
|
||||
io.Custom("M_MODELS").Input('prev_m_models', optional=True),
|
||||
io.Custom("PER_BLOCK").Input('per_block', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("M_MODELS").Output('M_MODELS'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("M_MODELS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl"
|
||||
FUNCTION = "apply_motion_model"
|
||||
|
||||
def apply_motion_model(self, motion_model: MotionModelPatcher, cameractrl_poses: list[list[float]], start_percent: float=0.0, end_percent: float=1.0,
|
||||
@classmethod
|
||||
def execute(cls, motion_model: MotionModelPatcher, cameractrl_poses: list[list[float]], start_percent: float=0.0, end_percent: float=1.0,
|
||||
motion_lora: MotionLoraList=None, ad_keyframes: ADKeyframeGroup=None,
|
||||
scale_multival=None, effect_multival=None, cameractrl_multival=None, per_block=None,
|
||||
prev_m_models: MotionModelGroup=None,):
|
||||
new_m_models = ApplyAnimateDiffModelNode.apply_motion_model(self, motion_model, start_percent=start_percent, end_percent=end_percent,
|
||||
new_m_models = ApplyAnimateDiffModelNode.execute( motion_model, start_percent=start_percent, end_percent=end_percent,
|
||||
motion_lora=motion_lora, ad_keyframes=ad_keyframes, per_block=per_block,
|
||||
scale_multival=scale_multival, effect_multival=effect_multival, prev_m_models=prev_m_models)
|
||||
scale_multival=scale_multival, effect_multival=effect_multival, prev_m_models=prev_m_models).args
|
||||
# most recent added model will always be first in list;
|
||||
curr_model = new_m_models[0].models[0]
|
||||
# confirm that model contains camera_encoder
|
||||
@@ -259,87 +262,88 @@ class ApplyAnimateDiffWithCameraCtrl:
|
||||
attachment = get_mm_attachment(curr_model)
|
||||
attachment.orig_camera_entries = camera_entries
|
||||
attachment.cameractrl_multival = cameractrl_multival
|
||||
return new_m_models
|
||||
return io.NodeOutput(*new_m_models)
|
||||
|
||||
|
||||
class LoadAnimateDiffModelWithCameraCtrl:
|
||||
class LoadAnimateDiffModelWithCameraCtrl(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (get_available_motion_models(),),
|
||||
"camera_ctrl": (get_available_motion_models(),),
|
||||
},
|
||||
"optional": {
|
||||
"ad_settings": ("AD_SETTINGS",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_LoadAnimateDiffModelWithCameraCtrl',
|
||||
display_name='Load AnimateDiff+CameraCtrl Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl',
|
||||
inputs=[
|
||||
io.Combo.Input('model_name', options=get_available_motion_models()),
|
||||
io.Combo.Input('camera_ctrl', options=get_available_motion_models()),
|
||||
io.Custom("AD_SETTINGS").Input('ad_settings', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Output('MOTION_MODEL'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MOTION_MODEL_ADE",)
|
||||
RETURN_NAMES = ("MOTION_MODEL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl"
|
||||
FUNCTION = "load_camera_ctrl"
|
||||
|
||||
def load_camera_ctrl(self, model_name: str, camera_ctrl: str, ad_settings: AnimateDiffSettings=None):
|
||||
@classmethod
|
||||
def execute(cls, model_name: str, camera_ctrl: str, ad_settings: AnimateDiffSettings=None):
|
||||
loaded_motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings)
|
||||
inject_camera_encoder_into_model(motion_model=loaded_motion_model, camera_ctrl_name=camera_ctrl)
|
||||
return (loaded_motion_model,)
|
||||
return io.NodeOutput(loaded_motion_model,)
|
||||
|
||||
|
||||
class CameraCtrlADKeyframeNode:
|
||||
class CameraCtrlADKeyframeNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
||||
},
|
||||
"optional": {
|
||||
"prev_ad_keyframes": ("AD_KEYFRAMES", ),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"cameractrl_multival": ("MULTIVAL",),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}, ),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_CameraCtrlAnimateDiffKeyframe',
|
||||
display_name='AnimateDiff+CameraCtrl Keyframe 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl',
|
||||
inputs=[
|
||||
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Custom("AD_KEYFRAMES").Input('prev_ad_keyframes', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('cameractrl_multival', optional=True),
|
||||
io.Boolean.Input('inherit_missing', optional=True, default=True),
|
||||
io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("AD_KEYFRAMES").Output('AD_KEYFRAMES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("AD_KEYFRAMES", )
|
||||
FUNCTION = "load_keyframe"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl"
|
||||
|
||||
def load_keyframe(self,
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
start_percent: float, prev_ad_keyframes=None,
|
||||
scale_multival: Union[float, torch.Tensor]=None, effect_multival: Union[float, torch.Tensor]=None,
|
||||
cameractrl_multival: Union[float, torch.Tensor]=None,
|
||||
inherit_missing: bool=True, guarantee_steps: int=1):
|
||||
return ADKeyframeNode.load_keyframe(self,
|
||||
return io.NodeOutput(*ADKeyframeNode.execute(
|
||||
start_percent=start_percent, prev_ad_keyframes=prev_ad_keyframes,
|
||||
scale_multival=scale_multival, effect_multival=effect_multival, cameractrl_multival=cameractrl_multival,
|
||||
inherit_missing=inherit_missing, guarantee_steps=guarantee_steps
|
||||
)
|
||||
).args)
|
||||
|
||||
|
||||
class LoadCameraPosesFromFile:
|
||||
class LoadCameraPosesFromFile(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
input_dir = folder_paths.get_input_directory()
|
||||
files = [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
||||
files = [f for f in files if f.endswith(".txt")]
|
||||
return {
|
||||
"required": {
|
||||
"pose_filename": (sorted(files),),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_LoadCameraPoses',
|
||||
display_name='Load CameraCtrl Poses (File) 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.Combo.Input('pose_filename', options=sorted(f for f in os.listdir(folder_paths.get_input_directory()) if os.path.isfile(os.path.join(folder_paths.get_input_directory(), f)) and f.endswith(".txt"))),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
FUNCTION = "load_camera_poses"
|
||||
|
||||
def load_camera_poses(self, pose_filename: str):
|
||||
@classmethod
|
||||
def execute(cls, pose_filename: str):
|
||||
file_path = folder_paths.get_annotated_filepath(pose_filename)
|
||||
with open(file_path, 'r') as f:
|
||||
poses = f.readlines()
|
||||
@@ -348,36 +352,40 @@ class LoadCameraPosesFromFile:
|
||||
poses = [pose.strip().split(' ') for pose in poses[1:]]
|
||||
poses = [[float(x) for x in pose] for pose in poses]
|
||||
poses = set_original_pose_dims(poses, pose_width=CAM.DEFAULT_POSE_WIDTH, pose_height=CAM.DEFAULT_POSE_HEIGHT)
|
||||
return (poses,)
|
||||
return io.NodeOutput(poses,)
|
||||
|
||||
|
||||
class LoadCameraPosesFromPath:
|
||||
class LoadCameraPosesFromPath(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"optional": {
|
||||
"file_path": ("STRING", {"default": "X://path/to/pose_file.txt"}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_LoadCameraPosesFromPath',
|
||||
display_name='Load CameraCtrl Poses (Path) 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.String.Input('file_path', optional=True, default='X://path/to/pose_file.txt'),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(s, file_path, **kwargs):
|
||||
def fingerprint_inputs(cls, file_path, **kwargs):
|
||||
if Path(file_path).is_file():
|
||||
return calculate_file_hash(strip_path(file_path))
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def VALIDATE_INPUTS(s, file_path, **kwargs):
|
||||
def validate_inputs(cls, file_path, **kwargs):
|
||||
# This function never gets ran for some reason, I don't care enough to figure out why right now.
|
||||
if not Path(strip_path(file_path)).is_file():
|
||||
return f"Pose file not found: {file_path}"
|
||||
return True
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
FUNCTION = "load_camera_poses"
|
||||
|
||||
def load_camera_poses(self, file_path: str):
|
||||
@classmethod
|
||||
def execute(cls, file_path: str):
|
||||
file_path = strip_path(file_path)
|
||||
if not Path(file_path).is_file():
|
||||
raise Exception(f"Pose file not found: {file_path}")
|
||||
@@ -388,63 +396,64 @@ class LoadCameraPosesFromPath:
|
||||
poses = [pose.strip().split(' ') for pose in poses[1:]]
|
||||
poses = [[float(x) for x in pose] for pose in poses]
|
||||
poses = set_original_pose_dims(poses, pose_width=CAM.DEFAULT_POSE_WIDTH, pose_height=CAM.DEFAULT_POSE_HEIGHT)
|
||||
return (poses,)
|
||||
return io.NodeOutput(poses,)
|
||||
|
||||
|
||||
class CameraCtrlPoseBasic:
|
||||
class CameraCtrlPoseBasic(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"motion_type": (CAM._LIST,),
|
||||
"speed": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}),
|
||||
"frame_length": ("INT", {"default": 16}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_poses": ("CAMERACTRL_POSES",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_CameraPoseBasic',
|
||||
display_name='Create CameraCtrl Poses 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.Combo.Input('motion_type', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('speed', default=1.0, max=100.0, min=-100.0, step=0.01),
|
||||
io.Int.Input('frame_length', default=16),
|
||||
io.Custom("CAMERACTRL_POSES").Input('prev_poses', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
FUNCTION = "camera_pose_basic"
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
|
||||
def camera_pose_basic(self, motion_type: str, speed: float, frame_length: int, prev_poses: list[list[float]]=None):
|
||||
@classmethod
|
||||
def execute(cls, motion_type: str, speed: float, frame_length: int, prev_poses: list[list[float]]=None):
|
||||
motion = CAM.get(motion_type)
|
||||
RT = get_camera_motion(motion.rotate, motion.translate, speed, frame_length)
|
||||
new_motion = ndarray_to_poses(RT=RT)
|
||||
if prev_poses is not None:
|
||||
new_motion = combine_poses(prev_poses, new_motion)
|
||||
return (new_motion,)
|
||||
return io.NodeOutput(new_motion,)
|
||||
|
||||
|
||||
class CameraCtrlPoseCombo:
|
||||
class CameraCtrlPoseCombo(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"motion_type1": (CAM._LIST,),
|
||||
"motion_type2": (CAM._LIST,),
|
||||
"motion_type3": (CAM._LIST,),
|
||||
"motion_type4": (CAM._LIST,),
|
||||
"motion_type5": (CAM._LIST,),
|
||||
"motion_type6": (CAM._LIST,),
|
||||
"speed": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}),
|
||||
"frame_length": ("INT", {"default": 16}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_poses": ("CAMERACTRL_POSES",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_CameraPoseCombo',
|
||||
display_name='Create CameraCtrl Poses (Combo) 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.Combo.Input('motion_type1', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Combo.Input('motion_type2', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Combo.Input('motion_type3', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Combo.Input('motion_type4', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Combo.Input('motion_type5', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Combo.Input('motion_type6', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('speed', default=1.0, max=100.0, min=-100.0, step=0.01),
|
||||
io.Int.Input('frame_length', default=16),
|
||||
io.Custom("CAMERACTRL_POSES").Input('prev_poses', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
FUNCTION = "camera_pose_combo"
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
|
||||
def camera_pose_combo(self,
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
motion_type1: str, motion_type2: str, motion_type3: str,
|
||||
motion_type4: str, motion_type5: str, motion_type6: str,
|
||||
speed: float, frame_length: int,
|
||||
@@ -458,88 +467,98 @@ class CameraCtrlPoseCombo:
|
||||
new_motion = ndarray_to_poses(RT=RT)
|
||||
if prev_poses is not None:
|
||||
new_motion = combine_poses(prev_poses, new_motion)
|
||||
return (new_motion,)
|
||||
return io.NodeOutput(new_motion,)
|
||||
|
||||
|
||||
class CameraCtrlPoseAdvanced:
|
||||
class CameraCtrlPoseAdvanced(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"motion_type1": (CAM._LIST,),
|
||||
"strength1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"motion_type2": (CAM._LIST,),
|
||||
"strength2": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"motion_type3": (CAM._LIST,),
|
||||
"strength3": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"motion_type4": (CAM._LIST,),
|
||||
"strength4": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"motion_type5": (CAM._LIST,),
|
||||
"strength5": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"motion_type6": (CAM._LIST,),
|
||||
"strength6": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"speed": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}),
|
||||
"frame_length": ("INT", {"default": 16}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_poses": ("CAMERACTRL_POSES",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_CameraPoseAdvanced',
|
||||
display_name='Create CameraCtrl Poses (Adv.) 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.Combo.Input('motion_type1', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('strength1', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||
io.Combo.Input('motion_type2', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('strength2', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||
io.Combo.Input('motion_type3', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('strength3', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||
io.Combo.Input('motion_type4', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('strength4', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||
io.Combo.Input('motion_type5', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('strength5', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||
io.Combo.Input('motion_type6', options=['Static', 'Pan Up', 'Pan Down', 'Pan Left', 'Pan Right', 'Zoom In', 'Zoom Out', 'Roll Clockwise', 'Roll Anticlockwise', 'Tilt Down', 'Tilt Up', 'Tilt Left', 'Tilt Right']),
|
||||
io.Float.Input('strength6', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||
io.Float.Input('speed', default=1.0, max=100.0, min=-100.0, step=0.01),
|
||||
io.Int.Input('frame_length', default=16),
|
||||
io.Custom("CAMERACTRL_POSES").Input('prev_poses', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
FUNCTION = "camera_pose_combo"
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
|
||||
def camera_pose_combo(self,
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
motion_type1: str, motion_type2: str, motion_type3: str,
|
||||
motion_type4: str, motion_type5: str, motion_type6: str,
|
||||
speed: float, frame_length: int,
|
||||
prev_poses: list[list[float]]=None,
|
||||
strength1=1.0, strength2=1.0, strength3=1.0, strength4=1.0, strength5=1.0, strength6=1.0):
|
||||
return CameraCtrlPoseCombo.camera_pose_combo(self,
|
||||
return io.NodeOutput(*CameraCtrlPoseCombo.execute(
|
||||
motion_type1=motion_type1, motion_type2=motion_type2, motion_type3=motion_type3,
|
||||
motion_type4=motion_type4, motion_type5=motion_type5, motion_type6=motion_type6,
|
||||
speed=speed, frame_length=frame_length, prev_poses=prev_poses,
|
||||
strength1=strength1, strength2=strength2, strength3=strength3,
|
||||
strength4=strength4, strength5=strength5, strength6=strength6)
|
||||
strength4=strength4, strength5=strength5, strength6=strength6).args)
|
||||
|
||||
|
||||
class CameraCtrlManualAppendPose:
|
||||
class CameraCtrlManualAppendPose(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"poses_first": ("CAMERACTRL_POSES",),
|
||||
"poses_last": ("CAMERACTRL_POSES",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_CameraManualPoseAppend',
|
||||
display_name='Manual Append CameraCtrl Poses 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Input('poses_first'),
|
||||
io.Custom("CAMERACTRL_POSES").Input('poses_last'),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
FUNCTION = "camera_manual_append"
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
|
||||
def camera_manual_append(self, poses_first: list[list[float]], poses_last: list[list[float]]):
|
||||
return (combine_poses(poses0=poses_first, poses1=poses_last),)
|
||||
|
||||
|
||||
class CameraCtrlReplaceCameraParameters:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"poses":("CAMERACTRL_POSES",),
|
||||
"fx": ("FLOAT", {"default": CAM.DEFAULT_FX, "min": 0, "max": 1, "step": 0.000000001}),
|
||||
"fy": ("FLOAT", {"default": CAM.DEFAULT_FY, "min": 0, "max": 1, "step": 0.000000001}),
|
||||
"cx": ("FLOAT", {"default": CAM.DEFAULT_CX, "min": 0, "max": 1, "step": 0.01}),
|
||||
"cy": ("FLOAT", {"default": CAM.DEFAULT_CY, "min": 0, "max": 1, "step": 0.01}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
FUNCTION = "set_camera_parameters"
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
def execute(cls, poses_first: list[list[float]], poses_last: list[list[float]]):
|
||||
return io.NodeOutput(combine_poses(poses0=poses_first, poses1=poses_last),)
|
||||
|
||||
def set_camera_parameters(self, poses: list[list[float]], fx: float, fy: float, cx: float, cy: float):
|
||||
|
||||
class CameraCtrlReplaceCameraParameters(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ReplaceCameraParameters',
|
||||
display_name='Replace Camera Parameters 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Input('poses'),
|
||||
io.Float.Input('fx', default=0.474812461, max=1, min=0, step=1e-09),
|
||||
io.Float.Input('fy', default=0.844111024, max=1, min=0, step=1e-09),
|
||||
io.Float.Input('cx', default=0.5, max=1, min=0, step=0.01),
|
||||
io.Float.Input('cy', default=0.5, max=1, min=0, step=0.01),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@classmethod
|
||||
def execute(cls, poses: list[list[float]], fx: float, fy: float, cx: float, cy: float):
|
||||
new_poses = copy.deepcopy(poses)
|
||||
for pose in new_poses:
|
||||
# fx,fy,cx,fy are in indexes 1-4 of the 19-long pose list
|
||||
@@ -547,23 +566,27 @@ class CameraCtrlReplaceCameraParameters:
|
||||
pose[2] = fy
|
||||
pose[3] = cx
|
||||
pose[4] = cy
|
||||
return (new_poses,)
|
||||
return io.NodeOutput(new_poses,)
|
||||
|
||||
|
||||
class CameraCtrlSetOriginalAspectRatio:
|
||||
class CameraCtrlSetOriginalAspectRatio(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"poses":("CAMERACTRL_POSES",),
|
||||
"orig_pose_width": ("INT", {"default": 1280, "min": 1, "max": BIGMAX}),
|
||||
"orig_pose_height": ("INT", {"default": 720, "min": 1, "max": BIGMAX}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ReplaceOriginalPoseAspectRatio',
|
||||
display_name='Replace Orig. Pose Aspect Ratio 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses',
|
||||
inputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Input('poses'),
|
||||
io.Int.Input('orig_pose_width', default=1280, max=9007199254740991, min=1),
|
||||
io.Int.Input('orig_pose_height', default=720, max=9007199254740991, min=1),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("CAMERACTRL_POSES").Output('CAMERACTRL_POSES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("CAMERACTRL_POSES",)
|
||||
FUNCTION = "set_aspect_ratio"
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/CameraCtrl/poses"
|
||||
|
||||
def set_aspect_ratio(self, poses: list[list[float]], orig_pose_width: int, orig_pose_height: int):
|
||||
return (set_original_pose_dims(poses, pose_width=orig_pose_width, pose_height=orig_pose_height),)
|
||||
@classmethod
|
||||
def execute(cls, poses: list[list[float]], orig_pose_width: int, orig_pose_height: int):
|
||||
return io.NodeOutput(set_original_pose_dims(poses, pose_width=orig_pose_width, pose_height=orig_pose_height),)
|
||||
|
||||
+187
-637
@@ -1,9 +1,9 @@
|
||||
from comfy_api.latest import io
|
||||
import uuid
|
||||
import folder_paths
|
||||
from typing import Union
|
||||
from torch import Tensor
|
||||
from collections.abc import Iterable
|
||||
|
||||
from comfy.model_patcher import ModelPatcher
|
||||
from comfy.sd import CLIP
|
||||
import comfy.sd
|
||||
@@ -11,64 +11,28 @@ from comfy.hooks import HookGroup, HookKeyframeGroup, HookKeyframe
|
||||
import comfy_extras.nodes_hooks
|
||||
import comfy.hooks
|
||||
import comfy.utils
|
||||
|
||||
from .utils_model import BIGMAX, InterpolationMethod
|
||||
from .logger import logger
|
||||
|
||||
|
||||
###################################################################
|
||||
# EVERYTHING BELOW HERE IS DEPRECATED;
|
||||
# Can be replaced with vanilla ComfyUI nodes
|
||||
#------------------------------------------------------------------
|
||||
#------------------------------------------------------------------
|
||||
#------------------------------------------------------------------
|
||||
#------------------------------------------------------------------
|
||||
#------------------------------------------------------------------
|
||||
class COND_CONST:
|
||||
COND_AREA_DEFAULT = "default"
|
||||
COND_AREA_MASK_BOUNDS = "mask bounds"
|
||||
COND_AREA_DEFAULT = 'default'
|
||||
COND_AREA_MASK_BOUNDS = 'mask bounds'
|
||||
_LIST_COND_AREA = [COND_AREA_DEFAULT, COND_AREA_MASK_BOUNDS]
|
||||
|
||||
class CreateLoraHookKeyframeInterpolationDEPR(io.ComfyNode):
|
||||
|
||||
class CreateLoraHookKeyframeInterpolationDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"strength_start": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
||||
"strength_end": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
||||
"interpolation": (InterpolationMethod._LIST, ),
|
||||
"intervals": ("INT", {"default": 5, "min": 2, "max": 100, "step": 1}),
|
||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_hook_kf": ("HOOK_KEYFRAMES",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
DEPRECATED = True
|
||||
RETURN_TYPES = ("HOOK_KEYFRAMES",)
|
||||
RETURN_NAMES = ("HOOK_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks"
|
||||
FUNCTION = "create_hook_keyframes"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_LoraHookKeyframeInterpolation', display_name='LoRA Hook Keyframes Interp. 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks', inputs=[io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001), io.Float.Input('strength_start', default=1.0, max=10.0, min=0.0, step=0.001), io.Float.Input('strength_end', default=1.0, max=10.0, min=0.0, step=0.001), io.Combo.Input('interpolation', options=['linear', 'ease_in', 'ease_out', 'ease_in_out']), io.Int.Input('intervals', default=5, max=100, min=2, step=1), io.Boolean.Input('print_keyframes', default=False), io.Custom('HOOK_KEYFRAMES').Input('prev_hook_kf', optional=True)], outputs=[io.Custom('HOOK_KEYFRAMES').Output('HOOK_KF')], is_deprecated=True)
|
||||
|
||||
def create_hook_keyframes(self,
|
||||
start_percent: float, end_percent: float,
|
||||
strength_start: float, strength_end: float, interpolation: str, intervals: int,
|
||||
prev_hook_kf: HookKeyframeGroup=None, print_keyframes=False):
|
||||
@classmethod
|
||||
def execute(cls, start_percent: float, end_percent: float, strength_start: float, strength_end: float, interpolation: str, intervals: int, prev_hook_kf: HookKeyframeGroup=None, print_keyframes=False):
|
||||
if prev_hook_kf:
|
||||
prev_hook_kf = prev_hook_kf.clone()
|
||||
else:
|
||||
prev_hook_kf = HookKeyframeGroup()
|
||||
percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=intervals, method=InterpolationMethod.LINEAR)
|
||||
strengths = InterpolationMethod.get_weights(num_from=strength_start, num_to=strength_end, length=intervals, method=interpolation)
|
||||
|
||||
is_first = True
|
||||
for percent, strength in zip(percents, strengths):
|
||||
guarantee_steps = 0
|
||||
@@ -77,385 +41,143 @@ class CreateLoraHookKeyframeInterpolationDEPR:
|
||||
is_first = False
|
||||
prev_hook_kf.add(HookKeyframe(strength=strength, start_percent=percent, guarantee_steps=guarantee_steps))
|
||||
if print_keyframes:
|
||||
logger.info(f"HookKeyframe - start_percent:{percent} = {strength}")
|
||||
return (prev_hook_kf,)
|
||||
logger.info(f'HookKeyframe - start_percent:{percent} = {strength}')
|
||||
return io.NodeOutput(prev_hook_kf)
|
||||
|
||||
class PairedConditioningSetMaskHookedDEPR(io.ComfyNode):
|
||||
|
||||
###############################################
|
||||
### Mask, Combine, and Hook Conditioning
|
||||
###############################################
|
||||
class PairedConditioningSetMaskHookedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"positive_ADD": ("CONDITIONING", ),
|
||||
"negative_ADD": ("CONDITIONING", ),
|
||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"set_cond_area": (COND_CONST._LIST_COND_AREA,),
|
||||
},
|
||||
"optional": {
|
||||
"opt_mask": ("MASK", ),
|
||||
"opt_lora_hook": ("HOOKS",),
|
||||
"opt_timesteps": ("TIMESTEPS_RANGE",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_PairedConditioningSetMask', display_name='Set Props on Conds 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning', inputs=[io.Conditioning.Input('positive_ADD'), io.Conditioning.Input('negative_ADD'), io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01), io.Combo.Input('set_cond_area', options=['default', 'mask bounds']), io.Mask.Input('opt_mask', optional=True), io.Custom('HOOKS').Input('opt_lora_hook', optional=True), io.Custom('TIMESTEPS_RANGE').Input('opt_timesteps', optional=True)], outputs=[io.Conditioning.Output('positive'), io.Conditioning.Output('negative')], is_deprecated=True)
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING")
|
||||
RETURN_NAMES = ("positive", "negative")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning"
|
||||
FUNCTION = "append_and_hook"
|
||||
DEPRECATED = True
|
||||
|
||||
def append_and_hook(self, positive_ADD, negative_ADD,
|
||||
strength: float, set_cond_area: str,
|
||||
opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
final_positive, final_negative = comfy.hooks.set_conds_props(conds=[positive_ADD, negative_ADD],
|
||||
strength=strength, set_cond_area=set_cond_area,
|
||||
mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return (final_positive, final_negative)
|
||||
|
||||
|
||||
class ConditioningSetMaskHookedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"cond_ADD": ("CONDITIONING",),
|
||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"set_cond_area": (COND_CONST._LIST_COND_AREA,),
|
||||
},
|
||||
"optional": {
|
||||
"opt_mask": ("MASK", ),
|
||||
"opt_lora_hook": ("HOOKS",),
|
||||
"opt_timesteps": ("TIMESTEPS_RANGE",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def execute(cls, positive_ADD, negative_ADD, strength: float, set_cond_area: str, opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
final_positive, final_negative = comfy.hooks.set_conds_props(conds=[positive_ADD, negative_ADD], strength=strength, set_cond_area=set_cond_area, mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return io.NodeOutput(final_positive, final_negative)
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops"
|
||||
FUNCTION = "append_and_hook"
|
||||
DEPRECATED = True
|
||||
class ConditioningSetMaskHookedDEPR(io.ComfyNode):
|
||||
|
||||
def append_and_hook(self, cond_ADD,
|
||||
strength: float, set_cond_area: str,
|
||||
opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
(final_conditioning,) = comfy.hooks.set_conds_props(conds=[cond_ADD],
|
||||
strength=strength, set_cond_area=set_cond_area,
|
||||
mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return (final_conditioning,)
|
||||
|
||||
|
||||
class PairedConditioningSetMaskAndCombineHookedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"positive": ("CONDITIONING",),
|
||||
"negative": ("CONDITIONING",),
|
||||
"positive_ADD": ("CONDITIONING",),
|
||||
"negative_ADD": ("CONDITIONING",),
|
||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"set_cond_area": (COND_CONST._LIST_COND_AREA,),
|
||||
},
|
||||
"optional": {
|
||||
"opt_mask": ("MASK", ),
|
||||
"opt_lora_hook": ("HOOKS",),
|
||||
"opt_timesteps": ("TIMESTEPS_RANGE",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING")
|
||||
RETURN_NAMES = ("positive", "negative")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning"
|
||||
FUNCTION = "append_and_combine"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ConditioningSetMask', display_name='Set Props on Cond 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/single cond ops', inputs=[io.Conditioning.Input('cond_ADD'), io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01), io.Combo.Input('set_cond_area', options=['default', 'mask bounds']), io.Mask.Input('opt_mask', optional=True), io.Custom('HOOKS').Input('opt_lora_hook', optional=True), io.Custom('TIMESTEPS_RANGE').Input('opt_timesteps', optional=True)], outputs=[io.Conditioning.Output('CONDITIONING')], is_deprecated=True)
|
||||
|
||||
def append_and_combine(self, positive, negative, positive_ADD, negative_ADD,
|
||||
strength: float, set_cond_area: str,
|
||||
opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
final_positive, final_negative = comfy.hooks.set_conds_props_and_combine(conds=[positive, negative], new_conds=[positive_ADD, negative_ADD],
|
||||
strength=strength, set_cond_area=set_cond_area,
|
||||
mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return (final_positive, final_negative,)
|
||||
|
||||
|
||||
class ConditioningSetMaskAndCombineHookedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"cond": ("CONDITIONING",),
|
||||
"cond_ADD": ("CONDITIONING",),
|
||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"set_cond_area": (COND_CONST._LIST_COND_AREA,),
|
||||
},
|
||||
"optional": {
|
||||
"opt_mask": ("MASK", ),
|
||||
"opt_lora_hook": ("HOOKS",),
|
||||
"opt_timesteps": ("TIMESTEPS_RANGE",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops"
|
||||
FUNCTION = "append_and_combine"
|
||||
DEPRECATED = True
|
||||
def execute(cls, cond_ADD, strength: float, set_cond_area: str, opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
final_conditioning, = comfy.hooks.set_conds_props(conds=[cond_ADD], strength=strength, set_cond_area=set_cond_area, mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return io.NodeOutput(final_conditioning)
|
||||
|
||||
def append_and_combine(self, cond, cond_ADD,
|
||||
strength: float, set_cond_area: str,
|
||||
opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
(final_conditioning,) = comfy.hooks.set_conds_props_and_combine(conds=[cond], new_conds=[cond_ADD],
|
||||
strength=strength, set_cond_area=set_cond_area,
|
||||
mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return (final_conditioning,)
|
||||
class PairedConditioningSetMaskAndCombineHookedDEPR(io.ComfyNode):
|
||||
|
||||
|
||||
class PairedConditioningSetUnmaskedAndCombineHookedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"positive": ("CONDITIONING",),
|
||||
"negative": ("CONDITIONING",),
|
||||
"positive_DEFAULT": ("CONDITIONING",),
|
||||
"negative_DEFAULT": ("CONDITIONING",),
|
||||
},
|
||||
"optional": {
|
||||
"opt_lora_hook": ("HOOKS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING")
|
||||
RETURN_NAMES = ("positive", "negative")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning"
|
||||
FUNCTION = "append_and_combine"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_PairedConditioningSetMaskAndCombine', display_name='Set Props and Combine Conds 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning', inputs=[io.Conditioning.Input('positive'), io.Conditioning.Input('negative'), io.Conditioning.Input('positive_ADD'), io.Conditioning.Input('negative_ADD'), io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01), io.Combo.Input('set_cond_area', options=['default', 'mask bounds']), io.Mask.Input('opt_mask', optional=True), io.Custom('HOOKS').Input('opt_lora_hook', optional=True), io.Custom('TIMESTEPS_RANGE').Input('opt_timesteps', optional=True)], outputs=[io.Conditioning.Output('positive'), io.Conditioning.Output('negative')], is_deprecated=True)
|
||||
|
||||
def append_and_combine(self, positive, negative, positive_DEFAULT, negative_DEFAULT,
|
||||
opt_lora_hook: HookGroup=None):
|
||||
final_positive, final_negative = comfy.hooks.set_default_conds_and_combine(conds=[positive, negative], new_conds=[positive_DEFAULT, negative_DEFAULT],
|
||||
hooks=opt_lora_hook)
|
||||
return (final_positive, final_negative,)
|
||||
|
||||
|
||||
class ConditioningSetUnmaskedAndCombineHookedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"cond": ("CONDITIONING",),
|
||||
"cond_DEFAULT": ("CONDITIONING",),
|
||||
},
|
||||
"optional": {
|
||||
"opt_lora_hook": ("HOOKS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops"
|
||||
FUNCTION = "append_and_combine"
|
||||
DEPRECATED = True
|
||||
def execute(cls, positive, negative, positive_ADD, negative_ADD, strength: float, set_cond_area: str, opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
final_positive, final_negative = comfy.hooks.set_conds_props_and_combine(conds=[positive, negative], new_conds=[positive_ADD, negative_ADD], strength=strength, set_cond_area=set_cond_area, mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return io.NodeOutput(final_positive, final_negative)
|
||||
|
||||
def append_and_combine(self, cond, cond_DEFAULT,
|
||||
opt_lora_hook: HookGroup=None):
|
||||
(final_conditioning,) = comfy.hooks.set_default_conds_and_combine(conds=[cond], new_conds=[cond_DEFAULT],
|
||||
hooks=opt_lora_hook)
|
||||
return (final_conditioning,)
|
||||
|
||||
class ConditioningSetMaskAndCombineHookedDEPR(io.ComfyNode):
|
||||
|
||||
class PairedConditioningCombineDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"positive_A": ("CONDITIONING",),
|
||||
"negative_A": ("CONDITIONING",),
|
||||
"positive_B": ("CONDITIONING",),
|
||||
"negative_B": ("CONDITIONING",),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ConditioningSetMaskAndCombine', display_name='Set Props and Combine Cond 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/single cond ops', inputs=[io.Conditioning.Input('cond'), io.Conditioning.Input('cond_ADD'), io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01), io.Combo.Input('set_cond_area', options=['default', 'mask bounds']), io.Mask.Input('opt_mask', optional=True), io.Custom('HOOKS').Input('opt_lora_hook', optional=True), io.Custom('TIMESTEPS_RANGE').Input('opt_timesteps', optional=True)], outputs=[io.Conditioning.Output('CONDITIONING')], is_deprecated=True)
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING")
|
||||
RETURN_NAMES = ("positive", "negative")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning"
|
||||
FUNCTION = "combine"
|
||||
DEPRECATED = True
|
||||
|
||||
def combine(self, positive_A, negative_A, positive_B, negative_B):
|
||||
final_positive, final_negative = comfy.hooks.set_conds_props_and_combine(conds=[positive_A, negative_A], new_conds=[positive_B, negative_B],)
|
||||
return (final_positive, final_negative,)
|
||||
|
||||
|
||||
class ConditioningCombineDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"cond_A": ("CONDITIONING",),
|
||||
"cond_B": ("CONDITIONING",),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops"
|
||||
FUNCTION = "combine"
|
||||
DEPRECATED = True
|
||||
def execute(cls, cond, cond_ADD, strength: float, set_cond_area: str, opt_mask: Tensor=None, opt_lora_hook: HookGroup=None, opt_timesteps: tuple=None):
|
||||
final_conditioning, = comfy.hooks.set_conds_props_and_combine(conds=[cond], new_conds=[cond_ADD], strength=strength, set_cond_area=set_cond_area, mask=opt_mask, hooks=opt_lora_hook, timesteps_range=opt_timesteps)
|
||||
return io.NodeOutput(final_conditioning)
|
||||
|
||||
def combine(self, cond_A, cond_B):
|
||||
(final_conditioning,) = comfy.hooks.set_conds_props_and_combine(conds=[cond_A], new_conds=[cond_B],)
|
||||
return (final_conditioning,)
|
||||
###############################################
|
||||
###############################################
|
||||
###############################################
|
||||
class PairedConditioningSetUnmaskedAndCombineHookedDEPR(io.ComfyNode):
|
||||
|
||||
|
||||
|
||||
###############################################
|
||||
### Scheduling
|
||||
###############################################
|
||||
class ConditioningTimestepsNodeDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001})
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("TIMESTEPS_RANGE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning"
|
||||
FUNCTION = "create_schedule"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_PairedConditioningSetUnmaskedAndCombine', display_name='Set Unmasked Conds 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning', inputs=[io.Conditioning.Input('positive'), io.Conditioning.Input('negative'), io.Conditioning.Input('positive_DEFAULT'), io.Conditioning.Input('negative_DEFAULT'), io.Custom('HOOKS').Input('opt_lora_hook', optional=True)], outputs=[io.Conditioning.Output('positive'), io.Conditioning.Output('negative')], is_deprecated=True)
|
||||
|
||||
def create_schedule(self, start_percent: float, end_percent: float):
|
||||
return ((start_percent, end_percent),)
|
||||
|
||||
|
||||
class SetLoraHookKeyframesDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"lora_hook": ("HOOKS",),
|
||||
"hook_kf": ("HOOK_KEYFRAMES",),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("HOOKS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning"
|
||||
FUNCTION = "set_hook_keyframes"
|
||||
DEPRECATED = True
|
||||
def execute(cls, positive, negative, positive_DEFAULT, negative_DEFAULT, opt_lora_hook: HookGroup=None):
|
||||
final_positive, final_negative = comfy.hooks.set_default_conds_and_combine(conds=[positive, negative], new_conds=[positive_DEFAULT, negative_DEFAULT], hooks=opt_lora_hook)
|
||||
return io.NodeOutput(final_positive, final_negative)
|
||||
|
||||
def set_hook_keyframes(self, lora_hook: HookGroup, hook_kf: HookKeyframeGroup):
|
||||
class ConditioningSetUnmaskedAndCombineHookedDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ConditioningSetUnmaskedAndCombine', display_name='Set Unmasked Cond 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/single cond ops', inputs=[io.Conditioning.Input('cond'), io.Conditioning.Input('cond_DEFAULT'), io.Custom('HOOKS').Input('opt_lora_hook', optional=True)], outputs=[io.Conditioning.Output('CONDITIONING')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, cond, cond_DEFAULT, opt_lora_hook: HookGroup=None):
|
||||
final_conditioning, = comfy.hooks.set_default_conds_and_combine(conds=[cond], new_conds=[cond_DEFAULT], hooks=opt_lora_hook)
|
||||
return io.NodeOutput(final_conditioning)
|
||||
|
||||
class PairedConditioningCombineDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_PairedConditioningCombine', display_name='Manual Combine Conds 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning', inputs=[io.Conditioning.Input('positive_A'), io.Conditioning.Input('negative_A'), io.Conditioning.Input('positive_B'), io.Conditioning.Input('negative_B')], outputs=[io.Conditioning.Output('positive'), io.Conditioning.Output('negative')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, positive_A, negative_A, positive_B, negative_B):
|
||||
final_positive, final_negative = comfy.hooks.set_conds_props_and_combine(conds=[positive_A, negative_A], new_conds=[positive_B, negative_B])
|
||||
return io.NodeOutput(final_positive, final_negative)
|
||||
|
||||
class ConditioningCombineDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ConditioningCombine', display_name='Manual Combine Cond 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/single cond ops', inputs=[io.Conditioning.Input('cond_A'), io.Conditioning.Input('cond_B')], outputs=[io.Conditioning.Output('CONDITIONING')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, cond_A, cond_B):
|
||||
final_conditioning, = comfy.hooks.set_conds_props_and_combine(conds=[cond_A], new_conds=[cond_B])
|
||||
return io.NodeOutput(final_conditioning)
|
||||
|
||||
class ConditioningTimestepsNodeDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_TimestepsConditioning', display_name='Timesteps Conditioning 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning', inputs=[io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001)], outputs=[io.Custom('TIMESTEPS_RANGE').Output('TIMESTEPS_RANGE')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, start_percent: float, end_percent: float):
|
||||
return io.NodeOutput((start_percent, end_percent))
|
||||
|
||||
class SetLoraHookKeyframesDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_SetLoraHookKeyframe', display_name='Set LoRA Hook Keyframes 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning', inputs=[io.Custom('HOOKS').Input('lora_hook'), io.Custom('HOOK_KEYFRAMES').Input('hook_kf')], outputs=[io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, lora_hook: HookGroup, hook_kf: HookKeyframeGroup):
|
||||
new_lora_hook = lora_hook.clone()
|
||||
new_lora_hook.set_keyframes_on_hooks(hook_kf=hook_kf)
|
||||
return (new_lora_hook,)
|
||||
return io.NodeOutput(new_lora_hook)
|
||||
|
||||
class CreateLoraHookKeyframeDEPR(io.ComfyNode):
|
||||
|
||||
class CreateLoraHookKeyframeDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_hook_kf": ("HOOK_KEYFRAMES",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("HOOK_KEYFRAMES",)
|
||||
RETURN_NAMES = ("HOOK_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks"
|
||||
FUNCTION = "create_hook_keyframe"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_LoraHookKeyframe', display_name='LoRA Hook Keyframe 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks', inputs=[io.Float.Input('strength_model', default=1.0, max=20.0, min=-20.0, step=0.01), io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', default=1, max=9007199254740991, min=0), io.Custom('HOOK_KEYFRAMES').Input('prev_hook_kf', optional=True)], outputs=[io.Custom('HOOK_KEYFRAMES').Output('HOOK_KF')], is_deprecated=True)
|
||||
|
||||
def create_hook_keyframe(self, strength_model: float, start_percent: float, guarantee_steps: float,
|
||||
prev_hook_kf: HookKeyframeGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, strength_model: float, start_percent: float, guarantee_steps: float, prev_hook_kf: HookKeyframeGroup=None):
|
||||
if prev_hook_kf:
|
||||
prev_hook_kf = prev_hook_kf.clone()
|
||||
else:
|
||||
prev_hook_kf = HookKeyframeGroup()
|
||||
keyframe = HookKeyframe(strength=strength_model, start_percent=start_percent, guarantee_steps=guarantee_steps)
|
||||
prev_hook_kf.add(keyframe)
|
||||
return (prev_hook_kf,)
|
||||
|
||||
return io.NodeOutput(prev_hook_kf)
|
||||
|
||||
class CreateLoraHookKeyframeFromStrengthListDEPR(io.ComfyNode):
|
||||
|
||||
class CreateLoraHookKeyframeFromStrengthListDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"strengths_float": ("FLOAT", {"default": -1, "min": -1, "step": 0.001, "forceInput": True}),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_hook_kf": ("HOOK_KEYFRAMES",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("HOOK_KEYFRAMES",)
|
||||
RETURN_NAMES = ("HOOK_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks"
|
||||
FUNCTION = "create_hook_keyframes"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_LoraHookKeyframeFromStrengthList', display_name='LoRA Hook Keyframes From List 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/schedule lora hooks', inputs=[io.Float.Input('strengths_float', default=-1, force_input=True, min=-1, step=0.001), io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001), io.Boolean.Input('print_keyframes', default=False), io.Custom('HOOK_KEYFRAMES').Input('prev_hook_kf', optional=True)], outputs=[io.Custom('HOOK_KEYFRAMES').Output('HOOK_KF')], is_deprecated=True)
|
||||
|
||||
def create_hook_keyframes(self, strengths_float: Union[float, list[float]],
|
||||
start_percent: float, end_percent: float,
|
||||
prev_hook_kf: HookKeyframeGroup=None, print_keyframes=False):
|
||||
@classmethod
|
||||
def execute(cls, strengths_float: Union[float, list[float]], start_percent: float, end_percent: float, prev_hook_kf: HookKeyframeGroup=None, print_keyframes=False):
|
||||
if prev_hook_kf:
|
||||
prev_hook_kf = prev_hook_kf.clone()
|
||||
else:
|
||||
@@ -465,9 +187,8 @@ class CreateLoraHookKeyframeFromStrengthListDEPR:
|
||||
elif isinstance(strengths_float, Iterable):
|
||||
pass
|
||||
else:
|
||||
raise Exception(f"strengths_float must be either an interable input or a float, but was {type(strengths_float).__repr__}.")
|
||||
raise Exception(f'strengths_float must be either an interable input or a float, but was {type(strengths_float).__repr__}.')
|
||||
percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=len(strengths_float), method=InterpolationMethod.LINEAR)
|
||||
|
||||
is_first = True
|
||||
for percent, strength in zip(percents, strengths_float):
|
||||
guarantee_steps = 0
|
||||
@@ -476,292 +197,121 @@ class CreateLoraHookKeyframeFromStrengthListDEPR:
|
||||
is_first = False
|
||||
prev_hook_kf.add(HookKeyframe(strength=strength, start_percent=percent, guarantee_steps=guarantee_steps))
|
||||
if print_keyframes:
|
||||
logger.info(f"HookKeyframe - start_percent:{percent} = {strength}")
|
||||
return (prev_hook_kf,)
|
||||
###############################################
|
||||
###############################################
|
||||
###############################################
|
||||
logger.info(f'HookKeyframe - start_percent:{percent} = {strength}')
|
||||
return io.NodeOutput(prev_hook_kf)
|
||||
|
||||
|
||||
###############################################
|
||||
### Register LoRA Hooks
|
||||
###############################################
|
||||
# based on ComfyUI's nodes.py LoraLoader
|
||||
class MaskableLoraLoaderDEPR:
|
||||
def __init__(self):
|
||||
self.loaded_lora = None
|
||||
class MaskableLoraLoaderDEPR(io.ComfyNode):
|
||||
loaded_lora = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"clip": ("CLIP",),
|
||||
"lora_name": (folder_paths.get_filename_list("loras"), ),
|
||||
"strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
|
||||
"strength_clip": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "HOOKS")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks"
|
||||
FUNCTION = "load_lora"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_RegisterLoraHook', display_name='Register LoRA Hook 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/register lora hooks', inputs=[io.Model.Input('model'), io.Clip.Input('clip'), io.Combo.Input('lora_name', options=folder_paths.get_filename_list('loras')), io.Float.Input('strength_model', default=1.0, max=20.0, min=-20.0, step=0.01), io.Float.Input('strength_clip', default=1.0, max=20.0, min=-20.0, step=0.01)], outputs=[io.Model.Output('MODEL'), io.Clip.Output('CLIP'), io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True)
|
||||
|
||||
def load_lora(self, model: Union[ModelPatcher], clip: CLIP, lora_name: str, strength_model: float, strength_clip: float):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, model: Union[ModelPatcher], clip: CLIP, lora_name: str, strength_model: float, strength_clip: float):
|
||||
if strength_model == 0 and strength_clip == 0:
|
||||
return (model, clip, None)
|
||||
|
||||
lora_path = folder_paths.get_full_path("loras", lora_name)
|
||||
return io.NodeOutput(model, clip, None)
|
||||
lora_path = folder_paths.get_full_path('loras', lora_name)
|
||||
lora = None
|
||||
if self.loaded_lora is not None:
|
||||
if self.loaded_lora[0] == lora_path:
|
||||
lora = self.loaded_lora[1]
|
||||
if cls.loaded_lora is not None:
|
||||
if cls.loaded_lora[0] == lora_path:
|
||||
lora = cls.loaded_lora[1]
|
||||
else:
|
||||
temp = self.loaded_lora
|
||||
self.loaded_lora = None
|
||||
temp = cls.loaded_lora
|
||||
cls.loaded_lora = None
|
||||
del temp
|
||||
|
||||
if lora is None:
|
||||
lora = comfy.utils.load_torch_file(lora_path, safe_load=True)
|
||||
self.loaded_lora = (lora_path, lora)
|
||||
|
||||
model_lora, clip_lora, hooks = comfy.hooks.load_hook_lora_for_models(model=model, clip=clip, lora=lora,
|
||||
strength_model=strength_model, strength_clip=strength_clip)
|
||||
return (model_lora, clip_lora, hooks)
|
||||
cls.loaded_lora = (lora_path, lora)
|
||||
model_lora, clip_lora, hooks = comfy.hooks.load_hook_lora_for_models(model=model, clip=clip, lora=lora, strength_model=strength_model, strength_clip=strength_clip)
|
||||
return io.NodeOutput(model_lora, clip_lora, hooks)
|
||||
|
||||
class MaskableLoraLoaderModelOnlyDEPR(io.ComfyNode):
|
||||
|
||||
class MaskableLoraLoaderModelOnlyDEPR(MaskableLoraLoaderDEPR):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"lora_name": (folder_paths.get_filename_list("loras"), ),
|
||||
"strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_RegisterLoraHookModelOnly', display_name='Register LoRA Hook (Model Only) 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/register lora hooks', inputs=[io.Model.Input('model'), io.Combo.Input('lora_name', options=folder_paths.get_filename_list('loras')), io.Float.Input('strength_model', default=1.0, max=20.0, min=-20.0, step=0.01)], outputs=[io.Model.Output('MODEL'), io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True)
|
||||
|
||||
RETURN_TYPES = ("MODEL", "HOOKS")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks"
|
||||
FUNCTION = "load_lora_model_only"
|
||||
DEPRECATED = True
|
||||
|
||||
def load_lora_model_only(self, model: ModelPatcher, lora_name: str, strength_model: float):
|
||||
model_lora, _, hooks = self.load_lora(model=model, clip=None, lora_name=lora_name,
|
||||
strength_model=strength_model, strength_clip=0)
|
||||
return (model_lora, hooks)
|
||||
|
||||
|
||||
class MaskableSDModelLoaderDEPR(comfy_extras.nodes_hooks.CreateHookModelAsLora):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"clip": ("CLIP",),
|
||||
"ckpt_name": (folder_paths.get_filename_list("checkpoints"), ),
|
||||
"strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
|
||||
"strength_clip": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "HOOKS")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks"
|
||||
FUNCTION = "load_model_as_lora"
|
||||
DEPRECATED = True
|
||||
def execute(cls, model: ModelPatcher, lora_name: str, strength_model: float):
|
||||
model_lora, _, hooks = MaskableLoraLoaderDEPR.execute(model=model, clip=None, lora_name=lora_name, strength_model=strength_model, strength_clip=0).args
|
||||
return io.NodeOutput(model_lora, hooks)
|
||||
|
||||
def load_model_as_lora(self, model: ModelPatcher, clip: CLIP, ckpt_name: str, strength_model: float, strength_clip: float):
|
||||
returned = self.create_hook(ckpt_name=ckpt_name, strength_model=strength_model, strength_clip=strength_clip)
|
||||
return (model.clone(), clip.clone(), returned[0])
|
||||
class MaskableSDModelLoaderDEPR(io.ComfyNode, comfy_extras.nodes_hooks.CreateHookModelAsLora):
|
||||
loaded_weights = None
|
||||
|
||||
|
||||
class MaskableSDModelLoaderModelOnlyDEPR(MaskableSDModelLoaderDEPR):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"ckpt_name": (folder_paths.get_filename_list("checkpoints"), ),
|
||||
"strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "HOOKS")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/register lora hooks"
|
||||
FUNCTION = "load_model_as_lora_model_only"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_RegisterModelAsLoraHook', display_name='Register Model as LoRA Hook 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/register lora hooks', inputs=[io.Model.Input('model'), io.Clip.Input('clip'), io.Combo.Input('ckpt_name', options=folder_paths.get_filename_list('checkpoints')), io.Float.Input('strength_model', default=1.0, max=20.0, min=-20.0, step=0.01), io.Float.Input('strength_clip', default=1.0, max=20.0, min=-20.0, step=0.01)], outputs=[io.Model.Output('MODEL'), io.Clip.Output('CLIP'), io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True, is_experimental=True)
|
||||
|
||||
def load_model_as_lora_model_only(self, model: ModelPatcher, ckpt_name: str, strength_model: float):
|
||||
model_lora, _, hooks = self.load_model_as_lora(model=model, clip=None, ckpt_name=ckpt_name,
|
||||
strength_model=strength_model, strength_clip=0)
|
||||
return (model_lora, hooks)
|
||||
###############################################
|
||||
###############################################
|
||||
###############################################
|
||||
|
||||
|
||||
|
||||
###############################################
|
||||
### Set LoRA Hooks
|
||||
###############################################
|
||||
class SetModelLoraHookDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"conditioning": ("CONDITIONING",),
|
||||
"lora_hook": ("HOOKS",),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/single cond ops"
|
||||
FUNCTION = "attach_lora_hook"
|
||||
DEPRECATED = True
|
||||
def execute(cls, model: ModelPatcher, clip: CLIP, ckpt_name: str, strength_model: float, strength_clip: float):
|
||||
returned = comfy_extras.nodes_hooks.CreateHookModelAsLora.create_hook(
|
||||
cls, ckpt_name=ckpt_name, strength_model=strength_model, strength_clip=strength_clip
|
||||
)
|
||||
return io.NodeOutput(model.clone(), clip.clone(), returned[0])
|
||||
|
||||
def attach_lora_hook(self, conditioning, lora_hook: HookGroup):
|
||||
return (comfy.hooks.set_hooks_for_conditioning(conditioning, lora_hook),)
|
||||
|
||||
class MaskableSDModelLoaderModelOnlyDEPR(io.ComfyNode):
|
||||
|
||||
class SetClipLoraHookDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"clip": ("CLIP",),
|
||||
"lora_hook": ("HOOKS",),
|
||||
},
|
||||
"optional": {
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CLIP",)
|
||||
RETURN_NAMES = ("hook_CLIP",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning"
|
||||
FUNCTION = "apply_lora_hook"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_RegisterModelAsLoraHookModelOnly', display_name='Register Model as LoRA Hook (MO) 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/register lora hooks', inputs=[io.Model.Input('model'), io.Combo.Input('ckpt_name', options=folder_paths.get_filename_list('checkpoints')), io.Float.Input('strength_model', default=1.0, max=20.0, min=-20.0, step=0.01)], outputs=[io.Model.Output('MODEL'), io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True, is_experimental=True)
|
||||
|
||||
def apply_lora_hook(self, clip: CLIP, lora_hook: HookGroup):
|
||||
return comfy_extras.nodes_hooks.SetClipHooks.apply_hooks(self, clip, False, lora_hook)
|
||||
|
||||
|
||||
class CombineLoraHooksDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"lora_hook_A": ("HOOKS",),
|
||||
"lora_hook_B": ("HOOKS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("HOOKS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/combine lora hooks"
|
||||
FUNCTION = "combine_lora_hooks"
|
||||
DEPRECATED = True
|
||||
def execute(cls, model: ModelPatcher, ckpt_name: str, strength_model: float):
|
||||
model_lora, _, hooks = MaskableSDModelLoaderDEPR.execute(model=model, clip=None, ckpt_name=ckpt_name, strength_model=strength_model, strength_clip=0).args
|
||||
return io.NodeOutput(model_lora, hooks)
|
||||
|
||||
def combine_lora_hooks(self, lora_hook_A: HookGroup=None, lora_hook_B: HookGroup=None):
|
||||
class SetModelLoraHookDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AttachLoraHookToConditioning', display_name='Set Model LoRA Hook 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/single cond ops', inputs=[io.Conditioning.Input('conditioning'), io.Custom('HOOKS').Input('lora_hook')], outputs=[io.Conditioning.Output('CONDITIONING')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, conditioning, lora_hook: HookGroup):
|
||||
return io.NodeOutput(comfy.hooks.set_hooks_for_conditioning(conditioning, lora_hook))
|
||||
|
||||
class SetClipLoraHookDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AttachLoraHookToCLIP', display_name='Set CLIP LoRA Hook 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning', inputs=[io.Clip.Input('clip'), io.Custom('HOOKS').Input('lora_hook')], outputs=[io.Clip.Output('hook_CLIP')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, clip: CLIP, lora_hook: HookGroup):
|
||||
return io.NodeOutput(*comfy_extras.nodes_hooks.SetClipHooks.apply_hooks(cls, clip, False, lora_hook))
|
||||
|
||||
class CombineLoraHooksDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_CombineLoraHooks', display_name='Combine LoRA Hooks [2] 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/combine lora hooks', inputs=[io.Custom('HOOKS').Input('lora_hook_A', optional=True), io.Custom('HOOKS').Input('lora_hook_B', optional=True)], outputs=[io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, lora_hook_A: HookGroup=None, lora_hook_B: HookGroup=None):
|
||||
candidates = [lora_hook_A, lora_hook_B]
|
||||
return (HookGroup.combine_all_hooks(candidates),)
|
||||
return io.NodeOutput(HookGroup.combine_all_hooks(candidates))
|
||||
|
||||
class CombineLoraHookFourOptionalDEPR(io.ComfyNode):
|
||||
|
||||
class CombineLoraHookFourOptionalDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"lora_hook_A": ("HOOKS",),
|
||||
"lora_hook_B": ("HOOKS",),
|
||||
"lora_hook_C": ("HOOKS",),
|
||||
"lora_hook_D": ("HOOKS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_CombineLoraHooksFour', display_name='Combine LoRA Hooks [4] 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/combine lora hooks', inputs=[io.Custom('HOOKS').Input('lora_hook_A', optional=True), io.Custom('HOOKS').Input('lora_hook_B', optional=True), io.Custom('HOOKS').Input('lora_hook_C', optional=True), io.Custom('HOOKS').Input('lora_hook_D', optional=True)], outputs=[io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True)
|
||||
|
||||
RETURN_TYPES = ("HOOKS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/combine lora hooks"
|
||||
FUNCTION = "combine_lora_hooks"
|
||||
DEPRECATED = True
|
||||
|
||||
def combine_lora_hooks(self,
|
||||
lora_hook_A: HookGroup=None, lora_hook_B: HookGroup=None,
|
||||
lora_hook_C: HookGroup=None, lora_hook_D: HookGroup=None,):
|
||||
@classmethod
|
||||
def execute(cls, lora_hook_A: HookGroup=None, lora_hook_B: HookGroup=None, lora_hook_C: HookGroup=None, lora_hook_D: HookGroup=None):
|
||||
candidates = [lora_hook_A, lora_hook_B, lora_hook_C, lora_hook_D]
|
||||
return (HookGroup.combine_all_hooks(candidates),)
|
||||
return io.NodeOutput(HookGroup.combine_all_hooks(candidates))
|
||||
|
||||
class CombineLoraHookEightOptionalDEPR(io.ComfyNode):
|
||||
|
||||
class CombineLoraHookEightOptionalDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"lora_hook_A": ("HOOKS",),
|
||||
"lora_hook_B": ("HOOKS",),
|
||||
"lora_hook_C": ("HOOKS",),
|
||||
"lora_hook_D": ("HOOKS",),
|
||||
"lora_hook_E": ("HOOKS",),
|
||||
"lora_hook_F": ("HOOKS",),
|
||||
"lora_hook_G": ("HOOKS",),
|
||||
"lora_hook_H": ("HOOKS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated - use native ComfyUI nodes instead."}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_CombineLoraHooksEight', display_name='Combine LoRA Hooks [8] 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/conditioning/combine lora hooks', inputs=[io.Custom('HOOKS').Input('lora_hook_A', optional=True), io.Custom('HOOKS').Input('lora_hook_B', optional=True), io.Custom('HOOKS').Input('lora_hook_C', optional=True), io.Custom('HOOKS').Input('lora_hook_D', optional=True), io.Custom('HOOKS').Input('lora_hook_E', optional=True), io.Custom('HOOKS').Input('lora_hook_F', optional=True), io.Custom('HOOKS').Input('lora_hook_G', optional=True), io.Custom('HOOKS').Input('lora_hook_H', optional=True)], outputs=[io.Custom('HOOKS').Output('HOOKS')], is_deprecated=True)
|
||||
|
||||
RETURN_TYPES = ("HOOKS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/conditioning/combine lora hooks"
|
||||
FUNCTION = "combine_lora_hooks"
|
||||
DEPRECATED = True
|
||||
|
||||
def combine_lora_hooks(self,
|
||||
lora_hook_A: HookGroup=None, lora_hook_B: HookGroup=None,
|
||||
lora_hook_C: HookGroup=None, lora_hook_D: HookGroup=None,
|
||||
lora_hook_E: HookGroup=None, lora_hook_F: HookGroup=None,
|
||||
lora_hook_G: HookGroup=None, lora_hook_H: HookGroup=None):
|
||||
candidates = [lora_hook_A, lora_hook_B, lora_hook_C, lora_hook_D,
|
||||
lora_hook_E, lora_hook_F, lora_hook_G, lora_hook_H]
|
||||
return (HookGroup.combine_all_hooks(candidates),)
|
||||
|
||||
# NOTE: if at some point I add more Javascript stuff to this repo, there should be a combine node
|
||||
# that dynamically increases the hooks available to plug in on the node
|
||||
###############################################
|
||||
###############################################
|
||||
###############################################
|
||||
@classmethod
|
||||
def execute(cls, lora_hook_A: HookGroup=None, lora_hook_B: HookGroup=None, lora_hook_C: HookGroup=None, lora_hook_D: HookGroup=None, lora_hook_E: HookGroup=None, lora_hook_F: HookGroup=None, lora_hook_G: HookGroup=None, lora_hook_H: HookGroup=None):
|
||||
candidates = [lora_hook_A, lora_hook_B, lora_hook_C, lora_hook_D, lora_hook_E, lora_hook_F, lora_hook_G, lora_hook_H]
|
||||
return io.NodeOutput(HookGroup.combine_all_hooks(candidates))
|
||||
|
||||
+98
-382
@@ -1,445 +1,161 @@
|
||||
from comfy_api.latest import io
|
||||
from torch import Tensor
|
||||
from typing import Union
|
||||
|
||||
import comfy.samplers
|
||||
from comfy.model_patcher import ModelPatcher
|
||||
|
||||
from .context import (ContextFuseMethod, ContextOptions, ContextOptionsGroup, ContextSchedules,
|
||||
generate_context_visualization)
|
||||
from .context import ContextFuseMethod, ContextOptions, ContextOptionsGroup, ContextSchedules, generate_context_visualization
|
||||
from .utils_model import BIGMAX, MAX_RESOLUTION
|
||||
LENGTH_MAX = 128
|
||||
STRIDE_MAX = 32
|
||||
OVERLAP_MAX = 128
|
||||
|
||||
class LoopedUniformContextOptionsNode(io.ComfyNode):
|
||||
|
||||
LENGTH_MAX = 128 # keep an eye on these max values;
|
||||
STRIDE_MAX = 32 # would need to be updated
|
||||
OVERLAP_MAX = 128 # if new motion modules come out
|
||||
|
||||
|
||||
class LoopedUniformContextOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"context_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
"context_stride": ("INT", {"default": 1, "min": 1, "max": STRIDE_MAX}),
|
||||
"context_overlap": ("INT", {"default": 4, "min": 0, "max": OVERLAP_MAX}),
|
||||
"closed_loop": ("BOOLEAN", {"default": False},),
|
||||
#"sync_context_to_pe": ("BOOLEAN", {"default": False},),
|
||||
},
|
||||
"optional": {
|
||||
"fuse_method": (ContextFuseMethod.LIST,),
|
||||
"use_on_equal_length": ("BOOLEAN", {"default": False},),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"prev_context": ("CONTEXT_OPTIONS",),
|
||||
"view_opts": ("VIEW_OPTS",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_OPTIONS",)
|
||||
RETURN_NAMES = ("CONTEXT_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts"
|
||||
FUNCTION = "create_options"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_LoopedUniformContextOptions', display_name='Context Options◆Looped Uniform 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts', inputs=[io.Int.Input('context_length', default=16, max=128, min=1), io.Int.Input('context_stride', default=1, max=32, min=1), io.Int.Input('context_overlap', default=4, max=128, min=0), io.Boolean.Input('closed_loop', default=False), io.Combo.Input('fuse_method', options=['pyramid', 'flat', 'overlap-linear', '🔬delayed reverse sawtooth', '🔬pyramid-sigma', '🔬pyramid-sigma inverse', '🔬gauss-sigma', '🔬gauss-sigma inverse', '🔬random'], optional=True), io.Boolean.Input('use_on_equal_length', optional=True, default=False), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Custom('CONTEXT_OPTIONS').Input('prev_context', optional=True), io.Custom('VIEW_OPTS').Input('view_opts', optional=True)], outputs=[io.Custom('CONTEXT_OPTIONS').Output('CONTEXT_OPTS')])
|
||||
|
||||
def create_options(self, context_length: int, context_stride: int, context_overlap: int, closed_loop: bool,
|
||||
fuse_method: str=ContextFuseMethod.FLAT, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1,
|
||||
view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, context_length: int, context_stride: int, context_overlap: int, closed_loop: bool, fuse_method: str=ContextFuseMethod.FLAT, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1, view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None):
|
||||
if prev_context is None:
|
||||
prev_context = ContextOptionsGroup()
|
||||
prev_context = prev_context.clone()
|
||||
|
||||
context_options = ContextOptions(
|
||||
context_length=context_length,
|
||||
context_stride=context_stride,
|
||||
context_overlap=context_overlap,
|
||||
context_schedule=ContextSchedules.UNIFORM_LOOPED,
|
||||
closed_loop=closed_loop,
|
||||
fuse_method=fuse_method,
|
||||
use_on_equal_length=use_on_equal_length,
|
||||
start_percent=start_percent,
|
||||
guarantee_steps=guarantee_steps,
|
||||
view_options=view_opts,
|
||||
)
|
||||
#context_options.set_sync_context_to_pe(sync_context_to_pe)
|
||||
context_options = ContextOptions(context_length=context_length, context_stride=context_stride, context_overlap=context_overlap, context_schedule=ContextSchedules.UNIFORM_LOOPED, closed_loop=closed_loop, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts)
|
||||
prev_context.add(context_options)
|
||||
return (prev_context,)
|
||||
return io.NodeOutput(prev_context)
|
||||
|
||||
class LegacyLoopedUniformContextOptionsNode(io.ComfyNode):
|
||||
|
||||
# This Legacy version exists to maintain compatiblity with old workflows
|
||||
class LegacyLoopedUniformContextOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"context_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
"context_stride": ("INT", {"default": 1, "min": 1, "max": STRIDE_MAX}),
|
||||
"context_overlap": ("INT", {"default": 4, "min": 0, "max": OVERLAP_MAX}),
|
||||
"context_schedule": (ContextSchedules.LEGACY_UNIFORM_SCHEDULE_LIST,),
|
||||
"closed_loop": ("BOOLEAN", {"default": False},),
|
||||
#"sync_context_to_pe": ("BOOLEAN", {"default": False},),
|
||||
},
|
||||
"optional": {
|
||||
"fuse_method": (ContextFuseMethod.LIST, {"default": ContextFuseMethod.FLAT}),
|
||||
"use_on_equal_length": ("BOOLEAN", {"default": False},),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"prev_context": ("CONTEXT_OPTIONS",),
|
||||
"view_opts": ("VIEW_OPTS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": ""}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_OPTIONS",)
|
||||
RETURN_NAMES = ("CONTEXT_OPTS",)
|
||||
CATEGORY = "" # No Category, so will not appear in menu
|
||||
FUNCTION = "create_options"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffUniformContextOptions', display_name='Context Options◆Looped Uniform 🎭🅐🅓', category='', inputs=[io.Int.Input('context_length', default=16, max=128, min=1), io.Int.Input('context_stride', default=1, max=32, min=1), io.Int.Input('context_overlap', default=4, max=128, min=0), io.Combo.Input('context_schedule', options=['uniform']), io.Boolean.Input('closed_loop', default=False), io.Combo.Input('fuse_method', options=['pyramid', 'flat', 'overlap-linear', '🔬delayed reverse sawtooth', '🔬pyramid-sigma', '🔬pyramid-sigma inverse', '🔬gauss-sigma', '🔬gauss-sigma inverse', '🔬random'], optional=True, default='flat'), io.Boolean.Input('use_on_equal_length', optional=True, default=False), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Custom('CONTEXT_OPTIONS').Input('prev_context', optional=True), io.Custom('VIEW_OPTS').Input('view_opts', optional=True)], outputs=[io.Custom('CONTEXT_OPTIONS').Output('CONTEXT_OPTS')], is_deprecated=True)
|
||||
|
||||
def create_options(self, fuse_method: str=ContextFuseMethod.FLAT, context_schedule: str=None, **kwargs):
|
||||
return LoopedUniformContextOptionsNode.create_options(self, fuse_method=fuse_method, **kwargs)
|
||||
|
||||
|
||||
class StandardUniformContextOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"context_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
"context_stride": ("INT", {"default": 1, "min": 1, "max": STRIDE_MAX}),
|
||||
"context_overlap": ("INT", {"default": 4, "min": 0, "max": OVERLAP_MAX}),
|
||||
},
|
||||
"optional": {
|
||||
"fuse_method": (ContextFuseMethod.LIST,),
|
||||
"use_on_equal_length": ("BOOLEAN", {"default": False},),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"prev_context": ("CONTEXT_OPTIONS",),
|
||||
"view_opts": ("VIEW_OPTS",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_OPTIONS",)
|
||||
RETURN_NAMES = ("CONTEXT_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts"
|
||||
FUNCTION = "create_options"
|
||||
def execute(cls, fuse_method: str=ContextFuseMethod.FLAT, context_schedule: str=None, **kwargs):
|
||||
return LoopedUniformContextOptionsNode.execute(fuse_method=fuse_method, **kwargs)
|
||||
|
||||
def create_options(self, context_length: int, context_stride: int, context_overlap: int,
|
||||
fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1,
|
||||
view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None):
|
||||
class StandardUniformContextOptionsNode(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_StandardUniformContextOptions', display_name='Context Options◆Standard Uniform 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts', inputs=[io.Int.Input('context_length', default=16, max=128, min=1), io.Int.Input('context_stride', default=1, max=32, min=1), io.Int.Input('context_overlap', default=4, max=128, min=0), io.Combo.Input('fuse_method', options=['pyramid', 'flat', 'overlap-linear', '🔬delayed reverse sawtooth', '🔬pyramid-sigma', '🔬pyramid-sigma inverse', '🔬gauss-sigma', '🔬gauss-sigma inverse', '🔬random'], optional=True), io.Boolean.Input('use_on_equal_length', optional=True, default=False), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Custom('CONTEXT_OPTIONS').Input('prev_context', optional=True), io.Custom('VIEW_OPTS').Input('view_opts', optional=True)], outputs=[io.Custom('CONTEXT_OPTIONS').Output('CONTEXT_OPTS')])
|
||||
|
||||
@classmethod
|
||||
def execute(cls, context_length: int, context_stride: int, context_overlap: int, fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1, view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None):
|
||||
if prev_context is None:
|
||||
prev_context = ContextOptionsGroup()
|
||||
prev_context = prev_context.clone()
|
||||
|
||||
context_options = ContextOptions(
|
||||
context_length=context_length,
|
||||
context_stride=context_stride,
|
||||
context_overlap=context_overlap,
|
||||
context_schedule=ContextSchedules.UNIFORM_STANDARD,
|
||||
closed_loop=False,
|
||||
fuse_method=fuse_method,
|
||||
use_on_equal_length=use_on_equal_length,
|
||||
start_percent=start_percent,
|
||||
guarantee_steps=guarantee_steps,
|
||||
view_options=view_opts,
|
||||
)
|
||||
context_options = ContextOptions(context_length=context_length, context_stride=context_stride, context_overlap=context_overlap, context_schedule=ContextSchedules.UNIFORM_STANDARD, closed_loop=False, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts)
|
||||
prev_context.add(context_options)
|
||||
return (prev_context,)
|
||||
return io.NodeOutput(prev_context)
|
||||
|
||||
class StandardStaticContextOptionsNode(io.ComfyNode):
|
||||
|
||||
class StandardStaticContextOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"context_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
"context_overlap": ("INT", {"default": 4, "min": 0, "max": OVERLAP_MAX}),
|
||||
},
|
||||
"optional": {
|
||||
"fuse_method": (ContextFuseMethod.LIST_STATIC,),
|
||||
"use_on_equal_length": ("BOOLEAN", {"default": False},),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"prev_context": ("CONTEXT_OPTIONS",),
|
||||
"view_opts": ("VIEW_OPTS",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_OPTIONS",)
|
||||
RETURN_NAMES = ("CONTEXT_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts"
|
||||
FUNCTION = "create_options"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_StandardStaticContextOptions', display_name='Context Options◆Standard Static 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts', inputs=[io.Int.Input('context_length', default=16, max=128, min=1), io.Int.Input('context_overlap', default=4, max=128, min=0), io.Combo.Input('fuse_method', options=['pyramid', 'relative', 'flat', 'overlap-linear', '🔬delayed reverse sawtooth', '🔬pyramid-sigma', '🔬pyramid-sigma inverse', '🔬gauss-sigma', '🔬gauss-sigma inverse', '🔬random'], optional=True), io.Boolean.Input('use_on_equal_length', optional=True, default=False), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Custom('CONTEXT_OPTIONS').Input('prev_context', optional=True), io.Custom('VIEW_OPTS').Input('view_opts', optional=True)], outputs=[io.Custom('CONTEXT_OPTIONS').Output('CONTEXT_OPTS')])
|
||||
|
||||
def create_options(self, context_length: int, context_overlap: int,
|
||||
fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1,
|
||||
view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, context_length: int, context_overlap: int, fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False, start_percent: float=0.0, guarantee_steps: int=1, view_opts: ContextOptions=None, prev_context: ContextOptionsGroup=None):
|
||||
if prev_context is None:
|
||||
prev_context = ContextOptionsGroup()
|
||||
prev_context = prev_context.clone()
|
||||
|
||||
context_options = ContextOptions(
|
||||
context_length=context_length,
|
||||
context_stride=None,
|
||||
context_overlap=context_overlap,
|
||||
context_schedule=ContextSchedules.STATIC_STANDARD,
|
||||
fuse_method=fuse_method,
|
||||
use_on_equal_length=use_on_equal_length,
|
||||
start_percent=start_percent,
|
||||
guarantee_steps=guarantee_steps,
|
||||
view_options=view_opts,
|
||||
)
|
||||
context_options = ContextOptions(context_length=context_length, context_stride=None, context_overlap=context_overlap, context_schedule=ContextSchedules.STATIC_STANDARD, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts)
|
||||
prev_context.add(context_options)
|
||||
return (prev_context,)
|
||||
return io.NodeOutput(prev_context)
|
||||
|
||||
class BatchedContextOptionsNode(io.ComfyNode):
|
||||
|
||||
class BatchedContextOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"context_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
},
|
||||
"optional": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"prev_context": ("CONTEXT_OPTIONS",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_OPTIONS",)
|
||||
RETURN_NAMES = ("CONTEXT_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts"
|
||||
FUNCTION = "create_options"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_BatchedContextOptions', display_name='Context Options◆Batched [Non-AD] 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts', inputs=[io.Int.Input('context_length', default=16, max=128, min=1), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Custom('CONTEXT_OPTIONS').Input('prev_context', optional=True)], outputs=[io.Custom('CONTEXT_OPTIONS').Output('CONTEXT_OPTS')])
|
||||
|
||||
def create_options(self, context_length: int, start_percent: float=0.0, guarantee_steps: int=1,
|
||||
prev_context: ContextOptionsGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, context_length: int, start_percent: float=0.0, guarantee_steps: int=1, prev_context: ContextOptionsGroup=None):
|
||||
if prev_context is None:
|
||||
prev_context = ContextOptionsGroup()
|
||||
prev_context = prev_context.clone()
|
||||
|
||||
context_options = ContextOptions(
|
||||
context_length=context_length,
|
||||
context_overlap=0,
|
||||
context_schedule=ContextSchedules.BATCHED,
|
||||
start_percent=start_percent,
|
||||
guarantee_steps=guarantee_steps,
|
||||
)
|
||||
context_options = ContextOptions(context_length=context_length, context_overlap=0, context_schedule=ContextSchedules.BATCHED, start_percent=start_percent, guarantee_steps=guarantee_steps)
|
||||
prev_context.add(context_options)
|
||||
return (prev_context,)
|
||||
return io.NodeOutput(prev_context)
|
||||
|
||||
class ViewAsContextOptionsNode(io.ComfyNode):
|
||||
|
||||
class ViewAsContextOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"view_opts_req": ("VIEW_OPTS",),
|
||||
},
|
||||
"optional": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"prev_context": ("CONTEXT_OPTIONS",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_OPTIONS",)
|
||||
RETURN_NAMES = ("CONTEXT_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts"
|
||||
FUNCTION = "create_options"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ViewsOnlyContextOptions', display_name='Context Options◆Views Only [VRAM⇈] 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts', inputs=[io.Custom('VIEW_OPTS').Input('view_opts_req'), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Custom('CONTEXT_OPTIONS').Input('prev_context', optional=True)], outputs=[io.Custom('CONTEXT_OPTIONS').Output('CONTEXT_OPTS')])
|
||||
|
||||
def create_options(self, view_opts_req: ContextOptions, start_percent: float=0.0, guarantee_steps: int=1,
|
||||
prev_context: ContextOptionsGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, view_opts_req: ContextOptions, start_percent: float=0.0, guarantee_steps: int=1, prev_context: ContextOptionsGroup=None):
|
||||
if prev_context is None:
|
||||
prev_context = ContextOptionsGroup()
|
||||
prev_context = prev_context.clone()
|
||||
context_options = ContextOptions(
|
||||
context_schedule=ContextSchedules.VIEW_AS_CONTEXT,
|
||||
start_percent=start_percent,
|
||||
guarantee_steps=guarantee_steps,
|
||||
view_options=view_opts_req,
|
||||
use_on_equal_length=True
|
||||
)
|
||||
context_options = ContextOptions(context_schedule=ContextSchedules.VIEW_AS_CONTEXT, start_percent=start_percent, guarantee_steps=guarantee_steps, view_options=view_opts_req, use_on_equal_length=True)
|
||||
prev_context.add(context_options)
|
||||
return (prev_context,)
|
||||
return io.NodeOutput(prev_context)
|
||||
|
||||
class StandardStaticViewOptionsNode(io.ComfyNode):
|
||||
|
||||
#########################
|
||||
# View Options
|
||||
class StandardStaticViewOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"view_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
"view_overlap": ("INT", {"default": 4, "min": 0, "max": OVERLAP_MAX}),
|
||||
},
|
||||
"optional": {
|
||||
"fuse_method": (ContextFuseMethod.LIST,),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VIEW_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/view opts"
|
||||
FUNCTION = "create_options"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_StandardStaticViewOptions', display_name='View Options◆Standard Static 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/view opts', inputs=[io.Int.Input('view_length', default=16, max=128, min=1), io.Int.Input('view_overlap', default=4, max=128, min=0), io.Combo.Input('fuse_method', options=['pyramid', 'flat', 'overlap-linear', '🔬delayed reverse sawtooth', '🔬pyramid-sigma', '🔬pyramid-sigma inverse', '🔬gauss-sigma', '🔬gauss-sigma inverse', '🔬random'], optional=True)], outputs=[io.Custom('VIEW_OPTS').Output('VIEW_OPTS')])
|
||||
|
||||
def create_options(self, view_length: int, view_overlap: int,
|
||||
fuse_method: str=ContextFuseMethod.FLAT,):
|
||||
view_options = ContextOptions(
|
||||
context_length=view_length,
|
||||
context_stride=None,
|
||||
context_overlap=view_overlap,
|
||||
context_schedule=ContextSchedules.STATIC_STANDARD,
|
||||
fuse_method=fuse_method,
|
||||
)
|
||||
return (view_options,)
|
||||
|
||||
|
||||
class StandardUniformViewOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"view_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
"view_stride": ("INT", {"default": 1, "min": 1, "max": STRIDE_MAX}),
|
||||
"view_overlap": ("INT", {"default": 4, "min": 0, "max": OVERLAP_MAX}),
|
||||
},
|
||||
"optional": {
|
||||
"fuse_method": (ContextFuseMethod.LIST,),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VIEW_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/view opts"
|
||||
FUNCTION = "create_options"
|
||||
def execute(cls, view_length: int, view_overlap: int, fuse_method: str=ContextFuseMethod.FLAT):
|
||||
view_options = ContextOptions(context_length=view_length, context_stride=None, context_overlap=view_overlap, context_schedule=ContextSchedules.STATIC_STANDARD, fuse_method=fuse_method)
|
||||
return io.NodeOutput(view_options)
|
||||
|
||||
def create_options(self, view_length: int, view_overlap: int, view_stride: int,
|
||||
fuse_method: str=ContextFuseMethod.PYRAMID,):
|
||||
view_options = ContextOptions(
|
||||
context_length=view_length,
|
||||
context_stride=view_stride,
|
||||
context_overlap=view_overlap,
|
||||
context_schedule=ContextSchedules.UNIFORM_STANDARD,
|
||||
fuse_method=fuse_method,
|
||||
)
|
||||
return (view_options,)
|
||||
class StandardUniformViewOptionsNode(io.ComfyNode):
|
||||
|
||||
|
||||
class LoopedUniformViewOptionsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"view_length": ("INT", {"default": 16, "min": 1, "max": LENGTH_MAX}),
|
||||
"view_stride": ("INT", {"default": 1, "min": 1, "max": STRIDE_MAX}),
|
||||
"view_overlap": ("INT", {"default": 4, "min": 0, "max": OVERLAP_MAX}),
|
||||
"closed_loop": ("BOOLEAN", {"default": False},),
|
||||
},
|
||||
"optional": {
|
||||
"fuse_method": (ContextFuseMethod.LIST,),
|
||||
"use_on_equal_length": ("BOOLEAN", {"default": False},),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VIEW_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/view opts"
|
||||
FUNCTION = "create_options"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_StandardUniformViewOptions', display_name='View Options◆Standard Uniform 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/view opts', inputs=[io.Int.Input('view_length', default=16, max=128, min=1), io.Int.Input('view_stride', default=1, max=32, min=1), io.Int.Input('view_overlap', default=4, max=128, min=0), io.Combo.Input('fuse_method', options=['pyramid', 'flat', 'overlap-linear', '🔬delayed reverse sawtooth', '🔬pyramid-sigma', '🔬pyramid-sigma inverse', '🔬gauss-sigma', '🔬gauss-sigma inverse', '🔬random'], optional=True)], outputs=[io.Custom('VIEW_OPTS').Output('VIEW_OPTS')])
|
||||
|
||||
def create_options(self, view_length: int, view_overlap: int, view_stride: int, closed_loop: bool,
|
||||
fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False):
|
||||
view_options = ContextOptions(
|
||||
context_length=view_length,
|
||||
context_stride=view_stride,
|
||||
context_overlap=view_overlap,
|
||||
context_schedule=ContextSchedules.UNIFORM_LOOPED,
|
||||
closed_loop=closed_loop,
|
||||
fuse_method=fuse_method,
|
||||
use_on_equal_length=use_on_equal_length,
|
||||
)
|
||||
return (view_options,)
|
||||
|
||||
|
||||
class VisualizeContextOptionsKAdv:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, ),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, ),
|
||||
},
|
||||
"optional": {
|
||||
"context_opts": ("CONTEXT_OPTIONS",),
|
||||
"visual_width": ("INT", {"min": 32, "max": MAX_RESOLUTION, "default": 1440}),
|
||||
"latents_length": ("INT", {"min": 1, "max": BIGMAX, "default": 32}),
|
||||
"steps": ("INT", {"min": 0, "max": BIGMAX, "default": 20}),
|
||||
"start_step": ("INT", {"min": 0, "max": BIGMAX, "default": 0}),
|
||||
"end_step": ("INT", {"min": 1, "max": BIGMAX, "default": 20}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/visualize"
|
||||
FUNCTION = "visualize"
|
||||
def execute(cls, view_length: int, view_overlap: int, view_stride: int, fuse_method: str=ContextFuseMethod.PYRAMID):
|
||||
view_options = ContextOptions(context_length=view_length, context_stride=view_stride, context_overlap=view_overlap, context_schedule=ContextSchedules.UNIFORM_STANDARD, fuse_method=fuse_method)
|
||||
return io.NodeOutput(view_options)
|
||||
|
||||
def visualize(self, model: ModelPatcher, sampler_name: str, scheduler: str, context_opts: ContextOptionsGroup=None,
|
||||
visual_width=1440, latents_length=32, steps=20, start_step=0, end_step=20):
|
||||
images = generate_context_visualization(model=model, context_opts=context_opts, width=visual_width, video_length=latents_length,
|
||||
sampler_name=sampler_name, scheduler=scheduler,
|
||||
steps=steps, start_step=start_step, end_step=end_step)
|
||||
return (images,)
|
||||
class LoopedUniformViewOptionsNode(io.ComfyNode):
|
||||
|
||||
|
||||
class VisualizeContextOptionsK:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, ),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, ),
|
||||
},
|
||||
"optional": {
|
||||
"context_opts": ("CONTEXT_OPTIONS",),
|
||||
"visual_width": ("INT", {"min": 32, "max": MAX_RESOLUTION, "default": 1440}),
|
||||
"latents_length": ("INT", {"min": 1, "max": BIGMAX, "default": 32}),
|
||||
"steps": ("INT", {"min": 0, "max": BIGMAX, "default": 20}),
|
||||
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/visualize"
|
||||
FUNCTION = "visualize"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_LoopedUniformViewOptions', display_name='View Options◆Looped Uniform 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/view opts', inputs=[io.Int.Input('view_length', default=16, max=128, min=1), io.Int.Input('view_stride', default=1, max=32, min=1), io.Int.Input('view_overlap', default=4, max=128, min=0), io.Boolean.Input('closed_loop', default=False), io.Combo.Input('fuse_method', options=['pyramid', 'flat', 'overlap-linear', '🔬delayed reverse sawtooth', '🔬pyramid-sigma', '🔬pyramid-sigma inverse', '🔬gauss-sigma', '🔬gauss-sigma inverse', '🔬random'], optional=True), io.Boolean.Input('use_on_equal_length', optional=True, default=False)], outputs=[io.Custom('VIEW_OPTS').Output('VIEW_OPTS')])
|
||||
|
||||
def visualize(self, model: ModelPatcher, sampler_name: str, scheduler: str, context_opts: ContextOptionsGroup=None,
|
||||
visual_width=1440, latents_length=32, steps=20, denoise=1.0):
|
||||
images = generate_context_visualization(model=model, context_opts=context_opts, width=visual_width, video_length=latents_length,
|
||||
sampler_name=sampler_name, scheduler=scheduler,
|
||||
steps=steps, denoise=denoise)
|
||||
return (images,)
|
||||
|
||||
|
||||
class VisualizeContextOptionsSCustom:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"sigmas": ("SIGMAS", ),
|
||||
},
|
||||
"optional": {
|
||||
"context_opts": ("CONTEXT_OPTIONS",),
|
||||
"visual_width": ("INT", {"min": 32, "max": MAX_RESOLUTION, "default": 1440}),
|
||||
"latents_length": ("INT", {"min": 1, "max": BIGMAX, "default": 32}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/visualize"
|
||||
FUNCTION = "visualize"
|
||||
def execute(cls, view_length: int, view_overlap: int, view_stride: int, closed_loop: bool, fuse_method: str=ContextFuseMethod.PYRAMID, use_on_equal_length=False):
|
||||
view_options = ContextOptions(context_length=view_length, context_stride=view_stride, context_overlap=view_overlap, context_schedule=ContextSchedules.UNIFORM_LOOPED, closed_loop=closed_loop, fuse_method=fuse_method, use_on_equal_length=use_on_equal_length)
|
||||
return io.NodeOutput(view_options)
|
||||
|
||||
def visualize(self, model: ModelPatcher, sigmas, context_opts: ContextOptionsGroup=None,
|
||||
visual_width=1440, latents_length=32):
|
||||
images = generate_context_visualization(model=model, context_opts=context_opts, width=visual_width, video_length=latents_length,
|
||||
sigmas=sigmas)
|
||||
return (images,)
|
||||
class VisualizeContextOptionsKAdv(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_VisualizeContextOptionsKAdv', display_name='Visualize Context Options (K.Adv.) 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/visualize', inputs=[io.Model.Input('model'), io.Combo.Input('sampler_name', options=comfy.samplers.KSampler.SAMPLERS), io.Combo.Input('scheduler', options=comfy.samplers.KSampler.SCHEDULERS), io.Custom('CONTEXT_OPTIONS').Input('context_opts', optional=True), io.Int.Input('visual_width', optional=True, default=1440, max=16384, min=32), io.Int.Input('latents_length', optional=True, default=32, max=9007199254740991, min=1), io.Int.Input('steps', optional=True, default=20, max=9007199254740991, min=0), io.Int.Input('start_step', optional=True, default=0, max=9007199254740991, min=0), io.Int.Input('end_step', optional=True, default=20, max=9007199254740991, min=1)], outputs=[io.Image.Output('IMAGE')])
|
||||
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, sampler_name: str, scheduler: str, context_opts: ContextOptionsGroup=None, visual_width=1440, latents_length=32, steps=20, start_step=0, end_step=20):
|
||||
images = generate_context_visualization(model=model, context_opts=context_opts, width=visual_width, video_length=latents_length, sampler_name=sampler_name, scheduler=scheduler, steps=steps, start_step=start_step, end_step=end_step)
|
||||
return io.NodeOutput(images)
|
||||
|
||||
class VisualizeContextOptionsK(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_VisualizeContextOptionsK', display_name='Visualize Context Options (K.) 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/visualize', inputs=[io.Model.Input('model'), io.Combo.Input('sampler_name', options=comfy.samplers.KSampler.SAMPLERS), io.Combo.Input('scheduler', options=comfy.samplers.KSampler.SCHEDULERS), io.Custom('CONTEXT_OPTIONS').Input('context_opts', optional=True), io.Int.Input('visual_width', optional=True, default=1440, max=16384, min=32), io.Int.Input('latents_length', optional=True, default=32, max=9007199254740991, min=1), io.Int.Input('steps', optional=True, default=20, max=9007199254740991, min=0), io.Float.Input('denoise', optional=True, default=1.0, max=1.0, min=0.0, step=0.01)], outputs=[io.Image.Output('IMAGE')])
|
||||
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, sampler_name: str, scheduler: str, context_opts: ContextOptionsGroup=None, visual_width=1440, latents_length=32, steps=20, denoise=1.0):
|
||||
images = generate_context_visualization(model=model, context_opts=context_opts, width=visual_width, video_length=latents_length, sampler_name=sampler_name, scheduler=scheduler, steps=steps, denoise=denoise)
|
||||
return io.NodeOutput(images)
|
||||
|
||||
class VisualizeContextOptionsSCustom(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_VisualizeContextOptionsSCustom', display_name='Visualize Context Options (S.Cus.) 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/visualize', inputs=[io.Model.Input('model'), io.Sigmas.Input('sigmas'), io.Custom('CONTEXT_OPTIONS').Input('context_opts', optional=True), io.Int.Input('visual_width', optional=True, default=1440, max=16384, min=32), io.Int.Input('latents_length', optional=True, default=32, max=9007199254740991, min=1)], outputs=[io.Image.Output('IMAGE')])
|
||||
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, sigmas, context_opts: ContextOptionsGroup=None, visual_width=1440, latents_length=32):
|
||||
images = generate_context_visualization(model=model, context_opts=context_opts, width=visual_width, video_length=latents_length, sigmas=sigmas)
|
||||
return io.NodeOutput(images)
|
||||
|
||||
+105
-393
@@ -1,197 +1,89 @@
|
||||
from comfy_api.latest import io
|
||||
from torch import Tensor
|
||||
from typing import Union
|
||||
from collections.abc import Iterable
|
||||
|
||||
from .context import (ContextOptionsGroup)
|
||||
from .context_extras import (ContextExtrasGroup,
|
||||
ContextRef, ContextRefTune, ContextRefMode, ContextRefKeyframeGroup, ContextRefKeyframe,
|
||||
NaiveReuse, NaiveReuseKeyframe, NaiveReuseKeyframeGroup)
|
||||
from .context import ContextOptionsGroup
|
||||
from .context_extras import ContextExtrasGroup, ContextRef, ContextRefTune, ContextRefMode, ContextRefKeyframeGroup, ContextRefKeyframe, NaiveReuse, NaiveReuseKeyframe, NaiveReuseKeyframeGroup
|
||||
from .utils_model import BIGMAX, InterpolationMethod
|
||||
from .utils_scheduling import convert_str_to_indexes
|
||||
from .logger import logger
|
||||
|
||||
class SetContextExtrasOnContextOptions(io.ComfyNode):
|
||||
|
||||
class SetContextExtrasOnContextOptions:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"context_opts": ("CONTEXT_OPTIONS",),
|
||||
},
|
||||
"optional": {
|
||||
"context_extras": ("CONTEXT_EXTRAS",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_OPTIONS",)
|
||||
RETURN_NAMES = ("CONTEXT_OPTS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras"
|
||||
FUNCTION = "set_context_extras"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_Set', display_name='Set Context Extras 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras', inputs=[io.Custom('CONTEXT_OPTIONS').Input('context_opts'), io.Custom('CONTEXT_EXTRAS').Input('context_extras', optional=True)], outputs=[io.Custom('CONTEXT_OPTIONS').Output('CONTEXT_OPTS')])
|
||||
|
||||
def set_context_extras(self, context_opts: ContextOptionsGroup, context_extras: ContextExtrasGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, context_opts: ContextOptionsGroup, context_extras: ContextExtrasGroup=None):
|
||||
context_opts = context_opts.clone()
|
||||
if context_extras is not None:
|
||||
context_opts.extras = context_extras.clone()
|
||||
return (context_opts,)
|
||||
return io.NodeOutput(context_opts)
|
||||
|
||||
class ContextExtras_NaiveReuse(io.ComfyNode):
|
||||
|
||||
#########################################
|
||||
# NaiveReuse
|
||||
class ContextExtras_NaiveReuse:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"prev_extras": ("CONTEXT_EXTRAS",),
|
||||
"strength_multival": ("MULTIVAL",),
|
||||
"naivereuse_kf": ("NAIVEREUSE_KEYFRAME",),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 0.15, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"weighted_mean": ("FLOAT", {"default": 0.95, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_EXTRAS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras"
|
||||
FUNCTION = "create_context_extra"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_NaiveReuse', display_name='Context Extras◆NaiveReuse 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras', inputs=[io.Custom('CONTEXT_EXTRAS').Input('prev_extras', optional=True), io.Custom('MULTIVAL').Input('strength_multival', optional=True), io.Custom('NAIVEREUSE_KEYFRAME').Input('naivereuse_kf', optional=True), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', optional=True, default=0.15, max=1.0, min=0.0, step=0.001), io.Float.Input('weighted_mean', optional=True, default=0.95, max=1.0, min=0.0, step=0.001)], outputs=[io.Custom('CONTEXT_EXTRAS').Output('CONTEXT_EXTRAS')])
|
||||
|
||||
def create_context_extra(self, start_percent=0.0, end_percent=0.1, weighted_mean=0.95, strength_multival: Union[float, Tensor]=None,
|
||||
naivereuse_kf: NaiveReuseKeyframeGroup=None, prev_extras: ContextExtrasGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, start_percent=0.0, end_percent=0.1, weighted_mean=0.95, strength_multival: Union[float, Tensor]=None, naivereuse_kf: NaiveReuseKeyframeGroup=None, prev_extras: ContextExtrasGroup=None):
|
||||
if prev_extras is None:
|
||||
prev_extras = prev_extras = ContextExtrasGroup()
|
||||
prev_extras = prev_extras.clone()
|
||||
# create extra
|
||||
naive_reuse = NaiveReuse(start_percent=start_percent, end_percent=end_percent, weighted_mean=weighted_mean, multival_opt=strength_multival,
|
||||
naivereuse_kf=naivereuse_kf)
|
||||
naive_reuse = NaiveReuse(start_percent=start_percent, end_percent=end_percent, weighted_mean=weighted_mean, multival_opt=strength_multival, naivereuse_kf=naivereuse_kf)
|
||||
prev_extras.add(naive_reuse)
|
||||
return (prev_extras,)
|
||||
return io.NodeOutput(prev_extras)
|
||||
|
||||
class NaiveReuse_KeyframeMultivalNode(io.ComfyNode):
|
||||
|
||||
class NaiveReuse_KeyframeMultivalNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"prev_kf": ("NAIVEREUSE_KEYFRAME",),
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
"mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}, ),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("NAIVEREUSE_KEYFRAME",)
|
||||
RETURN_NAMES = ("NAIVEREUSE_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/naivereuse"
|
||||
FUNCTION = "create_keyframe"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_NaiveReuse_Keyframe', display_name='NaiveReuse Keyframe 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/naivereuse', inputs=[io.Custom('NAIVEREUSE_KEYFRAME').Input('prev_kf', optional=True), io.Custom('MULTIVAL').Input('mult_multival', optional=True), io.Float.Input('mult', optional=True, default=1.0, max=1.0, min=0.0, step=0.001), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Boolean.Input('inherit_missing', optional=True, default=True)], outputs=[io.Custom('NAIVEREUSE_KEYFRAME').Output('NAIVEREUSE_KF')])
|
||||
|
||||
def create_keyframe(self, prev_kf=None, mult=1.0, mult_multival=None,
|
||||
start_percent=0.0, guarantee_steps=1, inherit_missing=True):
|
||||
@classmethod
|
||||
def execute(cls, prev_kf=None, mult=1.0, mult_multival=None, start_percent=0.0, guarantee_steps=1, inherit_missing=True):
|
||||
if prev_kf is None:
|
||||
prev_kf = NaiveReuseKeyframeGroup()
|
||||
prev_kf = prev_kf.clone()
|
||||
kf = NaiveReuseKeyframe(mult=mult, mult_multival=mult_multival,
|
||||
start_percent=start_percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing)
|
||||
kf = NaiveReuseKeyframe(mult=mult, mult_multival=mult_multival, start_percent=start_percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing)
|
||||
prev_kf.add(kf)
|
||||
return (prev_kf,)
|
||||
return io.NodeOutput(prev_kf)
|
||||
|
||||
class NaiveReuse_KeyframeInterpolationNode(io.ComfyNode):
|
||||
|
||||
class NaiveReuse_KeyframeInterpolationNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"mult_start": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"mult_end": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"interpolation": (InterpolationMethod._LIST, ),
|
||||
"intervals": ("INT", {"default": 50, "min": 2, "max": 100, "step": 1}),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}),
|
||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_kf": ("NAIVEREUSE_KEYFRAME",),
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("NAIVEREUSE_KEYFRAME",)
|
||||
RETURN_NAMES = ("NAIVEREUSE_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/naivereuse"
|
||||
FUNCTION = "create_keyframe"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_NaiveReuse_KeyframeInterpolation', display_name='NaiveReuse Keyframes Interp. 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/naivereuse', inputs=[io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001), io.Float.Input('mult_start', default=1.0, max=1.0, min=0.0, step=0.001), io.Float.Input('mult_end', default=1.0, max=1.0, min=0.0, step=0.001), io.Combo.Input('interpolation', options=['linear', 'ease_in', 'ease_out', 'ease_in_out']), io.Int.Input('intervals', default=50, max=100, min=2, step=1), io.Boolean.Input('inherit_missing', default=True), io.Boolean.Input('print_keyframes', default=False), io.Custom('NAIVEREUSE_KEYFRAME').Input('prev_kf', optional=True), io.Custom('MULTIVAL').Input('mult_multival', optional=True)], outputs=[io.Custom('NAIVEREUSE_KEYFRAME').Output('NAIVEREUSE_KF')])
|
||||
|
||||
def create_keyframe(self,
|
||||
start_percent: float, end_percent: float,
|
||||
mult_start: float, mult_end: float, interpolation: str, intervals: int,
|
||||
inherit_missing=True, prev_kf: NaiveReuseKeyframeGroup=None,
|
||||
mult_multival=None, print_keyframes=False):
|
||||
@classmethod
|
||||
def execute(cls, start_percent: float, end_percent: float, mult_start: float, mult_end: float, interpolation: str, intervals: int, inherit_missing=True, prev_kf: NaiveReuseKeyframeGroup=None, mult_multival=None, print_keyframes=False):
|
||||
if prev_kf is None:
|
||||
prev_kf = NaiveReuseKeyframeGroup()
|
||||
prev_kf = prev_kf.clone()
|
||||
prev_kf = prev_kf.clone()
|
||||
percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=intervals, method=InterpolationMethod.LINEAR)
|
||||
mults = InterpolationMethod.get_weights(num_from=mult_start, num_to=mult_end, length=intervals, method=interpolation)
|
||||
|
||||
is_first = True
|
||||
for percent, mult in zip(percents, mults):
|
||||
guarantee_steps = 0
|
||||
if is_first:
|
||||
guarantee_steps = 1
|
||||
is_first = False
|
||||
prev_kf.add(NaiveReuseKeyframe(mult=mult, mult_multival=mult_multival,
|
||||
start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
prev_kf.add(NaiveReuseKeyframe(mult=mult, mult_multival=mult_multival, start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
if print_keyframes:
|
||||
logger.info(f"NaiveReuseKeyframe - start_percent:{percent} = {mult}")
|
||||
return (prev_kf,)
|
||||
logger.info(f'NaiveReuseKeyframe - start_percent:{percent} = {mult}')
|
||||
return io.NodeOutput(prev_kf)
|
||||
|
||||
class NaiveReuse_KeyframeFromListNode(io.ComfyNode):
|
||||
|
||||
class NaiveReuse_KeyframeFromListNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"mults_float": ("FLOAT", {"default": -1, "min": -1, "step": 0.001, "forceInput": True}),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}),
|
||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_kf": ("NAIVEREUSE_KEYFRAME",),
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("NAIVEREUSE_KEYFRAME",)
|
||||
RETURN_NAMES = ("NAIVEREUSE_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/naivereuse"
|
||||
FUNCTION = "create_keyframe"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_NaiveReuse_KeyframeFromList', display_name='NaiveReuse Keyframes From List 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/naivereuse', inputs=[io.Float.Input('mults_float', default=-1, force_input=True, min=-1, step=0.001), io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001), io.Boolean.Input('inherit_missing', default=True), io.Boolean.Input('print_keyframes', default=False), io.Custom('NAIVEREUSE_KEYFRAME').Input('prev_kf', optional=True), io.Custom('MULTIVAL').Input('mult_multival', optional=True)], outputs=[io.Custom('NAIVEREUSE_KEYFRAME').Output('NAIVEREUSE_KF')])
|
||||
|
||||
def create_keyframe(self, mults_float: Union[float, list[float]],
|
||||
start_percent: float, end_percent: float,
|
||||
inherit_missing=True, prev_kf: NaiveReuseKeyframeGroup=None,
|
||||
mult_multival=None, print_keyframes=False):
|
||||
@classmethod
|
||||
def execute(cls, mults_float: Union[float, list[float]], start_percent: float, end_percent: float, inherit_missing=True, prev_kf: NaiveReuseKeyframeGroup=None, mult_multival=None, print_keyframes=False):
|
||||
if prev_kf is None:
|
||||
prev_kf = NaiveReuseKeyframeGroup()
|
||||
prev_kf = prev_kf.clone()
|
||||
@@ -200,192 +92,85 @@ class NaiveReuse_KeyframeFromListNode:
|
||||
elif isinstance(mults_float, Iterable):
|
||||
pass
|
||||
else:
|
||||
raise Exception(f"strengths_float must be either an interable input or a float, but was {type(mults_float).__repr__}.")
|
||||
raise Exception(f'strengths_float must be either an interable input or a float, but was {type(mults_float).__repr__}.')
|
||||
percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=len(mults_float), method=InterpolationMethod.LINEAR)
|
||||
|
||||
is_first = True
|
||||
for percent, mult in zip(percents, mults_float):
|
||||
guarantee_steps = 0
|
||||
if is_first:
|
||||
guarantee_steps = 1
|
||||
is_first = False
|
||||
prev_kf.add(NaiveReuseKeyframe(mult=mult, mult_multival=mult_multival,
|
||||
start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
prev_kf.add(NaiveReuseKeyframe(mult=mult, mult_multival=mult_multival, start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
if print_keyframes:
|
||||
logger.info(f"NaiveReuseKeyframe - start_percent:{percent} = {mult}")
|
||||
return (prev_kf,)
|
||||
#----------------------------------------
|
||||
#########################################
|
||||
logger.info(f'NaiveReuseKeyframe - start_percent:{percent} = {mult}')
|
||||
return io.NodeOutput(prev_kf)
|
||||
|
||||
class ContextExtras_ContextRef(io.ComfyNode):
|
||||
|
||||
#########################################
|
||||
# ContextRef
|
||||
class ContextExtras_ContextRef:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"prev_extras": ("CONTEXT_EXTRAS",),
|
||||
"strength_multival": ("MULTIVAL",),
|
||||
"contextref_mode": ("CONTEXTREF_MODE",),
|
||||
"contextref_tune": ("CONTEXTREF_TUNE",),
|
||||
"contextref_kf": ("CONTEXTREF_KEYFRAME",),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 0.25, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXT_EXTRAS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras"
|
||||
FUNCTION = "create_context_extra"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef', display_name='Context Extras◆ContextRef 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras', inputs=[io.Custom('CONTEXT_EXTRAS').Input('prev_extras', optional=True), io.Custom('MULTIVAL').Input('strength_multival', optional=True), io.Custom('CONTEXTREF_MODE').Input('contextref_mode', optional=True), io.Custom('CONTEXTREF_TUNE').Input('contextref_tune', optional=True), io.Custom('CONTEXTREF_KEYFRAME').Input('contextref_kf', optional=True), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', optional=True, default=0.25, max=1.0, min=0.0, step=0.001)], outputs=[io.Custom('CONTEXT_EXTRAS').Output('CONTEXT_EXTRAS')])
|
||||
|
||||
def create_context_extra(self, start_percent=0.0, end_percent=0.1, strength_multival: Union[float, Tensor]=None,
|
||||
contextref_mode: ContextRefMode=None, contextref_tune: ContextRefTune=None,
|
||||
contextref_kf: ContextRefKeyframeGroup=None, prev_extras: ContextExtrasGroup=None):
|
||||
@classmethod
|
||||
def execute(cls, start_percent=0.0, end_percent=0.1, strength_multival: Union[float, Tensor]=None, contextref_mode: ContextRefMode=None, contextref_tune: ContextRefTune=None, contextref_kf: ContextRefKeyframeGroup=None, prev_extras: ContextExtrasGroup=None):
|
||||
if prev_extras is None:
|
||||
prev_extras = prev_extras = ContextExtrasGroup()
|
||||
prev_extras = prev_extras.clone()
|
||||
# create extra
|
||||
# TODO: make customizable, and allow mask input
|
||||
if contextref_tune is None:
|
||||
contextref_tune = ContextRefTune(attn_style_fidelity=1.0, attn_ref_weight=1.0, attn_strength=1.0)
|
||||
if contextref_mode is None:
|
||||
contextref_mode = ContextRefMode.init_first()
|
||||
context_ref = ContextRef(start_percent=start_percent, end_percent=end_percent,
|
||||
strength_multival=strength_multival, tune=contextref_tune, mode=contextref_mode,
|
||||
keyframe=contextref_kf)
|
||||
context_ref = ContextRef(start_percent=start_percent, end_percent=end_percent, strength_multival=strength_multival, tune=contextref_tune, mode=contextref_mode, keyframe=contextref_kf)
|
||||
prev_extras.add(context_ref)
|
||||
return (prev_extras,)
|
||||
return io.NodeOutput(prev_extras)
|
||||
|
||||
class ContextRef_KeyframeMultivalNode(io.ComfyNode):
|
||||
|
||||
class ContextRef_KeyframeMultivalNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"prev_kf": ("CONTEXTREF_KEYFRAME",),
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
"mode_replace": ("CONTEXTREF_MODE",),
|
||||
"tune_replace": ("CONTEXTREF_TUNE",),
|
||||
"mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}, ),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_KEYFRAME",)
|
||||
RETURN_NAMES = ("CONTEXTREF_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_keyframe"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_Keyframe', display_name='ContextRef Keyframe 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[io.Custom('CONTEXTREF_KEYFRAME').Input('prev_kf', optional=True), io.Custom('MULTIVAL').Input('mult_multival', optional=True), io.Custom('CONTEXTREF_MODE').Input('mode_replace', optional=True), io.Custom('CONTEXTREF_TUNE').Input('tune_replace', optional=True), io.Float.Input('mult', optional=True, default=1.0, max=1.0, min=0.0, step=0.001), io.Float.Input('start_percent', optional=True, default=0.0, max=1.0, min=0.0, step=0.001), io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0), io.Boolean.Input('inherit_missing', optional=True, default=True)], outputs=[io.Custom('CONTEXTREF_KEYFRAME').Output('CONTEXTREF_KF')])
|
||||
|
||||
def create_keyframe(self, prev_kf: ContextRefKeyframeGroup=None,
|
||||
mult=1.0, mult_multival=None, mode_replace=None, tune_replace=None,
|
||||
start_percent=1.0, guarantee_steps=1, inherit_missing=True):
|
||||
@classmethod
|
||||
def execute(cls, prev_kf: ContextRefKeyframeGroup=None, mult=1.0, mult_multival=None, mode_replace=None, tune_replace=None, start_percent=1.0, guarantee_steps=1, inherit_missing=True):
|
||||
if prev_kf is None:
|
||||
prev_kf = ContextRefKeyframeGroup()
|
||||
prev_kf = prev_kf.clone()
|
||||
kf = ContextRefKeyframe(mult=mult, mult_multival=mult_multival, tune_replace=tune_replace, mode_replace=mode_replace,
|
||||
start_percent=start_percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing)
|
||||
kf = ContextRefKeyframe(mult=mult, mult_multival=mult_multival, tune_replace=tune_replace, mode_replace=mode_replace, start_percent=start_percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing)
|
||||
prev_kf.add(kf)
|
||||
return (prev_kf,)
|
||||
return io.NodeOutput(prev_kf)
|
||||
|
||||
class ContextRef_KeyframeInterpolationNode(io.ComfyNode):
|
||||
|
||||
class ContextRef_KeyframeInterpolationNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"mult_start": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"mult_end": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"interpolation": (InterpolationMethod._LIST, ),
|
||||
"intervals": ("INT", {"default": 50, "min": 2, "max": 100, "step": 1}),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}),
|
||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_kf": ("CONTEXTREF_KEYFRAME",),
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
"mode_replace": ("CONTEXTREF_MODE",),
|
||||
"tune_replace": ("CONTEXTREF_TUNE",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_KEYFRAME",)
|
||||
RETURN_NAMES = ("CONTEXTREF_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_keyframe"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_KeyframeInterpolation', display_name='ContextRef Keyframes Interp. 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001), io.Float.Input('mult_start', default=1.0, max=1.0, min=0.0, step=0.001), io.Float.Input('mult_end', default=1.0, max=1.0, min=0.0, step=0.001), io.Combo.Input('interpolation', options=['linear', 'ease_in', 'ease_out', 'ease_in_out']), io.Int.Input('intervals', default=50, max=100, min=2, step=1), io.Boolean.Input('inherit_missing', default=True), io.Boolean.Input('print_keyframes', default=False), io.Custom('CONTEXTREF_KEYFRAME').Input('prev_kf', optional=True), io.Custom('MULTIVAL').Input('mult_multival', optional=True), io.Custom('CONTEXTREF_MODE').Input('mode_replace', optional=True), io.Custom('CONTEXTREF_TUNE').Input('tune_replace', optional=True)], outputs=[io.Custom('CONTEXTREF_KEYFRAME').Output('CONTEXTREF_KF')])
|
||||
|
||||
def create_keyframe(self,
|
||||
start_percent: float, end_percent: float,
|
||||
mult_start: float, mult_end: float, interpolation: str, intervals: int,
|
||||
inherit_missing=True, prev_kf: ContextRefKeyframeGroup=None,
|
||||
mult_multival=None, mode_replace=None, tune_replace=None, print_keyframes=False):
|
||||
@classmethod
|
||||
def execute(cls, start_percent: float, end_percent: float, mult_start: float, mult_end: float, interpolation: str, intervals: int, inherit_missing=True, prev_kf: ContextRefKeyframeGroup=None, mult_multival=None, mode_replace=None, tune_replace=None, print_keyframes=False):
|
||||
if prev_kf is None:
|
||||
prev_kf = ContextRefKeyframeGroup()
|
||||
prev_kf = prev_kf.clone()
|
||||
percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=intervals, method=InterpolationMethod.LINEAR)
|
||||
mults = InterpolationMethod.get_weights(num_from=mult_start, num_to=mult_end, length=intervals, method=interpolation)
|
||||
|
||||
is_first = True
|
||||
for percent, mult in zip(percents, mults):
|
||||
guarantee_steps = 0
|
||||
if is_first:
|
||||
guarantee_steps = 1
|
||||
is_first = False
|
||||
prev_kf.add(ContextRefKeyframe(mult=mult, mult_multival=mult_multival, tune_replace=tune_replace, mode_replace=mode_replace,
|
||||
start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
prev_kf.add(ContextRefKeyframe(mult=mult, mult_multival=mult_multival, tune_replace=tune_replace, mode_replace=mode_replace, start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
if print_keyframes:
|
||||
logger.info(f"ContextRefKeyframe - start_percent:{percent} = {mult}")
|
||||
return (prev_kf,)
|
||||
logger.info(f'ContextRefKeyframe - start_percent:{percent} = {mult}')
|
||||
return io.NodeOutput(prev_kf)
|
||||
|
||||
class ContextRef_KeyframeFromListNode(io.ComfyNode):
|
||||
|
||||
class ContextRef_KeyframeFromListNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"mults_float": ("FLOAT", {"default": -1, "min": -1, "step": 0.001, "forceInput": True}),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}),
|
||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_kf": ("CONTEXTREF_KEYFRAME",),
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
"mode_replace": ("CONTEXTREF_MODE",),
|
||||
"tune_replace": ("CONTEXTREF_TUNE",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_KEYFRAME",)
|
||||
RETURN_NAMES = ("CONTEXTREF_KF",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_keyframe"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_KeyframeFromList', display_name='ContextRef Keyframes From List 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[io.Float.Input('mults_float', default=-1, force_input=True, min=-1, step=0.001), io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001), io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001), io.Boolean.Input('inherit_missing', default=True), io.Boolean.Input('print_keyframes', default=False), io.Custom('CONTEXTREF_KEYFRAME').Input('prev_kf', optional=True), io.Custom('MULTIVAL').Input('mult_multival', optional=True), io.Custom('CONTEXTREF_MODE').Input('mode_replace', optional=True), io.Custom('CONTEXTREF_TUNE').Input('tune_replace', optional=True)], outputs=[io.Custom('CONTEXTREF_KEYFRAME').Output('CONTEXTREF_KF')])
|
||||
|
||||
def create_keyframe(self, mults_float: Union[float, list[float]],
|
||||
start_percent: float, end_percent: float,
|
||||
inherit_missing=True, prev_kf: ContextRefKeyframeGroup=None,
|
||||
mult_multival=None, mode_replace=None, tune_replace=None, print_keyframes=False):
|
||||
@classmethod
|
||||
def execute(cls, mults_float: Union[float, list[float]], start_percent: float, end_percent: float, inherit_missing=True, prev_kf: ContextRefKeyframeGroup=None, mult_multival=None, mode_replace=None, tune_replace=None, print_keyframes=False):
|
||||
if prev_kf is None:
|
||||
prev_kf = ContextRefKeyframeGroup()
|
||||
prev_kf = prev_kf.clone()
|
||||
@@ -394,146 +179,73 @@ class ContextRef_KeyframeFromListNode:
|
||||
elif isinstance(mults_float, Iterable):
|
||||
pass
|
||||
else:
|
||||
raise Exception(f"strengths_float must be either an interable input or a float, but was {type(mults_float).__repr__}.")
|
||||
raise Exception(f'strengths_float must be either an interable input or a float, but was {type(mults_float).__repr__}.')
|
||||
percents = InterpolationMethod.get_weights(num_from=start_percent, num_to=end_percent, length=len(mults_float), method=InterpolationMethod.LINEAR)
|
||||
|
||||
is_first = True
|
||||
for percent, mult in zip(percents, mults_float):
|
||||
guarantee_steps = 0
|
||||
if is_first:
|
||||
guarantee_steps = 1
|
||||
is_first = False
|
||||
prev_kf.add(ContextRefKeyframe(mult=mult, mult_multival=mult_multival, tune_replace=tune_replace, mode_replace=mode_replace,
|
||||
start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
prev_kf.add(ContextRefKeyframe(mult=mult, mult_multival=mult_multival, tune_replace=tune_replace, mode_replace=mode_replace, start_percent=percent, guarantee_steps=guarantee_steps, inherit_missing=inherit_missing))
|
||||
if print_keyframes:
|
||||
logger.info(f"ContextRefKeyframe - start_percent:{percent} = {mult}")
|
||||
return (prev_kf,)
|
||||
logger.info(f'ContextRefKeyframe - start_percent:{percent} = {mult}')
|
||||
return io.NodeOutput(prev_kf)
|
||||
|
||||
class ContextRef_ModeFirst(io.ComfyNode):
|
||||
|
||||
class ContextRef_ModeFirst:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_MODE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_contextref_mode"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_ModeFirst', display_name='ContextRef Mode◆First 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[], outputs=[io.Custom('CONTEXTREF_MODE').Output('CONTEXTREF_MODE')])
|
||||
|
||||
def create_contextref_mode(self):
|
||||
@classmethod
|
||||
def execute(cls):
|
||||
mode = ContextRefMode.init_first()
|
||||
return (mode,)
|
||||
return io.NodeOutput(mode)
|
||||
|
||||
class ContextRef_ModeSliding(io.ComfyNode):
|
||||
|
||||
class ContextRef_ModeSliding:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"sliding_width": ("INT", {"default": 2, "min": 2, "max": BIGMAX, "step": 1}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_MODE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_contextref_mode"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_ModeSliding', display_name='ContextRef Mode◆Sliding 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[io.Int.Input('sliding_width', optional=True, default=2, max=9007199254740991, min=2, step=1)], outputs=[io.Custom('CONTEXTREF_MODE').Output('CONTEXTREF_MODE')])
|
||||
|
||||
def create_contextref_mode(self, sliding_width):
|
||||
@classmethod
|
||||
def execute(cls, sliding_width):
|
||||
mode = ContextRefMode.init_sliding(sliding_width=sliding_width)
|
||||
return (mode,)
|
||||
return io.NodeOutput(mode)
|
||||
|
||||
class ContextRef_ModeIndexes(io.ComfyNode):
|
||||
|
||||
class ContextRef_ModeIndexes:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"switch_on_idxs": ("STRING", {"default": ""}),
|
||||
"always_include_0": ("BOOLEAN", {"default": True},),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_MODE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_contextref_mode"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_ModeIndexes', display_name='ContextRef Mode◆Indexes 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[io.String.Input('switch_on_idxs', optional=True, default=''), io.Boolean.Input('always_include_0', optional=True, default=True)], outputs=[io.Custom('CONTEXTREF_MODE').Output('CONTEXTREF_MODE')])
|
||||
|
||||
def create_contextref_mode(self, switch_on_idxs: str, always_include_0: bool):
|
||||
@classmethod
|
||||
def execute(cls, switch_on_idxs: str, always_include_0: bool):
|
||||
idxs = set(convert_str_to_indexes(indexes_str=switch_on_idxs, length=0, allow_range=False))
|
||||
if always_include_0 and 0 not in idxs:
|
||||
idxs.add(0)
|
||||
mode = ContextRefMode.init_indexes(indexes=idxs)
|
||||
return (mode,)
|
||||
return io.NodeOutput(mode)
|
||||
|
||||
class ContextRef_TuneAttnAdain(io.ComfyNode):
|
||||
|
||||
class ContextRef_TuneAttnAdain:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"attn_style_fidelity": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"attn_ref_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"attn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"adain_style_fidelity": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"adain_ref_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"adain_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_TUNE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_contextref_tune"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_TuneAttnAdain', display_name='ContextRef Tune◆Attn+Adain 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[io.Float.Input('attn_style_fidelity', optional=True, default=1.0, max=1.0, min=0.0, step=0.01), io.Float.Input('attn_ref_weight', optional=True, default=1.0, max=1.0, min=0.0, step=0.01), io.Float.Input('attn_strength', optional=True, default=1.0, max=1.0, min=0.0, step=0.01), io.Float.Input('adain_style_fidelity', optional=True, default=1.0, max=1.0, min=0.0, step=0.01), io.Float.Input('adain_ref_weight', optional=True, default=1.0, max=1.0, min=0.0, step=0.01), io.Float.Input('adain_strength', optional=True, default=1.0, max=1.0, min=0.0, step=0.01)], outputs=[io.Custom('CONTEXTREF_TUNE').Output('CONTEXTREF_TUNE')])
|
||||
|
||||
def create_contextref_tune(self, attn_style_fidelity=1.0, attn_ref_weight=1.0, attn_strength=1.0,
|
||||
adain_style_fidelity=1.0, adain_ref_weight=1.0, adain_strength=1.0):
|
||||
params = ContextRefTune(attn_style_fidelity=attn_style_fidelity, adain_style_fidelity=adain_style_fidelity,
|
||||
attn_ref_weight=attn_ref_weight, adain_ref_weight=adain_ref_weight,
|
||||
attn_strength=attn_strength, adain_strength=adain_strength)
|
||||
return (params,)
|
||||
|
||||
|
||||
class ContextRef_TuneAttn:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"attn_style_fidelity": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"attn_ref_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"attn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONTEXTREF_TUNE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/context opts/context extras/contextref"
|
||||
FUNCTION = "create_contextref_tune"
|
||||
def execute(cls, attn_style_fidelity=1.0, attn_ref_weight=1.0, attn_strength=1.0, adain_style_fidelity=1.0, adain_ref_weight=1.0, adain_strength=1.0):
|
||||
params = ContextRefTune(attn_style_fidelity=attn_style_fidelity, adain_style_fidelity=adain_style_fidelity, attn_ref_weight=attn_ref_weight, adain_ref_weight=adain_ref_weight, attn_strength=attn_strength, adain_strength=adain_strength)
|
||||
return io.NodeOutput(params)
|
||||
|
||||
def create_contextref_tune(self, attn_style_fidelity=1.0, attn_ref_weight=1.0, attn_strength=1.0):
|
||||
return ContextRef_TuneAttnAdain.create_contextref_tune(self,
|
||||
attn_style_fidelity=attn_style_fidelity, attn_ref_weight=attn_ref_weight, attn_strength=attn_strength,
|
||||
adain_ref_weight=0.0, adain_style_fidelity=0.0, adain_strength=0.0)
|
||||
#----------------------------------------
|
||||
#########################################
|
||||
class ContextRef_TuneAttn(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_ContextExtras_ContextRef_TuneAttn', display_name='ContextRef Tune◆Attn 🎭🅐🅓', category='Animate Diff 🎭🅐🅓/context opts/context extras/contextref', inputs=[io.Float.Input('attn_style_fidelity', optional=True, default=1.0, max=1.0, min=0.0, step=0.01), io.Float.Input('attn_ref_weight', optional=True, default=1.0, max=1.0, min=0.0, step=0.01), io.Float.Input('attn_strength', optional=True, default=1.0, max=1.0, min=0.0, step=0.01)], outputs=[io.Custom('CONTEXTREF_TUNE').Output('CONTEXTREF_TUNE')])
|
||||
|
||||
@classmethod
|
||||
def execute(cls, attn_style_fidelity=1.0, attn_ref_weight=1.0, attn_strength=1.0):
|
||||
output = ContextRef_TuneAttnAdain.execute(attn_style_fidelity=attn_style_fidelity, attn_ref_weight=attn_ref_weight, attn_strength=attn_strength, adain_ref_weight=0.0, adain_style_fidelity=0.0, adain_strength=0.0)
|
||||
return io.NodeOutput(*output.args)
|
||||
|
||||
+105
-448
@@ -1,565 +1,222 @@
|
||||
from comfy_api.latest import io
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
from typing import Dict, List
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
from PIL import Image
|
||||
from PIL.PngImagePlugin import PngInfo
|
||||
|
||||
import folder_paths
|
||||
from comfy.model_patcher import ModelPatcher
|
||||
|
||||
from .ad_settings import AnimateDiffSettings, AdjustGroup, AdjustPE, AdjustWeight
|
||||
from .context import ContextOptionsGroup, ContextOptions, ContextSchedules
|
||||
from .logger import logger
|
||||
from .utils_model import Folders, BetaSchedules, get_available_motion_models
|
||||
from .utils_motion import ADKeyframeGroup
|
||||
from .motion_lora import MotionLoraList
|
||||
from .model_injection import (ModelPatcherHelper, InjectionParams, MotionModelGroup, get_mm_attachment, load_motion_module_gen1)
|
||||
from .model_injection import ModelPatcherHelper, InjectionParams, MotionModelGroup, get_mm_attachment, load_motion_module_gen1
|
||||
from .sampling import outer_sample_wrapper, sliding_calc_cond_batch
|
||||
from .sample_settings import SampleSettings
|
||||
|
||||
class AnimateDiffLoaderDEPR(io.ComfyNode):
|
||||
|
||||
class AnimateDiffLoaderDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"latents": ("LATENT",),
|
||||
"model_name": (get_available_motion_models(),),
|
||||
"unlimited_area_hack": ("BOOLEAN", {"default": False},),
|
||||
"beta_schedule": (BetaSchedules.get_alias_list_with_first_element(BetaSchedules.SQRT_LINEAR),),
|
||||
},
|
||||
"optional": {"deprecation_warning": ("ADEWARN", {"text": "Deprecated"})},
|
||||
}
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='AnimateDiffLoaderV1', display_name='🚫AnimateDiff Loader [DEPRECATED] 🎭🅐🅓', category='', inputs=[io.Model.Input('model'), io.Custom('LATENT').Input('latents'), io.Combo.Input('model_name', options=get_available_motion_models()), io.Boolean.Input('unlimited_area_hack', default=False), io.Combo.Input('beta_schedule', options=['sqrt_linear (AnimateDiff)', 'use existing', 'autoselect', 'linear (AnimateDiff-SDXL)', 'linear (HotshotXL/default)', 'avg(sqrt_linear,linear)', 'lcm avg(sqrt_linear,linear)', 'lcm', 'lcm[100_ots]', 'lcm >> sqrt_linear', 'sqrt', 'cosine', 'squaredcos_cap_v2'])], outputs=[io.Model.Output('MODEL'), io.Custom('LATENT').Output('LATENT')], is_deprecated=True)
|
||||
|
||||
RETURN_TYPES = ("MODEL", "LATENT")
|
||||
CATEGORY = ""
|
||||
FUNCTION = "load_mm_and_inject_params"
|
||||
DEPRECATED = True
|
||||
|
||||
def load_mm_and_inject_params(
|
||||
self,
|
||||
model: ModelPatcher,
|
||||
latents: Dict[str, torch.Tensor],
|
||||
model_name: str, unlimited_area_hack: bool, beta_schedule: str,
|
||||
):
|
||||
# load motion module
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, latents: Dict[str, torch.Tensor], model_name: str, unlimited_area_hack: bool, beta_schedule: str):
|
||||
motion_model = load_motion_module_gen1(model_name, model)
|
||||
# get total frames
|
||||
init_frames_len = len(latents["samples"]) # deprecated - no longer used for anything lol
|
||||
# set injection params
|
||||
params = InjectionParams(
|
||||
unlimited_area_hack=unlimited_area_hack,
|
||||
apply_v2_properly=False,
|
||||
)
|
||||
# inject for use in sampling code
|
||||
init_frames_len = len(latents['samples'])
|
||||
params = InjectionParams(unlimited_area_hack=unlimited_area_hack, apply_v2_properly=False)
|
||||
model = model.clone()
|
||||
helper = ModelPatcherHelper(model)
|
||||
helper.set_all_properties(
|
||||
outer_sampler_wrapper=outer_sample_wrapper,
|
||||
calc_cond_batch_wrapper=sliding_calc_cond_batch,
|
||||
params=params,
|
||||
motion_models=MotionModelGroup(motion_model),
|
||||
)
|
||||
|
||||
# save model sampling from BetaSchedule as object patch
|
||||
# if autoselect, get suggested beta_schedule from motion model
|
||||
if beta_schedule == BetaSchedules.AUTOSELECT and not model.motion_models.is_empty():
|
||||
helper.set_all_properties(outer_sampler_wrapper=outer_sample_wrapper, calc_cond_batch_wrapper=sliding_calc_cond_batch, params=params, motion_models=MotionModelGroup(motion_model))
|
||||
if beta_schedule == BetaSchedules.AUTOSELECT and (not model.motion_models.is_empty()):
|
||||
beta_schedule = model.motion_models[0].model.get_best_beta_schedule(log=True)
|
||||
new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model)
|
||||
if new_model_sampling is not None:
|
||||
model.add_object_patch("model_sampling", new_model_sampling)
|
||||
|
||||
model.add_object_patch('model_sampling', new_model_sampling)
|
||||
del motion_model
|
||||
return (model, latents)
|
||||
return io.NodeOutput(model, latents)
|
||||
|
||||
class AnimateDiffLoaderAdvancedDEPR(io.ComfyNode):
|
||||
|
||||
class AnimateDiffLoaderAdvancedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"latents": ("LATENT",),
|
||||
"model_name": (get_available_motion_models(),),
|
||||
"unlimited_area_hack": ("BOOLEAN", {"default": False},),
|
||||
"context_length": ("INT", {"default": 16, "min": 0, "max": 1000}),
|
||||
"context_stride": ("INT", {"default": 1, "min": 1, "max": 1000}),
|
||||
"context_overlap": ("INT", {"default": 4, "min": 0, "max": 1000}),
|
||||
"context_schedule": (ContextSchedules.LEGACY_UNIFORM_SCHEDULE_LIST,),
|
||||
"closed_loop": ("BOOLEAN", {"default": False},),
|
||||
"beta_schedule": (BetaSchedules.get_alias_list_with_first_element(BetaSchedules.SQRT_LINEAR),),
|
||||
},
|
||||
"optional": {"deprecation_warning": ("ADEWARN", {"text": "Deprecated"})},
|
||||
}
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffLoaderV1Advanced', display_name='🚫AnimateDiff Loader (Advanced) [DEPRECATED] 🎭🅐🅓', category='', inputs=[io.Model.Input('model'), io.Custom('LATENT').Input('latents'), io.Combo.Input('model_name', options=get_available_motion_models()), io.Boolean.Input('unlimited_area_hack', default=False), io.Int.Input('context_length', default=16, max=1000, min=0), io.Int.Input('context_stride', default=1, max=1000, min=1), io.Int.Input('context_overlap', default=4, max=1000, min=0), io.Combo.Input('context_schedule', options=['uniform']), io.Boolean.Input('closed_loop', default=False), io.Combo.Input('beta_schedule', options=['sqrt_linear (AnimateDiff)', 'use existing', 'autoselect', 'linear (AnimateDiff-SDXL)', 'linear (HotshotXL/default)', 'avg(sqrt_linear,linear)', 'lcm avg(sqrt_linear,linear)', 'lcm', 'lcm[100_ots]', 'lcm >> sqrt_linear', 'sqrt', 'cosine', 'squaredcos_cap_v2'])], outputs=[io.Model.Output('MODEL'), io.Custom('LATENT').Output('LATENT')], is_deprecated=True)
|
||||
|
||||
RETURN_TYPES = ("MODEL", "LATENT")
|
||||
CATEGORY = ""
|
||||
FUNCTION = "load_mm_and_inject_params"
|
||||
DEPRECATED = True
|
||||
|
||||
def load_mm_and_inject_params(self,
|
||||
model: ModelPatcher,
|
||||
latents: Dict[str, torch.Tensor],
|
||||
model_name: str, unlimited_area_hack: bool,
|
||||
context_length: int, context_stride: int, context_overlap: int, context_schedule: str, closed_loop: bool,
|
||||
beta_schedule: str,
|
||||
):
|
||||
# load motion module
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, latents: Dict[str, torch.Tensor], model_name: str, unlimited_area_hack: bool, context_length: int, context_stride: int, context_overlap: int, context_schedule: str, closed_loop: bool, beta_schedule: str):
|
||||
motion_model = load_motion_module_gen1(model_name, model)
|
||||
# get total frames
|
||||
init_frames_len = len(latents["samples"]) # deprecated - no longer used for anything lol
|
||||
# set injection params
|
||||
params = InjectionParams(
|
||||
unlimited_area_hack=unlimited_area_hack,
|
||||
apply_v2_properly=False,
|
||||
)
|
||||
init_frames_len = len(latents['samples'])
|
||||
params = InjectionParams(unlimited_area_hack=unlimited_area_hack, apply_v2_properly=False)
|
||||
context_group = ContextOptionsGroup()
|
||||
context_group.add(
|
||||
ContextOptions(
|
||||
context_length=context_length,
|
||||
context_stride=context_stride,
|
||||
context_overlap=context_overlap,
|
||||
context_schedule=context_schedule,
|
||||
closed_loop=closed_loop,
|
||||
)
|
||||
)
|
||||
# set context settings
|
||||
context_group.add(ContextOptions(context_length=context_length, context_stride=context_stride, context_overlap=context_overlap, context_schedule=context_schedule, closed_loop=closed_loop))
|
||||
params.set_context(context_options=context_group)
|
||||
# inject for use in sampling code
|
||||
model = model.clone()
|
||||
helper = ModelPatcherHelper(model)
|
||||
helper.set_all_properties(
|
||||
outer_sampler_wrapper=outer_sample_wrapper,
|
||||
calc_cond_batch_wrapper=sliding_calc_cond_batch,
|
||||
params=params,
|
||||
motion_models=MotionModelGroup(motion_model),
|
||||
)
|
||||
|
||||
# save model sampling from BetaSchedule as object patch
|
||||
# if autoselect, get suggested beta_schedule from motion model
|
||||
if beta_schedule == BetaSchedules.AUTOSELECT and not model.motion_models.is_empty():
|
||||
helper.set_all_properties(outer_sampler_wrapper=outer_sample_wrapper, calc_cond_batch_wrapper=sliding_calc_cond_batch, params=params, motion_models=MotionModelGroup(motion_model))
|
||||
if beta_schedule == BetaSchedules.AUTOSELECT and (not model.motion_models.is_empty()):
|
||||
beta_schedule = model.motion_models[0].model.get_best_beta_schedule(log=True)
|
||||
new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model)
|
||||
if new_model_sampling is not None:
|
||||
model.add_object_patch("model_sampling", new_model_sampling)
|
||||
|
||||
model.add_object_patch('model_sampling', new_model_sampling)
|
||||
del motion_model
|
||||
return (model, latents)
|
||||
return io.NodeOutput(model, latents)
|
||||
|
||||
class LegacyAnimateDiffLoaderWithContextDEPR(io.ComfyNode):
|
||||
|
||||
class LegacyAnimateDiffLoaderWithContextDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"model_name": (get_available_motion_models(),),
|
||||
"beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.AUTOSELECT}),
|
||||
#"apply_mm_groupnorm_hack": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {
|
||||
"context_options": ("CONTEXT_OPTIONS",),
|
||||
"motion_lora": ("MOTION_LORA",),
|
||||
"ad_settings": ("AD_SETTINGS",),
|
||||
"sample_settings": ("SAMPLE_SETTINGS",),
|
||||
"motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"apply_v2_models_properly": ("BOOLEAN", {"default": True}),
|
||||
"ad_keyframes": ("AD_KEYFRAMES",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated; use AnimateDiff Loader instead."}),
|
||||
}
|
||||
}
|
||||
|
||||
DEPRECATED = True
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/① Gen1 nodes ①"
|
||||
FUNCTION = "load_mm_and_inject_params"
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffLoaderWithContext', display_name='AnimateDiff Loader [Legacy] 🎭🅐🅓①', category='Animate Diff 🎭🅐🅓/① Gen1 nodes ①', inputs=[io.Model.Input('model'), io.Combo.Input('model_name', options=get_available_motion_models()), io.Combo.Input('beta_schedule', options=['autoselect', 'use existing', 'sqrt_linear (AnimateDiff)', 'linear (AnimateDiff-SDXL)', 'linear (HotshotXL/default)', 'avg(sqrt_linear,linear)', 'lcm avg(sqrt_linear,linear)', 'lcm', 'lcm[100_ots]', 'lcm >> sqrt_linear', 'sqrt', 'cosine', 'squaredcos_cap_v2'], default='autoselect'), io.Custom('CONTEXT_OPTIONS').Input('context_options', optional=True), io.Custom('MOTION_LORA').Input('motion_lora', optional=True), io.Custom('AD_SETTINGS').Input('ad_settings', optional=True), io.Custom('SAMPLE_SETTINGS').Input('sample_settings', optional=True), io.Float.Input('motion_scale', optional=True, default=1.0, min=0.0, step=0.001), io.Boolean.Input('apply_v2_models_properly', optional=True, default=True), io.Custom('AD_KEYFRAMES').Input('ad_keyframes', optional=True)], outputs=[io.Model.Output('MODEL')], is_deprecated=True)
|
||||
|
||||
def load_mm_and_inject_params(self,
|
||||
model: ModelPatcher,
|
||||
model_name: str, beta_schedule: str,# apply_mm_groupnorm_hack: bool,
|
||||
context_options: ContextOptionsGroup=None, motion_lora: MotionLoraList=None, ad_settings: AnimateDiffSettings=None, motion_model_settings: AnimateDiffSettings=None,
|
||||
sample_settings: SampleSettings=None, motion_scale: float=1.0, apply_v2_models_properly: bool=False, ad_keyframes: ADKeyframeGroup=None,
|
||||
):
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, model_name: str, beta_schedule: str, context_options: ContextOptionsGroup=None, motion_lora: MotionLoraList=None, ad_settings: AnimateDiffSettings=None, motion_model_settings: AnimateDiffSettings=None, sample_settings: SampleSettings=None, motion_scale: float=1.0, apply_v2_models_properly: bool=False, ad_keyframes: ADKeyframeGroup=None):
|
||||
if ad_settings is not None:
|
||||
motion_model_settings = ad_settings
|
||||
# load motion module
|
||||
motion_model = load_motion_module_gen1(model_name, model, motion_lora=motion_lora, motion_model_settings=motion_model_settings)
|
||||
# set injection params
|
||||
params = InjectionParams(
|
||||
unlimited_area_hack=False,
|
||||
apply_v2_properly=apply_v2_models_properly,
|
||||
)
|
||||
params = InjectionParams(unlimited_area_hack=False, apply_v2_properly=apply_v2_models_properly)
|
||||
if context_options:
|
||||
params.set_context(context_options)
|
||||
# set motion_scale and motion_model_settings
|
||||
if not motion_model_settings:
|
||||
motion_model_settings = AnimateDiffSettings()
|
||||
motion_model_settings.attn_scale = motion_scale
|
||||
params.set_motion_model_settings(motion_model_settings)
|
||||
|
||||
attachment = get_mm_attachment(motion_model)
|
||||
if params.motion_model_settings.mask_attn_scale is not None:
|
||||
attachment.scale_multival = params.motion_model_settings.mask_attn_scale * params.motion_model_settings.attn_scale
|
||||
else:
|
||||
attachment.scale_multival = params.motion_model_settings.attn_scale
|
||||
|
||||
attachment.keyframes = ad_keyframes.clone() if ad_keyframes else ADKeyframeGroup()
|
||||
|
||||
# need to use a ModelPatcher that supports injection of motion modules into unet
|
||||
model = model.clone()
|
||||
helper = ModelPatcherHelper(model)
|
||||
helper.set_all_properties(
|
||||
outer_sampler_wrapper=outer_sample_wrapper,
|
||||
calc_cond_batch_wrapper=sliding_calc_cond_batch,
|
||||
params=params,
|
||||
sample_settings=sample_settings,
|
||||
motion_models=MotionModelGroup(motion_model),
|
||||
)
|
||||
|
||||
helper.set_all_properties(outer_sampler_wrapper=outer_sample_wrapper, calc_cond_batch_wrapper=sliding_calc_cond_batch, params=params, sample_settings=sample_settings, motion_models=MotionModelGroup(motion_model))
|
||||
sample_settings = helper.get_sample_settings()
|
||||
if sample_settings.custom_cfg is not None:
|
||||
logger.info("[Sample Settings] custom_cfg is set; will override any KSampler cfg values or patches.")
|
||||
|
||||
logger.info('[Sample Settings] custom_cfg is set; will override any KSampler cfg values or patches.')
|
||||
if sample_settings.sigma_schedule is not None:
|
||||
logger.info("[Sample Settings] sigma_schedule is set; will override beta_schedule.")
|
||||
model.add_object_patch("model_sampling", sample_settings.sigma_schedule.clone().model_sampling)
|
||||
logger.info('[Sample Settings] sigma_schedule is set; will override beta_schedule.')
|
||||
model.add_object_patch('model_sampling', sample_settings.sigma_schedule.clone().model_sampling)
|
||||
else:
|
||||
# save model sampling from BetaSchedule as object patch
|
||||
# if autoselect, get suggested beta_schedule from motion model
|
||||
if beta_schedule == BetaSchedules.AUTOSELECT and helper.get_motion_models():
|
||||
beta_schedule = helper.get_motion_models()[0].model.get_best_beta_schedule(log=True)
|
||||
new_model_sampling = BetaSchedules.to_model_sampling(beta_schedule, model)
|
||||
if new_model_sampling is not None:
|
||||
model.add_object_patch("model_sampling", new_model_sampling)
|
||||
|
||||
model.add_object_patch('model_sampling', new_model_sampling)
|
||||
del motion_model
|
||||
return (model,)
|
||||
return io.NodeOutput(model)
|
||||
|
||||
class AnimateDiffCombineDEPR(io.ComfyNode):
|
||||
|
||||
class AnimateDiffCombineDEPR:
|
||||
ffmpeg_warning_already_shown = False
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
ffmpeg_path = shutil.which("ffmpeg")
|
||||
#Hide ffmpeg formats if ffmpeg isn't available
|
||||
def get_formats(cls):
|
||||
ffmpeg_path = shutil.which('ffmpeg')
|
||||
if ffmpeg_path is not None:
|
||||
ffmpeg_formats = ["video/"+x[:-5] for x in folder_paths.get_filename_list(Folders.VIDEO_FORMATS)]
|
||||
else:
|
||||
ffmpeg_formats = []
|
||||
if not s.ffmpeg_warning_already_shown:
|
||||
# Deprecated node are now hidden, so no need to show warning unless node is used.
|
||||
# logger.warning("This warning can be ignored, you should not be using the deprecated AnimateDiff Combine node anyway. If you are, use Video Combine from ComfyUI-VideoHelperSuite instead. ffmpeg could not be found. Outputs that require it have been disabled")
|
||||
s.ffmpeg_warning_already_shown = True
|
||||
return {
|
||||
"required": {
|
||||
"images": ("IMAGE",),
|
||||
"frame_rate": (
|
||||
"INT",
|
||||
{"default": 8, "min": 1, "max": 24, "step": 1},
|
||||
),
|
||||
"loop_count": ("INT", {"default": 0, "min": 0, "max": 100, "step": 1}),
|
||||
"filename_prefix": ("STRING", {"default": "AnimateDiff"}),
|
||||
"format": (["image/gif", "image/webp"] + ffmpeg_formats,),
|
||||
"pingpong": ("BOOLEAN", {"default": False}),
|
||||
"save_image": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {"deprecation_warning": ("ADEWARN", {"text": "Deprecated. Use VHS Video Combine"})},
|
||||
"hidden": {
|
||||
"prompt": "PROMPT",
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
},
|
||||
}
|
||||
return ['image/gif', 'image/webp'] + ['video/' + x[:-5] for x in folder_paths.get_filename_list(Folders.VIDEO_FORMATS)]
|
||||
cls.ffmpeg_warning_already_shown = True
|
||||
return ['image/gif', 'image/webp']
|
||||
|
||||
RETURN_TYPES = ("GIF",)
|
||||
OUTPUT_NODE = True
|
||||
CATEGORY = ""
|
||||
FUNCTION = "generate_gif"
|
||||
DEPRECATED = True
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffCombine', display_name='🚫AnimateDiff Combine [DEPRECATED, Use Video Combine (VHS) Instead!] 🎭🅐🅓', category='', inputs=[io.Image.Input('images'), io.Int.Input('frame_rate', default=8, max=24, min=1, step=1), io.Int.Input('loop_count', default=0, max=100, min=0, step=1), io.String.Input('filename_prefix', default='AnimateDiff'), io.Combo.Input('format', options=cls.get_formats()), io.Boolean.Input('pingpong', default=False), io.Boolean.Input('save_image', default=True)], outputs=[io.Custom('GIF').Output('GIF')], is_deprecated=True, is_output_node=True, hidden=[io.Hidden.prompt, io.Hidden.extra_pnginfo])
|
||||
ffmpeg_warning_already_shown = False
|
||||
|
||||
def generate_gif(
|
||||
self,
|
||||
images,
|
||||
frame_rate: int,
|
||||
loop_count: int,
|
||||
filename_prefix="AnimateDiff",
|
||||
format="image/gif",
|
||||
pingpong=False,
|
||||
save_image=True,
|
||||
prompt=None,
|
||||
extra_pnginfo=None,
|
||||
):
|
||||
logger.warning("Do not use AnimateDiff Combine node, it is deprecated. Use Video Combine node from ComfyUI-VideoHelperSuite instead. Video nodes from VideoHelperSuite are actively maintained, more feature-rich, and also automatically attempts to get ffmpeg.")
|
||||
# convert images to numpy
|
||||
@classmethod
|
||||
def execute(cls, images, frame_rate: int, loop_count: int, filename_prefix='AnimateDiff', format='image/gif', pingpong=False, save_image=True, prompt=None, extra_pnginfo=None):
|
||||
prompt = cls.hidden.prompt
|
||||
extra_pnginfo = cls.hidden.extra_pnginfo
|
||||
logger.warning('Do not use AnimateDiff Combine node, it is deprecated. Use Video Combine node from ComfyUI-VideoHelperSuite instead. Video nodes from VideoHelperSuite are actively maintained, more feature-rich, and also automatically attempts to get ffmpeg.')
|
||||
frames: List[Image.Image] = []
|
||||
for image in images:
|
||||
img = 255.0 * image.cpu().numpy()
|
||||
img = Image.fromarray(np.clip(img, 0, 255).astype(np.uint8))
|
||||
frames.append(img)
|
||||
|
||||
# get output information
|
||||
output_dir = (
|
||||
folder_paths.get_output_directory()
|
||||
if save_image
|
||||
else folder_paths.get_temp_directory()
|
||||
)
|
||||
(
|
||||
full_output_folder,
|
||||
filename,
|
||||
counter,
|
||||
subfolder,
|
||||
_,
|
||||
) = folder_paths.get_save_image_path(filename_prefix, output_dir)
|
||||
|
||||
output_dir = folder_paths.get_output_directory() if save_image else folder_paths.get_temp_directory()
|
||||
full_output_folder, filename, counter, subfolder, _ = folder_paths.get_save_image_path(filename_prefix, output_dir)
|
||||
metadata = PngInfo()
|
||||
if prompt is not None:
|
||||
metadata.add_text("prompt", json.dumps(prompt))
|
||||
metadata.add_text('prompt', json.dumps(prompt))
|
||||
if extra_pnginfo is not None:
|
||||
for x in extra_pnginfo:
|
||||
metadata.add_text(x, json.dumps(extra_pnginfo[x]))
|
||||
|
||||
# save first frame as png to keep metadata
|
||||
file = f"{filename}_{counter:05}_.png"
|
||||
file = f'{filename}_{counter:05}_.png'
|
||||
file_path = os.path.join(full_output_folder, file)
|
||||
frames[0].save(
|
||||
file_path,
|
||||
pnginfo=metadata,
|
||||
compress_level=4,
|
||||
)
|
||||
frames[0].save(file_path, pnginfo=metadata, compress_level=4)
|
||||
if pingpong:
|
||||
frames = frames + frames[-2:0:-1]
|
||||
|
||||
format_type, format_ext = format.split("/")
|
||||
file = f"{filename}_{counter:05}_.{format_ext}"
|
||||
format_type, format_ext = format.split('/')
|
||||
file = f'{filename}_{counter:05}_.{format_ext}'
|
||||
file_path = os.path.join(full_output_folder, file)
|
||||
if format_type == "image":
|
||||
# Use pillow directly to save an animated image
|
||||
frames[0].save(
|
||||
file_path,
|
||||
format=format_ext.upper(),
|
||||
save_all=True,
|
||||
append_images=frames[1:],
|
||||
duration=round(1000 / frame_rate),
|
||||
loop=loop_count,
|
||||
compress_level=4,
|
||||
)
|
||||
if format_type == 'image':
|
||||
frames[0].save(file_path, format=format_ext.upper(), save_all=True, append_images=frames[1:], duration=round(1000 / frame_rate), loop=loop_count, compress_level=4)
|
||||
else:
|
||||
# Use ffmpeg to save a video
|
||||
ffmpeg_path = shutil.which("ffmpeg")
|
||||
ffmpeg_path = shutil.which('ffmpeg')
|
||||
if ffmpeg_path is None:
|
||||
#Should never be reachable
|
||||
raise ProcessLookupError("Could not find ffmpeg")
|
||||
|
||||
video_format_path = folder_paths.get_full_path("video_formats", format_ext + ".json")
|
||||
raise ProcessLookupError('Could not find ffmpeg')
|
||||
video_format_path = folder_paths.get_full_path('video_formats', format_ext + '.json')
|
||||
with open(video_format_path, 'r') as stream:
|
||||
video_format = json.load(stream)
|
||||
file = f"{filename}_{counter:05}_.{video_format['extension']}"
|
||||
file_path = os.path.join(full_output_folder, file)
|
||||
dimensions = f"{frames[0].width}x{frames[0].height}"
|
||||
args = [ffmpeg_path, "-v", "error", "-f", "rawvideo", "-pix_fmt", "rgb24",
|
||||
"-s", dimensions, "-r", str(frame_rate), "-i", "-"] \
|
||||
+ video_format['main_pass'] + [file_path]
|
||||
|
||||
env=os.environ.copy()
|
||||
if "environment" in video_format:
|
||||
env.update(video_format["environment"])
|
||||
dimensions = f'{frames[0].width}x{frames[0].height}'
|
||||
args = [ffmpeg_path, '-v', 'error', '-f', 'rawvideo', '-pix_fmt', 'rgb24', '-s', dimensions, '-r', str(frame_rate), '-i', '-'] + video_format['main_pass'] + [file_path]
|
||||
env = os.environ.copy()
|
||||
if 'environment' in video_format:
|
||||
env.update(video_format['environment'])
|
||||
with subprocess.Popen(args, stdin=subprocess.PIPE, env=env) as proc:
|
||||
for frame in frames:
|
||||
proc.stdin.write(frame.tobytes())
|
||||
previews = [{'filename': file, 'subfolder': subfolder, 'type': 'output' if save_image else 'temp', 'format': format}]
|
||||
return io.NodeOutput.from_dict({'ui': {'images': previews, 'animated': (True,)}})
|
||||
|
||||
previews = [
|
||||
{
|
||||
"filename": file,
|
||||
"subfolder": subfolder,
|
||||
"type": "output" if save_image else "temp",
|
||||
"format": format,
|
||||
}
|
||||
]
|
||||
return {"ui": {"gifs": previews}}
|
||||
class AnimateDiffModelSettingsDEPR(io.ComfyNode):
|
||||
|
||||
|
||||
|
||||
class AnimateDiffModelSettingsDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
},
|
||||
"optional": {
|
||||
"mask_motion_scale": ("MASK",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AD_SETTINGS",)
|
||||
CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings"
|
||||
FUNCTION = "get_motion_model_settings"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffModelSettings_Release', display_name='🚫[DEPR] Motion Model Settings 🎭🅐🅓①', category='', inputs=[io.Float.Input('min_motion_scale', default=1.0, min=0.0, step=0.001), io.Float.Input('max_motion_scale', default=1.0, min=0.0, step=0.001), io.Mask.Input('mask_motion_scale', optional=True)], outputs=[io.Custom('AD_SETTINGS').Output('AD_SETTINGS')], is_deprecated=True)
|
||||
|
||||
def get_motion_model_settings(self, mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
motion_model_settings = AnimateDiffSettings(
|
||||
mask_attn_scale=mask_motion_scale,
|
||||
mask_attn_scale_min=min_motion_scale,
|
||||
mask_attn_scale_max=max_motion_scale,
|
||||
)
|
||||
|
||||
return (motion_model_settings,)
|
||||
|
||||
|
||||
class AnimateDiffModelSettingsSimpleDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"motion_pe_stretch": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
"mask_motion_scale": ("MASK",),
|
||||
"min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AD_SETTINGS",)
|
||||
CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings/experimental"
|
||||
FUNCTION = "get_motion_model_settings"
|
||||
DEPRECATED = True
|
||||
def execute(cls, mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
motion_model_settings = AnimateDiffSettings(mask_attn_scale=mask_motion_scale, mask_attn_scale_min=min_motion_scale, mask_attn_scale_max=max_motion_scale)
|
||||
return io.NodeOutput(motion_model_settings)
|
||||
|
||||
def get_motion_model_settings(self, motion_pe_stretch: int,
|
||||
mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
class AnimateDiffModelSettingsSimpleDEPR(io.ComfyNode):
|
||||
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffModelSettingsSimple', display_name='🚫[DEPR] Motion Model Settings (Simple) 🎭🅐🅓①', category='', inputs=[io.Int.Input('motion_pe_stretch', default=0, min=0, step=1), io.Mask.Input('mask_motion_scale', optional=True), io.Float.Input('min_motion_scale', optional=True, default=1.0, min=0.0, step=0.001), io.Float.Input('max_motion_scale', optional=True, default=1.0, min=0.0, step=0.001)], outputs=[io.Custom('AD_SETTINGS').Output('AD_SETTINGS')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, motion_pe_stretch: int, mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch))
|
||||
motion_model_settings = AnimateDiffSettings(
|
||||
adjust_pe=adjust_pe,
|
||||
mask_attn_scale=mask_motion_scale,
|
||||
mask_attn_scale_min=min_motion_scale,
|
||||
mask_attn_scale_max=max_motion_scale,
|
||||
)
|
||||
motion_model_settings = AnimateDiffSettings(adjust_pe=adjust_pe, mask_attn_scale=mask_motion_scale, mask_attn_scale_min=min_motion_scale, mask_attn_scale_max=max_motion_scale)
|
||||
return io.NodeOutput(motion_model_settings)
|
||||
|
||||
return (motion_model_settings,)
|
||||
class AnimateDiffModelSettingsAdvancedDEPR(io.ComfyNode):
|
||||
|
||||
|
||||
class AnimateDiffModelSettingsAdvancedDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"pe_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"attn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"other_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"motion_pe_stretch": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"cap_initial_pe_length": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"interpolate_pe_to_length": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"initial_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"final_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
"mask_motion_scale": ("MASK",),
|
||||
"min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AD_SETTINGS",)
|
||||
CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings/experimental"
|
||||
FUNCTION = "get_motion_model_settings"
|
||||
DEPRECATED = True
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffModelSettings', display_name='🚫[DEPR] Motion Model Settings (Advanced) 🎭🅐🅓①', category='', inputs=[io.Float.Input('pe_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('attn_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('other_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Int.Input('motion_pe_stretch', default=0, min=0, step=1), io.Int.Input('cap_initial_pe_length', default=0, min=0, step=1), io.Int.Input('interpolate_pe_to_length', default=0, min=0, step=1), io.Int.Input('initial_pe_idx_offset', default=0, min=0, step=1), io.Int.Input('final_pe_idx_offset', default=0, min=0, step=1), io.Mask.Input('mask_motion_scale', optional=True), io.Float.Input('min_motion_scale', optional=True, default=1.0, min=0.0, step=0.001), io.Float.Input('max_motion_scale', optional=True, default=1.0, min=0.0, step=0.001)], outputs=[io.Custom('AD_SETTINGS').Output('AD_SETTINGS')], is_deprecated=True)
|
||||
|
||||
def get_motion_model_settings(self, pe_strength: float, attn_strength: float, other_strength: float,
|
||||
motion_pe_stretch: int,
|
||||
cap_initial_pe_length: int, interpolate_pe_to_length: int,
|
||||
initial_pe_idx_offset: int, final_pe_idx_offset: int,
|
||||
mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch,
|
||||
cap_initial_pe_length=cap_initial_pe_length, interpolate_pe_to_length=interpolate_pe_to_length,
|
||||
initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset))
|
||||
adjust_weight = AdjustGroup(AdjustWeight(
|
||||
pe_MULT=pe_strength,
|
||||
attn_MULT=attn_strength,
|
||||
other_MULT=other_strength,
|
||||
))
|
||||
motion_model_settings = AnimateDiffSettings(
|
||||
adjust_pe=adjust_pe,
|
||||
adjust_weight=adjust_weight,
|
||||
mask_attn_scale=mask_motion_scale,
|
||||
mask_attn_scale_min=min_motion_scale,
|
||||
mask_attn_scale_max=max_motion_scale,
|
||||
)
|
||||
|
||||
return (motion_model_settings,)
|
||||
|
||||
|
||||
class AnimateDiffModelSettingsAdvancedAttnStrengthsDEPR:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"pe_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"attn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"attn_q_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"attn_k_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"attn_v_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"attn_out_weight_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"attn_out_bias_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"other_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.0001}),
|
||||
"motion_pe_stretch": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"cap_initial_pe_length": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"interpolate_pe_to_length": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"initial_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
"final_pe_idx_offset": ("INT", {"default": 0, "min": 0, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
"mask_motion_scale": ("MASK",),
|
||||
"min_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"max_motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Deprecated"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AD_SETTINGS",)
|
||||
CATEGORY = "" #"Animate Diff 🎭🅐🅓/① Gen1 nodes ①/motion settings/experimental"
|
||||
FUNCTION = "get_motion_model_settings"
|
||||
DEPRECATED = True
|
||||
def execute(cls, pe_strength: float, attn_strength: float, other_strength: float, motion_pe_stretch: int, cap_initial_pe_length: int, interpolate_pe_to_length: int, initial_pe_idx_offset: int, final_pe_idx_offset: int, mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch, cap_initial_pe_length=cap_initial_pe_length, interpolate_pe_to_length=interpolate_pe_to_length, initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset))
|
||||
adjust_weight = AdjustGroup(AdjustWeight(pe_MULT=pe_strength, attn_MULT=attn_strength, other_MULT=other_strength))
|
||||
motion_model_settings = AnimateDiffSettings(adjust_pe=adjust_pe, adjust_weight=adjust_weight, mask_attn_scale=mask_motion_scale, mask_attn_scale_min=min_motion_scale, mask_attn_scale_max=max_motion_scale)
|
||||
return io.NodeOutput(motion_model_settings)
|
||||
|
||||
def get_motion_model_settings(self, pe_strength: float, attn_strength: float,
|
||||
attn_q_strength: float,
|
||||
attn_k_strength: float,
|
||||
attn_v_strength: float,
|
||||
attn_out_weight_strength: float,
|
||||
attn_out_bias_strength: float,
|
||||
other_strength: float,
|
||||
motion_pe_stretch: int,
|
||||
cap_initial_pe_length: int, interpolate_pe_to_length: int,
|
||||
initial_pe_idx_offset: int, final_pe_idx_offset: int,
|
||||
mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch,
|
||||
cap_initial_pe_length=cap_initial_pe_length, interpolate_pe_to_length=interpolate_pe_to_length,
|
||||
initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset))
|
||||
adjust_weight = AdjustGroup(AdjustWeight(
|
||||
pe_MULT=pe_strength,
|
||||
attn_MULT=attn_strength,
|
||||
attn_q_MULT=attn_q_strength,
|
||||
attn_k_MULT=attn_k_strength,
|
||||
attn_v_MULT=attn_v_strength,
|
||||
attn_out_weight_MULT=attn_out_weight_strength,
|
||||
attn_out_bias_MULT=attn_out_bias_strength,
|
||||
other_MULT=other_strength,
|
||||
))
|
||||
motion_model_settings = AnimateDiffSettings(
|
||||
adjust_pe=adjust_pe,
|
||||
adjust_weight=adjust_weight,
|
||||
mask_attn_scale=mask_motion_scale,
|
||||
mask_attn_scale_min=min_motion_scale,
|
||||
mask_attn_scale_max=max_motion_scale,
|
||||
)
|
||||
class AnimateDiffModelSettingsAdvancedAttnStrengthsDEPR(io.ComfyNode):
|
||||
|
||||
return (motion_model_settings,)
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(node_id='ADE_AnimateDiffModelSettingsAdvancedAttnStrengths', display_name='🚫[DEPR] Motion Model Settings (Adv. Attn) 🎭🅐🅓①', category='', inputs=[io.Float.Input('pe_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('attn_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('attn_q_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('attn_k_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('attn_v_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('attn_out_weight_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('attn_out_bias_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Float.Input('other_strength', default=1.0, max=10.0, min=0.0, step=0.0001), io.Int.Input('motion_pe_stretch', default=0, min=0, step=1), io.Int.Input('cap_initial_pe_length', default=0, min=0, step=1), io.Int.Input('interpolate_pe_to_length', default=0, min=0, step=1), io.Int.Input('initial_pe_idx_offset', default=0, min=0, step=1), io.Int.Input('final_pe_idx_offset', default=0, min=0, step=1), io.Mask.Input('mask_motion_scale', optional=True), io.Float.Input('min_motion_scale', optional=True, default=1.0, min=0.0, step=0.001), io.Float.Input('max_motion_scale', optional=True, default=1.0, min=0.0, step=0.001)], outputs=[io.Custom('AD_SETTINGS').Output('AD_SETTINGS')], is_deprecated=True)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, pe_strength: float, attn_strength: float, attn_q_strength: float, attn_k_strength: float, attn_v_strength: float, attn_out_weight_strength: float, attn_out_bias_strength: float, other_strength: float, motion_pe_stretch: int, cap_initial_pe_length: int, interpolate_pe_to_length: int, initial_pe_idx_offset: int, final_pe_idx_offset: int, mask_motion_scale: torch.Tensor=None, min_motion_scale: float=1.0, max_motion_scale: float=1.0):
|
||||
adjust_pe = AdjustGroup(AdjustPE(motion_pe_stretch=motion_pe_stretch, cap_initial_pe_length=cap_initial_pe_length, interpolate_pe_to_length=interpolate_pe_to_length, initial_pe_idx_offset=initial_pe_idx_offset, final_pe_idx_offset=final_pe_idx_offset))
|
||||
adjust_weight = AdjustGroup(AdjustWeight(pe_MULT=pe_strength, attn_MULT=attn_strength, attn_q_MULT=attn_q_strength, attn_k_MULT=attn_k_strength, attn_v_MULT=attn_v_strength, attn_out_weight_MULT=attn_out_weight_strength, attn_out_bias_MULT=attn_out_bias_strength, other_MULT=other_strength))
|
||||
motion_model_settings = AnimateDiffSettings(adjust_pe=adjust_pe, adjust_weight=adjust_weight, mask_attn_scale=mask_motion_scale, mask_attn_scale_min=min_motion_scale, mask_attn_scale_max=max_motion_scale)
|
||||
return io.NodeOutput(motion_model_settings)
|
||||
|
||||
+62
-79
@@ -3,6 +3,8 @@ from typing import Union
|
||||
import torch
|
||||
from torch import Tensor
|
||||
|
||||
from comfy_api.latest import io
|
||||
|
||||
import folder_paths
|
||||
import nodes as comfy_nodes
|
||||
from comfy.model_patcher import ModelPatcher
|
||||
@@ -17,44 +19,36 @@ from .model_injection import get_vanilla_model_patcher
|
||||
from .cfg_extras import perturbed_attention_guidance_patch, rescale_cfg_patch
|
||||
|
||||
|
||||
class AnimateDiffUnload:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
class AnimateDiffUnload(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {"model": ("MODEL",)}}
|
||||
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/extras"
|
||||
FUNCTION = "unload_motion_modules"
|
||||
|
||||
def unload_motion_modules(self, model: ModelPatcher):
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AnimateDiffUnload',
|
||||
display_name='AnimateDiff Unload 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/extras',
|
||||
inputs=[io.Model.Input('model')],
|
||||
outputs=[io.Model.Output('MODEL')]
|
||||
)
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher):
|
||||
# return model clone with ejected params
|
||||
#model = eject_params_from_model(model)
|
||||
model = get_vanilla_model_patcher(model)
|
||||
return (model.clone(),)
|
||||
return io.NodeOutput(model.clone())
|
||||
|
||||
|
||||
class CheckpointLoaderSimpleWithNoiseSelect:
|
||||
class CheckpointLoaderSimpleWithNoiseSelect(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"ckpt_name": (folder_paths.get_filename_list("checkpoints"), ),
|
||||
"beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.USE_EXISTING}, )
|
||||
},
|
||||
"optional": {
|
||||
"use_custom_scale_factor": ("BOOLEAN", {"default": False}),
|
||||
"scale_factor": ("FLOAT", {"default": 0.18215, "min": 0.0, "max": 1.0, "step": 0.00001})
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE")
|
||||
FUNCTION = "load_checkpoint"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/extras"
|
||||
|
||||
def load_checkpoint(self, ckpt_name, beta_schedule, output_vae=True, output_clip=True, use_custom_scale_factor=False, scale_factor=0.18215):
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='CheckpointLoaderSimpleWithNoiseSelect',
|
||||
display_name='Load Checkpoint w/ Noise Select 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/extras',
|
||||
inputs=[io.Combo.Input('ckpt_name', options=folder_paths.get_filename_list("checkpoints")), io.Combo.Input('beta_schedule', options=['autoselect', 'use existing', 'sqrt_linear (AnimateDiff)', 'linear (AnimateDiff-SDXL)', 'linear (HotshotXL/default)', 'avg(sqrt_linear,linear)', 'lcm avg(sqrt_linear,linear)', 'lcm', 'lcm[100_ots]', 'lcm >> sqrt_linear', 'sqrt', 'cosine', 'squaredcos_cap_v2'] , default='use existing'), io.Boolean.Input('use_custom_scale_factor', default=False, optional=True), io.Float.Input('scale_factor', default=0.18215, max=1.0, min=0.0, step=1e-05, optional=True)],
|
||||
outputs=[io.Model.Output('MODEL'), io.Clip.Output('CLIP'), io.Vae.Output('VAE')]
|
||||
)
|
||||
@classmethod
|
||||
def execute(cls, ckpt_name, beta_schedule, output_vae=True, output_clip=True, use_custom_scale_factor=False, scale_factor=0.18215):
|
||||
ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name)
|
||||
out = load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings"))
|
||||
# register chosen beta schedule on model - convert to beta_schedule name recognized by ComfyUI
|
||||
@@ -63,66 +57,55 @@ class CheckpointLoaderSimpleWithNoiseSelect:
|
||||
out[0].model.model_sampling = new_model_sampling
|
||||
if use_custom_scale_factor:
|
||||
out[0].model.latent_format.scale_factor = scale_factor
|
||||
return out
|
||||
return io.NodeOutput(*out)
|
||||
|
||||
|
||||
class EmptyLatentImageLarge:
|
||||
def __init__(self, device="cpu"):
|
||||
self.device = device
|
||||
|
||||
class EmptyLatentImageLarge(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": { "width": ("INT", {"default": 512, "min": 64, "max": comfy_nodes.MAX_RESOLUTION, "step": 8}),
|
||||
"height": ("INT", {"default": 512, "min": 64, "max": comfy_nodes.MAX_RESOLUTION, "step": 8}),
|
||||
"batch_size": ("INT", {"default": 1, "min": 1, "max": 262144})}}
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
FUNCTION = "generate"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/extras"
|
||||
|
||||
def generate(self, width, height, batch_size=1):
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_EmptyLatentImageLarge',
|
||||
display_name='Empty Latent Image (Big Batch) 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/extras',
|
||||
inputs=[io.Int.Input('width', default=512, max=16384, min=64, step=8), io.Int.Input('height', default=512, max=16384, min=64, step=8), io.Int.Input('batch_size', default=1, max=262144, min=1)],
|
||||
outputs=[io.Latent.Output('LATENT')]
|
||||
)
|
||||
@classmethod
|
||||
def execute(cls, width, height, batch_size=1):
|
||||
latent = torch.zeros([batch_size, 4, height // 8, width // 8])
|
||||
return ({"samples":latent}, )
|
||||
return io.NodeOutput({"samples":latent})
|
||||
|
||||
|
||||
class PerturbedAttentionGuidanceMultival:
|
||||
class PerturbedAttentionGuidanceMultival(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
FUNCTION = "patch"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/extras"
|
||||
|
||||
def patch(self, model: ModelPatcher, scale_multival: Union[float, Tensor]):
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerturbedAttentionGuidanceMultival',
|
||||
display_name='PerturbedAttnGuide [Multival] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/extras',
|
||||
inputs=[io.Model.Input('model'), io.Custom('MULTIVAL').Input('scale_multival')],
|
||||
outputs=[io.Model.Output('MODEL')]
|
||||
)
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, scale_multival: Union[float, Tensor]):
|
||||
m = model.clone()
|
||||
m.set_model_sampler_post_cfg_function(perturbed_attention_guidance_patch(scale_multival))
|
||||
|
||||
return (m,)
|
||||
return io.NodeOutput(m)
|
||||
|
||||
|
||||
class RescaleCFGMultival:
|
||||
class RescaleCFGMultival(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
FUNCTION = "patch"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/extras"
|
||||
|
||||
def patch(self, model: ModelPatcher, mult_multival: Union[float, Tensor]):
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_RescaleCFGMultival',
|
||||
display_name='RescaleCFG [Multival] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/extras',
|
||||
inputs=[io.Model.Input('model'), io.Custom('MULTIVAL').Input('mult_multival')],
|
||||
outputs=[io.Model.Output('MODEL')]
|
||||
)
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, mult_multival: Union[float, Tensor]):
|
||||
m = model.clone()
|
||||
m.set_model_sampler_cfg_function(rescale_cfg_patch(mult_multival))
|
||||
return (m, )
|
||||
return io.NodeOutput(m)
|
||||
|
||||
@@ -36,9 +36,6 @@ class ApplyAnimateDiffFancyVideo:
|
||||
"prev_m_models": ("M_MODELS",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("M_MODELS",)
|
||||
|
||||
+27
-25
@@ -1,3 +1,4 @@
|
||||
from comfy_api.latest import io
|
||||
from comfy.model_patcher import ModelPatcher
|
||||
|
||||
from .ad_settings import AnimateDiffSettings
|
||||
@@ -13,33 +14,34 @@ from .sample_settings import SampleSettings
|
||||
from .sampling import outer_sample_wrapper, sliding_calc_cond_batch
|
||||
|
||||
|
||||
class AnimateDiffLoaderGen1:
|
||||
class AnimateDiffLoaderGen1(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"model_name": (get_available_motion_models(),),
|
||||
"beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.AUTOSELECT}),
|
||||
#"apply_mm_groupnorm_hack": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {
|
||||
"context_options": ("CONTEXT_OPTIONS",),
|
||||
"motion_lora": ("MOTION_LORA",),
|
||||
"ad_settings": ("AD_SETTINGS",),
|
||||
"ad_keyframes": ("AD_KEYFRAMES",),
|
||||
"sample_settings": ("SAMPLE_SETTINGS",),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AnimateDiffLoaderGen1',
|
||||
display_name='AnimateDiff Loader 🎭🅐🅓①',
|
||||
category='Animate Diff 🎭🅐🅓/① Gen1 nodes ①',
|
||||
inputs=[
|
||||
io.Model.Input('model'),
|
||||
io.Combo.Input('model_name', options=get_available_motion_models()),
|
||||
io.Combo.Input('beta_schedule', options=['autoselect', 'use existing', 'sqrt_linear (AnimateDiff)', 'linear (AnimateDiff-SDXL)', 'linear (HotshotXL/default)', 'avg(sqrt_linear,linear)', 'lcm avg(sqrt_linear,linear)', 'lcm', 'lcm[100_ots]', 'lcm >> sqrt_linear', 'sqrt', 'cosine', 'squaredcos_cap_v2'], default='autoselect'),
|
||||
io.Custom("CONTEXT_OPTIONS").Input('context_options', optional=True),
|
||||
io.Custom("MOTION_LORA").Input('motion_lora', optional=True),
|
||||
io.Custom("AD_SETTINGS").Input('ad_settings', optional=True),
|
||||
io.Custom("AD_KEYFRAMES").Input('ad_keyframes', optional=True),
|
||||
io.Custom("SAMPLE_SETTINGS").Input('sample_settings', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("PER_BLOCK").Input('per_block', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Model.Output('MODEL'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/① Gen1 nodes ①"
|
||||
FUNCTION = "load_mm_and_inject_params"
|
||||
|
||||
def load_mm_and_inject_params(self,
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
model: ModelPatcher,
|
||||
model_name: str, beta_schedule: str,# apply_mm_groupnorm_hack: bool,
|
||||
context_options: ContextOptionsGroup=None, motion_lora: MotionLoraList=None, ad_settings: AnimateDiffSettings=None,
|
||||
@@ -107,4 +109,4 @@ class AnimateDiffLoaderGen1:
|
||||
model.add_object_patch("model_sampling", new_model_sampling)
|
||||
|
||||
del motion_model
|
||||
return (model,)
|
||||
return io.NodeOutput(model,)
|
||||
|
||||
+106
-108
@@ -1,3 +1,4 @@
|
||||
from comfy_api.latest import io
|
||||
from typing import Union
|
||||
import torch
|
||||
|
||||
@@ -17,26 +18,28 @@ from .sample_settings import SampleSettings
|
||||
from .sampling import outer_sample_wrapper, sliding_calc_cond_batch
|
||||
|
||||
|
||||
class UseEvolvedSamplingNode:
|
||||
class UseEvolvedSamplingNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"beta_schedule": (BetaSchedules.ALIAS_LIST, {"default": BetaSchedules.AUTOSELECT}),
|
||||
},
|
||||
"optional": {
|
||||
"m_models": ("M_MODELS",),
|
||||
"context_options": ("CONTEXT_OPTIONS",),
|
||||
"sample_settings": ("SAMPLE_SETTINGS",),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_UseEvolvedSampling',
|
||||
display_name='Use Evolved Sampling 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②',
|
||||
inputs=[
|
||||
io.Model.Input('model'),
|
||||
io.Combo.Input('beta_schedule', options=['autoselect', 'use existing', 'sqrt_linear (AnimateDiff)', 'linear (AnimateDiff-SDXL)', 'linear (HotshotXL/default)', 'avg(sqrt_linear,linear)', 'lcm avg(sqrt_linear,linear)', 'lcm', 'lcm[100_ots]', 'lcm >> sqrt_linear', 'sqrt', 'cosine', 'squaredcos_cap_v2'], default='autoselect'),
|
||||
io.Custom("M_MODELS").Input('m_models', optional=True),
|
||||
io.Custom("CONTEXT_OPTIONS").Input('context_options', optional=True),
|
||||
io.Custom("SAMPLE_SETTINGS").Input('sample_settings', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Model.Output('MODEL'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MODEL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②"
|
||||
FUNCTION = "use_evolved_sampling"
|
||||
|
||||
def use_evolved_sampling(self, model: ModelPatcher, beta_schedule: str, m_models: MotionModelGroup=None, context_options: ContextOptionsGroup=None,
|
||||
@classmethod
|
||||
def execute(cls, model: ModelPatcher, beta_schedule: str, m_models: MotionModelGroup=None, context_options: ContextOptionsGroup=None,
|
||||
sample_settings: SampleSettings=None):
|
||||
model = model.clone()
|
||||
helper = ModelPatcherHelper(model)
|
||||
@@ -81,36 +84,35 @@ class UseEvolvedSamplingNode:
|
||||
model.add_object_patch("model_sampling", new_model_sampling)
|
||||
|
||||
del m_models
|
||||
return (model,)
|
||||
return io.NodeOutput(model,)
|
||||
|
||||
|
||||
class ApplyAnimateDiffModelNode:
|
||||
class ApplyAnimateDiffModelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"motion_model": ("MOTION_MODEL_ADE",),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
},
|
||||
"optional": {
|
||||
"motion_lora": ("MOTION_LORA",),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"ad_keyframes": ("AD_KEYFRAMES",),
|
||||
"prev_m_models": ("M_MODELS",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ApplyAnimateDiffModel',
|
||||
display_name='Apply AnimateDiff Model (Adv.) 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②',
|
||||
inputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Input('motion_model'),
|
||||
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Custom("MOTION_LORA").Input('motion_lora', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("AD_KEYFRAMES").Input('ad_keyframes', optional=True),
|
||||
io.Custom("M_MODELS").Input('prev_m_models', optional=True),
|
||||
io.Custom("PER_BLOCK").Input('per_block', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("M_MODELS").Output('M_MODELS'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("M_MODELS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②"
|
||||
FUNCTION = "apply_motion_model"
|
||||
|
||||
def apply_motion_model(self, motion_model: MotionModelPatcher, start_percent: float=0.0, end_percent: float=1.0,
|
||||
@classmethod
|
||||
def execute(cls, motion_model: MotionModelPatcher, start_percent: float=0.0, end_percent: float=1.0,
|
||||
motion_lora: MotionLoraList=None, ad_keyframes: ADKeyframeGroup=None,
|
||||
scale_multival=None, effect_multival=None, per_block: AllPerBlocks=None,
|
||||
prev_m_models: MotionModelGroup=None,):
|
||||
@@ -139,94 +141,90 @@ class ApplyAnimateDiffModelNode:
|
||||
attachment.timestep_percent_range = (start_percent, end_percent)
|
||||
# add to beginning, so that after injection, it will be the earliest of prev_m_models to be run
|
||||
prev_m_models.add_to_start(mm=motion_model)
|
||||
return (prev_m_models,)
|
||||
return io.NodeOutput(prev_m_models,)
|
||||
|
||||
|
||||
class ApplyAnimateDiffModelBasicNode:
|
||||
class ApplyAnimateDiffModelBasicNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"motion_model": ("MOTION_MODEL_ADE",),
|
||||
},
|
||||
"optional": {
|
||||
"motion_lora": ("MOTION_LORA",),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"ad_keyframes": ("AD_KEYFRAMES",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ApplyAnimateDiffModelSimple',
|
||||
display_name='Apply AnimateDiff Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②',
|
||||
inputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Input('motion_model'),
|
||||
io.Custom("MOTION_LORA").Input('motion_lora', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("AD_KEYFRAMES").Input('ad_keyframes', optional=True),
|
||||
io.Custom("PER_BLOCK").Input('per_block', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("M_MODELS").Output('M_MODELS'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("M_MODELS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②"
|
||||
FUNCTION = "apply_motion_model"
|
||||
|
||||
def apply_motion_model(self,
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
motion_model: MotionModelPatcher, motion_lora: MotionLoraList=None,
|
||||
scale_multival=None, effect_multival=None, ad_keyframes=None,
|
||||
per_block: AllPerBlocks=None):
|
||||
# just a subset of normal ApplyAnimateDiffModelNode inputs
|
||||
return ApplyAnimateDiffModelNode.apply_motion_model(self, motion_model, motion_lora=motion_lora,
|
||||
return io.NodeOutput(*ApplyAnimateDiffModelNode.execute( motion_model, motion_lora=motion_lora,
|
||||
scale_multival=scale_multival, effect_multival=effect_multival,
|
||||
ad_keyframes=ad_keyframes, per_block=per_block)
|
||||
ad_keyframes=ad_keyframes, per_block=per_block).args)
|
||||
|
||||
|
||||
class LoadAnimateDiffModelNode:
|
||||
class LoadAnimateDiffModelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (get_available_motion_models(),),
|
||||
},
|
||||
"optional": {
|
||||
"ad_settings": ("AD_SETTINGS",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 50}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_LoadAnimateDiffModel',
|
||||
display_name='Load AnimateDiff Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②',
|
||||
inputs=[
|
||||
io.Combo.Input('model_name', options=get_available_motion_models()),
|
||||
io.Custom("AD_SETTINGS").Input('ad_settings', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Output('MOTION_MODEL'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MOTION_MODEL_ADE",)
|
||||
RETURN_NAMES = ("MOTION_MODEL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②"
|
||||
FUNCTION = "load_motion_model"
|
||||
|
||||
def load_motion_model(self, model_name: str, ad_settings: AnimateDiffSettings=None):
|
||||
@classmethod
|
||||
def execute(cls, model_name: str, ad_settings: AnimateDiffSettings=None):
|
||||
# load motion module and motion settings, if included
|
||||
motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings)
|
||||
return (motion_model,)
|
||||
return io.NodeOutput(motion_model,)
|
||||
|
||||
|
||||
class ADKeyframeNode:
|
||||
class ADKeyframeNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
||||
},
|
||||
"optional": {
|
||||
"prev_ad_keyframes": ("AD_KEYFRAMES", ),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"per_block_replace": ("PER_BLOCK",),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}, ),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AnimateDiffKeyframe',
|
||||
display_name='AnimateDiff Keyframe 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓',
|
||||
inputs=[
|
||||
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Custom("AD_KEYFRAMES").Input('prev_ad_keyframes', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("PER_BLOCK").Input('per_block_replace', optional=True),
|
||||
io.Boolean.Input('inherit_missing', optional=True, default=True),
|
||||
io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("AD_KEYFRAMES").Output('AD_KEYFRAMES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("AD_KEYFRAMES", )
|
||||
FUNCTION = "load_keyframe"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓"
|
||||
|
||||
def load_keyframe(self,
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
start_percent: float, prev_ad_keyframes=None,
|
||||
scale_multival: Union[float, torch.Tensor]=None, effect_multival: Union[float, torch.Tensor]=None,
|
||||
per_block_replace: AllPerBlocks=None,
|
||||
@@ -241,4 +239,4 @@ class ADKeyframeNode:
|
||||
cameractrl_multival=cameractrl_multival, pia_input=pia_input,
|
||||
inherit_missing=inherit_missing, guarantee_steps=guarantee_steps)
|
||||
prev_ad_keyframes.add(keyframe)
|
||||
return (prev_ad_keyframes,)
|
||||
return io.NodeOutput(prev_ad_keyframes,)
|
||||
|
||||
+19
-19
@@ -1,3 +1,4 @@
|
||||
from comfy_api.latest import io
|
||||
from pathlib import Path
|
||||
|
||||
import folder_paths
|
||||
@@ -9,27 +10,26 @@ from .utils_model import get_available_motion_loras, get_motion_lora_path
|
||||
from .motion_lora import MotionLoraInfo, MotionLoraList
|
||||
|
||||
|
||||
class AnimateDiffLoraLoader:
|
||||
class AnimateDiffLoraLoader(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"name": (get_available_motion_loras(),),
|
||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}),
|
||||
},
|
||||
"optional": {
|
||||
"prev_motion_lora": ("MOTION_LORA",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 30}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_AnimateDiffLoRALoader',
|
||||
display_name='Load AnimateDiff LoRA 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓',
|
||||
inputs=[
|
||||
io.Combo.Input('name', options=get_available_motion_loras()),
|
||||
io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||
io.Custom("MOTION_LORA").Input('prev_motion_lora', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("MOTION_LORA").Output('MOTION_LORA'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MOTION_LORA",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓"
|
||||
FUNCTION = "load_motion_lora"
|
||||
|
||||
def load_motion_lora(self, name: str, strength: float, prev_motion_lora: MotionLoraList=None, lora_name: str=None):
|
||||
@classmethod
|
||||
def execute(cls, name: str, strength: float, prev_motion_lora: MotionLoraList=None, lora_name: str=None):
|
||||
if prev_motion_lora is None:
|
||||
prev_motion_lora = MotionLoraList()
|
||||
else:
|
||||
@@ -44,4 +44,4 @@ class AnimateDiffLoraLoader:
|
||||
lora_info = MotionLoraInfo(name=name, strength=strength)
|
||||
prev_motion_lora.add_lora(lora_info)
|
||||
|
||||
return (prev_motion_lora,)
|
||||
return io.NodeOutput(prev_motion_lora,)
|
||||
|
||||
@@ -114,9 +114,6 @@ class ApplyAnimateDiffMotionCtrlModel:
|
||||
"prev_m_models": ("M_MODELS",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("M_MODELS",)
|
||||
|
||||
+63
-120
@@ -4,6 +4,8 @@ from typing import Union
|
||||
import torch
|
||||
from torch import Tensor
|
||||
|
||||
from comfy_api.latest import io
|
||||
|
||||
from .utils_motion import create_multival_combo, linear_conversion, normalize_min_max, extend_to_batch_size, extend_list_to_batch_size
|
||||
|
||||
|
||||
@@ -13,51 +15,33 @@ class ScaleType:
|
||||
LIST = [ABSOLUTE, RELATIVE]
|
||||
|
||||
|
||||
class MultivalDynamicNode:
|
||||
class MultivalDynamicNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"float_val": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001},),
|
||||
},
|
||||
"optional": {
|
||||
"mask_optional": ("MASK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MULTIVAL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/multival"
|
||||
FUNCTION = "create_multival"
|
||||
|
||||
def create_multival(self, float_val: Union[float, list[float]]=1.0, mask_optional: Tensor=None):
|
||||
return (create_multival_combo(float_val=float_val, mask_optional=mask_optional),)
|
||||
|
||||
|
||||
class MultivalScaledMaskNode:
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_MultivalDynamic',
|
||||
display_name='Multival 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/multival',
|
||||
inputs=[io.Float.Input('float_val', default=1.0, min=0.0, step=0.001), io.Mask.Input('mask_optional', optional=True)],
|
||||
outputs=[io.Custom('MULTIVAL').Output('MULTIVAL')]
|
||||
)
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"min_float_val": ("FLOAT", {"default": 0.0, "min": 0.0, "step": 0.001}),
|
||||
"max_float_val": ("FLOAT", {"default": 1.0, "min": 0.0, "step": 0.001}),
|
||||
"mask": ("MASK",),
|
||||
},
|
||||
"optional": {
|
||||
"scaling": (ScaleType.LIST,),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def execute(cls, float_val: Union[float, list[float]]=1.0, mask_optional: Tensor=None):
|
||||
return io.NodeOutput(create_multival_combo(float_val=float_val, mask_optional=mask_optional))
|
||||
|
||||
RETURN_TYPES = ("MULTIVAL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/multival"
|
||||
FUNCTION = "create_multival"
|
||||
|
||||
def create_multival(self, min_float_val: float, max_float_val: float, mask: Tensor, scaling: str=ScaleType.ABSOLUTE):
|
||||
class MultivalScaledMaskNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_MultivalScaledMask',
|
||||
display_name='Multival Scaled Mask 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/multival',
|
||||
inputs=[io.Float.Input('min_float_val', default=0.0, min=0.0, step=0.001), io.Float.Input('max_float_val', default=1.0, min=0.0, step=0.001), io.Mask.Input('mask'), io.Combo.Input('scaling', options=['absolute', 'relative'] , optional=True)],
|
||||
outputs=[io.Custom('MULTIVAL').Output('MULTIVAL')]
|
||||
)
|
||||
@classmethod
|
||||
def execute(cls, min_float_val: float, max_float_val: float, mask: Tensor, scaling: str=ScaleType.ABSOLUTE):
|
||||
lengths = [mask.shape[0]]
|
||||
iterable_inputs = [False, False]
|
||||
val_inputs = [min_float_val, max_float_val]
|
||||
@@ -83,96 +67,55 @@ class MultivalScaledMaskNode:
|
||||
mask = normalize_min_max(mask.clone(), new_min=min_float_val, new_max=max_float_val)
|
||||
else:
|
||||
raise ValueError(f"scaling '{scaling}' not recognized.")
|
||||
return MultivalDynamicNode.create_multival(self, mask_optional=mask)
|
||||
return io.NodeOutput(*MultivalDynamicNode.execute(mask_optional=mask).args)
|
||||
|
||||
|
||||
class MultivalDynamicFloatInputNode:
|
||||
class MultivalDynamicFloatInputNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"float_val": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001, "forceInput": True},),
|
||||
},
|
||||
"optional": {
|
||||
"mask_optional": ("MASK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MULTIVAL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/multival"
|
||||
FUNCTION = "create_multival"
|
||||
|
||||
def create_multival(self, float_val: Union[float, list[float]]=None, mask_optional: Tensor=None):
|
||||
return MultivalDynamicNode.create_multival(self, float_val=float_val, mask_optional=mask_optional)
|
||||
|
||||
|
||||
class MultivalDynamicFloatsNode:
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_MultivalDynamicFloatInput',
|
||||
display_name='Multival [Float List] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/multival',
|
||||
inputs=[io.Float.Input('float_val', default=1.0, force_input=True, max=10.0, min=0.0, step=0.001), io.Mask.Input('mask_optional', optional=True)],
|
||||
outputs=[io.Custom('MULTIVAL').Output('MULTIVAL')]
|
||||
)
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"floats": ("FLOATS", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001},),
|
||||
},
|
||||
"optional": {
|
||||
"mask_optional": ("MASK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MULTIVAL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/multival"
|
||||
FUNCTION = "create_multival"
|
||||
|
||||
def create_multival(self, floats: Union[float, list[float]]=None, mask_optional: Tensor=None):
|
||||
return MultivalDynamicNode.create_multival(self, float_val=floats, mask_optional=mask_optional)
|
||||
def execute(cls, float_val: Union[float, list[float]]=None, mask_optional: Tensor=None):
|
||||
return io.NodeOutput(*MultivalDynamicNode.execute(float_val=float_val, mask_optional=mask_optional).args)
|
||||
|
||||
|
||||
class MultivalFloatNode:
|
||||
class MultivalDynamicFloatsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"float_val": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001},),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MULTIVAL",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/multival"
|
||||
FUNCTION = "create_multival"
|
||||
|
||||
def create_multival(self, float_val: Union[float, list[float]]=None):
|
||||
return MultivalDynamicNode.create_multival(self, float_val=float_val)
|
||||
|
||||
|
||||
class MultivalConvertToMaskNode:
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_MultivalDynamicFloats',
|
||||
display_name='Multival [Floats] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/multival',
|
||||
inputs=[io.Custom('FLOATS').Input('floats', extra_dict={'default': 1.0, 'min': 0.0, 'max': 10.0, 'step': 0.001}), io.Mask.Input('mask_optional', optional=True)],
|
||||
outputs=[io.Custom('MULTIVAL').Output('MULTIVAL')]
|
||||
)
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"multival": ("MULTIVAL",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MASK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/multival"
|
||||
FUNCTION = "convert_multival_to_mask"
|
||||
def execute(cls, floats: Union[float, list[float]]=None, mask_optional: Tensor=None):
|
||||
return io.NodeOutput(*MultivalDynamicNode.execute(float_val=floats, mask_optional=mask_optional).args)
|
||||
|
||||
def convert_multival_to_mask(self, multival: Union[float, Tensor]):
|
||||
|
||||
class MultivalConvertToMaskNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_MultivalConvertToMask',
|
||||
display_name='Multival to Mask 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/multival',
|
||||
inputs=[io.Custom('MULTIVAL').Input('multival')],
|
||||
outputs=[io.Mask.Output('MASK')]
|
||||
)
|
||||
@classmethod
|
||||
def execute(cls, multival: Union[float, Tensor]):
|
||||
# if already tensor, assume is a valid mask
|
||||
if type(multival) == Tensor:
|
||||
return (multival,)
|
||||
return io.NodeOutput(multival)
|
||||
# otherwise, make a single 1x1 mask with the proper value
|
||||
shape = (1,1,1)
|
||||
converted_multival = torch.ones(shape) * multival
|
||||
return (converted_multival,)
|
||||
return io.NodeOutput(converted_multival)
|
||||
|
||||
+114
-236
@@ -1,7 +1,8 @@
|
||||
from typing import Union
|
||||
from torch import Tensor
|
||||
|
||||
from .documentation import short_desc, register_description, coll, DocHelper
|
||||
from comfy_api.latest import io
|
||||
|
||||
from .motion_module_ad import BlockType
|
||||
from .utils_model import ModelTypeSD
|
||||
from .utils_motion import AllPerBlocks, PerBlock, PerBlockId, extend_list_to_batch_size
|
||||
@@ -27,85 +28,63 @@ class ADBlockHolder:
|
||||
return not has_anything
|
||||
|
||||
|
||||
class ADBlockComboNode:
|
||||
class ADBlockComboNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ADBlockCombo',
|
||||
display_name='AD Block 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('MULTIVAL').Input('effect', optional=True), io.Custom('MULTIVAL').Input('scale', optional=True)],
|
||||
outputs=[io.Custom('AD_BLOCK').Output('AD_BLOCK')]
|
||||
)
|
||||
NodeID = 'ADE_ADBlockCombo'
|
||||
NodeName = 'AD Block 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"effect": ("MULTIVAL",),
|
||||
"scale": ("MULTIVAL",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AD_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "block_control"
|
||||
|
||||
def block_control(self, effect: Union[float, Tensor, None]=None, scale: Union[float, Tensor, None]=None):
|
||||
def execute(cls, effect: Union[float, Tensor, None]=None, scale: Union[float, Tensor, None]=None):
|
||||
scales = [scale, scale]
|
||||
block = ADBlockHolder(effect=effect, scales=scales)
|
||||
if block.is_empty():
|
||||
block = None
|
||||
return (block,)
|
||||
return io.NodeOutput(block)
|
||||
|
||||
|
||||
class ADBlockIndivNode:
|
||||
class ADBlockIndivNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ADBlockIndiv',
|
||||
display_name='AD Block+ 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('MULTIVAL').Input('effect', optional=True), io.Custom('MULTIVAL').Input('scale_0', optional=True), io.Custom('MULTIVAL').Input('scale_1', optional=True)],
|
||||
outputs=[io.Custom('AD_BLOCK').Output('AD_BLOCK')]
|
||||
)
|
||||
NodeID = 'ADE_ADBlockIndiv'
|
||||
NodeName = 'AD Block+ 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"effect": ("MULTIVAL",),
|
||||
"scale_0": ("MULTIVAL",),
|
||||
"scale_1": ("MULTIVAL",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("AD_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "block_control"
|
||||
|
||||
def block_control(self, effect: Union[float, Tensor, None]=None,
|
||||
def execute(cls, effect: Union[float, Tensor, None]=None,
|
||||
scale_0: Union[float, Tensor, None]=None, scale_1: Union[float, Tensor, None]=None):
|
||||
scales = [scale_0, scale_1]
|
||||
block = ADBlockHolder(effect=effect, scales=scales)
|
||||
if block.is_empty():
|
||||
block = None
|
||||
return (block,)
|
||||
return io.NodeOutput(block)
|
||||
|
||||
|
||||
class PerBlockHighLevelNode:
|
||||
class PerBlockHighLevelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerBlockHighLevel',
|
||||
display_name='AD Per Block 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('AD_BLOCK').Input('down', optional=True), io.Custom('AD_BLOCK').Input('mid', optional=True), io.Custom('AD_BLOCK').Input('up', optional=True)],
|
||||
outputs=[io.Custom('PER_BLOCK').Output('PER_BLOCK')]
|
||||
)
|
||||
NodeID = 'ADE_PerBlockHighLevel'
|
||||
NodeName = 'AD Per Block 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"down": ("AD_BLOCK",),
|
||||
"mid": ("AD_BLOCK",),
|
||||
"up": ("AD_BLOCK",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PER_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "create_per_block"
|
||||
|
||||
def create_per_block(self,
|
||||
def execute(cls,
|
||||
down: Union[ADBlockHolder, None]=None,
|
||||
mid: Union[ADBlockHolder, None]=None,
|
||||
up: Union[ADBlockHolder, None]=None):
|
||||
@@ -120,36 +99,23 @@ class PerBlockHighLevelNode:
|
||||
blocks.append(PerBlock(id=id, effect=block.effect, scales=block.scales))
|
||||
if len(blocks) == 0:
|
||||
blocks = None
|
||||
return (AllPerBlocks(blocks),)
|
||||
return io.NodeOutput(AllPerBlocks(blocks))
|
||||
|
||||
|
||||
class PerBlock_SD15_MidLevelNode:
|
||||
class PerBlock_SD15_MidLevelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerBlock_SD15_MidLevel',
|
||||
display_name='AD Per Block+ (SD1.5) 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('AD_BLOCK').Input('down_0', optional=True), io.Custom('AD_BLOCK').Input('down_1', optional=True), io.Custom('AD_BLOCK').Input('down_2', optional=True), io.Custom('AD_BLOCK').Input('down_3', optional=True), io.Custom('AD_BLOCK').Input('mid', optional=True), io.Custom('AD_BLOCK').Input('up_0', optional=True), io.Custom('AD_BLOCK').Input('up_1', optional=True), io.Custom('AD_BLOCK').Input('up_2', optional=True), io.Custom('AD_BLOCK').Input('up_3', optional=True)],
|
||||
outputs=[io.Custom('PER_BLOCK').Output('PER_BLOCK')]
|
||||
)
|
||||
NodeID = 'ADE_PerBlock_SD15_MidLevel'
|
||||
NodeName = 'AD Per Block+ (SD1.5) 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"down_0": ("AD_BLOCK",),
|
||||
"down_1": ("AD_BLOCK",),
|
||||
"down_2": ("AD_BLOCK",),
|
||||
"down_3": ("AD_BLOCK",),
|
||||
"mid": ("AD_BLOCK",),
|
||||
"up_0": ("AD_BLOCK",),
|
||||
"up_1": ("AD_BLOCK",),
|
||||
"up_2": ("AD_BLOCK",),
|
||||
"up_3": ("AD_BLOCK",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PER_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "create_per_block"
|
||||
|
||||
def create_per_block(self,
|
||||
def execute(cls,
|
||||
down_0: Union[ADBlockHolder, None]=None,
|
||||
down_1: Union[ADBlockHolder, None]=None,
|
||||
down_2: Union[ADBlockHolder, None]=None,
|
||||
@@ -176,48 +142,23 @@ class PerBlock_SD15_MidLevelNode:
|
||||
blocks.append(PerBlock(id=id, effect=block.effect, scales=block.scales))
|
||||
if len(blocks) == 0:
|
||||
blocks = None
|
||||
return (AllPerBlocks(blocks, ModelTypeSD.SD1_5),)
|
||||
return io.NodeOutput(AllPerBlocks(blocks, ModelTypeSD.SD1_5))
|
||||
|
||||
|
||||
class PerBlock_SD15_LowLevelNode:
|
||||
class PerBlock_SD15_LowLevelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerBlock_SD15_LowLevel',
|
||||
display_name='AD Per Block++ (SD1.5) 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('AD_BLOCK').Input('down_0__0', optional=True), io.Custom('AD_BLOCK').Input('down_0__1', optional=True), io.Custom('AD_BLOCK').Input('down_1__0', optional=True), io.Custom('AD_BLOCK').Input('down_1__1', optional=True), io.Custom('AD_BLOCK').Input('down_2__0', optional=True), io.Custom('AD_BLOCK').Input('down_2__1', optional=True), io.Custom('AD_BLOCK').Input('down_3__0', optional=True), io.Custom('AD_BLOCK').Input('down_3__1', optional=True), io.Custom('AD_BLOCK').Input('mid', optional=True), io.Custom('AD_BLOCK').Input('up_0__0', optional=True), io.Custom('AD_BLOCK').Input('up_0__1', optional=True), io.Custom('AD_BLOCK').Input('up_0__2', optional=True), io.Custom('AD_BLOCK').Input('up_1__0', optional=True), io.Custom('AD_BLOCK').Input('up_1__1', optional=True), io.Custom('AD_BLOCK').Input('up_1__2', optional=True), io.Custom('AD_BLOCK').Input('up_2__0', optional=True), io.Custom('AD_BLOCK').Input('up_2__1', optional=True), io.Custom('AD_BLOCK').Input('up_2__2', optional=True), io.Custom('AD_BLOCK').Input('up_3__0', optional=True), io.Custom('AD_BLOCK').Input('up_3__1', optional=True), io.Custom('AD_BLOCK').Input('up_3__2', optional=True)],
|
||||
outputs=[io.Custom('PER_BLOCK').Output('PER_BLOCK')]
|
||||
)
|
||||
NodeID = 'ADE_PerBlock_SD15_LowLevel'
|
||||
NodeName = 'AD Per Block++ (SD1.5) 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"down_0__0": ("AD_BLOCK",),
|
||||
"down_0__1": ("AD_BLOCK",),
|
||||
"down_1__0": ("AD_BLOCK",),
|
||||
"down_1__1": ("AD_BLOCK",),
|
||||
"down_2__0": ("AD_BLOCK",),
|
||||
"down_2__1": ("AD_BLOCK",),
|
||||
"down_3__0": ("AD_BLOCK",),
|
||||
"down_3__1": ("AD_BLOCK",),
|
||||
"mid": ("AD_BLOCK",),
|
||||
"up_0__0": ("AD_BLOCK",),
|
||||
"up_0__1": ("AD_BLOCK",),
|
||||
"up_0__2": ("AD_BLOCK",),
|
||||
"up_1__0": ("AD_BLOCK",),
|
||||
"up_1__1": ("AD_BLOCK",),
|
||||
"up_1__2": ("AD_BLOCK",),
|
||||
"up_2__0": ("AD_BLOCK",),
|
||||
"up_2__1": ("AD_BLOCK",),
|
||||
"up_2__2": ("AD_BLOCK",),
|
||||
"up_3__0": ("AD_BLOCK",),
|
||||
"up_3__1": ("AD_BLOCK",),
|
||||
"up_3__2": ("AD_BLOCK",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PER_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "create_per_block"
|
||||
|
||||
def create_per_block(self,
|
||||
def execute(cls,
|
||||
down_0__0: Union[ADBlockHolder, None]=None,
|
||||
down_0__1: Union[ADBlockHolder, None]=None,
|
||||
down_1__0: Union[ADBlockHolder, None]=None,
|
||||
@@ -268,44 +209,28 @@ class PerBlock_SD15_LowLevelNode:
|
||||
blocks.append(PerBlock(id=id, effect=block.effect, scales=block.scales))
|
||||
if len(blocks) == 0:
|
||||
blocks = None
|
||||
return (AllPerBlocks(blocks, ModelTypeSD.SD1_5),)
|
||||
return io.NodeOutput(AllPerBlocks(blocks, ModelTypeSD.SD1_5))
|
||||
|
||||
|
||||
class PerBlock_SD15_FromFloatsNode:
|
||||
class PerBlock_SD15_FromFloatsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerBlock_SD15_FromFloats',
|
||||
display_name='AD Per Block Floats (SD1.5) 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('FLOATS').Input('effect_21_floats', optional=True), io.Custom('FLOATS').Input('scale_21_floats', optional=True)],
|
||||
outputs=[io.Custom('PER_BLOCK').Output('PER_BLOCK')],
|
||||
description='Use Floats from Value Schedules to select SD1.5 effect/scale values for blocks.'
|
||||
)
|
||||
NodeID = 'ADE_PerBlock_SD15_FromFloats'
|
||||
NodeName = 'AD Per Block Floats (SD1.5) 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"effect_21_floats": ("FLOATS",),
|
||||
"scale_21_floats": ("FLOATS",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PER_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "create_per_block"
|
||||
|
||||
Desc = [
|
||||
short_desc('Use Floats from Value Schedules to select SD1.5 effect/scale values for blocks.'),
|
||||
'SD1.5 Motion Modules contain 21 blocks:',
|
||||
'idx 0 - start of down blocks (down_0__0)',
|
||||
'idx 7 - end of down blocks (down_3__1)',
|
||||
'idx 8 - mid block (mid)',
|
||||
'idx 9 - start of up blocks (up_0__0)',
|
||||
'idx 20 - end of up blocks (up_3__2)',
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def create_per_block(self,
|
||||
def execute(cls,
|
||||
effect_21_floats: Union[list[float], None]=None,
|
||||
scale_21_floats: Union[list[float], None]=None):
|
||||
if effect_21_floats is None and scale_21_floats is None:
|
||||
return (AllPerBlocks(None, ModelTypeSD.SD1_5),)
|
||||
return io.NodeOutput(AllPerBlocks(None, ModelTypeSD.SD1_5))
|
||||
# SD1.5 has 21 blocks
|
||||
block_total = 21
|
||||
holders = [ADBlockHolder() for _ in range(block_total)]
|
||||
@@ -317,34 +242,23 @@ class PerBlock_SD15_FromFloatsNode:
|
||||
scale_21_floats = extend_list_to_batch_size(scale_21_floats, block_total)
|
||||
for scale, holder in zip(scale_21_floats, holders):
|
||||
holder.scales = [scale, scale]
|
||||
return PerBlock_SD15_LowLevelNode.create_per_block(self, *holders)
|
||||
return PerBlock_SD15_LowLevelNode.execute(*holders)
|
||||
|
||||
|
||||
class PerBlock_SDXL_MidLevelNode:
|
||||
class PerBlock_SDXL_MidLevelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerBlock_SDXL_MidLevel',
|
||||
display_name='AD Per Block+ (SDXL) 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('AD_BLOCK').Input('down_0', optional=True), io.Custom('AD_BLOCK').Input('down_1', optional=True), io.Custom('AD_BLOCK').Input('down_2', optional=True), io.Custom('AD_BLOCK').Input('mid', optional=True), io.Custom('AD_BLOCK').Input('up_0', optional=True), io.Custom('AD_BLOCK').Input('up_1', optional=True), io.Custom('AD_BLOCK').Input('up_2', optional=True)],
|
||||
outputs=[io.Custom('PER_BLOCK').Output('PER_BLOCK')]
|
||||
)
|
||||
NodeID = 'ADE_PerBlock_SDXL_MidLevel'
|
||||
NodeName = 'AD Per Block+ (SDXL) 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"down_0": ("AD_BLOCK",),
|
||||
"down_1": ("AD_BLOCK",),
|
||||
"down_2": ("AD_BLOCK",),
|
||||
"mid": ("AD_BLOCK",),
|
||||
"up_0": ("AD_BLOCK",),
|
||||
"up_1": ("AD_BLOCK",),
|
||||
"up_2": ("AD_BLOCK",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PER_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "create_per_block"
|
||||
|
||||
def create_per_block(self,
|
||||
def execute(cls,
|
||||
down_0: Union[ADBlockHolder, None]=None,
|
||||
down_1: Union[ADBlockHolder, None]=None,
|
||||
down_2: Union[ADBlockHolder, None]=None,
|
||||
@@ -367,43 +281,23 @@ class PerBlock_SDXL_MidLevelNode:
|
||||
blocks.append(PerBlock(id=id, effect=block.effect, scales=block.scales))
|
||||
if len(blocks) == 0:
|
||||
blocks = None
|
||||
return (AllPerBlocks(blocks, ModelTypeSD.SDXL),)
|
||||
return io.NodeOutput(AllPerBlocks(blocks, ModelTypeSD.SDXL))
|
||||
|
||||
|
||||
class PerBlock_SDXL_LowLevelNode:
|
||||
class PerBlock_SDXL_LowLevelNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerBlock_SDXL_LowLevel',
|
||||
display_name='AD Per Block++ (SDXL) 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('AD_BLOCK').Input('down_0__0', optional=True), io.Custom('AD_BLOCK').Input('down_0__1', optional=True), io.Custom('AD_BLOCK').Input('down_1__0', optional=True), io.Custom('AD_BLOCK').Input('down_1__1', optional=True), io.Custom('AD_BLOCK').Input('down_2__0', optional=True), io.Custom('AD_BLOCK').Input('down_2__1', optional=True), io.Custom('AD_BLOCK').Input('mid', optional=True), io.Custom('AD_BLOCK').Input('up_0__0', optional=True), io.Custom('AD_BLOCK').Input('up_0__1', optional=True), io.Custom('AD_BLOCK').Input('up_0__2', optional=True), io.Custom('AD_BLOCK').Input('up_1__0', optional=True), io.Custom('AD_BLOCK').Input('up_1__1', optional=True), io.Custom('AD_BLOCK').Input('up_1__2', optional=True), io.Custom('AD_BLOCK').Input('up_2__0', optional=True), io.Custom('AD_BLOCK').Input('up_2__1', optional=True), io.Custom('AD_BLOCK').Input('up_2__2', optional=True)],
|
||||
outputs=[io.Custom('PER_BLOCK').Output('PER_BLOCK')]
|
||||
)
|
||||
NodeID = 'ADE_PerBlock_SDXL_LowLevel'
|
||||
NodeName = 'AD Per Block++ (SDXL) 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"down_0__0": ("AD_BLOCK",),
|
||||
"down_0__1": ("AD_BLOCK",),
|
||||
"down_1__0": ("AD_BLOCK",),
|
||||
"down_1__1": ("AD_BLOCK",),
|
||||
"down_2__0": ("AD_BLOCK",),
|
||||
"down_2__1": ("AD_BLOCK",),
|
||||
"mid": ("AD_BLOCK",),
|
||||
"up_0__0": ("AD_BLOCK",),
|
||||
"up_0__1": ("AD_BLOCK",),
|
||||
"up_0__2": ("AD_BLOCK",),
|
||||
"up_1__0": ("AD_BLOCK",),
|
||||
"up_1__1": ("AD_BLOCK",),
|
||||
"up_1__2": ("AD_BLOCK",),
|
||||
"up_2__0": ("AD_BLOCK",),
|
||||
"up_2__1": ("AD_BLOCK",),
|
||||
"up_2__2": ("AD_BLOCK",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PER_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "create_per_block"
|
||||
|
||||
def create_per_block(self,
|
||||
def execute(cls,
|
||||
down_0__0: Union[ADBlockHolder, None]=None,
|
||||
down_0__1: Union[ADBlockHolder, None]=None,
|
||||
down_1__0: Union[ADBlockHolder, None]=None,
|
||||
@@ -444,44 +338,28 @@ class PerBlock_SDXL_LowLevelNode:
|
||||
blocks.append(PerBlock(id=id, effect=block.effect, scales=block.scales))
|
||||
if len(blocks) == 0:
|
||||
blocks = None
|
||||
return (AllPerBlocks(blocks, ModelTypeSD.SDXL),)
|
||||
return io.NodeOutput(AllPerBlocks(blocks, ModelTypeSD.SDXL))
|
||||
|
||||
|
||||
class PerBlock_SDXL_FromFloatsNode:
|
||||
class PerBlock_SDXL_FromFloatsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PerBlock_SDXL_FromFloats',
|
||||
display_name='AD Per Block Floats (SDXL) 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/per block',
|
||||
inputs=[io.Custom('FLOATS').Input('effect_16_floats', optional=True), io.Custom('FLOATS').Input('scale_16_floats', optional=True)],
|
||||
outputs=[io.Custom('PER_BLOCK').Output('PER_BLOCK')],
|
||||
description='Use Floats from Value Schedules to select SDXL effect/scale values for blocks.'
|
||||
)
|
||||
NodeID = 'ADE_PerBlock_SDXL_FromFloats'
|
||||
NodeName = 'AD Per Block Floats (SDXL) 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
},
|
||||
"optional": {
|
||||
"effect_16_floats": ("FLOATS",),
|
||||
"scale_16_floats": ("FLOATS",),
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("PER_BLOCK",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/per block"
|
||||
FUNCTION = "create_per_block"
|
||||
|
||||
Desc = [
|
||||
short_desc('Use Floats from Value Schedules to select SDXL effect/scale values for blocks.'),
|
||||
'SDXL Motion Modules contain 16 blocks:',
|
||||
'idx 0 - start of down blocks (down_0__0)',
|
||||
'idx 5 - end of down blocks (down_2__1)',
|
||||
'idx 6 - mid block (mid)',
|
||||
'idx 7 - start of up blocks (up_0__0)',
|
||||
'idx 15 - end of up blocks (up_2__2)',
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def create_per_block(self,
|
||||
def execute(cls,
|
||||
effect_16_floats: Union[list[float], None]=None,
|
||||
scale_16_floats: Union[list[float], None]=None):
|
||||
if effect_16_floats is None and scale_16_floats is None:
|
||||
return (AllPerBlocks(None, ModelTypeSD.SDXL),)
|
||||
return io.NodeOutput(AllPerBlocks(None, ModelTypeSD.SDXL))
|
||||
# SDXL has 16 blocks
|
||||
block_total = 16
|
||||
holders = [ADBlockHolder() for _ in range(block_total)]
|
||||
@@ -493,4 +371,4 @@ class PerBlock_SDXL_FromFloatsNode:
|
||||
scale_16_floats = extend_list_to_batch_size(scale_16_floats, block_total)
|
||||
for scale, holder in zip(scale_16_floats, holders):
|
||||
holder.scales = [scale, scale]
|
||||
return PerBlock_SDXL_LowLevelNode.create_per_block(self, *holders)
|
||||
return PerBlock_SDXL_LowLevelNode.execute(*holders)
|
||||
|
||||
+109
-110
@@ -1,3 +1,4 @@
|
||||
from comfy_api.latest import io
|
||||
from typing import Union
|
||||
import torch
|
||||
from torch import Tensor
|
||||
@@ -107,44 +108,43 @@ class InputPIA_PaperPresets(InputPIA):
|
||||
return mask
|
||||
|
||||
|
||||
class ApplyAnimateDiffPIAModel:
|
||||
class ApplyAnimateDiffPIAModel(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"motion_model": ("MOTION_MODEL_ADE",),
|
||||
"image": ("IMAGE",),
|
||||
"vae": ("VAE",),
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
},
|
||||
"optional": {
|
||||
"pia_input": ("PIA_INPUT",),
|
||||
"motion_lora": ("MOTION_LORA",),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"ad_keyframes": ("AD_KEYFRAMES",),
|
||||
"prev_m_models": ("M_MODELS",),
|
||||
"per_block": ("PER_BLOCK",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ApplyAnimateDiffModelWithPIA',
|
||||
display_name='Apply AnimateDiff-PIA Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA',
|
||||
inputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Input('motion_model'),
|
||||
io.Image.Input('image'),
|
||||
io.Vae.Input('vae'),
|
||||
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Custom("PIA_INPUT").Input('pia_input', optional=True),
|
||||
io.Custom("MOTION_LORA").Input('motion_lora', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("AD_KEYFRAMES").Input('ad_keyframes', optional=True),
|
||||
io.Custom("M_MODELS").Input('prev_m_models', optional=True),
|
||||
io.Custom("PER_BLOCK").Input('per_block', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("M_MODELS").Output('M_MODELS'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("M_MODELS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA"
|
||||
FUNCTION = "apply_motion_model"
|
||||
|
||||
def apply_motion_model(self, motion_model: MotionModelPatcher, image: Tensor, vae: VAE,
|
||||
@classmethod
|
||||
def execute(cls, motion_model: MotionModelPatcher, image: Tensor, vae: VAE,
|
||||
start_percent: float=0.0, end_percent: float=1.0, pia_input: InputPIA=None,
|
||||
motion_lora: MotionLoraList=None, ad_keyframes: ADKeyframeGroup=None,
|
||||
scale_multival=None, effect_multival=None, ref_multival=None, per_block=None,
|
||||
prev_m_models: MotionModelGroup=None,):
|
||||
new_m_models = ApplyAnimateDiffModelNode.apply_motion_model(self, motion_model, start_percent=start_percent, end_percent=end_percent,
|
||||
new_m_models = ApplyAnimateDiffModelNode.execute( motion_model, start_percent=start_percent, end_percent=end_percent,
|
||||
motion_lora=motion_lora, ad_keyframes=ad_keyframes,
|
||||
scale_multival=scale_multival, effect_multival=effect_multival, per_block=per_block,
|
||||
prev_m_models=prev_m_models)
|
||||
prev_m_models=prev_m_models).args
|
||||
# most recent added model will always be first in list;
|
||||
curr_model = new_m_models[0].models[0]
|
||||
# confirm that model is PIA
|
||||
@@ -157,121 +157,120 @@ class ApplyAnimateDiffPIAModel:
|
||||
pia_input = InputPIA_Multival(1.0)
|
||||
attachment.pia_input = pia_input
|
||||
#curr_model.pia_multival = ref_multival
|
||||
return new_m_models
|
||||
return io.NodeOutput(*new_m_models)
|
||||
|
||||
|
||||
class LoadAnimateDiffAndInjectPIANode:
|
||||
class LoadAnimateDiffAndInjectPIANode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"model_name": (get_available_motion_models(),),
|
||||
"motion_model": ("MOTION_MODEL_ADE",),
|
||||
},
|
||||
"optional": {
|
||||
"ad_settings": ("AD_SETTINGS",),
|
||||
"deprecation_warning": ("ADEWARN", {"text": "Experimental. Don't expect to work.", "warn_type": "experimental", "color": "#CFC"}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_InjectPIAIntoAnimateDiffModel',
|
||||
display_name='🧪Inject PIA into AnimateDiff Model 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA/🧪experimental',
|
||||
inputs=[
|
||||
io.Combo.Input('model_name', options=get_available_motion_models()),
|
||||
io.Custom("MOTION_MODEL_ADE").Input('motion_model'),
|
||||
io.Custom("AD_SETTINGS").Input('ad_settings', optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("MOTION_MODEL_ADE").Output('MOTION_MODEL'),
|
||||
],
|
||||
is_experimental=True,
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("MOTION_MODEL_ADE",)
|
||||
RETURN_NAMES = ("MOTION_MODEL",)
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA/🧪experimental"
|
||||
FUNCTION = "load_motion_model"
|
||||
|
||||
def load_motion_model(self, model_name: str, motion_model: MotionModelPatcher, ad_settings: AnimateDiffSettings=None):
|
||||
@classmethod
|
||||
def execute(cls, model_name: str, motion_model: MotionModelPatcher, ad_settings: AnimateDiffSettings=None):
|
||||
# make sure model actually has PIA conv_in
|
||||
if motion_model.model.conv_in is None:
|
||||
raise Exception("Passed-in motion model was expected to be PIA (contain conv_in), but did not.")
|
||||
# load motion module and motion settings, if included
|
||||
loaded_motion_model = load_motion_module_gen2(model_name=model_name, motion_model_settings=ad_settings)
|
||||
inject_pia_conv_in_into_model(motion_model=loaded_motion_model, w_pia=motion_model)
|
||||
return (loaded_motion_model,)
|
||||
return io.NodeOutput(loaded_motion_model,)
|
||||
|
||||
|
||||
class PIA_ADKeyframeNode:
|
||||
class PIA_ADKeyframeNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
||||
},
|
||||
"optional": {
|
||||
"prev_ad_keyframes": ("AD_KEYFRAMES", ),
|
||||
"scale_multival": ("MULTIVAL",),
|
||||
"effect_multival": ("MULTIVAL",),
|
||||
"pia_input": ("PIA_INPUT",),
|
||||
"inherit_missing": ("BOOLEAN", {"default": True}, ),
|
||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PIA_AnimateDiffKeyframe',
|
||||
display_name='AnimateDiff-PIA Keyframe 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA',
|
||||
inputs=[
|
||||
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||
io.Custom("AD_KEYFRAMES").Input('prev_ad_keyframes', optional=True),
|
||||
io.Custom("MULTIVAL").Input('scale_multival', optional=True),
|
||||
io.Custom("MULTIVAL").Input('effect_multival', optional=True),
|
||||
io.Custom("PIA_INPUT").Input('pia_input', optional=True),
|
||||
io.Boolean.Input('inherit_missing', optional=True, default=True),
|
||||
io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("AD_KEYFRAMES").Output('AD_KEYFRAMES'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("AD_KEYFRAMES", )
|
||||
FUNCTION = "load_keyframe"
|
||||
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA"
|
||||
|
||||
def load_keyframe(self,
|
||||
@classmethod
|
||||
def execute(cls,
|
||||
start_percent: float, prev_ad_keyframes=None,
|
||||
scale_multival: Union[float, torch.Tensor]=None, effect_multival: Union[float, torch.Tensor]=None,
|
||||
pia_input: InputPIA=None,
|
||||
inherit_missing: bool=True, guarantee_steps: int=1):
|
||||
return ADKeyframeNode.load_keyframe(self,
|
||||
return io.NodeOutput(*ADKeyframeNode.execute(
|
||||
start_percent=start_percent, prev_ad_keyframes=prev_ad_keyframes,
|
||||
scale_multival=scale_multival, effect_multival=effect_multival, pia_input=pia_input,
|
||||
inherit_missing=inherit_missing, guarantee_steps=guarantee_steps
|
||||
)
|
||||
).args)
|
||||
|
||||
|
||||
class InputPIA_MultivalNode:
|
||||
class InputPIA_MultivalNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"multival": ("MULTIVAL",),
|
||||
},
|
||||
# "optional": {
|
||||
# "effect_multival": ("MULTIVAL",),
|
||||
# }
|
||||
}
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_InputPIA_Multival',
|
||||
display_name='PIA Input [Multival] 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA',
|
||||
inputs=[
|
||||
io.Custom("MULTIVAL").Input('multival'),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("PIA_INPUT").Output('PIA_INPUT'),
|
||||
],
|
||||
)
|
||||
|
||||
RETURN_TYPES = ("PIA_INPUT",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA"
|
||||
FUNCTION = "create_pia_input"
|
||||
|
||||
def create_pia_input(self, multival: Union[float, Tensor], effect_multival: Union[float, Tensor]=None):
|
||||
return (InputPIA_Multival(multival, effect_multival),)
|
||||
|
||||
|
||||
class InputPIA_PaperPresetsNode:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"preset": (PIA_RANGES._LIST_ALL,),
|
||||
"batch_index": ("INT", {"default": 0, "min": BIGMIN, "max": BIGMAX, "step": 1}),
|
||||
},
|
||||
"optional": {
|
||||
"mult_multival": ("MULTIVAL",),
|
||||
"print_values": ("BOOLEAN", {"default": False},),
|
||||
#"effect_multival": ("MULTIVAL",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
def execute(cls, multival: Union[float, Tensor], effect_multival: Union[float, Tensor]=None):
|
||||
return io.NodeOutput(InputPIA_Multival(multival, effect_multival),)
|
||||
|
||||
RETURN_TYPES = ("PIA_INPUT",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA"
|
||||
FUNCTION = "create_pia_input"
|
||||
|
||||
def create_pia_input(self, preset: str, batch_index: int, mult_multival: Union[float, Tensor]=None, print_values: bool=False, effect_multival: Union[float, Tensor]=None):
|
||||
class InputPIA_PaperPresetsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_InputPIA_PaperPresets',
|
||||
display_name='PIA Input [Paper Presets] 🎭🅐🅓②',
|
||||
category='Animate Diff 🎭🅐🅓/② Gen2 nodes ②/PIA',
|
||||
inputs=[
|
||||
io.Combo.Input('preset', options=['Animation (Small Motion)', 'Animation (Medium Motion)', 'Animation (Large Motion)', 'Loop (Small Motion)', 'Loop (Medium Motion)', 'Loop (Large Motion)', 'Style Transfer (Small Motion)', 'Style Transfer (Medium Motion)', 'Style Transfer (Large Motion)']),
|
||||
io.Int.Input('batch_index', default=0, max=9007199254740991, min=-9007199254740991, step=1),
|
||||
io.Custom("MULTIVAL").Input('mult_multival', optional=True),
|
||||
io.Boolean.Input('print_values', optional=True, default=False),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("PIA_INPUT").Output('PIA_INPUT'),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@classmethod
|
||||
def execute(cls, preset: str, batch_index: int, mult_multival: Union[float, Tensor]=None, print_values: bool=False, effect_multival: Union[float, Tensor]=None):
|
||||
# verify preset exists - function will throw error if does not
|
||||
values = PIA_RANGES.get_preset(preset)
|
||||
if print_values:
|
||||
logger.info(f"PIA Preset '{preset}': {values}")
|
||||
return (InputPIA_PaperPresets(preset=preset, index=batch_index, mult_multival=mult_multival, effect_multival=effect_multival),)
|
||||
return io.NodeOutput(InputPIA_PaperPresets(preset=preset, index=batch_index, mult_multival=mult_multival, effect_multival=effect_multival),)
|
||||
|
||||
+436
-455
File diff suppressed because it is too large
Load Diff
+92
-240
@@ -1,253 +1,119 @@
|
||||
from typing import Union
|
||||
|
||||
from .documentation import register_description, short_desc, coll, DocHelper
|
||||
from comfy_api.latest import io
|
||||
|
||||
from .scheduling import (evaluate_prompt_schedule, evaluate_value_schedule, extract_cond_from_schedule, TensorInterp, PromptOptions,
|
||||
verify_key_value)
|
||||
from .utils_model import BIGMAX
|
||||
from .logger import logger
|
||||
|
||||
|
||||
desc_values = {coll('values'): 'Write your values here.'}
|
||||
desc_prompts = {coll('prompts'): 'Write your prompts here.'}
|
||||
desc_clip = {'clip': 'CLIP to use for encoding prompts.'}
|
||||
desc_latent = {'latent': 'Used to get the amount of frames (max_length) to use for scheduling.'}
|
||||
|
||||
desc_prepend_text = {'prepend_text': 'OPTIONAL, adds text before all prompts.'}
|
||||
desc_append_text = {'append_text': 'OPTIONAL, adds text after all prompts.'}
|
||||
desc_values_replace = {'values_replace': 'OPTIONAL, replaces keys from value_replace keys with provided value schedules. Keys in the prompt are written as `some_key`, surrounded by the ` characters.'}
|
||||
desc_tensor_interp = {'tensor_interp': 'Selects method of interpolating prompt conds - defaults to lerp.'}
|
||||
desc_print_schedule = {'print_schedule': 'When True, prints output values for each frame.'}
|
||||
|
||||
desc_max_length = {'max_length': 'Used to select the intended length of schedule. If set to 0, will use the largest index in the schedule as max_length, but will disable relative indexes (negative and decimal).'}
|
||||
desc_floats = {'floats': 'List of floats, likely outputted by a Value Scheduling node.'}
|
||||
desc_FLOAT = {'FLOAT': 'Float (or list of floats) to convert to FLOATS type.'}
|
||||
desc_value_key = {'value_key': 'Key to use for value schedule in Prompt Scheduling node. Can only contain a-z, A-Z, 0-9, and _ characters. In Prompt Scheduling, keys can be referred to as `some_key`, where the key is surrounded by ` characters.'}
|
||||
desc_prev_replace = {'prev_replace': 'OPTIONAL, other values_replace can be chained.'}
|
||||
|
||||
desc_input_conditioning = {'conditioning': 'Encoded prompts. The output of a Prompt Scheduling node.'}
|
||||
desc_index = {'index': 'The index to extract. Must be within the range [0,N] where N is the length of scheduled prompts.'}
|
||||
desc_output_conditioning_single = {'CONDITIONING': 'The single step conditioning from the schedule.'}
|
||||
|
||||
desc_output_conditioning = {'CONDITIONING': 'Encoded prompts.'}
|
||||
desc_output_latent = {'LATENT': 'Unmodified input latents; can be used as pipe, or can be ignored.'}
|
||||
|
||||
desc_format_allowed_idxs = {'allowed idxs':
|
||||
{'single': 'A positive integer (e.g. 0, 2) schedules value for frame. A negative integer (e.g. -1, -5) schedules value for frame from the end (-1 would be the last frame). ' +
|
||||
'A decimal (e.g. 0.5, 1.0) selects frame based relative location in whole schedule (0.5 would be halfway, 1.0 would be last frame).',
|
||||
'range': 'Using rules above, single:single chooses uninterpolated prompts from start idx (included) to end idx (excluded). Examples -> 0:12, 0:-5, 2:0.5',
|
||||
'hold': 'Putting a colon after a single idx stops interpolation until the next provided index. Examples -> 0:, 0.5:, 16: '}
|
||||
}
|
||||
|
||||
desc_format_prompt = [
|
||||
'Scheduling supports two formats: JSON and pythonic.',
|
||||
{'JSON': ['"idx": "your prompt here", ...'],
|
||||
'pythonic': ['idx = "your prompt here", ...']},
|
||||
'The idx is the index of the frame - first frame is 0, last frame is max_frames-1. An idx may be the following:',
|
||||
desc_format_allowed_idxs,
|
||||
'The prompts themselves should be surrounded by double quotes ("your prompt here"). Portions of prompts can use value schedules provided values_replace.',
|
||||
{'JSON': ['"0": "blue rock on mountain",', '"16": "green rock in lake"'],
|
||||
'pythonic': ['0 = "blue rock on mountain",', '16 = "green rock in lake"']}
|
||||
]
|
||||
|
||||
desc_format_values = [
|
||||
'Scheduling supports two formats: JSON and pythonic.',
|
||||
{'JSON': ['"idx": float/int_value, ...'],
|
||||
'pythonic': ['idx = float/int_value, ...']},
|
||||
'The idx is the index of the frame - first frame is 0, last frame is max_frames-1. An idx may be the following:',
|
||||
desc_format_allowed_idxs,
|
||||
'The values can be written without any special formatting.',
|
||||
{'JSON': ['"0": 1.0,', '"16": 1.3'],
|
||||
'pythonic': ['0 = 1.0,', '16 = 1.3']}
|
||||
]
|
||||
|
||||
|
||||
class PromptSchedulingLatentsNode:
|
||||
class PromptSchedulingLatentsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PromptSchedulingLatents',
|
||||
display_name='Prompt Scheduling [Latents] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/scheduling',
|
||||
inputs=[io.String.Input('prompts', default='', multiline=True), io.Clip.Input('clip'), io.Latent.Input('latent'), io.String.Input('prepend_text', default='', force_input=True, multiline=True, optional=True), io.String.Input('append_text', default='', force_input=True, multiline=True, optional=True), io.Custom('VALUES_REPLACE').Input('values_replace', optional=True), io.Boolean.Input('print_schedule', default=False, optional=True), io.Combo.Input('tensor_interp', options=['lerp', 'slerp'] , optional=True)],
|
||||
outputs=[io.Conditioning.Output('CONDITIONING'), io.Latent.Output('LATENT')],
|
||||
description='Encode a schedule of prompts with automatic interpolation, its length matching passed-in latent count.'
|
||||
)
|
||||
NodeID = 'ADE_PromptSchedulingLatents'
|
||||
NodeName = 'Prompt Scheduling [Latents] 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"prompts": ("STRING", {"multiline": True, "default": ''}),
|
||||
"clip": ("CLIP",),
|
||||
"latent": ("LATENT",),
|
||||
},
|
||||
"optional": {
|
||||
"prepend_text": ("STRING", {"multiline": True, "default": '', "forceInput": True}),
|
||||
"append_text": ("STRING", {"multiline": True, "default": '', "forceInput": True}),
|
||||
"values_replace": ("VALUES_REPLACE",),
|
||||
"print_schedule": ("BOOLEAN", {"default": False}),
|
||||
"tensor_interp": (TensorInterp._LIST,)
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "LATENT",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/scheduling"
|
||||
FUNCTION = "create_schedule"
|
||||
|
||||
Desc = [
|
||||
short_desc('Encode a schedule of prompts with automatic interpolation, its length matching passed-in latent count.'),
|
||||
{'Format': desc_format_prompt},
|
||||
{coll('Inputs'): DocHelper.combine(desc_prompts, desc_clip, desc_latent, desc_values_replace, desc_prepend_text, desc_append_text, desc_tensor_interp, desc_print_schedule)},
|
||||
{coll('Outputs'): DocHelper.combine(desc_output_conditioning, desc_output_latent)}
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def create_schedule(self, prompts: str, clip, latent: dict, print_schedule=False, tensor_interp=TensorInterp.LERP,
|
||||
def execute(cls, prompts: str, clip, latent: dict, print_schedule=False, tensor_interp=TensorInterp.LERP,
|
||||
prepend_text='', append_text='', values_replace=None):
|
||||
options = PromptOptions(interp=tensor_interp, prepend_text=prepend_text, append_text=append_text,
|
||||
values_replace=values_replace, print_schedule=print_schedule)
|
||||
conditioning = evaluate_prompt_schedule(prompts, latent["samples"].size(0), clip, options)
|
||||
return (conditioning, latent)
|
||||
return io.NodeOutput(conditioning, latent)
|
||||
|
||||
|
||||
class PromptSchedulingNode:
|
||||
class PromptSchedulingNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_PromptScheduling',
|
||||
display_name='Prompt Scheduling 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/scheduling',
|
||||
inputs=[io.String.Input('prompts', default='', multiline=True), io.Clip.Input('clip'), io.String.Input('prepend_text', default='', force_input=True, multiline=True, optional=True), io.String.Input('append_text', default='', force_input=True, multiline=True, optional=True), io.Custom('VALUES_REPLACE').Input('values_replace', optional=True), io.Boolean.Input('print_schedule', default=False, optional=True), io.Int.Input('max_length', default=0, max=9007199254740991, min=0, step=1, optional=True), io.Combo.Input('tensor_interp', options=['lerp', 'slerp'] , optional=True)],
|
||||
outputs=[io.Conditioning.Output('CONDITIONING')],
|
||||
description='Encode a schedule of prompts with automatic interpolation.'
|
||||
)
|
||||
NodeID = 'ADE_PromptScheduling'
|
||||
NodeName = 'Prompt Scheduling 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"prompts": ("STRING", {"multiline": True, "default": ''}),
|
||||
"clip": ("CLIP",),
|
||||
},
|
||||
"optional": {
|
||||
"prepend_text": ("STRING", {"multiline": True, "default": '', "forceInput": True}),
|
||||
"append_text": ("STRING", {"multiline": True, "default": '', "forceInput": True}),
|
||||
"values_replace": ("VALUES_REPLACE",),
|
||||
"print_schedule": ("BOOLEAN", {"default": False}),
|
||||
"max_length": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}),
|
||||
"tensor_interp": (TensorInterp._LIST,)
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/scheduling"
|
||||
FUNCTION = "create_schedule"
|
||||
|
||||
Desc = [
|
||||
short_desc('Encode a schedule of prompts with automatic interpolation.'),
|
||||
{'Format': desc_format_prompt},
|
||||
{coll('Inputs'): DocHelper.combine(desc_prompts, desc_clip, desc_values_replace, desc_prepend_text, desc_append_text, desc_max_length, desc_tensor_interp, desc_print_schedule)},
|
||||
{coll('Outputs'): DocHelper.combine(desc_output_conditioning)}
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def create_schedule(self, prompts: str, clip, print_schedule=False, max_length: int=0, tensor_interp=TensorInterp.LERP,
|
||||
def execute(cls, prompts: str, clip, print_schedule=False, max_length: int=0, tensor_interp=TensorInterp.LERP,
|
||||
prepend_text='', append_text='', values_replace=None):
|
||||
options = PromptOptions(interp=tensor_interp, prepend_text=prepend_text, append_text=append_text,
|
||||
values_replace=values_replace, print_schedule=print_schedule)
|
||||
conditioning = evaluate_prompt_schedule(prompts, max_length, clip, options)
|
||||
return (conditioning,)
|
||||
return io.NodeOutput(conditioning)
|
||||
|
||||
|
||||
class ValueSchedulingLatentsNode:
|
||||
class ValueSchedulingLatentsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ValueSchedulingLatents',
|
||||
display_name='Value Scheduling [Latents] 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/scheduling',
|
||||
inputs=[io.String.Input('values', default='', multiline=True), io.Latent.Input('latent'), io.Boolean.Input('print_schedule', default=False, optional=True)],
|
||||
outputs=[io.Float.Output('FLOAT'), io.Custom('FLOATS').Output('FLOATS'), io.Int.Output('INT'), io.Custom('INTS').Output('INTS')],
|
||||
description='Create a list of values with automatic interpolation, its length matching passed-in latent count.'
|
||||
)
|
||||
NodeID = 'ADE_ValueSchedulingLatents'
|
||||
NodeName = 'Value Scheduling [Latents] 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"values": ("STRING", {"multiline": True, "default": ""}),
|
||||
"latent": ("LATENT",),
|
||||
},
|
||||
"optional": {
|
||||
"print_schedule": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT", "FLOATS", "INT", "INTS")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/scheduling"
|
||||
FUNCTION = "create_schedule"
|
||||
|
||||
Desc = [
|
||||
short_desc('Create a list of values with automatic interpolation, its length matching passed-in latent count.'),
|
||||
{'Format': desc_format_values},
|
||||
{coll('Inputs'): DocHelper.combine(desc_values, desc_latent, desc_print_schedule)},
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def create_schedule(self, values: str, latent: dict, print_schedule=False):
|
||||
def execute(cls, values: str, latent: dict, print_schedule=False):
|
||||
float_vals = evaluate_value_schedule(values, latent["samples"].size(0))
|
||||
int_vals = [round(x) for x in float_vals]
|
||||
if print_schedule:
|
||||
logger.info(f"ValueScheduling ({len(float_vals)} values):")
|
||||
for i, val in enumerate(float_vals):
|
||||
logger.info(f"{i} = {val}")
|
||||
return (float_vals, float_vals, int_vals, int_vals)
|
||||
return io.NodeOutput(float_vals, float_vals, int_vals, int_vals)
|
||||
|
||||
|
||||
class ValueSchedulingNode:
|
||||
class ValueSchedulingNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ValueScheduling',
|
||||
display_name='Value Scheduling 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/scheduling',
|
||||
inputs=[io.String.Input('values', default='', multiline=True), io.Boolean.Input('print_schedule', default=False, optional=True), io.Int.Input('max_length', default=0, max=9007199254740991, min=0, step=1, optional=True)],
|
||||
outputs=[io.Float.Output('FLOAT'), io.Custom('FLOATS').Output('FLOATS'), io.Int.Output('INT'), io.Custom('INTS').Output('INTS')],
|
||||
description='Create a list of values with automatic interpolation.'
|
||||
)
|
||||
NodeID = 'ADE_ValueScheduling'
|
||||
NodeName = 'Value Scheduling 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"values": ("STRING", {"multiline": True, "default": ""}),
|
||||
},
|
||||
"optional": {
|
||||
"print_schedule": ("BOOLEAN", {"default": False}),
|
||||
"max_length": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOAT", "FLOATS", "INT", "INTS")
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/scheduling"
|
||||
FUNCTION = "create_schedule"
|
||||
|
||||
Desc = [
|
||||
short_desc('Create a list of values with automatic interpolation.'),
|
||||
{'Format': desc_format_values},
|
||||
{coll('Inputs'): DocHelper.combine(desc_values, desc_max_length, desc_print_schedule)},
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def create_schedule(self, values: str, max_length: int, print_schedule=False):
|
||||
def execute(cls, values: str, max_length: int, print_schedule=False):
|
||||
float_vals = evaluate_value_schedule(values, max_length)
|
||||
int_vals = [round(x) for x in float_vals]
|
||||
if print_schedule:
|
||||
logger.info(f"ValueScheduling ({len(float_vals)} values):")
|
||||
for i, val in enumerate(float_vals):
|
||||
logger.info(f"{i} = {val}")
|
||||
return (float_vals, float_vals, int_vals, int_vals)
|
||||
return io.NodeOutput(float_vals, float_vals, int_vals, int_vals)
|
||||
|
||||
|
||||
class AddValuesReplaceNode:
|
||||
class AddValuesReplaceNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ValuesReplace',
|
||||
display_name='Add Values Replace 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/scheduling',
|
||||
inputs=[io.String.Input('value_key', default=''), io.Custom('FLOATS').Input('floats'), io.Custom('VALUES_REPLACE').Input('prev_replace', optional=True)],
|
||||
outputs=[io.Custom('VALUES_REPLACE').Output('VALUES_REPLACE')],
|
||||
description='Add a values schedule bound to a key to be used in Prompt Scheduling node.'
|
||||
)
|
||||
NodeID = 'ADE_ValuesReplace'
|
||||
NodeName = 'Add Values Replace 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"value_key": ("STRING", {"default": ""}),
|
||||
"floats": ("FLOATS",)
|
||||
},
|
||||
"optional": {
|
||||
"prev_replace": ("VALUES_REPLACE",),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VALUES_REPLACE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/scheduling"
|
||||
FUNCTION = "add_values_replace"
|
||||
|
||||
Desc = [
|
||||
short_desc('Add a values schedule bound to a key to be used in Prompt Scheduling node.'),
|
||||
{'Inputs': DocHelper.combine(desc_value_key, desc_floats, desc_prev_replace)},
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def add_values_replace(self, value_key: str, floats: Union[list[float]], prev_replace: dict=None):
|
||||
def execute(cls, value_key: str, floats: Union[list[float]], prev_replace: dict=None):
|
||||
# key can only have a-z, A-Z, 0-9, and _ characters
|
||||
verify_key_value(key=value_key)
|
||||
# add/replace value floats
|
||||
@@ -257,58 +123,44 @@ class AddValuesReplaceNode:
|
||||
if value_key in prev_replace:
|
||||
logger.warn(f"Value key '{value_key}' is already present - corresponding floats value will be overriden.")
|
||||
prev_replace[value_key] = floats
|
||||
return (prev_replace,)
|
||||
return io.NodeOutput(prev_replace)
|
||||
|
||||
|
||||
class FloatToFloatsNode:
|
||||
class FloatToFloatsNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_FloatToFloats',
|
||||
display_name='Float to Floats 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/scheduling',
|
||||
inputs=[io.Float.Input('FLOAT', default=39, force_input=True)],
|
||||
outputs=[io.Custom('FLOATS').Output('FLOATS')]
|
||||
)
|
||||
NodeID = 'ADE_FloatToFloats'
|
||||
NodeName = 'Float to Floats 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"FLOAT": ("FLOAT", {"default": 39, "forceInput": True}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("FLOATS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/scheduling"
|
||||
FUNCTION = "convert_to_floats"
|
||||
|
||||
def convert_to_floats(self, FLOAT: Union[float, list[float]]):
|
||||
def execute(cls, FLOAT: Union[float, list[float]]):
|
||||
floats = None
|
||||
if isinstance(FLOAT, float):
|
||||
floats = [float(FLOAT)]
|
||||
else:
|
||||
floats = list(FLOAT)
|
||||
return (floats,)
|
||||
return io.NodeOutput(floats)
|
||||
|
||||
class ConditionExtractionNode:
|
||||
class ConditionExtractionNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_ConditionExtraction',
|
||||
display_name='Condition Step Extraction 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/scheduling',
|
||||
inputs=[io.Conditioning.Input('conditioning'), io.Int.Input('index', default=0, min=0, step=1)],
|
||||
outputs=[io.Conditioning.Output('CONDITIONING')],
|
||||
description='Extract a single conditioning step from a schedule of prompts.'
|
||||
)
|
||||
NodeID = 'ADE_ConditionExtraction'
|
||||
NodeName = 'Condition Step Extraction 🎭🅐🅓'
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"conditioning": ("CONDITIONING",),
|
||||
"index": ("INT", {"default": 0, "min": 0, "step": 1})
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/scheduling"
|
||||
FUNCTION = "extract_conditioning"
|
||||
|
||||
Desc = [
|
||||
short_desc('Extract a single conditioning step from a schedule of prompts.'),
|
||||
{coll('Inputs'): DocHelper.combine(desc_input_conditioning, desc_index)},
|
||||
{coll('Outputs'): DocHelper.combine(desc_output_conditioning)}
|
||||
]
|
||||
register_description(NodeID, Desc)
|
||||
|
||||
def extract_conditioning(self, conditioning, index: int=0):
|
||||
def execute(cls, conditioning, index: int=0):
|
||||
conditioning_step = extract_cond_from_schedule(conditioning, index)
|
||||
return (conditioning_step,)
|
||||
return io.NodeOutput(conditioning_step)
|
||||
|
||||
+123
-115
@@ -1,3 +1,4 @@
|
||||
from comfy_api.latest import io
|
||||
import torch
|
||||
|
||||
import comfy.samplers
|
||||
@@ -13,50 +14,54 @@ def validate_sigma_schedule_compatibility(schedule_A: SigmaSchedule, schedule_B:
|
||||
f"{name_b} has {schedule_B.total_sigmas()} sigmas (lcm={schedule_B.is_lcm()}).")
|
||||
|
||||
|
||||
class SigmaScheduleNode:
|
||||
class SigmaScheduleNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"beta_schedule": (BetaSchedules.ALIAS_ACTIVE_LIST,),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("SIGMA_SCHEDULE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule"
|
||||
FUNCTION = "get_sigma_schedule"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_SigmaSchedule',
|
||||
display_name='Create Sigma Schedule 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/sample settings/sigma schedule',
|
||||
inputs=[
|
||||
io.Combo.Input('beta_schedule', options=BetaSchedules.ALIAS_ACTIVE_LIST),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Output('SIGMA_SCHEDULE'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_sigma_schedule(self, beta_schedule: str):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, beta_schedule: str) -> io.NodeOutput:
|
||||
model_type = ModelSamplingType.from_alias(ModelSamplingType.EPS)
|
||||
new_model_sampling = BetaSchedules._to_model_sampling(alias=beta_schedule,
|
||||
model_type=model_type)
|
||||
return (SigmaSchedule(model_sampling=new_model_sampling, model_type=model_type),)
|
||||
return io.NodeOutput(SigmaSchedule(model_sampling=new_model_sampling, model_type=model_type))
|
||||
|
||||
|
||||
class RawSigmaScheduleNode:
|
||||
class RawSigmaScheduleNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"raw_beta_schedule": (BetaSchedules.RAW_BETA_SCHEDULE_LIST,),
|
||||
"linear_start": ("FLOAT", {"default": 0.00085, "min": 0.0, "max": 1.0, "step": 0.000001}),
|
||||
"linear_end": ("FLOAT", {"default": 0.012, "min": 0.0, "max": 1.0, "step": 0.000001}),
|
||||
#"cosine_s": ("FLOAT", {"default": 8e-3, "min": 0.0, "max": 1.0, "step": 0.000001}),
|
||||
"sampling": (ModelSamplingType._FULL_LIST,),
|
||||
"lcm_original_timesteps": ("INT", {"default": 50, "min": 1, "max": 1000}),
|
||||
"zsnr": ("BOOLEAN", {"default": False}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("SIGMA_SCHEDULE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule"
|
||||
FUNCTION = "get_sigma_schedule"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_RawSigmaSchedule',
|
||||
display_name='Create Raw Sigma Schedule 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/sample settings/sigma schedule',
|
||||
inputs=[
|
||||
io.Combo.Input('raw_beta_schedule', options=BetaSchedules.RAW_BETA_SCHEDULE_LIST),
|
||||
io.Float.Input('linear_start', default=0.00085, max=1.0, min=0.0, step=1e-06),
|
||||
io.Float.Input('linear_end', default=0.012, max=1.0, min=0.0, step=1e-06),
|
||||
io.Combo.Input('sampling', options=ModelSamplingType._FULL_LIST),
|
||||
io.Int.Input('lcm_original_timesteps', default=50, max=1000, min=1),
|
||||
io.Boolean.Input('zsnr', default=False),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Output('SIGMA_SCHEDULE'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_sigma_schedule(self, raw_beta_schedule: str, linear_start: float, linear_end: float,# cosine_s: float,
|
||||
sampling: str, lcm_original_timesteps: int, zsnr: bool, lcm_zsnr: bool=None):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, raw_beta_schedule: str, linear_start: float, linear_end: float,# cosine_s: float,
|
||||
sampling: str, lcm_original_timesteps: int, zsnr: bool, lcm_zsnr: bool=None) -> io.NodeOutput:
|
||||
if lcm_zsnr is not None:
|
||||
zsnr = lcm_zsnr
|
||||
# from pathlib import Path
|
||||
@@ -67,61 +72,63 @@ class RawSigmaScheduleNode:
|
||||
new_config = ModelSamplingConfig(beta_schedule=raw_beta_schedule, linear_start=linear_start, linear_end=linear_end)#, given_betas=given_betas)
|
||||
if sampling != ModelSamplingType.LCM:
|
||||
lcm_original_timesteps=None
|
||||
model_type = ModelSamplingType.from_alias(sampling)
|
||||
model_type = ModelSamplingType.from_alias(sampling)
|
||||
new_model_sampling = BetaSchedules._to_model_sampling(alias=BetaSchedules.AUTOSELECT, model_type=model_type, config_override=new_config, original_timesteps=lcm_original_timesteps)
|
||||
if zsnr:
|
||||
SigmaSchedule.apply_zsnr(new_model_sampling=new_model_sampling)
|
||||
return (SigmaSchedule(model_sampling=new_model_sampling, model_type=model_type),)
|
||||
return io.NodeOutput(SigmaSchedule(model_sampling=new_model_sampling, model_type=model_type))
|
||||
|
||||
|
||||
class WeightedAverageSigmaScheduleNode:
|
||||
class WeightedAverageSigmaScheduleNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"schedule_A": ("SIGMA_SCHEDULE",),
|
||||
"schedule_B": ("SIGMA_SCHEDULE",),
|
||||
"weight_A": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("SIGMA_SCHEDULE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule"
|
||||
FUNCTION = "get_sigma_schedule"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_SigmaScheduleWeightedAverage',
|
||||
display_name='Sigma Schedule Weighted Mean 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/sample settings/sigma schedule',
|
||||
inputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Input('schedule_A'),
|
||||
io.Custom("SIGMA_SCHEDULE").Input('schedule_B'),
|
||||
io.Float.Input('weight_A', default=0.5, max=1.0, min=0.0, step=0.001),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Output('SIGMA_SCHEDULE'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_sigma_schedule(self, schedule_A: SigmaSchedule, schedule_B: SigmaSchedule, weight_A: float):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, schedule_A: SigmaSchedule, schedule_B: SigmaSchedule, weight_A: float) -> io.NodeOutput:
|
||||
validate_sigma_schedule_compatibility(schedule_A, schedule_B)
|
||||
new_sigmas = schedule_A.model_sampling.sigmas * weight_A + schedule_B.model_sampling.sigmas * (1-weight_A)
|
||||
combo_schedule = schedule_A.clone()
|
||||
combo_schedule.model_sampling.set_sigmas(new_sigmas)
|
||||
return (combo_schedule,)
|
||||
return io.NodeOutput(combo_schedule)
|
||||
|
||||
|
||||
class InterpolatedWeightedAverageSigmaScheduleNode:
|
||||
class InterpolatedWeightedAverageSigmaScheduleNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"schedule_A": ("SIGMA_SCHEDULE",),
|
||||
"schedule_B": ("SIGMA_SCHEDULE",),
|
||||
"weight_A_Start": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"weight_A_End": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001}),
|
||||
"interpolation": (InterpolationMethod._LIST,),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("SIGMA_SCHEDULE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule"
|
||||
FUNCTION = "get_sigma_schedule"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_SigmaScheduleWeightedAverageInterp',
|
||||
display_name='Sigma Schedule Interp. Mean 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/sample settings/sigma schedule',
|
||||
inputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Input('schedule_A'),
|
||||
io.Custom("SIGMA_SCHEDULE").Input('schedule_B'),
|
||||
io.Float.Input('weight_A_Start', default=0.5, max=1.0, min=0.0, step=0.001),
|
||||
io.Float.Input('weight_A_End', default=0.5, max=1.0, min=0.0, step=0.001),
|
||||
io.Combo.Input('interpolation', options=InterpolationMethod._LIST),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Output('SIGMA_SCHEDULE'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_sigma_schedule(self, schedule_A: SigmaSchedule, schedule_B: SigmaSchedule,
|
||||
weight_A_Start: float, weight_A_End: float, interpolation: str):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, schedule_A: SigmaSchedule, schedule_B: SigmaSchedule,
|
||||
weight_A_Start: float, weight_A_End: float, interpolation: str) -> io.NodeOutput:
|
||||
validate_sigma_schedule_compatibility(schedule_A, schedule_B)
|
||||
# get reverse weights, since sigmas are currently reversed
|
||||
weights = InterpolationMethod.get_weights(num_from=weight_A_Start, num_to=weight_A_End,
|
||||
@@ -130,64 +137,65 @@ class InterpolatedWeightedAverageSigmaScheduleNode:
|
||||
new_sigmas = schedule_A.model_sampling.sigmas * weights + schedule_B.model_sampling.sigmas * (1.0-weights)
|
||||
combo_schedule = schedule_A.clone()
|
||||
combo_schedule.model_sampling.set_sigmas(new_sigmas)
|
||||
return (combo_schedule,)
|
||||
return io.NodeOutput(combo_schedule)
|
||||
|
||||
|
||||
class SplitAndCombineSigmaScheduleNode:
|
||||
class SplitAndCombineSigmaScheduleNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"schedule_Start": ("SIGMA_SCHEDULE",),
|
||||
"schedule_End": ("SIGMA_SCHEDULE",),
|
||||
"idx_split_percent": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.001})
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("SIGMA_SCHEDULE",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule"
|
||||
FUNCTION = "get_sigma_schedule"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_SigmaScheduleSplitAndCombine',
|
||||
display_name='Sigma Schedule Split Combine 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/sample settings/sigma schedule',
|
||||
inputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Input('schedule_Start'),
|
||||
io.Custom("SIGMA_SCHEDULE").Input('schedule_End'),
|
||||
io.Float.Input('idx_split_percent', default=0.5, max=1.0, min=0.0, step=0.001),
|
||||
],
|
||||
outputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Output('SIGMA_SCHEDULE'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_sigma_schedule(self, schedule_Start: SigmaSchedule, schedule_End: SigmaSchedule, idx_split_percent: float):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, schedule_Start: SigmaSchedule, schedule_End: SigmaSchedule, idx_split_percent: float) -> io.NodeOutput:
|
||||
validate_sigma_schedule_compatibility(schedule_Start, schedule_End)
|
||||
# first, calculate index to act as split; get diff from 1.0 since sigmas are flipped at this stage
|
||||
idx = int((1.0-idx_split_percent) * schedule_Start.total_sigmas())
|
||||
new_sigmas = torch.cat([schedule_End.model_sampling.sigmas[:idx], schedule_Start.model_sampling.sigmas[idx:]], dim=0)
|
||||
new_schedule = schedule_Start.clone()
|
||||
new_schedule.model_sampling.set_sigmas(new_sigmas)
|
||||
return (new_schedule,)
|
||||
return io.NodeOutput(new_schedule)
|
||||
|
||||
|
||||
class SigmaScheduleToSigmasNode:
|
||||
class SigmaScheduleToSigmasNode(io.ComfyNode):
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"sigma_schedule": ("SIGMA_SCHEDULE",),
|
||||
"scheduler": (comfy.samplers.SCHEDULER_NAMES, ),
|
||||
"steps": ("INT", {"default": 20, "min": 1, "max": 10000}),
|
||||
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
},
|
||||
"hidden": {
|
||||
"autosize": ("ADEAUTOSIZE", {"padding": 0}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("SIGMAS",)
|
||||
CATEGORY = "Animate Diff 🎭🅐🅓/sample settings/sigma schedule"
|
||||
FUNCTION = "get_sigmas"
|
||||
def define_schema(cls) -> io.Schema:
|
||||
return io.Schema(
|
||||
node_id='ADE_SigmaScheduleToSigmas',
|
||||
display_name='Sigma Schedule To Sigmas 🎭🅐🅓',
|
||||
category='Animate Diff 🎭🅐🅓/sample settings/sigma schedule',
|
||||
inputs=[
|
||||
io.Custom("SIGMA_SCHEDULE").Input('sigma_schedule'),
|
||||
io.Combo.Input('scheduler', options=comfy.samplers.SCHEDULER_NAMES),
|
||||
io.Int.Input('steps', default=20, max=10000, min=1),
|
||||
io.Float.Input('denoise', default=1.0, max=1.0, min=0.0, step=0.01),
|
||||
],
|
||||
outputs=[
|
||||
io.Sigmas.Output('SIGMAS'),
|
||||
],
|
||||
)
|
||||
|
||||
def get_sigmas(self, sigma_schedule: SigmaSchedule, scheduler: str, steps: int, denoise: float):
|
||||
|
||||
@classmethod
|
||||
def execute(cls, sigma_schedule: SigmaSchedule, scheduler: str, steps: int, denoise: float) -> io.NodeOutput:
|
||||
total_steps = steps
|
||||
if denoise < 1.0:
|
||||
if denoise <= 0.0:
|
||||
return (torch.FloatTensor([]),)
|
||||
return io.NodeOutput(torch.FloatTensor([]))
|
||||
total_steps = int(steps/denoise)
|
||||
|
||||
sigmas = comfy.samplers.calculate_sigmas(sigma_schedule, scheduler, total_steps).cpu()
|
||||
sigmas = sigmas[-(steps + 1):]
|
||||
return (sigmas, )
|
||||
|
||||
return io.NodeOutput(sigmas)
|
||||
|
||||
@@ -203,10 +203,13 @@ def groupnorm_mm_factory(params: InjectionParams, manual_cast=False):
|
||||
|
||||
input = rearrange(input, "(b f) c h w -> b c f h w", b=batched_conds)
|
||||
if manual_cast:
|
||||
weight, bias = comfy.ops.cast_bias_weight(self, input)
|
||||
weight, bias, offload_stream = comfy.ops.cast_bias_weight(self, input, offloadable=True)
|
||||
else:
|
||||
weight, bias = self.weight, self.bias
|
||||
offload_stream = None
|
||||
input = group_norm(input, self.num_groups, weight, bias, self.eps)
|
||||
if offload_stream is not None:
|
||||
comfy.ops.uncast_bias_weight(self, weight, bias, offload_stream)
|
||||
input = rearrange(input, "b c f h w -> (b f) c h w", b=batched_conds)
|
||||
return input
|
||||
return groupnorm_mm_forward
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-animatediff-evolved"
|
||||
description = "Improved AnimateDiff integration for ComfyUI."
|
||||
version = "1.5.6"
|
||||
version = "1.6.0"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = []
|
||||
|
||||
@@ -13,3 +13,4 @@ Repository = "https://github.com/Kosinkadink/ComfyUI-AnimateDiff-Evolved"
|
||||
PublisherId = "kosinkadink"
|
||||
DisplayName = "ComfyUI-AnimateDiff-Evolved"
|
||||
Icon = ""
|
||||
requires-comfyui = ">=0.3.68"
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# Condition Step Extraction
|
||||
|
||||
Extract a single conditioning step from a schedule of prompts.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `conditioning`: Encoded prompts from a Prompt Scheduling node.
|
||||
- `index`: The step to extract. It must be within the scheduled prompt range.
|
||||
|
||||
## Outputs
|
||||
|
||||
- `CONDITIONING`: The single conditioning step from the schedule.
|
||||
@@ -0,0 +1,24 @@
|
||||
# AD Per Block Floats (SD1.5)
|
||||
|
||||
Use Floats from Value Schedules to select SD1.5 effect and scale values for blocks.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `effect_21_floats`: Optional effect values. The list is extended to the required 21 values when needed.
|
||||
- `scale_21_floats`: Optional scale values. The list is extended to the required 21 values when needed.
|
||||
|
||||
## Block index map
|
||||
|
||||
SD1.5 motion modules contain 21 blocks.
|
||||
|
||||
| Index | Block |
|
||||
| ---: | --- |
|
||||
| 0 | Start of down blocks (`down_0__0`) |
|
||||
| 7 | End of down blocks (`down_3__1`) |
|
||||
| 8 | Mid block (`mid`) |
|
||||
| 9 | Start of up blocks (`up_0__0`) |
|
||||
| 20 | End of up blocks (`up_3__2`) |
|
||||
|
||||
## Outputs
|
||||
|
||||
- `PER_BLOCK`: Per-block effect and scale configuration for an SD1.5 motion module.
|
||||
@@ -0,0 +1,24 @@
|
||||
# AD Per Block Floats (SDXL)
|
||||
|
||||
Use Floats from Value Schedules to select SDXL effect and scale values for blocks.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `effect_16_floats`: Optional effect values. The list is extended to the required 16 values when needed.
|
||||
- `scale_16_floats`: Optional scale values. The list is extended to the required 16 values when needed.
|
||||
|
||||
## Block index map
|
||||
|
||||
SDXL motion modules contain 16 blocks.
|
||||
|
||||
| Index | Block |
|
||||
| ---: | --- |
|
||||
| 0 | Start of down blocks (`down_0__0`) |
|
||||
| 5 | End of down blocks (`down_2__1`) |
|
||||
| 6 | Mid block (`mid`) |
|
||||
| 7 | Start of up blocks (`up_0__0`) |
|
||||
| 15 | End of up blocks (`up_2__2`) |
|
||||
|
||||
## Outputs
|
||||
|
||||
- `PER_BLOCK`: Per-block effect and scale configuration for an SDXL motion module.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Prompt Scheduling
|
||||
|
||||
Encode a schedule of prompts with automatic interpolation.
|
||||
|
||||
## Schedule format
|
||||
|
||||
Schedules support JSON and Python-like formats. Frame 0 is the first frame and `max_frames - 1` is the last.
|
||||
|
||||
```text
|
||||
"0": "blue rock on mountain",
|
||||
"16": "green rock in lake"
|
||||
```
|
||||
|
||||
```text
|
||||
0 = "blue rock on mountain",
|
||||
16 = "green rock in lake"
|
||||
```
|
||||
|
||||
Prompts must be enclosed in double quotes. Prompt portions may use keys supplied through `values_replace`.
|
||||
|
||||
### Allowed indices
|
||||
|
||||
- **Single:** A positive integer such as `0` or `2` selects that frame. A negative integer such as `-1` or `-5` selects from the end (`-1` is the last frame). A decimal such as `0.5` or `1.0` selects a relative position (`0.5` is halfway and `1.0` is the last frame).
|
||||
- **Range:** `start:end` uses an uninterpolated prompt from the included start index to the excluded end index. Examples: `0:12`, `0:-5`, `2:0.5`.
|
||||
- **Hold:** A colon after one index stops interpolation until the next supplied index. Examples: `0:`, `0.5:`, `16:`.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Description |
|
||||
| --- | --- |
|
||||
| `prompts` | The prompt schedule. |
|
||||
| `clip` | CLIP used to encode prompts. |
|
||||
| `prepend_text` | Optional text added before every prompt. |
|
||||
| `append_text` | Optional text added after every prompt. |
|
||||
| `values_replace` | Optional value schedules substituted for keys written as `` `some_key` `` in prompts. |
|
||||
| `print_schedule` | Print the resulting schedule when enabled. |
|
||||
| `max_length` | Intended schedule length. At 0, the largest schedule index determines the length, but negative and decimal relative indices are disabled. |
|
||||
| `tensor_interp` | Prompt-conditioning interpolation method; defaults to linear interpolation. |
|
||||
|
||||
## Outputs
|
||||
|
||||
- `CONDITIONING`: Encoded prompts.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Prompt Scheduling [Latents]
|
||||
|
||||
Encode a schedule of prompts with automatic interpolation, its length matching the passed-in latent count.
|
||||
|
||||
## Schedule format
|
||||
|
||||
Schedules support JSON and Python-like formats. Frame 0 is the first frame and `max_frames - 1` is the last.
|
||||
|
||||
```text
|
||||
"0": "blue rock on mountain",
|
||||
"16": "green rock in lake"
|
||||
```
|
||||
|
||||
```text
|
||||
0 = "blue rock on mountain",
|
||||
16 = "green rock in lake"
|
||||
```
|
||||
|
||||
Prompts must be enclosed in double quotes. Prompt portions may use keys supplied through `values_replace`.
|
||||
|
||||
### Allowed indices
|
||||
|
||||
- **Single:** A positive integer such as `0` or `2` selects that frame. A negative integer such as `-1` or `-5` selects from the end (`-1` is the last frame). A decimal such as `0.5` or `1.0` selects a relative position (`0.5` is halfway and `1.0` is the last frame).
|
||||
- **Range:** `start:end` uses an uninterpolated prompt from the included start index to the excluded end index. Examples: `0:12`, `0:-5`, `2:0.5`.
|
||||
- **Hold:** A colon after one index stops interpolation until the next supplied index. Examples: `0:`, `0.5:`, `16:`.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Description |
|
||||
| --- | --- |
|
||||
| `prompts` | The prompt schedule. |
|
||||
| `clip` | CLIP used to encode prompts. |
|
||||
| `latent` | Supplies the frame count used as the schedule length. |
|
||||
| `prepend_text` | Optional text added before every prompt. |
|
||||
| `append_text` | Optional text added after every prompt. |
|
||||
| `values_replace` | Optional value schedules substituted for keys written as `` `some_key` `` in prompts. |
|
||||
| `tensor_interp` | Prompt-conditioning interpolation method; defaults to linear interpolation. |
|
||||
| `print_schedule` | Print the resulting schedule when enabled. |
|
||||
|
||||
## Outputs
|
||||
|
||||
- `CONDITIONING`: Encoded prompts.
|
||||
- `LATENT`: The unmodified input latents, usable as a pipe or safely ignored.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Value Scheduling
|
||||
|
||||
Create a list of values with automatic interpolation.
|
||||
|
||||
## Schedule format
|
||||
|
||||
Schedules support JSON and Python-like formats. Values need no special formatting.
|
||||
|
||||
```text
|
||||
"0": 1.0,
|
||||
"16": 1.3
|
||||
```
|
||||
|
||||
```text
|
||||
0 = 1.0,
|
||||
16 = 1.3
|
||||
```
|
||||
|
||||
Frame 0 is the first frame and `max_frames - 1` is the last.
|
||||
|
||||
- **Single:** Positive integers select a frame, negative integers select from the end (`-1` is last), and decimals select a relative position (`0.5` is halfway and `1.0` is last).
|
||||
- **Range:** `start:end` holds the start value without interpolation through the excluded end. Examples: `0:12`, `0:-5`, `2:0.5`.
|
||||
- **Hold:** A trailing colon stops interpolation until the next index. Examples: `0:`, `0.5:`, `16:`.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `values`: The value schedule.
|
||||
- `max_length`: Intended schedule length. At 0, the largest schedule index determines the length, but negative and decimal relative indices are disabled.
|
||||
- `print_schedule`: Print each output value when enabled.
|
||||
|
||||
## Outputs
|
||||
|
||||
The schedule is returned as `FLOAT`, `FLOATS`, rounded `INT`, and rounded `INTS` outputs.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Value Scheduling [Latents]
|
||||
|
||||
Create a list of values with automatic interpolation, its length matching the passed-in latent count.
|
||||
|
||||
## Schedule format
|
||||
|
||||
Schedules support JSON and Python-like formats. Values need no special formatting.
|
||||
|
||||
```text
|
||||
"0": 1.0,
|
||||
"16": 1.3
|
||||
```
|
||||
|
||||
```text
|
||||
0 = 1.0,
|
||||
16 = 1.3
|
||||
```
|
||||
|
||||
Frame 0 is the first frame and `max_frames - 1` is the last.
|
||||
|
||||
- **Single:** Positive integers select a frame, negative integers select from the end (`-1` is last), and decimals select a relative position (`0.5` is halfway and `1.0` is last).
|
||||
- **Range:** `start:end` holds the start value without interpolation through the excluded end. Examples: `0:12`, `0:-5`, `2:0.5`.
|
||||
- **Hold:** A trailing colon stops interpolation until the next index. Examples: `0:`, `0.5:`, `16:`.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `values`: The value schedule.
|
||||
- `latent`: Supplies the frame count used as the schedule length.
|
||||
- `print_schedule`: Print each output value when enabled.
|
||||
|
||||
## Outputs
|
||||
|
||||
The schedule is returned as `FLOAT`, `FLOATS`, rounded `INT`, and rounded `INTS` outputs.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Add Values Replace
|
||||
|
||||
Add a value schedule bound to a key for use in a Prompt Scheduling node.
|
||||
|
||||
## Inputs
|
||||
|
||||
- `value_key`: The key for the value schedule. It may contain only `a-z`, `A-Z`, `0-9`, and `_`. Refer to it in a prompt by surrounding it with backticks, for example `` `some_key` ``.
|
||||
- `floats`: A list of floats, typically produced by a Value Scheduling node.
|
||||
- `prev_replace`: Optional existing replacements, allowing multiple Values Replace nodes to be chained.
|
||||
|
||||
## Outputs
|
||||
|
||||
- `VALUES_REPLACE`: The replacement mapping for a Prompt Scheduling node.
|
||||
@@ -1,53 +0,0 @@
|
||||
import { app } from '../../../scripts/app.js'
|
||||
|
||||
function addResizeHook(node, padding, useOldMin=false) {
|
||||
let origOnCreated = node.onNodeCreated
|
||||
node.onNodeCreated = function() {
|
||||
let r = origOnCreated?.apply(this, arguments)
|
||||
let size = this.computeSize();
|
||||
size[0] += padding || 0;
|
||||
if (useOldMin) {
|
||||
//equal to LiteGraph.NODE_WIDTH*1.5*1.5
|
||||
size[0] = Math.max(size[0], 315)
|
||||
}
|
||||
this.setSize(size);
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
app.registerExtension({
|
||||
name: "AnimateDiffEvolved.autosize",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
//since python_module is based off folder path,
|
||||
//it could be changed by users and should only be used as fallback
|
||||
if (nodeData?.name?.startsWith("ADE_")
|
||||
|| nodeData.python_module == 'custom_nodes.ComfyUI-AnimateDiff-Evolved') {
|
||||
if (nodeData?.input?.hidden?.autosize) {
|
||||
addResizeHook(nodeType.prototype, nodeData.input.hidden.autosize[1]?.padding)
|
||||
} else if (!nodeData?.input?.optional?.autosize) {
|
||||
addResizeHook(nodeType.prototype, 0, true)
|
||||
}
|
||||
}
|
||||
},
|
||||
async getCustomWidgets() {
|
||||
return {
|
||||
ADEAUTOSIZE(node, inputName, inputData) {
|
||||
let w = {
|
||||
name : inputName,
|
||||
type : "ADE.AUTOSIZE",
|
||||
value : "",
|
||||
options : {"serialize": false},
|
||||
computeSize : function(width) {
|
||||
return [0, -4];
|
||||
}
|
||||
}
|
||||
if (!node.widgets) {
|
||||
node.widgets = []
|
||||
}
|
||||
node.widgets.push(w)
|
||||
addResizeHook(node, inputData[1].padding);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,51 +0,0 @@
|
||||
import { app } from '../../../scripts/app.js'
|
||||
|
||||
const deprecate_nodes = {
|
||||
name: 'AnimateDiff.deprecate_nodes',
|
||||
async getCustomWidgets() {
|
||||
return {
|
||||
ADEWARN(node, inputName, inputData) {
|
||||
let w = {
|
||||
name : inputName,
|
||||
type : "ADE.WARN",
|
||||
value : "",
|
||||
draw : function(ctx, node, widget_width, y, H) {
|
||||
var show_text = app.canvas.ds.scale > 0.5;
|
||||
var margin = 15;
|
||||
var text_color = inputData[1]['color'] || "#FCC"
|
||||
ctx.textAlign = "center";
|
||||
if (show_text) {
|
||||
if(!this.disabled)
|
||||
ctx.stroke();
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(margin, y, widget_width - margin * 2, H);
|
||||
ctx.clip();
|
||||
ctx.fillStyle = text_color;
|
||||
let disp_text = inputData[1]['text']
|
||||
ctx.fillText(disp_text, widget_width/2, y + H * 0.7);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
},
|
||||
options : {"serialize": false},
|
||||
computeSize : function(width) {
|
||||
if (inputData[1]['text']) {
|
||||
return [width, 20]
|
||||
}
|
||||
return [0, -4]
|
||||
|
||||
}
|
||||
}
|
||||
if (!node.widgets) {
|
||||
node.widgets = []
|
||||
}
|
||||
node.widgets.push(w)
|
||||
return w
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.registerExtension(deprecate_nodes)
|
||||
|
||||
@@ -1,292 +0,0 @@
|
||||
import { app } from '../../../scripts/app.js'
|
||||
|
||||
function chainCallback(object, property, callback) {
|
||||
if (object == undefined) {
|
||||
//This should not happen.
|
||||
console.error("Tried to add callback to non-existant object")
|
||||
return;
|
||||
}
|
||||
if (property in object && object[property]) {
|
||||
const callback_orig = object[property]
|
||||
object[property] = function () {
|
||||
const r = callback_orig.apply(this, arguments);
|
||||
callback.apply(this, arguments);
|
||||
return r
|
||||
};
|
||||
} else {
|
||||
object[property] = callback;
|
||||
}
|
||||
}
|
||||
var helpDOM;
|
||||
function initHelpDOM() {
|
||||
let parentDOM = document.createElement("div");
|
||||
document.body.appendChild(parentDOM)
|
||||
parentDOM.appendChild(helpDOM)
|
||||
helpDOM.className = "litegraph";
|
||||
let scrollbarStyle = document.createElement('style');
|
||||
parentDOM.className = "VHS_floatinghelp"
|
||||
scrollbarStyle.innerHTML = `
|
||||
.VHS_floatinghelp {
|
||||
scrollbar-width: 6px;
|
||||
scrollbar-color: #0003 #0000;
|
||||
&::-webkit-scrollbar {
|
||||
background: transparent;
|
||||
width: 6px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #0005;
|
||||
border-radius: 20px
|
||||
}
|
||||
&::-webkit-scrollbar-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.VHS_loopedvideo::-webkit-media-controls-mute-button {
|
||||
display:none;
|
||||
}
|
||||
.VHS_loopedvideo::-webkit-media-controls-fullscreen-button {
|
||||
display:none;
|
||||
}
|
||||
`
|
||||
parentDOM.appendChild(scrollbarStyle)
|
||||
chainCallback(app.canvas, "onDrawForeground", function (ctx, visible_rect){
|
||||
let n = helpDOM.node
|
||||
if (!n || !n?.graph) {
|
||||
parentDOM.style['left'] = '-5000px'
|
||||
return
|
||||
}
|
||||
//draw : function(ctx, node, widgetWidth, widgetY, height) {
|
||||
//update widget position, even if off screen
|
||||
const transform = ctx.getTransform();
|
||||
const scale = app.canvas.ds.scale;//gets the litegraph zoom
|
||||
//calculate coordinates with account for browser zoom
|
||||
const bcr = app.canvas.canvas.getBoundingClientRect()
|
||||
const x = transform.e*scale/transform.a + bcr.x;
|
||||
const y = transform.f*scale/transform.a + bcr.y;
|
||||
//TODO: text reflows at low zoom. investigate alternatives
|
||||
Object.assign(parentDOM.style, {
|
||||
left: (x+(n.pos[0] + n.size[0]+15)*scale) + "px",
|
||||
top: (y+(n.pos[1]-LiteGraph.NODE_TITLE_HEIGHT)*scale) + "px",
|
||||
width: "400px",
|
||||
minHeight: "100px",
|
||||
maxHeight: "600px",
|
||||
overflowY: 'scroll',
|
||||
transformOrigin: '0 0',
|
||||
transform: 'scale(' + scale + ',' + scale +')',
|
||||
fontSize: '18px',
|
||||
backgroundColor: LiteGraph.NODE_DEFAULT_BGCOLOR,
|
||||
boxShadow: '0 0 10px black',
|
||||
borderRadius: '4px',
|
||||
padding: '3px',
|
||||
zIndex: 3,
|
||||
position: "absolute",
|
||||
display: 'inline',
|
||||
});
|
||||
});
|
||||
function setCollapse(el, doCollapse) {
|
||||
if (doCollapse) {
|
||||
el.children[0].children[0].innerHTML = '+'
|
||||
Object.assign(el.children[1].style, {
|
||||
color: '#CCC',
|
||||
overflowX: 'hidden',
|
||||
width: '0px',
|
||||
minWidth: 'calc(100% - 20px)',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
})
|
||||
for (let child of el.children[1].children) {
|
||||
if (child.style.display != 'none'){
|
||||
child.origDisplay = child.style.display
|
||||
}
|
||||
child.style.display = 'none'
|
||||
}
|
||||
} else {
|
||||
el.children[0].children[0].innerHTML = '-'
|
||||
Object.assign(el.children[1].style, {
|
||||
color: '',
|
||||
overflowX: '',
|
||||
width: '100%',
|
||||
minWidth: '',
|
||||
textOverflow: '',
|
||||
whiteSpace: '',
|
||||
})
|
||||
for (let child of el.children[1].children) {
|
||||
child.style.display = child.origDisplay
|
||||
}
|
||||
}
|
||||
}
|
||||
helpDOM.collapseOnClick = function() {
|
||||
let doCollapse = this.children[0].innerHTML == '-'
|
||||
setCollapse(this.parentElement, doCollapse)
|
||||
}
|
||||
helpDOM.selectHelp = function(name, value) {
|
||||
//attempt to navigate to name in help
|
||||
function collapseUnlessMatch(items,t) {
|
||||
var match = items.querySelector('[vhs_title="' + t + '"]')
|
||||
if (!match) {
|
||||
for (let i of items.children) {
|
||||
if (i.innerHTML.slice(0,t.length+5).includes(t)) {
|
||||
match = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
return null
|
||||
}
|
||||
//For longer documentation items with fewer collapsable elements,
|
||||
//scroll to make sure the entirety of the selected item is visible
|
||||
//This has the unfortunate side effect of trying to scroll the main
|
||||
//window if the documentation windows is forcibly offscreen,
|
||||
//but it's easy to simply scroll the main window back and seems to
|
||||
//have no visual side effects
|
||||
match.scrollIntoView(false)
|
||||
window.scrollTo(0,0)
|
||||
for (let i of items.querySelectorAll('.VHS_collapse')) {
|
||||
if (i.contains(match)) {
|
||||
setCollapse(i, false)
|
||||
} else {
|
||||
setCollapse(i, true)
|
||||
}
|
||||
}
|
||||
return match
|
||||
}
|
||||
let target = collapseUnlessMatch(helpDOM, name)
|
||||
if (target && value) {
|
||||
collapseUnlessMatch(target, value)
|
||||
}
|
||||
}
|
||||
|
||||
helpDOM.addHelp = function(node, nodeType, description) {
|
||||
if (!description) {
|
||||
return
|
||||
}
|
||||
//Pad computed size for the clickable question mark
|
||||
let originalComputeSize = node.computeSize
|
||||
node.computeSize = function() {
|
||||
let size = originalComputeSize.apply(this, arguments)
|
||||
if (!this.title) {
|
||||
return size
|
||||
}
|
||||
let title_width = this.title.length * 0.6 * LiteGraph.NODE_TEXT_SIZE
|
||||
size[0] = Math.max(size[0], title_width + LiteGraph.NODE_TITLE_HEIGHT)
|
||||
return size
|
||||
}
|
||||
|
||||
node.description = description
|
||||
chainCallback(node, "onDrawForeground", function (ctx) {
|
||||
//draw question mark
|
||||
ctx.save()
|
||||
ctx.font = 'bold 20px Arial'
|
||||
ctx.fillText("?", this.size[0]-17, -8)
|
||||
ctx.restore()
|
||||
})
|
||||
chainCallback(node, "onMouseDown", function (e, pos, canvas) {
|
||||
//On click would be preferred, but this'll be good enough
|
||||
if (pos[1] < 0 && pos[0] + LiteGraph.NODE_TITLE_HEIGHT > this.size[0]) {
|
||||
//corner question mark clicked
|
||||
if (helpDOM.node == this) {
|
||||
helpDOM.node = undefined
|
||||
} else {
|
||||
helpDOM.node = this;
|
||||
helpDOM.innerHTML = this.description || "no help provided ".repeat(20)
|
||||
for (let e of helpDOM.querySelectorAll('.VHS_collapse')) {
|
||||
e.children[0].onclick = helpDOM.collapseOnClick
|
||||
e.children[0].style.cursor = 'pointer'
|
||||
}
|
||||
for (let e of helpDOM.querySelectorAll('.VHS_precollapse')) {
|
||||
setCollapse(e, true)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
let timeout = null
|
||||
chainCallback(node, "onMouseMove", function (e, pos, canvas) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
timeout = null
|
||||
}
|
||||
if (helpDOM.node != this) {
|
||||
return
|
||||
}
|
||||
timeout = setTimeout(() => {
|
||||
let n = this
|
||||
if (pos[0] > 0 && pos[0] < n.size[0]
|
||||
&& pos[1] > 0 && pos[1] < n.size[1]) {
|
||||
//TODO: provide help specific to element clicked
|
||||
let inputRows = Math.max(n.inputs.length, n.outputs.length)
|
||||
if (pos[1] < LiteGraph.NODE_SLOT_HEIGHT * inputRows) {
|
||||
let row = Math.floor((pos[1] - 7) / LiteGraph.NODE_SLOT_HEIGHT)
|
||||
if (pos[0] < n.size[0]/2) {
|
||||
if (row < n.inputs.length) {
|
||||
helpDOM.selectHelp(n.inputs[row].name)
|
||||
}
|
||||
} else {
|
||||
if (row < n.outputs.length) {
|
||||
helpDOM.selectHelp(n.outputs[row].name)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//probably widget, but widgets have variable height.
|
||||
let basey = LiteGraph.NODE_SLOT_HEIGHT * inputRows + 6
|
||||
for (let w of n.widgets) {
|
||||
if (w.y) {
|
||||
basey = w.y
|
||||
}
|
||||
let wheight = LiteGraph.NODE_WIDGET_HEIGHT+4
|
||||
if (w.computeSize) {
|
||||
wheight = w.computeSize(n.size[0])[1]
|
||||
}
|
||||
if (pos[1] < basey + wheight) {
|
||||
helpDOM.selectHelp(w.name, w.value)
|
||||
break
|
||||
}
|
||||
basey += wheight
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 500)
|
||||
})
|
||||
chainCallback(node, "onMouseLeave", function (e, pos, canvas) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout)
|
||||
timeout = null
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
app.registerExtension({
|
||||
name: "AnimateDiffEvolved.documentation",
|
||||
async init() {
|
||||
if (app.VHSHelp) {
|
||||
helpDOM = app.VHSHelp
|
||||
} else {
|
||||
helpDOM = document.createElement("div");
|
||||
initHelpDOM()
|
||||
app.VHSHelp = helpDOM
|
||||
}
|
||||
},
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
// NOTE: May need manual adjusting for the few non-namespaced nodes
|
||||
if(nodeData?.name?.startsWith("ADE_") && nodeData.description) {
|
||||
let description = nodeData.description
|
||||
let el = document.createElement("div")
|
||||
el.innerHTML = description
|
||||
if (!el.children.length) {
|
||||
//Is plaintext. Do minor convenience formatting
|
||||
let chunks = description.split('\n')
|
||||
nodeData.description = chunks[0]
|
||||
description = chunks.join('<br>')
|
||||
} else {
|
||||
nodeData.description = el.querySelector('#VHS_shortdesc')?.innerHTML || el.children[1]?.firstChild?.innerHTML
|
||||
}
|
||||
chainCallback(nodeType.prototype, "onNodeCreated", function () {
|
||||
helpDOM.addHelp(this, nodeType, description)
|
||||
})
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,142 +0,0 @@
|
||||
import { app } from '../../../scripts/app.js'
|
||||
import { api } from '../../../scripts/api.js'
|
||||
|
||||
function offsetDOMWidget(
|
||||
widget,
|
||||
ctx,
|
||||
node,
|
||||
widgetWidth,
|
||||
widgetY,
|
||||
height
|
||||
) {
|
||||
const margin = 10
|
||||
const elRect = ctx.canvas.getBoundingClientRect()
|
||||
const transform = new DOMMatrix()
|
||||
.scaleSelf(
|
||||
elRect.width / ctx.canvas.width,
|
||||
elRect.height / ctx.canvas.height
|
||||
)
|
||||
.multiplySelf(ctx.getTransform())
|
||||
.translateSelf(0, widgetY + margin)
|
||||
|
||||
const scale = new DOMMatrix().scaleSelf(transform.a, transform.d)
|
||||
Object.assign(widget.inputEl.style, {
|
||||
transformOrigin: '0 0',
|
||||
transform: scale,
|
||||
left: `${transform.e}px`,
|
||||
top: `${transform.d + transform.f}px`,
|
||||
width: `${widgetWidth}px`,
|
||||
height: `${(height || widget.parent?.inputHeight || 32) - margin}px`,
|
||||
position: 'absolute',
|
||||
background: !node.color ? '' : node.color,
|
||||
color: !node.color ? '' : 'white',
|
||||
zIndex: 5, //app.graph._nodes.indexOf(node),
|
||||
})
|
||||
}
|
||||
|
||||
export const hasWidgets = (node) => {
|
||||
if (!node.widgets || !node.widgets?.[Symbol.iterator]) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
export const cleanupNode = (node) => {
|
||||
if (!hasWidgets(node)) {
|
||||
return
|
||||
}
|
||||
|
||||
for (const w of node.widgets) {
|
||||
if (w.canvas) {
|
||||
w.canvas.remove()
|
||||
}
|
||||
if (w.inputEl) {
|
||||
w.inputEl.remove()
|
||||
}
|
||||
// calls the widget remove callback
|
||||
w.onRemoved?.()
|
||||
}
|
||||
}
|
||||
|
||||
const CreatePreviewElement = (name, val, format) => {
|
||||
const [type] = format.split('/')
|
||||
const w = {
|
||||
name,
|
||||
type,
|
||||
value: val,
|
||||
draw: function (ctx, node, widgetWidth, widgetY, height) {
|
||||
const [cw, ch] = this.computeSize(widgetWidth)
|
||||
offsetDOMWidget(this, ctx, node, widgetWidth, widgetY, ch)
|
||||
},
|
||||
computeSize: function (_) {
|
||||
const ratio = this.inputRatio || 1
|
||||
const width = Math.max(220, this.parent.size[0])
|
||||
return [width, (width / ratio + 10)]
|
||||
},
|
||||
onRemoved: function () {
|
||||
if (this.inputEl) {
|
||||
this.inputEl.remove()
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
w.inputEl = document.createElement(type === 'video' ? 'video' : 'img')
|
||||
w.inputEl.src = w.value
|
||||
if (type === 'video') {
|
||||
w.inputEl.setAttribute('type', 'video/webm');
|
||||
w.inputEl.autoplay = true
|
||||
w.inputEl.loop = true
|
||||
w.inputEl.controls = false;
|
||||
}
|
||||
w.inputEl.onload = function () {
|
||||
w.inputRatio = w.inputEl.naturalWidth / w.inputEl.naturalHeight
|
||||
}
|
||||
document.body.appendChild(w.inputEl)
|
||||
return w
|
||||
}
|
||||
|
||||
const gif_preview = {
|
||||
name: 'AnimateDiff.gif_preview',
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
switch (nodeData.name) {
|
||||
case 'ADE_AnimateDiffCombine':{
|
||||
const onExecuted = nodeType.prototype.onExecuted
|
||||
nodeType.prototype.onExecuted = function (message) {
|
||||
const prefix = 'ad_gif_preview_'
|
||||
const r = onExecuted ? onExecuted.apply(this, message) : undefined
|
||||
|
||||
if (this.widgets) {
|
||||
const pos = this.widgets.findIndex((w) => w.name === `${prefix}_0`)
|
||||
if (pos !== -1) {
|
||||
for (let i = pos; i < this.widgets.length; i++) {
|
||||
this.widgets[i].onRemoved?.()
|
||||
}
|
||||
this.widgets.length = pos
|
||||
}
|
||||
if (message?.gifs) {
|
||||
message.gifs.forEach((params, i) => {
|
||||
const previewUrl = api.apiURL(
|
||||
'/view?' + new URLSearchParams(params).toString()
|
||||
)
|
||||
const w = this.addCustomWidget(
|
||||
CreatePreviewElement(`${prefix}_${i}`, previewUrl, params.format || 'image/gif')
|
||||
)
|
||||
w.parent = this
|
||||
})
|
||||
}
|
||||
const onRemoved = this.onRemoved
|
||||
this.onRemoved = () => {
|
||||
cleanupNode(this)
|
||||
return onRemoved?.()
|
||||
}
|
||||
}
|
||||
this.setSize([this.size[0], this.computeSize([this.size[0], this.size[1]])[1]])
|
||||
return r
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.registerExtension(gif_preview)
|
||||
Reference in New Issue
Block a user