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