Files
tenser-tensor-ComfyUI-Tense…/nodes_sampling.py
T

177 lines
5.6 KiB
Python

# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
from typing import override
import latent_preview
from comfy import sample, model_management
from comfy_api.latest import ComfyExtension, io
from .nodes_latent import SCALE_FACTORS, SCALE_METHODS, scale_latent
from .nodes_text_encoder import SingleCondCFGGuider
CATEGORY = "TenserTensor/Sampling"
def execute_guided_sampling(**kwargs):
guider, latent, sigmas, random_noise, sampler, preview_latent = (
kwargs.get("guider"),
kwargs.get("latent"),
kwargs.get("sigmas"),
kwargs.get("random_noise"),
kwargs.get("sampler"),
kwargs.get("preview_latent"),
)
if not isinstance(guider, SingleCondCFGGuider):
guider = SingleCondCFGGuider.from_cfg_guider(guider)
model_patcher = guider.model_patcher
latent_dict = latent.copy()
latent_tensor = sample.fix_empty_latent_channels(
model_patcher,
latent_dict["samples"],
latent.get("downscale_ratio_spacial", None)
)
latent_dict["samples"] = latent_tensor
noise_mask = latent.get("noise_mask", None)
interim_buffer = {}
if preview_latent:
latent_preview.set_preview_method("latent2rgb")
callback = latent_preview.prepare_callback(model_patcher, sigmas.shape[-1] - 1, interim_buffer)
else:
callback = None
# disable_progress_bar = not utils.PROGRESS_BAR_ENABLED
samples = guider.sample(
random_noise.generate_noise(latent),
latent_tensor,
sampler,
sigmas,
denoise_mask=noise_mask,
callback=callback,
disable_pbar=False,
seed=random_noise.seed
).to(model_management.intermediate_device())
sampled_latent = latent_dict.copy()
sampled_latent.pop("downscale_ratio_spacial", None)
sampled_latent["samples"] = samples
return sampled_latent
class TT_GuidedKSamplerNode(io.ComfyNode):
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="TT_GuidedKSamplerNode",
display_name="TT Guided KSampler",
category=CATEGORY,
description="",
inputs=[
io.Latent.Input("latent"),
io.Guider.Input("guider"),
io.Sigmas.Input("sigmas"),
io.Sampler.Input("sampler"),
io.Noise.Input("random_noise"),
],
outputs=[
io.Latent.Output("SAMPLES")
]
)
@classmethod
def execute(cls, **kwargs) -> io.NodeOutput:
samples = execute_guided_sampling(**kwargs)
return io.NodeOutput(samples)
class TT_GuidedUpscaleKSamplerNode(io.ComfyNode):
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="TT_GuidedUpscaleKSamplerNode",
display_name="TT Guided Upscale KSampler",
category=CATEGORY,
description="",
inputs=[
io.Latent.Input("latent"),
io.Guider.Input("guider"),
io.Sigmas.Input("sigmas"),
io.Sampler.Input("sampler"),
io.Noise.Input("random_noise"),
io.Boolean.Input("scale_latent", default=False, label_on="Scale", label_off="Skip"),
io.Combo.Input("scale_factor", options=SCALE_FACTORS, default="1x", advanced=True),
io.Combo.Input("scale_method", options=SCALE_METHODS, default="bicubic", advanced=True),
],
outputs=[
io.Latent.Output("SAMPLES")
]
)
@classmethod
def execute(cls, **kwargs) -> io.NodeOutput:
samples = execute_guided_sampling(**kwargs)
if kwargs.get("scale_latent"):
samples = scale_latent(**kwargs)
return io.NodeOutput(samples)
class TT_GuidedKSamplerWithPreviewNode(io.ComfyNode):
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="TT_GuidedKSamplerWithPreviewNode",
display_name="TT Guided KSampler (With Preview)",
category=CATEGORY,
description="",
inputs=[
io.Latent.Input("latent"),
io.Guider.Input("guider"),
io.Sigmas.Input("sigmas"),
io.Sampler.Input("sampler"),
io.Noise.Input("random_noise"),
io.Boolean.Input("preview_latent", default=True, label_on="Show Peview", label_off="Only Sample"),
],
outputs=[
io.Latent.Output("SAMPLES")
]
)
@classmethod
def execute(cls, **kwargs) -> io.NodeOutput:
samples = execute_guided_sampling(**kwargs)
return io.NodeOutput(samples)
# ==============================================================================
# V3 entrypoint — registers context nodes with ComfyUI
# ==============================================================================
class SamplingNodesExtension(ComfyExtension):
@override
async def get_node_list(self) -> list[type[io.ComfyNode]]:
return [
TT_GuidedKSamplerNode,
TT_GuidedUpscaleKSamplerNode,
TT_GuidedKSamplerWithPreviewNode,
]
async def comfy_entrypoint() -> SamplingNodesExtension:
return SamplingNodesExtension()
# ==============================================================================
# Re-exports for backward compatibility
# ==============================================================================
__all__ = [
"TT_GuidedKSamplerNode",
"TT_GuidedUpscaleKSamplerNode",
"TT_GuidedKSamplerWithPreviewNode",
]