---
name: comfyui_build_skill_tree_node_workflow
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: pure
signature: "def comfyui_build_skill_tree_node_workflow(skill: str, *, frame: str = \"hexagonal\", state: str = \"unlocked\", ui_style: str = \"fantasy skill tree node\", checkpoint: str = \"IMG_dreamshaper_8.safetensors\", size: int = 256, transparent: bool = True, seed: int = 0, lora: str | None = None, lora_strength: float = 1.0, rembg_model: str = \"u2net\", negative: str | None = None, steps: int = 28, cfg: float = 7.0, sampler_name: str = \"dpmpp_2m\", scheduler: str = \"karras\", filename_prefix: str = \"skill_tree_node\") -> dict"
description: "Construye el dict (API format) del workflow de UN nodo de arbol de habilidades / talentos 2D (RPG, ARPG, MOBA, roguelike): el icono de una skill DENTRO de un marco decorativo (circular, hexagonal, rombo, escudo) que la UI de progresion pinta en la rejilla de talentos, con variante de ESTADO visual (desbloqueado brillante / bloqueado gris). Centrado, fondo limpio uniforme, recortable a alpha, estilo consistente entre nodos del arbol. DISTINTO de item_icon (objeto de inventario sin marco), status_effect_icon (simbolo de estado superpuesto sin marco) y ui_hud (chrome grande suelto): esto es el nodo ENMARCADO completo de la pantalla de talentos. El marco y el estado son la firma del asset. Compone comfyui_build_txt2img_workflow + comfyui_inject_lora (estilo opcional) + Image Rembg (fondo transparente si transparent). Hermano de comfyui_build_status_effect_icon/ui_hud_workflow. Pura, sin red ni I/O. class_types verificados contra /object_info."
tags: [comfyui, ml, gamedev-2d, ui, skill, talent, tree, progression, node, frame, rembg, workflow]
uses_functions: [comfyui_build_txt2img_workflow_py_ml, comfyui_inject_lora_py_ml]
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params:
  - name: skill
    desc: "Nombre de la habilidad/talento que va dentro del nodo (ej. 'fireball', 'double jump', 'critical strike', 'healing aura', 'stealth', 'lightning bolt'). Se inserta en un prompt scaffold de nodo de skill tree. No puede estar vacio."
  - name: frame
    desc: "Forma del marco del nodo (ej. 'hexagonal', 'circular', 'diamond', 'shield', 'square ornate'). Define la silueta enmarcada que perfila el nodo en la rejilla de talentos. Pasa el MISMO frame a todos los nodos del arbol para coherencia. keyword-only."
  - name: state
    desc: "Estado visual del nodo: 'unlocked' (disponible/comprado: brillante, saturado, resaltado) o 'locked' (bloqueado: gris, desaturado, atenuado). Genera el par con el mismo skill/frame/ui_style/seed para tener las dos caras del mismo talento. Cualquier otro valor se inserta literal y la pista visual cae a la de 'unlocked'. keyword-only."
  - name: ui_style
    desc: "Descriptor de estilo de UI que mantiene consistentes los nodos de un arbol (ej. 'fantasy skill tree node', 'sci-fi tech tree, neon', 'dark souls talent node', 'minimal flat skill node'). Pasa el MISMO ui_style + frame + checkpoint + lora a todos los nodos para coherencia visual. keyword-only."
  - name: checkpoint
    desc: "Checkpoint del servidor. 'IMG_dreamshaper_8.safetensors' (SD1.5, holgado en 8GB lowvram) por defecto; 'IMG_juggernaut_xl_v11.safetensors' para SDXL (mas VRAM, subir size). keyword-only."
  - name: size
    desc: "Lado del cuadrado en px (width = height = size). 256 por defecto: los nodos de talento se muestran a tamano reducido en la rejilla. keyword-only."
  - name: transparent
    desc: "Si True inyecta Image Rembg y el PNG sale con alpha (fondo recortado, la silueta del marco). False = nodo opaco sobre fondo plano, recortable luego por el caller. keyword-only."
  - name: seed
    desc: "Semilla del KSampler. Fija el mismo seed en el par unlocked/locked del mismo talento para que coincidan. keyword-only."
  - name: lora
    desc: "LoRA de estilo opcional en models/loras (ej. 'SD15_detail_tweaker.safetensors'). None = sin LoRA. keyword-only."
  - name: lora_strength
    desc: "Fuerza del LoRA sobre model y clip. Se clampa a [0.0, 2.0]. keyword-only."
  - name: rembg_model
    desc: "Modelo Rembg ('u2net' general, 'isnet-anime' para anime). Solo se usa si transparent=True. keyword-only."
  - name: negative
    desc: "Prompt negativo. None usa el negativo por defecto pensado para nodos de skill tree (icono enmarcado limpio, fondo limpio, sin escena/personaje/texto). keyword-only."
  - name: steps
    desc: "Pasos del KSampler. keyword-only."
  - name: cfg
    desc: "CFG del KSampler. keyword-only."
  - name: sampler_name
    desc: "Sampler del KSampler. keyword-only."
  - name: scheduler
    desc: "Scheduler del KSampler. keyword-only."
  - name: filename_prefix
    desc: "Prefijo del PNG en output/. keyword-only."
