#!/usr/bin/env python3
"""Standalone test for generate_topdown_asset logic."""
import asyncio
import json
import os
import sys
from pathlib import Path
from io import BytesIO
# Set environment before any imports
os.environ["BACKEND_TYPE"] = "comfyui"
os.environ["COMFYUI_HOST"] = "127.0.0.1"
os.environ["COMFYUI_PORT"] = "8188"
# Add server to path
server_dir = Path(__file__).parent / "server"
sys.path.insert(0, str(server_dir))
# Import required modules
from backends import ComfyUIBackend
from utils import create_depth_map, ensure_directory, generate_filename
from presets import get_preset
from PIL import Image
async def test_generate_topdown_asset():
"""Test generate_topdown_asset logic directly."""
try:
print("Initializing ComfyUI backend...", file=sys.stderr)
# Initialize backend
backend = ComfyUIBackend()
# Test parameters from payload
asset_type = "prop"
prompt = "ice crystal tower, frozen magical tower, blue glowing crystals, top-down view, game asset"
save_to_file = True
seed = 12348
size = 256
print(f"Testing with: asset_type={asset_type}, prompt={prompt[:50]}..., seed={seed}, size={size}", file=sys.stderr)
# Map asset type to preset and shape (from generate_topdown_asset)
preset_map = {
"prop": ("topdown_prop", "box"),
"character": ("topdown_character", "humanoid"),
"creature": ("topdown_creature", "humanoid"),
"tile": ("topdown_tile", "flat"),
"effect": ("effect", "sphere"),
}
preset, shape = preset_map.get(asset_type, ("topdown_prop", "flat"))
effective_strength = 0.95 # default control_strength
effective_prompt = prompt # for prop, no modification
# Get preset config
preset_config = get_preset(preset)
# Build full prompt
full_prompt = f"{preset_config.prompt_prefix}{effective_prompt}{preset_config.prompt_suffix}"
full_negative = preset_config.negative_prompt
img_width = size
img_height = size
render_width = img_width
render_height = img_height
should_downscale = (img_width < preset_config.default_width) or (img_height < preset_config.default_height)
if should_downscale:
scale = max(preset_config.default_width / max(1, img_width), preset_config.default_height / max(1, img_height))
render_width = int(round(img_width * scale))
render_height = int(round(img_height * scale))
# Clamp render dimensions
render_width = max(512, min(2048, (render_width // 8) * 8))
render_height = max(512, min(2048, (render_height // 8) * 8))
print(f"Render size: {render_width}x{render_height}, should_downscale: {should_downscale}", file=sys.stderr)
# Create depth map
print("Creating depth map...", file=sys.stderr)
depth_map = create_depth_map(render_width, render_height, view_type="topdown", shape=shape)
print(f"Depth map created, size: {len(depth_map)} bytes", file=sys.stderr)
# Generate with timeout
print("Starting generation with ControlNet...", file=sys.stderr)
image_bytes = await asyncio.wait_for(
backend.generate_with_controlnet(
prompt=full_prompt,
control_image=depth_map,
controlnet_model="diffusers_xl_depth_full.safetensors",
control_strength=effective_strength,
negative_prompt=full_negative,
width=render_width,
height=render_height,
seed=seed,
steps=preset_config.steps,
cfg_scale=preset_config.cfg_scale,
sampler=preset_config.sampler,
scheduler=preset_config.scheduler
),
timeout=300.0
)
print(f"Generation completed, image size: {len(image_bytes)} bytes", file=sys.stderr)
if should_downscale:
from utils import resize_image
image_bytes = resize_image(image_bytes, img_width, img_height)
# Save to file if requested
if save_to_file:
output_dir = ensure_directory(Path("./output") / "controlnet")
fname = generate_filename(prefix=f"cn_topdown", suffix=shape)
file_path = output_dir / fname
file_path.write_bytes(image_bytes)
print(f"Saved to file: {file_path}", file=sys.stderr)
# Create result JSON
result = {
"success": True,
"backend": backend.get_name(),
"width": img_width,
"height": img_height,
"view_type": "topdown",
"shape": shape,
"control_strength": effective_strength,
"preset": preset,
"prompt": full_prompt,
"hash": "test_hash", # Would compute actual hash
}
if save_to_file:
result["file_path"] = str(file_path)
result["depth_map_path"] = str(output_dir / f"depth_{fname}")
result["image_base64_omitted"] = True
result["image_base64_omitted_reason"] = "controlnet_always_saves_to_file"
print(json.dumps(result, indent=2))
except asyncio.TimeoutError:
print(json.dumps({
"success": False,
"error": "Generation timed out after 5 minutes",
"backend": "comfyui",
"backend_type": "comfyui"
}, indent=2))
except Exception as e:
print(f"Error during test: {e}", file=sys.stderr)
import traceback
traceback.print_exc(file=sys.stderr)
print(json.dumps({
"success": False,
"error": str(e),
"backend": "comfyui",
"backend_type": "comfyui"
}, indent=2))
if __name__ == "__main__":
asyncio.run(test_generate_topdown_asset())