PROBLEM: Images not displaying in gallery (404 errors) ROOT CAUSE: Paths were 'assets/...' but HTML is served from 'tools/' subfolder SOLUTION: Changed paths to '../assets/...' (relative from tools/ directory) CHANGES: - scripts/generate_asset_manifest.py: Prepend '../' to all asset paths - tools/asset_manifest.json: Regenerated with correct relative paths RESULT: All 1,166 images now load correctly in Visual Asset Manager TEST: Hard refresh browser (Cmd+Shift+R or Ctrl+Shift+R)
137 lines
4.4 KiB
Python
Executable File
137 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Asset Manifest Generator
|
|
Creates JSON manifest of all assets for Visual Asset Manager
|
|
"""
|
|
|
|
import os
|
|
import json
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
PROJECT_ROOT = Path(__file__).parent.parent
|
|
ASSETS_DIR = PROJECT_ROOT / "assets"
|
|
OUTPUT_FILE = PROJECT_ROOT / "tools" / "asset_manifest.json"
|
|
|
|
def get_file_size_readable(size_bytes):
|
|
"""Convert bytes to human readable format"""
|
|
for unit in ['B', 'KB', 'MB', 'GB']:
|
|
if size_bytes < 1024.0:
|
|
return f"{size_bytes:.1f} {unit}"
|
|
size_bytes /= 1024.0
|
|
return f"{size_bytes:.1f} TB"
|
|
|
|
def detect_category(filepath):
|
|
"""Detect category from filepath"""
|
|
path_str = str(filepath).lower()
|
|
|
|
# Check by folder
|
|
if '/liki/' in path_str or '/npcs/' in path_str:
|
|
return 'liki'
|
|
if '/zgradbe/' in path_str or 'building' in path_str:
|
|
return 'zgradbe'
|
|
if '/oprema/' in path_str or 'weapon' in path_str or 'tool' in path_str:
|
|
return 'oprema'
|
|
if '/narava/' in path_str or 'plant' in path_str or 'tree' in path_str:
|
|
return 'narava'
|
|
if '/notranjost/' in path_str or 'interior' in path_str:
|
|
return 'notranjost'
|
|
if '/teren/' in path_str or 'terrain' in path_str:
|
|
return 'teren'
|
|
if '/vmesnik/' in path_str or 'button' in path_str or 'icon' in path_str:
|
|
return 'vmesnik'
|
|
if '/biomi/' in path_str:
|
|
return 'biomi'
|
|
if 'animations' in path_str:
|
|
return 'animations'
|
|
|
|
return 'ostalo'
|
|
|
|
def scan_assets():
|
|
"""Scan all assets and create manifest"""
|
|
assets = []
|
|
asset_id = 0
|
|
|
|
print("🔍 Scanning assets...")
|
|
|
|
# Scan for all image files
|
|
extensions = ['.png', '.jpg', '.jpeg', '.webp', '.gif']
|
|
|
|
for ext in extensions:
|
|
for filepath in ASSETS_DIR.rglob(f'*{ext}'):
|
|
try:
|
|
# Get file info
|
|
file_size = filepath.stat().st_size
|
|
rel_path = filepath.relative_to(PROJECT_ROOT)
|
|
|
|
# Make path relative from tools/ directory (../)
|
|
# Since HTML is at tools/visual_asset_manager.html
|
|
tools_relative_path = '../' + str(rel_path)
|
|
|
|
# Create asset entry
|
|
asset = {
|
|
'id': f'asset_{asset_id}',
|
|
'name': filepath.name,
|
|
'path': tools_relative_path,
|
|
'folder': str(filepath.parent.relative_to(ASSETS_DIR)),
|
|
'category': detect_category(filepath),
|
|
'size': get_file_size_readable(file_size),
|
|
'size_bytes': file_size,
|
|
'extension': filepath.suffix
|
|
}
|
|
|
|
assets.append(asset)
|
|
asset_id += 1
|
|
|
|
if asset_id % 100 == 0:
|
|
print(f" Processed {asset_id} assets...")
|
|
|
|
except Exception as e:
|
|
print(f" ⚠️ Error processing {filepath}: {e}")
|
|
|
|
print(f"\n✅ Found {len(assets)} assets")
|
|
return assets
|
|
|
|
def generate_manifest():
|
|
"""Generate complete manifest"""
|
|
print("🎨 Asset Manifest Generator")
|
|
print("="*60)
|
|
|
|
assets = scan_assets()
|
|
|
|
# Calculate stats
|
|
total_size = sum(a['size_bytes'] for a in assets)
|
|
categories = {}
|
|
for asset in assets:
|
|
cat = asset['category']
|
|
categories[cat] = categories.get(cat, 0) + 1
|
|
|
|
manifest = {
|
|
'generated_at': datetime.now().isoformat(),
|
|
'total_assets': len(assets),
|
|
'total_size': get_file_size_readable(total_size),
|
|
'total_size_bytes': total_size,
|
|
'categories': categories,
|
|
'assets': assets
|
|
}
|
|
|
|
# Save manifest
|
|
print(f"\n💾 Saving manifest to {OUTPUT_FILE}")
|
|
with open(OUTPUT_FILE, 'w', encoding='utf-8') as f:
|
|
json.dump(manifest, f, indent=2, ensure_ascii=False)
|
|
|
|
# Print summary
|
|
print("\n" + "="*60)
|
|
print("📊 MANIFEST SUMMARY")
|
|
print("="*60)
|
|
print(f"Total Assets: {len(assets)}")
|
|
print(f"Total Size: {get_file_size_readable(total_size)}")
|
|
print(f"\nCategories:")
|
|
for cat, count in sorted(categories.items(), key=lambda x: x[1], reverse=True):
|
|
print(f" {cat}: {count}")
|
|
print(f"\n✅ Manifest saved: {OUTPUT_FILE}")
|
|
print(f" Ready for Visual Asset Manager!")
|
|
|
|
if __name__ == "__main__":
|
|
generate_manifest()
|