output: "dict en API format listo para comfyui_submit_workflow: base txt2img cuadrada con prompt scaffold de nodo de skill tree ('{skill} skill icon inside a {frame} {ui_style} frame, {state} ({state hint}), centered, plain background, game UI, ...') + LoRA de estilo opcional + Image Rembg (si transparent). UN nodo; un arbol completo -> llamar por skill (y por state) con mismo frame/ui_style/checkpoint/lora y montar la rejilla en el motor."
tested: true
test_file_path: python/functions/ml/comfyui_build_skill_tree_node_workflow_test.py
tests: [test_golden_transparent, test_edge_transparent_false_no_rembg, test_edge_size_reflected_square, test_edge_frame_reflected, test_edge_state_locked_reflected, test_edge_state_unlocked_hint, test_edge_ui_style_reflected, test_edge_skill_reflected, test_edge_lora_injected, test_error_empty_skill, test_determinism]
file_path: python/functions/ml/comfyui_build_skill_tree_node_workflow.py
---

Construye el dict (API format) del workflow de UN nodo de arbol de habilidades /
talentos 2D: el icono de una skill DENTRO de un marco decorativo (circular,
hexagonal, rombo, escudo) que la UI de progresion pinta en la rejilla de talentos,
con variante de ESTADO visual (desbloqueado brillante / bloqueado gris). Centrado,
fondo limpio uniforme, recortable a alpha, estilo de UI consistente entre nodos del
mismo arbol. Compone `comfyui_build_txt2img_workflow` + `comfyui_inject_lora` (estilo
opcional) + `Image Rembg` (fondo transparente si `transparent`). Hermano de
`comfyui_build_status_effect_icon_workflow` / `comfyui_build_ui_hud_workflow`. Pura,
sin red ni I/O. class_types verificados contra `/object_info`.

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_build_skill_tree_node_workflow import comfyui_build_skill_tree_node_workflow

