feat(hero): facade rework — inscription, medallions, motto band, banner lettering #39

Merged
zwitschi merged 93 commits from hero-facade-0.3.0 into main 2026-11-10 15:37:40 +01:00
53 changed files with 90 additions and 66 deletions
Showing only changes of commit bb12ce8c33 - Show all commits

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
View File
@@ -24,6 +24,8 @@ Actionable task list for this project. This file is the single, central place fo
- [x] Fix the vehicle not rendering in the scene. **Chased to a strong clue, not yet solved.** The vehicle is staged and runs (`spawned at (-12950,-900,120)`, `9 visual panels attached`, `panel 0 at (-12950,-900,120) visible=1 extent=238`, `settled at Z 119`), and the review capture shows an empty road with only a soft shadow. `Tools/visual_loop.py --verify` passes the frame; `Tools/judge_screenshot.py` returns `verdict=no confidence=1.0`. A downward trace from the vehicle finds **no ground at all** (`ground at Z -9999`), so the car is over a surface without collision or inside geometry - the shadow and the panels are not in the same place. **Fixed 2026-11-09** — the car renders, built from the owner's `hot hatch.blend`. **Fixed:** the vehicle was spawned 2.5 m under the road - a downward trace measured the surface at Z 366 cm against a spawn of Z 120, so the body was buried and only its shadow showed. The spawn is now Z 470 and it settles there.
- **Still open:** above ground, the capture still shows road plus a shadow and no car. Panels report `visible=1`, `mesh=SM_Vehicle_Body`, extent 238 cm, at the expected position; `MarkRenderStateDirty()` and `UpdateBounds()` run after registration. Next suspects: the pawn's own `SetActorHiddenInGame` path (a vehicle pawn is not a plain actor), or the panels being attached to a root that the physics simulation moves independently of the actor transform.
- [x] Fix the character and car floating. Character: the player start at Z 600 left the soles 39 cm in the air (the capsule settles at 561 on this pavement); the start is now the measured 561. Car: the template's lowest geometry is exhaust, so grounding on the whole model put the tyres 4 cm above the origin - it is now grounded on its wheels, staged at Z 342 after the traced road height (366) disagreed with the visible road by ~25 cm.
- [x] Fix the vehicle's material colour. The template's `car paint` is a legacy mix-shader graph that the FBX exporter cannot map, so `SM_Vehicle_Body` imported holding `WorldGridMaterial` and rendered black while Blender showed red. Legacy graphs are now converted to Principled before export (saturated colour wins over the grey diffuse next to it), and the staged body panel is assigned `M_Vehicle_HatchPaint`. Judge: `verdict=yes confidence=0.9`.
- [ ] Fix the missing vehicle glazing. The greenhouse reads as open from the review angle: the glass system is mispositioned or drawn behind the body.
- [ ] Implement enter/exit interaction.
- [ ] Build a closed driving route with boundaries.
- [ ] Tune basic handling to a drivable state.
+8
View File
@@ -719,6 +719,14 @@ def build():
if comp:
comp.set_static_mesh(mesh)
comp.set_mobility(unreal.ComponentMobility.MOVABLE)
# The body imports with no usable material (its slot resolves to
# WorldGridMaterial), so the paint is assigned on the staged panel.
if mesh_name == "SM_Vehicle_Body":
paint = unreal.EditorAssetLibrary.load_asset(
"/Game/Hollywood/Vehicle/M_Vehicle_HatchPaint")
if paint:
comp.set_material(0, paint)
log("Demo_VehiclePanel: body paint assigned")
staged_panels += 1
log(f"staged: {staged_panels} Demo_VehiclePanel actors (plain static meshes)")
+14 -3
View File
@@ -47,12 +47,13 @@ def existing_material_name(name):
return None
def replace_material(name, spec):
def replace_material(name, spec, create_if_missing=False):
resolved = existing_material_name(name)
if resolved is None:
if resolved is not None:
name = resolved
elif not create_if_missing:
log(f"{name}: no imported asset matches - skipped")
return None
name = resolved
full = f"{DEST}/{name}"
if unreal.EditorAssetLibrary.does_asset_exist(full):
unreal.EditorAssetLibrary.delete_asset(full)
@@ -88,6 +89,16 @@ def main():
for name, spec in materials.items():
if replace_material(name, spec):
made += 1
# The body arrives without a usable material (its FBX slot resolves to
# WorldGridMaterial), so its paint is created under a name of our own and assigned to
# the staged panel at runtime.
paint = materials.get("car paint")
if paint:
spec = dict(paint)
spec["base_color"] = [1.0, 0.05, 0.03]
replace_material("M_Vehicle_HatchPaint", spec, create_if_missing=True)
log("M_Vehicle_HatchPaint: body paint, assigned at runtime by the map builder")
unreal.EditorLoadingAndSavingUtils.save_dirty_packages(True, True)
lines.append(f"VERDICT: {'PASS' if made == len(materials) else 'FAIL'}")
log(f"{made}/{len(materials)} materials replaced")