#!/usr/bin/env python3 """ πŸŒ™ NOČNA GENERACIJA - FULL Asset Set BREZ NPCs in glavnih karakterjev Z avtomatskim Git commitom in progress trackingom """ import os import sys import json import time import uuid import requests import subprocess from pathlib import Path from datetime import datetime try: from rembg import remove from PIL import Image except ImportError: os.system("pip3 install --user rembg pillow onnxruntime") from rembg import remove from PIL import Image # Configuration COMFYUI_URL = "http://127.0.0.1:8000" OUTPUT_DIR = Path("/Users/davidkotnik/repos/novafarma/assets/images") REPO_DIR = Path("/Users/davidkotnik/repos/novafarma") PROGRESS_LOG = REPO_DIR / "generation_progress.log" STYLE = "2D indie game sprite, cartoon vector style, clean smooth outlines, full body visible, isolated on pure white background" NEGATIVE = "pixel art, pixelated, 3d render, realistic photo, anime, blurry, watermark, text, green background" def log(msg): ts = datetime.now().strftime("%H:%M:%S") line = f"[{ts}] {msg}" print(line) sys.stdout.flush() # Also write to progress log with open(PROGRESS_LOG, 'a') as f: f.write(line + "\\n") def git_commit(file_path, category, name): try: rel_path = file_path.relative_to(REPO_DIR) subprocess.run(["git", "add", str(rel_path)], cwd=REPO_DIR, check=True, capture_output=True) subprocess.run(["git", "commit", "-m", f"🎨 Generated: {category}/{name}"], cwd=REPO_DIR, capture_output=True) return True except: return False # Load FULL registry from existing script sys.path.insert(0, str(REPO_DIR / "scripts")) exec(open(REPO_DIR / "scripts/generate_assets_full.py").read().replace('if __name__', 'if False')) # Get all assets EXCEPT NPCs ALL_ASSETS = generate_registry() FILTERED_ASSETS = [a for a in ALL_ASSETS if a['cat'] != 'npcs'] def create_workflow(prompt_text, output_name, size=512): seed = int(time.time() * 1000) % 2147483647 full_prompt = f"{STYLE}, {prompt_text}" return { "1": {"class_type": "CheckpointLoaderSimple", "inputs": {"ckpt_name": "dreamshaper_8.safetensors"}}, "2": {"class_type": "EmptyLatentImage", "inputs": {"width": size, "height": size, "batch_size": 1}}, "3": {"class_type": "CLIPTextEncode", "inputs": {"text": full_prompt, "clip": ["1", 1]}}, "4": {"class_type": "CLIPTextEncode", "inputs": {"text": NEGATIVE, "clip": ["1", 1]}}, "5": { "class_type": "KSampler", "inputs": { "seed": seed, "steps": 30, "cfg": 7.5, "sampler_name": "euler_ancestral", "scheduler": "karras", "denoise": 1.0, "model": ["1", 0], "positive": ["3", 0], "negative": ["4", 0], "latent_image": ["2", 0] } }, "6": {"class_type": "VAEDecode", "inputs": {"samples": ["5", 0], "vae": ["1", 2]}}, "7": {"class_type": "SaveImage", "inputs": {"filename_prefix": output_name, "images": ["6", 0]}} } def queue_prompt(workflow): try: r = requests.post(f"{COMFYUI_URL}/prompt", json={"prompt": workflow, "client_id": f"full_{uuid.uuid4().hex[:8]}"}, timeout=10) return r.json().get("prompt_id") except Exception as e: log(f"❌ Queue error: {e}") return None def wait_completion(prompt_id, timeout=120): start = time.time() while time.time() - start < timeout: try: r = requests.get(f"{COMFYUI_URL}/history/{prompt_id}", timeout=5) if prompt_id in r.json() and r.json()[prompt_id].get("outputs"): return True except: pass time.sleep(2) return False def download_and_process(prompt_id, output_path): try: h = requests.get(f"{COMFYUI_URL}/history/{prompt_id}").json() for out in h.get(prompt_id, {}).get("outputs", {}).values(): for img in out.get("images", []): r = requests.get(f"{COMFYUI_URL}/view", params={"filename": img["filename"], "subfolder": img.get("subfolder", ""), "type": "output"}) if r.status_code == 200: output_path.parent.mkdir(parents=True, exist_ok=True) from io import BytesIO transparent_img = remove(Image.open(BytesIO(r.content))) transparent_img.save(str(output_path), "PNG") return True return False except Exception as e: log(f"❌ Download error: {e}") return False def main(): log("="*70) log("πŸŒ™ NOČNA GENERACIJA - FULL Asset Set") log(" BREZ NPCs in glavnih karakterjev") log("="*70) # Check ComfyUI try: r = requests.get(f"{COMFYUI_URL}/system_stats", timeout=5) log(f"βœ… ComfyUI v{r.json()['system']['comfyui_version']}") except: log("❌ ComfyUI not running!") return log(f"\\nπŸ“Š Registry Statistics:") log(f" Total assets: {len(ALL_ASSETS)}") log(f" NPCs (excluded): {len([a for a in ALL_ASSETS if a['cat'] == 'npcs'])}") log(f" FILTERED (to generate): {len(FILTERED_ASSETS)}") # Count existing existing = sum(1 for a in FILTERED_ASSETS if (OUTPUT_DIR / a['cat'] / a['file']).exists()) to_generate = len(FILTERED_ASSETS) - existing log(f"\\nπŸ“ File Status:") log(f" Already exist: {existing}") log(f" To generate: {to_generate}") # Category breakdown log(f"\\nπŸ“¦ By Category:") cats = {} for a in FILTERED_ASSETS: cats[a['cat']] = cats.get(a['cat'], 0) + 1 for cat, count in sorted(cats.items(), key=lambda x: -x[1]): existing_cat = sum(1 for a in FILTERED_ASSETS if a['cat'] == cat and (OUTPUT_DIR / a['cat'] / a['file']).exists()) log(f" {cat:20s}: {count:4d} total ({existing_cat} exist, {count-existing_cat} to gen)") if to_generate == 0: log("\\nβœ… All assets already generated!") return log(f"\\nπŸš€ Starting generation of {to_generate} assets...") log(f" ETA: ~{to_generate * 20 / 3600:.1f} hours\\n") success, skip, fail = 0, 0, 0 start_time = time.time() for i, asset in enumerate(FILTERED_ASSETS, 1): path = OUTPUT_DIR / asset['cat'] / asset['file'] if path.exists(): skip += 1 if i % 50 == 0: log(f"[{i}/{len(FILTERED_ASSETS)}] Progress: βœ…{success} ⏭️ {skip} ❌{fail}") continue log(f"[{i}/{len(FILTERED_ASSETS)}] 🎨 {asset['cat']}/{asset['file'][:40]}") # Boss size larger size = 768 if asset['cat'] == 'bosses' else 512 wf = create_workflow(asset['prompt'], asset['file'].replace('.png', ''), size) pid = queue_prompt(wf) if pid and wait_completion(pid) and download_and_process(pid, path): log(f" βœ… Done | Auto-committed") git_commit(path, asset['cat'], asset['file']) success += 1 else: log(f" ❌ FAILED") fail += 1 # Progress update every 10 if i % 10 == 0: elapsed = time.time() - start_time per_asset = elapsed / (success + fail) if (success + fail) > 0 else 20 remaining = per_asset * (to_generate - success - fail) log(f"\\nπŸ“Š [{i}/{len(FILTERED_ASSETS)}] βœ…{success} ⏭️ {skip} ❌{fail}") log(f" ⏱️ Elapsed: {elapsed/60:.1f}m | ETA: {remaining/60:.1f}m\\n") elapsed = time.time() - start_time log("\\n" + "="*70) log("πŸŒ™ NOČNA GENERACIJA COMPLETE!") log(f" βœ… Success: {success}") log(f" ⏭️ Skipped: {skip}") log(f" ❌ Failed: {fail}") log(f" ⏱️ Total time: {elapsed/3600:.1f} hours") log(f" πŸ“ Output: {OUTPUT_DIR}") log("="*70) log("\\nπŸ’€ Lahko greste spat - vse je avtomatsko!") if __name__ == "__main__": main()