180 lines
5.6 KiB
Python
180 lines
5.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Clean and organize asset structure:
|
|
1. Remove duplicate 'originals/' folders
|
|
2. Organize each asset into its own subfolder:
|
|
category/
|
|
assetname/
|
|
assetname_styleA_1024x1024.png (original)
|
|
assetname_styleA_preview_256x256.png (visible)
|
|
assetname_styleA_sprite_32x32.png (game)
|
|
assetname_styleB_1024x1024.png (original)
|
|
assetname_styleB_preview_256x256.png (visible)
|
|
assetname_styleB_sprite_32x32.png (game)
|
|
"""
|
|
|
|
import os
|
|
import shutil
|
|
from pathlib import Path
|
|
from collections import defaultdict
|
|
|
|
def get_base_asset_name(filename: str) -> str:
|
|
"""
|
|
Extract base asset name from filename.
|
|
Examples:
|
|
- campfire_styleA.png -> campfire
|
|
- campfire_styleA_preview_256x256.png -> campfire
|
|
- campfire_styleB_32x32.png -> campfire
|
|
"""
|
|
stem = filename.replace('.png', '')
|
|
|
|
# Remove style suffix
|
|
if '_styleA' in stem:
|
|
stem = stem.split('_styleA')[0]
|
|
elif '_styleB' in stem:
|
|
stem = stem.split('_styleB')[0]
|
|
|
|
return stem
|
|
|
|
def get_file_type(filename: str) -> str:
|
|
"""
|
|
Determine file type: original, preview, or sprite
|
|
"""
|
|
if 'preview' in filename:
|
|
return 'preview'
|
|
elif any(size in filename for size in ['32x32', '16x16', '32x64', '24x24']):
|
|
return 'sprite'
|
|
else:
|
|
return 'original'
|
|
|
|
def get_style(filename: str) -> str:
|
|
"""Get style (A or B) from filename"""
|
|
if 'styleA' in filename:
|
|
return 'styleA'
|
|
elif 'styleB' in filename:
|
|
return 'styleB'
|
|
return None
|
|
|
|
def organize_category(category_path: Path, dry_run: bool = False):
|
|
"""
|
|
Organize all assets in a category into subfolders
|
|
"""
|
|
|
|
if not category_path.exists():
|
|
return
|
|
|
|
print(f"\n{'='*70}")
|
|
print(f"📂 ORGANIZING: {category_path.name}/")
|
|
print(f"{'='*70}")
|
|
|
|
# Delete originals/ folder if it exists (it's duplicates!)
|
|
originals_path = category_path / 'originals'
|
|
if originals_path.exists():
|
|
if not dry_run:
|
|
shutil.rmtree(originals_path)
|
|
print(f" 🗑️ Deleted duplicate folder: originals/")
|
|
|
|
# Group all PNG files by base asset name
|
|
asset_groups = defaultdict(list)
|
|
|
|
for png_file in category_path.glob('*.png'):
|
|
if png_file.is_file():
|
|
base_name = get_base_asset_name(png_file.name)
|
|
asset_groups[base_name].append(png_file)
|
|
|
|
if not asset_groups:
|
|
print(" No assets to organize")
|
|
return
|
|
|
|
# Organize each asset group into subfolder
|
|
for asset_name, files in sorted(asset_groups.items()):
|
|
asset_folder = category_path / asset_name
|
|
|
|
if not dry_run:
|
|
asset_folder.mkdir(exist_ok=True)
|
|
|
|
print(f"\n 📁 {asset_name}/")
|
|
|
|
for file_path in files:
|
|
# Rename to proper format if needed
|
|
file_type = get_file_type(file_path.name)
|
|
style = get_style(file_path.name)
|
|
|
|
if style:
|
|
# Determine size from filename or type
|
|
if 'preview' in file_path.name:
|
|
size_str = '256x256'
|
|
elif '32x32' in file_path.name:
|
|
size_str = '32x32'
|
|
elif '16x16' in file_path.name:
|
|
size_str = '16x16'
|
|
elif '32x64' in file_path.name:
|
|
size_str = '32x64'
|
|
elif '24x24' in file_path.name:
|
|
size_str = '24x24'
|
|
else:
|
|
# Original - assume 1024x1024
|
|
size_str = '1024x1024'
|
|
|
|
# Create proper filename
|
|
if file_type == 'preview':
|
|
new_name = f"{asset_name}_{style}_preview_{size_str}.png"
|
|
elif file_type == 'sprite':
|
|
new_name = f"{asset_name}_{style}_sprite_{size_str}.png"
|
|
else:
|
|
new_name = f"{asset_name}_{style}_{size_str}.png"
|
|
|
|
new_path = asset_folder / new_name
|
|
|
|
# Move and rename
|
|
if not dry_run:
|
|
file_path.rename(new_path)
|
|
|
|
print(f" ✅ {file_type:8} | {style:6} | {new_name}")
|
|
|
|
def main():
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description='Clean and organize asset structure')
|
|
parser.add_argument('--dry-run', action='store_true', help='Show what would be done without doing it')
|
|
args = parser.parse_args()
|
|
|
|
print("=" * 70)
|
|
print("🧹 CLEAN & ORGANIZE ASSETS")
|
|
print("=" * 70)
|
|
|
|
if args.dry_run:
|
|
print("\n⚠️ DRY RUN MODE - No changes will be made\n")
|
|
|
|
print("\nThis will:")
|
|
print(" 1. Delete 'originals/' folders (duplicates)")
|
|
print(" 2. Organize each asset into subfolders")
|
|
print(" 3. Rename files to proper format:")
|
|
print(" - assetname_styleA_1024x1024.png")
|
|
print(" - assetname_styleA_preview_256x256.png")
|
|
print(" - assetname_styleA_sprite_32x32.png")
|
|
print("=" * 70)
|
|
|
|
# Process demo directory
|
|
demo_dir = Path('assets/images/demo')
|
|
|
|
categories = [
|
|
'terrain', 'crops', 'buildings', 'items',
|
|
'environment', 'characters', 'enemies',
|
|
'ui', 'effects', 'npcs'
|
|
]
|
|
|
|
for category in categories:
|
|
category_path = demo_dir / category
|
|
organize_category(category_path, dry_run=args.dry_run)
|
|
|
|
print("\n" + "=" * 70)
|
|
if not args.dry_run:
|
|
print("✅ COMPLETE! All assets organized")
|
|
else:
|
|
print("✅ DRY RUN COMPLETE! Run without --dry-run to apply changes")
|
|
print("=" * 70)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|