feat(gamedev): comfyui_build_item_icon_workflow — iconos de inventario
Builder puro hermano de pixelart/sprite_sheet/seamless_tile: arma el dict (API format) para iconos de items (espada/pocion/anillo/libro/escudo). txt2img cuadrado + prompt scaffold de icono + LoRA estilo opcional + Rembg (alpha). Compone comfyui_build_txt2img_workflow + comfyui_inject_lora. Test offline 7/7 verde. Generacion real verificada (icono de pocion de salud centrado, RGBA fondo recortado, prompt_id 70b7a52a, 512x512 SD1.5). Fila en docs/capabilities/gamedev-2d.md. Detalle en report 0147. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,7 @@ 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/0140` (VFX), `reports/0143` (ronda 2b: builders), `reports/0147` (item icons).
|
||||
|
||||
## Builders de workflow 2D (`gamedev-2d`, puros — generación)
|
||||
|
||||
@@ -34,6 +34,7 @@ VFX (ver `reports/0143`).
|
||||
| `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. |
|
||||
|
||||
## Funciones de post-proceso y puente (`gamedev`, CPU)
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
name: comfyui_build_item_icon_workflow
|
||||
kind: function
|
||||
lang: py
|
||||
domain: ml
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "def comfyui_build_item_icon_workflow(item: str, *, style: str = \"game icon, clean, centered\", checkpoint: str = \"dreamshaper_8.safetensors\", size: int = 512, 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 = \"item_icon\") -> dict"
|
||||
description: "Construye el dict (API format) del workflow de UN icono de item de inventario 2D (espada, pocion, anillo, libro, escudo, gema): sujeto unico centrado, fondo limpio uniforme, estilo consistente entre items, encuadre cuadrado. Compone comfyui_build_txt2img_workflow + comfyui_inject_lora (estilo opcional) + Image Rembg (fondo transparente si transparent). Hermano de comfyui_build_pixelart/sprite_sheet/seamless_tile_workflow. Pura, sin red ni I/O. class_types verificados contra /object_info."
|
||||
tags: [comfyui, ml, gamedev, gamedev-2d, icon, item, inventory, 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: item
|
||||
desc: "Nombre del item (ej. 'health potion', 'iron sword', 'gold ring'). Se inserta en un prompt scaffold de icono. No puede estar vacio."
|
||||
- name: style
|
||||
desc: "Descriptor de estilo que mantiene consistentes los items de un set (ej. 'game icon, clean, centered', 'hand-painted RPG icon', 'flat vector icon'). Pasa el MISMO style + checkpoint + lora a todos los items para coherencia visual. keyword-only."
|
||||
- name: checkpoint
|
||||
desc: "Checkpoint del servidor. 'dreamshaper_8.safetensors' (SD1.5, holgado en 8GB lowvram) por defecto; 'juggernaut_xl_v11.safetensors' para SDXL (mas VRAM, subir size). keyword-only."
|
||||
- name: size
|
||||
desc: "Lado del cuadrado en px (width = height = size). 512 SD1.5 por defecto. keyword-only."
|
||||
- name: transparent
|
||||
desc: "Si True inyecta Image Rembg y el PNG sale con alpha (fondo recortado). False = item opaco sobre fondo plano, recortable luego por el caller. keyword-only."
|
||||
- name: seed
|
||||
desc: "Semilla del KSampler. keyword-only."
|
||||
- name: lora
|
||||
desc: "LoRA de estilo opcional en models/loras (ej. 'detail_tweaker_sd15.safetensors', 'isometric_game_assets_sd15.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 iconos (un objeto, fondo limpio, sin texto/foto). 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 icono ('a {item}, game inventory icon, {style}, centered, single object, plain background, ...') + LoRA de estilo opcional + Image Rembg (si transparent). UN icono; set de items -> llamar por item con mismo style/checkpoint/lora."
|
||||
tested: true
|
||||
tests: ["golden transparent: clases CheckpointLoaderSimple/KSampler/VAEDecode/SaveImage/Image Rembg; item + 'game inventory icon' + 'centered' en prompt; SaveImage <- Rembg; transparency True", "edge transparent=False: sin Rembg, SaveImage <- VAEDecode", "edge size: width==height==768 (cuadrado)", "edge style en prompt", "edge lora: LoraLoader presente con strength", "error item vacio -> ValueError", "determinismo"]
|
||||
test_file_path: "python/functions/ml/comfyui_build_item_icon_workflow_test.py"
|
||||
file_path: "python/functions/ml/comfyui_build_item_icon_workflow.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
|
||||
from ml.comfyui_build_item_icon_workflow import comfyui_build_item_icon_workflow
|
||||
|
||||
# Un icono de pocion con fondo transparente (alpha), listo para submit.
|
||||
wf = comfyui_build_item_icon_workflow(
|
||||
"health potion",
|
||||
style="hand-painted RPG icon, glowing red liquid",
|
||||
transparent=True,
|
||||
seed=42,
|
||||
)
|
||||
# Set coherente: misma firma de estilo para cada item del inventario.
|
||||
# for it in ["iron sword", "gold ring", "ancient book", "wooden shield"]:
|
||||
# wf = comfyui_build_item_icon_workflow(it, style="hand-painted RPG icon",
|
||||
# lora="detail_tweaker_sd15.safetensors", seed=42)
|
||||
# comfyui_submit_workflow(wf) # -> comfyui_wait_result -> comfyui_fetch_output_image
|
||||
# Contact-sheet del set: montar los PNG resultantes con comfyui_build_grid.
|
||||
```
|
||||
|
||||
O lanzable directo con: `./fn run comfyui_build_item_icon_workflow` (imprime nodos + class_types del ejemplo).
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando necesites iconos de items de inventario para un juego (RPG, roguelike,
|
||||
crafting) con look consistente entre items: armas, pociones, anillos, libros,
|
||||
escudos, gemas, comida. Pasa el MISMO `style` + `checkpoint` + (`lora`) a todos
|
||||
los items del set para que combinen visualmente; varía solo `item`. `transparent`
|
||||
recorta el fondo (alpha) listo para el motor. Para un atlas/contact-sheet, genera
|
||||
cada icono y monta los PNG con `comfyui_build_grid`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **El recorte usa Rembg, NO luma-to-alpha**: un item es un sujeto solido con
|
||||
silueta definida, rembg lo recorta limpio. `comfyui_matting_luma_to_alpha` es
|
||||
para translucidos sobre negro (humo/fuego/magia) y aplanaria el item — no la
|
||||
uses para iconos.
|
||||
- **Coherencia del set = mismos parametros**: si cambias `style`/`checkpoint`/
|
||||
`lora`/`seed` entre items, el set deja de combinar. Fija esos y varía solo `item`.
|
||||
- **SDXL pide mas VRAM y resolucion**: con `checkpoint="juggernaut_xl_v11.safetensors"`
|
||||
sube `size` a 768/1024; con dreamshaper_8 (SD1.5) deja 512 (holgado en 8GB lowvram).
|
||||
- Si el modelo mete varios objetos o texto, el negativo por defecto ya empuja a
|
||||
"single object / plain background / no text"; refuerza `style` con "single item,
|
||||
isolated" si insiste.
|
||||
- `transparent=False` deja el item 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`.
|
||||
@@ -0,0 +1,203 @@
|
||||
"""Construye el workflow ComfyUI de UN icono de item de inventario (API format).
|
||||
|
||||
Iconos de inventario de juego (espada, pocion, anillo, libro, escudo, gema...):
|
||||
sujeto unico centrado, fondo limpio y uniforme, estilo consistente entre items,
|
||||
encuadre cuadrado. Es el builder hermano de comfyui_build_pixelart_workflow /
|
||||
comfyui_build_sprite_sheet_workflow / comfyui_build_seamless_tile_workflow:
|
||||
mismo patron (PURO, dict API format) que compone funciones existentes del
|
||||
registry, no reescribe el grafo.
|
||||
|
||||
Cableado:
|
||||
|
||||
CheckpointLoaderSimple -> [LoraLoader opcional de estilo] -> KSampler
|
||||
-> CLIPTextEncode (prompt scaffold de icono) ...
|
||||
-> VAEDecode -> [Image Rembg opcional] -> SaveImage
|
||||
|
||||
Compone:
|
||||
- comfyui_build_txt2img_workflow -> base txt2img cuadrada
|
||||
- comfyui_inject_lora -> LoRA de estilo opcional (consistencia)
|
||||
- 'Image Rembg (Remove Background)' (helper local) -> fondo transparente
|
||||
|
||||
Por que Rembg y NO comfyui_matting_luma_to_alpha: un item es un sujeto SOLIDO con
|
||||
silueta definida; rembg recorta limpio la silueta. La luma-to-alpha es para
|
||||
translucidos sobre negro (humo/fuego/magia), donde aplanaria el item. Si el caller
|
||||
prefiere recortar fuera del workflow (transparent=False) deja la imagen opaca
|
||||
sobre fondo plano, recortable luego por el pipeline o el caller.
|
||||
|
||||
class_types/inputs verificados contra /object_info del servidor (8GB lowvram):
|
||||
CheckpointLoaderSimple, CLIPTextEncode, EmptyLatentImage, KSampler, VAEDecode,
|
||||
SaveImage, LoraLoader, 'Image Rembg (Remove Background)' (transparency BOOLEAN).
|
||||
|
||||
Funcion pura: sin red, sin I/O. No muta dicts de entrada (copia profunda en el
|
||||
helper de rembg). Determinista para los mismos argumentos.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
||||
|
||||
# Negativo por defecto pensado para iconos: un solo objeto, fondo limpio, nada de
|
||||
# fotorrealismo ni texto/marcas que ensucien el sujeto centrado.
|
||||
_ICON_NEGATIVE = (
|
||||
"blurry, lowres, multiple objects, cluttered background, busy background, "
|
||||
"text, watermark, signature, photo, photorealistic, jpeg artifacts, "
|
||||
"cropped, out of frame, deformed"
|
||||
)
|
||||
|
||||
|
||||
def _inject_rembg(workflow: dict, model: str) -> dict:
|
||||
"""Inserta 'Image Rembg (Remove Background)' (transparency=True) entre VAEDecode y SaveImage.
|
||||
|
||||
Mismo helper que usa comfyui_build_sprite_sheet_workflow: el nodo recorta la
|
||||
silueta del item dejando alpha. Repunta SaveImage.images a la salida del Rembg.
|
||||
"""
|
||||
wf = copy.deepcopy(workflow)
|
||||
vaedecode_id = next(
|
||||
(nid for nid, n in wf.items() if n.get("class_type") == "VAEDecode"), None
|
||||
)
|
||||
save_id = next((nid for nid, n in wf.items() if n.get("class_type") == "SaveImage"), None)
|
||||
if vaedecode_id is None or save_id is None:
|
||||
raise ValueError(
|
||||
"comfyui_build_item_icon_workflow: no se encontro VAEDecode/SaveImage para Rembg"
|
||||
)
|
||||
numeric = [int(k) for k in wf.keys() if str(k).isdigit()]
|
||||
rembg_id = str((max(numeric) + 1) if numeric else len(wf) + 1)
|
||||
wf[rembg_id] = {
|
||||
"class_type": "Image Rembg (Remove Background)",
|
||||
"inputs": {
|
||||
"images": [vaedecode_id, 0],
|
||||
"transparency": True,
|
||||
"model": model,
|
||||
"post_processing": False,
|
||||
"only_mask": False,
|
||||
"alpha_matting": False,
|
||||
"alpha_matting_foreground_threshold": 240,
|
||||
"alpha_matting_background_threshold": 10,
|
||||
"alpha_matting_erode_size": 10,
|
||||
"background_color": "none",
|
||||
},
|
||||
}
|
||||
wf[save_id]["inputs"]["images"] = [rembg_id, 0]
|
||||
return wf
|
||||
|
||||
|
||||
def comfyui_build_item_icon_workflow(
|
||||
item: str,
|
||||
*,
|
||||
style: str = "game icon, clean, centered",
|
||||
checkpoint: str = "dreamshaper_8.safetensors",
|
||||
size: int = 512,
|
||||
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 = "item_icon",
|
||||
) -> dict:
|
||||
"""Construye el dict (API format) del workflow de un icono de item de inventario.
|
||||
|
||||
Args:
|
||||
item: nombre del item (ej. "health potion", "iron sword", "gold ring").
|
||||
Se inserta en un prompt scaffold de icono. No puede estar vacio.
|
||||
style: descriptor de estilo que mantiene consistentes los items de un set
|
||||
(ej. "game icon, clean, centered", "hand-painted RPG icon", "flat
|
||||
vector icon"). Pasa el MISMO style + checkpoint + (lora) a todos los
|
||||
items del set para coherencia visual. keyword-only.
|
||||
checkpoint: checkpoint del servidor. 'dreamshaper_8.safetensors' (SD1.5,
|
||||
holgado en 8GB lowvram) por defecto; 'juggernaut_xl_v11.safetensors'
|
||||
para SDXL (mas VRAM, subir size a 768/1024). keyword-only.
|
||||
size: lado del cuadrado en px (width = height = size). 512 SD1.5 por
|
||||
defecto. keyword-only.
|
||||
transparent: si True inyecta Rembg y el PNG sale con alpha (fondo
|
||||
recortado). Si False deja el item opaco sobre fondo plano, recortable
|
||||
luego por el caller/pipeline. keyword-only.
|
||||
seed: semilla del KSampler. keyword-only.
|
||||
lora: LoRA de estilo opcional en models/loras (ej.
|
||||
'detail_tweaker_sd15.safetensors', 'isometric_game_assets_sd15.safetensors').
|
||||
None = sin LoRA. keyword-only.
|
||||
lora_strength: fuerza del LoRA sobre model y clip. Se clampa a [0.0, 2.0].
|
||||
keyword-only.
|
||||
rembg_model: modelo Rembg ('u2net' general, 'isnet-anime' para anime).
|
||||
Solo se usa si transparent=True. keyword-only.
|
||||
negative: prompt negativo. None usa el negativo por defecto pensado para
|
||||
iconos (un objeto, fondo limpio, sin texto/foto). keyword-only.
|
||||
steps, cfg, sampler_name, scheduler, filename_prefix: parametros de
|
||||
generacion. keyword-only.
|
||||
|
||||
Returns:
|
||||
dict en API format listo para comfyui_submit_workflow: txt2img base
|
||||
cuadrada con prompt scaffold de icono + LoRA de estilo opcional + Rembg
|
||||
(si transparent). Es UN icono; un set de items -> llamar por item con el
|
||||
mismo style/checkpoint/lora y montar con comfyui_build_grid si se quiere.
|
||||
|
||||
Raises:
|
||||
ValueError: si item esta vacio, o si la base no tiene VAEDecode/SaveImage
|
||||
donde inyectar el Rembg (propagado por el helper).
|
||||
"""
|
||||
from ml.comfyui_build_txt2img_workflow import comfyui_build_txt2img_workflow
|
||||
|
||||
if not item or not item.strip():
|
||||
raise ValueError("comfyui_build_item_icon_workflow: 'item' no puede estar vacio")
|
||||
|
||||
lora_strength = max(0.0, min(2.0, float(lora_strength)))
|
||||
neg = _ICON_NEGATIVE if negative is None else negative
|
||||
|
||||
# Prompt scaffold de icono: sujeto unico, centrado, fondo plano, sin recorte.
|
||||
positive = (
|
||||
f"a {item.strip()}, game inventory icon, {style}, centered, "
|
||||
"single object, plain background, clean, high detail"
|
||||
)
|
||||
|
||||
wf = comfyui_build_txt2img_workflow(
|
||||
checkpoint,
|
||||
positive,
|
||||
neg,
|
||||
steps=steps,
|
||||
cfg=cfg,
|
||||
width=size,
|
||||
height=size,
|
||||
seed=seed,
|
||||
sampler_name=sampler_name,
|
||||
scheduler=scheduler,
|
||||
filename_prefix=filename_prefix,
|
||||
)
|
||||
|
||||
if lora:
|
||||
from ml.comfyui_inject_lora import comfyui_inject_lora
|
||||
|
||||
wf = comfyui_inject_lora(
|
||||
wf, lora, strength_model=lora_strength, strength_clip=lora_strength
|
||||
)
|
||||
|
||||
if transparent:
|
||||
wf = _inject_rembg(wf, rembg_model)
|
||||
|
||||
return wf
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import json
|
||||
|
||||
wf = comfyui_build_item_icon_workflow(
|
||||
"health potion",
|
||||
style="hand-painted RPG icon, glowing red liquid",
|
||||
transparent=True,
|
||||
seed=42,
|
||||
)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"nodes": list(wf),
|
||||
"classes": sorted({n["class_type"] for n in wf.values()}),
|
||||
},
|
||||
indent=2,
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,95 @@
|
||||
"""Tests offline de comfyui_build_item_icon_workflow (estructura del dict, sin GPU)."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from ml.comfyui_build_item_icon_workflow import ( # noqa: E402
|
||||
comfyui_build_item_icon_workflow,
|
||||
)
|
||||
|
||||
|
||||
def _classes(wf):
|
||||
return sorted({n["class_type"] for n in wf.values()})
|
||||
|
||||
|
||||
def _by_class(wf, cls):
|
||||
return [n for n in wf.values() if n["class_type"] == cls]
|
||||
|
||||
|
||||
def _id_of(wf, cls):
|
||||
return next(nid for nid, n in wf.items() if n["class_type"] == cls)
|
||||
|
||||
|
||||
def test_golden_transparent_recipe():
|
||||
wf = comfyui_build_item_icon_workflow("health potion", transparent=True, seed=42)
|
||||
cls = _classes(wf)
|
||||
# Cadena base txt2img + Rembg para alpha.
|
||||
assert "CheckpointLoaderSimple" in cls
|
||||
assert "KSampler" in cls
|
||||
assert "VAEDecode" in cls
|
||||
assert "SaveImage" in cls
|
||||
assert "Image Rembg (Remove Background)" in cls
|
||||
# El item aparece en el prompt positivo, con el scaffold de icono.
|
||||
pos = next(
|
||||
n for n in wf.values()
|
||||
if n["class_type"] == "CLIPTextEncode" and "health potion" in n["inputs"]["text"]
|
||||
)
|
||||
assert "game inventory icon" in pos["inputs"]["text"]
|
||||
assert "centered" in pos["inputs"]["text"]
|
||||
# SaveImage toma la imagen del Rembg (no del VAEDecode).
|
||||
rembg_id = _id_of(wf, "Image Rembg (Remove Background)")
|
||||
save = next(n for n in wf.values() if n["class_type"] == "SaveImage")
|
||||
assert save["inputs"]["images"] == [rembg_id, 0]
|
||||
assert _by_class(wf, "Image Rembg (Remove Background)")[0]["inputs"]["transparency"] is True
|
||||
|
||||
|
||||
def test_edge_opaque_no_rembg():
|
||||
wf = comfyui_build_item_icon_workflow("iron sword", transparent=False)
|
||||
assert "Image Rembg (Remove Background)" not in _classes(wf)
|
||||
# SaveImage toma del VAEDecode directamente.
|
||||
vd_id = _id_of(wf, "VAEDecode")
|
||||
save = next(n for n in wf.values() if n["class_type"] == "SaveImage")
|
||||
assert save["inputs"]["images"] == [vd_id, 0]
|
||||
|
||||
|
||||
def test_edge_size_reflected():
|
||||
wf = comfyui_build_item_icon_workflow("gold ring", size=768)
|
||||
latent = _by_class(wf, "EmptyLatentImage")[0]["inputs"]
|
||||
assert latent["width"] == 768
|
||||
assert latent["height"] == 768 # cuadrado
|
||||
|
||||
|
||||
def test_edge_style_in_prompt():
|
||||
wf = comfyui_build_item_icon_workflow(
|
||||
"ancient book", style="flat vector icon, minimalist", transparent=False
|
||||
)
|
||||
pos = next(
|
||||
n for n in wf.values()
|
||||
if n["class_type"] == "CLIPTextEncode" and "ancient book" in n["inputs"]["text"]
|
||||
)
|
||||
assert "flat vector icon, minimalist" in pos["inputs"]["text"]
|
||||
|
||||
|
||||
def test_edge_lora_reflected():
|
||||
wf = comfyui_build_item_icon_workflow(
|
||||
"magic shield", lora="detail_tweaker_sd15.safetensors", lora_strength=0.9
|
||||
)
|
||||
loras = _by_class(wf, "LoraLoader")
|
||||
assert len(loras) == 1
|
||||
assert loras[0]["inputs"]["lora_name"] == "detail_tweaker_sd15.safetensors"
|
||||
assert loras[0]["inputs"]["strength_model"] == 0.9
|
||||
|
||||
|
||||
def test_error_empty_item():
|
||||
try:
|
||||
comfyui_build_item_icon_workflow(" ")
|
||||
assert False
|
||||
except ValueError as e:
|
||||
assert "item" in str(e)
|
||||
|
||||
|
||||
def test_determinism():
|
||||
a = comfyui_build_item_icon_workflow("emerald gem", lora="detail_tweaker_sd15.safetensors", seed=7)
|
||||
b = comfyui_build_item_icon_workflow("emerald gem", lora="detail_tweaker_sd15.safetensors", seed=7)
|
||||
assert a == b
|
||||
Reference in New Issue
Block a user