#!/usr/bin/env python3 """ šŸ¦– COMPLETE DINO VALLEY DLC GENERATOR Generates all remaining 136 assets for Dino Valley biome """ import json import time import os from pathlib import Path from PIL import Image import google.generativeai as genai # Configure Gemini genai.configure(api_key=os.environ.get("GEMINI_API_KEY")) REPO = Path("/Users/davidkotnik/repos/novafarma") MANIFEST = REPO / "DINO_VALLEY_COMPLETE_MANIFEST.json" OUTPUT_DIR = REPO / "assets/slike/dinozavri" # Style prompts STYLE_A_BASE = "ISOLATED ON PURE WHITE BACKGROUND. Vibrant cartoon vector art with bold black outlines, flat colors, cute and playful style. NO shadows, NO gradients. Clean cel-shaded look." STYLE_B_BASE = "ISOLATED ON PURE WHITE BACKGROUND. Dark hand-drawn 2D indie game art. Noir style with high contrast, sketchy linework, dramatic shadows. Gritty and atmospheric." def create_preview(image_path: Path, size=256): """Create preview version""" try: img = Image.open(image_path) preview = img.resize((size, size), Image.Resampling.LANCZOS) preview_path = image_path.parent / f"{image_path.stem}_preview_{size}x{size}.png" preview.save(preview_path, 'PNG', optimize=True) return preview_path except Exception as e: print(f" āš ļø Preview failed: {e}") return None def generate_image(prompt: str, output_path: Path, log_file): """Generate single image using Gemini""" start = time.time() try: print(f" šŸŽØ Generating: {output_path.name}") log_file.write(f"{time.strftime('%H:%M:%S')} - Generating {output_path.name}\n") log_file.flush() model = genai.GenerativeModel('gemini-2.5-flash') response = model.generate_content([prompt]) if hasattr(response, '_result') and response._result.candidates: image_data = response._result.candidates[0].content.parts[0].inline_data.data # Save original with open(output_path, 'wb') as f: f.write(image_data) # Create preview preview = create_preview(output_path) elapsed = time.time() - start print(f" āœ… Saved: {output_path.name} ({elapsed:.1f}s)") log_file.write(f"{time.strftime('%H:%M:%S')} - SUCCESS {output_path.name} ({elapsed:.1f}s)\n") log_file.flush() return True else: print(f" āŒ No image data") log_file.write(f"{time.strftime('%H:%M:%S')} - FAILED {output_path.name} - No data\n") log_file.flush() return False except Exception as e: print(f" āŒ Error: {e}") log_file.write(f"{time.strftime('%H:%M:%S')} - ERROR {output_path.name} - {e}\n") log_file.flush() return False def run_generation(): """Run complete Dino Valley generation""" # Load manifest with open(MANIFEST, 'r') as f: manifest = json.load(f) # Create output directory OUTPUT_DIR.mkdir(parents=True, exist_ok=True) # Create log log_dir = REPO / "logs" log_dir.mkdir(exist_ok=True) log_file = open(log_dir / f"dino_valley_{time.strftime('%Y%m%d_%H%M%S')}.log", 'w') print("="*70) print("šŸ¦– COMPLETE DINO VALLEY DLC GENERATION") print("="*70) print(f"Total needed: {manifest['total_assets_needed']} assets") print(f"Completed: {manifest['completed']} assets") print(f"Remaining: {manifest['remaining']} assets") print("="*70) log_file.write(f"DINO VALLEY GENERATION - {time.strftime('%Y-%m-%d %H:%M:%S')}\n") log_file.write(f"Remaining: {manifest['remaining']} assets\n") log_file.write("="*70 + "\n\n") log_file.flush() stats = {'total': 0, 'success': 0, 'failed': 0} try: # Process each category for category_name in manifest['generation_order']: # Parse category name cat_key = category_name.split(' (')[0] category = manifest['categories'][cat_key] if category['status'] == "āœ… 100% COMPLETE": print(f"\nā­ļø Skipping {cat_key} (already complete)") continue print(f"\n{'='*70}") print(f"šŸ“¦ CATEGORY: {cat_key}") print(f"{'='*70}") log_file.write(f"\n{'='*70}\n") log_file.write(f"CATEGORY: {cat_key}\n") log_file.write(f"{'='*70}\n\n") log_file.flush() # Process each asset for asset in category['assets']: if isinstance(asset, str): # Simple string asset (skip, already done) continue asset_name = asset['name'] description = asset['description'] # Generate styleA stats['total'] += 1 print(f"\nšŸ“ø [{stats['total']}/{manifest['remaining']}] {asset_name}_styleA") prompt = f"{STYLE_A_BASE}\n\n{description}\n\nPrehistoric Dino Valley biome theme. Gamedev sprite asset." output_path = OUTPUT_DIR / f"{asset_name}_stylea.png" if generate_image(prompt, output_path, log_file): stats['success'] += 1 else: stats['failed'] += 1 time.sleep(15) # Rate limiting (5 req/min limit) # Generate styleB stats['total'] += 1 print(f"\nšŸ“ø [{stats['total']}/{manifest['remaining']}] {asset_name}_styleB") prompt = f"{STYLE_B_BASE}\n\n{description}\n\nPrehistoric Dino Valley biome theme. Gamedev sprite asset." output_path = OUTPUT_DIR / f"{asset_name}_styleb.png" if generate_image(prompt, output_path, log_file): stats['success'] += 1 else: stats['failed'] += 1 # Progress progress = (stats['total'] / manifest['remaining']) * 100 print(f"\nšŸ“Š Progress: {progress:.1f}% | Success: {stats['success']} | Failed: {stats['failed']}") time.sleep(15) # Rate limiting (5 req/min limit) # Final summary print("\n" + "="*70) print("āœ… DINO VALLEY GENERATION COMPLETE!") print("="*70) print(f"Total: {stats['total']}") print(f"āœ… Success: {stats['success']}") print(f"āŒ Failed: {stats['failed']}") print(f"šŸ“ˆ Success rate: {stats['success']/stats['total']*100:.1f}%") log_file.write(f"\n{'='*70}\n") log_file.write(f"GENERATION COMPLETE\n") log_file.write(f"Total: {stats['total']}\n") log_file.write(f"Success: {stats['success']}\n") log_file.write(f"Failed: {stats['failed']}\n") except KeyboardInterrupt: print(f"\n\nāš ļø INTERRUPTED at {stats['total']}") log_file.write(f"\n\nINTERRUPTED at {stats['total']}\n") finally: log_file.close() if __name__ == "__main__": run_generation()