diff --git a/__init__.py b/__init__.py index eeda1b7..9e5705b 100644 --- a/__init__.py +++ b/__init__.py @@ -1,31 +1,13 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -# import glob -# import re - -from .node_mappings import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS, NODES_COUNT, RESET, BRIGHT_GREEN, BRIGHT_CYAN, CYAN, YELLOW - - -# def count_tt_classes(): -# total = 0 -# for path in sorted(glob.glob("nodes_*.py")): -# count = sum(1 for line in open(path) if re.match(r"^class TT_", line)) -# total += count -# -# return total +# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) +from .comfy_extension import TenserTensorExtension WEB_DIRECTORY = "./web" -__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY'] -print() -SEP = f"{CYAN}{'=' * 60}{RESET}" -print(SEP) -print(f"{YELLOW}TenserTensor ComfyUI Nodes Pack (v1.7.8): {BRIGHT_GREEN}{NODES_COUNT} Nodes Loaded{RESET}") -print(SEP) -print(f"{BRIGHT_CYAN}[V] Repository: https://github.com/tenser-tensor/ComfyUI-TenserTensor{RESET}") -print(f"{BRIGHT_CYAN}[V] ComfyUI Registry: https://registry.comfy.org/publishers/tenser-tensor{RESET}") -print(f"{BRIGHT_CYAN}[V] Please check README file: https://github.com/tenser-tensor/ComfyUI-TenserTensor/blob/main/README.md{RESET}") -print(SEP) -print() +# ============================================================================== +# V3 entrypoint — registers context nodes with ComfyUI +# ============================================================================== + +async def comfy_entrypoint() -> TenserTensorExtension: + return TenserTensorExtension() diff --git a/comfy_extension.py b/comfy_extension.py new file mode 100644 index 0000000..d6134f4 --- /dev/null +++ b/comfy_extension.py @@ -0,0 +1,33 @@ +# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) + +from typing import override + +from comfy_api.latest import ComfyExtension, io + +from .nodes_context import NODES as NODES_CONTEXT +from .nodes_controlnet import NODES as NODES_CONTROLNET +from .nodes_detector import NODES as NODES_DETECTOR +from .nodes_image import NODES as NODES_IMAGE +from .nodes_latent import NODES as NODES_LATENT +from .nodes_loaders import NODES as NODES_LOADERS +from .nodes_postproduction import NODES as NODES_POSTPRODUCTION +from .nodes_sampling import NODES as NODES_SAMPLING +from .nodes_text_encoder import NODES as NODES_TEXT_ENCODER +from .nodes_workflow import NODES as NODES_WORKFLOW + + +class TenserTensorExtension(ComfyExtension): + @override + async def get_node_list(self) -> list[type[io.ComfyNode]]: + return [ + *NODES_CONTEXT, + *NODES_CONTROLNET, + *NODES_DETECTOR, + *NODES_IMAGE, + *NODES_LATENT, + *NODES_LOADERS, + *NODES_POSTPRODUCTION, + *NODES_SAMPLING, + *NODES_TEXT_ENCODER, + *NODES_WORKFLOW, + ] diff --git a/node_mappings.py b/node_mappings.py deleted file mode 100644 index d4d89df..0000000 --- a/node_mappings.py +++ /dev/null @@ -1,389 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -RESET = "\033[0m" -BOLD = "\033[1m" -RED = "\033[31m" -GREEN = "\033[32m" -YELLOW = "\033[33m" -BLUE = "\033[34m" -CYAN = "\033[36m" -WHITE = "\033[37m" -BRIGHT_GREEN = "\033[92m" -BRIGHT_CYAN = "\033[96m" - -import inspect -import sys - -try: - from .nodes_context import * - from .nodes.context.base_context import TT_BaseContext - from .nodes.context.context import TT_Context - from .nodes.context.context_passthrough import TT_ContextPassthrough - from .nodes.context.context_set_guider import TT_ContextSetGuider - from .nodes.context.context_set_image import TT_ContextSetImage - from .nodes.context.context_set_latent import TT_ContextSetLatent - from .nodes.context.even_larger_context import TT_EvenLargerContext - from .nodes.context.large_context_flux import TT_LargeContextFlux - from .nodes.context.large_context_sdxl import TT_LargeContextSdxl -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Context nodes unavailable{RESET}") - -try: - from .nodes_detector import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Detector nodes unavailable{RESET}") - -try: - from .nodes.image.image_preview_save import TT_ImagePreviewSave - from .nodes.image.image_preview_upscale_save import TT_ImagePreviewUpscaleSave - from .nodes.image.guider_image_reference import TT_GuiderImageReference - from .nodes_image import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Image nodes unavailable{RESET}") - -try: - from .nodes_controlnet import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: ControlNet nodes unavailable{RESET}") - -try: - from .nodes.latent.latent_factory import TT_LatentFactory - from .nodes_latent import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Latent nodes unavailable{RESET}") - -try: - from .nodes.loaders.flux_models_loader import TT_FluxModelsLoader - from .nodes.loaders.flux_models_loader_advanced import TT_FluxModelsLoaderAdvanced - from .nodes.loaders.gguf_models_loader import TT_Flux2GgufModelsLoader - from .nodes.loaders.gguf_models_loader_advanced import TT_Flux2GgufModelsLoaderAdvanced - from .nodes.loaders.sdxl_models_loader import TT_SdxlModelsLoader - from .nodes.loaders.sdxl_models_loader_advanced import TT_SdxlModelsLoaderAdvanced - from .nodes_loaders import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Loader nodes unavailable{RESET}") - -try: - from .nodes.postproduction.add_film_grain import TT_AddFilmGrain - from .nodes.postproduction.apply_lut import TT_ApplyLut - from .nodes.postproduction.image_enhancer import TT_ImageEnhancer - from .nodes.postproduction.postproduction import TT_Postproduction - from .nodes.postproduction.postproduction_advanced import TT_PostproductionAdvanced - from .nodes.postproduction.quick_image_upscaler import TT_QuickImageUpscaler - from .nodes_postproduction import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Postproduction nodes unavailable{RESET}") - -try: - from .nodes.sampling.ksampler import TT_KSampler - from .nodes.sampling.ksampler_advanced import TT_KSamplerAdvanced - from .nodes.sampling.ksampler_context import TT_KSamplerContext - from .nodes.sampling.ksampler_two_stage import TT_KSamplerTwoStage - from .nodes.sampling.ksampler_guided import TT_KSamplerGuided - from .nodes_sampling import * -except ImportError: - print("f{YELLOW}TenserTensor: {RED}ERROR: Sampler nodes unavailable{RESET}") - -try: - from .nodes.text_encoders.clip_text_encode_flux import TT_ClipTextEncodeFlux - from .nodes.text_encoders.clip_text_encode_flux_context import TT_ClipTextEncodeFluxContext - from .nodes.text_encoders.clip_text_encode_sdxl import TT_ClipTextEncodeSdxl - from .nodes.text_encoders.clip_text_encode_sdxl_context import TT_ClipTextEncodeSdxlContext - from .nodes.text_encoders.clip_text_encode_flux2 import TT_ClipTextEncodeFlux2 - from .nodes.text_encoders.clip_text_encode_flux2_context import TT_ClipTextEncodeFlux2Context - from .nodes_text_encoder import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Text Encoder nodes unavailable{RESET}") - -try: - from .nodes.vae.vae_decode_context import TT_VaeDecodeContext - from .nodes.vae.vae_decode_tiled import TT_VaeDecodeTiled - from .nodes.vae.vae_encode_context import TT_VaeEncodeContext - from .nodes.vae.vae_encode_tiled import TT_VaeEncodeTiled - from .nodes_vae import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: VAE nodes unavailable{RESET}") - -try: - before = set(dir()) - from .nodes.workflow.flux_workflow_settings import TT_FluxWorkflowSettings - from .nodes.workflow.flux_workflow_settings_advanced import TT_FluxWorkflowSettingsAdvanced - from .nodes.workflow.sdxl_workflow_settings import TT_SdxlWorkflowSettings - from .nodes.workflow.sdxl_workflow_settings_advanced import TT_SdxlWorkflowSettingsAdvanced - from .nodes.workflow.flux2_workflow_settings import TT_Flux2WorkflowSettings - from .nodes.workflow.flux2_workflow_settings_advanced import TT_Flux2WorkflowSettingsAdvanced - from .nodes_workflow import * -except ImportError: - print(f"{YELLOW}TenserTensor: {RED}ERROR: Workflow nodes unavailable{RESET}") - -ADDED = { - name - for name, obj - in inspect.getmembers(sys.modules[__name__], inspect.isclass) - if name.startswith("TT_") -} -NODES_COUNT = len(ADDED) - -NODE_CLASS_MAPPINGS = { - # Context Deprecated - "TT_BaseContext": TT_BaseContext, - "TT_Context": TT_Context, - "TT_LargeContextFlux": TT_LargeContextFlux, - "TT_LargeContextSdxl": TT_LargeContextSdxl, - "TT_EvenLargerContext": TT_EvenLargerContext, - "TT_ContextSetImage": TT_ContextSetImage, - "TT_ContextSetLatent": TT_ContextSetLatent, - "TT_ContextSetGuider": TT_ContextSetGuider, - "TT_ContextPassthrough": TT_ContextPassthrough, - # Context V3 Nodes - "TT_BaseContextNode": TT_BaseContextNode, - "TT_BaseContextFlux2Node": TT_BaseContextFlux2Node, - "TT_ContextPassthroughNode": TT_ContextPassthroughNode, - "TT_ContextNode": TT_ContextNode, - "TT_ContextFlux2Node": TT_ContextFlux2Node, - "TT_ContextSetGuiderNode": TT_ContextSetGuiderNode, - "TT_ContextSetImageNode": TT_ContextSetImageNode, - "TT_ContextSetLatentNode": TT_ContextSetLatentNode, - "TT_ContextExtractEncoderFlux2Node": TT_ContextExtractEncoderFlux2Node, - "TT_ContextExtractGuidedSamplerFlux2Node": TT_ContextExtractGuidedSamplerFlux2Node, - "TT_ContextExtractVaeNode": TT_ContextExtractVaeNode, - "TT_ContextExtractImageNode": TT_ContextExtractImageNode, - # ControlNet V3 Nodes - "TT_Flux2ApplyControlNetNode": TT_Flux2ApplyControlNetNode, - "TT_Flux2ApplyControlNetAdvancedNode": TT_Flux2ApplyControlNetAdvancedNode, - # Detector V3 Nodes - "TT_CannyEdgeDetectorNode": TT_CannyEdgeDetectorNode, - # Image - "TT_ImagePreviewSave": TT_ImagePreviewSave, - "TT_ImagePreviewUpscaleSave": TT_ImagePreviewUpscaleSave, - "TT_GuiderImageReference": TT_GuiderImageReference, - # Image V3 Nodes - "TT_ImageLoaderResizerNode": TT_ImageLoaderResizerNode, - "TT_ImagePreviewSaveNode": TT_ImagePreviewSaveNode, - "TT_ImagePreviewUpscaleSaveNode": TT_ImagePreviewUpscaleSaveNode, - "TT_GuiderImageReferenceNode": TT_GuiderImageReferenceNode, - # Latent - "TT_LatentFactory": TT_LatentFactory, - # Latent V3 Nodes - "TT_LatentFactoryNode": TT_LatentFactoryNode, - "TT_LatentFactoryByModelNode": TT_LatentFactoryByModelNode, - "TT_LatentMultiTransformNode": TT_LatentMultiTransformNode, - "TT_LatentMultiTransformOnPixelSpaceNode": TT_LatentMultiTransformOnPixelSpaceNode, - # Loaders - "TT_SdxlModelsLoader": TT_SdxlModelsLoader, - "TT_SdxlModelsLoaderAdvanced": TT_SdxlModelsLoaderAdvanced, - "TT_Flux2GgufModelsLoader": TT_Flux2GgufModelsLoader, - "TT_Flux2GgufModelsLoaderAdvanced": TT_Flux2GgufModelsLoaderAdvanced, - "TT_FluxModelsLoader": TT_FluxModelsLoader, - "TT_FluxModelsLoaderAdvanced": TT_FluxModelsLoaderAdvanced, - # Loaders V3 Nodes - "TT_SdxlModelsLoaderNode": TT_SdxlModelsLoaderNode, - "TT_SdxlModelsLoaderAdvancedNode": TT_SdxlModelsLoaderAdvancedNode, - "TT_FluxModelsLoaderNode": TT_FluxModelsLoaderNode, - "TT_FluxModelsLoaderAdvancedNode": TT_FluxModelsLoaderAdvancedNode, - "TT_Flux2GgufModelsLoaderNode": TT_Flux2GgufModelsLoaderNode, - "TT_Flux2GgufModelsLoaderAdvancedNode": TT_Flux2GgufModelsLoaderAdvancedNode, - "TT_Sd35GgufModelsLoaderNode": TT_Sd35GgufModelsLoaderNode, - "TT_Sd35GgufModelsLoaderAdvancedNode": TT_Sd35GgufModelsLoaderAdvancedNode, - # Postproduction - "TT_ApplyLut": TT_ApplyLut, - "TT_AddFilmGrain": TT_AddFilmGrain, - "TT_QuickImageUpscaler": TT_QuickImageUpscaler, - "TT_ImageEnhancer": TT_ImageEnhancer, - "TT_Postproduction": TT_Postproduction, - "TT_PostproductionAdvanced": TT_PostproductionAdvanced, - # Postproduction V3 Nodes - "TT_AddFilmGrainNode": TT_AddFilmGrainNode, - "TT_ApplyLutNode": TT_ApplyLutNode, - "TT_ImageEnhancerNode": TT_ImageEnhancerNode, - "TT_QuickImageUpscalerNode": TT_QuickImageUpscalerNode, - "TT_PostproductionNode": TT_PostproductionNode, - "TT_PostproductionAdvancedNode": TT_PostproductionAdvancedNode, - # Samplers - "TT_KSampler": TT_KSampler, - "TT_KSamplerAdvanced": TT_KSamplerAdvanced, - "TT_KSamplerContext": TT_KSamplerContext, - "TT_KSamplerTwoStage": TT_KSamplerTwoStage, - "TT_KSamplerGuided": TT_KSamplerGuided, - # Samplers V3 Nodes - "TT_KSamplerNode": TT_KSamplerNode, - "TT_KSamplerAdvancedNode": TT_KSamplerAdvancedNode, - "TT_KSamplerContextNode": TT_KSamplerContextNode, - "TT_KSamplerTwoStageNode": TT_KSamplerTwoStageNode, - "TT_GuidedKSamplerNode": TT_GuidedKSamplerNode, - "TT_GuidedUpscaleKSamplerNode": TT_GuidedUpscaleKSamplerNode, - # Text Encoder - "TT_ClipTextEncodeFlux": TT_ClipTextEncodeFlux, - "TT_ClipTextEncodeFluxContext": TT_ClipTextEncodeFluxContext, - "TT_ClipTextEncodeSdxl": TT_ClipTextEncodeSdxl, - "TT_ClipTextEncodeSdxlContext": TT_ClipTextEncodeSdxlContext, - "TT_ClipTextEncodeFlux2": TT_ClipTextEncodeFlux2, - "TT_ClipTextEncodeFlux2Context": TT_ClipTextEncodeFlux2Context, - # Text Encoder V3 Nodes - "TT_SdxlClipTextEncoderNode": TT_SdxlClipTextEncoderNode, - "TT_SdxlClipTextEncoderContextNode": TT_SdxlClipTextEncoderContextNode, - "TT_Flux1ClipTextEncoderNode": TT_Flux1ClipTextEncoderNode, - "TT_Flux1ClipTextEncoderContextNode": TT_Flux1ClipTextEncoderContextNode, - "TT_Flux2TextEncoderNode": TT_Flux2TextEncoderNode, - "TT_Flux2TextEncoderContextNode": TT_Flux2TextEncoderContextNode, - "TT_Sd35TextEncoderNode": TT_Sd35TextEncoderNode, - "TT_Sd35TextEncoderContextNode": TT_Sd35TextEncoderContextNode, - # VAE - "TT_VaeDecodeContext": TT_VaeDecodeContext, - "TT_VaeDecodeTiled": TT_VaeDecodeTiled, - "TT_VaeEncodeContext": TT_VaeEncodeContext, - "TT_VaeEncodeTiled": TT_VaeEncodeTiled, - # VAE V3 Nodes - "TT_VaeDecodeTiledNode": TT_VaeDecodeTiledNode, - "TT_VaeDecodeContextNode": TT_VaeDecodeContextNode, - "TT_VaeEncodeTiledNode": TT_VaeEncodeTiledNode, - "TT_VaeEncodeContextNode": TT_VaeEncodeContextNode, - # Workflow - "TT_FluxWorkflowSettings": TT_FluxWorkflowSettings, - "TT_FluxWorkflowSettingsAdvanced": TT_FluxWorkflowSettingsAdvanced, - "TT_SdxlWorkflowSettings": TT_SdxlWorkflowSettings, - "TT_SdxlWorkflowSettingsAdvanced": TT_SdxlWorkflowSettingsAdvanced, - "TT_Flux2WorkflowSettings": TT_Flux2WorkflowSettings, - "TT_Flux2WorkflowSettingsAdvanced": TT_Flux2WorkflowSettingsAdvanced, - # Workflow V3 Nodes - "TT_SdxlWorkflowSettingsNode": TT_SdxlWorkflowSettingsNode, - "TT_SdxlWorkflowSettingsAdvancedNode": TT_SdxlWorkflowSettingsAdvancedNode, - "TT_FluxWorkflowSettingsNode": TT_FluxWorkflowSettingsNode, - "TT_FluxWorkflowSettingsAdvancedNode": TT_FluxWorkflowSettingsAdvancedNode, - "TT_Flux2WorkflowSettingsNode": TT_Flux2WorkflowSettingsNode, - "TT_Flux2WorkflowSettingsAdvancedNode": TT_Flux2WorkflowSettingsAdvancedNode, - "TT_Sd35GgufWorkflowSettingsNode": TT_Sd35GgufWorkflowSettingsNode, - "TT_Sd35GgufWorkflowSettingsAdvancedNode": TT_Sd35GgufWorkflowSettingsAdvancedNode, -} - -NODE_DISPLAY_NAME_MAPPINGS = { - # Context Deprecated - "TT_BaseContext": "TT Base Context (Deprecated)", - "TT_Context": "TT Context (Deprecated)", - "TT_LargeContextFlux": "TT FLUX Large Context (Deprecated)", - "TT_LargeContextSdxl": "TT SDXL Large Context (Deprecated)", - "TT_EvenLargerContext": "TT Even Larger Context (Deprecated)", - "TT_ContextSetImage": "TT Context Set Image (Deprecated)", - "TT_ContextSetLatent": "TT Context Set Latent (Deprecated)", - "TT_ContextSetGuider": "TT Context Set Guider (Deprecated)", - "TT_ContextPassthrough": "TT Context Passthrough (Deprecated)", - # Context V3 Nodes - "TT_BaseContextNode": "TT Base Context", - "TT_BaseContextFlux2Node": "TT FLUX2 Base Context", - "TT_ContextPassthroughNode": "TT Context Passthrough", - "TT_ContextNode": "TT Context", - "TT_ContextFlux2Node": "TT FLUX2 Context", - "TT_ContextSetGuiderNode": "TT Context Set Guider", - "TT_ContextSetImageNode": "TT Context Set Image", - "TT_ContextSetLatentNode": "TT Context Set Latent", - "TT_ContextExtractEncoderFlux2Node": "TT Context Extract Encoder FLUX2", - "TT_ContextExtractGuidedSamplerFlux2Node": "TT Context Extract Guided Sampler Flux2", - "TT_ContextExtractVaeNode": "TT Context Extract VAE Flux2", - "TT_ContextExtractImageNode": "TT Context Extract Image Flux2", - # ControlNet V3 Nodes - "TT_Flux2ApplyControlNetNode": "TT Flux2 Apply ControlNet", - "TT_Flux2ApplyControlNetAdvancedNode": "TT FLUX2 Apply ControlNet (Advanced)", - # Detector V3 Nodes - "TT_CannyEdgeDetectorNode": "TT_Canny Edge Detector", - # Image - "TT_ImagePreviewSave": "TT Image Preview / Save (Deprecated)", - "TT_ImagePreviewUpscaleSave": "TT Image Preview / Upscale / Save (Deprecated)", - "TT_GuiderImageReference": "TT Guider Image Reference (Deprecated)", - # Image V3 Nodes - "TT_ImageLoaderResizerNode": "TT Image Loader / Resizer", - "TT_ImagePreviewSaveNode": "TT Image Preview / Save", - "TT_ImagePreviewUpscaleSaveNode": "TT Image Preview / Upscale / Save", - "TT_GuiderImageReferenceNode": "TT Guider Image Reference", - # Latent - "TT_LatentFactory": "TT Latent Factory (Deprecated)", - # Latent V3 Nodes - "TT_LatentFactoryNode": "TT Latent Factory", - "TT_LatentFactoryByModelNode": "TT Latent Factory (By Model)", - "TT_LatentMultiTransformNode": "TT Latent Multi Transform", - "TT_LatentMultiTransformOnPixelSpaceNode": "TT Latent MultiTransform (On Pixel Space)", - # Loaders - "TT_SdxlModelsLoader": "TT SDXL Models Loader", - "TT_SdxlModelsLoaderAdvanced": "TT SDXL Models Loader (Advanced)", - "TT_Flux2GgufModelsLoader": "TT FLUX2 GGUF Models Loader", - "TT_Flux2GgufModelsLoaderAdvanced": "TT FLUX2 GGUF Models Loader (Advanced)", - "TT_FluxModelsLoader": "TT FLUX Models Loader", - "TT_FluxModelsLoaderAdvanced": "TT FLUX Models Loader (Advanced)", - # Loaders V3 Nodes - "TT_SdxlModelsLoaderNode": "TT SDXL Models Loader", - "TT_SdxlModelsLoaderAdvancedNode": "TT SDXL Models Loader (Advanced)", - "TT_FluxModelsLoaderNode": "TT FLUX Models Loader", - "TT_FluxModelsLoaderAdvancedNode": "TT FLUX Models Loader (Advanced)", - "TT_Flux2GgufModelsLoaderNode": "TT FLUX2 GGUF Models Loader", - "TT_Flux2GgufModelsLoaderAdvancedNode": "TT FLUX2 GGUF Models Loader (Advanced)", - "TT_Sd35GgufModelsLoaderNode": "TT SD3.5 GGUF Models Loader", - "TT_Sd35GgufModelsLoaderAdvancedNode": "TT SD3.5 GGUF Models Loader (Advanced)", - # Postproduction - "TT_ApplyLut": "TT Apply LUT", - "TT_AddFilmGrain": "TT Add Film Grain", - "TT_QuickImageUpscaler": "TT Quick Image Upscaler", - "TT_ImageEnhancer": "TT Image Enhancer", - "TT_Postproduction": "TT Postproduction", - "TT_PostproductionAdvanced": "TT Postproduction (Advanced)", - # Postproduction V3 Nodes - "TT_AddFilmGrainNode": "TT Add Film Grain", - "TT_ApplyLutNode": "TT Apply LUT", - "TT_ImageEnhancerNode": "TT Image Enhancer", - "TT_QuickImageUpscalerNode": "TT Quick Image Upscaler", - "TT_PostproductionNode": "TT Postproduction", - "TT_PostproductionAdvancedNode": "TT Postproduction (Advanced)", - # Samplers - "TT_KSampler": "TT KSampler", - "TT_KSamplerAdvanced": "TT KSampler (Advanced)", - "TT_KSamplerContext": "TT KSampler (Context)", - "TT_KSamplerTwoStage": "TT KSampler (Two Stages)", - "TT_KSamplerGuided": "TT KSampler (Guided)", - # Samplers V3 Nodes - "TT_KSamplerNode": "TT KSampler", - "TT_KSamplerAdvancedNode": "TT KSampler (Advanced)", - "TT_KSamplerContextNode": "TT KSampler (Context)", - "TT_KSamplerTwoStageNode": "TT KSampler (Two Stage)", - "TT_GuidedKSamplerNode": "TT Guided KSampler", - "TT_GuidedUpscaleKSamplerNode": "TT Guided Upscale KSampler", - # Text Encoder - "TT_ClipTextEncodeFlux": "TT CLIP Text Encode FLUX", - "TT_ClipTextEncodeFluxContext": "TT CLIP Text Encode FLUX (Context)", - "TT_ClipTextEncodeSdxl": "TT CLIP Text Encode SDXL", - "TT_ClipTextEncodeSdxlContext": "TT CLIP Text Encode SDXL (Context)", - "TT_ClipTextEncodeFlux2": "TT CLIP Text Encode FLUX2", - "TT_ClipTextEncodeFlux2Context": "TT CLIP Text Encode FLUX2 (Context)", - # Text Encoder V3 Nodes - "TT_SdxlClipTextEncoderNode": "TT SDXL CLIP Text Encoder", - "TT_SdxlClipTextEncoderContextNode": "TT SDXL CLIP Text Encoder (Context)", - "TT_Flux1ClipTextEncoderNode": "TT FLUX1 CLIP Text Encoder", - "TT_Flux1ClipTextEncoderContextNode": "TT FLUX1 CLIP Text Encoder (Context)", - "TT_Flux2TextEncoderNode": "TT FLUX2 Text Encoder", - "TT_Flux2TextEncoderContextNode": "TT FLUX2 Text Encoder (Context)", - "TT_Sd35TextEncoderNode": "TT SD3.5 Text Encoder", - "TT_Sd35TextEncoderContextNode": "TT SD3.5 Text Encoder (Context)", - # VAE - "TT_VaeDecodeContext": "TT VAE Decode (Context)", - "TT_VaeDecodeTiled": "TT VAE Decode (Tiled)", - "TT_VaeEncodeContext": "TT Vae Encode (Context)", - "TT_VaeEncodeTiled": "TT Vae Encode (Tiled)", - # VAE V3 Nodes - "TT_VaeDecodeTiledNode": "TT Vae Decode (Tiled)", - "TT_VaeDecodeContextNode": "TT Vae Decode (Context)", - "TT_VaeEncodeTiledNode": "TT Vae Encode (Tiled)", - "TT_VaeEncodeContextNode": "TT Vae Encode (Context)", - # Workflow - "TT_FluxWorkflowSettings": "TT FLUX Workflow Settings", - "TT_FluxWorkflowSettingsAdvanced": "TT FLUX Workflow Settings (Advanced)", - "TT_SdxlWorkflowSettings": "TT SDXL Workflow Settings", - "TT_SdxlWorkflowSettingsAdvanced": "TT SDXL Workflow Settings (Advanced)", - "TT_Flux2WorkflowSettings": "TT FLUX2 Workflow Settings (Deprecated)", - "TT_Flux2WorkflowSettingsAdvanced": "TT FLUX2 Workflow Settings (Deprecated/Advanced)", - # Workflow V3 Nodes - "TT_SdxlWorkflowSettingsNode": "TT SDXL Workflow Settings", - "TT_SdxlWorkflowSettingsAdvancedNode": "TT SDXL Workflow Settings (Advanced)", - "TT_FluxWorkflowSettingsNode": "TT FLUX Workflow Settings", - "TT_FluxWorkflowSettingsAdvancedNode": "TT FLUX Workflow Settings (Advanced)", - "TT_Flux2WorkflowSettingsNode": "TT FLUX2 Workflow Settings", - "TT_Flux2WorkflowSettingsAdvancedNode": "TT FLUX2 Workflow Settings (Advanced)", - "TT_Sd35WorkflowSettingsNode": "TT SD3.5 Workflow Settings", - "TT_Sd35WorkflowSettingsAdvancedNode": "TT SD3.5 Workflow Settings (Advanced)", -} diff --git a/nodes/context/base_context.py b/nodes/context/base_context.py deleted file mode 100644 index 1f0ea86..0000000 --- a/nodes/context/base_context.py +++ /dev/null @@ -1,24 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import create_context_schema - - -class TT_BaseContext: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("base") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, workflow_config, model, clip, vae, latent): - context = { - "workflow_config": workflow_config, - "model": model, - "clip": clip, - "vae": vae, - "latent": latent, - } - - return (context,) diff --git a/nodes/context/context.py b/nodes/context/context.py deleted file mode 100644 index f5f0a87..0000000 --- a/nodes/context/context.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import (build_return_tuple, create_context_schema, init_context) - - -class TT_Context: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("standard") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context=None, **kwargs): - args = init_context(context, **kwargs) - - return build_return_tuple("standard", args) diff --git a/nodes/context/context_helpers.py b/nodes/context/context_helpers.py deleted file mode 100644 index ca249bc..0000000 --- a/nodes/context/context_helpers.py +++ /dev/null @@ -1,334 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - -CONTEXT_FIELDS = [ - # input_name, return_name, field_type - ("context", "CONTEXT", "TT_CONTEXT",), - ("model", "MODEL", "MODEL",), - ("clip", "CLIP", "CLIP",), - ("vae", "VAE", "VAE",), - ("latent", "LATENT", "LATENT",), - ("positive", "POSITIVE", "CONDITIONING"), - ("negative", "NEGATIVE", "CONDITIONING"), - ("image", "IMAGE", "IMAGE"), - ("mask", "MASK", "MASK"), - ("guider", "GUIDER", "GUIDER"), - ("control_net", "CONTROL_NET", "CONTROL_NET"), - ("workflow_config", "WORKFLOW_CONFIG", "TT_WORKFLOW_CONFIG",), - ("seed", "SEED", "INT"), - ("steps", "STEPS", "INT"), - ("cfg", "CFG", "FLOAT"), - ("sampler_name", "SAMPLER_NAME", S.KSampler.SAMPLERS), - ("sampler", "SAMPLER", "SAMPLER"), - ("scheduler", "SCHEDULER", S.KSampler.SCHEDULERS), - ("guidance", "GUIDANCE", "FLOAT"), - ("prompt", "PROMPT", "STRING"), - ("lora_triggers", "LORA_TRIGGERS", "STRING"), - ("clip_l_positive", "CLIP_L_POSITIVE", "STRING"), - ("clip_g_positive", "CLIP_L_POSITIVE", "STRING"), - ("t5xxl_positive", "T5XXL_POSITIVE", "STRING"), - ("clip_l_negative", "CLIP_L_NEGATIVE", "STRING"), - ("clip_g_negative", "CLIP_L_NEGATIVE", "STRING"), - ("t5xxl_negative", "T5XXL_NEGATIVE", "STRING"), - ("ascore_positive", "ASCORE_POSITIVE", "FLOAT"), - ("ascore_negative", "ASCORE_NEGATIVE", "FLOAT"), - ("width", "WIDTH", "INT"), - ("height", "HEIGHT", "INT"), - ("target_width", "TARGET_WIDTH", "INT"), - ("target_height", "TARGET_HEIGHT", "INT"), -] - -CONTEXTS = { - "base": { - "required": ( - "model", - "clip", - "vae", - "latent", - ), - "optional": ( - "workflow_config", - ), - "return": ( - "context", - ) - }, - "standard": { - "optional": ( - "context", - "workflow_config", - "model", - "clip", - "vae", - "positive", - "negative", - "latent", - "image", - "seed", - "steps", - "cfg", - "sampler_name", - "scheduler", - ) - }, - "big_flux": { - "optional": ( - "context", - "workflow_config", - "model", - "clip", - "vae", - "positive", - "negative", - "latent", - "image", - "seed", - "steps", - "cfg", - "sampler_name", - "scheduler", - "guidance", - "clip_l_positive", - "t5xxl_positive", - "clip_l_negative", - "t5xxl_negative", - "width", - "height", - ) - }, - "big_flux2": { - "optional": ( - "context", - "workflow_config", - "model", - "clip", - "vae", - "latent", - "image", - "seed", - "steps", - "cfg", - "sampler_name", - "sampler", - "scheduler", - "guidance", - "prompt", - "lora_triggers", - "width", - "height", - ) - }, - "big_sdxl": { - "optional": ( - "context", - "workflow_config", - "model", - "clip", - "vae", - "positive", - "negative", - "latent", - "image", - "seed", - "steps", - "cfg", - "sampler_name", - "scheduler", - "guidance", - "clip_l_positive", - "clip_g_positive", - "clip_l_negative", - "clip_g_negative", - "ascore_positive", - "ascore_negative", - "width", - "height", - "target_width", - "target_height", - ) - }, - "huge": { - "optional": tuple(f[0] for f in CONTEXT_FIELDS) - }, - "passthrough": { - "required": ( - "context", - ) - }, - "set_image": { - "required": ( - "context", - "image", - ), - "return": ( - "context", - ) - }, - "set_latent": { - "required": ( - "context", - "latent", - ), - "return": ( - "context", - ) - }, - "set_guider": { - "required": ( - "context", - "guider", - ), - "return": ( - "context", - ) - }, -} - -FORCE_INPUT_TYPES = { - "INT", - "FLOAT", - "STRING", - "BOOLEAN", -} - -WORKFOW_SETTINGS_KEYS = [ - "seed", - "steps", - "cfg", - "sampler_name", - "sampler", - "scheduler", - "pos_a_score", - "clip_l_positive", - "clip_g_positive", - "t5xxl_positive", - "neg_a_score", - "clip_l_negative", - "clip_g_negative", - "t5xxl_negative", - "guidance", - "ascore_positive", - "ascore_negative", - "width", - "height", - "target_width", - "target_height", -] - - -def _get_field_map(): - return {field[0]: (field[1], field[2]) for field in CONTEXT_FIELDS} - - -def _get_input_types(field_map, fields): - retval = {} - for field_name in fields: - field_type = field_map[field_name][1] - - if isinstance(field_type, (list, tuple)) or field_type in FORCE_INPUT_TYPES: - retval[field_name] = (field_type, {"forceInput": True}) - else: - retval[field_name] = (field_type,) - - return retval - - -def _get_input_schema(context_name): - context_def = CONTEXTS[context_name] - field_map = _get_field_map() - - input_types = { - "required": _get_input_types(field_map, context_def.get("required", ())), - "optional": _get_input_types(field_map, context_def.get("optional", ())) - } - - return input_types - - -def _get_return_fields(context_name): - context_def = CONTEXTS[context_name] - - if "return" in context_def: - return context_def.get("return", ()) - else: - return context_def.get("required", ()) + context_def.get("optional", ()) - - -def _get_return_schema(context_name): - field_map = _get_field_map() - return_fields = _get_return_fields(context_name) - - return_types = tuple(field_map[field][1] for field in return_fields) - return_names = tuple(field_map[field][0] for field in return_fields) - - return return_types, return_names - - -def create_context_schema(context_name): - input_types = _get_input_schema(context_name) - return_types, return_names = _get_return_schema(context_name) - - return input_types, return_types, return_names - - -def init_context(context, **kwargs): - field_map = _get_field_map() - retval = {} - - workflow_config = kwargs.get("workflow_config", None) - - if workflow_config is None and context and "workflow_config" in context: - workflow_config = context["workflow_config"] - - if workflow_config: - for key in WORKFOW_SETTINGS_KEYS: - if key in workflow_config: - retval[key] = workflow_config[key] - - for idx in field_map: - if idx == "context": - continue - - if idx in WORKFOW_SETTINGS_KEYS and idx in retval: - val = kwargs.get(idx, None) - if val is not None: - retval[idx] = val - continue - - val = kwargs[idx] if idx in kwargs else None - if val is not None: - retval[idx] = val - elif context and idx in context: - retval[idx] = context[idx] - else: - retval[idx] = None - - if any(k in retval for k in WORKFOW_SETTINGS_KEYS): - retval["workflow_config"] = { - "seed": retval.get("seed"), - "steps": retval.get("steps"), - "cfg": retval.get("cfg"), - "sampler_name": retval.get("sampler_name"), - "scheduler": retval.get("scheduler"), - "clip_l_positive": retval.get("clip_l_positive"), - "clip_g_positive": retval.get("clip_g_positive"), - "t5xxl_positive": retval.get("t5xxl_positive"), - "clip_l_negative": retval.get("clip_l_negative"), - "clip_g_negative": retval.get("clip_g_negative"), - "t5xxl_negative": retval.get("t5xxl_negative"), - "guidance": retval.get("guidance"), - "ascore_positive": retval.get("ascore_positive"), - "ascore_negative": retval.get("ascore_negative"), - "target_width": retval.get("target_width"), - "target_height": retval.get("target_height"), - } - else: - retval["workflow_config"] = workflow_config - - return retval - - -def build_return_tuple(context_name, args): - context_fields = _get_return_fields(context_name) - return tuple([args] + [args.get(field) for field in context_fields if field != "context"]) diff --git a/nodes/context/context_passthrough.py b/nodes/context/context_passthrough.py deleted file mode 100644 index f04dfe0..0000000 --- a/nodes/context/context_passthrough.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import (build_return_tuple, create_context_schema, init_context) - - -class TT_ContextPassthrough: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("passthrough") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context=None, **kwargs): - args = init_context(context, **kwargs) - - return build_return_tuple("passthrough", args) diff --git a/nodes/context/context_set_guider.py b/nodes/context/context_set_guider.py deleted file mode 100644 index 68cc884..0000000 --- a/nodes/context/context_set_guider.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import create_context_schema - - -class TT_ContextSetGuider: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("set_guider") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context, guider): - context["guider"] = guider - - return (context,) diff --git a/nodes/context/context_set_image.py b/nodes/context/context_set_image.py deleted file mode 100644 index f5993ef..0000000 --- a/nodes/context/context_set_image.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import create_context_schema - - -class TT_ContextSetImage: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("set_image") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context, image): - context["image"] = image - - return (context,) diff --git a/nodes/context/context_set_latent.py b/nodes/context/context_set_latent.py deleted file mode 100644 index 759d7a7..0000000 --- a/nodes/context/context_set_latent.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import create_context_schema - - -class TT_ContextSetLatent: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("set_latent") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context, latent): - context["latent"] = latent - - return (context,) diff --git a/nodes/context/even_larger_context.py b/nodes/context/even_larger_context.py deleted file mode 100644 index a0e5299..0000000 --- a/nodes/context/even_larger_context.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import (build_return_tuple, create_context_schema, init_context) - - -class TT_EvenLargerContext: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("huge") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context=None, **kwargs): - args = init_context(context, **kwargs) - - return build_return_tuple("huge", args) diff --git a/nodes/context/large_context_flux.py b/nodes/context/large_context_flux.py deleted file mode 100644 index bf72690..0000000 --- a/nodes/context/large_context_flux.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import (build_return_tuple, create_context_schema, init_context) - - -class TT_LargeContextFlux: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("big_flux") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context=None, **kwargs): - args = init_context(context, **kwargs) - - return build_return_tuple("big_flux", args) diff --git a/nodes/context/large_context_sdxl.py b/nodes/context/large_context_sdxl.py deleted file mode 100644 index c46375a..0000000 --- a/nodes/context/large_context_sdxl.py +++ /dev/null @@ -1,18 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .context_helpers import (build_return_tuple, create_context_schema, init_context) - - -class TT_LargeContextSdxl: - INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("big_sdxl") - FUNCTION = "process_context" - CATEGORY = "TenserTensor/Deprecated/Context" - - @classmethod - def INPUT_TYPES(cls): - return cls.INPUT_TYPES_DICT - - def process_context(self, context=None, **kwargs): - args = init_context(context, **kwargs) - - return build_return_tuple("big_sdxl", args) diff --git a/nodes/image/guider_image_reference.py b/nodes/image/guider_image_reference.py deleted file mode 100644 index cb064e8..0000000 --- a/nodes/image/guider_image_reference.py +++ /dev/null @@ -1,58 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import os - -import folder_paths as FP -from node_helpers import conditioning_set_values - -from ..image.image_helpers import load_image, resize_image_to_megapixels -from ...lib.common import CommonTypes - -UPSCALE_METHODS = ["nearest-exact", "bilinear", "area", "bicubic", "lanczos"] -TILE_SIZE, OVERLAP = 512, 64 - - -class TT_GuiderImageReference(): - @classmethod - def INPUT_TYPES(cls): - input_dir = FP.get_input_directory() - files = FP.filter_files_content_types( - [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))], ["image"] - ) - - return { - "required": { - "vae": ("VAE",), - "guider": ("GUIDER",), - "megapixels": (CommonTypes.MEGAPIXELS,), - "upscale_method": (UPSCALE_METHODS, {"default": "bicubic", "advanced": True}), - "dimension_step": ("INT", {"default": 1, "min": 1, "max": 10000, "advanced": True}), - "image": (sorted(files), {"image_upload": True}), - }, - } - - RETURN_TYPES = ("VAE", "GUIDER",) - RETURN_NAMES = ("VAE", "GUIDER",) - FUNCTION = "update_latent" - CATEGORY = "TenserTensor/Deprecated/Image" - - def update_latent(self, vae, guider, megapixels, upscale_method, dimension_step, image): - timage, _ = load_image(image) - scaled = resize_image_to_megapixels(timage, upscale_method, megapixels, dimension_step) - - samples = vae.encode_tiled( - scaled, - tile_x=TILE_SIZE, - tile_y=TILE_SIZE, - overlap=OVERLAP - ) - - conditioning = guider.get_conds() - - if conditioning is not None: - conditioning = conditioning_set_values(conditioning, {"reference_latents": [samples]}, append=True) - guider.set_conds(conditioning) - else: - raise ValueError("ERROR: Guider has no conditioning") - - return (vae, guider,) diff --git a/nodes/image/image_helpers.py b/nodes/image/image_helpers.py deleted file mode 100644 index 16bc8fe..0000000 --- a/nodes/image/image_helpers.py +++ /dev/null @@ -1,197 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import fnmatch -import math -import os -import random -import string as S -from datetime import datetime - -import folder_paths as FP -import numpy -import numpy as NP -import torch -from PIL import Image, ImageOps, ImageSequence -from comfy import model_management as MM -from comfy import utils as U -from node_helpers import pillow - -FORMAT_EXT = { - "PNG": ".png", - "JPEG": ".jpg", - "WEBP": ".webp", -} - - -class InvalidSavePathError(Exception): - pass - - -def _build_filename(save_path, filename_mask): - count = sum(1 for f in os.scandir(save_path) if fnmatch.fnmatch(f.name, filename_mask)) + 1 - - return filename_mask.replace("*", f"{count:05}") - - -def _build_save_path(output_path, subfolder, filename_prefix, filename_format, image_format): - save_path = os.path.join(output_path, subfolder) - if os.path.commonpath((output_path, os.path.abspath(save_path))) != output_path: - raise InvalidSavePathError("Saving image outside the output folder is not allowed.") - - os.makedirs(save_path, exist_ok=True) - - ext = FORMAT_EXT[image_format] - - filename = "" - match filename_format: - case "name-###": - filename = _build_filename(save_path, f"{filename_prefix}-*{ext}") - case "date-name-###": - date = datetime.now().strftime("%Y-%m-%d") - filename = _build_filename(save_path, f"{date}-{filename_prefix}-*{ext}") - case "name-datetime": - timestamp = datetime.now().strftime("%Y%m%d-%H%M%S") - filename = f"{filename_prefix}-{timestamp}{ext}" - case _: - filename = f"{filename_prefix}{ext}" - - return save_path, filename - - -def _store_image( - images, - filename_prefix, - output_path, - subfolder, - filename_format, - image_format, - quality, - compress_level -): - retval = list() - for image in images: - img_np = 255. * image.cpu().numpy() - timage = Image.fromarray(NP.clip(img_np, 0, 255).astype(NP.uint8)) - save_path, filename = _build_save_path( - output_path, subfolder, filename_prefix, filename_format, image_format - ) - params = {"compress_level": compress_level} if image_format == "PNG" else {"quality": quality} - timage.save(os.path.join(save_path, filename), format=image_format, **params) - - retval.append({ - "filename": filename, - "subfolder": subfolder, - "type": "temp" if filename_prefix.startswith("tmp") else "output" - }) - - return retval - - -def store( - image, - filename_prefix, - filename_format, - subfolder, - image_format, - image_quality, - compress_level -): - output_folder = FP.get_output_directory() - - return _store_image( - images=image, - filename_prefix=filename_prefix, - output_path=output_folder, - subfolder=subfolder, - filename_format=filename_format, - image_format=image_format, - quality=image_quality, - compress_level=compress_level - ) - - -def preview(image, filename_prefix): - temp_dir = FP.get_temp_directory() - rand = "".join(random.choices(S.ascii_lowercase, k=5)) - prefix = f"tmp-{filename_prefix}-{rand}" - - return _store_image( - images=image, - filename_prefix=prefix, - output_path=temp_dir, - ) - - -def load_image(image_filename, device=None): - tdevice = MM.get_torch_device() if device == None else torch.device("cpu") - - image_path = FP.get_annotated_filepath(image_filename) - pil_image = pillow(Image.open, image_path) - - images, masks = [], [] - width, height = None, None - - for frame in ImageSequence.Iterator(pil_image): - pil_frame = pillow(ImageOps.exif_transpose, frame) - - if pil_frame.mode == "I": - pil_frame = pil_frame.point(lambda i: i * (1 / 255)) - - if len(images) == 0: - width, height = pil_frame.size - - if pil_frame.size != (width, height,): - continue - - alpha = numpy.zeros((height, width,), dtype=numpy.float32) - if 'A' in pil_frame.getbands(): - alpha = numpy.array(pil_frame.getchannel('A'), dtype=numpy.float32) / 255.0 - elif pil_frame.mode == 'P' and 'transparency' in pil_frame.info: - alpha = numpy.array(pil_frame.convert('RGBA').getchannel('A'), dtype=numpy.float32) / 255.0 - - tmask = torch.from_numpy(1.0 - alpha).to(tdevice) - - rgb_frame = pil_frame.convert("RGB") - np_image = numpy.array(rgb_frame, dtype=numpy.float32) / 255.0 - timage = torch.from_numpy(np_image)[None].to(tdevice) - - images.append(timage) - masks.append(tmask) - - if pil_image.format == "MPO": - break - - if len(images) == 0: - raise ValueError(f"ERROR: No frames found in {image_path}") - - oimage = torch.cat(images, dim=0) if len(images) > 1 else images[0] - omask = torch.cat(masks, dim=0) if len(masks) > 1 else masks[0] - - return oimage, omask - - -def _align_to_step(size, scale_factor, dimension_step): - return round(size * scale_factor / dimension_step) * dimension_step - - -# crop = "center" / "disabled" -def resize_image(timage, to_width, to_height, upscale_method, dimension_step=1, crop="disabled"): - samples = timage.movedim(-1, 1) - orig_height, orig_width = samples.shape[2:] - scale_factor = max(to_width / orig_width, to_height / orig_height) - to_width = _align_to_step(orig_width, scale_factor, dimension_step) - to_height = _align_to_step(orig_height, scale_factor, dimension_step) - - return U.common_upscale(samples, int(to_width), int(to_height), upscale_method, crop).movedim(1, -1) - - -def resize_image_to_megapixels(timage, upscale_method, megapixels, dimension_step=1): - mp_value = float(megapixels.split()[0]) - total_pixels = int(mp_value * 1_000_000) - samples = timage.movedim(-1, 1) - orig_height, orig_width = samples.shape[2:] - scale_factor = math.sqrt(total_pixels / (orig_width * orig_height)) - to_width = _align_to_step(orig_width, scale_factor, dimension_step) - to_height = _align_to_step(orig_height, scale_factor, dimension_step) - - return U.common_upscale(samples, int(to_width), int(to_height), upscale_method, "disabled").movedim(1, -1) diff --git a/nodes/image/image_preview_save.py b/nodes/image/image_preview_save.py deleted file mode 100644 index 55eadaf..0000000 --- a/nodes/image/image_preview_save.py +++ /dev/null @@ -1,55 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .image_helpers import store, preview - - -class TT_ImagePreviewSave(): - @classmethod - def INPUT_TYPES(cls): - FILENAME_FORMATS = ["name-###", "date-name-###", "name-datetime"] - IMAGE_FORMATS = ["PNG", "JPEG", "WEBP"] - - return { - "required": { - "image": ("IMAGE",), - "save_image": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "filename_prefix": ("STRING", {"default": "tenser-tensor"}), - "filename_format": (FILENAME_FORMATS, {"default": "name-###", "advanced": True}), - "subfolder": ("STRING", {"default": "", "advanced": True}), - "image_format": (IMAGE_FORMATS, {"default": "PNG", "advanced": True}), - "image_quality": ("INT", {"default": 100, "min": 0, "max": 100, "advanced": True}), - "compression_level": ("INT", {"default": 9, "min": 0, "max": 9, "advanced": True}), - } - } - - RETURN_TYPES = () - RETURN_NAMES = () - OUTPUT_NODE = True - FUNCTION = "preview_save_image" - CATEGORY = "TenserTensor/Deprecated/Image" - - def preview_save_image( - self, - image, - save_image, - filename_prefix, - filename_format, - subfolder, - image_format, - image_quality, - compression_level - ): - if save_image: - retval = store( - image, - filename_prefix, - filename_format, - subfolder, - image_format, - image_quality, - compression_level - ) - else: - retval = preview(image, filename_prefix) - - return {"ui": {"images": retval}} diff --git a/nodes/image/image_preview_upscale_save.py b/nodes/image/image_preview_upscale_save.py deleted file mode 100644 index 519c500..0000000 --- a/nodes/image/image_preview_upscale_save.py +++ /dev/null @@ -1,71 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) -import folder_paths as FP - -from .image_helpers import store, preview -from ..postproduction.postproduction_helpers import upscale_image as upscale - - -class TT_ImagePreviewUpscaleSave(): - @classmethod - def INPUT_TYPES(cls): - FILENAME_FORMATS = ["name-###", "date-name-###", "name-datetime"] - IMAGE_FORMATS = ["PNG", "JPEG", "WEBP"] - DEVICES = ["default", "cpu"] - UPSCALE_MODELS = FP.get_filename_list("upscale_models") - - return { - "required": { - "image": ("IMAGE",), - "save_image": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "filename_prefix": ("STRING", {"default": "tenser-tensor"}), - "filename_format": (FILENAME_FORMATS, {"advanced": True, "default": "name-###"}), - "subfolder": ("STRING", {"default": "", "advanced": True}), - "image_format": (IMAGE_FORMATS, {"advanced": True, "default": "PNG"}), - "image_quality": ("INT", {"default": 100, "min": 0, "max": 100, "advanced": True}), - "compression_level": ("INT", {"default": 9, "min": 0, "max": 9, "advanced": True}), - "upscale_image": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "upscaler_device": (DEVICES, {"advanced": True}), - "upscale_model_name": (UPSCALE_MODELS, {"advanced": True}), - "tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64, "advanced": True}), - "overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8, "advanced": True}), - } - } - - RETURN_TYPES = () - RETURN_NAMES = () - OUTPUT_NODE = True - FUNCTION = "preview_upscale_save_image" - CATEGORY = "TenserTensor/Deprecated/Image" - - def preview_upscale_save_image(self, **kwargs): - image = kwargs.get("image") - timage = image.clone() - - upscale_image = kwargs.get("upscale_image") - if upscale_image: - timage = upscale( - timage=timage, - device=kwargs.get("upscaler_device"), - upscale_model_name=kwargs.get("upscale_model_name"), - tile=kwargs.get("tile"), - overlap=kwargs.get("overlap") - ) - - save_image = kwargs.get("save_image") - if save_image: - timage = store( - image=timage, - filename_prefix=kwargs.get("filename_prefix"), - subfolder=kwargs.get("subfolder"), - filename_format=kwargs.get("filename_format"), - image_format=kwargs.get("image_format"), - image_quality=kwargs.get("image_quality"), - compress_level=kwargs.get("compression_level"), - ) - else: - timage = preview( - image=timage, - filename_prefix=kwargs.get("filename_prefix"), - ) - - return {"ui": {"images": timage}} diff --git a/nodes/latent/latent_factory.py b/nodes/latent/latent_factory.py deleted file mode 100644 index 2c461a5..0000000 --- a/nodes/latent/latent_factory.py +++ /dev/null @@ -1,34 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .latent_helpers import create_empty_latent -from ...lib.common import CommonTypes - -ASPECT_RATIOS = ["1:1", "4:3", "3:2", "16:9", "21:9"] -ORIENTATIONS = ["landscape", "portrait"] -MODEL_TYPES = ["FLUX1.D", "FLUX2.D", "SDXL"] -CLIP_MULTIPLIERS = ["1x", "2x", "4x"] - - -class TT_LatentFactory: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff},), - "noise_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff},), - "aspect_ratio": (ASPECT_RATIOS,), - "megapixels": (CommonTypes.MEGAPIXELS,), - "orientation": (ORIENTATIONS,), - "model_type": (MODEL_TYPES,), - "batch_size": ("INT", {"default": 1, "min": 1, "max": 64, "advanced": True},), - "clip_multiplier": (CLIP_MULTIPLIERS, {"advanced": True},) - } - } - - RETURN_TYPES = ("LATENT", "NOISE", "INT", "INT", CommonTypes.MEGAPIXELS, "INT", "INT", "INT", "INT") - RETURN_NAMES = ("LATENT", "RANDOM_NOISE", "SEED", "NOISE_SEED", "MEGAPIXELS", "WIDTH", "HEIGHT", "TARGET_WIDTH", "TARGET_HEIGHT") - FUNCTION = "create_latent" - CATEGORY = "TenserTensor/Deprecated/Latent" - - def create_latent(self, **kwargs): - return create_empty_latent(**kwargs) diff --git a/nodes/latent/latent_helpers.py b/nodes/latent/latent_helpers.py deleted file mode 100644 index ef2b3e8..0000000 --- a/nodes/latent/latent_helpers.py +++ /dev/null @@ -1,89 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import math - -import torch - -import comfy.sample as S - - -class RandomNoise: - def __init__(self, seed): - self.seed = seed - - def generate_noise(self, input_latent): - latent_image = input_latent["samples"] - batch_idx = input_latent["batch_index"] if "batch_index" in input_latent else None - return S.prepare_noise(latent_image, self.seed, batch_idx) - - -LATENT_DIMENSION_STEP = 64 - - -def _calculate_dimensions(total_pixels, ratio_w, ratio_h): - height = math.sqrt(total_pixels * ratio_h / ratio_w) - width = height * ratio_w / ratio_h - width = int(width) - height = int(height) - width = round(width / LATENT_DIMENSION_STEP) * LATENT_DIMENSION_STEP - height = round(height / LATENT_DIMENSION_STEP) * LATENT_DIMENSION_STEP - - return width, height - - -def create_empty_latent(seed, noise_seed, aspect_ratio, megapixels, orientation, model_type, batch_size, clip_multiplier): - mp_value = float(megapixels.split()[0]) - total_pixels = int(mp_value * 1_000_000) - - ratio_parts = aspect_ratio.split(':') - ratio_w = int(ratio_parts[0]) - ratio_h = int(ratio_parts[1]) - - if orientation == "portrait": - ratio_w, ratio_h = ratio_h, ratio_w - - width, height = _calculate_dimensions(total_pixels, ratio_w, ratio_h) - - multiplier = int(clip_multiplier.replace('x', '')) - clip_width = width * multiplier - clip_height = height * multiplier - - match model_type: - case "FLUX1.D": - scale_factor, channels = 8, 16 - case "FLUX2.D": - scale_factor, channels = 16, 128 - case "SDXL": - scale_factor, channels = 8, 4 - - latent_width = width // scale_factor - latent_height = height // scale_factor - - generator = torch.Generator().manual_seed(seed) - latent = torch.randn( - batch_size, - channels, - latent_height, - latent_width, - generator=generator - ) - - latent_dict = {"samples": latent} - noise = RandomNoise(noise_seed) - - return (latent_dict, noise, seed, noise_seed, megapixels, width, height, clip_width, clip_height,) - - -def vae_encode(latent, image, vae): - tile_width, tile_height, overlap = 512, 512, 64 - - samples = vae.encode_tiled( - image, - tile_x=tile_width, - tile_y=tile_height, - overlap=overlap - ) - - latent["samples"] = samples - - return (latent,) diff --git a/nodes/loaders/flux_models_loader.py b/nodes/loaders/flux_models_loader.py deleted file mode 100644 index c24f98d..0000000 --- a/nodes/loaders/flux_models_loader.py +++ /dev/null @@ -1,39 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from folder_paths import get_filename_list - -from nodes import VAELoader -from .loader_helpers import load_unet, load_flux_clip, load_vae - - -class TT_FluxModelsLoader(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "unet_name": (get_filename_list("diffusion_models"),), - "clip_l": (get_filename_list("text_encoders"),), - "t5xxl": (get_filename_list("text_encoders"),), - "clip_device": (["default", "cpu"], {"advanced": True}), - "vae_name": (VAELoader.vae_list(VAELoader),) - } - } - - RETURN_TYPES = ("MODEL", "CLIP", "VAE",) - RETURN_NAMES = ("MODEL", "CLIP", "VAE",) - FUNCTION = "load_models" - CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX" - - def load_models( - self, - unet_name, - clip_l, - t5xxl, - clip_device, - vae_name - ): - model = load_unet(unet_name) - clip = load_flux_clip(clip_l, t5xxl, clip_device) - vae = load_vae(vae_name, "cpu", "bfloat16") - - return (model, clip, vae,) diff --git a/nodes/loaders/flux_models_loader_advanced.py b/nodes/loaders/flux_models_loader_advanced.py deleted file mode 100644 index f61de49..0000000 --- a/nodes/loaders/flux_models_loader_advanced.py +++ /dev/null @@ -1,90 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from folder_paths import get_filename_list - -from nodes import VAELoader, MAX_RESOLUTION -from .loader_helpers import load_unet, patch_flux_sampling, load_flux_clip, apply_lora, load_vae - - -class TT_FluxModelsLoaderAdvanced(): - def __init__(self): - self.loaded_lora_1 = None - self.loaded_lora_2 = None - self.loaded_lora_3 = None - self.loaded_lora_4 = None - - @classmethod - def INPUT_TYPES(cls): - UNET_DTYPES = ["default", "fp8_e4m3fn", "fp8_e4m3fn_fast", "fp8_e5m2"] - DEVICES = ["default", "cpu"] - VAE_DTYPES = ["bfloat16", "float16", "float32"] - - return { - "required": { - "unet_name": (get_filename_list("diffusion_models"),), - "unet_dtype": (UNET_DTYPES, {"advanced": True}), - "apply_sampling": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "base_sampling_shift": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 100.0, "step": 0.01}), - "max_sampling_shift": ("FLOAT", {"default": 1.15, "min": 0.0, "max": 100.0, "step": 0.01}), - "sampling_width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}), - "sampling_height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}), - "clip_l": (get_filename_list("text_encoders"),), - "t5xxl": (get_filename_list("text_encoders"),), - "clip_device": (["default", "cpu"], {"advanced": True}), - "lora_name_1": (["None"] + get_filename_list("loras"),), - "strength_1": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "lora_name_2": (["None"] + get_filename_list("loras"),), - "strength_2": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "lora_name_3": (["None"] + get_filename_list("loras"),), - "strength_3": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "lora_name_4": (["None"] + get_filename_list("loras"),), - "strength_4": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "vae_name": (VAELoader.vae_list(VAELoader),), - "vae_device": (DEVICES, {"advanced": True}), - "vae_dtype": (VAE_DTYPES, {"advanced": True}), - } - } - - RETURN_TYPES = ("MODEL", "CLIP", "VAE",) - RETURN_NAMES = ("MODEL", "CLIP", "VAE",) - FUNCTION = "load_models" - CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX" - - def load_models(self, **kwargs): - unet_name = kwargs.get("unet_name") - apply_sampling = kwargs.get("apply_sampling") - unet_dtype = kwargs.get("unet_dtype") - model = load_unet(unet_name, unet_dtype) - - if apply_sampling: - args = { - "model": model, - "base_sampling_shift": kwargs.get("base_sampling_shift"), - "max_sampling_shift": kwargs.get("max_sampling_shift"), - "sampling_width": kwargs.get("sampling_width"), - "sampling_height": kwargs.get("sampling_height"), - } - model = patch_flux_sampling(**args) - - clip = load_flux_clip( - clip_l=kwargs.get("clip_l"), - t5xxl=kwargs.get("t5xxl"), - device=kwargs.get("clip_device"), - ) - - loras = [ - (kwargs.get("lora_name_1"), kwargs.get("strength_1"), 'loaded_lora_1'), - (kwargs.get("lora_name_2"), kwargs.get("strength_2"), 'loaded_lora_2'), - (kwargs.get("lora_name_3"), kwargs.get("strength_3"), 'loaded_lora_3'), - (kwargs.get("lora_name_4"), kwargs.get("strength_4"), 'loaded_lora_4'), - ] - - for name, strength, attr in loras: - if name != "None" and strength != 0: - cached = getattr(self, attr) - model, clip, lora = apply_lora(cached, model, clip, name, strength) - setattr(self, attr, lora) - - vae = load_vae(kwargs.get("vae_name"), kwargs.get("vae_device"), kwargs.get("vae_dtype")) - - return (model, clip, vae,) diff --git a/nodes/loaders/gguf_loader_helpers.py b/nodes/loaders/gguf_loader_helpers.py deleted file mode 100644 index 9ac0dba..0000000 --- a/nodes/loaders/gguf_loader_helpers.py +++ /dev/null @@ -1,170 +0,0 @@ -# Contains slightly modified code by City96 -# (c) City96 || Apache-2.0 (apache.org/licenses/LICENSE-2.0) -# Modified by TenserTensor -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import collections as C -import inspect as I -import logging as LOG - -import folder_paths as FP -import torch -from comfy import float as FL, lora as L, model_management as MM, model_patcher as MP, sd as SD, utils as U - -from ...gguf.dequant import is_quantized, is_torch_compatible -from ...gguf.loader import gguf_sd_loader, gguf_clip_loader -from ...gguf.ops import GGMLOps, move_patch_to_device - -WeightBackup = C.namedtuple('WeightBackup', ['weight', 'inplace_update']) - - -class GGUFModelPatcher(MP.ModelPatcher): - patch_on_device = False - - def patch_weight_to_device(self, key, device_to=None, inplace_update=False): - if key not in self.patches: - return - - weight = U.get_attr(self.model, key) - - patches = self.patches[key] - if is_quantized(weight): - out_weight = weight.to(device_to) - patches = move_patch_to_device(patches, self.load_device if self.patch_on_device else self.offload_device) - # TODO: do we ever have legitimate duplicate patches? (i.e. patch on top of patched weight) - out_weight.patches = [(patches, key)] - else: - inplace_update = self.weight_inplace_update or inplace_update - if key not in self.backup: - self.backup[key] = WeightBackup( - weight.to(device=self.offload_device, copy=inplace_update), inplace_update - ) - - if device_to is not None: - temp_weight = MM.cast_to_device(weight, device_to, torch.float32, copy=True) - else: - temp_weight = weight.to(torch.float32, copy=True) - - out_weight = L.calculate_weight(patches, temp_weight, key) - out_weight = FL.stochastic_rounding(out_weight, weight.dtype) - - if inplace_update: - U.copy_to_param(self.model, key, out_weight) - else: - U.set_attr_param(self.model, key, out_weight) - - def unpatch_model(self, device_to=None, unpatch_weights=True): - if unpatch_weights: - for p in self.model.parameters(): - if is_torch_compatible(p): - continue - patches = getattr(p, "patches", []) - if len(patches) > 0: - p.patches = [] - # TODO: Find another way to not unload after patches - return super().unpatch_model(device_to=device_to, unpatch_weights=unpatch_weights) - - -def update_folder_names_and_paths(key, targets=[]): - base = FP.folder_names_and_paths.get(key, ([], {})) - base = base[0] if isinstance(base[0], (list, set, tuple)) else [] - - target = next((x for x in targets if x in FP.folder_names_and_paths), targets[0]) - orig, _ = FP.folder_names_and_paths.get(target, ([], {})) - FP.folder_names_and_paths[key] = (orig or base, {".gguf"}) - if base and base != orig: - LOG.warning(f"Unknown file list already present on key {key}: {base}") - - -def _get_dtype(dtype): - match dtype: - case None | "default": - return None - case "target": - return dtype - case _: - return getattr(torch, dtype) - - -def load_unet(unet_name, dequant_dtype=None, patch_dtype=None, patch_on_device=None): - ops = GGMLOps() - - ops.Linear.dequant_dtype = _get_dtype(dequant_dtype) - ops.Linear.patch_dtype = _get_dtype(patch_dtype) - - unet_path = FP.get_full_path("unet", unet_name) - sd, extra = gguf_sd_loader(unet_path) - - kwargs = {} - valid_params = I.signature(SD.load_diffusion_model_state_dict).parameters - if "metadata" in valid_params: - kwargs["metadata"] = extra.get("metadata", {}) - - model = SD.load_diffusion_model_state_dict( - sd, model_options={"custom_operations": ops}, **kwargs, - ) - - if model is None: - raise RuntimeError("ERROR: Could not detect model type of: {}".format(unet_path)) - - model = GGUFModelPatcher.clone(model) - model.patch_on_device = patch_on_device - - return model - - -def get_filename_list(): - files = [] - files += FP.get_filename_list("clip") - files += FP.get_filename_list("clip_gguf") - return sorted(files) - - -def _load_data(ckpt_paths): - clip_data = [] - for p in ckpt_paths: - if p.endswith(".gguf"): - sd = gguf_clip_loader(p) - else: - sd = U.load_torch_file(p, safe_load=True) - # NOTE: Scaled FP8 would require different custom ops, but only one can be active - if "scaled_fp8" in sd: - raise NotImplementedError( - f"Mixing scaled FP8 with GGUF is not supported! Use regular CLIP loader or switch model(s)\n({p})") - clip_data.append(sd) - - return clip_data - - -def _load_patcher(clip_type, clip_data): - clip = SD.load_text_encoder_state_dicts( - clip_type=clip_type, - state_dicts=clip_data, - model_options={ - "custom_operations": GGMLOps, - "initial_device": MM.text_encoder_offload_device() - }, - embedding_directory=FP.get_folder_paths("embeddings"), - ) - clip.patcher = GGUFModelPatcher.clone(clip.patcher) - - return clip - - -def load_clip(clip_name, type="flux2"): - clip_path = FP.get_full_path("clip", clip_name) - clip_type = getattr(SD.CLIPType, type.upper(), SD.CLIPType.FLUX2) - - return _load_patcher(clip_type, _load_data([clip_path])) - - -def apply_bypass_lora_for_models(loaded_lora, model, clip, lora_name, strength): - if loaded_lora == None: - lora_path = FP.get_full_path_or_raise("loras", lora_name) - lora = U.load_torch_file(lora_path, safe_load=True) - else: - lora = loaded_lora - - patched_model, patched_clip = SD.load_bypass_lora_for_models(model, clip, lora, strength, strength) - - return (patched_model, patched_clip, lora,) diff --git a/nodes/loaders/gguf_models_loader.py b/nodes/loaders/gguf_models_loader.py deleted file mode 100644 index 8337e6b..0000000 --- a/nodes/loaders/gguf_models_loader.py +++ /dev/null @@ -1,41 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import folder_paths as FP - -from nodes import VAELoader as VL -from .gguf_loader_helpers import update_folder_names_and_paths, load_unet, load_clip -from .loader_helpers import load_vae - -update_folder_names_and_paths("unet_gguf", ["diffusion_models", "unet"]) -update_folder_names_and_paths("clip_gguf", ["text_encoders", "clip"]) - - -class TT_Flux2GgufModelsLoader(): - @classmethod - def INPUT_TYPES(cls): - UNET_NAMES = [x for x in FP.get_filename_list("unet_gguf")] - CLIP_NAMES = [x for x in FP.get_filename_list("clip_gguf")] - VAE_NAMES = [x for x in VL.vae_list(VL)] - - return { - "required": { - "unet_name": (UNET_NAMES,), - "clip_name": (CLIP_NAMES,), - "vae_name": (VAE_NAMES,) - } - } - - RETURN_TYPES = ("MODEL", "CLIP", "VAE",) - RETURN_NAMES = ("MODEL", "CLIP", "VAE",) - FUNCTION = "load_models" - CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX2 GGUF" - - VAE_DEVICE = "cpu" - VAE_DTYPE = "bfloat16" - - def load_models(self, unet_name, clip_name, vae_name): - model = load_unet(unet_name) - clip = load_clip(clip_name) - vae = load_vae(vae_name, self.VAE_DEVICE, self.VAE_DTYPE) - - return (model, clip, vae,) diff --git a/nodes/loaders/gguf_models_loader_advanced.py b/nodes/loaders/gguf_models_loader_advanced.py deleted file mode 100644 index eb32531..0000000 --- a/nodes/loaders/gguf_models_loader_advanced.py +++ /dev/null @@ -1,96 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import folder_paths as FP - -from nodes import VAELoader as VL, MAX_RESOLUTION -from .gguf_loader_helpers import update_folder_names_and_paths, load_unet, load_clip, apply_bypass_lora_for_models -from .loader_helpers import load_vae, patch_flux_sampling - -update_folder_names_and_paths("unet_gguf", ["diffusion_models", "unet"]) -update_folder_names_and_paths("clip_gguf", ["text_encoders", "clip"]) - - -class TT_Flux2GgufModelsLoaderAdvanced(): - def __init__(self): - self.loaded_lora_1 = None - self.loaded_lora_2 = None - self.loaded_lora_3 = None - self.loaded_lora_4 = None - - @classmethod - def INPUT_TYPES(cls): - UNET_NAMES = [x for x in FP.get_filename_list("unet_gguf")] - CLIP_NAMES = [x for x in FP.get_filename_list("clip_gguf")] - LORAS = [x for x in FP.get_filename_list("loras")] - VAE_NAMES = [x for x in VL.vae_list(VL)] - DTYPES = ["default", "target", "float32", "float16", "bfloat16"] - DEVICES = ["default", "cpu"] - VAE_DTYPES = ["bfloat16", "float16", "float32"] - - return { - "required": { - "unet_name": (UNET_NAMES,), - "dequant_dtype": (DTYPES, {"default": "bfloat16", "advanced": True},), - "patch_dtype": (DTYPES, {"default": "bfloat16", "advanced": True},), - "apply_sampling": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"},), - "base_sampling_shift": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 100.0, "step": 0.01, "advanced": True},), - "max_sampling_shift": ("FLOAT", {"default": 1.15, "min": 0.0, "max": 100.0, "step": 0.01, "advanced": True},), - "sampling_width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8, "advanced": True},), - "sampling_height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8, "advanced": True},), - "lora_name_1": (["None"] + LORAS, {"advanced": True},), - "strength_1": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},), - "lora_name_2": (["None"] + LORAS, {"advanced": True},), - "strength_2": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},), - "lora_name_3": (["None"] + LORAS, {"advanced": True},), - "strength_3": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},), - "lora_name_4": (["None"] + LORAS, {"advanced": True},), - "strength_4": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},), - "clip_name": (CLIP_NAMES,), - "vae_name": (VAE_NAMES,), - "vae_device": (DEVICES, {"advanced": True},), - "vae_dtype": (VAE_DTYPES, {"advanced": True},), - } - } - - RETURN_TYPES = ("MODEL", "CLIP", "VAE",) - RETURN_NAMES = ("MODEL", "CLIP", "VAE",) - FUNCTION = "load_models" - CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX2 GGUF" - - def load_models(self, **kwargs): - model = load_unet( - kwargs.get("unet_name"), - kwargs.get("dequant_dtype"), - kwargs.get("patch_dtype"), - kwargs.get("patch_on_device") - ) - - apply_sampling = kwargs.get("apply_sampling") - if apply_sampling: - args = { - "model": model, - "base_sampling_shift": kwargs.get("base_sampling_shift"), - "max_sampling_shift": kwargs.get("max_sampling_shift"), - "sampling_width": kwargs.get("sampling_width"), - "sampling_height": kwargs.get("sampling_height"), - } - model = patch_flux_sampling(**args) - - clip = load_clip(kwargs.get("clip_name")) - - loras = [ - (kwargs.get("lora_name_1"), kwargs.get("strength_1"), 'loaded_lora_1'), - (kwargs.get("lora_name_2"), kwargs.get("strength_2"), 'loaded_lora_2'), - (kwargs.get("lora_name_3"), kwargs.get("strength_3"), 'loaded_lora_3'), - (kwargs.get("lora_name_4"), kwargs.get("strength_4"), 'loaded_lora_4'), - ] - - for name, strength, attr in loras: - if name != "None" and strength != 0: - cached = getattr(self, attr) - model, clip, lora = apply_bypass_lora_for_models(cached, model, clip, name, strength) - setattr(self, attr, lora) - - vae = load_vae(kwargs.get("vae_name"), kwargs.get("vae_device"), kwargs.get("vae_dtype")) - - return (model, clip, vae,) diff --git a/nodes/loaders/loader_helpers.py b/nodes/loaders/loader_helpers.py deleted file mode 100644 index 42061fe..0000000 --- a/nodes/loaders/loader_helpers.py +++ /dev/null @@ -1,140 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import os - -import folder_paths as FP -from comfy import model_management as MM, model_sampling as MS, sd as SD, utils as U -from torch import bfloat16, float16, float32, float8_e4m3fn, float8_e5m2, device, tensor - -from nodes import VAELoader as VL - -VIDEO_TAES = ["taehv", "lighttaew2_2", "lighttaew2_1", "lighttaehy1_5"] -IMAGE_TAES = ["taesd", "taesdxl", "taesd3", "taef1"] - - -def load_checkpoint(ckpt_name): - ckpt_path = FP.get_full_path_or_raise("checkpoints", ckpt_name) - return SD.load_checkpoint_guess_config( - ckpt_path, output_vae=False, output_clip=False, - embedding_directory=FP.get_folder_paths("embeddings") - ) - - -def load_unet(unet_name, unet_dtype="default"): - unet_path = FP.get_full_path_or_raise("diffusion_models", unet_name) - - model_options = {} - match unet_dtype: - case "fp8_e4m3fn": - model_options["dtype"] = float8_e4m3fn - case "fp8_e4m3fn_fast": - model_options["dtype"] = float8_e4m3fn - model_options["fp8_optimizations"] = True - case "fp8_e5m2": - model_options["dtype"] = float8_e5m2 - case _: - pass - - return SD.load_diffusion_model( - unet_path, - model_options=model_options - ) - - -TORCH_DEVICE_CPU = "cpu" - - -def _load_clip(clip_type, clip_paths, torch_device=TORCH_DEVICE_CPU): - model_options = {} - if torch_device == TORCH_DEVICE_CPU: - model_options["load_device"] = model_options["offload_device"] = device(TORCH_DEVICE_CPU) - - return SD.load_clip( - ckpt_paths=clip_paths, - embedding_directory=FP.get_folder_paths("embeddings"), - clip_type=clip_type, - model_options=model_options - ) - - -def load_sdxl_clip(clip_l, clip_g, device): - clip_type = getattr(SD.CLIPType, "SDXL", SD.CLIPType.STABLE_DIFFUSION) - clip_l_path = FP.get_full_path_or_raise("text_encoders", clip_l) - clip_g_path = FP.get_full_path_or_raise("text_encoders", clip_g) - clip_paths = [clip_l_path, clip_g_path] - - return _load_clip(clip_type, clip_paths, device) - - -def load_flux_clip(clip_l, t5xxl, device): - clip_type = SD.CLIPType.FLUX - clip_l_path = FP.get_full_path_or_raise("text_encoders", clip_l) - t5xxl_path = FP.get_full_path_or_raise("text_encoders", t5xxl) - clip_paths = [clip_l_path, t5xxl_path] - - return _load_clip(clip_type, clip_paths, device) - - -def apply_lora(loaded_lora, model, clip, lora_name, strength): - if loaded_lora == None: - lora_path = FP.get_full_path_or_raise("loras", lora_name) - lora = U.load_torch_file(lora_path, safe_load=True) - else: - lora = loaded_lora - - patched_model, patched_clip = SD.load_lora_for_models(model, clip, lora, strength, strength) - - return (patched_model, patched_clip, lora) - - -def load_vae(vae_name, vae_device="default", vae_dtype="bfloat16"): - dtype = {"bfloat16": bfloat16, "float16": float16, "float32": float32}[vae_dtype] - - torch_device = None - if vae_device == "default": - torch_device = MM.get_torch_device() - elif vae_device == TORCH_DEVICE_CPU: - torch_device = device(TORCH_DEVICE_CPU) - - metadata = None - if vae_name == "pixel_space": - sd = {} - sd["pixel_space_vae"] = tensor(1.0) - - elif vae_name in IMAGE_TAES: - sd = VL.load_taesd(vae_name) - - else: - if os.path.splitext(vae_name)[0] in VIDEO_TAES: - vae_path = FP.get_full_path_or_raise("vae_approx", vae_name) - else: - vae_path = FP.get_full_path_or_raise("vae", vae_name) - sd, metadata = U.load_torch_file(vae_path, return_metadata=True) - - vae = SD.VAE(sd=sd, device=torch_device, dtype=dtype, metadata=metadata) - vae.throw_exception_if_invalid() - - return vae - - -MIN_SAMPLING_RES = 256 -MAX_SAMPLING_RES = 4096 - - -class ModelSamplingFluxAdvanced(MS.ModelSamplingFlux, MS.CONST): - pass - - -def patch_flux_sampling(model, base_sampling_shift, max_sampling_shift, sampling_width, sampling_height): - tmodel = model.clone() - - slope = (max_sampling_shift - base_sampling_shift) / (MAX_SAMPLING_RES - MIN_SAMPLING_RES) - intercept = base_sampling_shift - slope * MIN_SAMPLING_RES - current_res = (sampling_width * sampling_height / (8 * 8 * 2 * 2)) - shift = current_res * slope + intercept - - model_sampling = ModelSamplingFluxAdvanced(model.model.model_config) - model_sampling.set_parameters(shift=shift) - tmodel.add_object_patch("model_sampling", model_sampling) - - return tmodel diff --git a/nodes/loaders/sdxl_models_loader.py b/nodes/loaders/sdxl_models_loader.py deleted file mode 100644 index 04f1d29..0000000 --- a/nodes/loaders/sdxl_models_loader.py +++ /dev/null @@ -1,43 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import folder_paths - -from nodes import VAELoader -from .loader_helpers import load_checkpoint, load_sdxl_clip, load_vae - - -class TT_SdxlModelsLoader: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "primary_ckpt": (folder_paths.get_filename_list("checkpoints"),), - "secondary_ckpt": (["None"] + folder_paths.get_filename_list("checkpoints"),), - "primary_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - "clip_l": (folder_paths.get_filename_list("text_encoders"),), - "clip_g": (folder_paths.get_filename_list("text_encoders"),), - "clip_device": (["default", "cpu"], {"advanced": True}), - "vae_name": (VAELoader.vae_list(VAELoader),) - } - } - - RETURN_TYPES = ("MODEL", "CLIP", "VAE",) - RETURN_NAMES = ("MODEL", "CLIP", "VAE",) - FUNCTION = "load_models" - CATEGORY = "TenserTensor/Deprecated/Loaders/SDXL" - - def load_models(self, primary_ckpt, secondary_ckpt, primary_weight, clip_l, clip_g, clip_device, vae_name): - model = load_checkpoint(primary_ckpt)[0] - - if secondary_ckpt != "None": - secondary_model = load_checkpoint(secondary_ckpt)[0] - model = model.clone() - key_patches = secondary_model.get_key_patches("diffusion_model.") - for key in key_patches: - model.add_patches({key: key_patches[key]}, 1.0 - primary_weight, primary_weight) - - clip = load_sdxl_clip(clip_l, clip_g, clip_device) - - vae = load_vae(vae_name, "cpu", "bfloat16") - - return (model, clip, vae,) diff --git a/nodes/loaders/sdxl_models_loader_advanced.py b/nodes/loaders/sdxl_models_loader_advanced.py deleted file mode 100644 index f558dd4..0000000 --- a/nodes/loaders/sdxl_models_loader_advanced.py +++ /dev/null @@ -1,78 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import folder_paths - -from nodes import VAELoader -from .loader_helpers import load_checkpoint, load_sdxl_clip, apply_lora, load_vae - - -class TT_SdxlModelsLoaderAdvanced: - def __init__(self): - self.loaded_lora_1 = None - self.loaded_lora_2 = None - self.loaded_lora_3 = None - self.loaded_lora_4 = None - - @classmethod - def INPUT_TYPES(cls): - DEVICES = ["default", "cpu"] - DTYPES = ["bfloat16", "float16", "float32"] - - return { - "required": { - "primary_ckpt": (folder_paths.get_filename_list("checkpoints"),), - "secondary_ckpt": (["None"] + folder_paths.get_filename_list("checkpoints"),), - "primary_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - "clip_l": (folder_paths.get_filename_list("text_encoders"),), - "clip_g": (folder_paths.get_filename_list("text_encoders"),), - "clip_device": (DEVICES, {"advanced": True}), - "lora_name_1": (["None"] + folder_paths.get_filename_list("loras"),), - "strength_1": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "lora_name_2": (["None"] + folder_paths.get_filename_list("loras"),), - "strength_2": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "lora_name_3": (["None"] + folder_paths.get_filename_list("loras"),), - "strength_3": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "lora_name_4": (["None"] + folder_paths.get_filename_list("loras"),), - "strength_4": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}), - "vae_name": (VAELoader.vae_list(VAELoader),), - "vae_device": (DEVICES, {"advanced": True}), - "vae_dtype": (DTYPES, {"advanced": True}), - } - } - - RETURN_TYPES = ("MODEL", "CLIP", "VAE",) - RETURN_NAMES = ("MODEL", "CLIP", "VAE",) - FUNCTION = "load_models" - CATEGORY = "TenserTensor/Deprecated/Loaders/SDXL" - - def load_models(self, primary_ckpt, secondary_ckpt, primary_weight, clip_l, clip_g, clip_device, - lora_name_1, strength_1, lora_name_2, strength_2, lora_name_3, strength_3, lora_name_4, strength_4, - vae_name, vae_device, vae_dtype): - - model = load_checkpoint(primary_ckpt)[0] - - if secondary_ckpt != "None": - secondary_model = load_checkpoint(secondary_ckpt)[0] - model = model.clone() - key_patches = secondary_model.get_key_patches("diffusion_model.") - for key in key_patches: - model.add_patches({key: key_patches[key]}, 1.0 - primary_weight, primary_weight) - - clip = load_sdxl_clip(clip_l, clip_g, clip_device) - - loras = [ - (lora_name_1, strength_1, 'loaded_lora_1'), - (lora_name_2, strength_2, 'loaded_lora_2'), - (lora_name_3, strength_3, 'loaded_lora_3'), - (lora_name_4, strength_4, 'loaded_lora_4'), - ] - - for name, strength, attr in loras: - if name != "None" and strength != 0: - cached = getattr(self, attr) - model, clip, lora = apply_lora(cached, model, clip, name, strength) - setattr(self, attr, lora) - - vae = load_vae(vae_name, vae_device, vae_dtype) - - return (model, clip, vae,) diff --git a/nodes/postproduction/add_film_grain.py b/nodes/postproduction/add_film_grain.py deleted file mode 100644 index 3e3a811..0000000 --- a/nodes/postproduction/add_film_grain.py +++ /dev/null @@ -1,39 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .postproduction_helpers import apply_film_grain - - -class TT_AddFilmGrain(): - @classmethod - def INPUT_TYPES(cls): - UPSCALE_MODES = ["bilinear", "bicubic", "lanczos", "nearest", "area"] - - return { - "required": { - "image": ("IMAGE",), - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "scale": ("FLOAT", {"default": 0.25, "min": 0.25, "max": 2.0, "step": 0.05}), - "strength": ("FLOAT", {"default": 0.15, "min": 0.0, "max": 10.0, "step": 0.01}), - "saturation": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 2.0, "step": 0.01}), - "toe": ("FLOAT", {"default": 0.0, "min": -0.2, "max": 0.5, "step": 0.001}), - "upscale_mode": (UPSCALE_MODES, {"advanced": True}), - "antialias": ("BOOLEAN", {"default": False, "label_on": "Enabled", "label_off": "Disabled"}), - } - } - - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) - FUNCTION = "apply_film_grain" - CATEGORY = "TenserTensor/Deprecated/Postproduction" - - def apply_film_grain(self, **kwargs): - return (apply_film_grain( - image=kwargs.get("image").clone(), - seed=kwargs.get("seed"), - scale=kwargs.get("scale"), - strength=kwargs.get("strength"), - saturation=kwargs.get("saturation"), - toe=kwargs.get("toe"), - mode=kwargs.get("upscale_mode"), - antialias=kwargs.get("antialias"), - ),) diff --git a/nodes/postproduction/apply_lut.py b/nodes/postproduction/apply_lut.py deleted file mode 100644 index 29e98aa..0000000 --- a/nodes/postproduction/apply_lut.py +++ /dev/null @@ -1,37 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .postproduction_helpers import get_lut_files_list, color_correction - - -class TT_ApplyLut: - LUT_DIR = None - - @classmethod - def INPUT_TYPES(cls): - cls.LUT_DIR, LUT_FILES = get_lut_files_list() - COLORSPACES = ["linear", "logarithmic"] - - return { - "required": { - "image": ("IMAGE",), - "lut_file": (LUT_FILES, {"advanced": True}), - "strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - "colorspace": (COLORSPACES, {"advanced": True}), - } - } - - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) - FUNCTION = "apply_lut" - CATEGORY = "TenserTensor/Deprecated/Postproduction" - - def apply_lut(self, image, lut_file, strength, colorspace): - return ( - color_correction( - image.clone(), - TT_ApplyLut.LUT_DIR, - lut_file, - strength, - colorspace - ), - ) diff --git a/nodes/postproduction/image_enhancer.py b/nodes/postproduction/image_enhancer.py deleted file mode 100644 index 8bd2fbd..0000000 --- a/nodes/postproduction/image_enhancer.py +++ /dev/null @@ -1,57 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .postproduction_helpers import enhance_image - - -class TT_ImageEnhancer(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "image": ("IMAGE",), - "brightness_factor": ("FLOAT", {"default": 0.0, "min": -1.0, "max": 1.0, "step": 0.01}), - "contrast_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 5.0, "step": 0.01}), - "gamma_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "gamma_gain": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "hue_factor": ("FLOAT", {"default": 0.0, "min": -3.14, "max": 3.14, "step": 0.01}), - "saturation_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "sharpness_factor": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "posterize_bits": ("INT", {"default": 8, "min": 0, "max": 8}), - "solarize_thresholds": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - } - } - - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) - FUNCTION = "enhance_image" - CATEGORY = "TenserTensor/Deprecated/Postproduction" - - def enhance_image( - self, - image, - brightness_factor, - contrast_factor, - gamma_factor, - gamma_gain, - hue_factor, - saturation_factor, - sharpness_factor, - posterize_bits, - solarize_thresholds - ): - timage = image.clone() - - timage = enhance_image( - timage, - brightness_factor, - contrast_factor, - gamma_factor, - gamma_gain, - hue_factor, - saturation_factor, - sharpness_factor, - posterize_bits, - solarize_thresholds - ) - - return (timage,) diff --git a/nodes/postproduction/postproduction.py b/nodes/postproduction/postproduction.py deleted file mode 100644 index 5684b29..0000000 --- a/nodes/postproduction/postproduction.py +++ /dev/null @@ -1,86 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from folder_paths import get_filename_list - -from .postproduction_helpers import get_lut_files_list, color_correction, apply_film_grain, upscale_image - - -class TT_Postproduction(): - LUT_DIR = None - - @classmethod - def INPUT_TYPES(cls): - cls.LUT_DIR, LUT_FILES = get_lut_files_list() - COLORSPACES = ["linear", "logarithmic"] - UPSCALE_MODES = ["bilinear", "bicubic", "lanczos", "nearest", "area"] - UPSCALE_MODELS = get_filename_list("upscale_models") - DEVICES = ["default", "cpu"] - - return { - "required": { - "image": ("IMAGE",), - "apply_lut": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "lut_file": (LUT_FILES, {"advanced": True}), - "lut_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - "lut_colorspace": (COLORSPACES, {"advanced": True}), - "add_film_grain": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "grain_seed": ( - "INT", - {"default": 0, "min": 0, "max": 0xffffffffffffffff, "control_after_generate": True} - ), - "grain_scale": ("FLOAT", {"default": 0.25, "min": 0.25, "max": 2.0, "step": 0.05}), - "grain_strength": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 10.0, "step": 0.01}), - "grain_saturation": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 2.0, "step": 0.01}), - "grain_toe": ("FLOAT", {"default": 0.05, "min": -0.2, "max": 0.5, "step": 0.01}), - "grain_upscale_mode": (UPSCALE_MODES, {"advanced": True}), - "grain_antialias": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "image_upscaler": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "upscaler_device": (DEVICES, {"advanced": True}), - "upscale_model_name": (UPSCALE_MODELS, {"advanced": True}), - "upscaler_tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64}), - "upscaler_overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8}), - } - } - - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) - FUNCTION = "apply_postprocessing" - CATEGORY = "TenserTensor/Deprecated/Postproduction" - - def apply_postprocessing(self, **kwargs): - image = kwargs.get("image").clone() - - apply_lut = kwargs.get("apply_lut") - if apply_lut: - image = color_correction( - image=image, - lut_dir=TT_Postproduction.LUT_DIR, - lut_file=kwargs.get("lut_file"), - strength=kwargs.get("lut_strength"), - colorspace=kwargs.get("lut_colorspace") - ) - - add_film_grain = kwargs.get("add_film_grain") - if add_film_grain: - image = apply_film_grain( - image=image, - seed=kwargs.get("grain_seed"), - scale=kwargs.get("grain_scale"), - strength=kwargs.get("grain_strength"), - saturation=kwargs.get("grain_saturation"), - toe=kwargs.get("grain_toe"), - mode=kwargs.get("grain_upscale_mode"), - antialias=kwargs.get("grain_antialias") - ) - - image_upscaler = kwargs.get("image_upscaler") - if image_upscaler: - image = upscale_image( - timage=image, - device=kwargs.get("upscaler_device"), - upscale_model_name=kwargs.get("upscale_model_name"), - tile=kwargs.get("upscaler_tile"), - overlap=kwargs.get("upscaler_overlap"), - ) - - return (image,) diff --git a/nodes/postproduction/postproduction_advanced.py b/nodes/postproduction/postproduction_advanced.py deleted file mode 100644 index 4883733..0000000 --- a/nodes/postproduction/postproduction_advanced.py +++ /dev/null @@ -1,111 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from folder_paths import get_filename_list - -from .postproduction_helpers import get_lut_files_list, color_correction, apply_film_grain, upscale_image, enhance_image - - -class TT_PostproductionAdvanced(): - LUT_DIR = None - - @classmethod - def INPUT_TYPES(cls): - cls.LUT_DIR, LUT_FILES = get_lut_files_list() - COLORSPACES = ["linear", "logarithmic"] - UPSCALE_MODES = ["bilinear", "bicubic", "lanczos", "nearest", "area"] - UPSCALE_MODELS = get_filename_list("upscale_models") - DEVICES = ["default", "cpu"] - - return { - "required": { - "image": ("IMAGE",), - "image_enhancer": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "brightness_factor": ("FLOAT", {"default": 0.0, "min": -1.0, "max": 1.0, "step": 0.01}), - "contrast_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 5.0, "step": 0.01}), - "gamma_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "gamma_gain": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "hue_factor": ("FLOAT", {"default": 0.0, "min": -3.14, "max": 3.14, "step": 0.01}), - "saturation_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "sharpness_factor": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 3.0, "step": 0.01}), - "posterize_bits": ("INT", {"default": 8, "min": 0, "max": 8}), - "solarize_thresholds": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - "apply_lut": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "lut_file": (LUT_FILES, {"advanced": True}), - "lut_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - "lut_colorspace": (COLORSPACES, {"advanced": True}), - "add_film_grain": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "grain_seed": ( - "INT", - {"default": 0, "min": 0, "max": 0xffffffffffffffff, "control_after_generate": True} - ), - "grain_scale": ("FLOAT", {"default": 0.25, "min": 0.25, "max": 2.0, "step": 0.05}), - "grain_strength": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 10.0, "step": 0.01}), - "grain_saturation": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 2.0, "step": 0.01}), - "grain_toe": ("FLOAT", {"default": 0.05, "min": -0.2, "max": 0.5, "step": 0.01}), - "grain_upscale_mode": (UPSCALE_MODES, {"advanced": True}), - "grain_antialias": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "image_upscaler": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "upscaler_device": (DEVICES, {"advanced": True}), - "upscale_model_name": (UPSCALE_MODELS, {"advanced": True}), - "upscaler_tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64}), - "upscaler_overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8}), - } - } - - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) - FUNCTION = "apply_postprocessing" - CATEGORY = "TenserTensor/Deprecated/Postproduction" - - def apply_postprocessing(self, **kwargs): - image = kwargs.get("image").clone() - - image_enhancer = kwargs.get("image_enhancer") - if image_enhancer: - image = enhance_image( - timage=image, - brightness_factor=kwargs.get("brightness_factor"), - contrast_factor=kwargs.get("contrast_factor"), - gamma_factor=kwargs.get("gamma_factor"), - gamma_gain=kwargs.get("gamma_gain"), - hue_factor=kwargs.get("hue_factor"), - saturation_factor=kwargs.get("saturation_factor"), - sharpness_factor=kwargs.get("sharpness_factor"), - posterize_bits=kwargs.get("posterize_bits"), - solarize_thresholds=kwargs.get("solarize_thresholds") - ) - - apply_lut = kwargs.get("apply_lut") - if apply_lut: - image = color_correction( - image=image, - lut_dir=TT_PostproductionAdvanced.LUT_DIR, - lut_file=kwargs.get("lut_file"), - strength=kwargs.get("lut_strength"), - colorspace=kwargs.get("lut_colorspace") - ) - - add_film_grain = kwargs.get("add_film_grain") - if add_film_grain: - image = apply_film_grain( - image=image, - seed=kwargs.get("grain_seed"), - scale=kwargs.get("grain_scale"), - strength=kwargs.get("grain_strength"), - saturation=kwargs.get("grain_saturation"), - toe=kwargs.get("grain_toe"), - mode=kwargs.get("grain_upscale_mode"), - antialias=kwargs.get("grain_antialias") - ) - - image_upscaler = kwargs.get("image_upscaler") - if image_upscaler: - image = upscale_image( - timage=image, - device=kwargs.get("upscaler_device"), - upscale_model_name=kwargs.get("upscale_model_name"), - tile=kwargs.get("upscaler_tile"), - overlap=kwargs.get("upscaler_overlap"), - ) - - return (image,) diff --git a/nodes/postproduction/postproduction_helpers.py b/nodes/postproduction/postproduction_helpers.py deleted file mode 100644 index 0ca190a..0000000 --- a/nodes/postproduction/postproduction_helpers.py +++ /dev/null @@ -1,236 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from pathlib import Path - -import colour -import comfy.utils as U -import kornia -import torch -import torch.nn.functional as F -from comfy import model_management -from folder_paths import get_folder_paths, get_filename_list, get_full_path_or_raise -from spandrel import ModelLoader, ImageModelDescriptor - - -def get_lut_files_list(): - base = get_folder_paths("custom_nodes")[0] - lut_dir = Path(base) / "ComfyUI-TenserTensor" / "lut" - - if not lut_dir.is_dir(): - raise FileNotFoundError(f"lut dir not found: {lut_dir}") - - files = [file.name for file in lut_dir.glob("*.cube")] - - return lut_dir, sorted(files) - - -def color_correction(image, lut_dir, lut_file, strength, colorspace): - is_log = colorspace == "logarithmic" - device, dtype = image.device, image.dtype - image = image.detach().cpu().numpy() - retval = image.copy() - if is_log: - retval **= 1 / 2.2 - retval = colour.read_LUT(str(lut_dir / lut_file)).apply(retval) - if is_log: - retval **= 2.2 - if strength < 1.0: - retval = strength * retval + (1 - strength) * image - - return torch.from_numpy(retval).to(device, dtype) - - -def apply_film_grain(image, seed, scale, strength, saturation, toe, mode, antialias): - batch, height, width, channels = image.shape - image = image.detach() - if seed is not None: - torch.manual_seed(seed) - grain = torch.rand(batch, int(height // scale), int(width // scale), 3) - ycbcr = kornia.color.rgb_to_ycbcr(grain.movedim(-1, 1)).movedim(1, -1) - - for idx, ksize in enumerate([3, 15, 11]): - sigma = (ksize / 3.0,) * 2 - kernel_size = (ksize,) * 2 - channel = ycbcr[..., idx:idx + 1].movedim(-1, 1) - ycbcr[..., idx] = kornia.filters.gaussian_blur2d( - channel, - kernel_size=kernel_size, - sigma=sigma, - border_type='reflect' - ).movedim(1, -1).squeeze(-1) - - grain = (kornia.color.ycbcr_to_rgb(ycbcr.movedim(-1, 1)).movedim(1, -1) - 0.5) * strength - grain[..., 0] *= 2 - grain[..., 2] *= 3 - grain += 1 - - mono = grain[..., 1:2].expand(-1, -1, -1, 3) - grain = grain * saturation + mono * (1 - saturation) - - grain = F.interpolate( - grain.movedim(-1, 1), - size=(height, width), - mode=mode, - antialias=antialias if mode in ['bilinear', 'bicubic'] else False - ).movedim(1, -1) - - base = image[..., :3] - shadow_lift = 1 - toe - image[..., :3] = torch.clip( - (1 - (1 - base) * grain) * shadow_lift + toe, - 0.0, 1.0 - ) - - return image - - -def _load_upscale_model(upscale_model_name): - model_path = get_full_path_or_raise("upscale_models", upscale_model_name) - - try: - state_dict = U.load_torch_file(model_path, safe_load=True) - except Exception as e: - raise RuntimeError(f"Failed to load model file {model_path}: {e}") - - state_dict = U.state_dict_prefix_replace(state_dict, {"module.": ""}) - upscale_model = ModelLoader().load_from_state_dict(state_dict).eval() - - if not isinstance(upscale_model, ImageModelDescriptor): - raise TypeError(f"Expected ImageModelDescriptor, got {type(upscale_model).__name__}") - - return upscale_model - - -def upscale_image(timage, device, upscale_model_name, tile, overlap): - upscale_device = model_management.get_torch_device() if device == "default" else torch.device("cpu") - upscale_model = _load_upscale_model(upscale_model_name) - - iimage = timage.movedim(-1, 1).to(upscale_device) - batch, channels, height, width = iimage.shape - - BUFFER_FACTOR = 384.0 - - model_mem = model_management.module_size(upscale_model.model) - tile_mem = (tile * tile * 3) * iimage.element_size() * max(upscale_model.scale, 1) * BUFFER_FACTOR - total_mem = model_mem + tile_mem + iimage.nelement() * iimage.element_size() - model_management.free_memory(total_mem, upscale_device) - upscale_model.to(upscale_device) - - try: - while True: - try: - steps = batch * U.get_tiled_scale_steps( - width, - height, - tile_x=tile, - tile_y=tile, - overlap=overlap - ) - pbar = U.ProgressBar(steps) - simage = U.tiled_scale( - iimage, - upscale_model, - tile_x=tile, - tile_y=tile, - overlap=overlap, - upscale_amount=upscale_model.scale, - pbar=pbar - ) - break - except model_management.OOM_EXCEPTION as e: - pbar = None - tile //= 2 - if tile < 128: - raise e - finally: - if upscale_device.type != "cpu": - upscale_model.to("cpu") - - return torch.clamp(simage.movedim(1, -1), min=0.0, max=1.0) - - -def adjust_brightness(image, factor, clip_output=True): - timage = image.movedim(-1, 1) - - return kornia.enhance.adjust_brightness(timage, factor, clip_output).movedim(1, -1) - - -def adjust_contrast(image, factor, clip_output=True): - timage = image.movedim(-1, 1) - - return kornia.enhance.adjust_contrast(timage, factor, clip_output).movedim(1, -1) - - -def adjust_gamma(image, gamma, gain=1.0): - timage = image.movedim(-1, 1) - - return kornia.enhance.adjust_gamma(timage, gamma, gain).movedim(1, -1) - - -def adjust_hue(image, factor): - timage = image.movedim(-1, 1) - - return kornia.enhance.adjust_hue(timage, factor).movedim(1, -1) - - -def adjust_saturation(image, factor): - timage = image.movedim(-1, 1) - - return kornia.enhance.adjust_saturation(timage, factor).movedim(1, -1) - - -def sharpness(image, factor): - timage = image.movedim(-1, 1) - - return kornia.enhance.sharpness(timage, factor).movedim(1, -1) - - -def posterize(image, bits): - timage = image.movedim(-1, 1) - - return kornia.enhance.posterize(timage, bits).movedim(1, -1) - - -def solarize(image, thresholds=0.5, additions=None): - timage = image.movedim(-1, 1) - - return kornia.enhance.solarize(timage, thresholds, additions).movedim(1, -1) - - -def enhance_image( - timage, - brightness_factor, - contrast_factor, - gamma_factor, - gamma_gain, - hue_factor, - saturation_factor, - sharpness_factor, - posterize_bits, - solarize_thresholds -): - if brightness_factor != 0.0: - timage = adjust_brightness(timage, brightness_factor) - - if contrast_factor != 1.0: - timage = adjust_contrast(timage, contrast_factor) - - if gamma_factor != 1.0: - timage = adjust_gamma(timage, gamma_factor, gamma_gain) - - if hue_factor != 0.0: - timage = adjust_hue(timage, hue_factor) - - if saturation_factor != 1.0: - timage = adjust_saturation(timage, saturation_factor) - - if sharpness_factor != 0.0: - timage = sharpness(timage, sharpness_factor) - - if posterize_bits != 8: - timage = posterize(timage, posterize_bits) - - if solarize_thresholds != 1.0: - timage = solarize(timage, solarize_thresholds) - - return timage diff --git a/nodes/postproduction/quick_image_upscaler.py b/nodes/postproduction/quick_image_upscaler.py deleted file mode 100644 index 707ffcf..0000000 --- a/nodes/postproduction/quick_image_upscaler.py +++ /dev/null @@ -1,38 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from folder_paths import get_filename_list - -from .postproduction_helpers import upscale_image - - -class TT_QuickImageUpscaler(): - @classmethod - def INPUT_TYPES(cls): - DEVICES = ["default", "cpu"] - UPSCALE_MODELS = get_filename_list("upscale_models") - - return { - "required": { - "image": ("IMAGE",), - "device": (DEVICES, {"advanced": True}), - "upscale_model_name": (UPSCALE_MODELS, {"advanced": True}), - "tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64}), - "overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8}), - } - } - - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) - FUNCTION = "upscale_image" - CATEGORY = "TenserTensor/Deprecated/Postproduction" - - def upscale_image(self, image, device, upscale_model_name, tile, overlap): - timage = image.clone() - - return (upscale_image( - timage=timage, - device=device, - upscale_model_name=upscale_model_name, - tile=tile, - overlap=overlap, - ),) diff --git a/nodes/sampling/ksampler.py b/nodes/sampling/ksampler.py deleted file mode 100644 index f656227..0000000 --- a/nodes/sampling/ksampler.py +++ /dev/null @@ -1,31 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers - -from .ksampler_helpers import sample_latents - - -class TT_KSampler(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "model": ("MODEL",), - "positive": ("CONDITIONING",), - "negative": ("CONDITIONING",), - "latent": ("LATENT",), - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (comfy.samplers.KSampler.SAMPLERS,), - "scheduler": (comfy.samplers.KSampler.SCHEDULERS,), - } - } - - RETURN_TYPES = ("LATENT",) - RETURN_NAMES = ("SAMPLES",) - FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Deprecated/Sampling" - - def execute_sampling(self, **kwargs): - return (sample_latents(**kwargs),) diff --git a/nodes/sampling/ksampler_advanced.py b/nodes/sampling/ksampler_advanced.py deleted file mode 100644 index f31d000..0000000 --- a/nodes/sampling/ksampler_advanced.py +++ /dev/null @@ -1,36 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers - -from .ksampler_helpers import sample_latents - - -class TT_KSamplerAdvanced(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "model": ("MODEL",), - "positive": ("CONDITIONING",), - "negative": ("CONDITIONING",), - "latent": ("LATENT",), - "add_noise": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}), - "full_denoise": ("BOOLEAN", {"default": False, "label_on": "Enabled", "label_off": "Disabled"}), - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "start_step": ("INT", {"default": 0, "min": 0, "max": 10000}), - "last_step": ("INT", {"default": 10000, "min": 0, "max": 10000}), - "cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (comfy.samplers.KSampler.SAMPLERS,), - "scheduler": (comfy.samplers.KSampler.SCHEDULERS,), - "denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - } - } - - RETURN_TYPES = ("LATENT",) - RETURN_NAMES = ("SAMPLES",) - FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Deprecated/Sampling" - - def execute_sampling(self, **kwargs): - return (sample_latents(**kwargs),) diff --git a/nodes/sampling/ksampler_context.py b/nodes/sampling/ksampler_context.py deleted file mode 100644 index 648e712..0000000 --- a/nodes/sampling/ksampler_context.py +++ /dev/null @@ -1,47 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .ksampler_helpers import sample_latents - - -class TT_KSamplerContext(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "context": ("TT_CONTEXT",) - } - } - - RETURN_TYPES = ("TT_CONTEXT", "LATENT",) - RETURN_NAMES = ("CONTEXT", "SAMPLES",) - FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Deprecated/Sampling" - - def execute_sampling(self, context): - model = context.get("model", None) - latent = context.get("latent", None) - config = context.get("workflow_config", None) - - if model is None: - raise ValueError("Model is required for sampling") - if latent is None: - raise ValueError("Latent image is required for sampling") - if config is None: - raise ValueError("Workflow Config is required for sampling") - - args = { - "model": model, - "positive": context.get("positive", None), - "negative": context.get("negative", None), - "latent": latent, - "seed": config.get("seed", 0), - "steps": config.get("steps", 0), - "cfg": config.get("cfg", 0), - "sampler_name": config.get("sampler_name", None), - "scheduler": config.get("scheduler", None), - } - - samples = sample_latents(**args) - context["latent"] = samples - - return (context, samples) diff --git a/nodes/sampling/ksampler_guided.py b/nodes/sampling/ksampler_guided.py deleted file mode 100644 index 9fa3c11..0000000 --- a/nodes/sampling/ksampler_guided.py +++ /dev/null @@ -1,25 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .ksampler_helpers import guided_sample_latents - - -class TT_KSamplerGuided: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "latent": ("LATENT",), - "guider": ("GUIDER",), - "sigmas": ("SIGMAS",), - "sampler": ("SAMPLER",), - "random_noise": ("NOISE",), - }, - } - - RETURN_TYPES = ("LATENT",) - RETURN_NAMES = ("SAMPLES",) - FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Deprecated/Sampling" - - def execute_sampling(self, latent, guider, sigmas, sampler, random_noise): - return (guided_sample_latents(latent, guider, sigmas, sampler, random_noise),) diff --git a/nodes/sampling/ksampler_helpers.py b/nodes/sampling/ksampler_helpers.py deleted file mode 100644 index 6872b13..0000000 --- a/nodes/sampling/ksampler_helpers.py +++ /dev/null @@ -1,95 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy -import latent_preview as LP -import torch -from comfy import sample as S, utils as U, model_management as MM, nested_tensor as NT - - -def sample_latents(**kwargs): - model = kwargs.get("model", None) - latent = kwargs.get("latent", None) - - if model is None: - raise ValueError("Model is required for sampling") - if latent is None: - raise ValueError("Latent image is required for sampling") - - steps = kwargs.get("steps", 0) - seed = kwargs.get("seed", 0) - - latent_img = comfy.sample.fix_empty_latent_channels(model, latent["samples"]) - - add_noise = kwargs.get("add_noise", True) - if add_noise: - bat_idx = latent.get("batch_index", None) - noise = comfy.sample.prepare_noise(latent_img, seed, bat_idx) - else: - noise = torch.zeros(latent_img.size(), dtype=latent_img.dtype, layout=latent_img.layout, device="cpu") - - callback = LP.prepare_callback(model, steps) - - args = { - "model": model, - "noise": noise, - "steps": steps, - "cfg": kwargs.get("cfg", 0), - "sampler_name": kwargs.get("sampler_name", None), - "scheduler": kwargs.get("scheduler", None), - "positive": kwargs.get("positive", None), - "negative": kwargs.get("negative", None), - "latent_image": latent_img, - "denoise": kwargs.get("denoise", 1.0), - "disable_noise": not add_noise, - "start_step": kwargs.get("start_step", 0), - "last_step": kwargs.get("last_step", 10000), - "force_full_denoise": kwargs.get("full_denoise", True), - "noise_mask": latent.get("noise_mask", None), - "disable_pbar": not comfy.utils.PROGRESS_BAR_ENABLED, - "callback": callback, - "seed": seed, - } - - samples = comfy.sample.sample(**args) - - retval = latent.copy() - retval["samples"] = samples - - return retval - - -def guided_sample_latents(latent, guider, sigmas, sampler, random_noise): - model_patcher = guider.model_patcher - latent_dict = latent.copy() - latent_tensor = S.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 = {} - callback = LP.prepare_callback(model_patcher, sigmas.shape[-1] - 1, interim_buffer) - disable_pbar = not U.PROGRESS_BAR_ENABLED - - print(f"latent: {latent}") - print(f"sampler: {sampler}") - print(f"sigmas: {sigmas}") - print(f"random_noise: {random_noise}") - print(f"GUIDER: {guider}") - - - samples = guider.sample( - random_noise.generate_noise(latent), - latent_tensor, - sampler, - sigmas, - denoise_mask=noise_mask, - callback=callback, - disable_pbar=disable_pbar, - seed=random_noise.seed - ).to(MM.intermediate_device()) - - retval = latent_dict.copy() - retval.pop("downscale_ratio_spacial", None) - retval["samples"] = samples - - return retval diff --git a/nodes/sampling/ksampler_two_stage.py b/nodes/sampling/ksampler_two_stage.py deleted file mode 100644 index b825864..0000000 --- a/nodes/sampling/ksampler_two_stage.py +++ /dev/null @@ -1,65 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers - -from .ksampler_helpers import sample_latents - - -class TT_KSamplerTwoStage(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "model": ("MODEL",), - "positive": ("CONDITIONING",), - "negative": ("CONDITIONING",), - "latent": ("LATENT",), - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}), - "draft_steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "refiner_steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "draft_sampler_name": (comfy.samplers.KSampler.SAMPLERS,), - "draft_scheduler": (comfy.samplers.KSampler.SCHEDULERS,), - "refiner_sampler_name": (comfy.samplers.KSampler.SAMPLERS,), - "refiner_scheduler": (comfy.samplers.KSampler.SCHEDULERS,), - "draft_denoise": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.01}), - "refiner_denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}), - } - } - - RETURN_TYPES = ("LATENT",) - RETURN_NAMES = ("SAMPLES",) - FUNCTION = "execute_sampling" - CATEGORY = "TenserTensor/Deprecated/Sampling" - - def execute_sampling(self, **kwargs): - draft_steps = kwargs["draft_steps"] - refiner_steps = kwargs["refiner_steps"] - - args = { - "model": kwargs["model"], - "positive": kwargs["positive"], - "negative": kwargs["negative"], - "latent": kwargs["latent"], - "seed": kwargs["seed"], - "steps": draft_steps, - "start_step": 0, - "cfg": kwargs["cfg"], - "sampler_name": kwargs["draft_sampler_name"], - "scheduler": kwargs["draft_scheduler"], - "add_noise": True, - "full_denoise": False, - "denoise": kwargs["refiner_denoise"], - } - - samples = sample_latents(**args) - - args["latent"] = samples - args["steps"] = draft_steps + refiner_steps - args["start_step"] = draft_steps - args["denoise"] = kwargs["draft_denoise"] - args["sampler_name"] = kwargs["refiner_sampler_name"] - args["scheduler"] = kwargs["refiner_scheduler"] - args["full_denoise"] = True - - return (sample_latents(**args),) diff --git a/nodes/text_encoders/clip_text_encode_flux.py b/nodes/text_encoders/clip_text_encode_flux.py deleted file mode 100644 index 4a98198..0000000 --- a/nodes/text_encoders/clip_text_encode_flux.py +++ /dev/null @@ -1,26 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .encoder_helpers import encode_prompts_flux - - -class TT_ClipTextEncodeFlux(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "clip": ("CLIP",), - "clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}), - "t5xxl_positive": ("STRING", {"multiline": True, "placeholder": "T5XXL Positive", "dynamicPrompts": True}), - "clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}), - "t5xxl_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}), - "guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1}) - } - } - - RETURN_TYPES = ("CONDITIONING", "CONDITIONING",) - RETURN_NAMES = ("POSITIVE", "NEGATIVE",) - FUNCTION = "execute" - CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX" - - def execute(self, **kwargs): - return encode_prompts_flux(**kwargs) diff --git a/nodes/text_encoders/clip_text_encode_flux2.py b/nodes/text_encoders/clip_text_encode_flux2.py deleted file mode 100644 index 998ba7c..0000000 --- a/nodes/text_encoders/clip_text_encode_flux2.py +++ /dev/null @@ -1,25 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .encoder_helpers import encode_prompts_flux2 - - -class TT_ClipTextEncodeFlux2(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "model": ("MODEL",), - "clip": ("CLIP",), - "prompt": ("STRING", {"multiline": True, "placeholder": "Prompt", "dynamicPrompts": True}), - "lora_triggers": ("STRING", {"multiline": True, "placeholder": "LoRA Triggers", "dynamicPrompts": True}), - "guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1}) - } - } - - RETURN_TYPES = ("GUIDER",) - RETURN_NAMES = ("GUIDER",) - FUNCTION = "execute" - CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX2" - - def execute(self, model, clip, prompt, lora_triggers, guidance): - return encode_prompts_flux2(model, clip, prompt, lora_triggers, guidance) diff --git a/nodes/text_encoders/clip_text_encode_flux2_context.py b/nodes/text_encoders/clip_text_encode_flux2_context.py deleted file mode 100644 index c99bb3b..0000000 --- a/nodes/text_encoders/clip_text_encode_flux2_context.py +++ /dev/null @@ -1,41 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .encoder_helpers import encode_prompts_flux2 - - -class TT_ClipTextEncodeFlux2Context(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "context": ("TT_CONTEXT",) - } - } - - RETURN_TYPES = ("TT_CONTEXT", "GUIDER",) - RETURN_NAMES = ("CONTEXT", "GUIDER",) - FUNCTION = "execute" - CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX2" - - def execute(self, context): - model = context.get("model", None) - clip = context.get("clip", None) - config = context.get("workflow_config", None) - - if model is None: - raise ValueError("Model is required for text encoder") - if clip is None: - raise ValueError("CLIP is required for text encoder") - if config is None: - raise ValueError("Workflow Config is required for text encoder") - - guider = encode_prompts_flux2( - model, - clip, - config.get("prompt", None), - config.get("lora_triggers", None), - config.get("guidance", None), - ) - context["guider"] = guider - - return (context, guider,) diff --git a/nodes/text_encoders/clip_text_encode_flux_context.py b/nodes/text_encoders/clip_text_encode_flux_context.py deleted file mode 100644 index 533b6ad..0000000 --- a/nodes/text_encoders/clip_text_encode_flux_context.py +++ /dev/null @@ -1,36 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .encoder_helpers import encode_prompts_flux - - -class TT_ClipTextEncodeFluxContext(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "context": ("TT_CONTEXT",) - } - } - - RETURN_TYPES = ("TT_CONTEXT", "CONDITIONING", "CONDITIONING",) - RETURN_NAMES = ("CONTEXT", "POSITIVE", "NEGATIVE",) - FUNCTION = "execute" - CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX" - - def execute(self, context): - clip = context["clip"] - config = context["workflow_config"] - - positive, negative = encode_prompts_flux( - clip, - config["clip_l_positive"], - config["t5xxl_positive"], - config["clip_l_negative"], - config["t5xxl_negative"], - config["guidance"], - ) - - context["positive"] = positive - context["negative"] = negative - - return (context, positive, negative,) diff --git a/nodes/text_encoders/clip_text_encode_sdxl.py b/nodes/text_encoders/clip_text_encode_sdxl.py deleted file mode 100644 index 0adca45..0000000 --- a/nodes/text_encoders/clip_text_encode_sdxl.py +++ /dev/null @@ -1,32 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from nodes import MAX_RESOLUTION -from .encoder_helpers import encode_prompts_sdxl - - -class TT_ClipTextEncodeSdxl(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "clip": ("CLIP",), - "clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}), - "clip_g_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_G Positive", "dynamicPrompts": True}), - "clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}), - "clip_g_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_G Negative", "dynamicPrompts": True}), - "ascore_positive": ("FLOAT", {"default": 9.0, "min": 0.0, "max": 1000.0, "step": 0.1}), - "ascore_negative": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 1000.0, "step": 0.1}), - "width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - "height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - "target_width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - "target_height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - } - } - - RETURN_TYPES = ("CONDITIONING", "CONDITIONING",) - RETURN_NAMES = ("POSITIVE", "NEGATIVE",) - FUNCTION = "execute" - CATEGORY = "TenserTensor/Deprecated/Text Encoders/SDXL" - - def execute(self, **kwargs): - return encode_prompts_sdxl(**kwargs) diff --git a/nodes/text_encoders/clip_text_encode_sdxl_context.py b/nodes/text_encoders/clip_text_encode_sdxl_context.py deleted file mode 100644 index 13d2872..0000000 --- a/nodes/text_encoders/clip_text_encode_sdxl_context.py +++ /dev/null @@ -1,41 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .encoder_helpers import encode_prompts_sdxl - - -class TT_ClipTextEncodeSdxlContext(): - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "context": ("TT_CONTEXT",) - } - } - - RETURN_TYPES = ("TT_CONTEXT", "CONDITIONING", "CONDITIONING",) - RETURN_NAMES = ("CONTEXT", "POSITIVE", "NEGATIVE",) - FUNCTION = "execute" - CATEGORY = "TenserTensor/Deprecated/Text Encoders/SDXL" - - def execute(self, context): - clip = context["clip"] - config = context["workflow_config"] - - positive, negative = encode_prompts_sdxl( - clip, - config["clip_l_positive"], - config["clip_g_positive"], - config["clip_l_negative"], - config["clip_g_negative"], - config["ascore_positive"], - config["ascore_negative"], - config["width"], - config["height"], - config["target_width"], - config["target_height"], - ) - - context["positive"] = positive - context["negative"] = negative - - return (context, positive, negative,) diff --git a/nodes/text_encoders/encoder_helpers.py b/nodes/text_encoders/encoder_helpers.py deleted file mode 100644 index 70a9cc2..0000000 --- a/nodes/text_encoders/encoder_helpers.py +++ /dev/null @@ -1,72 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - -from ...lib.common import BasicGuider - - -class Guider_Basic(S.CFGGuider): - def set_conds(self, positive): - self.inner_set_conds({"positive": positive}) - - -def encode_prompts_sdxl(clip, clip_l_positive, clip_g_positive, clip_l_negative, clip_g_negative, - ascore_positive, ascore_negative, width, height, target_width, target_height): - if clip is None: - raise ValueError("ERROR: CLIP is required for text encoder") - - positive_tokens = clip.tokenize(clip_g_positive) - positive_tokens["l"] = clip.tokenize(clip_l_positive)["l"] - negative_tokens = clip.tokenize(clip_g_negative) - negative_tokens["l"] = clip.tokenize(clip_l_negative)["l"] - - return ( - clip.encode_from_tokens_scheduled( - positive_tokens, - add_dict={ - "aesthetic_score": ascore_positive, - "width": width, - "height": height, - "target_width": target_width, - "target_height": target_height, - } - ), - clip.encode_from_tokens_scheduled( - negative_tokens, - add_dict={ - "aesthetic_score": ascore_negative, - "width": width, - "height": height, - "target_width": target_width, - "target_height": target_height, - } - ) - ) - - -def encode_prompts_flux(clip, clip_l_positive, t5xxl_positive, clip_l_negative, t5xxl_negative, guidance): - if clip is None: - raise ValueError("ERROR: CLIP is required for text encoder") - - positive_tokens = clip.tokenize(clip_l_positive) - positive_tokens["t5xxl"] = clip.tokenize(t5xxl_positive)["t5xxl"] - negative_tokens = clip.tokenize(clip_l_negative) - negative_tokens["t5xxl"] = clip.tokenize(t5xxl_negative)["t5xxl"] - - return ( - clip.encode_from_tokens_scheduled(positive_tokens, add_dict={"guidance": guidance, }), - clip.encode_from_tokens_scheduled(negative_tokens, add_dict={"guidance": guidance, }) - ) - - -def encode_prompts_flux2(model, clip, prompt, lora_triggers, guidance): - if clip is None: - raise ValueError("ERROR: CLIP is required for text encoder") - - full_prompt = f"{lora_triggers}, {prompt}" if lora_triggers.strip() else prompt - tokens = clip.tokenize(full_prompt) - conditioning = clip.encode_from_tokens_scheduled(tokens, add_dict={"guidance": guidance, }) - guider = BasicGuider(model) - guider.set_conds(conditioning) - - return (guider,) diff --git a/nodes/vae/vae_decode_context.py b/nodes/vae/vae_decode_context.py deleted file mode 100644 index a53babe..0000000 --- a/nodes/vae/vae_decode_context.py +++ /dev/null @@ -1,31 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) -from .vae_helpers import vae_decode - - -class TT_VaeDecodeContext: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "context": ("TT_CONTEXT",), - } - } - - RETURN_TYPES = ("TT_CONTEXT", "IMAGE",) - RETURN_NAMES = ("CONTEXT", "IMAGE",) - FUNCTION = "vae_decode" - CATEGORY = "TenserTensor/Deprecated/VAE" - - def vae_decode(self, context): - vae = context["vae"] - latent = context["latent"] - - if vae is None: - raise ValueError("ERROR: VAE is required for decode") - if latent is None: - raise ValueError("ERROR: Latent image is required for decode") - - images = vae_decode(latent, vae) - context["image"] = images - - return (context, images,) diff --git a/nodes/vae/vae_decode_tiled.py b/nodes/vae/vae_decode_tiled.py deleted file mode 100644 index b8e6ba3..0000000 --- a/nodes/vae/vae_decode_tiled.py +++ /dev/null @@ -1,27 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - - -from .vae_helpers import vae_decode - - -class TT_VaeDecodeTiled: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "vae": ("VAE",), - "latent": ("LATENT",), - "tile_width": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}), - "tile_height": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}), - "overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}), - "circular": ("BOOLEAN", {"default": False, "label_on": "Enabled", "label_off": "Disabled"}), - } - } - - RETURN_TYPES = ("IMAGE",) - RETURN_NAMES = ("IMAGE",) - FUNCTION = "vae_decode" - CATEGORY = "TenserTensor/Deprecated/VAE" - - def vae_decode(self, latent, vae, tile_width, tile_height, overlap, circular): - return (vae_decode(latent, vae, tile_width, tile_height, overlap, circular),) diff --git a/nodes/vae/vae_encode_context.py b/nodes/vae/vae_encode_context.py deleted file mode 100644 index 9e43f3e..0000000 --- a/nodes/vae/vae_encode_context.py +++ /dev/null @@ -1,32 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .vae_helpers import vae_encode - - -class TT_VaeEncodeContext: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "context": ("TT_CONTEXT",), - } - } - - RETURN_TYPES = ("TT_CONTEXT", "LATENT",) - RETURN_NAMES = ("CONTEXT", "LATENT",) - FUNCTION = "vae_encode" - CATEGORY = "TenserTensor/Deprecated/VAE" - - def vae_encode(self, context): - vae = context["vae"] - image = context["image"] - - if vae is None: - raise ValueError("VAE is required for encode") - if image is None: - raise ValueError("Pixel image is required for encode") - - samples = vae_encode(image, vae) - context["latent"] = samples - - return (context, samples,) diff --git a/nodes/vae/vae_encode_tiled.py b/nodes/vae/vae_encode_tiled.py deleted file mode 100644 index 13d572f..0000000 --- a/nodes/vae/vae_encode_tiled.py +++ /dev/null @@ -1,25 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -from .vae_helpers import vae_encode - - -class TT_VaeEncodeTiled: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "vae": ("VAE",), - "image": ("IMAGE",), - "tile_width": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}), - "tile_height": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}), - "overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}), - } - } - - RETURN_TYPES = ("LATENT",) - RETURN_NAMES = ("LATENT",) - FUNCTION = "vae_encode" - CATEGORY = "TenserTensor/Deprecated/VAE" - - def vae_encode(self, image, vae, tile_width, tile_height, overlap): - return (vae_encode(image, vae, tile_width, tile_height, overlap),) diff --git a/nodes/vae/vae_helpers.py b/nodes/vae/vae_helpers.py deleted file mode 100644 index 7c85049..0000000 --- a/nodes/vae/vae_helpers.py +++ /dev/null @@ -1,38 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import torch - - -def vae_encode(image, vae, tile_width=512, tile_height=512, overlap=64): - samples = vae.encode_tiled( - image, - tile_x=tile_width, - tile_y=tile_height, - overlap=overlap - ) - latent_dict = {"samples": samples} - - return latent_dict - - -def vae_decode(latent, vae, tile_width=512, tile_height=512, overlap=64, circular=False): - samples = latent["samples"] - if samples.is_nested: - samples = samples.unbind()[0] - - if circular == True: - for layer in [layer for layer in vae.first_stage_model.modules() if isinstance(layer, torch.nn.Conv2d)]: - layer.padding_mode = "circular" - - compression = vae.spacial_compression_decode() - images = vae.decode_tiled( - samples, - tile_x=tile_width // compression, - tile_y=tile_height // compression, - overlap=overlap // compression - ) - - if len(images.shape) == 5: - images = images.reshape(-1, images.shape[-3], images.shape[-2], images.shape[-1]) - - return images diff --git a/nodes/workflow/flux2_workflow_settings.py b/nodes/workflow/flux2_workflow_settings.py deleted file mode 100644 index 0486f86..0000000 --- a/nodes/workflow/flux2_workflow_settings.py +++ /dev/null @@ -1,67 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - -from nodes import MAX_RESOLUTION -from .workflow_settings_helpers import get_schedule - - -class TT_Flux2WorkflowSettings: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "cfg": ("FLOAT", {"default": 3.0, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (S.KSampler.SAMPLERS,), - "width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}), - "height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}), - "guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1}) - } - } - - RETURN_TYPES = ( - "TT_WORKFLOW_CONFIG", - "INT", - "INT", - "FLOAT", - "SAMPLER", - S.KSampler.SAMPLERS, - "SIGMAS", - "INT", - "INT", - "FLOAT" - ) - RETURN_NAMES = ( - "WORKFLOW_CONFIG", - "SEED", - "STEPS", - "CFG", - "SAMPLER", - "SAMPLER_NAME", - "SCHEDULER", - "WIDTH", - "HEIGHT", - "GUIDANCE" - ) - FUNCTION = "get_settings" - CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX2" - - def get_settings(self, seed, steps, cfg, sampler_name, width, height, guidance): - scheduler = get_schedule(steps, width, height) - sampler = S.sampler_object(sampler_name) - - workflow_config = { - "seed": seed, - "steps": steps, - "cfg": cfg, - "sampler": sampler, - "sampler_name": sampler_name, - "scheduler": scheduler, - "width": width, - "height": height, - "guidance": guidance - } - - return (workflow_config, seed, steps, cfg, sampler, sampler_name, scheduler, width, height, guidance) diff --git a/nodes/workflow/flux2_workflow_settings_advanced.py b/nodes/workflow/flux2_workflow_settings_advanced.py deleted file mode 100644 index 86b52bf..0000000 --- a/nodes/workflow/flux2_workflow_settings_advanced.py +++ /dev/null @@ -1,75 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - -from nodes import MAX_RESOLUTION -from .workflow_settings_helpers import get_schedule - - -class TT_Flux2WorkflowSettingsAdvanced: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "cfg": ("FLOAT", {"default": 3.0, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (S.KSampler.SAMPLERS,), - "width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}), - "height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}), - "prompt": ("STRING", {"multiline": True, "placeholder": "Prompt", "dynamicPrompts": True}), - "lora_triggers": ("STRING", {"multiline": True, "placeholder": "LoRA Triggers", "dynamicPrompts": True}), - "guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1}) - } - } - - RETURN_TYPES = ( - "TT_WORKFLOW_CONFIG", - "INT", - "INT", - "FLOAT", - S.KSampler.SAMPLERS, - "SAMPLER", - "SIGMAS", - "INT", - "INT", - "STRING", - "STRING", - "FLOAT" - ) - RETURN_NAMES = ( - "WORKFLOW_CONFIG", - "SEED", - "STEPS", - "CFG", - "SAMPLER_NAME", - "SAMPLER", - "SCHEDULER", - "WIDTH", - "HEIGHT", - "PROMPT", - "LORA_TRIGGERS", - "GUIDANCE" - ) - FUNCTION = "get_settings" - CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX2" - - def get_settings(self, seed, steps, cfg, sampler_name, width, height, prompt, lora_triggers, guidance): - scheduler = get_schedule(steps, width, height) - sampler = S.sampler_object(sampler_name) - - workflow_config = { - "seed": seed, - "steps": steps, - "cfg": cfg, - "sampler": sampler, - "sampler_name": sampler_name, - "scheduler": scheduler, - "width": width, - "height": height, - "prompt": prompt, - "lora_triggers": lora_triggers, - "guidance": guidance - } - - return (workflow_config, seed, steps, cfg, sampler_name, sampler, scheduler, width, height, prompt, lora_triggers, guidance) diff --git a/nodes/workflow/flux_workflow_settings.py b/nodes/workflow/flux_workflow_settings.py deleted file mode 100644 index 02dddd9..0000000 --- a/nodes/workflow/flux_workflow_settings.py +++ /dev/null @@ -1,51 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - - -class TT_FluxWorkflowSettings: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (S.KSampler.SAMPLERS,), - "scheduler": (S.KSampler.SCHEDULERS,), - "guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1}) - } - } - - RETURN_TYPES = ( - "TT_WORKFLOW_CONFIG", - "INT", - "INT", - "FLOAT", - S.KSampler.SAMPLERS, - S.KSampler.SCHEDULERS, - "FLOAT" - ) - RETURN_NAMES = ( - "WORKFLOW_CONFIG", - "SEED", - "STEPS", - "CFG", - "SAMPLER_NAME", - "SCHEDULER", - "GUIDANCE" - ) - FUNCTION = "get_settings" - CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX" - - def get_settings(self, seed, steps, cfg, sampler_name, scheduler, guidance, ): - workflow_config = { - "seed": seed, - "steps": steps, - "cfg": cfg, - "sampler_name": sampler_name, - "scheduler": scheduler, - "guidance": guidance - } - - return (workflow_config, seed, steps, cfg, sampler_name, scheduler, guidance) diff --git a/nodes/workflow/flux_workflow_settings_advanced.py b/nodes/workflow/flux_workflow_settings_advanced.py deleted file mode 100644 index a238ee9..0000000 --- a/nodes/workflow/flux_workflow_settings_advanced.py +++ /dev/null @@ -1,68 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - - -class TT_FluxWorkflowSettingsAdvanced: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 25, "min": 1, "max": 10000}), - "cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (S.KSampler.SAMPLERS,), - "scheduler": (S.KSampler.SCHEDULERS,), - "clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}), - "t5xxl_positive": ("STRING", {"multiline": True, "placeholder": "T5XXL Positive", "dynamicPrompts": True}), - "clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}), - "t5xxl_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}), - "guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1}) - } - } - - RETURN_TYPES = ( - "TT_WORKFLOW_CONFIG", - "INT", - "INT", - "FLOAT", - S.KSampler.SAMPLERS, - S.KSampler.SCHEDULERS, - "STRING", - "STRING", - "STRING", - "STRING", - "FLOAT", - ) - RETURN_NAMES = ( - "WORKFLOW_CONFIG", - "SEED", - "STEPS", - "CFG", - "SAMPLER_NAME", - "SCHEDULER", - "CLIP_L_POSITIVE", - "T5XXL_POSITIVE", - "CLIP_L_NEGATIVE", - "T5XXL_NEGATIVE", - "GUIDANCE", - ) - FUNCTION = "get_settings" - CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX" - - def get_settings(self, seed, steps, cfg, sampler_name, scheduler, guidance, clip_l_positive, t5xxl_positive, clip_l_negative, t5xxl_negative): - workflow_config = { - "seed": seed, - "steps": steps, - "cfg": cfg, - "sampler_name": sampler_name, - "scheduler": scheduler, - "clip_l_positive": clip_l_positive, - "t5xxl_positive": t5xxl_positive, - "clip_l_negative": clip_l_negative, - "t5xxl_negative": t5xxl_negative, - "guidance": guidance - } - - return (workflow_config, seed, steps, cfg, sampler_name, scheduler, guidance, clip_l_positive, t5xxl_positive, clip_l_negative, - t5xxl_negative) diff --git a/nodes/workflow/sdxl_workflow_settings.py b/nodes/workflow/sdxl_workflow_settings.py deleted file mode 100644 index b33a516..0000000 --- a/nodes/workflow/sdxl_workflow_settings.py +++ /dev/null @@ -1,49 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - - -class TT_SdxlWorkflowSettings: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 30, "min": 1, "max": 10000}), - "cfg": ("FLOAT", {"default": 7.0, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (S.KSampler.SAMPLERS,), - "scheduler": (S.KSampler.SCHEDULERS,), - } - } - - RETURN_TYPES = ( - "TT_WORKFLOW_CONFIG", - "INT", - "INT", - "FLOAT", - S.KSampler.SAMPLERS, - S.KSampler.SCHEDULERS, - ) - - RETURN_NAMES = ( - "WORKFLOW_CONFIG", - "SEED", - "STEPS", - "CFG", - "SAMPLER_NAME", - "SCHEDULER", - ) - - FUNCTION = "get_settings" - CATEGORY = "TenserTensor/Deprecated/Workflow/SDXL" - - def get_settings(self, seed, steps, cfg, sampler_name, scheduler): - workflow_config = { - "seed": seed, - "steps": steps, - "cfg": cfg, - "sampler_name": sampler_name, - "scheduler": scheduler, - } - - return (workflow_config, seed, steps, cfg, sampler_name, scheduler) diff --git a/nodes/workflow/sdxl_workflow_settings_advanced.py b/nodes/workflow/sdxl_workflow_settings_advanced.py deleted file mode 100644 index e59afe2..0000000 --- a/nodes/workflow/sdxl_workflow_settings_advanced.py +++ /dev/null @@ -1,92 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import comfy.samplers as S - -from nodes import MAX_RESOLUTION - - -class TT_SdxlWorkflowSettingsAdvanced: - @classmethod - def INPUT_TYPES(cls): - return { - "required": { - "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), - "steps": ("INT", {"default": 30, "min": 1, "max": 10000}), - "cfg": ("FLOAT", {"default": 7.0, "min": 0.0, "max": 100.0, "step": 0.1}), - "sampler_name": (S.KSampler.SAMPLERS,), - "scheduler": (S.KSampler.SCHEDULERS,), - "clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}), - "clip_g_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_G Positive", "dynamicPrompts": True}), - "clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}), - "clip_g_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_G Negative", "dynamicPrompts": True}), - "ascore_positive": ("FLOAT", {"default": 9.0, "min": 0.0, "max": 1000.0, "step": 0.1}), - "ascore_negative": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 1000.0, "step": 0.1}), - "width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - "height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - "target_width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - "target_height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}), - } - } - - RETURN_TYPES = ( - "TT_WORKFLOW_CONFIG", - "INT", - "INT", - "FLOAT", - S.KSampler.SAMPLERS, - S.KSampler.SCHEDULERS, - "STRING", - "STRING", - "STRING", - "STRING", - "FLOAT", - "FLOAT", - "INT", - "INT", - "INT", - "INT", - ) - RETURN_NAMES = ( - "WORKFLOW_CONFIG", - "SEED", - "STEPS", - "CFG", - "SAMPLER_NAME", - "SCHEDULER", - "CLIP_L_POSITIVE", - "CLIP_G_POSITIVE", - "CLIP_L_NEGATIVE", - "CLIP_G_NEGATIVE", - "ASCORE_POSITIVE", - "ASCORE_NEGATIVE", - "WIDTH", - "HEIGHT", - "TARGET_WIDTH", - "TARGET_HEIGHT", - ) - FUNCTION = "get_settings" - CATEGORY = "TenserTensor/Deprecated/Workflow/SDXL" - - def get_settings(self, seed, steps, cfg, sampler_name, scheduler, clip_l_positive, clip_g_positive, clip_l_negative, - clip_g_negative, ascore_positive, ascore_negative, width, height, target_width, target_height): - workflow_config = { - "seed": seed, - "steps": steps, - "cfg": cfg, - "sampler_name": sampler_name, - "scheduler": scheduler, - "clip_l_positive": clip_l_positive, - "clip_g_positive": clip_g_positive, - "clip_l_negative": clip_l_negative, - "clip_g_negative": clip_g_negative, - "ascore_positive": ascore_positive, - "ascore_negative": ascore_negative, - "width": width, - "height": height, - "target_width": target_width, - "target_height": target_height, - } - - return (workflow_config, seed, steps, cfg, sampler_name, scheduler, clip_l_positive, clip_g_positive, - clip_l_negative, - clip_g_negative, ascore_positive, ascore_negative, width, height, target_width, target_height) diff --git a/nodes/workflow/workflow_settings_helpers.py b/nodes/workflow/workflow_settings_helpers.py deleted file mode 100644 index e5e3fc5..0000000 --- a/nodes/workflow/workflow_settings_helpers.py +++ /dev/null @@ -1,36 +0,0 @@ -# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) - -import math - -import torch - - -def _compute_empirical_mu(image_seq_len, num_steps): - a1, b1 = 8.73809524e-05, 1.89833333 - a2, b2 = 0.00016927, 0.45666666 - - if image_seq_len > 4300: - mu = a2 * image_seq_len + b2 - return float(mu) - - m_200 = a2 * image_seq_len + b2 - m_10 = a1 * image_seq_len + b1 - - a = (m_200 - m_10) / 190.0 - b = m_200 - 200.0 * a - mu = a * num_steps + b - - return float(mu) - - -def _generalized_time_snr_shift(t, mu, sigma): - return math.exp(mu) / (math.exp(mu) + (1 / t - 1) ** sigma) - - -def get_schedule(num_steps, width, height): - image_seq_len = (width * height / (16 * 16)) - mu = _compute_empirical_mu(image_seq_len, num_steps) - timesteps = torch.linspace(1, 0, num_steps + 1) - timesteps = _generalized_time_snr_shift(timesteps, mu, 1.0) - - return timesteps diff --git a/nodes_context.py b/nodes_context.py index 48b96b3..0b55e5c 100644 --- a/nodes_context.py +++ b/nodes_context.py @@ -3,12 +3,10 @@ import dataclasses import re from dataclasses import dataclass -from typing import override - -import torch from comfy.clip_vision import Output from comfy_api.latest import IO, ComfyExtension, Input + from .nodes_workflow import TTWorkflowSettings, WorkflowSettings CATEGORY = "TenserTensor/Context" @@ -315,44 +313,17 @@ class TT_ContextExtractImageNode(ContextNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class ContextNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[IO.ComfyNode]]: - return [ - TT_BaseContextNode, - TT_BaseContextFlux2Node, - TT_ContextPassthroughNode, - TT_ContextNode, - TT_ContextFlux2Node, - TT_ContextSetGuiderNode, - TT_ContextSetImageNode, - TT_ContextSetLatentNode, - TT_ContextExtractEncoderFlux2Node, - TT_ContextExtractGuidedSamplerFlux2Node, - TT_ContextExtractVaeNode, - TT_ContextExtractImageNode, - ] - - -async def comfy_entrypoint() -> ContextNodesExtension: - return ContextNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_BaseContextNode", - "TT_BaseContextFlux2Node", - "TT_ContextPassthroughNode", - "TT_ContextNode", - "TT_ContextFlux2Node", - "TT_ContextSetGuiderNode", - "TT_ContextSetImageNode", - "TT_ContextSetLatentNode", - "TT_ContextExtractEncoderFlux2Node", - "TT_ContextExtractGuidedSamplerFlux2Node", - "TT_ContextExtractVaeNode", - "TT_ContextExtractImageNode", +NODES = [ + TT_BaseContextNode, + TT_BaseContextFlux2Node, + TT_ContextPassthroughNode, + TT_ContextNode, + TT_ContextFlux2Node, + TT_ContextSetGuiderNode, + TT_ContextSetImageNode, + TT_ContextSetLatentNode, + TT_ContextExtractEncoderFlux2Node, + TT_ContextExtractGuidedSamplerFlux2Node, + TT_ContextExtractVaeNode, + TT_ContextExtractImageNode, ] diff --git a/nodes_controlnet.py b/nodes_controlnet.py index 0749fcd..0835cfc 100644 --- a/nodes_controlnet.py +++ b/nodes_controlnet.py @@ -1,10 +1,9 @@ # (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) -from typing import override - import folder_paths from comfy import controlnet from comfy_api.latest import io, ui, ComfyExtension + from .nodes_image import SingleCondCFGGuider, get_image_files, load_image CATEGORY = "TenserTensor/ControlNet" @@ -170,24 +169,7 @@ class TT_Flux2ApplyControlNetAdvancedNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class ControlNetNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_Flux2ApplyControlNetNode, - TT_Flux2ApplyControlNetAdvancedNode, - ] - - -async def comfy_entrypoint() -> ControlNetNodesExtension: - return ControlNetNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_Flux2ApplyControlNetNode", - "TT_Flux2ApplyControlNetAdvancedNode", +NODES = [ + TT_Flux2ApplyControlNetNode, + TT_Flux2ApplyControlNetAdvancedNode, ] diff --git a/nodes_detector.py b/nodes_detector.py index dbdafe2..3d8f193 100644 --- a/nodes_detector.py +++ b/nodes_detector.py @@ -1,12 +1,10 @@ # (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) -from typing import override - -from kornia.filters import canny - from comfy import model_management from comfy_api.latest import io, ui, ComfyExtension +from kornia.filters import canny + from .nodes_image import get_image_files, load_image CATEGORY = "TenserTensor/Detector" @@ -51,22 +49,6 @@ class TT_CannyEdgeDetectorNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class DetectorNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_CannyEdgeDetectorNode, - ] - - -async def comfy_entrypoint() -> DetectorNodesExtension: - return DetectorNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_CannyEdgeDetectorNode", +NODES = [ + TT_CannyEdgeDetectorNode, ] diff --git a/nodes_image.py b/nodes_image.py index 7484c17..06de666 100644 --- a/nodes_image.py +++ b/nodes_image.py @@ -5,17 +5,17 @@ import math import os from datetime import datetime from pathlib import Path -from typing import override, Any +from typing import Any +import folder_paths import numpy import torch from PIL import Image, ImageOps, ImageSequence -from spandrel import ModelLoader, ImageModelDescriptor - -import folder_paths from comfy import model_management, utils from comfy_api.latest import ComfyExtension, io, ui from node_helpers import conditioning_set_values, pillow +from spandrel import ModelLoader, ImageModelDescriptor + from .nodes_text_encoder import SingleCondCFGGuider from .nodes_vae import vae_encode @@ -478,28 +478,9 @@ class TT_GuiderImageReferenceNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class ImageNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_ImageLoaderResizerNode, - TT_ImagePreviewSaveNode, - TT_ImagePreviewUpscaleSaveNode, - TT_GuiderImageReferenceNode, - ] - - -async def comfy_entrypoint() -> ImageNodesExtension: - return ImageNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_ImageLoaderResizerNode", - "TT_ImagePreviewSaveNode", - "TT_ImagePreviewUpscaleSaveNode", - "TT_GuiderImageReferenceNode", +NODES = [ + TT_ImageLoaderResizerNode, + TT_ImagePreviewSaveNode, + TT_ImagePreviewUpscaleSaveNode, + TT_GuiderImageReferenceNode, ] diff --git a/nodes_latent.py b/nodes_latent.py index f4c01ce..180116a 100644 --- a/nodes_latent.py +++ b/nodes_latent.py @@ -1,13 +1,13 @@ # (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) import math -from typing import Any, override +from typing import Any import torch - from comfy import sample, utils from comfy.latent_formats import SDXL, Flux, Flux2, SD3 from comfy_api.latest import io, ComfyExtension + from .nodes_image import MEGAPIXELS, resize_image, rotate_image, flip_image from .nodes_vae import vae_decode, vae_encode @@ -323,28 +323,9 @@ class TT_LatentMultiTransformOnPixelSpaceNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class LatentNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_LatentFactoryNode, - TT_LatentFactoryByModelNode, - TT_LatentMultiTransformNode, - TT_LatentMultiTransformOnPixelSpaceNode, - ] - - -async def comfy_entrypoint() -> LatentNodesExtension: - return LatentNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_LatentFactoryNode", - "TT_LatentFactoryByModelNode", - "TT_LatentMultiTransformNode", - "TT_LatentMultiTransformOnPixelSpaceNode", +NODES = [ + TT_LatentFactoryNode, + TT_LatentFactoryByModelNode, + TT_LatentMultiTransformNode, + TT_LatentMultiTransformOnPixelSpaceNode, ] diff --git a/nodes_loaders.py b/nodes_loaders.py index df81e88..36d94b3 100644 --- a/nodes_loaders.py +++ b/nodes_loaders.py @@ -8,14 +8,13 @@ import collections import inspect import os -from typing import override - -import torch -from torch import bfloat16, float16, float32, float8_e4m3fn, float8_e5m2, device, tensor import folder_paths +import torch from comfy import sd, model_management, utils, model_sampling, model_patcher, lora, float from comfy_api.latest import io, ComfyExtension +from torch import bfloat16, float16, float32, float8_e4m3fn, float8_e5m2, device, tensor + from nodes import VAELoader, MAX_RESOLUTION from .gguf.dequant import is_quantized, is_torch_compatible from .gguf.loader import gguf_sd_loader, gguf_clip_loader @@ -775,36 +774,13 @@ class TT_Sd35GgufModelsLoaderAdvancedNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class LoaderNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_SdxlModelsLoaderNode, - TT_SdxlModelsLoaderAdvancedNode, - TT_FluxModelsLoaderNode, - TT_FluxModelsLoaderAdvancedNode, - TT_Flux2GgufModelsLoaderNode, - TT_Flux2GgufModelsLoaderAdvancedNode, - TT_Sd35GgufModelsLoaderNode, - TT_Sd35GgufModelsLoaderAdvancedNode, - ] - - -async def comfy_entrypoint() -> LoaderNodesExtension: - return LoaderNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_SdxlModelsLoaderNode", - "TT_SdxlModelsLoaderAdvancedNode", - "TT_FluxModelsLoaderNode", - "TT_FluxModelsLoaderAdvancedNode", - "TT_Flux2GgufModelsLoaderNode", - "TT_Flux2GgufModelsLoaderAdvancedNode", - "TT_Sd35GgufModelsLoaderNode", - "TT_Sd35GgufModelsLoaderAdvancedNode", +NODES = [ + TT_SdxlModelsLoaderNode, + TT_SdxlModelsLoaderAdvancedNode, + TT_FluxModelsLoaderNode, + TT_FluxModelsLoaderAdvancedNode, + TT_Flux2GgufModelsLoaderNode, + TT_Flux2GgufModelsLoaderAdvancedNode, + TT_Sd35GgufModelsLoaderNode, + TT_Sd35GgufModelsLoaderAdvancedNode, ] diff --git a/nodes_postproduction.py b/nodes_postproduction.py index 9d3da1f..06b3924 100644 --- a/nodes_postproduction.py +++ b/nodes_postproduction.py @@ -1,15 +1,14 @@ # (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) from pathlib import Path -from typing import override import colour +import folder_paths import kornia import torch +from comfy_api.latest import ComfyExtension, io from torch.nn import functional -import folder_paths -from comfy_api.latest import ComfyExtension, io from .nodes_image import DEVICES, RESIZE_METHODS, get_upscale_models, upscale CATEGORY = "TenserTensor/Postproduction" @@ -460,32 +459,11 @@ class TT_PostproductionAdvancedNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class PostproductionNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_AddFilmGrainNode, - TT_ApplyLutNode, - TT_ImageEnhancerNode, - TT_QuickImageUpscalerNode, - TT_PostproductionNode, - TT_PostproductionAdvancedNode, - ] - - -async def comfy_entrypoint() -> PostproductionNodesExtension: - return PostproductionNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_AddFilmGrainNode", - 'TT_ApplyLutNode', - 'TT_ImageEnhancerNode', - 'TT_QuickImageUpscalerNode', - 'TT_PostproductionNode', - 'TT_PostproductionAdvancedNode', +NODES = [ + TT_AddFilmGrainNode, + TT_ApplyLutNode, + TT_ImageEnhancerNode, + TT_QuickImageUpscalerNode, + TT_PostproductionNode, + TT_PostproductionAdvancedNode, ] diff --git a/nodes_sampling.py b/nodes_sampling.py index bb822ba..edfe64f 100644 --- a/nodes_sampling.py +++ b/nodes_sampling.py @@ -1,12 +1,10 @@ # (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0) -from typing import override - -import torch - import latent_preview +import torch from comfy import sample, model_management, samplers from comfy_api.latest import ComfyExtension, io + from .nodes_context import Context from .nodes_latent import SCALE_FACTORS, SCALE_METHODS, scale_latent from .nodes_text_encoder import SingleCondCFGGuider @@ -368,32 +366,11 @@ class TT_GuidedUpscaleKSamplerNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class SamplingNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_KSamplerNode, - TT_KSamplerAdvancedNode, - TT_KSamplerContextNode, - TT_KSamplerTwoStageNode, - TT_GuidedKSamplerNode, - TT_GuidedUpscaleKSamplerNode, - ] - - -async def comfy_entrypoint() -> SamplingNodesExtension: - return SamplingNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_KSamplerNode", - "TT_KSamplerAdvancedNode", - "TT_KSamplerContextNode", - "TT_KSamplerTwoStageNode", - "TT_GuidedKSamplerNode", - "TT_GuidedUpscaleKSamplerNode", +NODES = [ + TT_KSamplerNode, + TT_KSamplerAdvancedNode, + TT_KSamplerContextNode, + TT_KSamplerTwoStageNode, + TT_GuidedKSamplerNode, + TT_GuidedUpscaleKSamplerNode, ] diff --git a/nodes_text_encoder.py b/nodes_text_encoder.py index 6e0c4ca..415ae98 100644 --- a/nodes_text_encoder.py +++ b/nodes_text_encoder.py @@ -4,6 +4,7 @@ from typing import override from comfy import samplers from comfy_api.latest import io, ComfyExtension + from nodes import MAX_RESOLUTION from .nodes_context import Context @@ -413,36 +414,13 @@ class TT_Sd35TextEncoderContextNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class TextEncodeNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_SdxlClipTextEncoderNode, - TT_SdxlClipTextEncoderContextNode, - TT_Flux1ClipTextEncoderNode, - TT_Flux1ClipTextEncoderContextNode, - TT_Flux2TextEncoderNode, - TT_Flux2TextEncoderContextNode, - TT_Sd35TextEncoderNode, - TT_Sd35TextEncoderContextNode, - ] - - -async def comfy_entrypoint() -> TextEncodeNodesExtension: - return TextEncodeNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_SdxlClipTextEncoderNode", - "TT_SdxlClipTextEncoderContextNode", - "TT_Flux1ClipTextEncoderNode", - "TT_Flux1ClipTextEncoderContextNode", - "TT_Flux2TextEncoderNode", - "TT_Flux2TextEncoderContextNode", - "TT_Sd35TextEncoderNode", - "TT_Sd35TextEncoderContextNode", +NODES = [ + TT_SdxlClipTextEncoderNode, + TT_SdxlClipTextEncoderContextNode, + TT_Flux1ClipTextEncoderNode, + TT_Flux1ClipTextEncoderContextNode, + TT_Flux2TextEncoderNode, + TT_Flux2TextEncoderContextNode, + TT_Sd35TextEncoderNode, + TT_Sd35TextEncoderContextNode, ] diff --git a/nodes_vae.py b/nodes_vae.py index 83d17e8..2d2d7a6 100644 --- a/nodes_vae.py +++ b/nodes_vae.py @@ -159,6 +159,11 @@ class TT_VaeEncodeContextNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== +NODES=[] + + + + class VaeNodesExtension(ComfyExtension): @override async def get_node_list(self) -> list[type[io.ComfyNode]]: diff --git a/nodes_workflow.py b/nodes_workflow.py index f9ca7e8..cac7a2b 100644 --- a/nodes_workflow.py +++ b/nodes_workflow.py @@ -3,10 +3,8 @@ import dataclasses import math from dataclasses import dataclass -from typing import override import torch - from comfy.samplers import KSampler, sampler_object, Sampler from comfy_api.latest import io, ComfyExtension from nodes import MAX_RESOLUTION @@ -560,36 +558,13 @@ class TT_Sd35GgufWorkflowSettingsAdvancedNode(io.ComfyNode): # V3 entrypoint — registers context nodes with ComfyUI # ============================================================================== -class WorkflowNodesExtension(ComfyExtension): - @override - async def get_node_list(self) -> list[type[io.ComfyNode]]: - return [ - TT_SdxlWorkflowSettingsNode, - TT_SdxlWorkflowSettingsAdvancedNode, - TT_FluxWorkflowSettingsNode, - TT_FluxWorkflowSettingsAdvancedNode, - TT_Flux2WorkflowSettingsNode, - TT_Flux2WorkflowSettingsAdvancedNode, - TT_Sd35GgufWorkflowSettingsNode, - TT_Sd35GgufWorkflowSettingsAdvancedNode, - ] - - -async def comfy_entrypoint() -> WorkflowNodesExtension: - return WorkflowNodesExtension() - - -# ============================================================================== -# Re-exports for backward compatibility -# ============================================================================== - -__all__ = [ - "TT_SdxlWorkflowSettingsNode", - "TT_SdxlWorkflowSettingsAdvancedNode", - "TT_FluxWorkflowSettingsNode", - "TT_FluxWorkflowSettingsAdvancedNode", - "TT_Flux2WorkflowSettingsNode", - "TT_Flux2WorkflowSettingsAdvancedNode", - "TT_Sd35GgufWorkflowSettingsNode", - "TT_Sd35GgufWorkflowSettingsAdvancedNode", +NODES = [ + TT_SdxlWorkflowSettingsNode, + TT_SdxlWorkflowSettingsAdvancedNode, + TT_FluxWorkflowSettingsNode, + TT_FluxWorkflowSettingsAdvancedNode, + TT_Flux2WorkflowSettingsNode, + TT_Flux2WorkflowSettingsAdvancedNode, + TT_Sd35GgufWorkflowSettingsNode, + TT_Sd35GgufWorkflowSettingsAdvancedNode, ] diff --git a/web/docs/TT_AddFilmGrain.md b/web/docs/TT_AddFilmGrain.md deleted file mode 100644 index ddada9a..0000000 --- a/web/docs/TT_AddFilmGrain.md +++ /dev/null @@ -1,34 +0,0 @@ -## TT Add Film Grain *TT_AddFilmGrain* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Add procedural film grain texture to images for a cinematic look. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------|---------|----------|---------------------------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image to add grain to | -| `seed` | INT | Yes | Random seed for grain pattern (0 to 2^64-1, default: 0) | -| `scale` | FLOAT | Yes | Scale of grain texture (0.25-2.0, default: 0.25) | -| `strength` | FLOAT | Yes | Intensity of grain effect (0.0-10.0, default: 0.15) | -| `saturation` | FLOAT | Yes | Color saturation of grain (0.0-2.0, default: 0.2) | -| `toe` | FLOAT | Yes | Toe adjustment for grain distribution (-0.2 to 0.5, default: 0.0) | -| `upscale_mode` | STRING | Yes | Interpolation mode for grain (bilinear/bicubic/lanczos/nearest/area) - advanced | -| `antialias` | BOOLEAN | Yes | Enable antialiasing for grain (default: False) | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|-------------------------------| -| `IMAGE` | IMAGE | Image with applied film grain | - -### Usage - -Add realistic film grain texture to images for a cinematic aesthetic. Adjust scale for grain size, strength for -intensity, and saturation for color. The toe parameter controls the distribution curve of grain in shadows/highlights. -Use different seeds for varied grain patterns. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ApplyLut.md b/web/docs/TT_ApplyLut.md deleted file mode 100644 index cdce266..0000000 --- a/web/docs/TT_ApplyLut.md +++ /dev/null @@ -1,30 +0,0 @@ -## TT Apply LUT *TT_ApplyLut* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Apply color grading LUT (Look-Up Table) to images for professional color correction. - -### Inputs - -| Parameter | Type | Required | Description | -|--------------|----------|----------|----------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image to apply LUT to | -| `lut_file` | LUT_FILE | Yes | LUT file to apply (from LUT directory) - advanced | -| `strength` | FLOAT | Yes | Blend strength of LUT effect (0.0-1.0, default: 1.0) | -| `colorspace` | STRING | Yes | Colorspace for LUT application (linear/logarithmic) - advanced | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|--------------------------------------| -| `IMAGE` | IMAGE | Image with applied LUT color grading | - -### Usage - -Apply professional color grading using LUT files. Place your .cube LUT files in the designated LUT directory. Adjust -strength to blend between original and graded image (1.0 = full LUT, 0.0 = original). Choose colorspace based on your -LUT file's intended working space. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_BaseContext.md b/web/docs/TT_BaseContext.md deleted file mode 100644 index fae7e95..0000000 --- a/web/docs/TT_BaseContext.md +++ /dev/null @@ -1,32 +0,0 @@ -## TT Base Context *TT_BaseContext* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Creates a foundational context object by combining essential workflow components. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------------------|----------|---------------------------------| -| `model` | MODEL | Yes | The diffusion model (UNet/DiT) | -| `clip` | CLIP | Yes | CLIP text encoder | -| `vae` | VAE | Yes | VAE for encoding/decoding | -| `latent` | LATENT | Yes | Latent image tensor | -| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|--------------------------------------------| -| `CONTEXT` | TT_CONTEXT | Dictionary containing all input components | - -### Usage - -Use this node to package your core workflow components into a single context object that can be passed through your -workflow and modified by other context nodes. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ClipTextEncodeFlux.md b/web/docs/TT_ClipTextEncodeFlux.md deleted file mode 100644 index 69ff38d..0000000 --- a/web/docs/TT_ClipTextEncodeFlux.md +++ /dev/null @@ -1,32 +0,0 @@ -## TT CLIP Text Encode FLUX *TT_ClipTextEncodeFlux* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Flux text encoder with separate CLIP-L and T5-XXL prompt inputs. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------|----------|--------------------------------------------------| -| `clip` | CLIP | Yes | CLIP text encoder (dual CLIP-L + T5-XXL) | -| `clip_l_positive` | STRING | Yes | CLIP-L positive prompt (multiline) | -| `t5xxl_positive` | STRING | Yes | T5-XXL positive prompt (multiline) | -| `clip_l_negative` | STRING | Yes | CLIP-L negative prompt (multiline) | -| `t5xxl_negative` | STRING | Yes | T5-XXL negative prompt (multiline) | -| `guidance` | FLOAT | Yes | Guidance scale for Flux (1.0-10.0, default: 3.5) | - -### Outputs - -| Parameter | Type | Description | -|------------|--------------|------------------------------------------| -| `POSITIVE` | CONDITIONING | Positive conditioning from both encoders | -| `NEGATIVE` | CONDITIONING | Negative conditioning from both encoders | - -### Usage - -Encode text prompts for Flux with fine-grained control over CLIP-L and T5-XXL inputs separately. Useful when you want -different prompts for each encoder or need precise control over the conditioning process. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ClipTextEncodeFlux2.md b/web/docs/TT_ClipTextEncodeFlux2.md deleted file mode 100644 index 149f56d..0000000 --- a/web/docs/TT_ClipTextEncodeFlux2.md +++ /dev/null @@ -1,31 +0,0 @@ -## TT Clip Text Encode Flux2 *TT_ClipTextEncodeFlux2* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Text prompt encoder for FLUX2 models with LoRA trigger word support and built-in guidance configuration. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------------|--------|----------|--------------------------------------------------------------| -| `model` | MODEL | Yes | Diffusion model | -| `clip` | CLIP | Yes | CLIP model for text encoding | -| `prompt` | STRING | Yes | Main generation prompt (multiline, supports dynamic prompts) | -| `lora_triggers` | STRING | Yes | LoRA trigger words (multiline, supports dynamic prompts) | -| `guidance` | FLOAT | Yes | Guidance scale for generation (1.0–10.0, default: 3.5) | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|----------------------------------------------------| -| `GUIDER` | GUIDER | Configured guider with encoded prompt and guidance | - -### Usage - -Encodes text prompts specifically for FLUX2 models. Enter your main prompt in `prompt` and any LoRA-specific trigger -words separately in `lora_triggers` — the node combines them internally. Adjust `guidance` to control how strongly -the model follows the prompt (3.5 is a good starting point for FLUX2). - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ClipTextEncodeFlux2Context.md b/web/docs/TT_ClipTextEncodeFlux2Context.md deleted file mode 100644 index c87c98e..0000000 --- a/web/docs/TT_ClipTextEncodeFlux2Context.md +++ /dev/null @@ -1,29 +0,0 @@ -## TT Clip Text Encode Flux2 (Context) *TT_ClipTextEncodeFlux2Context* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Context-based text prompt encoder for FLUX2 models. Extracts model, CLIP, and prompt configuration directly from a TT_CONTEXT object. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|---------------------------------------------------------------------------------------| -| `context` | TT_CONTEXT | Yes | Context object containing `model`, `clip`, and `workflow_config` with prompt settings | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|----------------------------------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context with `guider` written back into it | -| `GUIDER` | GUIDER | Configured guider with encoded prompt and guidance | - -### Usage - -Context-aware version of the FLUX2 text encoder. Instead of individual inputs, it reads `model`, `clip`, and -`workflow_config` (containing `prompt`, `lora_triggers`, and `guidance`) from the passed `context`. The resulting -guider is both returned as an output and stored back into the context under the `guider` key. Raises an error if -any of the required fields are missing from the context. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ClipTextEncodeFluxContext.md b/web/docs/TT_ClipTextEncodeFluxContext.md deleted file mode 100644 index d8a23a9..0000000 --- a/web/docs/TT_ClipTextEncodeFluxContext.md +++ /dev/null @@ -1,34 +0,0 @@ -## TT CLIP Text Encode FLUX (Context) *TT_ClipTextEncodeFluxContext* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Context-based Flux text encoder that extracts prompts from workflow config. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|------------------------------------------------------------------| -| `context` | TT_CONTEXT | Yes | Context containing CLIP encoder and workflow config with prompts | - -### Outputs - -| Parameter | Type | Description | -|------------|--------------|-----------------------------------------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context with positive/negative conditioning added | -| `POSITIVE` | CONDITIONING | Positive conditioning from both encoders | -| `NEGATIVE` | CONDITIONING | Negative conditioning from both encoders | - -### Usage - -Simplified encoder for context-based workflows. Automatically extracts CLIP-L and T5-XXL prompts plus guidance from -workflow_config: - -- `clip_l_positive`, `t5xxl_positive` for positive prompts -- `clip_l_negative`, `t5xxl_negative` for negative prompts -- `guidance` for Flux guidance scale - -Updates context with the generated conditioning and also returns them separately for convenient access. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ClipTextEncodeSdxl.md b/web/docs/TT_ClipTextEncodeSdxl.md deleted file mode 100644 index e4db7c6..0000000 --- a/web/docs/TT_ClipTextEncodeSdxl.md +++ /dev/null @@ -1,37 +0,0 @@ -## TT CLIP Text Encode SDXL *TT_ClipTextEncodeSdxl* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -SDXL text encoder with separate CLIP-L and CLIP-G prompt inputs and conditioning parameters. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------|----------|---------------------------------------------------------| -| `clip` | CLIP | Yes | CLIP text encoder (dual CLIP-L + CLIP-G) | -| `clip_l_positive` | STRING | Yes | CLIP-L positive prompt (multiline) | -| `clip_g_positive` | STRING | Yes | CLIP-G positive prompt (multiline) | -| `clip_l_negative` | STRING | Yes | CLIP-L negative prompt (multiline) | -| `clip_g_negative` | STRING | Yes | CLIP-G negative prompt (multiline) | -| `ascore_positive` | FLOAT | Yes | Aesthetic score for positive (0.0-1000.0, default: 9.0) | -| `ascore_negative` | FLOAT | Yes | Aesthetic score for negative (0.0-1000.0, default: 6.0) | -| `width` | INT | Yes | Image width for conditioning (default: 512) | -| `height` | INT | Yes | Image height for conditioning (default: 512) | -| `target_width` | INT | Yes | Target width for conditioning (default: 512) | -| `target_height` | INT | Yes | Target height for conditioning (default: 512) | - -### Outputs - -| Parameter | Type | Description | -|------------|--------------|-----------------------------------------------------------| -| `POSITIVE` | CONDITIONING | Positive conditioning with aesthetic score and dimensions | -| `NEGATIVE` | CONDITIONING | Negative conditioning with aesthetic score and dimensions | - -### Usage - -Encode text prompts for SDXL with separate control over CLIP-L and CLIP-G inputs, aesthetic scores, and target -dimensions. The aesthetic scores and dimensions are embedded into the conditioning to guide the generation process. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ClipTextEncodeSdxlContext.md b/web/docs/TT_ClipTextEncodeSdxlContext.md deleted file mode 100644 index 0899816..0000000 --- a/web/docs/TT_ClipTextEncodeSdxlContext.md +++ /dev/null @@ -1,35 +0,0 @@ -## TT CLIP Text Encode SDXL (Context) *TT_ClipTextEncodeSdxlContext* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Context-based SDXL text encoder that extracts prompts and parameters from workflow config. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|---------------------------------------------------------------------------------| -| `context` | TT_CONTEXT | Yes | Context containing CLIP encoder and workflow config with prompts and parameters | - -### Outputs - -| Parameter | Type | Description | -|------------|--------------|-----------------------------------------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context with positive/negative conditioning added | -| `POSITIVE` | CONDITIONING | Positive conditioning with aesthetic score and dimensions | -| `NEGATIVE` | CONDITIONING | Negative conditioning with aesthetic score and dimensions | - -### Usage - -Simplified encoder for context-based SDXL workflows. Automatically extracts all encoding parameters from -workflow_config: - -- `clip_l_positive`, `clip_g_positive` for positive prompts -- `clip_l_negative`, `clip_g_negative` for negative prompts -- `ascore_positive`, `ascore_negative` for aesthetic scores -- `width`, `height`, `target_width`, `target_height` for dimensions - -Updates context with the generated conditioning and also returns them separately for convenient access. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Context.md b/web/docs/TT_Context.md deleted file mode 100644 index 9c60bb3..0000000 --- a/web/docs/TT_Context.md +++ /dev/null @@ -1,55 +0,0 @@ -## TT Context *TT_Context* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Standard context node that can create a new context or modify an existing one. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------------------|----------|-----------------------------------------------------------| -| `context` | TT_CONTEXT | No | Existing context to modify (if not provided, creates new) | -| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings | -| `model` | MODEL | No | The diffusion model (UNet/DiT) | -| `clip` | CLIP | No | CLIP text encoder | -| `vae` | VAE | No | VAE for encoding/decoding | -| `positive` | CONDITIONING | No | Positive conditioning | -| `negative` | CONDITIONING | No | Negative conditioning | -| `latent` | LATENT | No | Latent image tensor | -| `image` | IMAGE | No | Image tensor | -| `seed` | INT | No | Random seed | -| `steps` | INT | No | Sampling steps | -| `cfg` | FLOAT | No | Classifier-free guidance scale | -| `sampler_name` | COMBO | No | Sampler name | -| `scheduler` | COMBO | No | Scheduler name | - -### Outputs - -| Parameter | Type | Description | -|-------------------|--------------------|-----------------------------| -| `CONTEXT` | TT_CONTEXT | Created or modified context | -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration | -| `MODEL` | MODEL | Diffusion model | -| `CLIP` | CLIP | Text encoder | -| `VAE` | VAE | VAE | -| `POSITIVE` | CONDITIONING | Positive conditioning | -| `NEGATIVE` | CONDITIONING | Negative conditioning | -| `LATENT` | LATENT | Latent tensor | -| `IMAGE` | IMAGE | Image tensor | -| `SEED` | INT | Random seed | -| `STEPS` | INT | Sampling steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER_NAME` | COMBO | Sampler name | -| `SCHEDULER` | COMBO | Scheduler name | - -### Usage - -Use this node to create a new context from scratch or modify specific parameters in an existing context. All parameters -are optional - provide only what you need to set or change. - - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ContextExtractEncoderFlux2.md b/web/docs/TT_ContextExtractEncoderFlux2.md deleted file mode 100644 index c3f9350..0000000 --- a/web/docs/TT_ContextExtractEncoderFlux2.md +++ /dev/null @@ -1,32 +0,0 @@ -## TT Context Extract Encoder FLUX2 *TT_ContextExtractEncoderFlux2* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Extracts model, clip, prompt, LoRA triggers, and guidance from the context for direct connection to a FLUX2 -text encoder node. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|----------------| -| `context` | TT_CONTEXT | Yes | Context object | - -### Outputs - -| Parameter | Type | Description | -|-----------------|------------|---------------------------------| -| `CONTEXT` | TT_CONTEXT | Passthrough context object | -| `MODEL` | MODEL | Diffusion model | -| `CLIP` | CLIP | CLIP text encoder | -| `PROMPT` | STRING | Main generation prompt | -| `LORA_TRIGGERS` | STRING | LoRA trigger words | -| `GUIDANCE` | FLOAT | Guidance scale for text encoder | - -### Usage - -Use this node to extract encoding parameters from the context and connect them directly to a FLUX2 text -encoder node without manually routing each wire. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ContextExtractEncoderFlux2Node.md b/web/docs/TT_ContextExtractEncoderFlux2Node.md new file mode 100644 index 0000000..0d6931d --- /dev/null +++ b/web/docs/TT_ContextExtractEncoderFlux2Node.md @@ -0,0 +1,30 @@ +## TT Context Extract Encoder (FLUX2) *TT_ContextExtractEncoderFlux2Node* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Extracts model, CLIP, and encoding parameters from a context object for use with a FLUX2 text encoder node. + +### Inputs + +| Parameter | Type | Required | Description | +|-----------|------------|----------|----------------------------------------------| +| `context` | TT_CONTEXT | Yes | Context object from an upstream context node | + +### Outputs + +| Parameter | Type | Description | +|-----------------|------------|---------------------| +| `CONTEXT` | TT_CONTEXT | Context passthrough | +| `MODEL` | MODEL | Diffusion model | +| `CLIP` | CLIP | CLIP text encoder | +| `PROMPT` | STRING | Text prompt | +| `LORA_TRIGGERS` | STRING | LoRA trigger words | +| `GUIDANCE` | FLOAT | Guidance scale | + +### Usage + +Connect `CONTEXT` from a FLUX2 context node. Connect outputs to a FLUX2 text encoder node. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ContextExtractGuidedSamplerFlux2Node.md b/web/docs/TT_ContextExtractGuidedSamplerFlux2Node.md new file mode 100644 index 0000000..4bffd9c --- /dev/null +++ b/web/docs/TT_ContextExtractGuidedSamplerFlux2Node.md @@ -0,0 +1,30 @@ +## TT Context Extract Guided Sampler (FLUX2) *TT_ContextExtractGuidedSamplerFlux2Node* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Extracts latent, guider, sigmas, sampler, and noise from a context object for use with a FLUX2 guided sampler node. + +### Inputs + +| Parameter | Type | Required | Description | +|-----------|------------|----------|----------------------------------------------| +| `context` | TT_CONTEXT | Yes | Context object from an upstream context node | + +### Outputs + +| Parameter | Type | Description | +|-------------|------------|-------------------------------------| +| `CONTEXT` | TT_CONTEXT | Context passthrough | +| `LATENT` | LATENT | Latent tensor | +| `GUIDER` | GUIDER | Configured guider with conditioning | +| `SIGMAS` | SIGMAS | Noise schedule | +| `SAMPLER` | SAMPLER | Sampler algorithm | +| `RND_NOISE` | NOISE | Noise generator with seed | + +### Usage + +Connect `CONTEXT` from a FLUX2 context node. Connect outputs directly to a guided sampler node. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ContextNode.md b/web/docs/TT_ContextNode.md index c7c2f04..dda599d 100644 --- a/web/docs/TT_ContextNode.md +++ b/web/docs/TT_ContextNode.md @@ -2,47 +2,46 @@ *This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* -General-purpose context node for FLUX and SDXL workflows. Accepts any combination of pipeline fields and -merges them into the context object. All fields are optional. +General-purpose context node for FLUX and SDXL workflows. Merges or updates fields in an existing context object. All fields are optional. ### Inputs -| Parameter | Type | Required | Description | -|-------------------|--------------------|----------|-------------------------------| -| `context` | TT_CONTEXT | No | Existing context to update | -| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration object | -| `model` | MODEL | No | Diffusion model | -| `clip` | CLIP | No | CLIP text encoder | -| `vae` | VAE | No | VAE encoder/decoder | -| `latent` | LATENT | No | Latent image tensor | -| `positive` | CONDITIONING | No | Positive conditioning | -| `negative` | CONDITIONING | No | Negative conditioning | -| `image` | IMAGE | No | Pixel-space image | -| `seed` | INT | No | Generation seed | -| `steps` | INT | No | Number of sampling steps | -| `cfg` | FLOAT | No | CFG scale | +| Parameter | Type | Required | Description | +|-------------------|--------------------|----------|-----------------------------------| +| `context` | TT_CONTEXT | No | Existing context object to update | +| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration object | +| `model` | MODEL | No | Diffusion model | +| `clip` | CLIP | No | CLIP text encoder | +| `vae` | VAE | No | VAE encoder/decoder | +| `latent` | LATENT | No | Latent tensor | +| `positive` | CONDITIONING | No | Positive conditioning | +| `negative` | CONDITIONING | No | Negative conditioning | +| `image` | IMAGE | No | Image tensor | +| `seed` | INT | No | Sampling seed | +| `steps` | INT | No | Number of denoising steps | +| `cfg` | FLOAT | No | Classifier-free guidance scale | ### Outputs -| Parameter | Type | Description | -|-------------------|--------------------|--------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context object | -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration | -| `MODEL` | MODEL | Diffusion model | -| `CLIP` | CLIP | CLIP text encoder | -| `VAE` | VAE | VAE encoder/decoder | -| `LATENT` | LATENT | Latent image tensor | -| `POSITIVE` | CONDITIONING | Positive conditioning | -| `NEGATIVE` | CONDITIONING | Negative conditioning | -| `IMAGE` | IMAGE | Pixel-space image | -| `SEED` | INT | Generation seed | -| `STEPS` | INT | Number of sampling steps | -| `CFG` | FLOAT | CFG scale | +| Parameter | Type | Description | +|-------------------|--------------------|-----------------------------------| +| `CONTEXT` | TT_CONTEXT | Updated context object | +| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow config passthrough | +| `MODEL` | MODEL | Model passthrough | +| `CLIP` | CLIP | CLIP passthrough | +| `VAE` | VAE | VAE passthrough | +| `LATENT` | LATENT | Latent passthrough | +| `POSITIVE` | CONDITIONING | Positive conditioning passthrough | +| `NEGATIVE` | CONDITIONING | Negative conditioning passthrough | +| `IMAGE` | IMAGE | Image passthrough | +| `SEED` | INT | Seed passthrough | +| `STEPS` | INT | Steps passthrough | +| `CFG` | FLOAT | CFG passthrough | ### Usage -Use this node to create or update a context object with any combination of pipeline fields. If `context` is -connected, existing fields are updated with the provided values. If not connected, a new context is created. +Use to update or extend an existing context object mid-pipeline. Connect `context` from an upstream context node and override only the fields you +need. --- diff --git a/web/docs/TT_ContextPassthrough.md b/web/docs/TT_ContextPassthrough.md deleted file mode 100644 index 99f6de2..0000000 --- a/web/docs/TT_ContextPassthrough.md +++ /dev/null @@ -1,28 +0,0 @@ -## TT Context Passthrough *TT_ContextPassthrough* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Pass-through node that forwards context while allowing optional parameter modifications. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|-------------------------------| -| `context` | TT_CONTEXT | Yes | Input context to pass through | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|---------------------------------------------| -| `CONTEXT` | TT_CONTEXT | Context with optionally modified parameters | - -### Usage - -Use this node to pass context through your workflow while optionally modifying specific parameters without changing the -rest of the context. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ContextSetGuider.md b/web/docs/TT_ContextSetGuider.md deleted file mode 100644 index f996bfd..0000000 --- a/web/docs/TT_ContextSetGuider.md +++ /dev/null @@ -1,29 +0,0 @@ -## TT Context Set Guider *TT_ContextSetGuider* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Writes a GUIDER object into the TT_CONTEXT, making it available for downstream context-aware nodes. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|--------------------------------| -| `context` | TT_CONTEXT | Yes | Context object to update | -| `guider` | GUIDER | Yes | Guider to store in the context | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|-----------------------------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context with `guider` written into it | - -### Usage - -Sets the `guider` field inside a TT_CONTEXT object. Use this node when you have a guider produced outside the -context pipeline and need to inject it back in for use by subsequent context-aware nodes. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ContextSetImage.md b/web/docs/TT_ContextSetImage.md deleted file mode 100644 index 7c65c0d..0000000 --- a/web/docs/TT_ContextSetImage.md +++ /dev/null @@ -1,28 +0,0 @@ -## TT Context Set Image *TT_ContextSetImage* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Adds or updates image in context object. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|---------------------------| -| `context` | TT_CONTEXT | Yes | Context to update | -| `image` | IMAGE | Yes | Image to store in context | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context object | - -### Usage - -Stores pixel-space image in context for use by downstream nodes. Overwrites existing image if present. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ContextSetLatent.md b/web/docs/TT_ContextSetLatent.md deleted file mode 100644 index fe4771f..0000000 --- a/web/docs/TT_ContextSetLatent.md +++ /dev/null @@ -1,28 +0,0 @@ -## TT Context Set Image *TT_ContextSetImage* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Adds or updates latent image in context object. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|----------------------------------| -| `context` | TT_CONTEXT | Yes | Context to update | -| `latent` | LATENT | Yes | Latent image to store in context | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context object | - -### Usage - -Stores latent representation in context for use by downstream nodes. Overwrites existing latent if present. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_EvenLargerContext.md b/web/docs/TT_EvenLargerContext.md deleted file mode 100644 index 91dba95..0000000 --- a/web/docs/TT_EvenLargerContext.md +++ /dev/null @@ -1,84 +0,0 @@ -## TT Even Larger Context *TT_EvenLargerContext* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Maximum capacity context node supporting all workflow parameters including ControlNet and masking. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------------------|----------|-----------------------------------------------------------| -| `context` | TT_CONTEXT | No | Existing context to modify (if not provided, creates new) | -| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings | -| `model` | MODEL | No | The diffusion model (UNet/DiT) | -| `clip` | CLIP | No | CLIP text encoder | -| `vae` | VAE | No | VAE for encoding/decoding | -| `positive` | CONDITIONING | No | Positive conditioning | -| `negative` | CONDITIONING | No | Negative conditioning | -| `latent` | LATENT | No | Latent image tensor | -| `image` | IMAGE | No | Image tensor | -| `mask` | MASK | No | Image mask | -| `control_net` | CONTROL_NET | No | ControlNet model | -| `seed` | INT | No | Random seed | -| `steps` | INT | No | Sampling steps | -| `cfg` | FLOAT | No | Classifier-free guidance scale | -| `sampler_name` | COMBO | No | Sampler name | -| `scheduler` | COMBO | No | Scheduler name | -| `guidance` | FLOAT | No | Guidance value | -| `clip_l_positive` | STRING | No | CLIP-L positive prompt | -| `clip_g_positive` | STRING | No | CLIP-G positive prompt | -| `t5xxl_positive` | STRING | No | T5-XXL positive prompt | -| `clip_l_negative` | STRING | No | CLIP-L negative prompt | -| `clip_g_negative` | STRING | No | CLIP-G negative prompt | -| `t5xxl_negative` | STRING | No | T5-XXL negative prompt | -| `ascore_positive` | FLOAT | No | Aesthetic score for positive | -| `ascore_negative` | FLOAT | No | Aesthetic score for negative | -| `width` | INT | No | Image width | -| `height` | INT | No | Image height | -| `target_width` | INT | No | Target width for conditioning | -| `target_height` | INT | No | Target height for conditioning | - -### Outputs - -| Parameter | Type | Description | -|-------------------|--------------------|-----------------------------| -| `CONTEXT` | TT_CONTEXT | Created or modified context | -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration | -| `MODEL` | MODEL | Diffusion model | -| `CLIP` | CLIP | Text encoder | -| `VAE` | VAE | VAE | -| `POSITIVE` | CONDITIONING | Positive conditioning | -| `NEGATIVE` | CONDITIONING | Negative conditioning | -| `LATENT` | LATENT | Latent tensor | -| `IMAGE` | IMAGE | Image tensor | -| `MASK` | MASK | Image mask | -| `CONTROL_NET` | CONTROL_NET | ControlNet | -| `SEED` | INT | Random seed | -| `STEPS` | INT | Sampling steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER_NAME` | COMBO | Sampler name | -| `SCHEDULER` | COMBO | Scheduler name | -| `GUIDANCE` | FLOAT | Guidance value | -| `CLIP_L_POSITIVE` | STRING | CLIP-L positive | -| `CLIP_G_POSITIVE` | STRING | CLIP-G positive | -| `T5XXL_POSITIVE` | STRING | T5-XXL positive | -| `CLIP_L_NEGATIVE` | STRING | CLIP-L negative | -| `CLIP_G_NEGATIVE` | STRING | CLIP-G negative | -| `T5XXL_NEGATIVE` | STRING | T5-XXL negative | -| `ASCORE_POSITIVE` | FLOAT | Aesthetic score positive | -| `ASCORE_NEGATIVE` | FLOAT | Aesthetic score negative | -| `WIDTH` | INT | Width | -| `HEIGHT` | INT | Height | -| `TARGET_WIDTH` | INT | Target width | -| `TARGET_HEIGHT` | INT | Target height | - -### Usage - -Use this node when you need comprehensive control over all workflow parameters including ControlNet and masking. -Supports both SDXL (CLIP-L/G) and Flux (T5-XXL) conditioning simultaneously. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Flux2ApplyControlNetAdvancedNode.md b/web/docs/TT_Flux2ApplyControlNetAdvancedNode.md new file mode 100644 index 0000000..e8723f9 --- /dev/null +++ b/web/docs/TT_Flux2ApplyControlNetAdvancedNode.md @@ -0,0 +1,36 @@ +## TT FLUX2 Apply ControlNet (Advanced) *TT_Flux2ApplyControlNetAdvancedNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Extended version of TT FLUX2 Apply ControlNet with built-in image picker and reference image preview. Supports both connected image input and file +browser selection. + +### Inputs + +| Parameter | Type | Required | Description | +|-----------------------|------------|----------|-----------------------------------------------------------------------------------------------| +| `guider` | GUIDER | Yes | Configured guider from a FLUX2 context or workflow settings node | +| `control_net_opt` | CONTROLNET | No | Preloaded ControlNet object. If provided, `control_net` combo is ignored | +| `reference_image_opt` | IMAGE | No | Connected reference image. If provided, `reference_image` file picker is ignored | +| `vae_opt` | VAE | No | Optional VAE for image preprocessing | +| `control_net` | COMBO | Yes | ControlNet model file from `models/controlnet` | +| `strength` | FLOAT | No | ControlNet influence strength. Default: `1.0`, range: `0.0` to `10.0`. Set to `0.0` to bypass | +| `start_percent` | FLOAT | No | Step percentage at which ControlNet starts. Default: `0.0` | +| `end_percent` | FLOAT | No | Step percentage at which ControlNet ends. Default: `100.0` | +| `reference_image` | COMBO | No | Reference image file picker with upload support | + +### Outputs + +| Parameter | Type | Description | +|-----------|--------|--------------------------------| +| `GUIDER` | GUIDER | Guider with ControlNet applied | + +### Usage + +Connect `GUIDER` from a FLUX2 workflow settings or context node. Use `reference_image_opt` to pass an image from another node, or use the built-in +file picker to load from disk. Reference image is displayed as a preview after execution. Set `strength=0.0` to bypass ControlNet without +disconnecting the node. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Flux2ApplyControlNetNode.md b/web/docs/TT_Flux2ApplyControlNetNode.md new file mode 100644 index 0000000..6a3ef46 --- /dev/null +++ b/web/docs/TT_Flux2ApplyControlNetNode.md @@ -0,0 +1,33 @@ +## TT FLUX2 Apply ControlNet *TT_Flux2ApplyControlNetNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Applies a ControlNet to a FLUX2 guider using a reference image. Supports preloaded ControlNet objects and optional VAE for image preprocessing. + +### Inputs + +| Parameter | Type | Required | Description | +|-------------------|------------|----------|-----------------------------------------------------------------------------------------------| +| `guider` | GUIDER | Yes | Configured guider from a FLUX2 context or workflow settings node | +| `reference_image` | IMAGE | Yes | Reference image for ControlNet conditioning | +| `control_net_opt` | CONTROLNET | No | Preloaded ControlNet object. If provided, `control_net` combo is ignored | +| `vae_opt` | VAE | No | Optional VAE for image preprocessing | +| `control_net` | COMBO | Yes | ControlNet model file from `models/controlnet` | +| `strength` | FLOAT | No | ControlNet influence strength. Default: `1.0`, range: `0.0` to `10.0`. Set to `0.0` to bypass | +| `start_percent` | FLOAT | No | Step percentage at which ControlNet starts. Default: `0.0` | +| `end_percent` | FLOAT | No | Step percentage at which ControlNet ends. Default: `100.0` | + +### Outputs + +| Parameter | Type | Description | +|-----------|--------|--------------------------------| +| `GUIDER` | GUIDER | Guider with ControlNet applied | + +### Usage + +Connect `GUIDER` from a FLUX2 workflow settings or context node. Connect output `GUIDER` to a guided sampler node. Set `strength=0.0` to bypass +ControlNet without disconnecting the node. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Flux2GgufModelsLoader.md b/web/docs/TT_Flux2GgufModelsLoader.md deleted file mode 100644 index e9857cf..0000000 --- a/web/docs/TT_Flux2GgufModelsLoader.md +++ /dev/null @@ -1,30 +0,0 @@ -## TT FLUX2 GGUF Models Loader *TT_GgufModelsLoader* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Load GGUF-quantized diffusion model (UNet), CLIP text encoder, and VAE in a single node. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------|--------|----------|------------------------------------| -| `unet_name` | STRING | Yes | GGUF UNet/diffusion model filename | -| `clip_name` | STRING | Yes | GGUF CLIP text encoder filename | -| `vae_name` | STRING | Yes | VAE model filename | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|------------------------| -| `MODEL` | MODEL | Loaded diffusion model | -| `CLIP` | CLIP | Loaded text encoder | -| `VAE` | VAE | Loaded VAE decoder | - -### Usage - -All-in-one loader for GGUF-quantized FLUX2 models. Place your `.gguf` diffusion model files in the `diffusion_models` or `unet` directory, CLIP files in -`text_encoders` or `clip` directory. VAE can be any standard ComfyUI-compatible VAE file. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Flux2GgufModelsLoaderAdvanced.md b/web/docs/TT_Flux2GgufModelsLoaderAdvanced.md deleted file mode 100644 index f8304f6..0000000 --- a/web/docs/TT_Flux2GgufModelsLoaderAdvanced.md +++ /dev/null @@ -1,42 +0,0 @@ -## TT FLUX2 GGUF Models Loader (Advanced) *TT_GgufModelsLoaderAdvanced* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -All-in-one loader for GGUF-quantized models with extended control over quantization, sampling, and LoRA support. - -### Inputs - -| Parameter | Type | Required | Advanced | Description | -|-----------------------|---------|----------|----------|------------------------------------------------------------------------| -| `unet_name` | STRING | Yes | | GGUF UNet/diffusion model filename | -| `dequant_dtype` | STRING | Yes | Yes | Data type for dequantization (default/target/float32/float16/bfloat16) | -| `patch_dtype` | STRING | Yes | Yes | Data type for weight patching | -| `apply_sampling` | BOOLEAN | Yes | | Enable/disable flux sampling shift patch | -| `base_sampling_shift` | FLOAT | Yes | Yes | Base shift value for flux sampling (default: 0.5) | -| `max_sampling_shift` | FLOAT | Yes | Yes | Maximum shift value for flux sampling (default: 1.15) | -| `sampling_width` | INT | Yes | Yes | Reference width for sampling shift calculation | -| `sampling_height` | INT | Yes | Yes | Reference height for sampling shift calculation | -| `lora_name_1..4` | STRING | Yes | Yes | LoRA filename (None to skip) | -| `strength_1..4` | FLOAT | Yes | Yes | LoRA blend strength (-10.0 to 10.0, default: 1.0) | -| `clip_name` | STRING | Yes | | GGUF CLIP text encoder filename | -| `vae_name` | STRING | Yes | | VAE model filename | -| `vae_device` | STRING | Yes | Yes | Device for VAE (default/cpu) | -| `vae_dtype` | STRING | Yes | Yes | Data type for VAE (bfloat16/float16/float32) | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|------------------------| -| `MODEL` | MODEL | Loaded diffusion model | -| `CLIP` | CLIP | Loaded text encoder | -| `VAE` | VAE | Loaded VAE decoder | - -### Usage - -Extended version of FLUX2 GGUF Models Loader. Supports up to 4 LoRAs loaded simultaneously. Enable `apply_sampling` to apply flux sampling shift patch — -useful for improving quality at non-standard resolutions. Advanced parameters are hidden by default and can be revealed via the node's show/hide -controls. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Flux2WorkflowSettings.md b/web/docs/TT_Flux2WorkflowSettings.md deleted file mode 100644 index da9233a..0000000 --- a/web/docs/TT_Flux2WorkflowSettings.md +++ /dev/null @@ -1,46 +0,0 @@ -## TT Flux2 Workflow Settings *TT_Flux2WorkflowSettings* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Central workflow configuration node for FLUX2 pipelines. Consolidates all sampling parameters into a single -TT_WORKFLOW_CONFIG object while also exposing each value as an individual output. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------|--------|----------|---------------------------------------------------------------------------| -| `seed` | INT | Yes | Generation seed (0 – 18446744073709551615, default: 0) | -| `steps` | INT | Yes | Number of sampling steps (1–10000, default: 25) | -| `cfg` | FLOAT | Yes | CFG scale (0.0–100.0, default: 1.5) | -| `sampler_name` | STRING | Yes | Sampler algorithm (KSampler sampler list) | -| `width` | INT | Yes | Output image width in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) | -| `height` | INT | Yes | Output image height in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) | -| `guidance` | FLOAT | Yes | Guidance scale for text encoder (1.0–10.0, default: 3.5) | - -### Outputs - -| Parameter | Type | Description | -|-------------------|--------------------|------------------------------------------------------| -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Full configuration object with all settings bundled | -| `SEED` | INT | Generation seed | -| `STEPS` | INT | Number of sampling steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER` | SAMPLER | Instantiated sampler object | -| `SAMPLER_NAME` | STRING | Name of the selected sampler | -| `SCHEDULER` | SIGMAS | Computed sigma schedule based on seed and resolution | -| `WIDTH` | INT | Output image width | -| `HEIGHT` | INT | Output image height | -| `GUIDANCE` | FLOAT | Guidance scale | - -### Usage - -Use this node as the single source of truth for FLUX2 workflow parameters. The `WORKFLOW_CONFIG` output is -designed for context-aware nodes that consume a TT_WORKFLOW_CONFIG directly. Individual outputs are available -for connecting to standard ComfyUI nodes. The sigma schedule (`SCHEDULER`) is computed automatically from -the seed and resolution via `get_schedule`. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Flux2WorkflowSettingsAdvanced.md b/web/docs/TT_Flux2WorkflowSettingsAdvanced.md deleted file mode 100644 index a074ab7..0000000 --- a/web/docs/TT_Flux2WorkflowSettingsAdvanced.md +++ /dev/null @@ -1,49 +0,0 @@ -## TT Flux2 Workflow Settings (Advanced) *TT_Flux2WorkflowSettingsAdvanced* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Extended workflow configuration node for FLUX2 pipelines. Includes all parameters from the base version plus -built-in prompt and LoRA trigger fields, bundling everything into a single TT_WORKFLOW_CONFIG object. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------------|--------|----------|---------------------------------------------------------------------------| -| `seed` | INT | Yes | Generation seed (0 – 18446744073709551615, default: 0) | -| `steps` | INT | Yes | Number of sampling steps (1–10000, default: 25) | -| `cfg` | FLOAT | Yes | CFG scale (0.0–100.0, default: 1.5) | -| `sampler_name` | STRING | Yes | Sampler algorithm (KSampler sampler list) | -| `width` | INT | Yes | Output image width in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) | -| `height` | INT | Yes | Output image height in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) | -| `prompt` | STRING | Yes | Main generation prompt (multiline, supports dynamic prompts) | -| `lora_triggers` | STRING | Yes | LoRA trigger words (multiline, supports dynamic prompts) | -| `guidance` | FLOAT | Yes | Guidance scale for text encoder (1.0–10.0, default: 3.5) | - -### Outputs - -| Parameter | Type | Description | -|-------------------|--------------------|------------------------------------------------------| -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Full configuration object with all settings bundled | -| `SEED` | INT | Generation seed | -| `STEPS` | INT | Number of sampling steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER` | SAMPLER | Instantiated sampler object | -| `SAMPLER_NAME` | STRING | Name of the selected sampler | -| `SCHEDULER` | SIGMAS | Computed sigma schedule based on seed and resolution | -| `WIDTH` | INT | Output image width | -| `HEIGHT` | INT | Output image height | -| `PROMPT` | STRING | Main generation prompt | -| `GUIDANCE` | FLOAT | Guidance scale | - -### Usage - -Advanced version of TT Flux2 Workflow Settings with `prompt` and `lora_triggers` fields included directly in the -node. Both are stored in the `WORKFLOW_CONFIG` output alongside all other sampling parameters, making this node -sufficient as the sole configuration source for full context-driven FLUX2 pipelines. Individual outputs remain -available for connecting to standard ComfyUI nodes. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_FluxModelsLoader.md b/web/docs/TT_FluxModelsLoader.md deleted file mode 100644 index 3627dc0..0000000 --- a/web/docs/TT_FluxModelsLoader.md +++ /dev/null @@ -1,32 +0,0 @@ -## TT FLUX Models Loader *TT_FluxModelsLoader* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -All-in-one model loader for Flux workflows. - -### Inputs - -| Parameter | Type | Required | Description | -|---------------|------------|----------|-------------------------------------------------| -| `ckpt_name` | CHECKPOINT | Yes | Flux checkpoint to load | -| `clip_l` | STRING | Yes | CLIP-L text encoder model | -| `t5xxl` | STRING | Yes | T5-XXL text encoder model | -| `clip_device` | STRING | Yes | Device for CLIP ("default" or "cpu") - advanced | -| `vae_name` | VAE | Yes | VAE model to load | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|------------------------------------------| -| `MODEL` | MODEL | Loaded Flux model | -| `CLIP` | CLIP | Combined CLIP-L and T5-XXL text encoders | -| `VAE` | VAE | Loaded VAE | - -### Usage - -Load all Flux model components in one place. Combines CLIP-L and T5-XXL encoders into a dual CLIP for Flux's text -conditioning system. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_FluxModelsLoaderAdvanced.md b/web/docs/TT_FluxModelsLoaderAdvanced.md deleted file mode 100644 index c34c95e..0000000 --- a/web/docs/TT_FluxModelsLoaderAdvanced.md +++ /dev/null @@ -1,49 +0,0 @@ -## TT FLUX Models Loader (Advanced) *TT_FluxModelsLoaderAdvanced* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Extended all-in-one model loader for Flux with sampling patches, LoRA support, and advanced settings. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------------------|------------|----------|------------------------------------------------------------------------------------| -| `unet_name` | CHECKPOINT | Yes | Flux checkpoint to load | -| `unet_dtype` | STRING | Yes | U-Net data type: "default", "fp8_e4m3fn", "fp8_e4m3fn_fast", "fp8_e5m2" - advanced | -| `apply_sampling` | BOOLEAN | Yes | Apply sampling shift patch (default: True) | -| `base_sampling_shift` | FLOAT | Yes | Base sampling shift value (0.0-100.0, default: 0.5) | -| `max_sampling_shift` | FLOAT | Yes | Maximum sampling shift (0.0-100.0, default: 1.15) | -| `sampling_width` | INT | Yes | Width for sampling shift calculation (16-MAX_RESOLUTION, step: 8, default: 1024) | -| `sampling_height` | INT | Yes | Height for sampling shift calculation (16-MAX_RESOLUTION, step: 8, default: 1024) | -| `clip_l` | STRING | Yes | CLIP-L text encoder model | -| `t5xxl` | STRING | Yes | T5-XXL text encoder model | -| `clip_device` | STRING | Yes | Device for CLIP ("default" or "cpu") - advanced | -| `lora_name_1` | LORA | Yes | First LoRA to apply (select "None" to skip) | -| `strength_1` | FLOAT | Yes | Strength for first LoRA (-10.0 to 10.0, default: 1.0) | -| `lora_name_2` | LORA | Yes | Second LoRA to apply (select "None" to skip) | -| `strength_2` | FLOAT | Yes | Strength for second LoRA (-10.0 to 10.0, default: 1.0) | -| `lora_name_3` | LORA | Yes | Third LoRA to apply (select "None" to skip) | -| `strength_3` | FLOAT | Yes | Strength for third LoRA (-10.0 to 10.0, default: 1.0) | -| `lora_name_4` | LORA | Yes | Fourth LoRA to apply (select "None" to skip) | -| `strength_4` | FLOAT | Yes | Strength for fourth LoRA (-10.0 to 10.0, default: 1.0) | -| `vae_name` | VAE | Yes | VAE model to load | -| `vae_device` | STRING | Yes | Device for VAE ("default" or "cpu") - advanced | -| `vae_dtype` | STRING | Yes | Data type for VAE ("bfloat16", "float16", "float32") - advanced | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|-------------------------------------------------------------| -| `MODEL` | MODEL | Loaded Flux model with applied patches and LoRAs | -| `CLIP` | CLIP | Combined CLIP-L and T5-XXL text encoders with applied LoRAs | -| `VAE` | VAE | Loaded VAE | - -### Usage - -Extended Flux loader with optional sampling shift patching for improved high-resolution generation, support for up to 4 -LoRAs, and advanced VAE configuration. The sampling shift patch adjusts noise scheduling based on image dimensions. -LoRAs are cached for efficiency. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_FluxWorkflowSettings.md b/web/docs/TT_FluxWorkflowSettings.md deleted file mode 100644 index 1261f2f..0000000 --- a/web/docs/TT_FluxWorkflowSettings.md +++ /dev/null @@ -1,37 +0,0 @@ -# TT FLUX Workflow Settings *TT_FluxWorkflowSettings* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Node for configuring Flux workflow generation parameters. - -## Inputs - -| Parameter | Type | Default | Range | Description | -|----------------|-------|---------|-------------|--------------------------------------| -| `seed` | INT | 0 | 0 - 2^64-1 | Seed for reproducible results | -| `steps` | INT | 25 | 1 - 10000 | Number of sampling steps | -| `cfg` | FLOAT | 1.5 | 0.0 - 100.0 | CFG scale (classifier-free guidance) | -| `sampler_name` | COMBO | - | - | Sampler name from available list | -| `scheduler` | COMBO | - | - | Scheduler type | -| `guidance` | FLOAT | 3.5 | 1.0 - 10.0 | Guidance strength for Flux | - -## Outputs - -| Output | Type | Description | -|-------------------|--------------------|------------------------------| -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Dictionary with all settings | -| `SEED` | INT | Seed value | -| `STEPS` | INT | Number of steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER_NAME` | COMBO | Sampler name | -| `SCHEDULER` | COMBO | Scheduler | -| `GUIDANCE` | FLOAT | Guidance value | - -## Purpose - -Centralized control of generation settings for Flux models. Allows you to set all main parameters in one place and pass -them through the workflow both as a single config object and as individual values. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_FluxWorkflowSettingsAdvanced.md b/web/docs/TT_FluxWorkflowSettingsAdvanced.md deleted file mode 100644 index b0a5f98..0000000 --- a/web/docs/TT_FluxWorkflowSettingsAdvanced.md +++ /dev/null @@ -1,45 +0,0 @@ -# TT FLUX Workflow Settings (Advanced) *TT_FluxWorkflowSettingsAdvanced* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Advanced node for configuring Flux workflow generation parameters with separate CLIP-L and T5XXL prompts. - -## Inputs - -| Parameter | Type | Default | Range | Description | -|-------------------|--------|---------|-------------|--------------------------------------| -| `seed` | INT | 0 | 0 - 2^64-1 | Seed for reproducible results | -| `steps` | INT | 25 | 1 - 10000 | Number of sampling steps | -| `cfg` | FLOAT | 1.5 | 0.0 - 100.0 | CFG scale (classifier-free guidance) | -| `sampler_name` | COMBO | - | - | Sampler name from available list | -| `scheduler` | COMBO | - | - | Scheduler type | -| `clip_l_positive` | STRING | - | - | Positive prompt for CLIP-L encoder | -| `t5xxl_positive` | STRING | - | - | Positive prompt for T5XXL encoder | -| `clip_l_negative` | STRING | - | - | Negative prompt for CLIP-L encoder | -| `t5xxl_negative` | STRING | - | - | Negative prompt for T5XXL encoder | -| `guidance` | FLOAT | 3.5 | 1.0 - 10.0 | Guidance strength for Flux | - -## Outputs - -| Output | Type | Description | -|-------------------|--------------------|------------------------------| -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Dictionary with all settings | -| `SEED` | INT | Seed value | -| `STEPS` | INT | Number of steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER_NAME` | COMBO | Sampler name | -| `SCHEDULER` | COMBO | Scheduler | -| `CLIP_L_POSITIVE` | STRING | CLIP-L positive prompt | -| `T5XXL_POSITIVE` | STRING | T5XXL positive prompt | -| `CLIP_L_NEGATIVE` | STRING | CLIP-L negative prompt | -| `T5XXL_NEGATIVE` | STRING | T5XXL negative prompt | -| `GUIDANCE` | FLOAT | Guidance value | - -## Purpose - -Extended version of Flux workflow settings with dual-encoder prompt control. Allows separate configuration of CLIP-L and -T5XXL text encoders for precise control over the generation process. Supports dynamic prompts and multiline text input. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_GuidedKSamplerWithPreviewNode.md b/web/docs/TT_GuidedKSamplerWithPreviewNode.md deleted file mode 100644 index 03042f2..0000000 --- a/web/docs/TT_GuidedKSamplerWithPreviewNode.md +++ /dev/null @@ -1,32 +0,0 @@ -## TT Guided KSampler (With Preview) *TT_GuidedKSamplerWithPreviewNode* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Runs guided diffusion sampling with optional step-by-step latent preview in the ComfyUI interface. Identical to TT Guided KSampler with an added -preview toggle. - -### Inputs - -| Parameter | Type | Required | Description | -|------------------|---------|----------|--------------------------------------------| -| `latent` | LATENT | Yes | Input latent tensor | -| `guider` | GUIDER | Yes | Configured Guider with conditioning | -| `sigmas` | SIGMAS | Yes | Noise schedule | -| `sampler` | SAMPLER | Yes | Sampler algorithm | -| `random_noise` | NOISE | Yes | Noise generator with seed | -| `preview_latent` | BOOLEAN | Yes | Show intermediate previews during sampling | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|-----------------------| -| `SAMPLES` | LATENT | Sampled latent tensor | - -### Usage - -Enable `preview_latent` to display latent previews at each sampling step in the node interface. Note: ComfyUI launches with previews disabled by -default — this node overrides that setting automatically. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_GuiderImageReference.md b/web/docs/TT_GuiderImageReference.md deleted file mode 100644 index 2c58d36..0000000 --- a/web/docs/TT_GuiderImageReference.md +++ /dev/null @@ -1,32 +0,0 @@ -## TT Guider Image Reference *TT_GuiderImageReference* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Encode a reference image into latent space and inject it into a Guider's positive conditioning for reference-based generation. - -### Inputs - -| Parameter | Type | Required | Description | -|------------------|--------|----------|---------------------------------------------------------------------------| -| `vae` | VAE | Yes | VAE model used to encode the reference image | -| `guider` | GUIDER | Yes | Guider to inject reference latent into | -| `megapixels` | COMBO | Yes | Target resolution for the reference image before encoding | -| `upscale_method` | STRING | Yes | Resampling method for resizing (default: bicubic) - advanced | -| `dimension_step` | INT | Yes | Snaps image dimensions to multiples of this value (default: 1) - advanced | -| `image` | STRING | Yes | Reference image from input directory | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|---------------------------------------| -| `VAE` | VAE | Passthrough VAE for chaining | -| `GUIDER` | GUIDER | Guider with reference latent injected | - -### Usage - -Loads a reference image, resizes it to the target megapixel resolution, encodes it with VAE, and injects the resulting latent into the Guider's -positive conditioning as `reference_latents`. Raises an error if the Guider has no positive conditioning. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ImageEnhancer.md b/web/docs/TT_ImageEnhancer.md deleted file mode 100644 index 68296cc..0000000 --- a/web/docs/TT_ImageEnhancer.md +++ /dev/null @@ -1,36 +0,0 @@ -## TT Image Enhancer *TT_ImageEnhancer* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Comprehensive image adjustment node with multiple enhancement controls. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------------------|-------|----------|--------------------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image to enhance | -| `brightness_factor` | FLOAT | Yes | Brightness adjustment (-1.0 to 1.0, default: 0.0, 0.0=no effect) | -| `contrast_factor` | FLOAT | Yes | Contrast multiplier (0.0-5.0, default: 1.0, 1.0=no effect) | -| `gamma_factor` | FLOAT | Yes | Gamma correction value (0.0-3.0, default: 1.0, 1.0=no effect) | -| `gamma_gain` | FLOAT | Yes | Gamma gain multiplier (0.0-3.0, default: 1.0, 1.0=no effect) | -| `hue_factor` | FLOAT | Yes | Hue rotation in radians (-π to π, default: 0.0, 0.0=no effect) | -| `saturation_factor` | FLOAT | Yes | Saturation multiplier (0.0-3.0, default: 1.0, 1.0=no effect) | -| `sharpness_factor` | FLOAT | Yes | Sharpness amount (0.0-3.0, default: 0.0, 0.0=no effect) | -| `posterize_bits` | INT | Yes | Bit depth for posterization (0-8, default: 8, 8=no effect) | -| `solarize_thresholds` | FLOAT | Yes | Threshold for solarization effect (0.0-1.0, default: 1.0, 1.0=no effect) | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|-----------------------------------------| -| `IMAGE` | IMAGE | Enhanced image with applied adjustments | - -### Usage - -All-in-one image enhancement node for adjusting brightness, contrast, colors, and applying effects. Use default values ( -brightness: 0.0, contrast/gamma/saturation: 1.0, posterize: 8, solarize: 1.0) for no effect. Adjust individual -parameters as needed - effects are applied sequentially. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ImagePreviewSave.md b/web/docs/TT_ImagePreviewSave.md deleted file mode 100644 index aecfcb1..0000000 --- a/web/docs/TT_ImagePreviewSave.md +++ /dev/null @@ -1,30 +0,0 @@ -## TT Image Preview / Save *TT_ImagePreviewSave* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Combined preview and save node with flexible output options. - -### Inputs - -| Parameter | Type | Required | Description | -|---------------------|---------|----------|-------------------------------------------------------------------------------------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image tensor to preview or save | -| `save_image` | BOOLEAN | Yes | Enable/disable saving to disk (default: Enabled) | -| `filename_prefix` | STRING | Yes | Prefix for output filename (default: "tenser-tensor") | -| `filename_format` | STRING | Yes | Naming pattern: "name-###" (prefix-00001), "date-name-###" (2026-02-16-prefix-00001), "name-datetime" (prefix-20260216-143045) - advanced | -| `subfolder` | STRING | Yes | Optional subfolder within output directory (empty = root output folder) - advanced | -| `image_format` | STRING | Yes | Output format: PNG, JPEG, or WEBP (default: PNG) - advanced | -| `image_quality` | INT | Yes | Quality for JPEG and WEBP formats (0-100, default: 100). Ignored for PNG | -| `compression_level` | INT | Yes | Compression level for PNG format (0-9, default: 9). Ignored for JPEG and WEBP | - -### Outputs - -This is an output node with no return values. Images are displayed in the UI and optionally saved to disk. - -### Usage - -Dual-purpose node that can preview images in the UI and/or save them to disk with extensive formatting options. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_ImagePreviewUpscaleSave.md b/web/docs/TT_ImagePreviewUpscaleSave.md deleted file mode 100644 index 93fd13a..0000000 --- a/web/docs/TT_ImagePreviewUpscaleSave.md +++ /dev/null @@ -1,35 +0,0 @@ -## TT Image Preview / Upscale / Save *TT_ImagePreviewUpscaleSave* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Combined preview, upscale, and save node with flexible output options. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------------|---------|----------|-------------------------------------------------------------------------------------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image tensor to preview, upscale, or save | -| `save_image` | BOOLEAN | Yes | Enable/disable saving to disk (default: Enabled) | -| `filename_prefix` | STRING | Yes | Prefix for output filename (default: "tenser-tensor") | -| `filename_format` | STRING | Yes | Naming pattern: "name-###" (prefix-00001), "date-name-###" (2026-02-16-prefix-00001), "name-datetime" (prefix-20260216-143045) - advanced | -| `subfolder` | STRING | Yes | Optional subfolder within output directory (empty = root output folder) - advanced | -| `image_format` | STRING | Yes | Output format: PNG, JPEG, or WEBP (default: PNG) - advanced | -| `image_quality` | INT | Yes | Quality for JPEG and WEBP formats (0-100, default: 100). Ignored for PNG - advanced | -| `compression_level` | INT | Yes | Compression level for PNG format (0-9, default: 9). Ignored for JPEG and WEBP - advanced | -| `upscale_image` | BOOLEAN | Yes | Enable/disable upscaling (default: Enabled) | -| `upscaler_device` | STRING | Yes | Device for upscaling: "default" or "cpu" - advanced | -| `upscale_model_name` | STRING | Yes | Upscale model selected from available upscale_models - advanced | -| `tile` | INT | Yes | Tile size for tiled upscaling (256-4096, step 64, default: 512) - advanced | -| `overlap` | INT | Yes | Overlap between tiles in pixels (0-256, step 8, default: 64) - advanced | - -### Outputs - -This is an output node with no return values. Images are displayed in the UI and optionally upscaled and saved to disk. - -### Usage - -All-in-one node that can preview, upscale, and save images in a single step. Upscaling is applied before saving — the upscaled result is both displayed in the UI and written to disk. When `upscale_image` is disabled, the original image is used. When `save_image` is disabled, the image is only previewed in the UI without writing to disk. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSampler.md b/web/docs/TT_KSampler.md deleted file mode 100644 index d9c987d..0000000 --- a/web/docs/TT_KSampler.md +++ /dev/null @@ -1,34 +0,0 @@ -## TT KSampler *TT_KSampler* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Standard sampler node for generating images from latents. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------|--------------|----------|-----------------------------------------------------------| -| `model` | MODEL | Yes | The diffusion model to use for sampling | -| `positive` | CONDITIONING | Yes | Positive conditioning (what to generate) | -| `negative` | CONDITIONING | Yes | Negative conditioning (what to avoid) | -| `latent` | LATENT | Yes | Latent image to denoise | -| `seed` | INT | Yes | Random seed for reproducibility (0 to 2^64-1, default: 0) | -| `steps` | INT | Yes | Number of sampling steps (1-10000, default: 25) | -| `cfg` | FLOAT | Yes | Classifier-free guidance scale (0.0-100.0, default: 1.5) | -| `sampler_name` | COMBO | Yes | Sampler algorithm to use | -| `scheduler` | COMBO | Yes | Noise schedule to use | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|-----------------------| -| `LATENT` | LATENT | Denoised latent image | - -### Usage - -Standard KSampler for generating images. Accepts all common sampling parameters and returns a denoised latent ready for -VAE decoding. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSamplerAdvanced.md b/web/docs/TT_KSamplerAdvanced.md deleted file mode 100644 index 1c34575..0000000 --- a/web/docs/TT_KSamplerAdvanced.md +++ /dev/null @@ -1,40 +0,0 @@ -## TT KSampler (Advanced) *TT_KSamplerAdvanced* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Advanced sampler with fine-grained control over denoising steps and noise addition. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------|--------------|----------|-----------------------------------------------------------| -| `model` | MODEL | Yes | The diffusion model to use for sampling | -| `positive` | CONDITIONING | Yes | Positive conditioning (what to generate) | -| `negative` | CONDITIONING | Yes | Negative conditioning (what to avoid) | -| `latent` | LATENT | Yes | Latent image to denoise | -| `add_noise` | BOOLEAN | Yes | Add noise before sampling (default: True) | -| `full_denoise` | BOOLEAN | Yes | Complete full denoising (default: False) | -| `seed` | INT | Yes | Random seed for reproducibility (0 to 2^64-1, default: 0) | -| `steps` | INT | Yes | Total number of sampling steps (1-10000, default: 25) | -| `start_step` | INT | Yes | Step to start sampling from (0-10000, default: 0) | -| `last_step` | INT | Yes | Step to end sampling at (0-10000, default: 10000) | -| `cfg` | FLOAT | Yes | Classifier-free guidance scale (0.0-100.0, default: 1.5) | -| `sampler_name` | COMBO | Yes | Sampler algorithm to use | -| `scheduler` | COMBO | Yes | Noise schedule to use | -| `denoise` | FLOAT | Yes | Denoising strength (0.0-1.0, default: 1.0) | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|-----------------------| -| `LATENT` | LATENT | Denoised latent image | - -### Usage - -Advanced sampler for multi-stage workflows and fine control. Use start_step/last_step for partial denoising, add_noise -to control noise injection, and denoise for strength control. Useful for img2img, refinement passes, and complex -sampling workflows. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSamplerContext.md b/web/docs/TT_KSamplerContext.md deleted file mode 100644 index 452cbfb..0000000 --- a/web/docs/TT_KSamplerContext.md +++ /dev/null @@ -1,31 +0,0 @@ -## TT KSampler (Context) *TT_KSamplerContext* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Context-based sampler that extracts parameters from workflow context. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|---------------------------------------------------------------------| -| `context` | TT_CONTEXT | Yes | Context containing model, latent, conditioning, and workflow config | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|-----------------------| -| `CONTEXT` | TT_CONTEXT | Pass-through context | -| `LATENT` | LATENT | Denoised latent image | - -### Usage - -Simplified sampler for context-based workflows. Automatically extracts all sampling parameters from the context object: - -- Model, positive/negative conditioning, and latent from context -- Seed, steps, cfg, sampler_name, and scheduler from workflow_config - -Requires context to contain: model, latent, and workflow_config. Raises error if any required component is missing. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSamplerGuided.md b/web/docs/TT_KSamplerGuided.md deleted file mode 100644 index dd28806..0000000 --- a/web/docs/TT_KSamplerGuided.md +++ /dev/null @@ -1,31 +0,0 @@ -## TT KSampler (Guided) *TT_KSamplerGuided* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Guided latent sampler that takes a pre-configured guider, sigmas, sampler, and noise to produce denoised latent samples. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------|---------|----------|-----------------------------------------| -| `latent` | LATENT | Yes | Input latent to sample from | -| `guider` | GUIDER | Yes | Configured guider with encoded prompt | -| `sigmas` | SIGMAS | Yes | Sigma schedule for the sampling process | -| `sampler` | SAMPLER | Yes | Instantiated sampler object | -| `random_noise` | NOISE | Yes | Noise source for the diffusion process | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|-------------------------| -| `SAMPLES` | LATENT | Denoised latent samples | - -### Usage - -Runs guided diffusion sampling on the input latent. Connect a guider from a text encoder node, sigmas from a -scheduler, and a sampler from a workflow settings node. `random_noise` controls stochasticity — use a seeded -noise node for reproducible results. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_KSamplerTwoStage.md b/web/docs/TT_KSamplerTwoStage.md deleted file mode 100644 index 206e67c..0000000 --- a/web/docs/TT_KSamplerTwoStage.md +++ /dev/null @@ -1,40 +0,0 @@ -## TT KSampler (Two Stages) *TT_KSamplerTwoStage* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Two-stage sampler with separate draft and refinement passes. - -### Inputs - -| Parameter | Type | Required | Description | -|------------------------|--------------|----------|------------------------------------------------------------| -| `model` | MODEL | Yes | The diffusion model to use for sampling | -| `positive` | CONDITIONING | Yes | Positive conditioning (what to generate) | -| `negative` | CONDITIONING | Yes | Negative conditioning (what to avoid) | -| `latent` | LATENT | Yes | Latent image to denoise | -| `seed` | INT | Yes | Random seed for reproducibility (0 to 2^64-1, default: 0) | -| `cfg` | FLOAT | Yes | Classifier-free guidance scale (0.0-100.0, default: 1.5) | -| `draft_steps` | INT | Yes | Number of steps for draft pass (1-10000, default: 25) | -| `refiner_steps` | INT | Yes | Number of steps for refinement pass (1-10000, default: 25) | -| `draft_sampler_name` | COMBO | Yes | Sampler algorithm for draft pass | -| `draft_scheduler` | COMBO | Yes | Noise schedule for draft pass | -| `refiner_sampler_name` | COMBO | Yes | Sampler algorithm for refinement pass | -| `refiner_scheduler` | COMBO | Yes | Noise schedule for refinement pass | -| `draft_denoise` | FLOAT | Yes | Denoising strength for draft (0.0-1.0, default: 0.7) | -| `refiner_denoise` | FLOAT | Yes | Denoising strength for refinement (0.0-1.0, default: 1.0) | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|-----------------------------------------| -| `LATENT` | LATENT | Fully denoised latent after both passes | - -### Usage - -Automated two-stage sampling workflow. First performs a draft pass with partial denoising, then refines the result with -a second pass. Each stage can use different samplers, schedulers, and step counts. Useful for quick previews followed by -quality refinement, or combining different sampling strategies. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_LargeContextFlux.md b/web/docs/TT_LargeContextFlux.md deleted file mode 100644 index a7f0efc..0000000 --- a/web/docs/TT_LargeContextFlux.md +++ /dev/null @@ -1,68 +0,0 @@ -## TT FLUX Large Context *TT_LargeContextFlux* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Extended context node for Flux workflows with additional CLIP and T5 conditioning inputs. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------------------|----------|-----------------------------------------------------------| -| `context` | TT_CONTEXT | No | Existing context to modify (if not provided, creates new) | -| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings | -| `model` | MODEL | No | The diffusion model (UNet/DiT) | -| `clip` | CLIP | No | CLIP text encoder | -| `vae` | VAE | No | VAE for encoding/decoding | -| `positive` | CONDITIONING | No | Positive conditioning | -| `negative` | CONDITIONING | No | Negative conditioning | -| `latent` | LATENT | No | Latent image tensor | -| `image` | IMAGE | No | Image tensor | -| `seed` | INT | No | Random seed | -| `steps` | INT | No | Sampling steps | -| `cfg` | FLOAT | No | Classifier-free guidance scale | -| `sampler_name` | COMBO | No | Sampler name | -| `scheduler` | COMBO | No | Scheduler name | -| `guidance` | FLOAT | No | Flux guidance value | -| `clip_l_positive` | STRING | No | CLIP-L positive prompt | -| `t5xxl_positive` | STRING | No | T5-XXL positive prompt | -| `clip_l_negative` | STRING | No | CLIP-L negative prompt | -| `t5xxl_negative` | STRING | No | T5-XXL negative prompt | -| `width` | INT | No | Image width | -| `height` | INT | No | Image height | - -### Outputs - -| Parameter | Type | Description | -|-------------------|--------------------|-----------------------------| -| `CONTEXT` | TT_CONTEXT | Created or modified context | -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration | -| `MODEL` | MODEL | Diffusion model | -| `CLIP` | CLIP | Text encoder | -| `VAE` | VAE | VAE | -| `POSITIVE` | CONDITIONING | Positive conditioning | -| `NEGATIVE` | CONDITIONING | Negative conditioning | -| `LATENT` | LATENT | Latent tensor | -| `IMAGE` | IMAGE | Image tensor | -| `SEED` | INT | Random seed | -| `STEPS` | INT | Sampling steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER_NAME` | COMBO | Sampler name | -| `SCHEDULER` | COMBO | Scheduler name | -| `GUIDANCE` | FLOAT | Flux guidance | -| `CLIP_L_POSITIVE` | STRING | CLIP-L positive | -| `T5XXL_POSITIVE` | STRING | T5-XXL positive | -| `CLIP_L_NEGATIVE` | STRING | CLIP-L negative | -| `T5XXL_NEGATIVE` | STRING | T5-XXL negative | -| `WIDTH` | INT | Width | -| `HEIGHT` | INT | Height | - -### Usage - -Use this node for Flux workflows when you need fine-grained control over CLIP-L and T5-XXL prompts separately, along -with Flux-specific guidance settings. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_LargeContextSdxl.md b/web/docs/TT_LargeContextSdxl.md deleted file mode 100644 index 0863973..0000000 --- a/web/docs/TT_LargeContextSdxl.md +++ /dev/null @@ -1,76 +0,0 @@ -## TT SDXL Large Context *TT_LargeContextSdxl* - -⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes. - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Extended context node for SDXL workflows with CLIP-L/G conditioning and aesthetic score inputs. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------------------|----------|-----------------------------------------------------------| -| `context` | TT_CONTEXT | No | Existing context to modify (if not provided, creates new) | -| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings | -| `model` | MODEL | No | The diffusion model (UNet/DiT) | -| `clip` | CLIP | No | CLIP text encoder | -| `vae` | VAE | No | VAE for encoding/decoding | -| `positive` | CONDITIONING | No | Positive conditioning | -| `negative` | CONDITIONING | No | Negative conditioning | -| `latent` | LATENT | No | Latent image tensor | -| `image` | IMAGE | No | Image tensor | -| `seed` | INT | No | Random seed | -| `steps` | INT | No | Sampling steps | -| `cfg` | FLOAT | No | Classifier-free guidance scale | -| `sampler_name` | COMBO | No | Sampler name | -| `scheduler` | COMBO | No | Scheduler name | -| `guidance` | FLOAT | No | SDXL guidance value | -| `clip_l_positive` | STRING | No | CLIP-L positive prompt | -| `clip_g_positive` | STRING | No | CLIP-G positive prompt | -| `clip_l_negative` | STRING | No | CLIP-L negative prompt | -| `clip_g_negative` | STRING | No | CLIP-G negative prompt | -| `ascore_positive` | FLOAT | No | Aesthetic score for positive | -| `ascore_negative` | FLOAT | No | Aesthetic score for negative | -| `width` | INT | No | Image width | -| `height` | INT | No | Image height | -| `target_width` | INT | No | Target width for conditioning | -| `target_height` | INT | No | Target height for conditioning | - -### Outputs - -| Parameter | Type | Description | -|-------------------|--------------------|-----------------------------| -| `CONTEXT` | TT_CONTEXT | Created or modified context | -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration | -| `MODEL` | MODEL | Diffusion model | -| `CLIP` | CLIP | Text encoder | -| `VAE` | VAE | VAE | -| `POSITIVE` | CONDITIONING | Positive conditioning | -| `NEGATIVE` | CONDITIONING | Negative conditioning | -| `LATENT` | LATENT | Latent tensor | -| `IMAGE` | IMAGE | Image tensor | -| `SEED` | INT | Random seed | -| `STEPS` | INT | Sampling steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER_NAME` | COMBO | Sampler name | -| `SCHEDULER` | COMBO | Scheduler name | -| `GUIDANCE` | FLOAT | SDXL guidance | -| `CLIP_L_POSITIVE` | STRING | CLIP-L positive | -| `CLIP_G_POSITIVE` | STRING | CLIP-G positive | -| `CLIP_L_NEGATIVE` | STRING | CLIP-L negative | -| `CLIP_G_NEGATIVE` | STRING | CLIP-G negative | -| `ASCORE_POSITIVE` | FLOAT | Aesthetic score positive | -| `ASCORE_NEGATIVE` | FLOAT | Aesthetic score negative | -| `WIDTH` | INT | Width | -| `HEIGHT` | INT | Height | -| `TARGET_WIDTH` | INT | Target width | -| `TARGET_HEIGHT` | INT | Target height | - -### Usage - -Use this node for SDXL workflows when you need separate control over CLIP-L and CLIP-G prompts, aesthetic scores, and -target dimensions for conditioning. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) \ No newline at end of file diff --git a/web/docs/TT_LatentFactory.md b/web/docs/TT_LatentFactory.md deleted file mode 100644 index f9f8a74..0000000 --- a/web/docs/TT_LatentFactory.md +++ /dev/null @@ -1,44 +0,0 @@ -## TT Latent Factory *TT_LatentFactory* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Generates empty latent images with precise dimension control based on aspect ratio and megapixel count. -Automatically calculates correct dimensions for FLUX and SDXL models, plus separate CLIP conditioning sizes. - -### Inputs - -| Parameter | Type | Required | Description | -|-------------------|--------|----------|---------------------------------------------------------------| -| `seed` | INT | Yes | Seed for reproducible results (0 – 18446744073709551615) | -| `noise_seed` | INT | Yes | Separate seed for noise generation (0 – 18446744073709551615) | -| `aspect_ratio` | STRING | Yes | Image proportions (1:1, 4:3, 3:2, 16:9, 21:9) | -| `megapixels` | COMBO | Yes | Total resolution (0.25 MP, 0.5 MP, 1 MP, 2 MP, 4 MP, 8 MP) | -| `orientation` | STRING | Yes | Image orientation (landscape / portrait) | -| `model_type` | STRING | Yes | Target model architecture (FLUX1.D, FLUX2.D, SDXL) | -| `batch_size` | INT | Yes | Number of latents to generate (1–64, default: 1) - advanced | -| `clip_multiplier` | STRING | Yes | CLIP target size multiplier (1x, 2x, 4x) - advanced | - -### Outputs - -| Parameter | Type | Description | -|-----------------|--------|------------------------------------------| -| `LATENT` | LATENT | Empty latent tensor ready for sampling | -| `RANDOM_NOISE` | NOISE | Noise object seeded with `noise_seed` | -| `SEED` | INT | Generation seed | -| `NOISE_SEED` | INT | Noise seed | -| `MEGAPIXELS` | COMBO | Selected megapixel value for chaining | -| `WIDTH` | INT | Calculated image width (multiple of 64) | -| `HEIGHT` | INT | Calculated image height (multiple of 64) | -| `TARGET_WIDTH` | INT | CLIP conditioning target width | -| `TARGET_HEIGHT` | INT | CLIP conditioning target height | - -### Usage - -Select aspect ratio, resolution, and orientation to automatically compute pixel dimensions suited for the chosen -model. FLUX1.D uses 16-channel latents, FLUX2.D uses 128-channel, SDXL uses 4-channel. `clip_multiplier` scales the TARGET -dimensions relative to the image dimensions — useful for multi-resolution CLIP conditioning. Connect `RANDOM_NOISE` -directly to a sampler node for reproducible noise tied to `noise_seed`. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Postproduction.md b/web/docs/TT_Postproduction.md deleted file mode 100644 index d31223a..0000000 --- a/web/docs/TT_Postproduction.md +++ /dev/null @@ -1,44 +0,0 @@ -## TT Postproduction *TT_Postproduction* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -All-in-one post-production node combining LUT color grading, film grain, and upscaling. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------------|---------------|----------|------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image to process | -| `apply_lut` | BOOLEAN | Yes | Enable LUT color grading (default: True) | -| `lut_file` | LUT_FILE | Yes | LUT file to apply - advanced | -| `lut_strength` | FLOAT | Yes | LUT blend strength (0.0-1.0, default: 1.0) | -| `lut_colorspace` | STRING | Yes | Colorspace for LUT (linear/logarithmic) - advanced | -| `add_film_grain` | BOOLEAN | Yes | Enable film grain effect (default: True) | -| `grain_seed` | INT | Yes | Seed for grain pattern (0 to 2^64-1, default: 0) | -| `grain_scale` | FLOAT | Yes | Grain texture scale (0.25-2.0, default: 0.25) | -| `grain_strength` | FLOAT | Yes | Grain intensity (0.0-10.0, default: 0.2) | -| `grain_saturation` | FLOAT | Yes | Grain color saturation (0.0-2.0, default: 0.5) | -| `grain_toe` | FLOAT | Yes | Grain distribution toe (-0.2 to 0.5, default: 0.05) | -| `grain_upscale_mode` | STRING | Yes | Grain interpolation mode - advanced | -| `grain_antialias` | BOOLEAN | Yes | Grain antialiasing (default: True) | -| `image_upscaler` | BOOLEAN | Yes | Enable image upscaling (default: True) | -| `upscaler_device` | STRING | Yes | Device for upscaler (default/cpu) - advanced | -| `upscale_model_name` | UPSCALE_MODEL | Yes | Upscale model to use - advanced | -| `upscaler_tile` | INT | Yes | Tile size for upscaling (256-4096, step: 64, default: 512) | -| `upscaler_overlap` | INT | Yes | Tile overlap (0-256, step: 8, default: 64) | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|--------------------------------------| -| `IMAGE` | IMAGE | Processed image with applied effects | - -### Usage - -Complete post-production pipeline in one node. Toggle each effect on/off with boolean switches. Processing order: LUT → -Film Grain → Upscale. Disable any effect by setting its toggle to False. All effects are optional and can be used -independently or combined. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_PostproductionAdvanced.md b/web/docs/TT_PostproductionAdvanced.md deleted file mode 100644 index e60b7bd..0000000 --- a/web/docs/TT_PostproductionAdvanced.md +++ /dev/null @@ -1,54 +0,0 @@ -## TT Postproduction (Advanced) *TT_PostproductionAdvanced* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Extended post-production node with image enhancement, LUT color grading, film grain, and upscaling. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------------------|---------------|----------|------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image to process | -| `image_enhancer` | BOOLEAN | Yes | Enable image enhancement (default: True) | -| `brightness_factor` | FLOAT | Yes | Brightness adjustment (-1.0 to 1.0, default: 0.0) | -| `contrast_factor` | FLOAT | Yes | Contrast multiplier (0.0-5.0, default: 1.0) | -| `gamma_factor` | FLOAT | Yes | Gamma correction (0.0-3.0, default: 1.0) | -| `gamma_gain` | FLOAT | Yes | Gamma gain (0.0-3.0, default: 1.0) | -| `hue_factor` | FLOAT | Yes | Hue rotation (-π to π, default: 0.0) | -| `saturation_factor` | FLOAT | Yes | Saturation multiplier (0.0-3.0, default: 1.0) | -| `sharpness_factor` | FLOAT | Yes | Sharpness amount (0.0-3.0, default: 0.0) | -| `posterize_bits` | INT | Yes | Posterization bit depth (0-8, default: 8) | -| `solarize_thresholds` | FLOAT | Yes | Solarization threshold (0.0-1.0, default: 1.0) | -| `apply_lut` | BOOLEAN | Yes | Enable LUT color grading (default: True) | -| `lut_file` | LUT_FILE | Yes | LUT file to apply - advanced | -| `lut_strength` | FLOAT | Yes | LUT blend strength (0.0-1.0, default: 1.0) | -| `lut_colorspace` | STRING | Yes | Colorspace for LUT (linear/logarithmic) - advanced | -| `add_film_grain` | BOOLEAN | Yes | Enable film grain effect (default: True) | -| `grain_seed` | INT | Yes | Seed for grain pattern (0 to 2^64-1, default: 0) | -| `grain_scale` | FLOAT | Yes | Grain texture scale (0.25-2.0, default: 0.25) | -| `grain_strength` | FLOAT | Yes | Grain intensity (0.0-10.0, default: 0.2) | -| `grain_saturation` | FLOAT | Yes | Grain color saturation (0.0-2.0, default: 0.5) | -| `grain_toe` | FLOAT | Yes | Grain distribution toe (-0.2 to 0.5, default: 0.05) | -| `grain_upscale_mode` | STRING | Yes | Grain interpolation mode - advanced | -| `grain_antialias` | BOOLEAN | Yes | Grain antialiasing (default: True) | -| `image_upscaler` | BOOLEAN | Yes | Enable image upscaling (default: True) | -| `upscaler_device` | STRING | Yes | Device for upscaler (default/cpu) - advanced | -| `upscale_model_name` | UPSCALE_MODEL | Yes | Upscale model to use - advanced | -| `upscaler_tile` | INT | Yes | Tile size for upscaling (256-4096, step: 64, default: 512) | -| `upscaler_overlap` | INT | Yes | Tile overlap (0-256, step: 8, default: 64) | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|--------------------------------------| -| `IMAGE` | IMAGE | Processed image with applied effects | - -### Usage - -Complete post-production pipeline with full enhancement controls. Processing order: Image Enhancement → LUT → Film -Grain → Upscale. Toggle each effect on/off independently. Image enhancement includes brightness, contrast, gamma, hue, -saturation, sharpness, posterize, and solarize adjustments. All effects are optional. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_QuickImageUpscaler.md b/web/docs/TT_QuickImageUpscaler.md deleted file mode 100644 index 43e252c..0000000 --- a/web/docs/TT_QuickImageUpscaler.md +++ /dev/null @@ -1,31 +0,0 @@ -## TT Quick Image Upscaler *TT_QuickImageUpscaler* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Tiled image upscaler using AI upscale models. - -### Inputs - -| Parameter | Type | Required | Description | -|----------------------|---------------|----------|-------------------------------------------------------------| -| `image` | IMAGE | Yes | Input image to upscale | -| `device` | STRING | Yes | Device for upscaling (default/cpu) - advanced | -| `upscale_model_name` | UPSCALE_MODEL | Yes | Upscale model to use - advanced | -| `tile` | INT | Yes | Tile size for processing (256-4096, step: 64, default: 512) | -| `overlap` | INT | Yes | Tile overlap to reduce seams (0-256, step: 8, default: 64) | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|----------------| -| `IMAGE` | IMAGE | Upscaled image | - -### Usage - -Quick and simple AI upscaling node using tiled processing for memory efficiency. Select an upscale model from your -upscale_models directory. Adjust tile size based on VRAM - smaller tiles use less memory. Increase overlap to reduce -visible seams between tiles. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Sd35GgufWorkflowSettingsAdvancedNode.md b/web/docs/TT_Sd35GgufWorkflowSettingsAdvancedNode.md new file mode 100644 index 0000000..b036fd1 --- /dev/null +++ b/web/docs/TT_Sd35GgufWorkflowSettingsAdvancedNode.md @@ -0,0 +1,58 @@ +## TT SD3.5 GGUF Workflow Settings (Advanced) *TT_Sd35GgufWorkflowSettingsAdvancedNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Configures sampling parameters for SD3.5 pipelines with full control over all three text encoders, sigma schedule shift, and target resolution +conditioning. + +### Inputs + +| Parameter | Type | Required | Description | +|-------------------|--------|----------|-----------------------------------------------------------------| +| `seed` | INT | No | Sampling seed. Default: `0` | +| `steps` | INT | No | Number of denoising steps. Default: `30`, range: `1` to `10000` | +| `cfg` | FLOAT | No | Classifier-free guidance scale. Default: `5.0` | +| `sampler_name` | COMBO | Yes | Sampler algorithm | +| `schedule_shift` | FLOAT | No | Sigma schedule shift. Default: `3.0`, range: `0.0` to `20.0` | +| `clip_l_positive` | STRING | No | Positive prompt for CLIP-L encoder | +| `clip_g_positive` | STRING | No | Positive prompt for CLIP-G encoder | +| `t5xxl_positive` | STRING | No | Positive prompt for T5-XXL encoder | +| `clip_l_negative` | STRING | No | Negative prompt for CLIP-L encoder | +| `clip_g_negative` | STRING | No | Negative prompt for CLIP-G encoder | +| `t5xxl_negative` | STRING | No | Negative prompt for T5-XXL encoder | +| `lora_triggers` | STRING | No | LoRA trigger words appended to positive prompts | +| `width` | INT | No | Output width in pixels. Default: `1024`, step: `8` | +| `height` | INT | No | Output height in pixels. Default: `1024`, step: `8` | +| `target_width` | INT | No | Target width for resolution conditioning. Default: `1024` | +| `target_height` | INT | No | Target height for resolution conditioning. Default: `1024` | + +### Outputs + +| Parameter | Type | Description | +|-------------------|--------------------|-----------------------------------------| +| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration object | +| `SAMPLER` | SAMPLER | Configured sampler | +| `SIGMAS` | SIGMAS | SD3.5 noise schedule with shift applied | +| `SEED` | INT | Seed passthrough | +| `STEPS` | INT | Steps passthrough | +| `CFG` | FLOAT | CFG passthrough | +| `WIDTH` | INT | Width passthrough | +| `HEIGHT` | INT | Height passthrough | +| `TARGET_WIDTH` | INT | Target width passthrough | +| `TARGET_HEIGHT` | INT | Target height passthrough | +| `CLIP_L_POSITIVE` | STRING | CLIP-L positive prompt passthrough | +| `CLIP_G_POSITIVE` | STRING | CLIP-G positive prompt passthrough | +| `T5XXL_POSITIVE` | STRING | T5-XXL positive prompt passthrough | +| `CLIP_L_NEGATIVE` | STRING | CLIP-L negative prompt passthrough | +| `CLIP_G_NEGATIVE` | STRING | CLIP-G negative prompt passthrough | +| `T5XXL_NEGATIVE` | STRING | T5-XXL negative prompt passthrough | +| `LORA_TRIGGERS` | STRING | LoRA triggers passthrough | + +### Usage + +Connect outputs to a SD3.5 text encoder context node. Use different prompts per encoder for fine-grained control — T5-XXL handles long descriptive +prompts best, CLIP-L and CLIP-G work better with short style tags. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Sd35GgufWorkflowSettingsNode.md b/web/docs/TT_Sd35GgufWorkflowSettingsNode.md new file mode 100644 index 0000000..85387b6 --- /dev/null +++ b/web/docs/TT_Sd35GgufWorkflowSettingsNode.md @@ -0,0 +1,43 @@ +## TT SD3.5 GGUF Workflow Settings *TT_Sd35GgufWorkflowSettingsNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Configures sampling parameters for SD3.5 pipelines. Builds a workflow config object, sampler, and SD3.5-specific sigmas in a single node. + +### Inputs + +| Parameter | Type | Required | Description | +|------------------|-------|----------|-----------------------------------------------------------------| +| `seed` | INT | No | Sampling seed. Default: `0` | +| `steps` | INT | No | Number of denoising steps. Default: `30`, range: `1` to `10000` | +| `cfg` | FLOAT | No | Classifier-free guidance scale. Default: `5.0` | +| `sampler_name` | COMBO | Yes | Sampler algorithm | +| `schedule_shift` | FLOAT | No | Sigma schedule shift. Default: `3.0`, range: `0.0` to `20.0` | +| `width` | INT | No | Output width in pixels. Default: `1024`, step: `8` | +| `height` | INT | No | Output height in pixels. Default: `1024`, step: `8` | +| `target_width` | INT | No | Target width for resolution conditioning. Default: `1024` | +| `target_height` | INT | No | Target height for resolution conditioning. Default: `1024` | + +### Outputs + +| Parameter | Type | Description | +|-------------------|--------------------|-----------------------------------------| +| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration object | +| `SAMPLER` | SAMPLER | Configured sampler | +| `SIGMAS` | SIGMAS | SD3.5 noise schedule with shift applied | +| `SEED` | INT | Seed passthrough | +| `STEPS` | INT | Steps passthrough | +| `CFG` | FLOAT | CFG passthrough | +| `WIDTH` | INT | Width passthrough | +| `HEIGHT` | INT | Height passthrough | +| `TARGET_WIDTH` | INT | Target width passthrough | +| `TARGET_HEIGHT` | INT | Target height passthrough | + +### Usage + +Connect outputs to a SD3.5 text encoder context node. Use `target_width` and `target_height` to match the resolution the model was trained on when +generating at non-standard sizes. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Sd35TextEncoderContextNode.md b/web/docs/TT_Sd35TextEncoderContextNode.md new file mode 100644 index 0000000..1c98970 --- /dev/null +++ b/web/docs/TT_Sd35TextEncoderContextNode.md @@ -0,0 +1,27 @@ +## TT SD3.5 Text Encoder (Context) *TT_Sd35TextEncoderContextNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Encodes text prompts for SD3.5 using all three text encoders (CLIP-L, CLIP-G, T5-XXL) from context and returns a configured Guider object. + +### Inputs + +| Parameter | Type | Required | Description | +|-----------|------------|----------|-------------------------------------------------------------------------| +| `context` | TT_CONTEXT | Yes | Context object containing model, CLIP, prompts, and resolution settings | + +### Outputs + +| Parameter | Type | Description | +|-----------|------------|---------------------------------------------------------| +| `CONTEXT` | TT_CONTEXT | Updated context with guider stored | +| `GUIDER` | GUIDER | Configured guider with encoded conditioning for sampler | + +### Usage + +Connect `CONTEXT` from a SD3.5 workflow settings context node. Connect `GUIDER` to a sampler node. Prompts and resolution are read from context — use +`TT SD3.5 GGUF Workflow Settings (Advanced)` to set per-encoder prompts. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_Sd35TextEncoderNode.md b/web/docs/TT_Sd35TextEncoderNode.md new file mode 100644 index 0000000..0d0073e --- /dev/null +++ b/web/docs/TT_Sd35TextEncoderNode.md @@ -0,0 +1,39 @@ +## TT SD3.5 Text Encoder *TT_Sd35TextEncoderNode* + +*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* + +Encodes text prompts for SD3.5 using all three text encoders (CLIP-L, CLIP-G, T5-XXL) and returns a configured Guider object ready for sampling. + +### Inputs + +| Parameter | Type | Required | Description | +|-------------------|--------|----------|-----------------------------------------------------------| +| `model` | MODEL | Yes | SD3.5 diffusion model | +| `clip` | CLIP | Yes | SD3.5 text encoders (CLIP-L, CLIP-G, T5-XXL) | +| `cfg` | FLOAT | No | Classifier-free guidance scale. Default: `5.0` | +| `clip_l_positive` | STRING | No | Positive prompt for CLIP-L encoder | +| `clip_g_positive` | STRING | No | Positive prompt for CLIP-G encoder | +| `t5xxl_positive` | STRING | No | Positive prompt for T5-XXL encoder | +| `clip_l_negative` | STRING | No | Negative prompt for CLIP-L encoder | +| `clip_g_negative` | STRING | No | Negative prompt for CLIP-G encoder | +| `t5xxl_negative` | STRING | No | Negative prompt for T5-XXL encoder | +| `lora_triggers` | STRING | No | LoRA trigger words appended to positive prompts | +| `width` | INT | No | Output width for resolution conditioning. Default: `512` | +| `height` | INT | No | Output height for resolution conditioning. Default: `512` | +| `target_width` | INT | No | Target width for resolution conditioning. Default: `512` | +| `target_height` | INT | No | Target height for resolution conditioning. Default: `512` | + +### Outputs + +| Parameter | Type | Description | +|-----------|--------|---------------------------------------------------------| +| `GUIDER` | GUIDER | Configured guider with encoded conditioning for sampler | + +### Usage + +Connect `MODEL` and `CLIP` from a SD3.5 models loader node. Connect `GUIDER` to a sampler node. Use different prompts per encoder for fine-grained +control — T5-XXL handles long descriptive prompts best, CLIP-L and CLIP-G work better with short style tags. + +--- + +[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_SdxlModelsLoader.md b/web/docs/TT_SdxlModelsLoader.md deleted file mode 100644 index 756ea4b..0000000 --- a/web/docs/TT_SdxlModelsLoader.md +++ /dev/null @@ -1,34 +0,0 @@ -## TT SDXL Models Loader *TT_SdxlModelsLoader* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -All-in-one model loader for SDXL workflows with checkpoint merging support. - -### Inputs - -| Parameter | Type | Required | Description | -|------------------|--------------|----------|----------------------------------------------------------------| -| `primary_ckpt` | CHECKPOINT | Yes | Primary SDXL checkpoint to load | -| `secondary_ckpt` | CHECKPOINT | Yes | Secondary checkpoint to merge (select "None" to skip) | -| `primary_weight` | FLOAT | Yes | Weight for primary checkpoint in merge (0.0-1.0, default: 1.0) | -| `clip_l` | TEXT_ENCODER | Yes | CLIP-L text encoder model | -| `clip_g` | TEXT_ENCODER | Yes | CLIP-G text encoder model | -| `clip_device` | STRING | Yes | Device for CLIP ("default" or "cpu") - advanced | -| `vae_name` | VAE | Yes | VAE model to load | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|-------------------------------------------| -| `MODEL` | MODEL | Loaded (and optionally merged) SDXL model | -| `CLIP` | CLIP | Combined CLIP-L and CLIP-G text encoders | -| `VAE` | VAE | Loaded VAE | - -### Usage - -Use this node to load all SDXL model components in one place. Optionally merge two checkpoints by selecting a secondary -checkpoint and adjusting the primary_weight (1.0 = 100% primary, 0.5 = 50/50 mix, 0.0 = 100% secondary). - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_SdxlModelsLoaderAdvanced.md b/web/docs/TT_SdxlModelsLoaderAdvanced.md deleted file mode 100644 index 28b4c3f..0000000 --- a/web/docs/TT_SdxlModelsLoaderAdvanced.md +++ /dev/null @@ -1,45 +0,0 @@ -## TT SDXL Models Loader (Advanced) *TT_SdxlModelsLoaderAdvanced* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Extended all-in-one model loader for SDXL with checkpoint merging and LoRA support. - -### Inputs - -| Parameter | Type | Required | Description | -|------------------|--------------|----------|-----------------------------------------------------------------| -| `primary_ckpt` | CHECKPOINT | Yes | Primary SDXL checkpoint to load | -| `secondary_ckpt` | CHECKPOINT | Yes | Secondary checkpoint to merge (select "None" to skip) | -| `primary_weight` | FLOAT | Yes | Weight for primary checkpoint in merge (0.0-1.0, default: 1.0) | -| `clip_l` | TEXT_ENCODER | Yes | CLIP-L text encoder model | -| `clip_g` | TEXT_ENCODER | Yes | CLIP-G text encoder model | -| `clip_device` | STRING | Yes | Device for CLIP ("default" or "cpu") - advanced | -| `lora_name_1` | LORA | Yes | First LoRA to apply (select "None" to skip) | -| `strength_1` | FLOAT | Yes | Strength for first LoRA (-10.0 to 10.0, default: 1.0) | -| `lora_name_2` | LORA | Yes | Second LoRA to apply (select "None" to skip) | -| `strength_2` | FLOAT | Yes | Strength for second LoRA (-10.0 to 10.0, default: 1.0) | -| `lora_name_3` | LORA | Yes | Third LoRA to apply (select "None" to skip) | -| `strength_3` | FLOAT | Yes | Strength for third LoRA (-10.0 to 10.0, default: 1.0) | -| `lora_name_4` | LORA | Yes | Fourth LoRA to apply (select "None" to skip) | -| `strength_4` | FLOAT | Yes | Strength for fourth LoRA (-10.0 to 10.0, default: 1.0) | -| `vae_name` | VAE | Yes | VAE model to load | -| `vae_device` | STRING | Yes | Device for VAE ("default" or "cpu") - advanced | -| `vae_dtype` | STRING | Yes | Data type for VAE ("bfloat16", "float16", "float32") - advanced | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|-------------------------------------------------------------| -| `MODEL` | MODEL | Loaded model with applied LoRAs and optional merge | -| `CLIP` | CLIP | Combined CLIP-L and CLIP-G text encoders with applied LoRAs | -| `VAE` | VAE | Loaded VAE | - -### Usage - -Extended version of the SDXL loader with support for up to 4 LoRAs and additional VAE configuration options. Load all -model components, optionally merge checkpoints, apply LoRAs sequentially, and configure device/dtype settings for CLIP -and VAE. LoRAs are cached for efficiency. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_SdxlWorkflowSettings.md b/web/docs/TT_SdxlWorkflowSettings.md deleted file mode 100644 index f16cf20..0000000 --- a/web/docs/TT_SdxlWorkflowSettings.md +++ /dev/null @@ -1,36 +0,0 @@ -# TT SDXL Workflow Settings *TT_SdxlWorkflowSettings* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Node for configuring SDXL workflow generation parameters. - -## Inputs - -| Parameter | Type | Default | Range | Description | -|----------------|-------|---------|-------------|--------------------------------------| -| `seed` | INT | 0 | 0 - 2^64-1 | Seed for reproducible results | -| `steps` | INT | 30 | 1 - 10000 | Number of sampling steps | -| `cfg` | FLOAT | 7.0 | 0.0 - 100.0 | CFG scale (classifier-free guidance) | -| `sampler_name` | COMBO | - | - | Sampler name from available list | -| `scheduler` | COMBO | - | - | Scheduler type | - -## Outputs - -| Output | Type | Description | -|-------------------|--------------------|------------------------------| -| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Dictionary with all settings | -| `SEED` | INT | Seed value | -| `STEPS` | INT | Number of steps | -| `CFG` | FLOAT | CFG scale | -| `SAMPLER_NAME` | COMBO | Sampler name | -| `SCHEDULER` | COMBO | Scheduler | - -## Purpose - -Centralized control of generation settings for SDXL models. Allows you to set all main parameters in one place and pass -them through the workflow both as a single config object and as individual values. Uses SDXL-optimized defaults (30 -steps, CFG 7.0). - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_VaeDecodeContext.md b/web/docs/TT_VaeDecodeContext.md deleted file mode 100644 index b23bd68..0000000 --- a/web/docs/TT_VaeDecodeContext.md +++ /dev/null @@ -1,28 +0,0 @@ -## TT VAE Decode (Context) *TT_VaeDecodeContext* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Context-based VAE decoder that extracts latent and VAE from context. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|-----------------------------------------| -| `context` | TT_CONTEXT | Yes | Context containing VAE and latent image | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|------------------------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context with decoded image added | -| `IMAGE` | IMAGE | Decoded image tensor | - -### Usage - -Simplified decoder for context-based workflows. Automatically extracts VAE and latent from context, decodes to image -space, and stores the result back in context. Handles nested tensors and reshapes output to standard format. Raises -error if VAE or latent is missing from context. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_VaeDecodeTiled.md b/web/docs/TT_VaeDecodeTiled.md deleted file mode 100644 index 35a0eaf..0000000 --- a/web/docs/TT_VaeDecodeTiled.md +++ /dev/null @@ -1,32 +0,0 @@ -## TT VAE Decode (Tiled) *TT_VaeDecodeTiled* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Tiled VAE decoder for processing large images without running out of VRAM. - -### Inputs - -| Parameter | Type | Required | Description | -|---------------|---------|----------|---------------------------------------------------------------------| -| `vae` | VAE | Yes | VAE model for decoding | -| `latent` | LATENT | Yes | Latent image to decode | -| `tile_width` | INT | Yes | Width of each tile in pixels (320-4096, step: 64, default: 512) | -| `tile_height` | INT | Yes | Height of each tile in pixels (320-4096, step: 64, default: 512) | -| `overlap` | INT | Yes | Overlap between tiles to reduce seams (0-256, step: 8, default: 64) | -| `circular` | BOOLEAN | Yes | Enable circular padding for seamless tiling (default: False) | - -### Outputs - -| Parameter | Type | Description | -|-----------|-------|----------------------| -| `IMAGE` | IMAGE | Decoded image tensor | - -### Usage - -Decode large latent images by processing them in smaller tiles. Useful for generating high-resolution images that would -otherwise exceed VRAM capacity. The overlap parameter helps reduce visible seams between tiles. Enable circular padding -for seamless texture generation. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_VaeEncodeContext.md b/web/docs/TT_VaeEncodeContext.md deleted file mode 100644 index 879e957..0000000 --- a/web/docs/TT_VaeEncodeContext.md +++ /dev/null @@ -1,29 +0,0 @@ -## TT VAE Encode (Context) *TT_VaeEncodeContext* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Encodes pixel image to latent space using VAE from context. - -### Inputs - -| Parameter | Type | Required | Description | -|-----------|------------|----------|----------------------------------| -| `context` | TT_CONTEXT | Yes | Context containing VAE and image | - -### Outputs - -| Parameter | Type | Description | -|-----------|------------|-------------------------------------| -| `CONTEXT` | TT_CONTEXT | Updated context with encoded latent | -| `LATENT` | LATENT | Encoded latent representation | - -### Usage - -Encodes pixel-space images into latent representations for diffusion processing. Extracts VAE and image from context, -performs encoding, and stores the result back in context. - -Requires context to contain both `vae` and `image` components. Raises error if either is missing. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor) diff --git a/web/docs/TT_VaeEncodeTiled.md b/web/docs/TT_VaeEncodeTiled.md deleted file mode 100644 index 89d6c53..0000000 --- a/web/docs/TT_VaeEncodeTiled.md +++ /dev/null @@ -1,34 +0,0 @@ -## TT VAE Encode (Tiled) *TT_VaeEncodeTiled* - -*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.* - -Encodes large images to latent space using tiled processing to reduce VRAM usage. - -### Inputs - -| Parameter | Type | Required | Description | -|---------------|-------|----------|-----------------------------------------------------| -| `vae` | VAE | Yes | VAE model for encoding | -| `image` | IMAGE | Yes | Input image to encode | -| `tile_width` | INT | Yes | Width of processing tiles in pixels (default: 512) | -| `tile_height` | INT | Yes | Height of processing tiles in pixels (default: 512) | -| `overlap` | INT | Yes | Overlap between tiles in pixels (default: 64) | - -### Outputs - -| Parameter | Type | Description | -|-----------|--------|-------------------------------| -| `LATENT` | LATENT | Encoded latent representation | - -### Usage - -Processes large images in smaller tiles to reduce memory requirements during VAE encoding. Useful for encoding -high-resolution images that would otherwise cause out-of-memory errors. - -Tile size should be set based on available VRAM (smaller tiles = less memory). Overlap prevents visible seams at tile -boundaries - higher overlap produces smoother results but increases processing time. Recommended overlap is 10-15% of -tile size. - ---- - -[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)