--- name: comfyui_apply_style_preset kind: function lang: py domain: ml version: "1.0.0" purity: pure signature: "def comfyui_apply_style_preset(preset: dict, subject: str, *, style: str | None = None, negative: str | None = None) -> dict" description: "Traduce un STYLE PRESET gamedev (de comfyui_get_gamedev_style_preset) + un subject del usuario a lo que necesita un builder de sujeto del grupo gamedev-2d: el subject combinado con el prefijo/sufijo del estilo, los kwargs comunes (style, checkpoint, lora, lora_strength, negative) listos para **spread, la resolucion y el recorte recomendados (size, transparent) y la spec de post-proceso (post, p.ej. pixelize) que el caller aplica al PNG. Asi el mismo estilo se aplica a CUALQUIER builder (item_icon, enemy_creature, prop_object, ...) y al pipeline comfyui_generate_asset_pack_oneshot sin acoplar firmas. Pura, sin red ni I/O; no muta el preset." tags: [comfyui, ml, gamedev-2d, style, preset, theme] uses_functions: [comfyui_get_gamedev_style_preset_py_ml] uses_types: [] returns: [] returns_optional: false error_type: "" imports: [] params: - name: preset desc: "Receta de estilo (dict de comfyui_get_gamedev_style_preset). Debe traer los campos del preset (se valida que esten). No se muta." - name: subject desc: "Lo que el usuario quiere generar (ej. 'knight character', 'health potion'). Se combina con el prefijo/sufijo del estilo. No puede estar vacio." - name: style desc: "Override puntual: si se pasa, sustituye al style del preset. None usa el del preset. keyword-only." - name: negative desc: "Negativo extra del caller; se MERGEA (sin duplicar) con el negativo del estilo, no lo reemplaza. None = solo el del estilo. keyword-only." output: "dict con: name (estilo aplicado), subject (combinado con prefijo/sufijo), builder_kwargs ({style, checkpoint, lora, lora_strength, negative} para **spread en el builder), size (resolucion recomendada), transparent (recorte recomendado), post (post-proceso CPU: {'pixelize': {...}} o {})." tested: true tests: ["golden gameboy: subject combina suffix (8-bit), builder_kwargs con las 5 claves comunes, checkpoint dreamshaper, lora None, post pixelize paleta game-boy", "golden contrato: los builder_kwargs hacen **spread en comfyui_build_item_icon_workflow sin TypeError y el LoRA del preset aparece en el grafo", "edge style override sustituye el del preset", "edge negative se mergea con el del estilo (no se pierde photorealistic) y deduplica", "edge no muta el preset de entrada", "error subject vacio -> ValueError", "error preset incompleto -> ValueError"] test_file_path: "python/functions/ml/comfyui_apply_style_preset_test.py" file_path: "python/functions/ml/comfyui_apply_style_preset.py" --- ## Ejemplo ```python 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 # 1. Elegir estilo + aplicarlo a un subject preset = comfyui_get_gamedev_style_preset("gameboy") ap = comfyui_apply_style_preset(preset, "knight character") # 2. Construir el workflow con cualquier builder de sujeto (kwargs por **spread) wf = comfyui_build_enemy_creature_workflow( ap["subject"], size=ap["size"], transparent=ap["transparent"], **ap["builder_kwargs"] ) # 3. Generar (submit/wait/fetch) y, si el estilo lo pide, post-proceso: # if ap["post"].get("pixelize"): # comfyui_pixelize_image(raw_png, dst_png, **ap["post"]["pixelize"]) ``` O lanzable directo con: `./fn run comfyui_apply_style_preset` (aplica pixel-art-retro a "knight character"). ## Cuando usarla Justo despues de elegir un estilo con `comfyui_get_gamedev_style_preset`, para convertir esa receta en los argumentos exactos de un builder. Es el puente entre "que estilo quiero" y "como lo paso a item_icon/enemy_creature/prop_object/...". El mismo `ap` sirve para generar N assets distintos en el MISMO estilo (varia solo el `subject`). Para overrides puntuales sin tocar el preset, usa `style=`/`negative=`. ## Gotchas - Devuelve `builder_kwargs` con EXACTAMENTE las 5 claves comunes a los builders de SUJETO (`style`, `checkpoint`, `lora`, `lora_strength`, `negative`). Builders que NO las acepten todas (p.ej. `seamless_tile`, `parallax_background` no tienen `transparent`/`lora` igual) exigen filtrar las claves; este helper esta pensado para los builders de sujeto cuadrado. - `size` y `transparent` van FUERA de `builder_kwargs` (son recomendaciones del estilo): el caller los pasa explicitos o decide otros. `transparent=False` en los presets de demo es para que el look (paleta/pintura) cubra todo el frame; para un sprite con alpha pon `transparent=True` (el recorte es ortogonal al estilo). - El `post` NO se aplica solo: el caller debe llamar `comfyui_pixelize_image(raw, dst, **ap["post"]["pixelize"])` tras descargar el PNG si `ap["post"].get("pixelize")`. Sin eso, estilos como gameboy/pixel-art-retro no sellan su grid/paleta. - Es **pura**: no llama a ningun builder ni toca la GPU; solo arma kwargs. No muta el `preset` de entrada (lo que devuelve es independiente). ## Capability growth log (v1.0.0 — sin cambios todavia.)