Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a0c10b25b | ||
|
|
4b37dbd421 | ||
|
|
84cbeab2e6 | ||
|
|
d508fe9027 |
+5
-6
@@ -1,11 +1,10 @@
|
|||||||
from .adv_control.nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
from .adv_control.nodes import AdvancedControlNetExtension
|
||||||
from .adv_control import documentation
|
|
||||||
from .adv_control.dinklink import init_dinklink
|
from .adv_control.dinklink import init_dinklink
|
||||||
from .adv_control.sampling import prepare_dinklink_acn_wrapper
|
from .adv_control.sampling import prepare_dinklink_acn_wrapper
|
||||||
|
|
||||||
WEB_DIRECTORY = "./web"
|
|
||||||
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', "WEB_DIRECTORY"]
|
|
||||||
documentation.format_descriptions(NODE_CLASS_MAPPINGS)
|
|
||||||
|
|
||||||
init_dinklink()
|
init_dinklink()
|
||||||
prepare_dinklink_acn_wrapper()
|
prepare_dinklink_acn_wrapper()
|
||||||
|
|
||||||
|
|
||||||
|
async def comfy_entrypoint() -> AdvancedControlNetExtension:
|
||||||
|
return AdvancedControlNetExtension()
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
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>'
|
|
||||||
|
|
||||||
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 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}")
|
|
||||||
|
|
||||||
+52
-122
@@ -1,4 +1,4 @@
|
|||||||
import comfy.sample
|
from comfy_api.latest import ComfyExtension, io
|
||||||
|
|
||||||
from .nodes_main import (ControlNetLoaderAdvanced, DiffControlNetLoaderAdvanced, AnimaLLLiteLoaderAdvanced,
|
from .nodes_main import (ControlNetLoaderAdvanced, DiffControlNetLoaderAdvanced, AnimaLLLiteLoaderAdvanced,
|
||||||
AdvancedControlNetApply, AdvancedControlNetApplySingle)
|
AdvancedControlNetApply, AdvancedControlNetApplySingle)
|
||||||
@@ -12,132 +12,62 @@ from .nodes_sparsectrl import SparseCtrlMergedLoaderAdvanced, SparseCtrlLoaderAd
|
|||||||
from .nodes_reference import ReferenceControlNetNode, ReferenceControlFinetune, ReferencePreprocessorNode
|
from .nodes_reference import ReferenceControlNetNode, ReferenceControlFinetune, ReferencePreprocessorNode
|
||||||
from .nodes_plusplus import PlusPlusLoaderAdvanced, PlusPlusLoaderSingle, PlusPlusInputNode
|
from .nodes_plusplus import PlusPlusLoaderAdvanced, PlusPlusLoaderSingle, PlusPlusInputNode
|
||||||
from .nodes_ctrlora import CtrLoRALoader
|
from .nodes_ctrlora import CtrLoRALoader
|
||||||
from .nodes_loosecontrol import ControlNetLoaderWithLoraAdvanced
|
|
||||||
from .nodes_deprecated import (LoadImagesFromDirectory, ScaledSoftUniversalWeightsDeprecated,
|
from .nodes_deprecated import (LoadImagesFromDirectory, ScaledSoftUniversalWeightsDeprecated,
|
||||||
SoftControlNetWeightsDeprecated, CustomControlNetWeightsDeprecated,
|
SoftControlNetWeightsDeprecated, CustomControlNetWeightsDeprecated,
|
||||||
SoftT2IAdapterWeightsDeprecated, CustomT2IAdapterWeightsDeprecated,
|
SoftT2IAdapterWeightsDeprecated, CustomT2IAdapterWeightsDeprecated,
|
||||||
AdvancedControlNetApplyDEPR, AdvancedControlNetApplySingleDEPR,
|
AdvancedControlNetApplyDEPR, AdvancedControlNetApplySingleDEPR,
|
||||||
ControlNetLoaderAdvancedDEPR, DiffControlNetLoaderAdvancedDEPR)
|
ControlNetLoaderAdvancedDEPR, DiffControlNetLoaderAdvancedDEPR)
|
||||||
from .logger import logger
|
|
||||||
|
|
||||||
|
|
||||||
# NODE MAPPING
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
|
||||||
# Keyframes
|
|
||||||
"TimestepKeyframe": TimestepKeyframeNode,
|
|
||||||
"ACN_TimestepKeyframeInterpolation": TimestepKeyframeInterpolationNode,
|
|
||||||
"ACN_TimestepKeyframeFromStrengthList": TimestepKeyframeFromStrengthListNode,
|
|
||||||
"LatentKeyframe": LatentKeyframeNode,
|
|
||||||
"LatentKeyframeTiming": LatentKeyframeInterpolationNode,
|
|
||||||
"LatentKeyframeBatchedGroup": LatentKeyframeBatchedGroupNode,
|
|
||||||
"LatentKeyframeGroup": LatentKeyframeGroupNode,
|
|
||||||
# Conditioning
|
|
||||||
"ACN_AdvancedControlNetApply_v2": AdvancedControlNetApply,
|
|
||||||
"ACN_AdvancedControlNetApplySingle_v2": AdvancedControlNetApplySingle,
|
|
||||||
# Loaders
|
|
||||||
"ACN_ControlNetLoaderAdvanced": ControlNetLoaderAdvanced,
|
|
||||||
"ACN_DiffControlNetLoaderAdvanced": DiffControlNetLoaderAdvanced,
|
|
||||||
"ACN_AnimaLLLiteLoaderAdvanced": AnimaLLLiteLoaderAdvanced,
|
|
||||||
# Weights
|
|
||||||
"ACN_ScaledSoftControlNetWeights": ScaledSoftUniversalWeights,
|
|
||||||
"ScaledSoftMaskedUniversalWeights": ScaledSoftMaskedUniversalWeights,
|
|
||||||
"ACN_SoftControlNetWeightsSD15": SoftControlNetWeightsSD15,
|
|
||||||
"ACN_CustomControlNetWeightsSD15": CustomControlNetWeightsSD15,
|
|
||||||
"ACN_CustomControlNetWeightsFlux": CustomControlNetWeightsFlux,
|
|
||||||
"ACN_CustomControlNetWeightsAnima": CustomControlNetWeightsAnima,
|
|
||||||
"ACN_SoftT2IAdapterWeights": SoftT2IAdapterWeights,
|
|
||||||
"ACN_CustomT2IAdapterWeights": CustomT2IAdapterWeights,
|
|
||||||
"ACN_DefaultUniversalWeights": DefaultWeights,
|
|
||||||
"ACN_ExtrasMiddleMult": ExtrasMiddleMultNode,
|
|
||||||
"ACN_AnimaLLLiteExtras": AnimaLLLiteExtras,
|
|
||||||
# SparseCtrl
|
|
||||||
"ACN_SparseCtrlRGBPreprocessor": RgbSparseCtrlPreprocessor,
|
|
||||||
"ACN_SparseCtrlLoaderAdvanced": SparseCtrlLoaderAdvanced,
|
|
||||||
"ACN_SparseCtrlMergedLoaderAdvanced": SparseCtrlMergedLoaderAdvanced,
|
|
||||||
"ACN_SparseCtrlIndexMethodNode": SparseIndexMethodNode,
|
|
||||||
"ACN_SparseCtrlSpreadMethodNode": SparseSpreadMethodNode,
|
|
||||||
"ACN_SparseCtrlWeightExtras": SparseWeightExtras,
|
|
||||||
# ControlNet++
|
|
||||||
"ACN_ControlNet++LoaderSingle": PlusPlusLoaderSingle,
|
|
||||||
"ACN_ControlNet++LoaderAdvanced": PlusPlusLoaderAdvanced,
|
|
||||||
"ACN_ControlNet++InputNode": PlusPlusInputNode,
|
|
||||||
# CtrLoRA
|
|
||||||
"ACN_CtrLoRALoader": CtrLoRALoader,
|
|
||||||
# Reference
|
|
||||||
"ACN_ReferencePreprocessor": ReferencePreprocessorNode,
|
|
||||||
"ACN_ReferenceControlNet": ReferenceControlNetNode,
|
|
||||||
"ACN_ReferenceControlNetFinetune": ReferenceControlFinetune,
|
|
||||||
# LOOSEControl
|
|
||||||
#"ACN_ControlNetLoaderWithLoraAdvanced": ControlNetLoaderWithLoraAdvanced,
|
|
||||||
# Deprecated
|
|
||||||
"LoadImagesFromDirectory": LoadImagesFromDirectory,
|
|
||||||
"ScaledSoftControlNetWeights": ScaledSoftUniversalWeightsDeprecated,
|
|
||||||
"SoftControlNetWeights": SoftControlNetWeightsDeprecated,
|
|
||||||
"CustomControlNetWeights": CustomControlNetWeightsDeprecated,
|
|
||||||
"SoftT2IAdapterWeights": SoftT2IAdapterWeightsDeprecated,
|
|
||||||
"CustomT2IAdapterWeights": CustomT2IAdapterWeightsDeprecated,
|
|
||||||
"ACN_AdvancedControlNetApply": AdvancedControlNetApplyDEPR,
|
|
||||||
"ACN_AdvancedControlNetApplySingle": AdvancedControlNetApplySingleDEPR,
|
|
||||||
"ControlNetLoaderAdvanced": ControlNetLoaderAdvancedDEPR,
|
|
||||||
"DiffControlNetLoaderAdvanced": DiffControlNetLoaderAdvancedDEPR,
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
|
||||||
# Keyframes
|
class AdvancedControlNetExtension(ComfyExtension):
|
||||||
"TimestepKeyframe": "Timestep Keyframe 🛂🅐🅒🅝",
|
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||||
"ACN_TimestepKeyframeInterpolation": "Timestep Keyframe Interp. 🛂🅐🅒🅝",
|
return [
|
||||||
"ACN_TimestepKeyframeFromStrengthList": "Timestep Keyframe From List 🛂🅐🅒🅝",
|
TimestepKeyframeNode,
|
||||||
"LatentKeyframe": "Latent Keyframe 🛂🅐🅒🅝",
|
TimestepKeyframeInterpolationNode,
|
||||||
"LatentKeyframeTiming": "Latent Keyframe Interp. 🛂🅐🅒🅝",
|
TimestepKeyframeFromStrengthListNode,
|
||||||
"LatentKeyframeBatchedGroup": "Latent Keyframe From List 🛂🅐🅒🅝",
|
LatentKeyframeNode,
|
||||||
"LatentKeyframeGroup": "Latent Keyframe Group 🛂🅐🅒🅝",
|
LatentKeyframeInterpolationNode,
|
||||||
# Conditioning
|
LatentKeyframeBatchedGroupNode,
|
||||||
"ACN_AdvancedControlNetApply_v2": "Apply Advanced ControlNet 🛂🅐🅒🅝",
|
LatentKeyframeGroupNode,
|
||||||
"ACN_AdvancedControlNetApplySingle_v2": "Apply Advanced ControlNet(1) 🛂🅐🅒🅝",
|
AdvancedControlNetApply,
|
||||||
# Loaders
|
AdvancedControlNetApplySingle,
|
||||||
"ACN_ControlNetLoaderAdvanced": "Load Advanced ControlNet Model 🛂🅐🅒🅝",
|
ControlNetLoaderAdvanced,
|
||||||
"ACN_DiffControlNetLoaderAdvanced": "Load Advanced ControlNet Model (diff) 🛂🅐🅒🅝",
|
DiffControlNetLoaderAdvanced,
|
||||||
"ACN_AnimaLLLiteLoaderAdvanced": "Load Anima LLLite Model 🛂🅐🅒🅝",
|
AnimaLLLiteLoaderAdvanced,
|
||||||
# Weights
|
ScaledSoftUniversalWeights,
|
||||||
"ACN_ScaledSoftControlNetWeights": "Scaled Soft Weights 🛂🅐🅒🅝",
|
ScaledSoftMaskedUniversalWeights,
|
||||||
"ScaledSoftMaskedUniversalWeights": "Scaled Soft Masked Weights 🛂🅐🅒🅝",
|
SoftControlNetWeightsSD15,
|
||||||
"ACN_SoftControlNetWeightsSD15": "ControlNet Soft Weights [SD1.5] 🛂🅐🅒🅝",
|
CustomControlNetWeightsSD15,
|
||||||
"ACN_CustomControlNetWeightsSD15": "ControlNet Custom Weights [SD1.5] 🛂🅐🅒🅝",
|
CustomControlNetWeightsFlux,
|
||||||
"ACN_CustomControlNetWeightsFlux": "ControlNet Custom Weights [Flux] 🛂🅐🅒🅝",
|
CustomControlNetWeightsAnima,
|
||||||
"ACN_CustomControlNetWeightsAnima": "ControlNet Custom Weights [Anima] 🛂🅐🅒🅝",
|
SoftT2IAdapterWeights,
|
||||||
"ACN_SoftT2IAdapterWeights": "T2IAdapter Soft Weights 🛂🅐🅒🅝",
|
CustomT2IAdapterWeights,
|
||||||
"ACN_CustomT2IAdapterWeights": "T2IAdapter Custom Weights 🛂🅐🅒🅝",
|
DefaultWeights,
|
||||||
"ACN_DefaultUniversalWeights": "Default Weights 🛂🅐🅒🅝",
|
ExtrasMiddleMultNode,
|
||||||
"ACN_ExtrasMiddleMult": "Middle Weight Extras 🛂🅐🅒🅝",
|
AnimaLLLiteExtras,
|
||||||
"ACN_AnimaLLLiteExtras": "Anima LLLite Extras 🛂🅐🅒🅝",
|
RgbSparseCtrlPreprocessor,
|
||||||
# SparseCtrl
|
SparseCtrlLoaderAdvanced,
|
||||||
"ACN_SparseCtrlRGBPreprocessor": "RGB SparseCtrl 🛂🅐🅒🅝",
|
SparseCtrlMergedLoaderAdvanced,
|
||||||
"ACN_SparseCtrlLoaderAdvanced": "Load SparseCtrl Model 🛂🅐🅒🅝",
|
SparseIndexMethodNode,
|
||||||
"ACN_SparseCtrlMergedLoaderAdvanced": "🧪Load Merged SparseCtrl Model 🛂🅐🅒🅝",
|
SparseSpreadMethodNode,
|
||||||
"ACN_SparseCtrlIndexMethodNode": "SparseCtrl Index Method 🛂🅐🅒🅝",
|
SparseWeightExtras,
|
||||||
"ACN_SparseCtrlSpreadMethodNode": "SparseCtrl Spread Method 🛂🅐🅒🅝",
|
PlusPlusLoaderSingle,
|
||||||
"ACN_SparseCtrlWeightExtras": "SparseCtrl Weight Extras 🛂🅐🅒🅝",
|
PlusPlusLoaderAdvanced,
|
||||||
# ControlNet++
|
PlusPlusInputNode,
|
||||||
"ACN_ControlNet++LoaderSingle": "Load ControlNet++ Model (Single) 🛂🅐🅒🅝",
|
CtrLoRALoader,
|
||||||
"ACN_ControlNet++LoaderAdvanced": "Load ControlNet++ Model (Multi) 🛂🅐🅒🅝",
|
ReferencePreprocessorNode,
|
||||||
"ACN_ControlNet++InputNode": "ControlNet++ Input 🛂🅐🅒🅝",
|
ReferenceControlNetNode,
|
||||||
# CtrLoRA
|
ReferenceControlFinetune,
|
||||||
"ACN_CtrLoRALoader": "Load CtrLoRA Model 🛂🅐🅒🅝",
|
LoadImagesFromDirectory,
|
||||||
# Reference
|
ScaledSoftUniversalWeightsDeprecated,
|
||||||
"ACN_ReferencePreprocessor": "Reference Preproccessor 🛂🅐🅒🅝",
|
SoftControlNetWeightsDeprecated,
|
||||||
"ACN_ReferenceControlNet": "Reference ControlNet 🛂🅐🅒🅝",
|
CustomControlNetWeightsDeprecated,
|
||||||
"ACN_ReferenceControlNetFinetune": "Reference ControlNet (Finetune) 🛂🅐🅒🅝",
|
SoftT2IAdapterWeightsDeprecated,
|
||||||
# LOOSEControl
|
CustomT2IAdapterWeightsDeprecated,
|
||||||
#"ACN_ControlNetLoaderWithLoraAdvanced": "Load Adv. ControlNet Model w/ LoRA 🛂🅐🅒🅝",
|
AdvancedControlNetApplyDEPR,
|
||||||
# Deprecated
|
AdvancedControlNetApplySingleDEPR,
|
||||||
"LoadImagesFromDirectory": "🚫Load Images [DEPRECATED] 🛂🅐🅒🅝",
|
ControlNetLoaderAdvancedDEPR,
|
||||||
"ScaledSoftControlNetWeights": "Scaled Soft Weights 🛂🅐🅒🅝",
|
DiffControlNetLoaderAdvancedDEPR
|
||||||
"SoftControlNetWeights": "ControlNet Soft Weights 🛂🅐🅒🅝",
|
]
|
||||||
"CustomControlNetWeights": "ControlNet Custom Weights 🛂🅐🅒🅝",
|
|
||||||
"SoftT2IAdapterWeights": "T2IAdapter Soft Weights 🛂🅐🅒🅝",
|
|
||||||
"CustomT2IAdapterWeights": "T2IAdapter Custom Weights 🛂🅐🅒🅝",
|
|
||||||
"ACN_AdvancedControlNetApply": "Apply Advanced ControlNet 🛂🅐🅒🅝",
|
|
||||||
"ACN_AdvancedControlNetApplySingle": "Apply Advanced ControlNet(1) 🛂🅐🅒🅝",
|
|
||||||
"ControlNetLoaderAdvanced": "Load Advanced ControlNet Model 🛂🅐🅒🅝",
|
|
||||||
"DiffControlNetLoaderAdvanced": "Load Advanced ControlNet Model (diff) 🛂🅐🅒🅝",
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,25 +1,28 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
import folder_paths
|
import folder_paths
|
||||||
|
|
||||||
from .control_ctrlora import load_ctrlora
|
from .control_ctrlora import load_ctrlora
|
||||||
|
|
||||||
|
class CtrLoRALoader(io.ComfyNode):
|
||||||
class CtrLoRALoader:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_CtrLoRALoader',
|
||||||
"base": (folder_paths.get_filename_list("controlnet"), ),
|
display_name='Load CtrLoRA Model 🛂🅐🅒🅝',
|
||||||
"lora": (folder_paths.get_filename_list("controlnet"), ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/CtrLoRA',
|
||||||
}
|
inputs=[
|
||||||
}
|
io.Combo.Input('base', options=folder_paths.get_filename_list("controlnet")),
|
||||||
|
io.Combo.Input('lora', options=folder_paths.get_filename_list("controlnet"))
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET",)
|
|
||||||
FUNCTION = "load_controlnet_plusplus"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/CtrLoRA"
|
@classmethod
|
||||||
|
def execute(cls, base: str, lora: str):
|
||||||
def load_controlnet_plusplus(self, base: str, lora: str):
|
|
||||||
base_path = folder_paths.get_full_path("controlnet", base)
|
base_path = folder_paths.get_full_path("controlnet", base)
|
||||||
lora_path = folder_paths.get_full_path("controlnet", lora)
|
lora_path = folder_paths.get_full_path("controlnet", lora)
|
||||||
controlnet = load_ctrlora(base_path, lora_path)
|
controlnet = load_ctrlora(base_path, lora_path)
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|||||||
+257
-279
@@ -1,3 +1,4 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
@@ -7,29 +8,31 @@ import numpy as np
|
|||||||
from PIL import Image, ImageOps
|
from PIL import Image, ImageOps
|
||||||
from .control import load_controlnet, is_advanced_controlnet
|
from .control import load_controlnet, is_advanced_controlnet
|
||||||
from .nodes_main import AdvancedControlNetApply
|
from .nodes_main import AdvancedControlNetApply
|
||||||
from .utils import BIGMAX, ControlWeights, TimestepKeyframeGroup, TimestepKeyframe, get_properly_arranged_t2i_weights
|
from .utils import ControlWeights, TimestepKeyframeGroup, TimestepKeyframe, get_properly_arranged_t2i_weights
|
||||||
from .logger import logger
|
|
||||||
|
|
||||||
|
class LoadImagesFromDirectory(io.ComfyNode):
|
||||||
class LoadImagesFromDirectory:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='LoadImagesFromDirectory',
|
||||||
"directory": ("STRING", {"default": ""}),
|
display_name='🚫Load Images [DEPRECATED] 🛂🅐🅒🅝',
|
||||||
},
|
category='',
|
||||||
"optional": {
|
inputs=[
|
||||||
"image_load_cap": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}),
|
io.String.Input('directory', default=''),
|
||||||
"start_index": ("INT", {"default": 0, "min": 0, "max": BIGMAX, "step": 1}),
|
io.Int.Input('image_load_cap', optional=True, default=0, max=9007199254740991, min=0, step=1),
|
||||||
}
|
io.Int.Input('start_index', optional=True, default=0, max=9007199254740991, min=0, step=1)
|
||||||
}
|
],
|
||||||
|
outputs=[
|
||||||
|
io.Image.Output('IMAGE', is_output_list=False),
|
||||||
|
io.Mask.Output('MASK', is_output_list=False),
|
||||||
|
io.Int.Output('INT', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE", "MASK", "INT")
|
|
||||||
FUNCTION = "load_images"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
@classmethod
|
||||||
|
def execute(cls, directory: str, image_load_cap: int = 0, start_index: int = 0):
|
||||||
def load_images(self, directory: str, image_load_cap: int = 0, start_index: int = 0):
|
|
||||||
if not os.path.isdir(directory):
|
if not os.path.isdir(directory):
|
||||||
raise FileNotFoundError(f"Directory '{directory} cannot be found.'")
|
raise FileNotFoundError(f"Directory '{directory} cannot be found.'")
|
||||||
dir_files = os.listdir(directory)
|
dir_files = os.listdir(directory)
|
||||||
@@ -71,306 +74,283 @@ class LoadImagesFromDirectory:
|
|||||||
if len(images) == 0:
|
if len(images) == 0:
|
||||||
raise FileNotFoundError(f"No images could be loaded from directory '{directory}'.")
|
raise FileNotFoundError(f"No images could be loaded from directory '{directory}'.")
|
||||||
|
|
||||||
return (torch.cat(images, dim=0), torch.stack(masks, dim=0), image_count)
|
return io.NodeOutput(torch.cat(images, dim=0), torch.stack(masks, dim=0), image_count)
|
||||||
|
|
||||||
|
class ScaledSoftUniversalWeightsDeprecated(io.ComfyNode):
|
||||||
class ScaledSoftUniversalWeightsDeprecated:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ScaledSoftControlNetWeights',
|
||||||
"base_multiplier": ("FLOAT", {"default": 0.825, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
display_name='Scaled Soft Weights 🛂🅐🅒🅝',
|
||||||
"flip_weights": ("BOOLEAN", {"default": False}),
|
category='',
|
||||||
},
|
inputs=[
|
||||||
"optional": {
|
io.Float.Input('base_multiplier', default=0.825, max=1.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Boolean.Input('flip_weights', default=False),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = ("CN_WEIGHTS", "TK_SHORTCUT")
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
@classmethod
|
||||||
|
def execute(cls, base_multiplier, flip_weights, uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
def load_weights(self, base_multiplier, flip_weights, uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
|
||||||
weights = ControlWeights.universal(base_multiplier=base_multiplier, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
weights = ControlWeights.universal(base_multiplier=base_multiplier, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class SoftControlNetWeightsDeprecated(io.ComfyNode):
|
||||||
class SoftControlNetWeightsDeprecated:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='SoftControlNetWeights',
|
||||||
"weight_00": ("FLOAT", {"default": 0.09941396206337118, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='ControlNet Soft Weights 🛂🅐🅒🅝',
|
||||||
"weight_01": ("FLOAT", {"default": 0.12050177219802567, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='',
|
||||||
"weight_02": ("FLOAT", {"default": 0.14606275417942507, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"weight_03": ("FLOAT", {"default": 0.17704576264172736, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_00', default=0.09941396206337118, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_04": ("FLOAT", {"default": 0.214600924414215, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_01', default=0.12050177219802567, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_05": ("FLOAT", {"default": 0.26012233262329093, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_02', default=0.14606275417942507, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_06": ("FLOAT", {"default": 0.3152997971191405, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_03', default=0.17704576264172736, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_07": ("FLOAT", {"default": 0.3821815722656249, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_04', default=0.214600924414215, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_08": ("FLOAT", {"default": 0.4632503906249999, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_05', default=0.26012233262329093, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_09": ("FLOAT", {"default": 0.561515625, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_06', default=0.3152997971191405, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_10": ("FLOAT", {"default": 0.6806249999999999, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_07', default=0.3821815722656249, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_11": ("FLOAT", {"default": 0.825, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_08', default=0.4632503906249999, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_12": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_09', default=0.561515625, max=10.0, min=0.0, step=0.001),
|
||||||
"flip_weights": ("BOOLEAN", {"default": False}),
|
io.Float.Input('weight_10', default=0.6806249999999999, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('weight_11', default=0.825, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('weight_12', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Boolean.Input('flip_weights', default=False),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = ("CN_WEIGHTS", "TK_SHORTCUT")
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
@classmethod
|
||||||
|
def execute(cls, weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
||||||
def load_weights(self, weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
|
||||||
weight_07, weight_08, weight_09, weight_10, weight_11, weight_12, flip_weights,
|
weight_07, weight_08, weight_09, weight_10, weight_11, weight_12, flip_weights,
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
weights_output = [weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
weights_output = [weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
||||||
weight_07, weight_08, weight_09, weight_10, weight_11]
|
weight_07, weight_08, weight_09, weight_10, weight_11]
|
||||||
weights_middle = [weight_12]
|
weights_middle = [weight_12]
|
||||||
weights = ControlWeights.controlnet(weights_output=weights_output, weights_middle=weights_middle, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
weights = ControlWeights.controlnet(weights_output=weights_output, weights_middle=weights_middle, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class CustomControlNetWeightsDeprecated(io.ComfyNode):
|
||||||
class CustomControlNetWeightsDeprecated:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='CustomControlNetWeights',
|
||||||
"weight_00": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='ControlNet Custom Weights 🛂🅐🅒🅝',
|
||||||
"weight_01": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='',
|
||||||
"weight_02": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"weight_03": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_00', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_04": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_01', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_05": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_02', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_06": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_03', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_07": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_04', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_08": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_05', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_09": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_06', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_10": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_07', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_11": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_08', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"weight_12": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_09', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"flip_weights": ("BOOLEAN", {"default": False}),
|
io.Float.Input('weight_10', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('weight_11', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('weight_12', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Boolean.Input('flip_weights', default=False),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = ("CN_WEIGHTS", "TK_SHORTCUT")
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
@classmethod
|
||||||
|
def execute(cls, weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
||||||
def load_weights(self, weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
|
||||||
weight_07, weight_08, weight_09, weight_10, weight_11, weight_12, flip_weights,
|
weight_07, weight_08, weight_09, weight_10, weight_11, weight_12, flip_weights,
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
weights_output = [weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
weights_output = [weight_00, weight_01, weight_02, weight_03, weight_04, weight_05, weight_06,
|
||||||
weight_07, weight_08, weight_09, weight_10, weight_11]
|
weight_07, weight_08, weight_09, weight_10, weight_11]
|
||||||
weights_middle = [weight_12]
|
weights_middle = [weight_12]
|
||||||
weights = ControlWeights.controlnet(weights_output=weights_output, weights_middle=weights_middle, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
weights = ControlWeights.controlnet(weights_output=weights_output, weights_middle=weights_middle, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class SoftT2IAdapterWeightsDeprecated(io.ComfyNode):
|
||||||
class SoftT2IAdapterWeightsDeprecated:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='SoftT2IAdapterWeights',
|
||||||
"weight_00": ("FLOAT", {"default": 0.25, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='T2IAdapter Soft Weights 🛂🅐🅒🅝',
|
||||||
"weight_01": ("FLOAT", {"default": 0.62, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='',
|
||||||
"weight_02": ("FLOAT", {"default": 0.825, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"weight_03": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_00', default=0.25, max=10.0, min=0.0, step=0.001),
|
||||||
"flip_weights": ("BOOLEAN", {"default": False}),
|
io.Float.Input('weight_01', default=0.62, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('weight_02', default=0.825, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('weight_03', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Boolean.Input('flip_weights', default=False),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = ("CN_WEIGHTS", "TK_SHORTCUT")
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
@classmethod
|
||||||
|
def execute(cls, weight_00, weight_01, weight_02, weight_03, flip_weights,
|
||||||
def load_weights(self, weight_00, weight_01, weight_02, weight_03, flip_weights,
|
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
weights = [weight_00, weight_01, weight_02, weight_03]
|
weights = [weight_00, weight_01, weight_02, weight_03]
|
||||||
weights = get_properly_arranged_t2i_weights(weights)
|
weights = get_properly_arranged_t2i_weights(weights)
|
||||||
weights = ControlWeights.t2iadapter(weights_input=weights, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
weights = ControlWeights.t2iadapter(weights_input=weights, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class CustomT2IAdapterWeightsDeprecated(io.ComfyNode):
|
||||||
class CustomT2IAdapterWeightsDeprecated:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='CustomT2IAdapterWeights',
|
||||||
"weight_00": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='T2IAdapter Custom Weights 🛂🅐🅒🅝',
|
||||||
"weight_01": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='',
|
||||||
"weight_02": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"weight_03": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('weight_00', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"flip_weights": ("BOOLEAN", {"default": False}),
|
io.Float.Input('weight_01', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('weight_02', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('weight_03', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Boolean.Input('flip_weights', default=False),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = ("CN_WEIGHTS", "TK_SHORTCUT")
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
@classmethod
|
||||||
|
def execute(cls, weight_00, weight_01, weight_02, weight_03, flip_weights,
|
||||||
def load_weights(self, weight_00, weight_01, weight_02, weight_03, flip_weights,
|
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
weights = [weight_00, weight_01, weight_02, weight_03]
|
weights = [weight_00, weight_01, weight_02, weight_03]
|
||||||
weights = get_properly_arranged_t2i_weights(weights)
|
weights = get_properly_arranged_t2i_weights(weights)
|
||||||
weights = ControlWeights.t2iadapter(weights_input=weights, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
weights = ControlWeights.t2iadapter(weights_input=weights, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class AdvancedControlNetApplyDEPR(io.ComfyNode):
|
||||||
class AdvancedControlNetApplyDEPR:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_AdvancedControlNetApply',
|
||||||
"positive": ("CONDITIONING", ),
|
display_name='Apply Advanced ControlNet 🛂🅐🅒🅝',
|
||||||
"negative": ("CONDITIONING", ),
|
category='',
|
||||||
"control_net": ("CONTROL_NET", ),
|
inputs=[
|
||||||
"image": ("IMAGE", ),
|
io.Conditioning.Input('positive'),
|
||||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
io.Conditioning.Input('negative'),
|
||||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
io.ControlNet.Input('control_net'),
|
||||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001})
|
io.Image.Input('image'),
|
||||||
},
|
io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||||
"optional": {
|
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
"mask_optional": ("MASK", ),
|
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||||
"timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Mask.Input('mask_optional', optional=True),
|
||||||
"latent_kf_override": ("LATENT_KEYFRAME", ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('timestep_kf', optional=True),
|
||||||
"weights_override": ("CONTROL_NET_WEIGHTS", ),
|
io.Custom('LATENT_KEYFRAME').Input('latent_kf_override', optional=True),
|
||||||
"model_optional": ("MODEL",),
|
io.Custom('CONTROL_NET_WEIGHTS').Input('weights_override', optional=True),
|
||||||
"vae_optional": ("VAE",),
|
io.Model.Input('model_optional', optional=True),
|
||||||
},
|
io.Vae.Input('vae_optional', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Conditioning.Output('positive', is_output_list=False),
|
||||||
}
|
io.Conditioning.Output('negative', is_output_list=False),
|
||||||
|
io.Model.Output('model_opt', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
@classmethod
|
||||||
RETURN_TYPES = ("CONDITIONING","CONDITIONING","MODEL",)
|
def execute(cls, positive, negative, control_net, image, strength, start_percent, end_percent,
|
||||||
RETURN_NAMES = ("positive", "negative", "model_opt")
|
|
||||||
FUNCTION = "apply_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
|
||||||
|
|
||||||
def apply_controlnet(self, positive, negative, control_net, image, strength, start_percent, end_percent,
|
|
||||||
mask_optional=None, model_optional=None, vae_optional=None,
|
mask_optional=None, model_optional=None, vae_optional=None,
|
||||||
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override=None,
|
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override=None,
|
||||||
weights_override: ControlWeights=None, control_apply_to_uncond=False):
|
weights_override: ControlWeights=None, control_apply_to_uncond=False):
|
||||||
new_positive, new_negative = AdvancedControlNetApply.apply_controlnet(self, positive=positive, negative=negative, control_net=control_net, image=image,
|
new_positive, new_negative = AdvancedControlNetApply.execute(positive=positive, negative=negative, control_net=control_net, image=image,
|
||||||
strength=strength, start_percent=start_percent, end_percent=end_percent,
|
strength=strength, start_percent=start_percent, end_percent=end_percent,
|
||||||
mask_optional=mask_optional, vae_optional=vae_optional,
|
mask_optional=mask_optional, vae_optional=vae_optional,
|
||||||
timestep_kf=timestep_kf, latent_kf_override=latent_kf_override, weights_override=weights_override,)
|
timestep_kf=timestep_kf, latent_kf_override=latent_kf_override, weights_override=weights_override,).args
|
||||||
return (new_positive, new_negative, model_optional)
|
return io.NodeOutput(new_positive, new_negative, model_optional)
|
||||||
|
|
||||||
|
class AdvancedControlNetApplySingleDEPR(io.ComfyNode):
|
||||||
class AdvancedControlNetApplySingleDEPR:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_AdvancedControlNetApplySingle',
|
||||||
"conditioning": ("CONDITIONING", ),
|
display_name='Apply Advanced ControlNet(1) 🛂🅐🅒🅝',
|
||||||
"control_net": ("CONTROL_NET", ),
|
category='',
|
||||||
"image": ("IMAGE", ),
|
inputs=[
|
||||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
io.Conditioning.Input('conditioning'),
|
||||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
io.ControlNet.Input('control_net'),
|
||||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001})
|
io.Image.Input('image'),
|
||||||
},
|
io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||||
"optional": {
|
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
"mask_optional": ("MASK", ),
|
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||||
"timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Mask.Input('mask_optional', optional=True),
|
||||||
"latent_kf_override": ("LATENT_KEYFRAME", ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('timestep_kf', optional=True),
|
||||||
"weights_override": ("CONTROL_NET_WEIGHTS", ),
|
io.Custom('LATENT_KEYFRAME').Input('latent_kf_override', optional=True),
|
||||||
"model_optional": ("MODEL",),
|
io.Custom('CONTROL_NET_WEIGHTS').Input('weights_override', optional=True),
|
||||||
"vae_optional": ("VAE",),
|
io.Model.Input('model_optional', optional=True),
|
||||||
},
|
io.Vae.Input('vae_optional', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Conditioning.Output('CONDITIONING', is_output_list=False),
|
||||||
}
|
io.Model.Output('model_opt', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
@classmethod
|
||||||
RETURN_TYPES = ("CONDITIONING","MODEL",)
|
def execute(cls, conditioning, control_net, image, strength, start_percent, end_percent,
|
||||||
RETURN_NAMES = ("CONDITIONING", "model_opt")
|
|
||||||
FUNCTION = "apply_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
|
||||||
|
|
||||||
def apply_controlnet(self, conditioning, control_net, image, strength, start_percent, end_percent,
|
|
||||||
mask_optional=None, model_optional=None, vae_optional=None,
|
mask_optional=None, model_optional=None, vae_optional=None,
|
||||||
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override=None,
|
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override=None,
|
||||||
weights_override: ControlWeights=None):
|
weights_override: ControlWeights=None):
|
||||||
values = AdvancedControlNetApply.apply_controlnet(self, positive=conditioning, negative=None, control_net=control_net, image=image,
|
values = AdvancedControlNetApply.execute(positive=conditioning, negative=None, control_net=control_net, image=image,
|
||||||
strength=strength, start_percent=start_percent, end_percent=end_percent,
|
strength=strength, start_percent=start_percent, end_percent=end_percent,
|
||||||
mask_optional=mask_optional, vae_optional=vae_optional,
|
mask_optional=mask_optional, vae_optional=vae_optional,
|
||||||
timestep_kf=timestep_kf, latent_kf_override=latent_kf_override, weights_override=weights_override,
|
timestep_kf=timestep_kf, latent_kf_override=latent_kf_override, weights_override=weights_override,
|
||||||
control_apply_to_uncond=True)
|
control_apply_to_uncond=True)
|
||||||
return (values[0], model_optional)
|
return io.NodeOutput(values.args[0], model_optional)
|
||||||
|
|
||||||
|
class ControlNetLoaderAdvancedDEPR(io.ComfyNode):
|
||||||
class ControlNetLoaderAdvancedDEPR:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ControlNetLoaderAdvanced',
|
||||||
"control_net_name": (folder_paths.get_filename_list("controlnet"), ),
|
display_name='Load Advanced ControlNet Model 🛂🅐🅒🅝',
|
||||||
},
|
category='',
|
||||||
"optional": {
|
inputs=[
|
||||||
"tk_optional": ("TIMESTEP_KEYFRAME", ),
|
io.Combo.Input('control_net_name', options=folder_paths.get_filename_list("controlnet")),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Input('tk_optional', optional=True)
|
||||||
}
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
@classmethod
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
def execute(cls, control_net_name,
|
||||||
FUNCTION = "load_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
|
||||||
|
|
||||||
def load_controlnet(self, control_net_name,
|
|
||||||
tk_optional: TimestepKeyframeGroup=None,
|
tk_optional: TimestepKeyframeGroup=None,
|
||||||
timestep_keyframe: TimestepKeyframeGroup=None,
|
timestep_keyframe: TimestepKeyframeGroup=None,
|
||||||
):
|
):
|
||||||
@@ -378,32 +358,30 @@ class ControlNetLoaderAdvancedDEPR:
|
|||||||
tk_optional = timestep_keyframe
|
tk_optional = timestep_keyframe
|
||||||
controlnet_path = folder_paths.get_full_path("controlnet", control_net_name)
|
controlnet_path = folder_paths.get_full_path("controlnet", control_net_name)
|
||||||
controlnet = load_controlnet(controlnet_path, tk_optional)
|
controlnet = load_controlnet(controlnet_path, tk_optional)
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|
||||||
|
|
||||||
class DiffControlNetLoaderAdvancedDEPR:
|
class DiffControlNetLoaderAdvancedDEPR(io.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='DiffControlNetLoaderAdvanced',
|
||||||
"model": ("MODEL",),
|
display_name='Load Advanced ControlNet Model (diff) 🛂🅐🅒🅝',
|
||||||
"control_net_name": (folder_paths.get_filename_list("controlnet"), )
|
category='',
|
||||||
},
|
inputs=[
|
||||||
"optional": {
|
io.Model.Input('model'),
|
||||||
"tk_optional": ("TIMESTEP_KEYFRAME", ),
|
io.Combo.Input('control_net_name', options=folder_paths.get_filename_list("controlnet")),
|
||||||
},
|
io.Custom('TIMESTEP_KEYFRAME').Input('tk_optional', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
}
|
],
|
||||||
|
is_deprecated=True
|
||||||
|
)
|
||||||
|
|
||||||
DEPRECATED = True
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
|
||||||
FUNCTION = "load_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = ""
|
@classmethod
|
||||||
|
def execute(cls, control_net_name, model,
|
||||||
def load_controlnet(self, control_net_name, model,
|
|
||||||
tk_optional: TimestepKeyframeGroup=None,
|
tk_optional: TimestepKeyframeGroup=None,
|
||||||
timestep_keyframe: TimestepKeyframeGroup=None
|
timestep_keyframe: TimestepKeyframeGroup=None
|
||||||
):
|
):
|
||||||
@@ -413,4 +391,4 @@ class DiffControlNetLoaderAdvancedDEPR:
|
|||||||
controlnet = load_controlnet(controlnet_path, tk_optional, model)
|
controlnet = load_controlnet(controlnet_path, tk_optional, model)
|
||||||
if is_advanced_controlnet(controlnet):
|
if is_advanced_controlnet(controlnet):
|
||||||
controlnet.verify_all_weights()
|
controlnet.verify_all_weights()
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|||||||
+171
-192
@@ -1,43 +1,40 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
|
|
||||||
from .utils import ControlWeights, TimestepKeyframe, TimestepKeyframeGroup, LatentKeyframe, LatentKeyframeGroup, BIGMIN, BIGMAX
|
from .utils import ControlWeights, TimestepKeyframe, TimestepKeyframeGroup, LatentKeyframe, LatentKeyframeGroup
|
||||||
from .utils import StrengthInterpolation as SI
|
from .utils import StrengthInterpolation as SI
|
||||||
from .logger import logger
|
from .logger import logger
|
||||||
|
|
||||||
|
class TimestepKeyframeNode(io.ComfyNode):
|
||||||
class TimestepKeyframeNode:
|
|
||||||
OUTDATED_DUMMY = -39
|
OUTDATED_DUMMY = -39
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='TimestepKeyframe',
|
||||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
display_name='Timestep Keyframe 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/keyframes',
|
||||||
"optional": {
|
inputs=[
|
||||||
"prev_timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('prev_timestep_kf', optional=True),
|
||||||
"cn_weights": ("CONTROL_NET_WEIGHTS", ),
|
io.Float.Input('strength', optional=True, default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"latent_keyframe": ("LATENT_KEYFRAME", ),
|
io.Custom('CONTROL_NET_WEIGHTS').Input('cn_weights', optional=True),
|
||||||
"null_latent_kf_strength": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Custom('LATENT_KEYFRAME').Input('latent_keyframe', optional=True),
|
||||||
"inherit_missing": ("BOOLEAN", {"default": True}, ),
|
io.Float.Input('null_latent_kf_strength', optional=True, default=0.0, max=10.0, min=0.0, step=0.001),
|
||||||
"guarantee_steps": ("INT", {"default": 1, "min": 0, "max": BIGMAX}),
|
io.Boolean.Input('inherit_missing', optional=True, default=True),
|
||||||
"mask_optional": ("MASK", ),
|
io.Int.Input('guarantee_steps', optional=True, default=1, max=9007199254740991, min=0),
|
||||||
},
|
io.Mask.Input('mask_optional', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TIMESTEP_KF', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_NAMES = ("TIMESTEP_KF", )
|
|
||||||
RETURN_TYPES = ("TIMESTEP_KEYFRAME", )
|
|
||||||
FUNCTION = "load_keyframe"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
@classmethod
|
||||||
|
def execute(cls,
|
||||||
def load_keyframe(self,
|
|
||||||
start_percent: float,
|
start_percent: float,
|
||||||
strength: float=1.0,
|
strength: float=1.0,
|
||||||
cn_weights: ControlWeights=None, control_net_weights: ControlWeights=None, # old name
|
cn_weights: ControlWeights=None, control_net_weights: ControlWeights=None, # old name
|
||||||
@@ -49,7 +46,7 @@ class TimestepKeyframeNode:
|
|||||||
guarantee_usage=True, # old input
|
guarantee_usage=True, # old input
|
||||||
mask_optional=None,):
|
mask_optional=None,):
|
||||||
# if using outdated dummy value, means node on workflow is outdated and should appropriately convert behavior
|
# if using outdated dummy value, means node on workflow is outdated and should appropriately convert behavior
|
||||||
if guarantee_steps == self.OUTDATED_DUMMY:
|
if guarantee_steps == cls.OUTDATED_DUMMY:
|
||||||
guarantee_steps = int(guarantee_usage)
|
guarantee_steps = int(guarantee_usage)
|
||||||
control_net_weights = control_net_weights if control_net_weights else cn_weights
|
control_net_weights = control_net_weights if control_net_weights else cn_weights
|
||||||
prev_timestep_keyframe = prev_timestep_keyframe if prev_timestep_keyframe else prev_timestep_kf
|
prev_timestep_keyframe = prev_timestep_keyframe if prev_timestep_keyframe else prev_timestep_kf
|
||||||
@@ -61,42 +58,39 @@ class TimestepKeyframeNode:
|
|||||||
control_weights=control_net_weights, latent_keyframes=latent_keyframe, inherit_missing=inherit_missing,
|
control_weights=control_net_weights, latent_keyframes=latent_keyframe, inherit_missing=inherit_missing,
|
||||||
guarantee_steps=guarantee_steps, mask_hint_orig=mask_optional)
|
guarantee_steps=guarantee_steps, mask_hint_orig=mask_optional)
|
||||||
prev_timestep_keyframe.add(keyframe)
|
prev_timestep_keyframe.add(keyframe)
|
||||||
return (prev_timestep_keyframe,)
|
return io.NodeOutput(prev_timestep_keyframe,)
|
||||||
|
|
||||||
|
|
||||||
class TimestepKeyframeInterpolationNode:
|
class TimestepKeyframeInterpolationNode(io.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_TimestepKeyframeInterpolation',
|
||||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001},),
|
display_name='Timestep Keyframe Interp. 🛂🅐🅒🅝',
|
||||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
category='Adv-ControlNet 🛂🅐🅒🅝/keyframes',
|
||||||
"strength_start": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001},),
|
inputs=[
|
||||||
"strength_end": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001},),
|
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
"interpolation": (SI._LIST, ),
|
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||||
"intervals": ("INT", {"default": 50, "min": 2, "max": 100, "step": 1}),
|
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),
|
||||||
"optional": {
|
io.Combo.Input('interpolation', options=['linear', 'ease-in', 'ease-out', 'ease-in-out']),
|
||||||
"prev_timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Int.Input('intervals', default=50, max=100, min=2, step=1),
|
||||||
"cn_weights": ("CONTROL_NET_WEIGHTS", ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('prev_timestep_kf', optional=True),
|
||||||
"latent_keyframe": ("LATENT_KEYFRAME", ),
|
io.Custom('CONTROL_NET_WEIGHTS').Input('cn_weights', optional=True),
|
||||||
"null_latent_kf_strength": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 10.0, "step": 0.001},),
|
io.Custom('LATENT_KEYFRAME').Input('latent_keyframe', optional=True),
|
||||||
"inherit_missing": ("BOOLEAN", {"default": True},),
|
io.Float.Input('null_latent_kf_strength', optional=True, default=0.0, max=10.0, min=0.0, step=0.001),
|
||||||
"mask_optional": ("MASK", ),
|
io.Boolean.Input('inherit_missing', optional=True, default=True),
|
||||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
io.Mask.Input('mask_optional', optional=True),
|
||||||
},
|
io.Boolean.Input('print_keyframes', optional=True, default=False)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TIMESTEP_KF', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_NAMES = ("TIMESTEP_KF", )
|
|
||||||
RETURN_TYPES = ("TIMESTEP_KEYFRAME", )
|
|
||||||
FUNCTION = "load_keyframe"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
@classmethod
|
||||||
|
def execute(cls,
|
||||||
def load_keyframe(self,
|
|
||||||
start_percent: float, end_percent: float,
|
start_percent: float, end_percent: float,
|
||||||
strength_start: float, strength_end: float, interpolation: str, intervals: int,
|
strength_start: float, strength_end: float, interpolation: str, intervals: int,
|
||||||
cn_weights: ControlWeights=None,
|
cn_weights: ControlWeights=None,
|
||||||
@@ -125,39 +119,35 @@ class TimestepKeyframeInterpolationNode:
|
|||||||
guarantee_steps=guarantee_steps, mask_hint_orig=mask_optional))
|
guarantee_steps=guarantee_steps, mask_hint_orig=mask_optional))
|
||||||
if print_keyframes:
|
if print_keyframes:
|
||||||
logger.info(f"TimestepKeyframe - start_percent:{percent} = {strength}")
|
logger.info(f"TimestepKeyframe - start_percent:{percent} = {strength}")
|
||||||
return (prev_timestep_kf,)
|
return io.NodeOutput(prev_timestep_kf,)
|
||||||
|
|
||||||
|
class TimestepKeyframeFromStrengthListNode(io.ComfyNode):
|
||||||
class TimestepKeyframeFromStrengthListNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_TimestepKeyframeFromStrengthList',
|
||||||
"float_strengths": ("FLOAT", {"default": -1, "min": -1, "step": 0.001, "forceInput": True}),
|
display_name='Timestep Keyframe From List 🛂🅐🅒🅝',
|
||||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001},),
|
category='Adv-ControlNet 🛂🅐🅒🅝/keyframes',
|
||||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
inputs=[
|
||||||
},
|
io.Float.Input('float_strengths', default=-1, force_input=True, min=-1, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
"prev_timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||||
"cn_weights": ("CONTROL_NET_WEIGHTS", ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('prev_timestep_kf', optional=True),
|
||||||
"latent_keyframe": ("LATENT_KEYFRAME", ),
|
io.Custom('CONTROL_NET_WEIGHTS').Input('cn_weights', optional=True),
|
||||||
"null_latent_kf_strength": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 10.0, "step": 0.001},),
|
io.Custom('LATENT_KEYFRAME').Input('latent_keyframe', optional=True),
|
||||||
"inherit_missing": ("BOOLEAN", {"default": True},),
|
io.Float.Input('null_latent_kf_strength', optional=True, default=0.0, max=10.0, min=0.0, step=0.001),
|
||||||
"mask_optional": ("MASK", ),
|
io.Boolean.Input('inherit_missing', optional=True, default=True),
|
||||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
io.Mask.Input('mask_optional', optional=True),
|
||||||
},
|
io.Boolean.Input('print_keyframes', optional=True, default=False)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TIMESTEP_KF', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_NAMES = ("TIMESTEP_KF", )
|
|
||||||
RETURN_TYPES = ("TIMESTEP_KEYFRAME", )
|
|
||||||
FUNCTION = "load_keyframe"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
@classmethod
|
||||||
|
def execute(cls,
|
||||||
def load_keyframe(self,
|
|
||||||
start_percent: float, end_percent: float,
|
start_percent: float, end_percent: float,
|
||||||
float_strengths: float,
|
float_strengths: float,
|
||||||
cn_weights: ControlWeights=None,
|
cn_weights: ControlWeights=None,
|
||||||
@@ -191,32 +181,27 @@ class TimestepKeyframeFromStrengthListNode:
|
|||||||
guarantee_steps=guarantee_steps, mask_hint_orig=mask_optional))
|
guarantee_steps=guarantee_steps, mask_hint_orig=mask_optional))
|
||||||
if print_keyframes:
|
if print_keyframes:
|
||||||
logger.info(f"TimestepKeyframe - start_percent:{percent} = {strength}")
|
logger.info(f"TimestepKeyframe - start_percent:{percent} = {strength}")
|
||||||
return (prev_timestep_kf,)
|
return io.NodeOutput(prev_timestep_kf,)
|
||||||
|
|
||||||
|
class LatentKeyframeNode(io.ComfyNode):
|
||||||
class LatentKeyframeNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='LatentKeyframe',
|
||||||
"batch_index": ("INT", {"default": 0, "min": BIGMIN, "max": BIGMAX, "step": 1}),
|
display_name='Latent Keyframe 🛂🅐🅒🅝',
|
||||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/keyframes',
|
||||||
},
|
inputs=[
|
||||||
"optional": {
|
io.Int.Input('batch_index', default=0, max=9007199254740991, min=-9007199254740991, step=1),
|
||||||
"prev_latent_kf": ("LATENT_KEYFRAME", ),
|
io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Custom('LATENT_KEYFRAME').Input('prev_latent_kf', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('LATENT_KEYFRAME').Output('LATENT_KF', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_NAMES = ("LATENT_KF", )
|
@classmethod
|
||||||
RETURN_TYPES = ("LATENT_KEYFRAME", )
|
def execute(cls,
|
||||||
FUNCTION = "load_keyframe"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
|
||||||
|
|
||||||
def load_keyframe(self,
|
|
||||||
batch_index: int,
|
batch_index: int,
|
||||||
strength: float,
|
strength: float,
|
||||||
prev_latent_kf: LatentKeyframeGroup=None,
|
prev_latent_kf: LatentKeyframeGroup=None,
|
||||||
@@ -229,33 +214,29 @@ class LatentKeyframeNode:
|
|||||||
prev_latent_keyframe = prev_latent_keyframe.clone()
|
prev_latent_keyframe = prev_latent_keyframe.clone()
|
||||||
keyframe = LatentKeyframe(batch_index, strength)
|
keyframe = LatentKeyframe(batch_index, strength)
|
||||||
prev_latent_keyframe.add(keyframe)
|
prev_latent_keyframe.add(keyframe)
|
||||||
return (prev_latent_keyframe,)
|
return io.NodeOutput(prev_latent_keyframe,)
|
||||||
|
|
||||||
|
class LatentKeyframeGroupNode(io.ComfyNode):
|
||||||
class LatentKeyframeGroupNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='LatentKeyframeGroup',
|
||||||
"index_strengths": ("STRING", {"multiline": True, "default": ""}),
|
display_name='Latent Keyframe Group 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/keyframes',
|
||||||
"optional": {
|
inputs=[
|
||||||
"prev_latent_kf": ("LATENT_KEYFRAME", ),
|
io.String.Input('index_strengths', default='', multiline=True),
|
||||||
"latent_optional": ("LATENT", ),
|
io.Custom('LATENT_KEYFRAME').Input('prev_latent_kf', optional=True),
|
||||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
io.Latent.Input('latent_optional', optional=True),
|
||||||
},
|
io.Boolean.Input('print_keyframes', optional=True, default=False)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('LATENT_KEYFRAME').Output('LATENT_KF', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_NAMES = ("LATENT_KF", )
|
|
||||||
RETURN_TYPES = ("LATENT_KEYFRAME", )
|
|
||||||
FUNCTION = "load_keyframes"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
@staticmethod
|
||||||
|
def validate_index(index: int, latent_count: int = 0, is_range: bool = False, allow_negative = False) -> int:
|
||||||
def validate_index(self, index: int, latent_count: int = 0, is_range: bool = False, allow_negative = False) -> int:
|
|
||||||
# if part of range, do nothing
|
# if part of range, do nothing
|
||||||
if is_range:
|
if is_range:
|
||||||
return index
|
return index
|
||||||
@@ -273,13 +254,15 @@ class LatentKeyframeGroupNode:
|
|||||||
index = conv_index
|
index = conv_index
|
||||||
return index
|
return index
|
||||||
|
|
||||||
def convert_to_index_int(self, raw_index: str, latent_count: int = 0, is_range: bool = False, allow_negative = False) -> int:
|
@classmethod
|
||||||
|
def convert_to_index_int(cls, raw_index: str, latent_count: int = 0, is_range: bool = False, allow_negative = False) -> int:
|
||||||
try:
|
try:
|
||||||
return self.validate_index(int(raw_index), latent_count=latent_count, is_range=is_range, allow_negative=allow_negative)
|
return cls.validate_index(int(raw_index), latent_count=latent_count, is_range=is_range, allow_negative=allow_negative)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise ValueError(f"index '{raw_index}' must be an integer.", e)
|
raise ValueError(f"index '{raw_index}' must be an integer.", e)
|
||||||
|
|
||||||
def convert_to_latent_keyframes(self, latent_indeces: str, latent_count: int) -> set[LatentKeyframe]:
|
@classmethod
|
||||||
|
def convert_to_latent_keyframes(cls, latent_indeces: str, latent_count: int) -> set[LatentKeyframe]:
|
||||||
if not latent_indeces:
|
if not latent_indeces:
|
||||||
return set()
|
return set()
|
||||||
int_latent_indeces = [i for i in range(0, latent_count)]
|
int_latent_indeces = [i for i in range(0, latent_count)]
|
||||||
@@ -304,8 +287,8 @@ class LatentKeyframeGroupNode:
|
|||||||
if ':' in g:
|
if ':' in g:
|
||||||
index_range = g.split(":", 1)
|
index_range = g.split(":", 1)
|
||||||
index_range = [r.strip() for r in index_range]
|
index_range = [r.strip() for r in index_range]
|
||||||
start_index = self.convert_to_index_int(index_range[0], latent_count=latent_count, is_range=True, allow_negative=allow_negative)
|
start_index = cls.convert_to_index_int(index_range[0], latent_count=latent_count, is_range=True, allow_negative=allow_negative)
|
||||||
end_index = self.convert_to_index_int(index_range[1], latent_count=latent_count, is_range=True, allow_negative=allow_negative)
|
end_index = cls.convert_to_index_int(index_range[1], latent_count=latent_count, is_range=True, allow_negative=allow_negative)
|
||||||
# if latents were passed in, base indeces on known latent count
|
# if latents were passed in, base indeces on known latent count
|
||||||
if len(int_latent_indeces) > 0:
|
if len(int_latent_indeces) > 0:
|
||||||
for i in int_latent_indeces[start_index:end_index]:
|
for i in int_latent_indeces[start_index:end_index]:
|
||||||
@@ -316,14 +299,16 @@ class LatentKeyframeGroupNode:
|
|||||||
chosen_indeces.add(LatentKeyframe(i, strength))
|
chosen_indeces.add(LatentKeyframe(i, strength))
|
||||||
# parse individual indeces
|
# parse individual indeces
|
||||||
else:
|
else:
|
||||||
chosen_indeces.add(LatentKeyframe(self.convert_to_index_int(g, latent_count=latent_count, allow_negative=allow_negative), strength))
|
chosen_indeces.add(LatentKeyframe(cls.convert_to_index_int(g, latent_count=latent_count, allow_negative=allow_negative), strength))
|
||||||
return chosen_indeces
|
return chosen_indeces
|
||||||
|
|
||||||
def load_keyframes(self,
|
@classmethod
|
||||||
|
def execute(cls,
|
||||||
index_strengths: str,
|
index_strengths: str,
|
||||||
prev_latent_kf: LatentKeyframeGroup=None,
|
prev_latent_kf: LatentKeyframeGroup=None,
|
||||||
prev_latent_keyframe: LatentKeyframeGroup=None, # old name
|
prev_latent_keyframe: LatentKeyframeGroup=None, # old name
|
||||||
latent_image_opt=None,
|
latent_optional=None,
|
||||||
|
latent_image_opt=None, # old name
|
||||||
print_keyframes=False):
|
print_keyframes=False):
|
||||||
prev_latent_keyframe = prev_latent_keyframe if prev_latent_keyframe else prev_latent_kf
|
prev_latent_keyframe = prev_latent_keyframe if prev_latent_keyframe else prev_latent_kf
|
||||||
if not prev_latent_keyframe:
|
if not prev_latent_keyframe:
|
||||||
@@ -332,10 +317,11 @@ class LatentKeyframeGroupNode:
|
|||||||
prev_latent_keyframe = prev_latent_keyframe.clone()
|
prev_latent_keyframe = prev_latent_keyframe.clone()
|
||||||
curr_latent_keyframe = LatentKeyframeGroup()
|
curr_latent_keyframe = LatentKeyframeGroup()
|
||||||
|
|
||||||
|
latent_image_opt = latent_image_opt if latent_image_opt is not None else latent_optional
|
||||||
latent_count = -1
|
latent_count = -1
|
||||||
if latent_image_opt:
|
if latent_image_opt:
|
||||||
latent_count = latent_image_opt['samples'].size()[0]
|
latent_count = latent_image_opt['samples'].size()[0]
|
||||||
latent_keyframes = self.convert_to_latent_keyframes(index_strengths, latent_count=latent_count)
|
latent_keyframes = cls.convert_to_latent_keyframes(index_strengths, latent_count=latent_count)
|
||||||
|
|
||||||
for latent_keyframe in latent_keyframes:
|
for latent_keyframe in latent_keyframes:
|
||||||
curr_latent_keyframe.add(latent_keyframe)
|
curr_latent_keyframe.add(latent_keyframe)
|
||||||
@@ -348,35 +334,32 @@ class LatentKeyframeGroupNode:
|
|||||||
for latent_keyframe in prev_latent_keyframe.keyframes:
|
for latent_keyframe in prev_latent_keyframe.keyframes:
|
||||||
curr_latent_keyframe.add(latent_keyframe)
|
curr_latent_keyframe.add(latent_keyframe)
|
||||||
|
|
||||||
return (curr_latent_keyframe,)
|
return io.NodeOutput(curr_latent_keyframe,)
|
||||||
|
|
||||||
|
|
||||||
class LatentKeyframeInterpolationNode:
|
class LatentKeyframeInterpolationNode(io.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='LatentKeyframeTiming',
|
||||||
"batch_index_from": ("INT", {"default": 0, "min": BIGMIN, "max": BIGMAX, "step": 1}),
|
display_name='Latent Keyframe Interp. 🛂🅐🅒🅝',
|
||||||
"batch_index_to_excl": ("INT", {"default": 0, "min": BIGMIN, "max": BIGMAX, "step": 1}),
|
category='Adv-ControlNet 🛂🅐🅒🅝/keyframes',
|
||||||
"strength_from": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"strength_to": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Int.Input('batch_index_from', default=0, max=9007199254740991, min=-9007199254740991, step=1),
|
||||||
"interpolation": (SI._LIST, ),
|
io.Int.Input('batch_index_to_excl', default=0, max=9007199254740991, min=-9007199254740991, step=1),
|
||||||
},
|
io.Float.Input('strength_from', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('strength_to', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"prev_latent_kf": ("LATENT_KEYFRAME", ),
|
io.Combo.Input('interpolation', options=['linear', 'ease-in', 'ease-out', 'ease-in-out']),
|
||||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
io.Custom('LATENT_KEYFRAME').Input('prev_latent_kf', optional=True),
|
||||||
},
|
io.Boolean.Input('print_keyframes', optional=True, default=False)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('LATENT_KEYFRAME').Output('LATENT_KF', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_NAMES = ("LATENT_KF", )
|
@classmethod
|
||||||
RETURN_TYPES = ("LATENT_KEYFRAME", )
|
def execute(cls,
|
||||||
FUNCTION = "load_keyframe"
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
|
||||||
|
|
||||||
def load_keyframe(self,
|
|
||||||
batch_index_from: int,
|
batch_index_from: int,
|
||||||
strength_from: float,
|
strength_from: float,
|
||||||
batch_index_to_excl: int,
|
batch_index_to_excl: int,
|
||||||
@@ -425,31 +408,27 @@ class LatentKeyframeInterpolationNode:
|
|||||||
for latent_keyframe in prev_latent_keyframe.keyframes:
|
for latent_keyframe in prev_latent_keyframe.keyframes:
|
||||||
curr_latent_keyframe.add(latent_keyframe)
|
curr_latent_keyframe.add(latent_keyframe)
|
||||||
|
|
||||||
return (curr_latent_keyframe,)
|
return io.NodeOutput(curr_latent_keyframe,)
|
||||||
|
|
||||||
|
class LatentKeyframeBatchedGroupNode(io.ComfyNode):
|
||||||
class LatentKeyframeBatchedGroupNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='LatentKeyframeBatchedGroup',
|
||||||
"float_strengths": ("FLOAT", {"default": -1, "min": -1, "step": 0.001, "forceInput": True}),
|
display_name='Latent Keyframe From List 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/keyframes',
|
||||||
"optional": {
|
inputs=[
|
||||||
"prev_latent_kf": ("LATENT_KEYFRAME", ),
|
io.Float.Input('float_strengths', default=-1, force_input=True, min=-1, step=0.001),
|
||||||
"print_keyframes": ("BOOLEAN", {"default": False}),
|
io.Custom('LATENT_KEYFRAME').Input('prev_latent_kf', optional=True),
|
||||||
},
|
io.Boolean.Input('print_keyframes', optional=True, default=False)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('LATENT_KEYFRAME').Output('LATENT_KF', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_NAMES = ("LATENT_KF", )
|
@classmethod
|
||||||
RETURN_TYPES = ("LATENT_KEYFRAME", )
|
def execute(cls, float_strengths: Union[float, list[float]],
|
||||||
FUNCTION = "load_keyframe"
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/keyframes"
|
|
||||||
|
|
||||||
def load_keyframe(self, float_strengths: Union[float, list[float]],
|
|
||||||
prev_latent_kf: LatentKeyframeGroup=None,
|
prev_latent_kf: LatentKeyframeGroup=None,
|
||||||
prev_latent_keyframe: LatentKeyframeGroup=None, # old name
|
prev_latent_keyframe: LatentKeyframeGroup=None, # old name
|
||||||
print_keyframes=False):
|
print_keyframes=False):
|
||||||
@@ -479,4 +458,4 @@ class LatentKeyframeBatchedGroupNode:
|
|||||||
for latent_keyframe in prev_latent_keyframe.keyframes:
|
for latent_keyframe in prev_latent_keyframe.keyframes:
|
||||||
curr_latent_keyframe.add(latent_keyframe)
|
curr_latent_keyframe.add(latent_keyframe)
|
||||||
|
|
||||||
return (curr_latent_keyframe,)
|
return io.NodeOutput(curr_latent_keyframe,)
|
||||||
|
|||||||
+111
-123
@@ -1,129 +1,120 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
from torch import Tensor
|
from torch import Tensor
|
||||||
|
|
||||||
import folder_paths
|
import folder_paths
|
||||||
from comfy.model_patcher import ModelPatcher
|
|
||||||
|
|
||||||
from .control import load_controlnet, convert_to_advanced, is_advanced_controlnet, is_sd3_advanced_controlnet
|
from .control import load_controlnet, convert_to_advanced, is_advanced_controlnet, is_sd3_advanced_controlnet
|
||||||
from .control_lllite import load_anima_lllite
|
from .control_lllite import load_anima_lllite
|
||||||
from .utils import ControlWeights, LatentKeyframeGroup, TimestepKeyframeGroup, AbstractPreprocWrapper, BIGMAX
|
from .utils import ControlWeights, LatentKeyframeGroup, TimestepKeyframeGroup, AbstractPreprocWrapper
|
||||||
|
|
||||||
from .logger import logger
|
class ControlNetLoaderAdvanced(io.ComfyNode):
|
||||||
|
|
||||||
|
|
||||||
class ControlNetLoaderAdvanced:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ControlNetLoaderAdvanced',
|
||||||
"cnet": (folder_paths.get_filename_list("controlnet"), ),
|
display_name='Load Advanced ControlNet Model 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝',
|
||||||
"optional": {
|
inputs=[
|
||||||
"_tk_opt": ("TIMESTEP_KEYFRAME", ),
|
io.Combo.Input('cnet', options=folder_paths.get_filename_list("controlnet")),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Input('_tk_opt', optional=True)
|
||||||
}
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
@classmethod
|
||||||
FUNCTION = "load_controlnet"
|
def execute(cls, cnet,
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝"
|
|
||||||
|
|
||||||
def load_controlnet(self, cnet,
|
|
||||||
_tk_opt: TimestepKeyframeGroup=None,
|
_tk_opt: TimestepKeyframeGroup=None,
|
||||||
):
|
):
|
||||||
controlnet_path = folder_paths.get_full_path("controlnet", cnet)
|
controlnet_path = folder_paths.get_full_path("controlnet", cnet)
|
||||||
controlnet = load_controlnet(controlnet_path, _tk_opt)
|
controlnet = load_controlnet(controlnet_path, _tk_opt)
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|
||||||
|
|
||||||
class DiffControlNetLoaderAdvanced:
|
class DiffControlNetLoaderAdvanced(io.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_DiffControlNetLoaderAdvanced',
|
||||||
"model": ("MODEL",),
|
display_name='Load Advanced ControlNet Model (diff) 🛂🅐🅒🅝',
|
||||||
"cnet": (folder_paths.get_filename_list("controlnet"), )
|
category='Adv-ControlNet 🛂🅐🅒🅝',
|
||||||
},
|
inputs=[
|
||||||
"optional": {
|
io.Model.Input('model'),
|
||||||
"_tk_opt": ("TIMESTEP_KEYFRAME", ),
|
io.Combo.Input('cnet', options=folder_paths.get_filename_list("controlnet")),
|
||||||
},
|
io.Custom('TIMESTEP_KEYFRAME').Input('_tk_opt', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
|
||||||
FUNCTION = "load_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝"
|
@classmethod
|
||||||
|
def execute(cls, cnet, model,
|
||||||
def load_controlnet(self, cnet, model,
|
|
||||||
_tk_opt: TimestepKeyframeGroup=None,
|
_tk_opt: TimestepKeyframeGroup=None,
|
||||||
):
|
):
|
||||||
controlnet_path = folder_paths.get_full_path("controlnet", cnet)
|
controlnet_path = folder_paths.get_full_path("controlnet", cnet)
|
||||||
controlnet = load_controlnet(controlnet_path, _tk_opt, model)
|
controlnet = load_controlnet(controlnet_path, _tk_opt, model)
|
||||||
if is_advanced_controlnet(controlnet):
|
if is_advanced_controlnet(controlnet):
|
||||||
controlnet.verify_all_weights()
|
controlnet.verify_all_weights()
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|
||||||
|
class AnimaLLLiteLoaderAdvanced(io.ComfyNode):
|
||||||
class AnimaLLLiteLoaderAdvanced:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_AnimaLLLiteLoaderAdvanced',
|
||||||
"model_patch": (folder_paths.get_filename_list("model_patches"), ),
|
display_name='Load Anima LLLite Model 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/loaders',
|
||||||
"optional": {
|
inputs=[
|
||||||
"timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Combo.Input('model_patch', options=folder_paths.get_filename_list("model_patches")),
|
||||||
},
|
io.Custom('TIMESTEP_KEYFRAME').Input('timestep_kf', optional=True)
|
||||||
}
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
@classmethod
|
||||||
FUNCTION = "load_controlnet"
|
def execute(cls, model_patch, timestep_kf: TimestepKeyframeGroup=None):
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/loaders"
|
|
||||||
|
|
||||||
def load_controlnet(self, model_patch, timestep_kf: TimestepKeyframeGroup=None):
|
|
||||||
model_patch_path = folder_paths.get_full_path_or_raise("model_patches", model_patch)
|
model_patch_path = folder_paths.get_full_path_or_raise("model_patches", model_patch)
|
||||||
return (load_anima_lllite(model_patch_path, timestep_keyframe=timestep_kf),)
|
return io.NodeOutput(load_anima_lllite(model_patch_path, timestep_keyframe=timestep_kf),)
|
||||||
|
|
||||||
|
class AdvancedControlNetApply(io.ComfyNode):
|
||||||
class AdvancedControlNetApply:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_AdvancedControlNetApply_v2',
|
||||||
"positive": ("CONDITIONING", ),
|
display_name='Apply Advanced ControlNet 🛂🅐🅒🅝',
|
||||||
"negative": ("CONDITIONING", ),
|
category='Adv-ControlNet 🛂🅐🅒🅝',
|
||||||
"control_net": ("CONTROL_NET", ),
|
inputs=[
|
||||||
"image": ("IMAGE", ),
|
io.Conditioning.Input('positive'),
|
||||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
io.Conditioning.Input('negative'),
|
||||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
io.ControlNet.Input('control_net'),
|
||||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001})
|
io.Image.Input('image'),
|
||||||
},
|
io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||||
"optional": {
|
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
"mask_optional": ("MASK", ),
|
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||||
"timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Mask.Input('mask_optional', optional=True),
|
||||||
"latent_kf_override": ("LATENT_KEYFRAME", ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('timestep_kf', optional=True),
|
||||||
"weights_override": ("CONTROL_NET_WEIGHTS", ),
|
io.Custom('LATENT_KEYFRAME').Input('latent_kf_override', optional=True),
|
||||||
"vae_optional": ("VAE",),
|
io.Custom('CONTROL_NET_WEIGHTS').Input('weights_override', optional=True),
|
||||||
},
|
io.Vae.Input('vae_optional', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Conditioning.Output('positive', is_output_list=False),
|
||||||
}
|
io.Conditioning.Output('negative', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONDITIONING","CONDITIONING",)
|
@classmethod
|
||||||
RETURN_NAMES = ("positive", "negative")
|
def execute(cls, positive, negative, control_net, image, strength, start_percent, end_percent,
|
||||||
FUNCTION = "apply_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝"
|
|
||||||
|
|
||||||
def apply_controlnet(self, positive, negative, control_net, image, strength, start_percent, end_percent,
|
|
||||||
mask_optional: Tensor=None, vae_optional=None,
|
mask_optional: Tensor=None, vae_optional=None,
|
||||||
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override: LatentKeyframeGroup=None,
|
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override: LatentKeyframeGroup=None,
|
||||||
weights_override: ControlWeights=None, control_apply_to_uncond=False):
|
weights_override: ControlWeights=None, control_apply_to_uncond=False):
|
||||||
if strength == 0:
|
if strength == 0:
|
||||||
return (positive, negative)
|
return io.NodeOutput(positive, negative)
|
||||||
|
|
||||||
control_hint = image.movedim(-1,1)
|
control_hint = image.movedim(-1,1)
|
||||||
cnets = {}
|
cnets = {}
|
||||||
@@ -189,46 +180,43 @@ class AdvancedControlNetApply:
|
|||||||
n = [t[0], d]
|
n = [t[0], d]
|
||||||
c.append(n)
|
c.append(n)
|
||||||
out.append(c)
|
out.append(c)
|
||||||
return (out[0], out[1])
|
return io.NodeOutput(out[0], out[1])
|
||||||
|
|
||||||
|
|
||||||
class AdvancedControlNetApplySingle:
|
class AdvancedControlNetApplySingle(io.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_AdvancedControlNetApplySingle_v2',
|
||||||
"conditioning": ("CONDITIONING", ),
|
display_name='Apply Advanced ControlNet(1) 🛂🅐🅒🅝',
|
||||||
"control_net": ("CONTROL_NET", ),
|
category='Adv-ControlNet 🛂🅐🅒🅝',
|
||||||
"image": ("IMAGE", ),
|
inputs=[
|
||||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}),
|
io.Conditioning.Input('conditioning'),
|
||||||
"start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}),
|
io.ControlNet.Input('control_net'),
|
||||||
"end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001})
|
io.Image.Input('image'),
|
||||||
},
|
io.Float.Input('strength', default=1.0, max=10.0, min=0.0, step=0.01),
|
||||||
"optional": {
|
io.Float.Input('start_percent', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
"mask_optional": ("MASK", ),
|
io.Float.Input('end_percent', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||||
"timestep_kf": ("TIMESTEP_KEYFRAME", ),
|
io.Mask.Input('mask_optional', optional=True),
|
||||||
"latent_kf_override": ("LATENT_KEYFRAME", ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('timestep_kf', optional=True),
|
||||||
"weights_override": ("CONTROL_NET_WEIGHTS", ),
|
io.Custom('LATENT_KEYFRAME').Input('latent_kf_override', optional=True),
|
||||||
"vae_optional": ("VAE",),
|
io.Custom('CONTROL_NET_WEIGHTS').Input('weights_override', optional=True),
|
||||||
},
|
io.Vae.Input('vae_optional', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Conditioning.Output('CONDITIONING', is_output_list=False),
|
||||||
}
|
io.Model.Output('model_opt', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONDITIONING","MODEL",)
|
@classmethod
|
||||||
RETURN_NAMES = ("CONDITIONING", "model_opt")
|
def execute(cls, conditioning, control_net, image, strength, start_percent, end_percent,
|
||||||
FUNCTION = "apply_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝"
|
|
||||||
|
|
||||||
def apply_controlnet(self, conditioning, control_net, image, strength, start_percent, end_percent,
|
|
||||||
mask_optional: Tensor=None, vae_optional=None,
|
mask_optional: Tensor=None, vae_optional=None,
|
||||||
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override: LatentKeyframeGroup=None,
|
timestep_kf: TimestepKeyframeGroup=None, latent_kf_override: LatentKeyframeGroup=None,
|
||||||
weights_override: ControlWeights=None):
|
weights_override: ControlWeights=None):
|
||||||
values = AdvancedControlNetApply.apply_controlnet(self, positive=conditioning, negative=None, control_net=control_net, image=image,
|
values = AdvancedControlNetApply.execute(positive=conditioning, negative=None, control_net=control_net, image=image,
|
||||||
strength=strength, start_percent=start_percent, end_percent=end_percent,
|
strength=strength, start_percent=start_percent, end_percent=end_percent,
|
||||||
mask_optional=mask_optional, vae_optional=vae_optional,
|
mask_optional=mask_optional, vae_optional=vae_optional,
|
||||||
timestep_kf=timestep_kf, latent_kf_override=latent_kf_override, weights_override=weights_override,
|
timestep_kf=timestep_kf, latent_kf_override=latent_kf_override, weights_override=weights_override,
|
||||||
control_apply_to_uncond=True)
|
control_apply_to_uncond=True)
|
||||||
return (values[0],)
|
return io.NodeOutput(values.args[0], None)
|
||||||
|
|||||||
@@ -1,81 +1,82 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
from torch import Tensor
|
from torch import Tensor
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import folder_paths
|
import folder_paths
|
||||||
|
|
||||||
from .control_plusplus import load_controlnetplusplus, PlusPlusType, PlusPlusInput, PlusPlusInputGroup, PlusPlusImageWrapper
|
from .control_plusplus import load_controlnetplusplus, PlusPlusInput, PlusPlusInputGroup, PlusPlusImageWrapper
|
||||||
from .utils import BIGMAX
|
|
||||||
|
|
||||||
|
class PlusPlusLoaderAdvanced(io.ComfyNode):
|
||||||
class PlusPlusLoaderAdvanced:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ControlNet++LoaderAdvanced',
|
||||||
"plus_input": ("PLUS_INPUT", ),
|
display_name='Load ControlNet++ Model (Multi) 🛂🅐🅒🅝',
|
||||||
"name": (folder_paths.get_filename_list("controlnet"), ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/ControlNet++',
|
||||||
}
|
inputs=[
|
||||||
}
|
io.Custom('PLUS_INPUT').Input('plus_input'),
|
||||||
|
io.Combo.Input('name', options=folder_paths.get_filename_list("controlnet"))
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False),
|
||||||
|
io.Image.Output('IMAGE', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", "IMAGE",)
|
|
||||||
FUNCTION = "load_controlnet_plusplus"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/ControlNet++"
|
@classmethod
|
||||||
|
def execute(cls, plus_input: PlusPlusInputGroup, name: str):
|
||||||
def load_controlnet_plusplus(self, plus_input: PlusPlusInputGroup, name: str):
|
|
||||||
controlnet_path = folder_paths.get_full_path("controlnet", name)
|
controlnet_path = folder_paths.get_full_path("controlnet", name)
|
||||||
controlnet = load_controlnetplusplus(controlnet_path)
|
controlnet = load_controlnetplusplus(controlnet_path)
|
||||||
controlnet.verify_control_type(name, plus_input)
|
controlnet.verify_control_type(name, plus_input)
|
||||||
controlnet.allow_condhint_latents = True
|
controlnet.allow_condhint_latents = True
|
||||||
return (controlnet, PlusPlusImageWrapper(plus_input),)
|
return io.NodeOutput(controlnet, PlusPlusImageWrapper(plus_input),)
|
||||||
|
|
||||||
|
class PlusPlusLoaderSingle(io.ComfyNode):
|
||||||
class PlusPlusLoaderSingle:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ControlNet++LoaderSingle',
|
||||||
"name": (folder_paths.get_filename_list("controlnet"), ),
|
display_name='Load ControlNet++ Model (Single) 🛂🅐🅒🅝',
|
||||||
"control_type": (PlusPlusType._LIST_WITH_NONE, {"default": PlusPlusType.NONE}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/ControlNet++',
|
||||||
}
|
inputs=[
|
||||||
}
|
io.Combo.Input('name', options=folder_paths.get_filename_list("controlnet")),
|
||||||
|
io.Combo.Input('control_type', options=['openpose', 'depth', 'hed/pidi/scribble/ted', 'canny/lineart/mlsd', 'normal', 'segment', 'tile', 'inpaint/outpaint', 'none'], default='none')
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET",)
|
|
||||||
FUNCTION = "load_controlnet_plusplus"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/ControlNet++"
|
@classmethod
|
||||||
|
def execute(cls, name: str, control_type: str):
|
||||||
def load_controlnet_plusplus(self, name: str, control_type: str):
|
|
||||||
controlnet_path = folder_paths.get_full_path("controlnet", name)
|
controlnet_path = folder_paths.get_full_path("controlnet", name)
|
||||||
controlnet = load_controlnetplusplus(controlnet_path)
|
controlnet = load_controlnetplusplus(controlnet_path)
|
||||||
controlnet.single_control_type = control_type
|
controlnet.single_control_type = control_type
|
||||||
controlnet.verify_control_type(name)
|
controlnet.verify_control_type(name)
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|
||||||
|
class PlusPlusInputNode(io.ComfyNode):
|
||||||
class PlusPlusInputNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ControlNet++InputNode',
|
||||||
"image": ("IMAGE",),
|
display_name='ControlNet++ Input 🛂🅐🅒🅝',
|
||||||
"control_type": (PlusPlusType._LIST,),
|
category='Adv-ControlNet 🛂🅐🅒🅝/ControlNet++',
|
||||||
},
|
inputs=[
|
||||||
"optional": {
|
io.Image.Input('image'),
|
||||||
"prev_plus_input": ("PLUS_INPUT",),
|
io.Combo.Input('control_type', options=['openpose', 'depth', 'hed/pidi/scribble/ted', 'canny/lineart/mlsd', 'normal', 'segment', 'tile', 'inpaint/outpaint']),
|
||||||
#"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": BIGMAX, "step": 0.01}),
|
io.Custom('PLUS_INPUT').Input('prev_plus_input', optional=True)
|
||||||
},
|
],
|
||||||
"hidden": {
|
outputs=[
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
io.Custom('PLUS_INPUT').Output('PLUS_INPUT', is_output_list=False)
|
||||||
}
|
]
|
||||||
}
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("PLUS_INPUT", )
|
|
||||||
FUNCTION = "wrap_images"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/ControlNet++"
|
@classmethod
|
||||||
|
def execute(cls, image: Tensor, control_type: str, strength=1.0, prev_plus_input: PlusPlusInputGroup=None):
|
||||||
def wrap_images(self, image: Tensor, control_type: str, strength=1.0, prev_plus_input: PlusPlusInputGroup=None):
|
|
||||||
if prev_plus_input is None:
|
if prev_plus_input is None:
|
||||||
prev_plus_input = PlusPlusInputGroup()
|
prev_plus_input = PlusPlusInputGroup()
|
||||||
prev_plus_input = prev_plus_input.clone()
|
prev_plus_input = prev_plus_input.clone()
|
||||||
@@ -85,4 +86,4 @@ class PlusPlusInputNode:
|
|||||||
pp_input = PlusPlusInput(image, control_type, strength)
|
pp_input = PlusPlusInput(image, control_type, strength)
|
||||||
prev_plus_input.add(pp_input)
|
prev_plus_input.add(pp_input)
|
||||||
|
|
||||||
return (prev_plus_input,)
|
return io.NodeOutput(prev_plus_input,)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
from torch import Tensor
|
from torch import Tensor
|
||||||
|
|
||||||
from nodes import VAEEncode
|
from nodes import VAEEncode
|
||||||
@@ -6,77 +7,81 @@ from comfy.sd import VAE
|
|||||||
|
|
||||||
from .control_reference import ReferenceAdvanced, ReferenceOptions, ReferenceType, ReferencePreprocWrapper
|
from .control_reference import ReferenceAdvanced, ReferenceOptions, ReferenceType, ReferencePreprocWrapper
|
||||||
|
|
||||||
|
|
||||||
# node for ReferenceCN
|
# node for ReferenceCN
|
||||||
class ReferenceControlNetNode:
|
class ReferenceControlNetNode(io.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ReferenceControlNet',
|
||||||
"reference_type": (ReferenceType._LIST,),
|
display_name='Reference ControlNet 🛂🅐🅒🅝',
|
||||||
"style_fidelity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
category='Adv-ControlNet 🛂🅐🅒🅝/Reference',
|
||||||
"ref_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
inputs=[
|
||||||
},
|
io.Combo.Input('reference_type', options=['reference_attn', 'reference_adain', 'reference_attn+adain']),
|
||||||
}
|
io.Float.Input('style_fidelity', default=0.5, max=1.0, min=0.0, step=0.01),
|
||||||
|
io.Float.Input('ref_weight', default=1.0, max=1.0, min=0.0, step=0.01)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
|
||||||
FUNCTION = "load_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/Reference"
|
@classmethod
|
||||||
|
def execute(cls, reference_type: str, style_fidelity: float, ref_weight: float):
|
||||||
def load_controlnet(self, reference_type: str, style_fidelity: float, ref_weight: float):
|
|
||||||
ref_opts = ReferenceOptions.create_combo(reference_type=reference_type, style_fidelity=style_fidelity, ref_weight=ref_weight)
|
ref_opts = ReferenceOptions.create_combo(reference_type=reference_type, style_fidelity=style_fidelity, ref_weight=ref_weight)
|
||||||
controlnet = ReferenceAdvanced(ref_opts=ref_opts, timestep_keyframes=None)
|
controlnet = ReferenceAdvanced(ref_opts=ref_opts, timestep_keyframes=None)
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|
||||||
|
class ReferenceControlFinetune(io.ComfyNode):
|
||||||
class ReferenceControlFinetune:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ReferenceControlNetFinetune',
|
||||||
"attn_style_fidelity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
display_name='Reference ControlNet (Finetune) 🛂🅐🅒🅝',
|
||||||
"attn_ref_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
category='Adv-ControlNet 🛂🅐🅒🅝/Reference',
|
||||||
"attn_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
inputs=[
|
||||||
"adain_style_fidelity": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
io.Float.Input('attn_style_fidelity', default=0.5, max=1.0, min=0.0, step=0.01),
|
||||||
"adain_ref_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
io.Float.Input('attn_ref_weight', default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
"adain_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
io.Float.Input('attn_strength', default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Float.Input('adain_style_fidelity', default=0.5, max=1.0, min=0.0, step=0.01),
|
||||||
}
|
io.Float.Input('adain_ref_weight', default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
|
io.Float.Input('adain_strength', default=1.0, max=1.0, min=0.0, step=0.01)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
|
||||||
FUNCTION = "load_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/Reference"
|
@classmethod
|
||||||
|
def execute(cls,
|
||||||
def load_controlnet(self,
|
|
||||||
attn_style_fidelity: float, attn_ref_weight: float, attn_strength: float,
|
attn_style_fidelity: float, attn_ref_weight: float, attn_strength: float,
|
||||||
adain_style_fidelity: float, adain_ref_weight: float, adain_strength: float):
|
adain_style_fidelity: float, adain_ref_weight: float, adain_strength: float):
|
||||||
ref_opts = ReferenceOptions(reference_type=ReferenceType.ATTN_ADAIN,
|
ref_opts = ReferenceOptions(reference_type=ReferenceType.ATTN_ADAIN,
|
||||||
attn_style_fidelity=attn_style_fidelity, attn_ref_weight=attn_ref_weight, attn_strength=attn_strength,
|
attn_style_fidelity=attn_style_fidelity, attn_ref_weight=attn_ref_weight, attn_strength=attn_strength,
|
||||||
adain_style_fidelity=adain_style_fidelity, adain_ref_weight=adain_ref_weight, adain_strength=adain_strength)
|
adain_style_fidelity=adain_style_fidelity, adain_ref_weight=adain_ref_weight, adain_strength=adain_strength)
|
||||||
controlnet = ReferenceAdvanced(ref_opts=ref_opts, timestep_keyframes=None)
|
controlnet = ReferenceAdvanced(ref_opts=ref_opts, timestep_keyframes=None)
|
||||||
return (controlnet,)
|
return io.NodeOutput(controlnet,)
|
||||||
|
|
||||||
|
class ReferencePreprocessorNode(io.ComfyNode):
|
||||||
class ReferencePreprocessorNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ReferencePreprocessor',
|
||||||
"image": ("IMAGE", ),
|
display_name='Reference Preproccessor 🛂🅐🅒🅝',
|
||||||
"vae": ("VAE", ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/Reference/preprocess',
|
||||||
"latent_size": ("LATENT", ),
|
inputs=[
|
||||||
}
|
io.Image.Input('image'),
|
||||||
}
|
io.Vae.Input('vae'),
|
||||||
|
io.Latent.Input('latent_size')
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.Image.Output('proc_IMAGE', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE",)
|
@classmethod
|
||||||
RETURN_NAMES = ("proc_IMAGE",)
|
def execute(cls, vae: VAE, image: Tensor, latent_size: Tensor):
|
||||||
FUNCTION = "preprocess_images"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/Reference/preprocess"
|
|
||||||
|
|
||||||
def preprocess_images(self, vae: VAE, image: Tensor, latent_size: Tensor):
|
|
||||||
# first, resize image to match latents
|
# first, resize image to match latents
|
||||||
image = image.movedim(-1,1)
|
image = image.movedim(-1,1)
|
||||||
image = comfy.utils.common_upscale(image, latent_size["samples"].shape[3] * 8, latent_size["samples"].shape[2] * 8, 'nearest-exact', "center")
|
image = comfy.utils.common_upscale(image, latent_size["samples"].shape[3] * 8, latent_size["samples"].shape[2] * 8, 'nearest-exact', "center")
|
||||||
@@ -87,4 +92,4 @@ class ReferencePreprocessorNode:
|
|||||||
except Exception:
|
except Exception:
|
||||||
image = VAEEncode.vae_encode_crop_pixels(image)
|
image = VAEEncode.vae_encode_crop_pixels(image)
|
||||||
encoded = vae.encode(image[:,:,:,:3])
|
encoded = vae.encode(image[:,:,:,:3])
|
||||||
return (ReferencePreprocWrapper(condhint=encoded),)
|
return io.NodeOutput(ReferencePreprocWrapper(condhint=encoded),)
|
||||||
|
|||||||
+118
-118
@@ -1,3 +1,4 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
from torch import Tensor
|
from torch import Tensor
|
||||||
|
|
||||||
import folder_paths
|
import folder_paths
|
||||||
@@ -7,68 +8,68 @@ from comfy.sd import VAE
|
|||||||
|
|
||||||
from .utils import TimestepKeyframeGroup
|
from .utils import TimestepKeyframeGroup
|
||||||
from .control_sparsectrl import SparseMethod, SparseIndexMethod, SparseSettings, SparseSpreadMethod, PreprocSparseRGBWrapper, SparseConst, SparseContextAware, get_idx_list_from_str
|
from .control_sparsectrl import SparseMethod, SparseIndexMethod, SparseSettings, SparseSpreadMethod, PreprocSparseRGBWrapper, SparseConst, SparseContextAware, get_idx_list_from_str
|
||||||
from .control import load_sparsectrl, load_controlnet, ControlNetAdvanced, SparseCtrlAdvanced
|
from .control import load_sparsectrl, load_controlnet, ControlNetAdvanced
|
||||||
|
|
||||||
|
|
||||||
# node for SparseCtrl loading
|
# node for SparseCtrl loading
|
||||||
class SparseCtrlLoaderAdvanced:
|
class SparseCtrlLoaderAdvanced(io.ComfyNode):
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_SparseCtrlLoaderAdvanced',
|
||||||
"sparsectrl_name": (folder_paths.get_filename_list("controlnet"), ),
|
display_name='Load SparseCtrl Model 🛂🅐🅒🅝',
|
||||||
"use_motion": ("BOOLEAN", {"default": True}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl',
|
||||||
"motion_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Combo.Input('sparsectrl_name', options=folder_paths.get_filename_list("controlnet")),
|
||||||
},
|
io.Boolean.Input('use_motion', default=True),
|
||||||
"optional": {
|
io.Float.Input('motion_strength', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"sparse_method": ("SPARSE_METHOD", ),
|
io.Float.Input('motion_scale', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"tk_optional": ("TIMESTEP_KEYFRAME", ),
|
io.Custom('SPARSE_METHOD').Input('sparse_method', optional=True),
|
||||||
"context_aware": (SparseContextAware.LIST, ),
|
io.Custom('TIMESTEP_KEYFRAME').Input('tk_optional', optional=True),
|
||||||
"sparse_hint_mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Combo.Input('context_aware', optional=True, options=['nearest_hint', 'off']),
|
||||||
"sparse_nonhint_mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('sparse_hint_mult', optional=True, default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"sparse_mask_mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('sparse_nonhint_mult', optional=True, default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
}
|
io.Float.Input('sparse_mask_mult', optional=True, default=1.0, max=10.0, min=0.0, step=0.001)
|
||||||
}
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
|
||||||
FUNCTION = "load_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl"
|
@classmethod
|
||||||
|
def execute(cls, sparsectrl_name: str, use_motion: bool, motion_strength: float, motion_scale: float, sparse_method: SparseMethod=SparseSpreadMethod(), tk_optional: TimestepKeyframeGroup=None,
|
||||||
def load_controlnet(self, sparsectrl_name: str, use_motion: bool, motion_strength: float, motion_scale: float, sparse_method: SparseMethod=SparseSpreadMethod(), tk_optional: TimestepKeyframeGroup=None,
|
|
||||||
context_aware=SparseContextAware.NEAREST_HINT, sparse_hint_mult=1.0, sparse_nonhint_mult=1.0, sparse_mask_mult=1.0):
|
context_aware=SparseContextAware.NEAREST_HINT, sparse_hint_mult=1.0, sparse_nonhint_mult=1.0, sparse_mask_mult=1.0):
|
||||||
sparsectrl_path = folder_paths.get_full_path("controlnet", sparsectrl_name)
|
sparsectrl_path = folder_paths.get_full_path("controlnet", sparsectrl_name)
|
||||||
sparse_settings = SparseSettings(sparse_method=sparse_method, use_motion=use_motion, motion_strength=motion_strength, motion_scale=motion_scale,
|
sparse_settings = SparseSettings(sparse_method=sparse_method, use_motion=use_motion, motion_strength=motion_strength, motion_scale=motion_scale,
|
||||||
context_aware=context_aware,
|
context_aware=context_aware,
|
||||||
sparse_mask_mult=sparse_mask_mult, sparse_hint_mult=sparse_hint_mult, sparse_nonhint_mult=sparse_nonhint_mult)
|
sparse_mask_mult=sparse_mask_mult, sparse_hint_mult=sparse_hint_mult, sparse_nonhint_mult=sparse_nonhint_mult)
|
||||||
sparsectrl = load_sparsectrl(sparsectrl_path, timestep_keyframe=tk_optional, sparse_settings=sparse_settings)
|
sparsectrl = load_sparsectrl(sparsectrl_path, timestep_keyframe=tk_optional, sparse_settings=sparse_settings)
|
||||||
return (sparsectrl,)
|
return io.NodeOutput(sparsectrl,)
|
||||||
|
|
||||||
|
class SparseCtrlMergedLoaderAdvanced(io.ComfyNode):
|
||||||
class SparseCtrlMergedLoaderAdvanced:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_SparseCtrlMergedLoaderAdvanced',
|
||||||
"sparsectrl_name": (folder_paths.get_filename_list("controlnet"), ),
|
display_name='🧪Load Merged SparseCtrl Model 🛂🅐🅒🅝',
|
||||||
"control_net_name": (folder_paths.get_filename_list("controlnet"), ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/experimental',
|
||||||
"use_motion": ("BOOLEAN", {"default": True}, ),
|
inputs=[
|
||||||
"motion_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Combo.Input('sparsectrl_name', options=folder_paths.get_filename_list("controlnet")),
|
||||||
"motion_scale": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Combo.Input('control_net_name', options=folder_paths.get_filename_list("controlnet")),
|
||||||
},
|
io.Boolean.Input('use_motion', default=True),
|
||||||
"optional": {
|
io.Float.Input('motion_strength', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"sparse_method": ("SPARSE_METHOD", ),
|
io.Float.Input('motion_scale', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"tk_optional": ("TIMESTEP_KEYFRAME", ),
|
io.Custom('SPARSE_METHOD').Input('sparse_method', optional=True),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Input('tk_optional', optional=True)
|
||||||
}
|
],
|
||||||
|
outputs=[
|
||||||
|
io.ControlNet.Output('CONTROL_NET', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET", )
|
|
||||||
FUNCTION = "load_controlnet"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/experimental"
|
@classmethod
|
||||||
|
def execute(cls, sparsectrl_name: str, control_net_name: str, use_motion: bool, motion_strength: float, motion_scale: float, sparse_method: SparseMethod=SparseSpreadMethod(), tk_optional: TimestepKeyframeGroup=None):
|
||||||
def load_controlnet(self, sparsectrl_name: str, control_net_name: str, use_motion: bool, motion_strength: float, motion_scale: float, sparse_method: SparseMethod=SparseSpreadMethod(), tk_optional: TimestepKeyframeGroup=None):
|
|
||||||
sparsectrl_path = folder_paths.get_full_path("controlnet", sparsectrl_name)
|
sparsectrl_path = folder_paths.get_full_path("controlnet", sparsectrl_name)
|
||||||
controlnet_path = folder_paths.get_full_path("controlnet", control_net_name)
|
controlnet_path = folder_paths.get_full_path("controlnet", control_net_name)
|
||||||
sparse_settings = SparseSettings(sparse_method=sparse_method, use_motion=use_motion, motion_strength=motion_strength, motion_scale=motion_scale, merged=True)
|
sparse_settings = SparseSettings(sparse_method=sparse_method, use_motion=use_motion, motion_strength=motion_strength, motion_scale=motion_scale, merged=True)
|
||||||
@@ -85,67 +86,68 @@ class SparseCtrlMergedLoaderAdvanced:
|
|||||||
new_state_dict[key] = value
|
new_state_dict[key] = value
|
||||||
# now, reload sparsectrl with real settings
|
# now, reload sparsectrl with real settings
|
||||||
sparsectrl = load_sparsectrl(sparsectrl_path, controlnet_data=new_state_dict, timestep_keyframe=tk_optional, sparse_settings=sparse_settings)
|
sparsectrl = load_sparsectrl(sparsectrl_path, controlnet_data=new_state_dict, timestep_keyframe=tk_optional, sparse_settings=sparse_settings)
|
||||||
return (sparsectrl,)
|
return io.NodeOutput(sparsectrl,)
|
||||||
|
|
||||||
|
class SparseIndexMethodNode(io.ComfyNode):
|
||||||
class SparseIndexMethodNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_SparseCtrlIndexMethodNode',
|
||||||
"indexes": ("STRING", {"default": "0"}),
|
display_name='SparseCtrl Index Method 🛂🅐🅒🅝',
|
||||||
}
|
category='Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl',
|
||||||
}
|
inputs=[
|
||||||
|
io.String.Input('indexes', default='0')
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.Custom('SPARSE_METHOD').Output('SPARSE_METHOD', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("SPARSE_METHOD",)
|
|
||||||
FUNCTION = "get_method"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl"
|
@classmethod
|
||||||
|
def execute(cls, indexes: str):
|
||||||
def get_method(self, indexes: str):
|
|
||||||
idxs = get_idx_list_from_str(indexes)
|
idxs = get_idx_list_from_str(indexes)
|
||||||
return (SparseIndexMethod(idxs),)
|
return io.NodeOutput(SparseIndexMethod(idxs),)
|
||||||
|
|
||||||
|
class SparseSpreadMethodNode(io.ComfyNode):
|
||||||
class SparseSpreadMethodNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_SparseCtrlSpreadMethodNode',
|
||||||
"spread": (SparseSpreadMethod.LIST,),
|
display_name='SparseCtrl Spread Method 🛂🅐🅒🅝',
|
||||||
}
|
category='Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl',
|
||||||
}
|
inputs=[
|
||||||
|
io.Combo.Input('spread', options=['uniform', 'starting', 'ending', 'center'])
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.Custom('SPARSE_METHOD').Output('SPARSE_METHOD', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("SPARSE_METHOD",)
|
|
||||||
FUNCTION = "get_method"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl"
|
|
||||||
|
|
||||||
def get_method(self, spread: str):
|
|
||||||
return (SparseSpreadMethod(spread=spread),)
|
|
||||||
|
|
||||||
|
|
||||||
class RgbSparseCtrlPreprocessor:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def execute(cls, spread: str):
|
||||||
return {
|
return io.NodeOutput(SparseSpreadMethod(spread=spread),)
|
||||||
"required": {
|
|
||||||
"image": ("IMAGE", ),
|
|
||||||
"vae": ("VAE", ),
|
|
||||||
"latent_size": ("LATENT", ),
|
|
||||||
},
|
|
||||||
"hidden": {
|
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE",)
|
class RgbSparseCtrlPreprocessor(io.ComfyNode):
|
||||||
RETURN_NAMES = ("proc_IMAGE",)
|
@classmethod
|
||||||
FUNCTION = "preprocess_images"
|
def define_schema(cls) -> io.Schema:
|
||||||
|
return io.Schema(
|
||||||
|
node_id='ACN_SparseCtrlRGBPreprocessor',
|
||||||
|
display_name='RGB SparseCtrl 🛂🅐🅒🅝',
|
||||||
|
category='Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/preprocess',
|
||||||
|
inputs=[
|
||||||
|
io.Image.Input('image'),
|
||||||
|
io.Vae.Input('vae'),
|
||||||
|
io.Latent.Input('latent_size')
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.Image.Output('proc_IMAGE', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/preprocess"
|
@classmethod
|
||||||
|
def execute(cls, vae: VAE, image: Tensor, latent_size: Tensor):
|
||||||
def preprocess_images(self, vae: VAE, image: Tensor, latent_size: Tensor):
|
|
||||||
# first, resize image to match latents
|
# first, resize image to match latents
|
||||||
image = image.movedim(-1,1)
|
image = image.movedim(-1,1)
|
||||||
image = comfy.utils.common_upscale(image, latent_size["samples"].shape[3] * 8, latent_size["samples"].shape[2] * 8, 'nearest-exact', "center")
|
image = comfy.utils.common_upscale(image, latent_size["samples"].shape[3] * 8, latent_size["samples"].shape[2] * 8, 'nearest-exact', "center")
|
||||||
@@ -156,33 +158,31 @@ class RgbSparseCtrlPreprocessor:
|
|||||||
except Exception:
|
except Exception:
|
||||||
image = VAEEncode.vae_encode_crop_pixels(image)
|
image = VAEEncode.vae_encode_crop_pixels(image)
|
||||||
encoded = vae.encode(image[:,:,:,:3])
|
encoded = vae.encode(image[:,:,:,:3])
|
||||||
return (PreprocSparseRGBWrapper(condhint=encoded),)
|
return io.NodeOutput(PreprocSparseRGBWrapper(condhint=encoded),)
|
||||||
|
|
||||||
|
class SparseWeightExtras(io.ComfyNode):
|
||||||
class SparseWeightExtras:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"optional": {
|
node_id='ACN_SparseCtrlWeightExtras',
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
display_name='SparseCtrl Weight Extras 🛂🅐🅒🅝',
|
||||||
"sparse_hint_mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/extras',
|
||||||
"sparse_nonhint_mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"sparse_mask_mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True),
|
||||||
},
|
io.Float.Input('sparse_hint_mult', optional=True, default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"hidden": {
|
io.Float.Input('sparse_nonhint_mult', optional=True, default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
io.Float.Input('sparse_mask_mult', optional=True, default=1.0, max=10.0, min=0.0, step=0.001)
|
||||||
}
|
],
|
||||||
}
|
outputs=[
|
||||||
|
io.Custom('CN_WEIGHTS_EXTRAS').Output('cn_extras', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CN_WEIGHTS_EXTRAS", )
|
|
||||||
RETURN_NAMES = ("cn_extras", )
|
|
||||||
FUNCTION = "create_weight_extras"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/SparseCtrl/extras"
|
@classmethod
|
||||||
|
def execute(cls, cn_extras: dict[str]={}, sparse_hint_mult=1.0, sparse_nonhint_mult=1.0, sparse_mask_mult=1.0):
|
||||||
def create_weight_extras(self, cn_extras: dict[str]={}, sparse_hint_mult=1.0, sparse_nonhint_mult=1.0, sparse_mask_mult=1.0):
|
|
||||||
cn_extras = cn_extras.copy()
|
cn_extras = cn_extras.copy()
|
||||||
cn_extras[SparseConst.HINT_MULT] = sparse_hint_mult
|
cn_extras[SparseConst.HINT_MULT] = sparse_hint_mult
|
||||||
cn_extras[SparseConst.NONHINT_MULT] = sparse_nonhint_mult
|
cn_extras[SparseConst.NONHINT_MULT] = sparse_nonhint_mult
|
||||||
cn_extras[SparseConst.MASK_MULT] = sparse_mask_mult
|
cn_extras[SparseConst.MASK_MULT] = sparse_mask_mult
|
||||||
return (cn_extras, )
|
return io.NodeOutput(cn_extras, )
|
||||||
|
|||||||
+281
-292
@@ -1,63 +1,56 @@
|
|||||||
|
from comfy_api.latest import io
|
||||||
from torch import Tensor
|
from torch import Tensor
|
||||||
import torch
|
import torch
|
||||||
from .utils import TimestepKeyframe, TimestepKeyframeGroup, ControlWeights, Extras, get_properly_arranged_t2i_weights, linear_conversion
|
from .utils import TimestepKeyframe, TimestepKeyframeGroup, ControlWeights, Extras, get_properly_arranged_t2i_weights, linear_conversion
|
||||||
from .control_lllite import AnimaLLLiteConst
|
from .control_lllite import AnimaLLLiteConst
|
||||||
from .logger import logger
|
|
||||||
|
|
||||||
|
|
||||||
WEIGHTS_RETURN_NAMES = ("CN_WEIGHTS", "TK_SHORTCUT")
|
WEIGHTS_RETURN_NAMES = ("CN_WEIGHTS", "TK_SHORTCUT")
|
||||||
|
|
||||||
|
class DefaultWeights(io.ComfyNode):
|
||||||
class DefaultWeights:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"optional": {
|
node_id='ACN_DefaultUniversalWeights',
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
display_name='Default Weights 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights',
|
||||||
"hidden": {
|
inputs=[
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
}
|
],
|
||||||
}
|
outputs=[
|
||||||
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights"
|
@classmethod
|
||||||
|
def execute(cls, cn_extras: dict[str]={}):
|
||||||
def load_weights(self, cn_extras: dict[str]={}):
|
|
||||||
weights = ControlWeights.default(extras=cn_extras)
|
weights = ControlWeights.default(extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class ScaledSoftMaskedUniversalWeights(io.ComfyNode):
|
||||||
class ScaledSoftMaskedUniversalWeights:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ScaledSoftMaskedUniversalWeights',
|
||||||
"mask": ("MASK", ),
|
display_name='Scaled Soft Masked Weights 🛂🅐🅒🅝',
|
||||||
"min_base_multiplier": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights',
|
||||||
"max_base_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
inputs=[
|
||||||
#"lock_min": ("BOOLEAN", {"default": False}, ),
|
io.Mask.Input('mask'),
|
||||||
#"lock_max": ("BOOLEAN", {"default": False}, ),
|
io.Float.Input('min_base_multiplier', default=0.0, max=1.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('max_base_multiplier', default=1.0, max=1.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
],
|
||||||
},
|
outputs=[
|
||||||
"hidden": {
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
}
|
]
|
||||||
}
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights"
|
@classmethod
|
||||||
|
def execute(cls, mask: Tensor, min_base_multiplier: float, max_base_multiplier: float, lock_min=False, lock_max=False,
|
||||||
def load_weights(self, mask: Tensor, min_base_multiplier: float, max_base_multiplier: float, lock_min=False, lock_max=False,
|
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
# normalize mask
|
# normalize mask
|
||||||
mask = mask.clone()
|
mask = mask.clone()
|
||||||
@@ -68,116 +61,107 @@ class ScaledSoftMaskedUniversalWeights:
|
|||||||
else:
|
else:
|
||||||
mask = linear_conversion(mask, x_min, x_max, min_base_multiplier, max_base_multiplier)
|
mask = linear_conversion(mask, x_min, x_max, min_base_multiplier, max_base_multiplier)
|
||||||
weights = ControlWeights.universal_mask(weight_mask=mask, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
weights = ControlWeights.universal_mask(weight_mask=mask, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class ScaledSoftUniversalWeights(io.ComfyNode):
|
||||||
class ScaledSoftUniversalWeights:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ScaledSoftControlNetWeights',
|
||||||
"base_multiplier": ("FLOAT", {"default": 0.825, "min": 0.0, "max": 1.0, "step": 0.001}, ),
|
display_name='Scaled Soft Weights 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights',
|
||||||
"optional": {
|
inputs=[
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Float.Input('base_multiplier', default=0.825, max=1.0, min=0.0, step=0.001),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights"
|
@classmethod
|
||||||
|
def execute(cls, base_multiplier, uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
def load_weights(self, base_multiplier, uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
|
||||||
weights = ControlWeights.universal(base_multiplier=base_multiplier, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
weights = ControlWeights.universal(base_multiplier=base_multiplier, uncond_multiplier=uncond_multiplier, extras=cn_extras)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class SoftControlNetWeightsSD15(io.ComfyNode):
|
||||||
class SoftControlNetWeightsSD15:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_SoftControlNetWeightsSD15',
|
||||||
"output_0": ("FLOAT", {"default": 0.09941396206337118, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='ControlNet Soft Weights [SD1.5] 🛂🅐🅒🅝',
|
||||||
"output_1": ("FLOAT", {"default": 0.12050177219802567, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet',
|
||||||
"output_2": ("FLOAT", {"default": 0.14606275417942507, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"output_3": ("FLOAT", {"default": 0.17704576264172736, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_0', default=0.09941396206337118, max=10.0, min=0.0, step=0.001),
|
||||||
"output_4": ("FLOAT", {"default": 0.214600924414215, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_1', default=0.12050177219802567, max=10.0, min=0.0, step=0.001),
|
||||||
"output_5": ("FLOAT", {"default": 0.26012233262329093, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_2', default=0.14606275417942507, max=10.0, min=0.0, step=0.001),
|
||||||
"output_6": ("FLOAT", {"default": 0.3152997971191405, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_3', default=0.17704576264172736, max=10.0, min=0.0, step=0.001),
|
||||||
"output_7": ("FLOAT", {"default": 0.3821815722656249, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_4', default=0.214600924414215, max=10.0, min=0.0, step=0.001),
|
||||||
"output_8": ("FLOAT", {"default": 0.4632503906249999, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_5', default=0.26012233262329093, max=10.0, min=0.0, step=0.001),
|
||||||
"output_9": ("FLOAT", {"default": 0.561515625, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_6', default=0.3152997971191405, max=10.0, min=0.0, step=0.001),
|
||||||
"output_10": ("FLOAT", {"default": 0.6806249999999999, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_7', default=0.3821815722656249, max=10.0, min=0.0, step=0.001),
|
||||||
"output_11": ("FLOAT", {"default": 0.825, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_8', default=0.4632503906249999, max=10.0, min=0.0, step=0.001),
|
||||||
"middle_0": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_9', default=0.561515625, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('output_10', default=0.6806249999999999, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('output_11', default=0.825, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Float.Input('middle_0', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet"
|
@classmethod
|
||||||
|
def execute(cls, output_0, output_1, output_2, output_3, output_4, output_5, output_6,
|
||||||
def load_weights(self, output_0, output_1, output_2, output_3, output_4, output_5, output_6,
|
|
||||||
output_7, output_8, output_9, output_10, output_11, middle_0,
|
output_7, output_8, output_9, output_10, output_11, middle_0,
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
return CustomControlNetWeightsSD15.load_weights(self,
|
return CustomControlNetWeightsSD15.execute(
|
||||||
output_0=output_0, output_1=output_1, output_2=output_2, output_3=output_3,
|
output_0=output_0, output_1=output_1, output_2=output_2, output_3=output_3,
|
||||||
output_4=output_4, output_5=output_5, output_6=output_6, output_7=output_7,
|
output_4=output_4, output_5=output_5, output_6=output_6, output_7=output_7,
|
||||||
output_8=output_8, output_9=output_9, output_10=output_10, output_11=output_11,
|
output_8=output_8, output_9=output_9, output_10=output_10, output_11=output_11,
|
||||||
middle_0=middle_0,
|
middle_0=middle_0,
|
||||||
uncond_multiplier=uncond_multiplier, cn_extras=cn_extras)
|
uncond_multiplier=uncond_multiplier, cn_extras=cn_extras)
|
||||||
|
|
||||||
|
class CustomControlNetWeightsSD15(io.ComfyNode):
|
||||||
class CustomControlNetWeightsSD15:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_CustomControlNetWeightsSD15',
|
||||||
"output_0": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='ControlNet Custom Weights [SD1.5] 🛂🅐🅒🅝',
|
||||||
"output_1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet',
|
||||||
"output_2": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"output_3": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_0', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_4": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_1', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_5": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_2', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_6": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_3', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_7": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_4', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_8": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_5', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_9": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_6', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_10": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_7', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"output_11": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_8', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"middle_0": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('output_9', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('output_10', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('output_11', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Float.Input('middle_0', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet"
|
@classmethod
|
||||||
|
def execute(cls, output_0, output_1, output_2, output_3, output_4, output_5, output_6,
|
||||||
def load_weights(self, output_0, output_1, output_2, output_3, output_4, output_5, output_6,
|
|
||||||
output_7, output_8, output_9, output_10, output_11, middle_0,
|
output_7, output_8, output_9, output_10, output_11, middle_0,
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
weights_output = [output_0, output_1, output_2, output_3, output_4, output_5, output_6,
|
weights_output = [output_0, output_1, output_2, output_3, output_4, output_5, output_6,
|
||||||
@@ -185,50 +169,47 @@ class CustomControlNetWeightsSD15:
|
|||||||
weights_middle = [middle_0]
|
weights_middle = [middle_0]
|
||||||
weights = ControlWeights.controlnet(weights_output=weights_output, weights_middle=weights_middle, uncond_multiplier=uncond_multiplier,
|
weights = ControlWeights.controlnet(weights_output=weights_output, weights_middle=weights_middle, uncond_multiplier=uncond_multiplier,
|
||||||
extras=cn_extras, disable_applied_to=True)
|
extras=cn_extras, disable_applied_to=True)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class CustomControlNetWeightsFlux(io.ComfyNode):
|
||||||
class CustomControlNetWeightsFlux:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_CustomControlNetWeightsFlux',
|
||||||
"input_0": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='ControlNet Custom Weights [Flux] 🛂🅐🅒🅝',
|
||||||
"input_1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet',
|
||||||
"input_2": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"input_3": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_0', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_4": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_1', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_5": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_2', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_6": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_3', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_7": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_4', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_8": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_5', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_9": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_6', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_10": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_7', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_11": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_8', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_12": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_9', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_13": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_10', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_14": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_11', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_15": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_12', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_16": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_13', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_17": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_14', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"input_18": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_15', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('input_16', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('input_17', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Float.Input('input_18', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet"
|
@classmethod
|
||||||
|
def execute(cls, input_0, input_1, input_2, input_3, input_4, input_5, input_6,
|
||||||
def load_weights(self, input_0, input_1, input_2, input_3, input_4, input_5, input_6,
|
|
||||||
input_7, input_8, input_9, input_10, input_11, input_12, input_13,
|
input_7, input_8, input_9, input_10, input_11, input_12, input_13,
|
||||||
input_14, input_15, input_16, input_17, input_18,
|
input_14, input_15, input_16, input_17, input_18,
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
@@ -236,154 +217,162 @@ class CustomControlNetWeightsFlux:
|
|||||||
input_6, input_7, input_8, input_9, input_10, input_11,
|
input_6, input_7, input_8, input_9, input_10, input_11,
|
||||||
input_12, input_13, input_14, input_15, input_16, input_17, input_18]
|
input_12, input_13, input_14, input_15, input_16, input_17, input_18]
|
||||||
weights = ControlWeights.controlnet(weights_input=weights_input, uncond_multiplier=uncond_multiplier, extras=cn_extras, disable_applied_to=True)
|
weights = ControlWeights.controlnet(weights_input=weights_input, uncond_multiplier=uncond_multiplier, extras=cn_extras, disable_applied_to=True)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class CustomControlNetWeightsAnima(io.ComfyNode):
|
||||||
class CustomControlNetWeightsAnima:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
required = {
|
return io.Schema(
|
||||||
f"block_{index}": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001})
|
node_id='ACN_CustomControlNetWeightsAnima',
|
||||||
for index in range(28)
|
display_name='ControlNet Custom Weights [Anima] 🛂🅐🅒🅝',
|
||||||
}
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet',
|
||||||
return {
|
inputs=[
|
||||||
"required": required,
|
io.Float.Input('block_0', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('block_1', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
io.Float.Input('block_2', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('block_3', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('block_4', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"hidden": {
|
io.Float.Input('block_5', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
io.Float.Input('block_6', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('block_7', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
}
|
io.Float.Input('block_8', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_9', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_10', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_11', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_12', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_13', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_14', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_15', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_16', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_17', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_18', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_19', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_20', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_21', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_22', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_23', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_24', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_25', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_26', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('block_27', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
|
],
|
||||||
|
outputs=[
|
||||||
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
@classmethod
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
def execute(cls, uncond_multiplier: float=1.0, cn_extras: dict[str]={}, **kwargs):
|
||||||
FUNCTION = "load_weights"
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/ControlNet"
|
|
||||||
|
|
||||||
def load_weights(self, uncond_multiplier: float=1.0, cn_extras: dict[str]={}, **kwargs):
|
|
||||||
weights = [kwargs[f"block_{index}"] for index in range(28)]
|
weights = [kwargs[f"block_{index}"] for index in range(28)]
|
||||||
control_weights = ControlWeights.controllllite(
|
control_weights = ControlWeights.controllllite(
|
||||||
weights_input=weights,
|
weights_input=weights,
|
||||||
uncond_multiplier=uncond_multiplier,
|
uncond_multiplier=uncond_multiplier,
|
||||||
extras=cn_extras,
|
extras=cn_extras,
|
||||||
)
|
)
|
||||||
return (control_weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=control_weights)))
|
return io.NodeOutput(control_weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=control_weights)))
|
||||||
|
|
||||||
|
class SoftT2IAdapterWeights(io.ComfyNode):
|
||||||
class SoftT2IAdapterWeights:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_SoftT2IAdapterWeights',
|
||||||
"input_0": ("FLOAT", {"default": 0.25, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='T2IAdapter Soft Weights 🛂🅐🅒🅝',
|
||||||
"input_1": ("FLOAT", {"default": 0.62, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter',
|
||||||
"input_2": ("FLOAT", {"default": 0.825, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"input_3": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_0', default=0.25, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('input_1', default=0.62, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('input_2', default=0.825, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Float.Input('input_3', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter"
|
@classmethod
|
||||||
|
def execute(cls, input_0, input_1, input_2, input_3,
|
||||||
def load_weights(self, input_0, input_1, input_2, input_3,
|
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
return CustomT2IAdapterWeights.load_weights(self, input_0=input_0, input_1=input_1, input_2=input_2, input_3=input_3,
|
return CustomT2IAdapterWeights.execute(input_0=input_0, input_1=input_1, input_2=input_2, input_3=input_3,
|
||||||
uncond_multiplier=uncond_multiplier, cn_extras=cn_extras)
|
uncond_multiplier=uncond_multiplier, cn_extras=cn_extras)
|
||||||
|
|
||||||
|
class CustomT2IAdapterWeights(io.ComfyNode):
|
||||||
class CustomT2IAdapterWeights:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_CustomT2IAdapterWeights',
|
||||||
"input_0": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
display_name='T2IAdapter Custom Weights 🛂🅐🅒🅝',
|
||||||
"input_1": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter',
|
||||||
"input_2": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
inputs=[
|
||||||
"input_3": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}, ),
|
io.Float.Input('input_0', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Float.Input('input_1', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"optional": {
|
io.Float.Input('input_2', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"uncond_multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}, ),
|
io.Float.Input('input_3', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('uncond_multiplier', optional=True, default=1.0, max=1.0, min=0.0, step=0.01),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CONTROL_NET_WEIGHTS').Output('CN_WEIGHTS', is_output_list=False),
|
||||||
}
|
io.Custom('TIMESTEP_KEYFRAME').Output('TK_SHORTCUT', is_output_list=False)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CONTROL_NET_WEIGHTS", "TIMESTEP_KEYFRAME",)
|
|
||||||
RETURN_NAMES = WEIGHTS_RETURN_NAMES
|
|
||||||
FUNCTION = "load_weights"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/T2IAdapter"
|
@classmethod
|
||||||
|
def execute(cls, input_0, input_1, input_2, input_3,
|
||||||
def load_weights(self, input_0, input_1, input_2, input_3,
|
|
||||||
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
uncond_multiplier: float=1.0, cn_extras: dict[str]={}):
|
||||||
weights = [input_0, input_1, input_2, input_3]
|
weights = [input_0, input_1, input_2, input_3]
|
||||||
weights = get_properly_arranged_t2i_weights(weights)
|
weights = get_properly_arranged_t2i_weights(weights)
|
||||||
weights = ControlWeights.t2iadapter(weights_input=weights, uncond_multiplier=uncond_multiplier, extras=cn_extras, disable_applied_to=True)
|
weights = ControlWeights.t2iadapter(weights_input=weights, uncond_multiplier=uncond_multiplier, extras=cn_extras, disable_applied_to=True)
|
||||||
return (weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
return io.NodeOutput(weights, TimestepKeyframeGroup.default(TimestepKeyframe(control_weights=weights)))
|
||||||
|
|
||||||
|
class ExtrasMiddleMultNode(io.ComfyNode):
|
||||||
class ExtrasMiddleMultNode:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_ExtrasMiddleMult',
|
||||||
"middle_mult": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.001}),
|
display_name='Middle Weight Extras 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/extras',
|
||||||
"optional": {
|
inputs=[
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Float.Input('middle_mult', default=1.0, max=10.0, min=0.0, step=0.001),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
}
|
io.Custom('CN_WEIGHTS_EXTRAS').Output('cn_extras', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CN_WEIGHTS_EXTRAS",)
|
|
||||||
RETURN_NAMES = ("cn_extras",)
|
|
||||||
FUNCTION = "create_extras"
|
|
||||||
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/extras"
|
@classmethod
|
||||||
|
def execute(cls, middle_mult: float, cn_extras: dict[str]={}):
|
||||||
def create_extras(self, middle_mult: float, cn_extras: dict[str]={}):
|
|
||||||
cn_extras = cn_extras.copy()
|
cn_extras = cn_extras.copy()
|
||||||
cn_extras[Extras.MIDDLE_MULT] = middle_mult
|
cn_extras[Extras.MIDDLE_MULT] = middle_mult
|
||||||
return (cn_extras,)
|
return io.NodeOutput(cn_extras,)
|
||||||
|
|
||||||
|
class AnimaLLLiteExtras(io.ComfyNode):
|
||||||
class AnimaLLLiteExtras:
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def INPUT_TYPES(s):
|
def define_schema(cls) -> io.Schema:
|
||||||
return {
|
return io.Schema(
|
||||||
"required": {
|
node_id='ACN_AnimaLLLiteExtras',
|
||||||
"inpaint_mask": ("MASK",),
|
display_name='Anima LLLite Extras 🛂🅐🅒🅝',
|
||||||
},
|
category='Adv-ControlNet 🛂🅐🅒🅝/weights/extras',
|
||||||
"optional": {
|
inputs=[
|
||||||
"cn_extras": ("CN_WEIGHTS_EXTRAS",),
|
io.Mask.Input('inpaint_mask'),
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Input('cn_extras', optional=True)
|
||||||
"hidden": {
|
],
|
||||||
"autosize": ("ACNAUTOSIZE", {"padding": 0}),
|
outputs=[
|
||||||
},
|
io.Custom('CN_WEIGHTS_EXTRAS').Output('cn_extras', is_output_list=False)
|
||||||
}
|
]
|
||||||
|
)
|
||||||
|
|
||||||
RETURN_TYPES = ("CN_WEIGHTS_EXTRAS",)
|
@classmethod
|
||||||
RETURN_NAMES = ("cn_extras",)
|
def execute(cls, inpaint_mask: Tensor, cn_extras: dict[str]={}):
|
||||||
FUNCTION = "create_extras"
|
|
||||||
CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝/weights/extras"
|
|
||||||
|
|
||||||
def create_extras(self, inpaint_mask: Tensor, cn_extras: dict[str]={}):
|
|
||||||
cn_extras = cn_extras.copy()
|
cn_extras = cn_extras.copy()
|
||||||
cn_extras[AnimaLLLiteConst.INPAINT_MASK] = inpaint_mask.clone()
|
cn_extras[AnimaLLLiteConst.INPAINT_MASK] = inpaint_mask.clone()
|
||||||
return (cn_extras,)
|
return io.NodeOutput(cn_extras,)
|
||||||
|
|||||||
@@ -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: "AdvancedControlNet.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("ACN_")
|
|
||||||
|| nodeData.python_module == 'custom_nodes.ComfyUI-Advanced-ControlNet') {
|
|
||||||
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 {
|
|
||||||
ACNAUTOSIZE(node, inputName, inputData) {
|
|
||||||
let w = {
|
|
||||||
name : inputName,
|
|
||||||
type : "ACN.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,293 +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');
|
|
||||||
scrollbarStyle.innerHTML = `
|
|
||||||
<style id="scroll-properties">
|
|
||||||
* {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
`
|
|
||||||
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: "AdvancedControlNet.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("ACN_") && 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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user