McRogueFace/tests/demo/tutorial_screenshots.py

169 lines
4.9 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""
Tutorial Screenshot Generator
Usage:
./mcrogueface --headless --exec tests/demo/tutorial_screenshots.py
Extracts code from tutorial markdown files and generates screenshots.
"""
import mcrfpy
from mcrfpy import automation
import sys
import os
import re
# Paths
DOCS_REPO = "/opt/goblincorps/repos/mcrogueface.github.io"
TUTORIAL_DIR = os.path.join(DOCS_REPO, "tutorial")
OUTPUT_DIR = os.path.join(DOCS_REPO, "images", "tutorials")
# Tutorials to process (in order)
TUTORIALS = [
"part_01_grid_movement.md",
"part_02_tiles_collision.md",
"part_03_dungeon_generation.md",
"part_04_fov.md",
"part_05_enemies.md",
"part_06_combat.md",
"part_07_ui.md",
]
def extract_code_from_markdown(filepath):
"""Extract the main Python code block from a tutorial markdown file."""
with open(filepath, 'r') as f:
content = f.read()
# Find code blocks after "## The Complete Code" header
# Look for the first python code block after that header
complete_code_match = re.search(
r'##\s+The Complete Code.*?```python\s*\n(.*?)```',
content,
re.DOTALL | re.IGNORECASE
)
if complete_code_match:
return complete_code_match.group(1)
# Fallback: just get the first large python code block
code_blocks = re.findall(r'```python\s*\n(.*?)```', content, re.DOTALL)
if code_blocks:
# Return the largest code block (likely the main example)
return max(code_blocks, key=len)
return None
def add_screenshot_hook(code, screenshot_path):
"""Add screenshot capture code to the end of the script."""
# Add code to take screenshot after a brief delay
hook_code = f'''
# === Screenshot capture hook (added by tutorial_screenshots.py) ===
import mcrfpy
from mcrfpy import automation
import sys
_screenshot_taken = [False]
def _take_screenshot(timer, runtime):
if not _screenshot_taken[0]:
_screenshot_taken[0] = True
automation.screenshot("{screenshot_path}")
print(f"Screenshot saved: {screenshot_path}")
sys.exit(0)
# Wait a moment for scene to render, then capture
mcrfpy.Timer("_screenshot_hook", _take_screenshot, 200)
'''
return code + hook_code
class TutorialScreenshotter:
"""Manages tutorial screenshot generation."""
def __init__(self):
self.tutorials = []
self.current_index = 0
def load_tutorials(self):
"""Load and parse all tutorial files."""
for filename in TUTORIALS:
filepath = os.path.join(TUTORIAL_DIR, filename)
if not os.path.exists(filepath):
print(f"Warning: {filepath} not found, skipping")
continue
code = extract_code_from_markdown(filepath)
if code:
# Generate output filename
base = os.path.splitext(filename)[0]
screenshot_name = f"{base}.png"
self.tutorials.append({
'name': filename,
'code': code,
'screenshot': screenshot_name,
'filepath': filepath,
})
print(f"Loaded: {filename}")
else:
print(f"Warning: No code found in {filename}")
def run(self):
"""Generate all screenshots."""
# Ensure output directory exists
os.makedirs(OUTPUT_DIR, exist_ok=True)
print(f"\nGenerating {len(self.tutorials)} tutorial screenshots...")
print(f"Output directory: {OUTPUT_DIR}\n")
self.process_next()
def process_next(self):
"""Process the next tutorial."""
if self.current_index >= len(self.tutorials):
print("\nAll screenshots generated!")
sys.exit(0)
return
tutorial = self.tutorials[self.current_index]
print(f"[{self.current_index + 1}/{len(self.tutorials)}] Processing {tutorial['name']}...")
# Add screenshot hook to the code
screenshot_path = os.path.join(OUTPUT_DIR, tutorial['screenshot'])
modified_code = add_screenshot_hook(tutorial['code'], screenshot_path)
# Write to temp file and execute
temp_path = f"/tmp/tutorial_screenshot_{self.current_index}.py"
with open(temp_path, 'w') as f:
f.write(modified_code)
try:
# Execute the code
exec(compile(modified_code, temp_path, 'exec'), {'__name__': '__main__'})
except Exception as e:
print(f"Error processing {tutorial['name']}: {e}")
self.current_index += 1
self.process_next()
finally:
try:
os.unlink(temp_path)
except:
pass
def main():
"""Main entry point."""
screenshotter = TutorialScreenshotter()
screenshotter.load_tutorials()
if not screenshotter.tutorials:
print("No tutorials found to process!")
sys.exit(1)
screenshotter.run()
# Run when executed
main()