|
|
#!/usr/bin/env python3 |
|
|
""" |
|
|
Quick demonstration of using extracted StarCraft assets |
|
|
|
|
|
This script shows basic examples of loading and using different |
|
|
asset types from the extracted StarCraft MPQ. |
|
|
""" |
|
|
|
|
|
import sys |
|
|
from pathlib import Path |
|
|
|
|
|
|
|
|
def demo_list_assets(): |
|
|
"""List all extracted assets by category""" |
|
|
assets_dir = Path("assets") |
|
|
|
|
|
if not assets_dir.exists(): |
|
|
print("❌ Assets directory not found!") |
|
|
print("Please run: python extract_starcraft_assets.py") |
|
|
return False |
|
|
|
|
|
print("=" * 80) |
|
|
print("StarCraft Extracted Assets Overview") |
|
|
print("=" * 80) |
|
|
print() |
|
|
|
|
|
total_files = 0 |
|
|
total_size = 0 |
|
|
|
|
|
for category_dir in sorted(assets_dir.iterdir()): |
|
|
if not category_dir.is_dir(): |
|
|
continue |
|
|
|
|
|
files = list(category_dir.rglob("*")) |
|
|
files = [f for f in files if f.is_file()] |
|
|
|
|
|
if not files: |
|
|
continue |
|
|
|
|
|
category_size = sum(f.stat().st_size for f in files) |
|
|
total_files += len(files) |
|
|
total_size += category_size |
|
|
|
|
|
print(f"📁 {category_dir.name}/") |
|
|
print(f" Files: {len(files)}") |
|
|
print(f" Size: {format_size(category_size)}") |
|
|
|
|
|
# Show some example files |
|
|
examples = sorted(files)[:3] |
|
|
if examples: |
|
|
print(f" Examples:") |
|
|
for f in examples: |
|
|
print(f" - {f.name}") |
|
|
print() |
|
|
|
|
|
print("-" * 80) |
|
|
print(f"Total: {total_files} files, {format_size(total_size)}") |
|
|
print() |
|
|
|
|
|
return True |
|
|
|
|
|
|
|
|
def demo_audio_info(): |
|
|
"""Show information about audio files""" |
|
|
audio_dir = Path("assets/audio") |
|
|
|
|
|
if not audio_dir.exists(): |
|
|
print("❌ Audio directory not found!") |
|
|
return False |
|
|
|
|
|
print("=" * 80) |
|
|
print("Audio Assets Analysis") |
|
|
print("=" * 80) |
|
|
print() |
|
|
|
|
|
wav_files = list(audio_dir.glob("*.wav")) |
|
|
|
|
|
if not wav_files: |
|
|
print("No WAV files found!") |
|
|
return False |
|
|
|
|
|
print(f"Found {len(wav_files)} WAV files") |
|
|
print() |
|
|
|
|
|
# Try to read WAV headers (if wave module available) |
|
|
try: |
|
|
import wave |
|
|
|
|
|
print("Sample WAV file information:") |
|
|
print("-" * 80) |
|
|
|
|
|
for wav_file in sorted(wav_files)[:5]: |
|
|
try: |
|
|
with wave.open(str(wav_file), 'rb') as wf: |
|
|
channels = wf.getnchannels() |
|
|
sample_width = wf.getsampwidth() |
|
|
framerate = wf.getframerate() |
|
|
n_frames = wf.getnframes() |
|
|
duration = n_frames / framerate |
|
|
|
|
|
print(f"📢 {wav_file.name}") |
|
|
print(f" Channels: {channels} ({'Mono' if channels == 1 else 'Stereo'})") |
|
|
print(f" Sample Rate: {framerate} Hz") |
|
|
print(f" Bit Depth: {sample_width * 8} bit") |
|
|
print(f" Duration: {duration:.2f} seconds") |
|
|
print(f" Size: {format_size(wav_file.stat().st_size)}") |
|
|
print() |
|
|
except Exception as e: |
|
|
print(f" ⚠️ Could not read: {e}") |
|
|
|
|
|
except ImportError: |
|
|
print("⚠️ wave module not available for detailed analysis") |
|
|
print("Showing file sizes instead:") |
|
|
print("-" * 80) |
|
|
|
|
|
for wav_file in sorted(wav_files)[:10]: |
|
|
size = wav_file.stat().st_size |
|
|
print(f" {wav_file.name:.<50} {format_size(size):>10}") |
|
|
|
|
|
print() |
|
|
return True |
|
|
|
|
|
|
|
|
def demo_graphics_info(): |
|
|
"""Show information about graphics files""" |
|
|
graphics_dir = Path("assets/graphics") |
|
|
|
|
|
if not graphics_dir.exists(): |
|
|
print("❌ Graphics directory not found!") |
|
|
return False |
|
|
|
|
|
print("=" * 80) |
|
|
print("Graphics Assets Analysis") |
|
|
print("=" * 80) |
|
|
print() |
|
|
|
|
|
# Count by extension |
|
|
from collections import defaultdict |
|
|
by_ext = defaultdict(list) |
|
|
|
|
|
for gfx_file in graphics_dir.rglob("*"): |
|
|
if gfx_file.is_file(): |
|
|
ext = gfx_file.suffix.lower() |
|
|
by_ext[ext].append(gfx_file) |
|
|
|
|
|
print("File types:") |
|
|
print("-" * 80) |
|
|
for ext in sorted(by_ext.keys()): |
|
|
files = by_ext[ext] |
|
|
total_size = sum(f.stat().st_size for f in files) |
|
|
print(f" {ext or '(no ext)':.<15} {len(files):>4} files {format_size(total_size):>10}") |
|
|
print() |
|
|
|
|
|
# Try to analyze PCX files if PIL available |
|
|
try: |
|
|
from PIL import Image |
|
|
|
|
|
pcx_files = list(graphics_dir.glob("*.pcx")) |
|
|
if pcx_files: |
|
|
print("Sample PCX images:") |
|
|
print("-" * 80) |
|
|
|
|
|
for pcx_file in sorted(pcx_files)[:5]: |
|
|
try: |
|
|
with Image.open(pcx_file) as img: |
|
|
print(f"🖼️ {pcx_file.name}") |
|
|
print(f" Size: {img.width}x{img.height}") |
|
|
print(f" Mode: {img.mode}") |
|
|
print(f" Format: {img.format}") |
|
|
print() |
|
|
except Exception as e: |
|
|
print(f" ⚠️ Could not read: {e}") |
|
|
|
|
|
except ImportError: |
|
|
print("⚠️ PIL/Pillow not available for image analysis") |
|
|
print("Install with: pip install Pillow") |
|
|
|
|
|
print() |
|
|
return True |
|
|
|
|
|
|
|
|
def demo_search_files(query: str): |
|
|
"""Search for files matching a pattern""" |
|
|
assets_dir = Path("assets") |
|
|
|
|
|
if not assets_dir.exists(): |
|
|
print("❌ Assets directory not found!") |
|
|
return False |
|
|
|
|
|
query_lower = query.lower() |
|
|
matches = [] |
|
|
|
|
|
for file_path in assets_dir.rglob("*"): |
|
|
if file_path.is_file() and query_lower in file_path.name.lower(): |
|
|
matches.append(file_path) |
|
|
|
|
|
print(f"\nSearch results for '{query}':") |
|
|
print("=" * 80) |
|
|
|
|
|
if not matches: |
|
|
print("No files found!") |
|
|
return False |
|
|
|
|
|
print(f"Found {len(matches)} matching files:\n") |
|
|
|
|
|
for match in sorted(matches)[:20]: |
|
|
rel_path = match.relative_to(assets_dir) |
|
|
size = match.stat().st_size |
|
|
print(f" {str(rel_path):.<60} {format_size(size):>10}") |
|
|
|
|
|
if len(matches) > 20: |
|
|
print(f"\n ... and {len(matches) - 20} more files") |
|
|
|
|
|
print() |
|
|
return True |
|
|
|
|
|
|
|
|
def format_size(size_bytes: int) -> str: |
|
|
"""Format size in bytes to human-readable format""" |
|
|
if size_bytes < 1024: |
|
|
return f"{size_bytes} B" |
|
|
elif size_bytes < 1024 * 1024: |
|
|
return f"{size_bytes / 1024:.1f} KB" |
|
|
else: |
|
|
return f"{size_bytes / 1024 / 1024:.1f} MB" |
|
|
|
|
|
|
|
|
def main(): |
|
|
"""Main entry point""" |
|
|
print("\n" + "=" * 80) |
|
|
print("StarCraft Asset Demo") |
|
|
print("=" * 80) |
|
|
print() |
|
|
|
|
|
# Check if assets exist |
|
|
if not Path("assets").exists(): |
|
|
print("❌ Assets not extracted yet!") |
|
|
print("\nPlease run the extraction script first:") |
|
|
print(" python extract_starcraft_assets.py") |
|
|
print() |
|
|
return 1 |
|
|
|
|
|
# Show main menu if no arguments |
|
|
if len(sys.argv) == 1: |
|
|
print("Available demos:") |
|
|
print(" 1. List all assets") |
|
|
print(" 2. Analyze audio files") |
|
|
print(" 3. Analyze graphics files") |
|
|
print(" 4. Search files") |
|
|
print() |
|
|
|
|
|
choice = input("Select demo (1-4) or 'q' to quit: ").strip() |
|
|
|
|
|
if choice == '1': |
|
|
demo_list_assets() |
|
|
elif choice == '2': |
|
|
demo_audio_info() |
|
|
elif choice == '3': |
|
|
demo_graphics_info() |
|
|
elif choice == '4': |
|
|
query = input("Enter search query: ").strip() |
|
|
demo_search_files(query) |
|
|
elif choice.lower() == 'q': |
|
|
return 0 |
|
|
else: |
|
|
print("Invalid choice!") |
|
|
return 1 |
|
|
|
|
|
# Command line usage |
|
|
elif sys.argv[1] == 'list': |
|
|
demo_list_assets() |
|
|
elif sys.argv[1] == 'audio': |
|
|
demo_audio_info() |
|
|
elif sys.argv[1] == 'graphics': |
|
|
demo_graphics_info() |
|
|
elif sys.argv[1] == 'search': |
|
|
if len(sys.argv) < 3: |
|
|
print("Usage: python demo_assets.py search <query>") |
|
|
return 1 |
|
|
demo_search_files(sys.argv[2]) |
|
|
else: |
|
|
print("Usage:") |
|
|
print(" python demo_assets.py [list|audio|graphics|search <query>]") |
|
|
print("\nOr run without arguments for interactive menu") |
|
|
return 1 |
|
|
|
|
|
return 0 |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
sys.exit(main())
|
|
|
|