diff --git a/adv_control/nodes.py b/adv_control/nodes.py index 470149f..d335d42 100644 --- a/adv_control/nodes.py +++ b/adv_control/nodes.py @@ -104,7 +104,7 @@ class AdvancedControlNetApply: "weights_override": ("CONTROL_NET_WEIGHTS", ), "model_optional": ("MODEL",), "vae_optional": ("VAE",), - "autosize": ("ACNAUTOSIZE", {"padding": 40}), + "autosize": ("ACNAUTOSIZE", {"padding": 0}), } } @@ -117,7 +117,7 @@ class AdvancedControlNetApply: def apply_controlnet(self, positive, negative, control_net, image, strength, start_percent, end_percent, mask_optional: Tensor=None, model_optional: ModelPatcher=None, vae_optional=None, timestep_kf: TimestepKeyframeGroup=None, latent_kf_override: LatentKeyframeGroup=None, - weights_override: ControlWeights=None): + weights_override: ControlWeights=None, control_apply_to_uncond=False): if strength == 0: return (positive, negative, model_optional) if model_optional: @@ -129,59 +129,101 @@ class AdvancedControlNetApply: out = [] for conditioning in [positive, negative]: c = [] - for t in conditioning: - d = t[1].copy() + if conditioning is not None: + for t in conditioning: + d = t[1].copy() - prev_cnet = d.get('control', None) - if prev_cnet in cnets: - c_net = cnets[prev_cnet] - else: - # copy, convert to advanced if needed, and set cond - c_net = convert_to_advanced(control_net.copy()).set_cond_hint(control_hint, strength, (start_percent, end_percent), vae_optional) - if is_advanced_controlnet(c_net): - # disarm node check - c_net.disarm() - # if model required, verify model is passed in, and if so patch it - if c_net.require_model: - if not model_optional: - raise Exception(f"Type '{type(c_net).__name__}' requires model_optional input, but got None.") - c_net.patch_model(model=model_optional) - # if vae required, verify vae is passed in - if c_net.require_vae: - # if controlnet can accept preprocced condhint latents and is the case, ignore vae requirement - if c_net.allow_condhint_latents and isinstance(control_hint, AbstractPreprocWrapper): - pass - elif not vae_optional: - # make sure SD3 ControlNet will get a special message instead of generic type mention - if is_sd3_advanced_controlnet: - raise Exception(f"SD3 ControlNet requires vae_optional input, but got None.") - else: - raise Exception(f"Type '{type(c_net).__name__}' requires vae_optional input, but got None.") - # apply optional parameters and overrides, if provided - if timestep_kf is not None: - c_net.set_timestep_keyframes(timestep_kf) - if latent_kf_override is not None: - c_net.latent_keyframe_override = latent_kf_override - if weights_override is not None: - c_net.weights_override = weights_override - # verify weights are compatible - c_net.verify_all_weights() - # set cond hint mask - if mask_optional is not None: - mask_optional = mask_optional.clone() - # if not in the form of a batch, make it so - if len(mask_optional.shape) < 3: - mask_optional = mask_optional.unsqueeze(0) - c_net.set_cond_hint_mask(mask_optional) - c_net.set_previous_controlnet(prev_cnet) - cnets[prev_cnet] = c_net + prev_cnet = d.get('control', None) + if prev_cnet in cnets: + c_net = cnets[prev_cnet] + else: + # copy, convert to advanced if needed, and set cond + c_net = convert_to_advanced(control_net.copy()).set_cond_hint(control_hint, strength, (start_percent, end_percent), vae_optional) + if is_advanced_controlnet(c_net): + # disarm node check + c_net.disarm() + # if model required, verify model is passed in, and if so patch it + if c_net.require_model: + if not model_optional: + raise Exception(f"Type '{type(c_net).__name__}' requires model_optional input, but got None.") + c_net.patch_model(model=model_optional) + # if vae required, verify vae is passed in + if c_net.require_vae: + # if controlnet can accept preprocced condhint latents and is the case, ignore vae requirement + if c_net.allow_condhint_latents and isinstance(control_hint, AbstractPreprocWrapper): + pass + elif not vae_optional: + # make sure SD3 ControlNet will get a special message instead of generic type mention + if is_sd3_advanced_controlnet: + raise Exception(f"SD3 ControlNet requires vae_optional input, but got None.") + else: + raise Exception(f"Type '{type(c_net).__name__}' requires vae_optional input, but got None.") + # apply optional parameters and overrides, if provided + if timestep_kf is not None: + c_net.set_timestep_keyframes(timestep_kf) + if latent_kf_override is not None: + c_net.latent_keyframe_override = latent_kf_override + if weights_override is not None: + c_net.weights_override = weights_override + # verify weights are compatible + c_net.verify_all_weights() + # set cond hint mask + if mask_optional is not None: + mask_optional = mask_optional.clone() + # if not in the form of a batch, make it so + if len(mask_optional.shape) < 3: + mask_optional = mask_optional.unsqueeze(0) + c_net.set_cond_hint_mask(mask_optional) + c_net.set_previous_controlnet(prev_cnet) + cnets[prev_cnet] = c_net - d['control'] = c_net - d['control_apply_to_uncond'] = False - n = [t[0], d] - c.append(n) + d['control'] = c_net + d['control_apply_to_uncond'] = control_apply_to_uncond + n = [t[0], d] + c.append(n) out.append(c) return (out[0], out[1], model_optional) + + +class AdvancedControlNetApplySingle: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "conditioning": ("CONDITIONING", ), + "control_net": ("CONTROL_NET", ), + "image": ("IMAGE", ), + "strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 10.0, "step": 0.01}), + "start_percent": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.001}) + }, + "optional": { + "mask_optional": ("MASK", ), + "timestep_kf": ("TIMESTEP_KEYFRAME", ), + "latent_kf_override": ("LATENT_KEYFRAME", ), + "weights_override": ("CONTROL_NET_WEIGHTS", ), + "model_optional": ("MODEL",), + "vae_optional": ("VAE",), + "autosize": ("ACNAUTOSIZE", {"padding": 0}), + } + } + + RETURN_TYPES = ("CONDITIONING","MODEL",) + RETURN_NAMES = ("CONDITIONING", "model_opt") + FUNCTION = "apply_controlnet" + + CATEGORY = "Adv-ControlNet 🛂🅐🅒🅝" + + def apply_controlnet(self, conditioning, control_net, image, strength, start_percent, end_percent, + mask_optional: Tensor=None, model_optional: ModelPatcher=None, vae_optional=None, + timestep_kf: TimestepKeyframeGroup=None, latent_kf_override: LatentKeyframeGroup=None, + weights_override: ControlWeights=None): + values = AdvancedControlNetApply.apply_controlnet(self, positive=conditioning, negative=None, control_net=control_net, image=image, + strength=strength, start_percent=start_percent, end_percent=end_percent, + mask_optional=mask_optional, model_optional=model_optional, vae_optional=vae_optional, + timestep_kf=timestep_kf, latent_kf_override=latent_kf_override, weights_override=weights_override, + control_apply_to_uncond=True) + return (values[0], values[2]) # NODE MAPPING @@ -196,6 +238,7 @@ NODE_CLASS_MAPPINGS = { "LatentKeyframeGroup": LatentKeyframeGroupNode, # Conditioning "ACN_AdvancedControlNetApply": AdvancedControlNetApply, + "ACN_AdvancedControlNetApplySingle": AdvancedControlNetApplySingle, # Loaders "ControlNetLoaderAdvanced": ControlNetLoaderAdvanced, "DiffControlNetLoaderAdvanced": DiffControlNetLoaderAdvanced, @@ -239,6 +282,7 @@ NODE_DISPLAY_NAME_MAPPINGS = { "LatentKeyframeGroup": "Latent Keyframe Group 🛂🅐🅒🅝", # Conditioning "ACN_AdvancedControlNetApply": "Apply Advanced ControlNet 🛂🅐🅒🅝", + "ACN_AdvancedControlNetApplySingle": "Apply Advanced ControlNet(1) 🛂🅐🅒🅝", # Loaders "ControlNetLoaderAdvanced": "Load Advanced ControlNet Model 🛂🅐🅒🅝", "DiffControlNetLoaderAdvanced": "Load Advanced ControlNet Model (diff) 🛂🅐🅒🅝",