diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 460d86f..f5cf00b 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a3c68632e916cab692d991b550855054822cb0196c3f69be337c42ccbc5d60c -size 44952 +oid sha256:02c0472158a947e60eda4375729a5dcb7b5e90441dbe6659cc3816be00fe2726 +size 45507 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index bb6d30d..71d83e2 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fc0d523f0fb587306a9e946e27b10113eb89df1218e6fdb8553b29f083384e49 -size 4605 +oid sha256:d3ce9d98468f5bb8dcfc530ad2d1567790c0e446fdf46c272a9fd6da09e9e808 +size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index fa49e20..a0603b3 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c765035f6c076c4016831884b167fa93e162bab7d0038f55cd09d240105dfa4c -size 4610 +oid sha256:f5f7213ec007a363d456ffb1376305a510e1113d95427f77633098700ca64a7b +size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset new file mode 100644 index 0000000..dd97e69 --- /dev/null +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4255a288970bcec6521a2ca3a2c718e240295336fda55f4fb6144ffc517fa27c +size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 5948d47..9a86660 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:21454ed393d70dc103e0ad7ca00b06aed6fded381062ddcde87a424c05ff580d -size 4600 +oid sha256:6111173ab3a2a530cd42edc931d0e4d6f539527403b9cca016c064629a47184b +size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset new file mode 100644 index 0000000..874df3b --- /dev/null +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc5c41a2c161635471d1dc74de3cedbe6fd11b4eaffbe6e397734e640831013a +size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index 7aa4d2f..8ded297 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:891ee60d2feac3e741509e9e03756e9941b4561994e1a77732f565b7aae5bb52 -size 4615 +oid sha256:0209f2cef5ce37668e642f9d937242878381326b6d1d437167dea3f601aa3a02 +size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset new file mode 100644 index 0000000..4b309bf --- /dev/null +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bf3cbcc33ccc1d5fc1e72c1c31d2bc32077bf6f00002963ad99b12486e98ebf +size 7871 diff --git a/Game/GigLine/Content/Test/ReviewMap.umap b/Game/GigLine/Content/Test/ReviewMap.umap index f416a72..6e70625 100644 --- a/Game/GigLine/Content/Test/ReviewMap.umap +++ b/Game/GigLine/Content/Test/ReviewMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b60d901d3cdc13183eac08749faf028dc532c3f1da1a03d7aba8f2111d63c11 +oid sha256:4c46349a4d52e479d9580b1d1a45ff8bec3afc8ada802908a0f2387cbf887c84 size 28715 diff --git a/Screenshots/README.md b/Screenshots/README.md index 411d572..5a6f226 100644 --- a/Screenshots/README.md +++ b/Screenshots/README.md @@ -50,10 +50,14 @@ All ☑ approved 2026-11-07. Z 2 m; both are exactly 1 m — the scale reference. - **Demo map** (`/Game/Hollywood/DemoMap`): fixed daytime — sun at pitch −50 / yaw 120 (intensity 4, warm), sky light 2.6, sky atmosphere, height fog, fixed - exposure. Surface colours are assigned explicitly in - `Tools/ue_build_demo_map.py` (`M_Asphalt`, `M_Concrete`, `M_Ground`, - `M_RoadPaint`) because Blender's flat diffuse colours do not survive the - FBX → Unreal import. + exposure. +- **Materials**: every exported surface carries a look-developed material built + in `Tools/ue_build_demo_map.py` (`ensure_material`) because Blender's flat + diffuse colours do not survive the FBX → Unreal import. Each has an explicit + roughness and a subtle world-space noise blend between two shades: + `M_Asphalt` (0.92), `M_Concrete` (0.88), `M_KerbConcrete` (0.85), + `M_Ground` (0.98), `M_RoadPaint` (0.62), `M_FacadeStone` (0.72) and + `M_Stucco` (0.86) for the north-side buildings. - **Lighting is dynamic-only** (`r.AllowStaticLighting=False`, all lights Movable), so no lighting build is ever required. - **Attribution overlay**: every shot carries the required ODbL credit in the diff --git a/Screenshots/demo/review-demo-crossing.png b/Screenshots/demo/review-demo-crossing.png index 3a11a09..434d0fb 100644 --- a/Screenshots/demo/review-demo-crossing.png +++ b/Screenshots/demo/review-demo-crossing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c653c408d41483f37ad1801da5b25896a7b55c4b685abf42cd5d396c32472767 -size 1588910 +oid sha256:676b50cd950b4ea3417073d1b604f64c9317c453f83db9eabfb5662d6821f867 +size 2534457 diff --git a/Screenshots/demo/review-demo-north-buildings.png b/Screenshots/demo/review-demo-north-buildings.png index ebf9fa2..cd094da 100644 --- a/Screenshots/demo/review-demo-north-buildings.png +++ b/Screenshots/demo/review-demo-north-buildings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2155329bab55bcbbb507c78a6fe6246a8d5968769fc12d70d5d28f7ca7b5bafe -size 1551804 +oid sha256:bbe1fe758d2e10266204507da00f27c366deda7dfd1ee1f8888cacb097940465 +size 2766034 diff --git a/Screenshots/demo/review-demo-spawn-view.png b/Screenshots/demo/review-demo-spawn-view.png index 9805d4e..4784f39 100644 --- a/Screenshots/demo/review-demo-spawn-view.png +++ b/Screenshots/demo/review-demo-spawn-view.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d0f73699a0557705cab7cc08cb8563dfbc815b2412437f842a989eade31afb95 -size 1608333 +oid sha256:513a6f2ca281001b80295d0c82c533c48fdd8496938d7f835f9856db721383c6 +size 1588985 diff --git a/Screenshots/demo/review-demo-street-level.png b/Screenshots/demo/review-demo-street-level.png index 3291657..f702ef0 100644 --- a/Screenshots/demo/review-demo-street-level.png +++ b/Screenshots/demo/review-demo-street-level.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06ebb28aa6276bf73488bd29fa2b3c6b9768fd5fdeccf449b9053a7482574b6a -size 1782195 +oid sha256:581898cdd897101711c72520f786021b24800c8f3c0731300692d4a898919734 +size 2241154 diff --git a/Screenshots/review-character.png b/Screenshots/review-character.png index dde1aeb..39e2532 100644 --- a/Screenshots/review-character.png +++ b/Screenshots/review-character.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e3263c3e03689deff30963c8ba87b12db86e9e9144c980ea161d56719c189fbe -size 2281114 +oid sha256:737d7cacd9573cf9d41b9add8c6182b94d804c0f2a6f5e29ac317c9f55da135e +size 2496192 diff --git a/Screenshots/review-ground-contact.png b/Screenshots/review-ground-contact.png index 27d23dd..ae72e1f 100644 --- a/Screenshots/review-ground-contact.png +++ b/Screenshots/review-ground-contact.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a8d2ce6def7b696a6bf0a17ad9b7b83df8830b47272d940b3aafe2e5d0866cc5 -size 1941667 +oid sha256:5009a7639444b00f471fff091b0ba9cb354469b0a07134bf9a78a5b768ed54f8 +size 1742167 diff --git a/Screenshots/review-hero-facade-front.png b/Screenshots/review-hero-facade-front.png index 286ab15..2824ce4 100644 --- a/Screenshots/review-hero-facade-front.png +++ b/Screenshots/review-hero-facade-front.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0e692691c25c96a303058f1c602f40c20399d8e722cfe7c2c603de37ef82d9a8 -size 2081796 +oid sha256:8f958d6988ca97321cfaf03415a67cbec4a34b75c20a524d3e3b9f59d2bd01cc +size 2110749 diff --git a/Screenshots/review-hero-facade-oblique.png b/Screenshots/review-hero-facade-oblique.png index 6286615..441206e 100644 --- a/Screenshots/review-hero-facade-oblique.png +++ b/Screenshots/review-hero-facade-oblique.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:43dc46936a78cfaddc9de96e54176ee9bd5c4f437d577adfa1c8fb4fe7fe9131 -size 1966305 +oid sha256:a710d8ff8e5ff2cfc744d3f06c1aecec7568e1e813b4a7e83f72c04d8e323913 +size 1965431 diff --git a/Screenshots/review-hero-portals.png b/Screenshots/review-hero-portals.png index 533a332..b13c180 100644 --- a/Screenshots/review-hero-portals.png +++ b/Screenshots/review-hero-portals.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:abf01a465d1a7bf67548c3218a0621259d2ed667c4c23dd9bab54b5990377c74 -size 1901906 +oid sha256:db1188759bda61be3362aa513ba06887aff39ae5b4bba590c8ba17fd0aa48455 +size 1778180 diff --git a/Screenshots/review-npc-prefab.png b/Screenshots/review-npc-prefab.png index e366649..193bb32 100644 --- a/Screenshots/review-npc-prefab.png +++ b/Screenshots/review-npc-prefab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0bda1773d8ec4b16f7cb9ca546c7806913186445cccdc79d9fde5536a8484c52 -size 1908365 +oid sha256:786e237feeda93652b73524d1cbf22869e71fa320ca664354efbf8142b34602e +size 1739520 diff --git a/Screenshots/review-overview.png b/Screenshots/review-overview.png index 6e5b3e0..3102ec8 100644 --- a/Screenshots/review-overview.png +++ b/Screenshots/review-overview.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9d7c9d86a752e4b9b61427d1f95aed0e11e02ce5031de0e0a8428e6620693831 -size 2621180 +oid sha256:90630d97e51c5c97b1e09738a95074e9f85294d9465a819f0833c785c33c24f6 +size 2604622 diff --git a/Screenshots/review-player-placement.png b/Screenshots/review-player-placement.png index 6a37d2d..1700256 100644 --- a/Screenshots/review-player-placement.png +++ b/Screenshots/review-player-placement.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a3a43c0786c7f458850041ae519633210fe22e9603e8ab34301a3dd0103f955d -size 2049465 +oid sha256:4b1925e2e85c39d66d7a245b63f7dd2e12e08a8e8058b23cf54fd87141549bbb +size 1986975 diff --git a/Screenshots/review-scale-cubes.png b/Screenshots/review-scale-cubes.png index 8412d14..2248d25 100644 --- a/Screenshots/review-scale-cubes.png +++ b/Screenshots/review-scale-cubes.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8db5324138e9e9ad0ca9c0fd0c03d73cb9274f40f889e9fdf27f364912b1ec54 -size 2100021 +oid sha256:6cd0241d169bf92c043b08d30385792e7c2ac2c6d297f5697323deb499d1bf7f +size 1903735 diff --git a/Screenshots/review-shadow-compare.png b/Screenshots/review-shadow-compare.png index 26ed002..c7a8dea 100644 --- a/Screenshots/review-shadow-compare.png +++ b/Screenshots/review-shadow-compare.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81fbf6b9a504e125f7e990cd0be9c54ec31b117ddf8cc14a0461765e5d03f72c -size 1931209 +oid sha256:e71421e8c29fa36c4506bfcb9d99848329840d2eb0ac02946071672b04464257 +size 1711217 diff --git a/TODO.md b/TODO.md index 6173aaf..89232f1 100644 --- a/TODO.md +++ b/TODO.md @@ -87,7 +87,7 @@ The MPFB character asset is planned as the NPC template (see `ROADMAP.md`). Keep - [ ] Model surrounding block frontage. - [x] Model simplified background buildings directly across Hollywood Boulevard. Done 2026-11-07, the two in-scope north-side buildings — TCL Chinese Theatre (SM_TCL_Chinese_Theatre) and Madame Tussaud's (SM_Madame_Tussauds) — taken from the verified OSM blockout volumes and exported with `ue_metric_v1`, with a Y-mirror so they land north of Hollywood Blvd across the street from the hero (TCL spans Unreal Y 1802..9431, Tussaud's 1888..7586; road centreline ≈ 0, hero façade at Y −1450). Staged in the DemoMap as `North_TCL_Chinese` / `North_Madame_Tussauds`; demo shot `review-03-demo-north-buildings` captured. Simple flat facade materials (surfaces are the `0.1.4` patch). - [A] Build sidewalks, roads, and collision meshes. Terrain, road, sidewalks and kerbs exist (`Art/blender/terrain/`, `street/`) and are assembled in `site/site-2026-11-06.blend`; collision and details (crossing markings, kerb radii, aprons) are not built. Ground must follow the DEM: 3.94 m fall along the block, ~2 % crown between the gutters at ±10–11 m from the centreline, north sidewalk higher than south. Kerb height is an unresolved assumption — the DEM does not resolve it (`Geo/verification/2026-11-06-cross-sections.md`). -- [A] Materials and look development for all exported assets. +- [x] Materials and look development for all exported assets. Done 2026-11-07: every exported surface now carries a look-developed material built procedurally in `Tools/ue_build_demo_map.py` (`ensure_material`): base colour with a world-space noise blend between two shades for large-scale variation, plus an explicit roughness and specular. Set is `M_Asphalt` 0.92, `M_Concrete` 0.88, `M_KerbConcrete` 0.85, `M_Ground` 0.98, `M_RoadPaint` 0.62, `M_FacadeStone` 0.72 (hero façade) and `M_Stucco` 0.86 (TCL, Tussaud's), assigned by mesh and by actor label. Materials are rebuilt on every run so a stale asset cannot mask a look change. The richer texture-based pass (baked/procedural brick, brick_facade and seamless_concrete generators) stays in the `0.1.4` façade patch. ### Gameplay - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `gameplay-attribution-0.1.0`) diff --git a/Tools/ue_build_demo_map.py b/Tools/ue_build_demo_map.py index 2883931..2b08281 100644 --- a/Tools/ue_build_demo_map.py +++ b/Tools/ue_build_demo_map.py @@ -50,26 +50,78 @@ def spawn(cls, loc, label, rot=None): return actor -def ensure_material(asset_name, rgb): - """Create/reuse a flat-colour material under /Game/Hollywood/Site. +def ensure_material(mat_name, spec): + """Create/reuse a look-developed material under /Game/Hollywood/Site. - Used where the FBX material round-trip does not survive import: the terrain - arrives with WorldGridMaterial (UE's bright default grid), which reads as a - blown-out white field under the demo sun. + Blender's flat diffuse colours do not survive the FBX -> Unreal import (the + terrain even lands with WorldGridMaterial), so the demo has always assigned + its own material per surface. Those were flat colour only, which read as + plastic. Each material here gets: + + * base colour with a subtle world-space noise blend between two shades, + so asphalt and concrete have large-scale variation instead of a fill, + * an explicit roughness (and specular) so the surface type is readable, + wet-looking stone vs matte concrete vs chalky road paint. + + spec keys: dark, bright (RGB tuples), roughness, specular, noise_scale + (world units per noise cycle; smaller = larger features). """ - path = f"/Game/Hollywood/Site/{asset_name}" + path = f"/Game/Hollywood/Site/{mat_name}" if unreal.EditorAssetLibrary.does_asset_exist(path): - return unreal.EditorAssetLibrary.load_asset(path) + # Rebuilt every run so a look change cannot be masked by a stale asset. + unreal.EditorAssetLibrary.delete_asset(path) + mat = unreal.AssetToolsHelpers.get_asset_tools().create_asset( - asset_name, "/Game/Hollywood/Site", unreal.Material, unreal.MaterialFactoryNew()) - node = unreal.MaterialEditingLibrary.create_material_expression( - mat, unreal.MaterialExpressionConstant3Vector) - node.set_editor_property("constant", unreal.LinearColor(rgb[0], rgb[1], rgb[2], 1.0)) - unreal.MaterialEditingLibrary.connect_material_property( - node, "", unreal.MaterialProperty.MP_BASE_COLOR) - unreal.MaterialEditingLibrary.recompile_material(mat) + mat_name, "/Game/Hollywood/Site", unreal.Material, unreal.MaterialFactoryNew()) + lib = unreal.MaterialEditingLibrary + + def node(cls): + return lib.create_material_expression(mat, cls) + + def c3(rgb): + n = node(unreal.MaterialExpressionConstant3Vector) + n.set_editor_property("constant", unreal.LinearColor(rgb[0], rgb[1], rgb[2], 1.0)) + return n + + def scalar(value): + n = node(unreal.MaterialExpressionConstant) + n.set_editor_property("r", float(value)) + return n + + # world position -> noise -> lerp(dark, bright) -> base colour + wp = node(unreal.MaterialExpressionWorldPosition) + scale = scalar(spec.get("noise_scale", 0.004)) + mul = node(unreal.MaterialExpressionMultiply) + lib.connect_material_expressions(wp, "", mul, "A") + lib.connect_material_expressions(scale, "", mul, "B") + + noise = node(unreal.MaterialExpressionNoise) + for prop, value in (("scale", 1.0), ("quality", 1), ("levels", 2), + ("output_min", 0.0), ("output_max", 1.0)): + try: + noise.set_editor_property(prop, value) + except Exception: # noqa: BLE001 + pass + lib.connect_material_expressions(mul, "", noise, "Position") + + lerp = node(unreal.MaterialExpressionLinearInterpolate) + lib.connect_material_expressions(c3(spec["dark"]), "", lerp, "A") + lib.connect_material_expressions(c3(spec["bright"]), "", lerp, "B") + lib.connect_material_expressions(noise, "", lerp, "Alpha") + lib.connect_material_property(lerp, "", unreal.MaterialProperty.MP_BASE_COLOR) + + lib.connect_material_property( + scalar(spec.get("roughness", 0.85)), "", unreal.MaterialProperty.MP_ROUGHNESS) + try: + lib.connect_material_property( + scalar(spec.get("specular", 0.3)), "", unreal.MaterialProperty.MP_SPECULAR) + except Exception: # noqa: BLE001 - specular input is optional in UE5 + pass + + lib.recompile_material(mat) unreal.EditorAssetLibrary.save_loaded_asset(mat) - log(f"created material {asset_name} rgb={rgb}") + log(f"material {mat_name}: rough={spec.get('roughness')} " + f"dark={spec['dark']} bright={spec['bright']}") return mat @@ -209,17 +261,38 @@ def build(): # builds a material with a default white base colour, and the terrain even # lands with WorldGridMaterial. Every site surface therefore rendered white, # which is what washed out the demo. Assign explicit colours per mesh here. - SURFACE_MATERIALS = { - "Terrain_DEM": ("M_Ground", (0.30, 0.28, 0.25)), - "Road_Hollywood": ("M_Asphalt", (0.055, 0.055, 0.06)), - "Sidewalk_South": ("M_Concrete", (0.52, 0.50, 0.47)), - "Sidewalk_North": ("M_Concrete", (0.52, 0.50, 0.47)), - "Kerb_South": ("M_Concrete", (0.52, 0.50, 0.47)), - "Kerb_North": ("M_Concrete", (0.52, 0.50, 0.47)), - "Crossing_Markings": ("M_RoadPaint", (0.80, 0.80, 0.78)), + # Look-developed surface materials (see ensure_material for the graph). + MATERIAL_SPECS = { + "M_Asphalt": dict(dark=(0.040, 0.040, 0.044), bright=(0.072, 0.072, 0.078), + roughness=0.92, specular=0.22, noise_scale=0.006), + "M_Concrete": dict(dark=(0.44, 0.42, 0.39), bright=(0.56, 0.54, 0.50), + roughness=0.88, specular=0.28, noise_scale=0.004), + "M_KerbConcrete": dict(dark=(0.47, 0.45, 0.42), bright=(0.60, 0.58, 0.54), + roughness=0.85, specular=0.30, noise_scale=0.008), + "M_Ground": dict(dark=(0.22, 0.20, 0.17), bright=(0.33, 0.30, 0.26), + roughness=0.98, specular=0.15, noise_scale=0.003), + "M_RoadPaint": dict(dark=(0.74, 0.74, 0.72), bright=(0.86, 0.86, 0.84), + roughness=0.62, specular=0.35, noise_scale=0.02), + "M_FacadeStone": dict(dark=(0.62, 0.58, 0.50), bright=(0.74, 0.70, 0.62), + roughness=0.72, specular=0.32, noise_scale=0.005), + "M_Stucco": dict(dark=(0.52, 0.48, 0.42), bright=(0.66, 0.62, 0.55), + roughness=0.86, specular=0.25, noise_scale=0.004), } + SURFACE_MATERIALS = { + "Terrain_DEM": "M_Ground", + "Road_Hollywood": "M_Asphalt", + "Sidewalk_South": "M_Concrete", + "Sidewalk_North": "M_Concrete", + "Kerb_South": "M_KerbConcrete", + "Kerb_North": "M_KerbConcrete", + "Crossing_Markings": "M_RoadPaint", + } + built = {} + for mat_name, spec in MATERIAL_SPECS.items(): + built[mat_name] = ensure_material(mat_name, spec) + imported = 0 - for name, (mat_name, rgb) in SURFACE_MATERIALS.items(): + for name, mat_name in SURFACE_MATERIALS.items(): mesh = unreal.EditorAssetLibrary.load_asset(f"/Game/Hollywood/Site/{name}") if mesh is None: continue @@ -227,12 +300,29 @@ def build(): if actor: actor.static_mesh_component.set_static_mesh(mesh) actor.static_mesh_component.set_mobility(unreal.ComponentMobility.MOVABLE) - mat = ensure_material(mat_name, rgb) + mat = built.get(mat_name) if mat: actor.static_mesh_component.set_material(0, mat) imported += 1 log(f"staged {imported} site meshes with explicit surface materials") + # The hero facade and the two north-side buildings are staged by other + # scripts (or reused between rebuilds), so assign their look materials by + # actor label after everything is in the level. + LABEL_MATERIALS = {"Hero_Facade": "M_FacadeStone", + "North_TCL_Chinese": "M_Stucco", + "North_Madame_Tussauds": "M_Stucco"} + assigned = 0 + for actor in unreal.EditorLevelLibrary.get_all_level_actors(): + mat_name = LABEL_MATERIALS.get(actor.get_actor_label()) + if not mat_name or mat_name not in built: + continue + comp = actor.get_component_by_class(unreal.StaticMeshComponent) + if comp and comp.static_mesh: + comp.set_material(0, built[mat_name]) + assigned += 1 + log(f"assigned look materials to {assigned} facade/background actors") + # --- player start: north sidewalk, facing the hero frontage ------------- # Signs were measured from the imported meshes rather than assumed: the FBX # preset flips north, so in Unreal the road spans Y -1382..+1047, the NORTH