""" Forge-Props-Env-UI Brick """ import gradio as gr import spaces # Robust import for local workspace + HF Space deployment (common is vendored on push) import sys from pathlib import Path HERE = Path(__file__).resolve().parent for candidate in (HERE.parent, HERE): if (candidate / "common" / "manifest.py").exists(): sys.path.insert(0, str(candidate)) break try: from common.manifest import create_manifest from common.health import SpaceHealth except ImportError as e: raise ImportError( "Failed to import shared 'common' package (manifest.py / health.py).\n" "For local development: run ./install.sh from the forge-bricks/ root.\n" "For HF Spaces: re-run scripts/push_to_hf.py so it vendors common/." ) from e health = SpaceHealth() import os from pathlib import Path from datetime import datetime @spaces.GPU(duration=90) def generate_prop(prompt: str, category: str = "prop") -> dict: out_dir = Path(os.environ.get("FORGE_BRICKS_OUTPUT", "./outputs/forge_props")) out_dir.mkdir(parents=True, exist_ok=True) ts = int(datetime.now().timestamp()) # Enhance prompt based on category for better game assets cat_prompt = { "prop": "game prop, clean topology, PBR friendly", "environment": "game environment asset, tileable if possible", "skybox": "game skybox, panoramic, atmospheric", "ui": "game UI element, clean, icon style, transparent background friendly" }.get(category, "") full_prompt = f"{prompt}, {cat_prompt}, stylized game art, high detail, no text" target = "black-forest-labs/FLUX.1-schnell" api_name = "/infer" img_path = None try: if health.is_ok(target) is not False: # Note: health may not be defined here, add if needed from gradio_client import Client client = Client(target, timeout=120) res = client.predict( prompt=full_prompt, seed=-1, randomize_seed=True, width=1024, height=1024, num_inference_steps=6, api_name=api_name, ) if isinstance(res, (list, tuple)) and res: p = res[0] if isinstance(res[0], str) else res[0].get("path") if isinstance(res[0], dict) else None if p and os.path.exists(str(p)): img_path = str(out_dir / f"{category}_{ts}.png") Image.open(p).save(img_path) except Exception as e: print(f"Prop gen client error: {e}") if not img_path: img_path = str(out_dir / f"{category}_{ts}.png") from PIL import Image Image.new("RGB", (512, 512), (90, 120, 80)).save(img_path) man = create_manifest( name=prompt[:30].replace(" ", "_"), type=f"ui_element" if category=="ui" else "prop", source_brick="forge-props-env-ui", prompt_or_desc=prompt, files={"image": img_path}, metadata={"category": category, "model": "FLUX.1-schnell"}, commercial_ok=True ) man.save(out_dir / f"manifest_{ts}.json") return {"file": img_path, "manifest": man.to_dict()} def build_ui(): with gr.Blocks() as d: gr.Markdown("# Forge-Props-Env-UI") p = gr.Textbox("fantasy wooden barrel with metal bands") cat = gr.Dropdown(["prop", "environment", "skybox", "ui"], value="prop") btn = gr.Button("Generate") out = gr.JSON() btn.click(generate_prop, [p, cat], out) return d # Build at module level so that `demo` (and `gradio_app`) exist when the module is imported # (required for Hugging Face Spaces and for agent/MCP discovery). demo = build_ui() gradio_app = demo # alias for compatibility with tools/skills that expect `gradio_app` if __name__ == "__main__": demo.launch(server_name="0.0.0.0", server_port=7865, mcp_server=True)