Files
filament/docs_src/build/snapshot_samples.py
Powei Feng a73957a590 web: refactor examples and tutorials (#9833)
* Refactor web examples and tutorials

- Consolidate web/docs and web/samples into web/examples
- Remove literal programming blocks from Markdown tutorials
- Replace tutorial_template.html with a fully embedded template in serve.py
- Move serve.py to web/examples/serve.py and update dependency rules
- Update filament-js wrapper to expose _malloc, _free and set GEN_MIPMAPPABLE usage
- Update sample materials and WebGL asset generation within web/examples/CMakeLists.txt
- Add python venv instructions and usage details to web/README.md
- Remove obsolete examples, Pipfile, and demo templates

* Transfer web tutorials and samples to docs_src

- Introduce copy_web_docs.py api to deploy and rewrite web sample outputs into the docs output tree
- Hook copy_web_docs into docs_src/build/run.py natively
- Configure duplicates.json to map WebGL outputs to embedded .md docs
- Strip html skeleton out of examples in run.py so they map into markdown cleanly
- Update update-docs workflow to pre-build the WebGL target
- Remove obsolete remote docs path from src_raw
- Add explanatory comments to copy_web_docs.py and run.py
- Add index page with thumbnails for Web Tutorials and samples
2026-03-25 23:52:48 +00:00

111 lines
3.8 KiB
Python

#!/usr/bin/env python3
#
# Copyright (C) 2026 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Automated WebGL Snapshot Generator
This script starts a local HTTP server pointing to the built mdbook output directory
and uses a headless Chrome browser (via Selenium) to load the generated WebGL examples.
For each sample and tutorial:
1. It waits for the scene and its assets (textures, models, materials) to fully render.
2. It explicitly targets the `<canvas>` DOM element to take an isolated screenshot.
3. It crops the raw screenshot into a perfect square based on its aspect ratio.
4. It uses Lanczos resampling to scale the image down to a 100x100 pixel thumbnail.
5. It saves the final thumbnail to `docs_src/src_mdbook/src/images/` for embedding in the Markdown.
These thumbnails are used directly by the "Web Tutorials" and "Web Samples" index pages.
"""
import os
import time
from PIL import Image
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import http.server
import socketserver
import threading
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
BOOK_DIR = os.path.join(CUR_DIR, '../src_mdbook/book')
IMAGES_DIR = os.path.join(CUR_DIR, '../src_mdbook/src/images')
os.makedirs(IMAGES_DIR, exist_ok=True)
class Server(socketserver.ThreadingMixIn, http.server.HTTPServer):
pass
class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=BOOK_DIR, **kwargs)
def start_server(port):
httpd = Server(("", port), Handler)
server_thread = threading.Thread(target=httpd.serve_forever)
server_thread.daemon = True
server_thread.start()
print(f"Server started on port {port}...")
return httpd
def snapshot_samples():
port = 8081
httpd = start_server(port)
time.sleep(2)
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=800,600")
driver = webdriver.Chrome(options=chrome_options)
samples = ['animation', 'cube_fl0', 'helmet', 'morphing', 'parquet', 'skinning', 'triangle', 'redball', 'suzanne']
for sample in samples:
print(f"Taking snapshot of {sample}...")
driver.get(f"http://localhost:{port}/samples/web/{sample}.html")
time.sleep(4) # Wait for models to load and render
canvas = driver.find_element(By.TAG_NAME, "canvas")
if not canvas:
print(f"Failed to find canvas for {sample}")
continue
# Get raw screenshot of the canvas element
png = canvas.screenshot_as_png
import io
img = Image.open(io.BytesIO(png))
# Crop to square
width, height = img.size
size = min(width, height)
left = (width - size) / 2
top = (height - size) / 2
right = (width + size) / 2
bottom = (height + size) / 2
img = img.crop((left, top, right, bottom))
# Resize to 100x100
img = img.resize((100, 100), Image.Resampling.LANCZOS)
img.save(os.path.join(IMAGES_DIR, f"web_sample_{sample}.png"))
print(f"Saved snapshot for {sample}")
driver.quit()
httpd.shutdown()
if __name__ == "__main__":
snapshot_samples()