Mueve el indicador de arquitectura del SUFIJO al PREFIJO del nombre de cada LoRA para que el dropdown del LoraLoader muestre de inmediato que LoRA casa con que checkpoint (evita el shape mismatch SD1.5 vs SDXL que crashea ComfyUI). - 20 LoRAs renombradas en disco (15 SD15/SDXL en /mnt/2tb, 5 FLUX en ~/ComfyUI), mapa de reversion en ~/ComfyUI/models/loras/_rename_map.json. - Refs actualizadas en builders gamedev-2d, style presets, pipelines, tests y docs/capabilities. Defaults hardcodeados (pixel-art, lcm-lora, etc.) apuntan a los nombres con prefijo. - Ejemplos genericos en docstrings normalizados a la convencion de prefijo. - comfyui_replicate_civitai_oneshot::_norm ignora el token de arquitectura al comparar, robusto al reordenado (sufijo civitai vs prefijo instalado). Refs a repos HuggingFace (nerijs/pixel-art-xl) y checkpoints (juggernaut_xl_v11) preservados. Verificado: dropdown LoraLoader con prefijos + generacion real pixel-art OK + tests comfyui verdes (481 ml + 26 pipelines). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
64 KiB
Capability group: gamedev-2d — assets 2D para Godot (generación + post-proceso + puente)
Cluster de funciones para producir y mover assets 2D de juego entre ComfyUI (generación) y Godot 4 (consumo). Tres capas:
- Builders de workflow 2D (
gamedev-2d, GPU): construyen el dict (API format) de los workflows ComfyUI para pixel-art, tiles seamless, isométrico, sprites de personaje y VFX en bucle. Son puros (no tocan GPU al construir); el coste GPU está al enviar concomfyui_submit_workflow. - Post-proceso determinista (CPU): pixelizar, recortar a alpha.
- Puente de assets (CPU): coloca el resultado en un proyecto Godot con sus import settings.
Tag único del grupo: gamedev-2d (los 31 builders de workflow + las 5 funciones de
apoyo de post-proceso y puente). El tag plano gamedev quedó deprecado y unificado a
gamedev-2d. El runtime de juego C++ (el motor que ejecuta el juego: game loop,
cámara, input, render por lotes, audio) vive en el grupo hermano gamedev-engine.
Filtro: mcp__registry__fn_search query="" tag="gamedev-2d".
Documento hermano del grupo comfyui (generación genérica de imágenes/video/3D).
Diseño del puente: docs/comfyui-godot-integration.md. Planes origen: reports/0135
(pixelart), reports/0139 (entornos/tiles/iso), reports/0137 (personajes/sprites),
reports/0140 (VFX), reports/0143 (ronda 2b: builders), reports/0147 (item icons),
reports/0149 (parallax background).
Builders de workflow 2D (gamedev-2d, puros — generación)
Construyen el dict API format listo para comfyui_submit_workflow. Cada uno compone
funciones existentes del registry (comfyui_build_txt2img_workflow, comfyui_inject_*,
comfyui_build_ipadapter_workflow) — no reinventan el grafo. class_types verificados
contra /object_info del server (8GB lowvram). Probados e2e en GPU: pixelart, seamless,
VFX (ver reports/0143).
| ID | Firma corta | Qué hace |
|---|---|---|
comfyui_build_pixelart_workflow_py_ml |
(positive, negative=…, *, ckpt_name="juggernaut_xl_v11…", pixel_lora="SDXL_pixel-art…", use_lcm=True, …) -> dict |
Fase 1 pixel-art: SDXL + LoRA SDXL_pixel-art (+ LCM 8 steps). El pixel-perfect es post (comfyui_pixelize_image). |
comfyui_build_seamless_tile_workflow_py_ml |
(positive, negative="", *, tiling="enable", copy_model="Make a copy", circular_vae=True, material_lora=None, …) -> dict |
Textura tileable: SeamlessTile (Conv2d circular) + CircularVAEDecode. Coste VRAM ≈0. |
comfyui_build_isometric_workflow_py_ml |
(positive, negative=…, *, iso_lora="SD15_isometric_game_assets…", grid_image=None, …) -> dict |
Asset iso 2:1: LoRA iso + ControlNet grid opcional. |
comfyui_build_sprite_sheet_workflow_py_ml |
(subject, *, ref_image=None, pose_skeleton=None, char_lora=None, transparent=True, …) -> dict |
UN sprite de personaje: IPAdapter-FaceID + LoRA + ControlNet OpenPose (Advanced, end<1) + Rembg. Varias poses → sheet. SD1.5. |
comfyui_build_vfx_spritesheet_workflow_py_ml |
(prompt, *, motion_model="mm_sd_v15_v2.ckpt", num_frames=16, closed_loop=True, lora=None, …) -> dict |
N frames AnimateDiff loop sobre negro (insumo de luma→alpha). 8GB: 16f@512² revienta, usar ≤8f@512² o bajar resolución. |
comfyui_build_item_icon_workflow_py_ml |
(item, *, style="game icon, clean, centered", checkpoint="dreamshaper_8…", size=512, transparent=True, lora=None, …) -> dict |
UN icono de item de inventario (espada/poción/anillo/libro/escudo): txt2img cuadrado + prompt scaffold de icono + LoRA estilo opcional + Rembg (alpha). Set coherente = mismo style/checkpoint/lora por item. SD1.5. |
comfyui_build_portrait_avatar_workflow_py_ml |
(character, *, style="character portrait", ref_face=None, checkpoint="dreamshaper_8…", size=512, facedetailer=True, lora=None, …) -> dict |
UN retrato/avatar de personaje (busto centrado, cara al espectador, fondo simple): txt2img + prompt scaffold de retrato + FaceDetailer (cara nítida) + LoRA estilo opcional; ref_face → IPAdapter-FaceID para rostro consistente entre retratos. Diálogo/perfil/selección. SD1.5. |
comfyui_build_emote_workflow_py_ml |
(character, expression, *, ref_face=None, style="character portrait", checkpoint="dreamshaper_8…", size=512, facedetailer=True, lora=None, …) -> dict |
UN emote/expresión facial del MISMO personaje (alegre/triste/enfadado/sorprendido/neutral…) para diálogo, retratos reactivos o emotes de chat: txt2img + prompt scaffold de emote (portrait of {character}, {expression} expression, emote, clean background) + FaceDetailer (conserva la expresión); ref_face → IPAdapter-FaceID para que varíe SOLO la expresión y el rostro sea el mismo. UNA expresión por llamada; set = mismas claves variando expression → comfyui_build_grid. Probado e2e en GPU (reports/0151). SD1.5. |
comfyui_build_parallax_background_workflow_py_ml |
(scene, *, style="game background, side-scroller…", layers=3, checkpoint="dreamshaper_8…", depth_node="DepthAnythingV2Preprocessor", width=1024, height=512, …) -> dict |
Fondo en capas para parallax 2.5D: genera el fondo apaisado (txt2img) + su depth map (DepthAnythingV2Preprocessor sobre el VAEDecode), dos SaveImage. El split en N bandas por profundidad es post (GAP: split_parallax_layers, aún no creada). Probado e2e en GPU (reports/0149). SD1.5. |
comfyui_build_normal_map_workflow_py_ml |
(image, *, method="normal", strength=1.0, resolution=512, bg_threshold=0.1, filename_prefix="normal_map") -> dict |
Normal/depth map de un sprite existente para iluminación dinámica 2.5D (Godot CanvasItem normal_map, Unity sprite normal). LoadImage → preprocesador controlnet_aux → SaveImage. method: normal (default, BAE-NormalMapPreprocessor, normal canónico azul/violeta usable directo en motor), normal_midas (MiDaS, único con strength→a, paleta no canónica), normal_dsine (DSINE), depth (DepthAnythingV2, height en gris). image debe estar en input/ de ComfyUI. Coste VRAM ≈0. Probado e2e en GPU (reports/0150). |
comfyui_build_ui_hud_workflow_py_ml |
(element, *, ui_style="fantasy game UI", checkpoint="dreamshaper_8…", size=512, transparent=True, lora=None, …) -> dict |
UN elemento de interfaz/HUD de juego (botón, marco/panel, barra de vida/maná/XP, icono de UI, cursor, viñeta de menú): txt2img cuadrado + prompt scaffold de UI ({element}, {ui_style}, game UI element, centered, clean, plain background…) + LoRA estilo opcional + Rembg (alpha). HUD coherente = mismo ui_style/checkpoint/lora por pieza, varía solo element. El texto/label lo pone el motor (negativo empuja a no text). Probado e2e en GPU (reports/0152). SD1.5. |
comfyui_build_dialogue_box_workflow_py_ml |
(box_style="fantasy RPG dialogue box", *, shape="rounded panel", checkpoint="dreamshaper_8…", width=768, height=256, transparent=True, seed=0, lora=None, …) -> dict |
EL contenedor de diálogo / bocadillo / panel de texto de juego (RPG, visual novel, aventura): marco apaisado (width>height, 768×256) con borde decorativo y un interior plano/vacío reservado para que el motor renderice el texto de la conversación encima → {box_style}, {shape}, game UI dialogue box frame, ornate border, empty flat interior for text, plain background + LoRA estilo opcional + Rembg (alpha). DISTINTO de ui_hud (elementos sueltos: botón/barra/icono): esto es el panel-contenedor completo. shape (rounded panel/scroll parchment/stone tablet/speech bubble…) + set coherente = mismo box_style/shape/checkpoint/lora. El interior se mantiene liso (negativo rechaza busy/decorated interior); el texto lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — medieval fantasy dialogue box, wood and gold 768×256 RGBA, panel madera+oro con interior plano y alpha (reports/0171). SD1.5. |
comfyui_build_status_effect_icon_workflow_py_ml |
(effect, *, ui_style="game status icon, bold symbol, flat", checkpoint="dreamshaper_8…", size=256, transparent=True, seed=0, lora=None, …) -> dict |
UN icono de estado / buff-debuff (veneno, quemadura, congelación, escudo, regeneración, aturdimiento, velocidad, sangrado, maldición): símbolo compacto que se superpone al HUD para indicar un efecto activo, optimizado para legibilidad a tamaño reducido (16-32 px) → {effect} status effect icon, {ui_style}, simple bold symbol, centered, readable at small size, plain background… + LoRA estilo opcional + Rembg (alpha). size por defecto menor (256, no 512) porque se muestra pequeño; el negativo rechaza intricate details/complex/cluttered para no perder legibilidad. DISTINTO de item_icon (objeto de inventario) y ui_hud (chrome grande de interfaz): aquí es un símbolo de estado. Barra coherente = mismo ui_style/checkpoint/lora, varía solo effect (color habla del tipo). El texto/contador lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — poison 256×256 RGBA, símbolo verde flat centrado (reports/0162). SD1.5. |
comfyui_build_skill_tree_node_workflow_py_ml |
(skill, *, frame="hexagonal", state="unlocked", ui_style="fantasy skill tree node", checkpoint="dreamshaper_8…", size=256, transparent=True, seed=0, lora=None, …) -> dict |
UN nodo de árbol de habilidades / talentos (RPG, ARPG, MOBA, roguelike): el icono de una skill DENTRO de un marco (frame: hexagonal/circular/diamond/shield) que la UI de progresión pinta en la rejilla, con variante de estado visual (state: unlocked=brillante/saturado, locked=gris/desaturado) → {skill} skill icon inside a {frame} {ui_style} frame, {state} (…hint…), centered, plain background, game UI, skill tree talent node… + LoRA estilo opcional + Rembg (alpha). El marco y el estado son la firma del asset. DISTINTO de item_icon (objeto suelto sin marco), status_effect_icon (símbolo superpuesto sin marco) y ui_hud (chrome grande): aquí es el nodo enmarcado completo de la pantalla de talentos. Par de un mismo talento = mismo skill/frame/ui_style/seed, varía solo state (las dos caras de la rejilla). Árbol coherente = mismo frame/ui_style/checkpoint/lora, varía skill. El texto/coste lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — fireball hexagonal unlocked 256×256 RGBA, nodo enmarcado brillante centrado (reports/0173). SD1.5. |
comfyui_build_achievement_badge_workflow_py_ml |
(badge, *, tier="gold", style="game achievement badge, ornate", checkpoint="dreamshaper_8…", size=256, transparent=True, seed=0, lora=None, …) -> dict |
UNA insignia / medalla / logro (achievement, recompensa, rango): un trofeo, una medalla con cinta, un escudo de logro o un badge de rango que el panel de logros pinta al desbloquear un hito, con tier metálico (bronze/silver/gold/platinum/diamond) que distingue el grado → {badge} achievement badge, {tier} tier (…hint metálico…), {style}, medal with ribbon, centered, plain background, game UI reward, trophy emblem… + LoRA estilo opcional + Rembg (alpha). El tier metálico y la forma de medalla/trofeo con cinta son la firma del asset. DISTINTO de item_icon (objeto de inventario suelto, sin tier ni cinta), status_effect_icon (símbolo de estado superpuesto sin marco) y skill_tree_node (nodo enmarcado de la rejilla de talentos con estado unlocked/locked): aquí es la insignia de logro/recompensa del panel de achievements. Familia de un mismo logro = mismo badge/style/seed, varía solo tier (los grados); set coherente = mismo style/checkpoint/lora, varía badge. El nombre/descripción/fecha lo pone el motor (negativo empuja a no text). Probado e2e en GPU con SD1.5 — dragon slayer tier gold seed 77 256×256 RGBA, medalla circular dorada con emblema centrado y fondo recortado a alpha (esquina α=0, centro α=254; prompt_id 8b8b7ede, reports/0175). SD1.5. |
comfyui_build_card_art_workflow_py_ml |
(subject, *, card_style="fantasy trading card art", checkpoint="juggernaut_xl_v11…", width=512, height=768, hires=True, seed=0, lora=None, …) -> dict |
LA ilustración central de UNA carta coleccionable (TCG): criatura/personaje/hechizo en formato vertical de carta (width<height, ~512×768), composición centrada + iluminación dramática ({subject}, {card_style}, dramatic lighting, detailed illustration, centered composition, full art…). hires=True → 2ª pasada de detalle (comfyui_build_hires_fix_workflow); si no, txt2img + LoRA estilo opcional. Genera SOLO la ilustración — el marco/título/stats los pone el motor/post (negativo rechaza card frame/border/text/stats/UI). Set coherente = mismo card_style/checkpoint/lora, varía solo subject. Probado e2e en GPU con SD1.5 (reports/0153); ⚠️ el path hires=True falla hoy por bug del builder comfyui_build_hires_fix_workflow (nodo UltimateSDUpscale pide batch_size) — usar hires=False hasta el fix. SD1.5/SDXL. |
comfyui_build_enemy_creature_workflow_py_ml |
(creature, *, variant=None, style="game creature, full body", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN enemigo/criatura de juego (goblin, esqueleto, slime, dragón, boss, elemental): figura de cuerpo entero centrada, fondo limpio recortable a alpha ({variant} {creature}, {style}, full body, centered, plain background, game asset…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). variant (ice/fire/elite/corrupted…) se antepone a la criatura para generar la familia del MISMO enemigo (misma creature/seed/style, varía solo variant); bestiario coherente = mismo style/checkpoint/lora, varía solo creature. El negativo empuja a UNA criatura entera sin recorte. Probado e2e en GPU con SD1.5 (reports/0154). SD1.5. |
comfyui_build_prop_object_workflow_py_ml |
(prop, *, style="game prop, isometric or side view", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN prop/objeto de escenario (barril, cofre, antorcha, planta, mueble, roca, fuente, estatua): objeto inanimado aislado a escala de escena y perspectiva de juego (iso/lateral), centrado, fondo limpio recortable a alpha ({prop}, {style}, game asset, single object, centered, plain background, scene prop, world object…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Objeto de MUNDO, no icono plano de inventario (≠ item_icon, que es para una casilla de UI); este puebla el nivel. Atrezzo coherente = mismo style/checkpoint/lora, varía solo prop. El negativo excluye personas/criaturas (objeto inanimado). Probado e2e en GPU con SD1.5 (reports/0155). SD1.5. |
comfyui_build_vehicle_mount_workflow_py_ml |
(vehicle, *, view="side", style="game vehicle", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN vehículo/montura que el personaje USA o CONDUCE (caballo, dragón-montura, nave espacial, coche, barco, carro, grifo, mecha): el vehículo COMPLETO en vista lateral o isométrica, centrado, fondo limpio recortable a alpha, SIN jinete/conductor ({vehicle}, {view} view, {style}, full vehicle, centered, plain background, game asset, no rider, empty…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Se genera VACÍO (el negativo rechaza person/rider/driver/passenger) para que el motor componga al personaje encima. DISTINTO de enemy_creature (sujeto a COMBATIR) y prop_object (atrezzo inanimado que decora): aquí el objeto se MONTA/USA; una montura viva que se cabalga (caballo, dragón) entra aquí, no en enemy_creature. view (side/iso) fija la geometría del parque móvil; set coherente = mismo view/style/checkpoint/lora, varía solo vehicle. Probado e2e en GPU con SD1.5 — armored war horse with saddle side 512×512 RGBA, vehículo centrado recortado a alpha (centroide 0.55/0.54, 4 esquinas transparentes, reports/0169). SD1.5. |
comfyui_build_topdown_sprite_workflow_py_ml |
(subject, *, direction="south", style="top-down game sprite, RPG", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN sprite en vista CENITAL (top-down) estilo RPG clásico/roguelike (Zelda, juegos cenitales): personaje/objeto visto desde arriba, centrado, fondo limpio recortable a alpha ({subject}, top-down view, overhead view, {direction} facing, {style}, centered, plain background, game asset…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). direction (south/north/east/west) para el sprite de movimiento: las 4 vistas del MISMO personaje = misma subject/style/seed, varía solo direction → montar con comfyui_build_grid. DISTINTO de sprite_sheet (vista lateral/frontal de plataformas): el negativo por defecto rechaza side/front/3-4/isometric/perspective para forzar la cenital. Con SD1.5 sin LoRA sale picado alto; cenital estricto pide LoRA top-down + cfg alto. Probado e2e en GPU con SD1.5 (reports/0156). SD1.5. |
comfyui_build_splash_art_workflow_py_ml |
(scene, *, mood="epic, cinematic", checkpoint="juggernaut_xl_v11…", width=1024, height=576, hires=True, seed=0, lora=None, …) -> dict |
LA ilustración grande de UN splash / pantalla de carga / key art en formato pantalla apaisado 16:9 (width>height, ~1024×576), composición cinematográfica ({scene}, {mood}, key art, game splash screen, dramatic lighting, cinematic composition, wide shot, epic scale, atmospheric…). hires=True → 2ª pasada de detalle (comfyui_build_hires_fix_workflow) para verse a pantalla completa; si no, txt2img + LoRA estilo opcional. Genera SOLO la ilustración — el título/logo/barra de carga los pone el motor/post (negativo rechaza text/title/logo/UI/frame/watermark), dejando aire para superponer el título. Set coherente = mismo mood/checkpoint/lora, varía solo scene. Probado e2e en GPU con SD1.5 + hires (1024×576 → 1536×864, 54s, reports/0159). SD1.5/SDXL. |
comfyui_build_world_map_workflow_py_ml |
(region, *, map_style="fantasy cartography, aged parchment", checkpoint="juggernaut_xl_v11…", width=768, height=768, hires=False, seed=0, lora=None, …) -> dict |
LA ilustración de la pantalla de mapa del juego: una lámina cartográfica en vista cenital de un continente/región/reino/mazmorra con aspecto de atlas fantasy (map of {region}, {map_style}, top-down cartographic view, illustrated game world map, labeled regions, decorative border, compass rose, fantasy atlas, no people…). Cuadrado por defecto (768×768; sube width para mundo apaisado, height para mazmorra en columna), hires=False por defecto (ponlo True para detalle fino de costas/relieve). Genera SOLO la ilustración — las marcas interactivas, los iconos pinchables, las rutas y el "estás aquí" los pone el motor SOBRE la lámina; la difusión dibuja labels/ornamentos DECORATIVOS pero NO garantiza ortografía ni posiciones usables como datos (el negativo rechaza photo/3d render/perspective/character/person para mantener la vista cenital plana). Atlas coherente = mismo map_style/checkpoint/lora, varía solo region. Probado e2e en GPU con SD1.5 — reino fantasy 768×768, lámina de pergamino con costas/montañas/regiones + borde ornamental + rosa de los vientos (prompt_id bf4861fc, reports/0167). SD1.5/SDXL. |
comfyui_build_decal_overlay_workflow_py_ml |
(decal, *, on_black=True, style="grunge decal, high detail", checkpoint="dreamshaper_8…", size=512, seed=0, lora=None, …) -> dict |
UN decal/overlay con alpha para superponer sobre superficies/paredes/sprites con blend mode del motor (sangre, grietas, suciedad, óxido, quemaduras, salpicaduras, arañazos, musgo): textura aislada sobre fondo PLANO ({decal}, {style}, single isolated decal, centered, on a solid pure black background, flat backdrop, sticker, no scenery, texture overlay, game asset…) → txt2img cuadrado + LoRA estilo opcional. on_black=True (defecto) pensado para extraer alpha con comfyui_matting_luma_to_alpha (luma=alpha, conserva el falloff de translúcidos — la técnica gamedev correcta, ≠ recorte binario). NO inyecta Rembg (el matting es luma→alpha de disco, no un nodo): el SaveImage sale directo del VAEDecode. Set coherente = mismo style/checkpoint/lora, varía solo decal/seed. ⚠️ "grunge" en style arrastra fondo gris en SD1.5 → para fondo negro plano usar un style sin connotación de fondo + reroll de seed; luma Rec601 penaliza el rojo → para sangre roja pasar luma_weights con más peso al rojo. Probado e2e en GPU con SD1.5 (reports/0160). SD1.5. |
comfyui_build_projectile_workflow_py_ml |
(projectile, *, direction="right", glow=False, style="game projectile, side view", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN proyectil orientado (flecha, bala, bola de fuego, rayo, misil, hechizo): sprite pequeño con orientación (apunta a la derecha por defecto, ángulo 0 — el motor rota el sprite), aislado, listo para instanciar. glow elige el camino a alpha: glow=False (defecto) = proyectil SÓLIDO con silueta → plain background + Rembg (alpha por recorte, como item_icon/topdown_sprite); glow=True = brillante/mágico → glowing, on black background sin Rembg (recortaría el halo), insumo de comfyui_matting_luma_to_alpha que el caller aplica luego (como vfx_spritesheet/decal_overlay). glow=True ignora transparent/rembg_model; el negativo por defecto NO rechaza "black background". direction se inserta como pointing {direction} (""/None = sin orientación). Set coherente = mismo style/checkpoint/lora, varía solo projectile/seed. Probado e2e en GPU con SD1.5 — fireball glow sobre negro + luma→alpha RGBA (reports/0161). SD1.5. |
comfyui_build_structure_workflow_py_ml |
(structure, *, view="isometric", style="game building", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN edificio/estructura de escenario (casa, torre, castillo, tienda, posada, ruina, muralla, puente, templo, faro): UN building COMPLETO y centrado a perspectiva de juego ({view} view, iso por defecto), fondo limpio recortable a alpha ({structure}, {view} view, {style}, full building, complete structure, single building, centered, plain background, game asset, architecture…) → txt2img cuadrado + LoRA estilo/iso opcional + Rembg (alpha). EDIFICACIÓN grande que ocupa varios tiles y define el escenario, no un objeto pequeño suelto (≠ prop_object, que es atrezzo que se deja sobre un tile); el negativo rechaza small object / single item / prop / furniture. view fija la perspectiva del mapa (iso/side/front/top-down/¾); LoRA iso fija mejor el ángulo 2:1. Set coherente = mismo view/style/checkpoint/lora, varía solo structure. Probado e2e en GPU con SD1.5 — medieval blacksmith shop iso 512×512 RGBA, edificio centrado recortado a alpha (centroide 0.54/0.53, reports/0164). SD1.5. |
comfyui_build_foliage_set_workflow_py_ml |
(plant, *, view="side", style="game foliage, stylized", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UN elemento de vegetación/foliage de escenario (árbol, arbusto, hierba alta, flores, helecho, hongo, cactus, tronco caído, juncos, hiedra): UN elemento de naturaleza ORGÁNICA AISLADO y centrado a perspectiva de juego ({view} view, side por defecto), fondo limpio recortable a alpha ({plant}, {view} view, {style}, single plant element, centered, plain background, game nature asset, natural vegetation, organic, isolated plant…) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Vegetación que viste el terreno, distinta del objeto MANUFACTURADO suelto (≠ prop_object: barril/cofre/mueble) y del EDIFICIO (≠ structure: casa/torre); el negativo rechaza building / manmade object / barrel / furniture / person y multiple plants / dense forest / jungle / landscape (UN elemento, no un bosque) + pot / planter / vase (planta en maceta = prop_object). Recorte por Rembg (planta opaca de silueta definida), no luma→alpha. Set coherente = mismo view/style/checkpoint/lora, varía solo plant. ⚠️ dos gotchas reales SD1.5+Rembg: (1) plantas grandes (árbol) tienden a PAISAJE (cielo+campo) en lugar de fondo plano → re-roll de seeds buscando fondo uniforme (comfyui_batch_generate); (2) follaje verde claro sobre fondo claro → Rembg se come las hojas y deja solo tronco/ramas → preferir elementos de silueta compacta y color saturado (hongo, arbusto denso) o transparent=False + matting manual. Probado e2e en GPU con SD1.5 — golden a glowing mushroom seed 7 512×512 RGBA, hongo centrado recortado a alpha limpio (centroide 0.51/0.58, opaco 19%, prompt_id 8fb65a51); evidencia del gotcha del roble en reports/0170. SD1.5. |
comfyui_build_trap_hazard_workflow_py_ml |
(hazard, *, view="side", style="game hazard trap", checkpoint="dreamshaper_8…", size=512, transparent=True, seed=0, lora=None, …) -> dict |
UNA trampa/peligro JUGABLE de nivel (pinchos del suelo, sierra giratoria, foso de lava, placa de presión, columna de llamas, trampa de flechas, charco ácido, descarga eléctrica, prensa, estaca cayendo): UN objeto de peligro AISLADO y centrado a perspectiva de juego ({view} view, side por defecto), fondo limpio recortable a alpha ({hazard}, {view} view, {style}, single hazard object, trap, dangerous, centered, plain background, game asset, high detail) → txt2img cuadrado + LoRA estilo opcional + Rembg (alpha). Peligro al que el motor asigna hitbox de daño + estado activo/inactivo, distinto del objeto INERTE de decoración (≠ prop_object: barril/cofre que solo ambienta) y del enemigo VIVO (≠ enemy_creature); el negativo rechaza character / person / creature / multiple objects para que salga el mecanismo, no un enemigo ni una escena. Recorte por Rembg (trampa sólida de silueta definida: pinchos/sierra/placa); ⚠️ para hazards puramente etéreos (columna de llamas, arco eléctrico, gas) usar transparent=False + comfyui_matting_luma_to_alpha (conserva el falloff translúcido para blend aditivo), no Rembg. view fija la perspectiva del nivel (side/top-down/iso); set coherente = mismo view/style/checkpoint/lora, varía solo hazard. Probado e2e en GPU con SD1.5 — spiked floor trap side seed 7 512×512 RGBA, mecanismo de peligro centrado recortado a alpha (alpha extrema 0–255, fondo transparente real, prompt_id ab1b1560, reports/0174). SD1.5. |
comfyui_build_particle_texture_workflow_py_ml |
(particle, *, soft=True, style="particle texture, soft glow", checkpoint="dreamshaper_8…", size=256, seed=0, lora=None, …) -> dict |
UNA textura de partícula individual reutilizable (chispa, humo, polvo, destello/flare, gota, copo, hoja, círculo de energía) — el "ladrillo" que el sistema de partículas del motor (Godot GPUParticles2D, Unity VFX Graph) instancia a miles y anima (spawn/fade/color over lifetime). Aislada y centrada sobre fondo NEGRO (`{particle} particle, {style}, isolated on pure black background, <soft |
comfyui_build_weather_overlay_workflow_py_ml |
(weather, *, on_black=True, style="weather overlay, atmospheric", checkpoint="dreamshaper_8…", width=1024, height=576, seed=0, lora=None, …) -> dict |
UNA capa de clima/atmósfera a PANTALLA COMPLETA que cubre toda la vista del jugador y se superpone sobre la escena con blend del motor (lluvia, niebla, nieve, rayos de sol/god rays, polvo, viñeta de tormenta): cobertura uniforme de borde a borde, generada APAISADA a resolución de pantalla (16:9, 1024×576 por defecto — width>height, NO cuadrado) ({weather} overlay, {style}, full screen atmospheric layer, <particles/streaks on pure black background | translucent layer>, seamless full screen coverage, edge to edge, game VFX…) → txt2img apaisado + LoRA estilo opcional. on_black elige el modo de blend: on_black=True (defecto) = clima BRILLANTE sobre NEGRO puro (estrías de lluvia, copos, haces de luz, motas), sin Rembg, insumo de comfyui_matting_luma_to_alpha (luma=alpha, blend aditivo/screen — el negro desaparece, el clima brilla sobre la escena); on_black=False = película TRANSLÚCIDA semi-transparente (niebla densa, tinte de tormenta) para blend multiply/overlay o alpha global. El negativo rechaza solid object/single subject/character/building/landscape scene/horizon line/frame (cobertura total, NO un sujeto centrado) + (si on_black) blue sky/gray/white background para forzar negro plano. DISTINTO de decal_overlay (ése es una mancha LOCALIZADA que se pega en un punto de una superficie) y de vfx_spritesheet (ése es la SECUENCIA animada de UN efecto puntual): la capa de clima es UNA película estática de cobertura full-screen que el motor anima por scroll/loop/shader. Set coherente = mismo style/checkpoint/lora, varía weather/seed. ⚠️ algunos climas (lluvia/niebla) pintan cielo azul de fondo en SD1.5 aunque pidas negro → subir cfg + re-roll de seed; climas brillantes-sobre-negro (god rays, snow, sparks) salen más limpios que los difusos (fog). luma Rec601 penaliza el azul → para lluvia azulada ajustar luma_weights/gamma en el matting. Probado e2e en GPU con SD1.5 — heavy rain on_black seed 11 1024×576 (16:9 exacto), estrías de lluvia brillantes sobre negro plano (esquinas luma 0.00, dark 89.6%, lluvia 1.4% brillante) apto luma→alpha aditivo (prompt_id 5d2300d1, reports/0176). SD1.5/SDXL. |
comfyui_build_rune_glyph_workflow_py_ml |
(glyph, *, glow=True, style="arcane glowing rune", checkpoint="dreamshaper_8…", size=512, seed=0, lora=None, …) -> dict |
UNA runa / glifo / sigilo mágico (glifos rúnicos, círculos mágicos, sigilos de invocación, inscripciones brillantes) para hechizos, portales, marcas de conjuro y efectos de magia: símbolo arcano aislado sobre fondo uniforme ({glyph}, {style}, magic symbol, single isolated glyph, centered, glowing on a solid pure black background, occult sigil, arcane inscription, no scenery, game asset…) → txt2img cuadrado + LoRA estilo opcional. glow elige el camino a alpha: glow=True (defecto) = runa BRILLANTE sobre NEGRO puro, sin Rembg (recortaría el halo del resplandor), insumo de comfyui_matting_luma_to_alpha (luma=alpha, blend aditivo en el motor — conserva el glow); glow=False = runa MATE/grabada sobre fondo plano (el negativo rechaza glow/neon/bloom), recorte/inversión por el caller. El negativo rechaza realistic text/readable words/latin alphabet (un glifo arcano, no letras reales) + fondo texturizado/niebla. DISTINTO de status_effect_icon (símbolo SÓLIDO de UI, recorte Rembg, legible a 16-32 px en el HUD): la runa es una marca translúcida que emite luz e se inscribe en el mundo. Grimorio coherente = mismo style/checkpoint/lora, varía glyph/seed. ⚠️ luma Rec601 penaliza el rojo → para runas rojas (sigilo demoníaco) pasar luma_weights con más peso al rojo + subir gamma; runas blancas/azules/doradas van con pesos por defecto. Probado e2e en GPU con SD1.5 — circular summoning rune glow seed 11 512×512, círculo de invocación brillante sobre negro puro (esquinas luma 0.00, dark 83%, runa 3.4% brillante, max 255) apto luma→alpha (prompt_id 701d149a, reports/0172). SD1.5. |
comfyui_build_title_lettering_workflow_py_ml |
(text, *, letter_style="epic fantasy metallic", checkpoint="juggernaut_xl_v11…", width=1024, height=512, transparent=True, seed=0, lora=None, …) -> dict |
EL texto/logo de título de un juego (el nombre del juego o una palabra) renderizado con un tratamiento de lettering (metálico, tallado en fuego/piedra/madera, neón, cristal, oro), formato apaisado (width>height, 1024×512 por defecto), fondo plano recortable a alpha (the word "{text}" as a game logo, {letter_style} lettering, stylized typography, centered, plain background…) → txt2img apaisado + LoRA estilo opcional + Rembg (alpha). El negativo NO rechaza texto (el lettering es el sujeto) y empuja contra el ruido textual (extra letters/jumbled text/deformed letters). El VALOR es el ESTILO del lettering, NO la fidelidad tipográfica: ⚠️ la difusión renderiza texto de forma imperfecta — letras de más, deformadas o mal escritas; mitigar con palabras CORTAS en MAYÚSCULA, re-roll de seeds (comfyui_batch_generate), SDXL > SD1.5 para texto, o pintar el texto real con una fuente en el motor. Una palabra que es un objeto concreto (DRAGON) → el modelo dibuja el objeto, no las letras — usar palabras abstractas o reforzar letter_style. Marca coherente = mismo letter_style/checkpoint/lora, varía solo text. Recorte por Rembg (logo sólido), no luma→alpha. Probado e2e en GPU: DRAGON/fire engraved SD1.5 1024×512 → ilustró dragones rojos (alpha OK, confirma el gotcha de palabra-objeto, prompt_id 6f3920b7); AETHER/epic fantasy metallic SDXL 768×384 → logo de texto metálico dorado legible con ortografía imperfecta + alpha (prompt_id 2a7fe8ba, reports/0165). SD1.5/SDXL. |
Animación de assets (vídeo) — caminos validados e2e
Tres vías para que un asset 2D se mueva (loop de VFX, sprite animado, fondo con
movimiento), todas cabiendo en 8GB con la GPU vacía (cierra el juego antes — el
vídeo NO convive con un juego AAA en VRAM). Los builders son del grupo hermano comfyui
(dominio ml); aquí se documenta su uso gamedev. Reutilizan el round-trip canónico
build → comfyui_submit_workflow → (sondear /history) → comfyui_fetch_output_video.
| Vía | Builder | Para qué (gamedev) | Validado |
|---|---|---|---|
| txt2video (LTX) | comfyui_build_video_workflow(prompt, model='ltx', width=512, height=320, num_frames=25, fps=12) |
Loop de elemento desde texto: portal, antorcha, agua, humo, magia. Sale .mp4. Modelo LTX-Video 2B v0.9.5 (ltx-video-2b-v0.9.5.safetensors + text encoder t5xxl_fp8). |
e2e GPU: portal mágico 512×320, 25 frames, 2.08s, pico 7717 MiB / 8192, prompt_id 54eda033, reports/0186. |
| txt2video (Wan) | comfyui_build_video_workflow(prompt, model='wan', …) |
Igual que LTX pero con Wan2.1 T2V 1.3B (wan2.1_t2v_1.3B_fp16 + umt5_xxl_fp8 + wan_2.1_vae). Enlazado y visible en /object_info. |
Enlace verificado en reports/0186; clip no generado aún (LTX cubrió el golden). |
| img2vid (SVD) | comfyui_build_img2vid_workflow('sprite.png', width=512, height=512, video_frames=14, motion_bucket_id=127) |
Animar un sprite/fondo YA generado: copia la imagen a ~/ComfyUI/input/, SVD la condiciona por CLIP_VISION (no usa prompt de texto) y la pone en movimiento. Sale .webp animado. |
e2e GPU: enemy_creature (del pack) → 512×512 RGBA 14 frames animado, pico 7463 MiB / 8192, prompt_id 5b501d03, reports/0186. |
| spritesheet (AnimateDiff) | comfyui_build_vfx_spritesheet_workflow(prompt, num_frames=8, closed_loop=True) |
N frames de un VFX 2D en bucle seamless sobre negro (insumo de luma→alpha + montaje de spritesheet). | e2e GPU previos (reports/0140/0143); 8GB: usar ≤8f@512² o bajar resolución (16f@512² revienta). |
Límites VRAM (RTX 3070 8GB, GPU vacía): LTX 512×320@25f → 7717 MiB; SVD 512×512@14f →
7463 MiB. Margen estrecho (~0.5 GB): con un juego AAA abierto (~2.7 GB) ningún camino
de vídeo cabe → cerrar el juego o ir a frames/res mínimos. La generación de imagen
estática sí convive con el juego. comfyui_wait_result lanza TimeoutError al
expirar (envolver en try/except); SVD es lento (>10 min para 14f en lowvram), pero el job
completa en GPU aunque el script de orquestación expire — recuperar el output sondeando
/history por prompt_id. Para transparencia, post-procesar los frames a alpha
(luma→alpha o rembg por frame).
Builders de transformación (gamedev-2d, puros — parten de una imagen/dibujo de entrada)
A diferencia de los builders de generación de arriba (parten de TEXTO, txt2img desde ruido), estos parten de una imagen de entrada y la transforman. Cuatro sub-ejes:
- img2img (
asset_variant): parte de un asset ya pintado; el KSampler arranca del latente de la imagen base (LoadImage → VAEEncode), no de ruido, así que condenoisemedio conserva la estructura mientras el prompt reescribe material/paleta/tier. Reescribe todo el asset conservando forma y color del original. - sketch→ControlNet (
sprite_from_sketch): parte del dibujo tosco del dev (boceto, lineart, garabato); estxt2img(arranca de ruido) pero condicionado por un ControlNet atado al mapa de líneas del dibujo. Conserva solo la forma; la IA pone material/color/acabado. - inpaint (
inpaint_asset): parte de un asset ya pintado + una máscara que marca qué región editar (blanco) y cuál conservar (negro); el sampler regenera solo la zona enmascarada dejando el resto del pixel intacto. Cambia una parte (arma, casco, escudo, reparación), no el asset entero. - outpaint (
outpaint_asset): parte de un asset ya pintado y agranda el lienzo por uno o varios lados; el nodoImagePadForOutpaintextiende el canvas y genera la máscara feathered de la franja nueva (no la recibe el caller), y el sampler genera ahí contenido coherente. Cambia el tamaño del asset (recortar/extender un fondo o parallax a otra resolución/aspect), no lo de dentro. - multi-vista 3D / 2.5D (
directional_sprite): parte del sprite frontal de un personaje y lo rota en 3D (SV3D turntable u Stable Zero123 órbita) para producir N vistas direccionales del MISMO personaje (8-way N/NE/E/SE/S/SW/W/NW o 4-way). A diferencia desprite_sheet(re-poza con OpenPose 2D, re-dibuja la silueta → identidad inconsistente entre ángulos), aquí la difusión 3D gira la figura sobre su eje, así casco/arma/paleta son los mismos en cada dirección (consistencia rotacional). Cambia el ángulo de cámara, no la pose ni el material.
Cubren el eje que el critic de generación (reports/0178) no exploró: derivar de un asset o
del dibujo del dev, no inventar un tipo nuevo desde texto.
| ID | Firma corta | Qué hace |
|---|---|---|
comfyui_build_asset_variant_workflow_py_ml |
(input_image, variant, *, checkpoint="dreamshaper_8…", denoise=0.5, style="game asset", size=512, seed=0, lora=None, …) -> dict |
UNA variante coherente de un asset 2D ya generado (img2img): parte del sprite/icono que existe en input_image y produce su versión de otro material/paleta/tier/estado (ice element, fire element, battle-damaged, golden tier 2, corrupted) manteniendo silueta, pose y composición del original. Compone comfyui_build_img2img_workflow (LoadImage → VAEEncode → KSampler con denoise) + comfyui_inject_lora (estilo opcional) + ImageScale opcional (size normaliza la base a size×size; size=None preserva las dimensiones exactas sin deformar). El prompt es {variant}, {style}, same composition, same pose, same silhouette, …. denoise es la palanca: ~0.3 invisible, 0.45-0.6 recomendado (cambia material/paleta, conserva forma), ~0.8 deriva la pose y se acerca a txt2img. Set de variantes del MISMO asset = mismo input_image/style/seed, varía solo variant. DISTINTO de los builders txt2img (enemy_creature, item_icon…): esos generan un tipo desde cero; éste transforma uno concreto. NO inyecta Rembg (img2img preserva el fondo/alpha del original según la base). ⚠️ la imagen base debe existir en input/ del server (subir con POST /upload/image); pura, no valida (usar comfyui_validate_workflow antes de enviar); asset NO cuadrado + size fijo + crop="disabled" deforma → size=None o crop="center". Probado e2e en GPU con SD1.5 — variante ice element, frozen del goblin enemy_creature_00001_.png denoise 0.5 seed 7 512×512 (prompt_id 5e4a5d3d): silueta conservada (luminance corr 0.63) + paleta a frío (blueness B−R −1.6→+1.9), reports/0181. SD1.5. |
comfyui_build_sprite_from_sketch_workflow_py_ml |
(sketch_image, subject, *, control_type="lineart", checkpoint="dreamshaper_8…", style="game asset, clean, centered", strength=0.8, size=512, seed=0, lora=None, preprocess=True, controlnet_name=None, …) -> dict |
UN sprite pintado a partir del BOCETO del dev, guiado por ControlNet (sub-eje sketch→ControlNet, NO img2img). Recibe el dibujo tosco que existe en sketch_image (boceto/lineart/garabato) + subject (qué es), y genera un sprite en estilo de juego que conserva la forma dibujada: el dev marca la silueta, la IA pone material/color/acabado. Mecanismo: txt2img base (ruido, EmptyLatentImage, denoise 1.0) cuyo positivo pasa por ControlNetApply atado al mapa de líneas del boceto. control_type elige el preprocesador (LineArtPreprocessor / ScribblePreprocessor / CannyEdgePreprocessor, interpuesto entre el boceto y el ControlNet por un helper) y, por defecto, el modelo CN emparejado. Compone comfyui_build_txt2img_workflow + comfyui_inject_controlnet + comfyui_inject_lora (estilo opcional). strength es la palanca: 0 = ignora el dibujo (txt2img puro), ~0.8 recomendado (respeta forma dejando limpiar a la IA), 1.0 = se ciñe estricto. DISTINTO de asset_variant (img2img conserva forma+color de una imagen ya pintada) y de los txt2img (enemy_creature…, inventan la forma desde texto): éste conserva solo la forma del dibujo. ⚠️ el boceto debe existir en input/ (subir con POST /upload/image); pura, no valida (usar comfyui_validate_workflow antes de enviar); preprocess=False solo si el sketch ya es un lineart limpio. GOTCHA del server 8GB: solo canny/depth/openpose SD1.5 instalados — para lineart/scribble pasa controlnet_name="control_v11p_sd15_canny_fp16.safetensors" u usa control_type="canny" (out-of-the-box); pendiente humano descargar control_v11p_sd15_lineart_fp16/scribble. Probado e2e en GPU con SD1.5 — boceto del goblin enemy_creature_00001_.png → CannyEdgePreprocessor → ControlNet canny, subject="dark fantasy goblin warrior" strength 0.85 seed 123 512×512 (prompt_id ea6fc372): pose/orejas/hombrera/lanza dentada/espada del dibujo conservadas, repintado en estilo de juego, reports/0182. SD1.5. |
comfyui_build_inpaint_asset_workflow_py_ml |
(input_image, mask_image, prompt, *, checkpoint="dreamshaper_8…", denoise=1.0, style="game asset", grow_mask=6, size=None, seed=0, lora=None, mode="vae_encode", …) -> dict |
EDITA solo una región de un asset 2D ya pintado (inpaint, sub-eje propio). Recibe el asset en input_image + una máscara mask_image (BLANCO = editar, NEGRO = conservar) + prompt de qué poner ahí, y repinta únicamente la zona enmascarada dejando el resto del sprite intacto (cambiar/añadir un arma, quitar un casco, poner un escudo, reparar una zona dañada). Mecanismo (mode="vae_encode"): VAEEncodeForInpaint codifica el latente respetando la máscara y dilata su borde grow_mask px para difuminar la costura; KSampler (denoise alto) regenera solo esa región con {prompt}, {style}, seamless blend…. Compone comfyui_build_inpaint_workflow (base) + comfyui_inject_lora (estilo opcional); size escala imagen Y máscara de forma consistente (escalar solo una las desalinea). grow_mask es la palanca de costura (6-10 px difumina el borde lo/nuevo); denoise 1.0 reescribe entero, ~0.5-0.7 repara suave. DISTINTO de asset_variant (img2img reescribe TODO el asset) y de sprite_from_sketch (ControlNet parte de un dibujo de líneas para un sprite nuevo): éste edita un trozo delimitado por la máscara. ERROR-PATH: si el server no expone VAEEncodeForInpaint, pasar mode="noise_mask" → degrada a VAEEncode + SetLatentNoiseMask (+ GrowMask); mask_image vacío lanza ValueError. ⚠️ asset y máscara deben existir en input/ (subir con POST /upload/image) y compartir resolución (o usar size); ImageScale aquí NO ofrece lanczos (válidos bilinear/nearest-exact/area/bicubic); pura, no valida. Probado e2e en GPU con SD1.5 — máscara circular (R70) sobre la mano del goblin enemy_creature_00001_.png, prompt="a glowing blue magic orb" grow_mask 8 denoise 1.0 seed 7 (prompt_id 88b52c66): orbe azul en la región, resto idéntico (diff medio dentro 40.3 vs fuera 1.97 → ratio 20.4×; 44.6% px cambiados dentro vs 1.7% fuera), reports/0183. SD1.5. |
comfyui_build_directional_sprite_workflow_py_ml |
(input_image, *, directions=8, model="sv3d", elevation=0.0, size=None, orbit_frames=None, seed=0, ckpt=None, …) -> dict |
UN sprite MULTI-DIRECCIONAL del MISMO personaje rotado en 3D (multi-vista 2.5D, sub-eje propio): parte de la imagen frontal del personaje (fondo limpio, en input/) y construye el workflow que genera N vistas direccionales CONSISTENTES (8-way N/NE/E/SE/S/SW/W/NW o 4-way) para top-down/iso/shooter 8-way. model="sv3d" (default) = SV3D_Conditioning produce un orbit turntable de N frames equiespaciados en 360° en una pasada (mejor consistencia, sv3d_p.safetensors, nativo 576²); model="zero123" = StableZero123_Conditioning_Batched da un batch de N vistas por azimuth (fallback menor VRAM, stable_zero123.ckpt, nativo 256²). elevation (~15-30) da picado para cámara cenital; orbit_frames (SOLO sv3d) densifica el orbit (21 nativo) para submuestrear; el módulo expone directional_sprite_view_order(directions) (frame i = dirección i). DISTINTO de sprite_sheet (OpenPose 2D re-poza la silueta → identidad inconsistente): aquí la difusión 3D ROTA la figura sobre su eje → casco/arma/paleta idénticos en cada dirección (rotación 3D real, no re-dibujo). Construye, NO genera (el coste GPU es el submit); pura, no valida (la imagen frontal debe existir en input/). Hermana pura de comfyui_generate_views_from_image (orquestador impuro para recon 3D, 4 cardinales). ⚠️ VRAM RTX 3070 8GB: SV3D es modelo de vídeo, pesa — 8 frames@576² → pico 7145 MiB; limpiar GPU antes (POST /free); OOM → baja size/directions o cae a zero123, NO matar procesos; comfyui_wait_result lanza TimeoutError pero el job completa (sondear /history). Probado e2e en GPU con SV3D — goblin enemy_creature_00001_.png (compuesto sobre blanco 576²) → 8 direcciones elevation 15 seed 7, 8 frames 576² en 75 s, consistencia rotacional medida (MAE adyacentes 27 < frente↔espalda 29.6, spread de paleta 3.83 = mismo personaje en las 8 vistas; prompt_id 8b9f75de, reports/0187). SV3D/Zero123. |
comfyui_build_outpaint_asset_workflow_py_ml |
(input_image, prompt, *, left=0, right=0, top=0, bottom=0, feather=40, checkpoint="dreamshaper_8…", denoise=1.0, style="game background", grow_mask=0, seed=0, lora=None, …) -> dict |
EXTIENDE el lienzo de un asset 2D ya pintado (outpaint, sub-eje propio). Recibe el asset en input_image + cuánto extender por cada lado (left/right/top/bottom px) + prompt de qué generar fuera de los bordes, y agranda el canvas generando contenido coherente con el original más allá de sus bordes (recortar/extender un fondo, parallax, card_art o splash a otra resolución/aspect ratio). Mecanismo: el nodo nativo ImagePadForOutpaint amplía el lienzo y EMITE a la vez la imagen extendida y la máscara feathered de la franja nueva (la genera el grafo, NO la recibe el caller); VAEEncodeForInpaint codifica respetando esa máscara y KSampler (denoise alto) genera lo nuevo con {prompt}, {style}, seamless extension…. Compone comfyui_build_inpaint_workflow (base; su LoadImageMask se elimina y VAEEncodeForInpaint se reconecta a las dos salidas del pad) + comfyui_inject_lora (estilo opcional). feather difumina la costura (40 px por defecto, no debe pasarse de la extensión); grow_mask (0 por defecto) dilata adicionalmente el borde si aparece costura dura. DISTINTO de inpaint_asset: éste no recibe máscara (la genera el pad) y cambia el tamaño del asset extendiendo hacia fuera, mientras inpaint edita una región interior con máscara externa del mismo tamaño. ERROR-PATH: input_image/prompt vacíos o las cuatro extensiones en 0 tras redondear (left=3→0) lanzan ValueError; si el server no expone ImagePadForOutpaint, consultar /object_info. ⚠️ el asset debe existir en input/ (subir con POST /upload/image); las extensiones se redondean a múltiplo de 8 (250→248); pura, no valida. Probado e2e en GPU con SD1.5 — fondo seamless_00004_.png 512×512 extendido right=256 feather 40 denoise 1.0 seed 7 (prompt_id aa33de05): canvas 512→768×512 (+256), original conservado (diff medio 7.2 lejos del borde) + franja nueva con contenido coherente (std 28.9, dist de paleta 28.6), reports/0185. SD1.5. |
Funciones de post-proceso y puente (gamedev-2d, CPU)
| ID | Firma corta | Qué hace |
|---|---|---|
comfyui_pixelize_image_py_ml |
(src, dst, *, downscale=8, colors=16, palette=None, dither=False, upscale_back=True) -> dict |
Pixel-perfect: downscale nearest + cuantización a N colores o paleta fija (game-boy/pico-8/nes). Fase 2 pixelart. Impura (I/O). |
comfyui_matting_luma_to_alpha_py_ml |
(image_path, *, out_path=None, gamma=1.0, black_point=0.0, premultiply=False, luma_weights=(.299,.587,.114)) -> dict |
Frame VFX sobre negro -> RGBA usando luminancia como alpha (translúcidos con additive blend). Impura (I/O). |
comfyui_export_asset_to_godot_py_pipelines |
(asset_path, kind, godot_project, *, name=None, reimport=True, godot_bin=None) -> dict |
Copia el asset a res://assets/<dir>/ por kind + escribe .import + filtro Nearest si pixelart + reimport headless. Pipeline impuro. |
godot_map_asset_dir_py_core |
(kind) -> str |
Mapea kind -> subcarpeta de res://assets/. Pura. |
godot_clean_asset_name_py_core |
(filename, *, override=None) -> str |
Normaliza el nombre <prefijo>_NNNNN_.<ext> a snake_case seguro para res://. Pura. |
Estilos (style presets) — calidad por ESTILO reutilizable
Un style preset es la receta curada de un look visual que se aplica a TODOS los
assets de un juego de una vez ("todo en Game Boy", "estilo Ghibli", "pixel-art retro").
En vez de repetir a mano style/checkpoint/lora/negative + post-proceso en cada
builder, el preset los empaqueta como DATOS puros y el helper los traduce a los kwargs de
cualquier builder de sujeto (item_icon, enemy_creature, prop_object, …) o del pipeline
comfyui_generate_asset_pack_oneshot. Diseño (issue 0087): función pura de presets +
helper de aplicación (NO un pipeline monolítico) — máxima composabilidad, sin acoplar
firmas. Extensible: añadir un estilo = una entrada en _PRESETS.
| ID | Firma corta | Qué hace |
|---|---|---|
comfyui_get_gamedev_style_preset_py_ml |
(name=None) -> dict |
Devuelve la receta de un STYLE PRESET curado o el catálogo si name=None. Receta = {subject_prefix, subject_suffix, style, negative, checkpoint, lora, lora_strength, size, transparent, post, notes}. Pura, copias profundas. 6 estilos: gameboy (sin LoRA → prompt + post pixelize paleta game-boy 4 tonos verde), ghibli (degrada a SD15_watercolor_style gratis instalado + prompt; no hay LoRA Ghibli dedicado ni se descargó nada gated), pixel-art-retro (reutiliza SDXL_pixel-art SDXL ya instalado → checkpoint juggernaut_xl_v11 + size 768 + post pixelize 16 colores), cyberpunk-neon (prompt puro SD1.5, glow magenta/cyan, sin post), low-poly-flat (prompt puro SD1.5, facetas/flat shading PS1, sin post, transparent), cartoon-cel-shaded (LoRA SD15_anime_style_box 0.7 + prompt cel-shaded, sin post, transparent). Extensible: añadir un estilo = una entrada en _PRESETS. |
comfyui_apply_style_preset_py_ml |
(preset, subject, *, style=None, negative=None) -> dict |
Traduce un preset + un subject a {name, subject (con prefijo/sufijo), builder_kwargs={style,checkpoint,lora,lora_strength,negative}, size, transparent, post}. Los builder_kwargs hacen **spread directo en cualquier builder de sujeto; size/transparent van aparte (recomendaciones); el caller aplica post["pixelize"] al PNG si existe. Pura, no muta el preset; negative se mergea (no reemplaza). |
Ejemplo canónico (mismo subject, look del juego entero):
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_get_gamedev_style_preset import comfyui_get_gamedev_style_preset
from ml.comfyui_apply_style_preset import comfyui_apply_style_preset
from ml.comfyui_build_enemy_creature_workflow import comfyui_build_enemy_creature_workflow
from ml.comfyui_submit_workflow import comfyui_submit_workflow
from ml.comfyui_wait_result import comfyui_wait_result
from ml.comfyui_fetch_output_image import comfyui_fetch_output_image
from ml.comfyui_pixelize_image import comfyui_pixelize_image
preset = comfyui_get_gamedev_style_preset("gameboy") # o "ghibli" / "pixel-art-retro"
ap = comfyui_apply_style_preset(preset, "knight character")
wf = comfyui_build_enemy_creature_workflow(ap["subject"], size=ap["size"],
transparent=ap["transparent"], seed=7, **ap["builder_kwargs"])
pid = comfyui_submit_workflow(wf)["prompt_id"]
outs = comfyui_wait_result(pid, timeout=500)
fn = next(i["filename"] for o in outs.values() for i in o.get("images", []))
raw = comfyui_fetch_output_image(fn, dest_dir="/tmp")["path"]
if ap["post"].get("pixelize"): # gameboy/pixel-retro sellan el grid/paleta
comfyui_pixelize_image(raw, "/tmp/knight.png", **ap["post"]["pixelize"])
Validado e2e en GPU con el MISMO knight character en los 3 estilos (reports/0190):
gameboy 4 colores verde (prompt_id 0657e3e3), ghibli 78 552 colores acuarela
(42f2f492), pixel-art-retro SDXL 768 16 colores (84b08581) — tres looks
visiblemente distintos y coherentes. Gotcha: en el flujo manual de arriba el post no
se aplica solo (el caller llama comfyui_pixelize_image) — para evitarlo usa el pipeline
one-shot comfyui_generate_styled_asset_oneshot (abajo), que auto-aplica el post. El LoRA y
el checkpoint deben casar de base (SDXL_pixel-art es SDXL → exige juggernaut); OOM en 8 GB →
bajar size, NO matar procesos.
Pipelines one-shot (gamedev-2d, impuros)
| ID | Firma corta | Qué hace |
|---|---|---|
comfyui_generate_asset_pack_oneshot_py_pipelines |
(pack, *, checkpoint="dreamshaper_8…", style="", lora=None, base_seed=0, size=None, server="127.0.0.1:8188", export_godot=None, out_dir=None, …) -> dict |
Set COHERENTE de assets 2D de un mismo juego de un solo tiro: pack=[{"kind","subject"}, …] → despacha cada kind a su builder atómico (26 kinds: item_icon, enemy_creature, prop_object, seamless_tile, ui_hud, particle_texture, …) compartiendo el MISMO checkpoint/lora + style común inyectado al subject + seed = base_seed + i, encola (submit) + espera (wait) + descarga (fetch) cada uno, y (si export_godot) los exporta a Godot. Promoción a pipeline del patrón "N builders con el mismo estilo" (issue 0087). Fail-fast si kind desconocido; un OOM aislado no aborta el resto. Probado e2e en GPU SD1.5 512: magic sword(item_icon, seed 42) + goblin warrior(enemy_creature, seed 43), style="dark fantasy, hand-painted" → 2/2 PNG 512×512 RGBA coherentes (prompt_id f7cfda43 + 11d1d031, reports/0179). Impuro: HTTP + disco + (export) subprocess. |
comfyui_generate_character_set_oneshot_py_pipelines |
(character, *, style="game character, full body, clean background", checkpoint="dreamshaper_8…", base_kind="enemy_creature", directions=8, make_directional=True, make_3d=True, directional_model="sv3d", elevation=15.0, seed=0, size=512, directional_size=None, flatten_color=(255,255,255), variant_3d="mini", lora=None, server="127.0.0.1:8188", export_godot=None, out_dir=None, free_vram=True, …) -> dict |
Set COMPLETO y COHERENTE de UN personaje de un solo tiro (culminación cross-frontera del grupo): genera del MISMO personaje (1) imagen base 2D recortada a alpha, (2) sprite direccional N-way (vistas 3D consistentes SV3D/Zero123) y (3) malla 3D .glb (Hunyuan3D-2). La CLAVE es la coherencia: el direccional y el 3D parten de la MISMA base 2D aplanada (base_flat), no de tres generaciones independientes → mismo personaje en las tres representaciones, no tres personajes distintos. Compone un builder de personaje (enemy_creature/portrait_avatar/topdown_sprite, elegido por introspección) + comfyui_flatten_alpha_on_color (aplana la base recortada sobre blanco — los modelos 3D y LoadImage hacen convert("RGB") y tiran el alpha) + comfyui_image_to_3d_oneshot + comfyui_build_directional_sprite_workflow + submit/wait/fetch + comfyui_export_asset_to_godot. Secuencial liberando VRAM (POST /free) entre los pasos pesados, el 3D ANTES del direccional (SV3D es el de mayor pico, ~7.1 GB), para caber en 8 GB. Un fallo aislado (p.ej. OOM en el 3D) NO aborta el resto: deja el set PARCIAL. Promoción a pipeline (issue 0087) de la secuencia que hoy exige 4 llamadas a mano. Probado e2e en GPU — ver reports/0188. Impuro: HTTP + disco + (export) subprocess. |
comfyui_generate_styled_asset_oneshot_py_pipelines |
(kind, subject, style_preset, *, seed=0, server="127.0.0.1:8188", out_dir=None, export_godot=None, style_override=None, negative_extra=None, free_vram=False, **builder_extra) -> dict |
Aplica un ESTILO curado a UN asset de un solo tiro, con AUTO-POST: comfyui_get_gamedev_style_preset(style_preset) → comfyui_apply_style_preset → despacha kind a su builder (REUTILIZA el dispatch _SUPPORTED del pack, mismos 26 kinds) → submit/wait/fetch → auto-aplica el post del preset (comfyui_pixelize_image si el estilo lo pide) → export opcional a Godot (como pixelart si hubo pixelize → fija el filtro Nearest). Cierra el hueco #1 de los style presets (report 0190): los estilos pixelart (gameboy, pixel-art-retro) salen ya pixelizados del pipeline, sin llamar a comfyui_pixelize_image a mano. Devuelve path (FINAL post-procesado) y raw_path (crudo); path==raw_path si el estilo no pide post. Kind/estilo desconocido → ok=False sin tocar la GPU (validación pura; parte pura aislada en styled_asset_build_only). Probado e2e en GPU: mismo treasure chest(prop_object) en cyberpunk-neon (prompt_id 02473baa), low-poly-flat (7a186053) y gameboy (46b396e2, crudo 17374 colores → final 4 colores Game Boy, auto-pixelizado) — ver reports/0191. Impuro: HTTP + disco + (export) subprocess. |
Ejemplo end-to-end con builder (Fase 1 GPU → Fase 2 CPU → Godot)
Flujo completo pixel-art: construir workflow → generar en ComfyUI → pixel-perfect → Godot.
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_build_pixelart_workflow import comfyui_build_pixelart_workflow
from ml.comfyui_submit_workflow import comfyui_submit_workflow
from ml.comfyui_wait_result import comfyui_wait_result
from ml.comfyui_fetch_output_image import comfyui_fetch_output_image
from ml.comfyui_pixelize_image import comfyui_pixelize_image
# 1. Construir (puro) + 2. generar (GPU)
wf = comfyui_build_pixelart_workflow("isometric tiny house, pixel, 32x32 style", use_lcm=True, seed=42)
pid = comfyui_submit_workflow(wf)["prompt_id"]
outs = comfyui_wait_result(pid, timeout=300)
fn = next(img["filename"] for o in outs.values() for img in o.get("images", []))
raw = comfyui_fetch_output_image(fn, dest_dir="/tmp")["out_path"]
# 3. pixel-perfect (CPU) -> 4. export Godot (ver ejemplo de abajo)
px = comfyui_pixelize_image(raw, "/tmp/house_pixel.png", downscale=8, colors=16)
VFX: comfyui_build_vfx_spritesheet_workflow(prompt, num_frames=8) → submit → fetch N frames
→ comfyui_matting_luma_to_alpha por frame → montar sheet RGBA con Image.alpha_composite
(NO comfyui_build_grid, que aplana el alpha).
Ejemplo canónico de post-proceso
Flujo: crudo generado en ComfyUI -> pixelizar -> exportar a Godot con Nearest.
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_pixelize_image import comfyui_pixelize_image
from ml.comfyui_matting_luma_to_alpha import comfyui_matting_luma_to_alpha
from pipelines.comfyui_export_asset_to_godot import comfyui_export_asset_to_godot
OUT = os.path.expanduser("~/ComfyUI/output")
PROJ = os.path.expanduser("~/gamedev/projects/crossy_road")
# 1. Pixelizar un sprite crudo (SDXL+SDXL_pixel-art) a 16 colores
px = comfyui_pixelize_image(f"{OUT}/hero_00001_.png", "/tmp/hero_pixel.png",
downscale=8, colors=16)
# 2. Exportarlo a Godot como pixelart (carpeta sprites/, filtro Nearest, reimport)
exp = comfyui_export_asset_to_godot("/tmp/hero_pixel.png", "pixelart", PROJ)
print(exp["dest_res_path"], exp["pixelart_filter_set"], exp["reimported"])
# Rama VFX: frame de humo sobre negro -> RGBA -> carpeta vfx/
rgba = comfyui_matting_luma_to_alpha(f"{OUT}/vfx_loop_00007_.png", gamma=1.2, black_point=0.04)
comfyui_export_asset_to_godot(rgba["out_path"], "vfx", PROJ)
Fronteras (qué NO cubre)
- Montaje de spritesheet dedicado (grid RGBA + JSON sidecar para Godot/Unity):
no hay función propia todavía — el ejemplo VFX monta con
Image.alpha_compositeinline.comfyui_build_gridNO sirve (aplana el alpha sobre fondo oscuro). Pendiente de R4 (planreports/0140F2). - Pipelines one-shot (build → submit → wait → fetch → post en una call): el
set coherente ya está promovido —
comfyui_generate_asset_pack_oneshotgenera un pack entero compartiendo checkpoint/style/lora/seed (issue 0087, ver tabla de pipelines arriba). One-shots por-asset individuales (pixelart/sprite/VFX) siguen encadenándose a mano; candidatos a promoción cuando el patrón se repita. - Sprite turnaround multi-vista (N direcciones del mismo personaje con identidad fija):
cubierto por
comfyui_build_directional_sprite_workflow(rotación 3D SV3D/Zero123, consistencia rotacional medida —reports/0187). Lo que sigue pendiente es la orquestación multi-POSE 2D con juez (re-pozar un personaje en N acciones manteniendo identidad, distinto de rotarlo):comfyui_build_sprite_sheet_workflowproduce UN frame; el pipeline multi-pose con juez sigue pendiente (planreports/0137T2). - Paletas lospec por red (
load_lospec_palette): no incluido.pixelizeusa paletas fijas embebidas (game-boy/pico-8/nes) o lista de hex, sin HTTP. - TileSet / SpriteFrames
.tres: Godot no los deriva solos;export_asset_to_godotcopia la textura y avisa, pero no genera el recurso (paso manual o futura función).
Prerequisitos / notas
- Godot CLI para el reimport headless: autodetectado en PATH y en
~/godot/Godot_v4.7-stable_linux.x86_64. Si falta,export_asset_to_godotdeja el.importescrito y lo anota (no falla). - Filtro Nearest (Godot 4): se setea global en
project.godot(default_texture_filter=0), no por.import. La función lo asegura para pixelart. - CPU-only: Pillow + numpy del venv del registry. Cero VRAM, cero red.