docs(review): split into ReviewMap and DemoMap, with one status table

The review file now separates the two questions it was mixing:

  ReviewMap - assets staged on their own: individual objects, the Blender import, camera angles
  and the lighting comparison. Nothing from the game map is involved.
  DemoMap   - the actual game map in development: street, buildings, player, vehicle in place.

One status table at the top covers both parts, with a Part column, and remains the only place
approval and issue notes are recorded. Between them sits the Blender-vs-UE comparison, which now
pairs ReviewMap captures as well as DemoMap ones, followed by the ReviewMap image grid and the
existing in-game shot sections.

Tools/ue_build_review_map.py also stages the LATEST vehicle assets (five systems plus the hatch
paint) and two new cameras - a three-quarter view of the car and a ground-level look at the
character's feet - so the staging map never drifts from what the Blender tools last produced.
Tools/render_screenshots.sh gained a second capture pass that renders ReviewMap into
Screenshots/review/, after the demo collection because that pass clears the engine's screenshot
folder.
This commit is contained in:
zwitschi committed 2026-11-09 17:34:12 +01:00
1 parent a983dfdcdf
commit 72d5bab427
54 files changed
+254 -112

No files matched your search

+11 -4
View File
@@ -23,6 +23,7 @@ import shutil
import subprocess
DEMO_DIR = "Screenshots/demo"
REVIEW_DIR = "Screenshots/review"
BLENDER_DIR = "Screenshots/blender"
OUT = "Screenshots/README.md"
BEGIN = "<!-- blender-comparison:begin -->"
@@ -43,6 +44,12 @@ SHOT_ALIASES = {
}
def review_shots():
if not os.path.isdir(REVIEW_DIR):
return []
return sorted(f for f in os.listdir(REVIEW_DIR) if f.endswith(".png"))
def demo_shots():
if not os.path.isdir(DEMO_DIR):
return []
@@ -95,15 +102,15 @@ def image_cell(path, width=520):
def build():
shots = demo_shots()
shots = review_shots() + demo_shots()
renders = blender_renders()
lines = [
"## Blender vs in-game",
"### Blender vs in-game",
"",
"Regenerated by `Tools/build_comparison_md.py`; everything between the markers is",
"rewritten, so edit outside them.",
"",
f"- In-game captures: `{DEMO_DIR}/` ({len(shots)} files)",
f"- Captures: `{REVIEW_DIR}/` and `{DEMO_DIR}/` ({len(shots)} files)",
f"- Blender renders: `{BLENDER_DIR}/` ({len(renders)} files), made by `Tools/blender_screenshots.py`",
"",
"Left is what the engine draws, right is what Blender has. A gap between them is the",
@@ -121,7 +128,7 @@ def build():
match = best_blender_match(shot, renders)
paired[shot] = match
lines.append(
f"| {image_cell(f'{DEMO_DIR}/{shot}')} "
f"| {image_cell(f'{REVIEW_DIR if shot in review_shots() else DEMO_DIR}/{shot}')} "
f"| {image_cell(f'{BLENDER_DIR}/{match}' if match else None)} "
f"| `{shot}` |")
if not shots:
+27
View File
@@ -69,6 +69,33 @@ done
[ "$found" = "1" ] || { echo "ERROR: no demo screenshots found"; exit 1; }
ls -1 "$REPO/Screenshots/demo"
echo "== 6b/7 capture the review map (asset staging) =="
# The ReviewMap stages the models on their own - imported assets, camera angles and the
# lighting comparison - which is a different question from "does the game map look right".
# Its shots collect into Screenshots/review/ so the two reviews stay separate.
rm -rf "$REPO"/Game/GigLine/Saved/Screenshots/* 2>/dev/null || true
mkdir -p "$REPO/Game/GigLine/Saved/Screenshots/LinuxEditor"
"$ENGINE/Engine/Binaries/Linux/UnrealEditor-Cmd" "$PROJ" /Game/Test/ReviewMap \
-game -windowed -ResX=1920 -ResY=1080 -nopause -nosplash -stdout
echo "== 6c/7 collect the review-map screenshots =="
mkdir -p "$REPO/Screenshots/review"
rm -f "$REPO"/Screenshots/review/review-*.png
found_review=0
for src in \
"$REPO/Game/GigLine/Saved/Screenshots"/*/review-*.png \
"$REPO/Game/GigLine/Saved/Screenshots"/*/*/review-*.png \
"$HOME/.config/Epic/GigLine/Saved/Screenshots"/*/review-*.png; do
[ -e "$src" ] || continue
case "$(basename "$src")" in
*demo-*) : ;;
*) cp -f "$src" "$REPO/Screenshots/review/"; found_review=1 ;;
esac
done
[ "$found_review" = "1" ] || echo "WARN: no review-map screenshots found"
ls -1 "$REPO/Screenshots/review" 2>/dev/null | head -20
# The scene audit is a gate: a wrong-material or misplaced actor is exactly the
# kind of failure that still renders plausibly.
if grep -q "failure(s) ==" /tmp/gigline/scene-audit.txt 2>/dev/null; then
+30
View File
@@ -192,6 +192,32 @@ try:
else:
log("MISSING: /Script/GigLine.GigLineCharacter")
# --- vehicle, from the latest Blender import ------------------------------
# Staged from the same assets the demo map uses, so the review always shows what
# Tools/vehicle_from_template.py most recently produced rather than a copy that can
# drift. The panels are plain static meshes because the vehicle pawn keeps its
# physics only.
vehicle_origin = unreal.Vector(-1600.0, 600.0, 0.0)
vehicle_systems = ("SM_Vehicle_Body", "SM_Vehicle_Trim", "SM_Vehicle_Glass",
"SM_Vehicle_Lights", "SM_Vehicle_Wheels")
staged_vehicle = 0
for index, mesh_name in enumerate(vehicle_systems):
mesh = unreal.EditorAssetLibrary.load_asset(f"/Game/Hollywood/Vehicle/{mesh_name}")
if not mesh:
log(f"MISSING vehicle system: {mesh_name}")
continue
piece = spawn(unreal.StaticMeshActor, vehicle_origin, f"Review_Vehicle_{index:02d}")
if piece:
piece.static_mesh_component.set_static_mesh(mesh)
piece.static_mesh_component.set_mobility(unreal.ComponentMobility.STATIC)
if mesh_name == "SM_Vehicle_Body":
paint = unreal.EditorAssetLibrary.load_asset(
"/Game/Hollywood/Vehicle/M_Vehicle_HatchPaint")
if paint:
piece.static_mesh_component.set_material(0, paint)
staged_vehicle += 1
log(f"staged: {staged_vehicle} vehicle systems at the staging area")
# --- NPC prefab -----------------------------------------------------------
# The reusable NPC person: a collision capsule + visible MPFB body, standing
# feet on Z 0, placed clear of the pawn so the prefab reads on its own.
@@ -211,6 +237,10 @@ try:
cams = [
# wide scene: character, both cubes, floor
("overview", unreal.Vector(700, -900, 620), unreal.Vector(0, 300, 80)),
# the vehicle staging, three-quarter front, same framing idea as the demo shot
("vehicle", unreal.Vector(-900, -200, 260), unreal.Vector(-1600, 600, 90)),
# ground-level contact check: feet on the floor, shadow at the contact point
("character-feet", unreal.Vector(220, -420, 45), unreal.Vector(0, 0, 25)),
# the MPFB mannequin, mid shot
("character", unreal.Vector(200, -300, 160), unreal.Vector(0, 0, 85)),
# both cubes from the south: contact shadow vs cast shadow