Files
novafarma/scripts/generate_all_biomes_complete.py
David Kotnik c7c10d5a5c 🎨 STRICT STYLE ENFORCEMENT - Style 32/30 Mandatory
STYLE 32 (Dark-Chibi Noir) - ALL entities:
- 4-5px thick black outlines (bold marker)
- Chibi proportions (40-50% head:body)
- Flat colors ONLY (zero gradients)
- Sharp noir block shadows
- Large empty eyes (NO pupils)
- Pastel-gothic palette

STYLE 30 (Garden Story Cozy) - ALL vegetation:
- Thin outlines (1-2px)
- Soft watercolor shading
- Rounded organic shapes
- Pastel-botanical colors
- Wholesome aesthetic

Updated files:
- STYLE_32_STRICT_MANDATE.md (new enforcement document)
- scripts/generate_all_biomes_complete.py (auto-style selection)

Zero-tolerance policy for style drift.
2026-01-02 23:56:05 +01:00

208 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
COMPLETE BIOME ASSET GENERATOR - STRICT STYLE ENFORCEMENT
Generates ALL missing biome assets with dual art style:
- Style 32 (Dark-Chibi Noir): ALL entities, creatures, NPCs, objects
- Style 30 (Garden Story Cozy): ALL vegetation, plants, botanical items
UPDATED: 02.01.2026 - Zero-tolerance style enforcement
"""
import os
import time
import requests
import json
from pathlib import Path
# ========================================
# CONFIGURATION
# ========================================
PROJECT_ROOT = Path("/Users/davidkotnik/repos/novafarma")
BIOME_ROOT = PROJECT_ROOT / "assets/slike/biomi"
# Gemini API endpoint (če imaš API key)
API_KEY = os.getenv("GEMINI_API_KEY") # Set this in environment
API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image:generateImage"
# Art styles - STRICT ENFORCEMENT (02.01.2026)
STYLE_32_ENTITIES = """exact Dark-Chibi Noir style with:
- Very thick black outlines (4-5px bold marker lines)
- Chibi proportions (head 40-50% of total body, large features)
- Flat colors ONLY, NO gradients, NO soft shading
- Sharp block shadows (black/dark purple on one side for noir effect)
- Large empty eyes (white or red, NO pupils, cult-like)
- Pastel-gothic color palette (soft colors + dark accents)"""
STYLE_30_VEGETATION = """exact Garden Story cozy botanical style with:
- Thin gentle outlines (1-2px)
- Soft watercolor-like shading (subtle gradients allowed)
- Rounded organic shapes, wholesome aesthetic
- Pastel-vibrant botanical colors
- Friendly, inviting, nature-focused look"""
# ========================================
# BIOME DEFINITIONS
# ========================================
BIOMES = {
"dino_valley": {
"rekviziti": [
"dinosaur_skeleton_full",
"dino_ribcage",
"fossil_imprint",
"amber_chunk_insect",
"dino_tooth_large",
"dino_nest_eggs",
"volcanic_rock_cluster",
"steam_vent_active",
"tar_pit_bubbles",
"cave_entrance_prehistoric",
"ruins_pillar_ancient",
"ruins_wall_ancient",
"stone_altar_prehistoric",
"lava_flow",
"geyser_active",
"dino_claw_large",
"precious_stone_raw",
"ancient_artifact",
"plant_sample_rare",
"volcano_background"
],
"npcs": [
"paleontologist",
"cave_person_male",
"cave_person_female",
"cave_child",
"dino_keeper_romance"
],
# Add other categories as needed
},
# Add other biomes...
}
# ========================================
# HELPER FUNCTIONS
# ========================================
def check_existing_assets(biome_name, category):
"""Check which assets already exist"""
folder = BIOME_ROOT / biome_name / category
if not folder.exists():
return []
existing = []
for file in folder.glob("*.png"):
# Extract base name without _styleA/B suffix
name = file.stem
if name.endswith("_stylea") or name.endswith("_styleb"):
base = name.rsplit("_style", 1)[0]
existing.append(base)
return list(set(existing))
def generate_asset_prompt(asset_name, asset_type, is_vegetation=False):
"""Generate prompt for specific asset with strict style enforcement"""
category_prompts = {
"rekviziti": "2D game prop",
"npcs": "2D game character NPC",
"vegetacija": "2D game vegetation",
"teren": "2D game terrain tile, seamlessly tileable",
"fauna": "2D game creature",
"zgradbe": "2D game building/structure",
"hrana": "2D game food item",
"materiali": "2D game crafting material",
"oblacila": "2D game clothing/armor piece",
"orodja": "2D game tool/weapon"
}
base_prompt = category_prompts.get(asset_type, "2D game asset")
# Select style based on asset type
if asset_type == "vegetacija" or is_vegetation:
style_text = STYLE_30_VEGETATION
else:
style_text = STYLE_32_ENTITIES
# Format asset name to readable
readable_name = asset_name.replace("_", " ").title()
prompt = f"{base_prompt}, {style_text}. Asset: {readable_name}. Background: SOLID CHROMA GREEN (#00FF00), centered, animation-ready, game-ready."
return prompt
def save_to_file(image_data, filepath):
"""Save generated image to file"""
filepath.parent.mkdir(parents=True, exist_ok=True)
with open(filepath, 'wb') as f:
f.write(image_data)
print(f"✅ Saved: {filepath.name}")
# ========================================
# MAIN GENERATION LOGIC
# ========================================
def generate_missing_assets(biome_name, category, assets_list):
"""Generate all missing assets for a biome category"""
existing = check_existing_assets(biome_name, category)
missing = [a for a in assets_list if a not in existing]
if not missing:
print(f"{biome_name}/{category} - All assets exist!")
return
print(f"\n🎨 Generating {biome_name}/{category}: {len(missing)} assets missing")
for asset_name in missing:
filename = f"{asset_name.lower()}.png"
filepath = BIOME_ROOT / biome_name / category / filename
if filepath.exists():
print(f"⏭️ Skipping (exists): {filename}")
continue
print(f"🖼️ Generating: {filename}")
# Check if this is vegetation for style selection
is_veg = (category == "vegetacija")
prompt = generate_asset_prompt(asset_name, category, is_vegetation=is_veg)
# TODO: Replace with actual API call
# For now, just create placeholder
print(f" Prompt: {prompt[:100]}...")
# Simulate generation delay
time.sleep(1)
# NOTE: Replace this with actual image generation API call
# image_data = call_image_api(prompt)
# save_to_file(image_data, filepath)
print(f"{biome_name}/{category} complete!")
# ========================================
# SCRIPT EXECUTION
# ========================================
if __name__ == "__main__":
print("="*60)
print("🦖 BIOME ASSET GENERATOR - COMPLETE EDITION")
print("="*60)
total_generated = 0
for biome_name, categories in BIOMES.items():
print(f"\n{'='*60}")
print(f"📁 BIOME: {biome_name.upper()}")
print(f"{'='*60}")
for category, assets in categories.items():
generate_missing_assets(biome_name, category, assets)
total_generated += len(assets) * 2 # × 2 for dual styles
print(f"\n{'='*60}")
print(f"✅ GENERATION COMPLETE!")
print(f"📊 Total assets processed: {total_generated}")
print(f"{'='*60}")