summaryrefslogtreecommitdiff
path: root/embed_assets.py
diff options
context:
space:
mode:
authorIndrajith K L2025-11-03 17:48:56 +0530
committerIndrajith K L2025-11-03 17:48:56 +0530
commit737214b71be8fe5fdf51155ad50bb064b3156bd3 (patch)
tree21a2713d03830b21ee2b3ffd919708b054728e40 /embed_assets.py
parent3afcbd32001fc2ab2dcee1553268dbb39dabf070 (diff)
downloadreilua-enhanced-737214b71be8fe5fdf51155ad50bb064b3156bd3.tar.gz
reilua-enhanced-737214b71be8fe5fdf51155ad50bb064b3156bd3.tar.bz2
reilua-enhanced-737214b71be8fe5fdf51155ad50bb064b3156bd3.zip
Add embedded assets, splash screens, and asset loading support
Features added: - Embedded main.lua and Lua files support (EMBED_MAIN option) - Embedded assets support (EMBED_ASSETS option) - Splash screens with dual logo display (always embedded) - Asset loading progress tracking API (BeginAssetLoading, UpdateAssetLoading, EndAssetLoading) - Custom font embedding for splash/loading screens - --log flag for Windows console control - --no-logo flag to skip splash screens in development - Python scripts for embedding (embed_lua.py, embed_assets.py, embed_logo.py, embed_font.py) - Documentation (EMBEDDING.md, ASSET_LOADING.md, SPLASH_SCREENS.md) This allows building single-executable releases with all Lua code and assets embedded.
Diffstat (limited to 'embed_assets.py')
-rw-r--r--embed_assets.py116
1 files changed, 116 insertions, 0 deletions
diff --git a/embed_assets.py b/embed_assets.py
new file mode 100644
index 0000000..52309ef
--- /dev/null
+++ b/embed_assets.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+"""
+Embed asset files (images, sounds, fonts, etc.) into a C header file.
+Usage: python embed_assets.py <output.h> <file1.png> [file2.wav] [file3.ttf] ...
+
+Embeds all specified asset files into a C header for inclusion in the executable.
+"""
+import sys
+import os
+
+def sanitize_name(filename):
+ """Convert filename to valid C identifier"""
+ name = os.path.basename(filename)
+ # Remove or replace all non-alphanumeric characters (except underscore)
+ valid_chars = []
+ for char in name:
+ if char.isalnum() or char == '_':
+ valid_chars.append(char)
+ else:
+ valid_chars.append('_')
+ name = ''.join(valid_chars)
+ # Ensure it doesn't start with a digit
+ if name and name[0].isdigit():
+ name = '_' + name
+ return name
+
+def get_file_extension(filename):
+ """Get the file extension"""
+ return os.path.splitext(filename)[1].lower()
+
+def embed_files(output_file, input_files):
+ with open(output_file, 'w') as f:
+ f.write('#ifndef EMBEDDED_ASSETS_H\n')
+ f.write('#define EMBEDDED_ASSETS_H\n\n')
+ f.write('/* Auto-generated file - do not edit manually */\n\n')
+
+ # Embed each file as a separate array
+ for idx, input_file in enumerate(input_files):
+ with open(input_file, 'rb') as inf:
+ data = inf.read()
+
+ var_name = sanitize_name(input_file)
+ # Extract relative path from 'assets/' onwards if present
+ if 'assets' in input_file.replace('\\', '/'):
+ parts = input_file.replace('\\', '/').split('assets/')
+ if len(parts) > 1:
+ relative_name = 'assets/' + parts[-1]
+ else:
+ relative_name = os.path.basename(input_file)
+ else:
+ relative_name = os.path.basename(input_file)
+
+ f.write(f'/* Embedded asset: {input_file} ({len(data)} bytes) */\n')
+ f.write(f'static const unsigned char embedded_asset_{idx}_{var_name}[] = {{\n')
+
+ for i, byte in enumerate(data):
+ if i % 12 == 0:
+ f.write(' ')
+ f.write(f'0x{byte:02x}')
+ if i < len(data) - 1:
+ f.write(',')
+ if (i + 1) % 12 == 0:
+ f.write('\n')
+ else:
+ f.write(' ')
+
+ f.write('\n};\n')
+ f.write(f'static const unsigned int embedded_asset_{idx}_{var_name}_len = {len(data)};\n\n')
+
+ # Create the asset table
+ f.write('/* Asset table for virtual filesystem */\n')
+ f.write('typedef struct {\n')
+ f.write(' const char* name;\n')
+ f.write(' const unsigned char* data;\n')
+ f.write(' unsigned int size;\n')
+ f.write('} EmbeddedAsset;\n\n')
+
+ f.write('static const EmbeddedAsset embedded_assets[] = {\n')
+ for idx, input_file in enumerate(input_files):
+ var_name = sanitize_name(input_file)
+ # Extract relative path from 'assets/' onwards if present
+ if 'assets' in input_file.replace('\\', '/'):
+ parts = input_file.replace('\\', '/').split('assets/')
+ if len(parts) > 1:
+ relative_name = 'assets/' + parts[-1]
+ else:
+ relative_name = os.path.basename(input_file)
+ else:
+ relative_name = os.path.basename(input_file)
+ f.write(f' {{ "{relative_name}", embedded_asset_{idx}_{var_name}, embedded_asset_{idx}_{var_name}_len }},\n')
+ f.write('};\n\n')
+
+ f.write(f'static const int embedded_asset_count = {len(input_files)};\n\n')
+ f.write('#endif /* EMBEDDED_ASSETS_H */\n')
+
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ print('Usage: python embed_assets.py <output.h> <asset1> [asset2] ...')
+ print(' Embeds images, sounds, fonts, and other asset files into a C header.')
+ print(' Supported: .png, .jpg, .wav, .ogg, .mp3, .ttf, .otf, etc.')
+ sys.exit(1)
+
+ output_file = sys.argv[1]
+ input_files = sys.argv[2:]
+
+ # Check all input files exist
+ for f in input_files:
+ if not os.path.exists(f):
+ print(f'Error: File not found: {f}')
+ sys.exit(1)
+
+ embed_files(output_file, input_files)
+ print(f'Embedded {len(input_files)} asset file(s) into {output_file}')
+ for f in input_files:
+ size = os.path.getsize(f)
+ print(f' - {f} ({size} bytes)')