Files
novafarma/scripts/generate_dino_valley_complete.py

193 lines
7.2 KiB
Python

#!/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()