Quinto vertice del eje transform de gamedev-2d. Funcion pura (dict API format) que extiende el lienzo de un asset ya pintado por uno o varios lados y genera contenido coherente mas alla de sus bordes via el nodo nativo ImagePadForOutpaint, que ademas de ampliar el canvas EMITE la mascara feathered de la franja nueva (la genera el grafo, no la recibe el caller — esa es la diferencia con inpaint_asset). Compone comfyui_build_inpaint_workflow (base; su LoadImageMask se elimina y VAEEncodeForInpaint se reconecta a las dos salidas del pad) + comfyui_inject_lora. Probado e2e en GPU con SD1.5: seamless_00004 512x512 extendido right=256 -> 768x512 (prompt_id aa33de05), original conservado (diff 7.2) + franja nueva coherente. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 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="pixel-art-xl…", use_lcm=True, …) -> dict |
Fase 1 pixel-art: SDXL + LoRA pixel-art-xl (+ 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="isometric_game_assets_sd15…", 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. |
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.
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_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. |
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. |
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+pixel-art-xl) 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 (orquestar N poses con identidad fija + juez):
el builder
comfyui_build_sprite_sheet_workflowproduce UN frame; la orquestación multi-pose es pipeline 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.