# Nodo de skill desbloqueado, marco hexagonal, fondo transparente (alpha).
wf = comfyui_build_skill_tree_node_workflow(
    "fireball",
    frame="hexagonal",
    state="unlocked",
    ui_style="fantasy skill tree node",
    transparent=True,
    seed=12345,
)
# El par de un mismo talento (las dos caras de la rejilla): mismo skill/frame/seed,
# solo cambia state. El motor intercambia el sprite segun el progreso del jugador.
#   for st in ["unlocked", "locked"]:
#       wf = comfyui_build_skill_tree_node_workflow("fireball", frame="hexagonal",
#                                                   state=st, seed=12345)
#       comfyui_submit_workflow(wf)  # -> comfyui_wait_result -> comfyui_fetch_output_image
# Arbol completo coherente: misma firma de frame/ui_style por nodo, varia skill.
```

O lanzable directo con: `./fn run comfyui_build_skill_tree_node_workflow` (imprime nodos + class_types del ejemplo).

## Cuando usarla

Cuando necesites los nodos de la pantalla de talentos / arbol de habilidades de un
juego (RPG, ARPG, MOBA, roguelike): cada celda de la rejilla de progresion es el icono
de una skill enmarcado, con un aspecto cuando esta disponible/comprado (brillante) y
otro cuando esta bloqueado (gris). Genera el **par** `state="unlocked"` /
`state="locked"` con el mismo `skill`/`frame`/`ui_style`/`seed` para tener las dos
caras del mismo talento; el motor cambia el sprite segun el progreso. Pasa el MISMO
`frame` + `ui_style` + `checkpoint` + (`lora`) a todos los nodos para que la rejilla
combine. `transparent` recorta la silueta del marco (alpha) lista para el motor.

Eligela frente a sus hermanos por el ROL del asset:
- **item_icon** -> objeto de inventario (espada, pocion): ilustracion de un objeto
  suelto, SIN marco.
- **status_effect_icon** -> simbolo de estado compacto que se superpone al retrato/barra
  del personaje, SIN marco; optimizado para 16-32 px.
- **ui_hud** -> chrome grande/suelto de la interfaz (botones, barras, marcos vacios);
  no es el nodo de talento completo.
- **skill_tree_node (esta)** -> el nodo ENMARCADO completo de la pantalla de talentos =
  icono de skill + marco + estado (unlocked/locked).

## Gotchas

- **El marco y el estado son la firma**: lo que distingue este builder de
  item_icon/status_effect_icon es que el icono va DENTRO de un `frame` y arrastra un
  `state`. El negativo por defecto NO rechaza "frame/border" (el marco es parte del
  asset), pero si rechaza escenas recargadas, multiples nodos y fondos sucios. Si el
  modelo ignora el marco, refuerza `ui_style` con "ornate {frame} frame, bordered".
- **El par unlocked/locked debe compartir parametros**: para que las dos caras del
  mismo talento coincidan, fija el mismo `skill`/`frame`/`ui_style`/`seed` y varia
  SOLO `state`. La pista visual del estado (`unlocked` -> glowing/vibrant; `locked` ->
  greyed out/desaturated) se anade automaticamente en el prompt.
- **Coherencia del arbol = mismos parametros**: si cambias `frame`/`ui_style`/
  `checkpoint`/`lora` entre nodos, la rejilla deja de combinar. Fija esos y varia solo
  `skill` (y `state`).
- **El recorte usa Rembg, NO luma-to-alpha**: un nodo es una pieza SOLIDA con silueta
  definida (el marco perfila el borde), rembg lo recorta limpio. `comfyui_matting_luma_to_alpha`
  es para translucidos sobre negro (humo/fuego/runas brillantes) y aplanaria el marco
  — no la uses para estos nodos.
- **El texto/nombre lo pone el motor, no la imagen**: el negativo por defecto empuja a
  "no text/no letters/no numbers" para que el nodo quede limpio; el nombre del talento,
  el coste y los rangos los renderiza el juego sobre el nodo.
- **SDXL pide mas VRAM y resolucion**: con `checkpoint="IMG_juggernaut_xl_v11.safetensors"`
  sube `size` a 512; con IMG_dreamshaper_8 (SD1.5) deja 256 (holgado en 8GB lowvram).
- `transparent=False` deja el nodo opaco sobre fondo plano: util si prefieres recortar
  fuera del workflow o el motor compone sobre un slot solido.
- Es una funcion **pura**: solo arma el dict. La generacion real (GPU) la hacen
  `comfyui_submit_workflow` + `comfyui_wait_result` + `comfyui_fetch_output_image`.
