# Builds /Game/Test/ReviewMap — the visual-review scene — and saves it as a # map asset. Run before the screenshot pass (Tools/render_screenshots.sh does # this automatically). # # Scene: metric floor, key light, fill sky, sky atmosphere, MPFB character, # the three 1 m scale cubes, and an AGigLineShotActor with the camera list. # # UnrealEditor-Cmd -run=pythonscript -script=/Tools/ue_build_review_map.py \ # -nullrhi -unattended -nopause -stdout # # Do NOT load_map here: after a map load the commandlet's spawn context dies # (every spawn_actor call returns None). Everything is spawned into the # default world and saved as a new map asset. import os import unreal RESULT = "/tmp/ue-review-map-result.txt" MAP_PATH = "/Game/Test/ReviewMap" lines = [] def log(msg): lines.append(str(msg)) def spawn(cls, loc, label=None, scale=None, rot=None): a = unreal.EditorLevelLibrary.spawn_actor_from_class(cls, loc) if a is None: log(f"spawn {cls.__name__} returned None") return None if rot is not None: a.set_actor_rotation(rot, False) if scale is not None: a.set_actor_scale3d(scale) if label: a.set_actor_label(label) return a # --- scene ------------------------------------------------------------------- try: # Neutral gray floor material (the scale-test mesh ships red) floor_mat = None if not unreal.EditorAssetLibrary.does_asset_exist("/Game/Test/M_ReviewFloor"): floor_mat = unreal.AssetToolsHelpers.get_asset_tools().create_asset( "M_ReviewFloor", "/Game/Test", unreal.Material, unreal.MaterialFactoryNew()) n = unreal.MaterialEditingLibrary.create_material_expression( floor_mat, unreal.MaterialExpressionConstant3Vector) n.set_editor_property("constant", unreal.LinearColor(0.35, 0.35, 0.35, 1.0)) unreal.MaterialEditingLibrary.connect_material_property( n, "", unreal.MaterialProperty.MP_BASE_COLOR) unreal.MaterialEditingLibrary.recompile_material(floor_mat) unreal.EditorAssetLibrary.save_loaded_asset(floor_mat) else: floor_mat = unreal.EditorAssetLibrary.load_asset("/Game/Test/M_ReviewFloor") floor_mesh = unreal.EditorAssetLibrary.load_asset("/Game/Test/ScaleTest/ScaleTest_A") if floor_mesh and floor_mat: floor = spawn(unreal.StaticMeshActor, unreal.Vector(450, 450, -50.0), "ReviewFloor", scale=(45.0, 45.0, 0.1)) if floor: floor.static_mesh_component.set_static_mesh(floor_mesh) floor.static_mesh_component.set_material(0, floor_mat) log("staged: floor (45 m plane, gray)") else: log("floor spawn failed") if spawn(unreal.DirectionalLight, unreal.Vector(0, 0, 900), "RenderKeyLight", rot=unreal.Rotator(pitch=-38.0, yaw=35.0, roll=0.0)): log("staged: DirectionalLight") if spawn(unreal.SkyLight, unreal.Vector(0, 0, 1200), "RenderFillSky"): log("staged: SkyLight") if spawn(unreal.SkyAtmosphere, unreal.Vector(0, 0, 0), "RenderSky"): log("staged: SkyAtmosphere") char_mesh = unreal.EditorAssetLibrary.load_asset("/Game/Test/Character/character") if char_mesh: ch = spawn(unreal.SkeletalMeshActor, unreal.Vector(0, 0, 0), "ReviewCharacter", rot=unreal.Rotator(pitch=0.0, yaw=180.0, roll=0.0)) if ch: ch.skeletal_mesh_component.set_skinned_asset_and_update(char_mesh) log("staged: MPFB character at origin, facing -Y") else: log("MISSING: /Game/Test/Character/character") for name, x in (("ScaleTest_A", -400.0), ("ScaleTest_B", 0.0), ("ScaleTest_C", 400.0)): m = unreal.EditorAssetLibrary.load_asset(f"/Game/Test/ScaleTest/{name}") if m: c = spawn(unreal.StaticMeshActor, unreal.Vector(x, 600.0, 50.0), f"Cube_{name}") if c: c.static_mesh_component.set_static_mesh(m) log(f"staged: {name} at ({x}, 600, 50)") # Hero facade, if the import has run: two views a reviewer needs — straight on # from the north sidewalk, and the oblique street view from further west. hero = unreal.EditorAssetLibrary.load_asset("/Game/Hollywood/ElCapitan/SM_HeroFacade") # The imported mesh spans Y -7..+1250 cm in local space (front plane at -7, the # body behind it) and is centred on X. To put the front plane on the block's # building line the actor goes at Y = building line + 7 cm. hero_x = -12024.5 + 1302.0 hero_y = -1450.0 + 7.0 if hero: actor = spawn(unreal.StaticMeshActor, unreal.Vector(hero_x, hero_y, 0.0), "Hero_Facade") if actor: actor.static_mesh_component.set_static_mesh(hero) actor.static_mesh_component.set_mobility(unreal.ComponentMobility.STATIC) log("staged: hero facade at the measured building line") else: log("MISSING: /Game/Hollywood/ElCapitan/SM_HeroFacade (run Tools/ue_hero_facade_import.py)") shots = spawn(unreal.GigLineShotActor, unreal.Vector(0, 0, 300), "ShotSequencer") if shots: shots.set_editor_property("shot_locations", [ unreal.Vector(900, -1100, 500), unreal.Vector(200, -300, 160), unreal.Vector(200, 100, 200), # first-person eye height, just south-east of the character: this is the # view a player has at spawn, capsule and camera stack in frame unreal.Vector(120, -260, 165), # straight on from the north sidewalk at eye height. No camera may sit # inside the facade body (Y -1443..+250 cm), so both stand north of the # front plane and look south into the colonnade. unreal.Vector(hero_x + 200, -3200, 420), # oblique from the north-west, reading the colonnade in depth unreal.Vector(hero_x - 2200, -3400, 620), ]) shots.set_editor_property("shot_rotations", [ unreal.MathLibrary.find_look_at_rotation( unreal.Vector(900, -1100, 500), unreal.Vector(100, 200, 80)), unreal.MathLibrary.find_look_at_rotation( unreal.Vector(200, -300, 160), unreal.Vector(0, 0, 85)), unreal.MathLibrary.find_look_at_rotation( unreal.Vector(200, 100, 200), unreal.Vector(0, 600, 50)), unreal.MathLibrary.find_look_at_rotation( unreal.Vector(120, -260, 165), unreal.Vector(-200, 600, 90)), unreal.MathLibrary.find_look_at_rotation( unreal.Vector(hero_x + 200, -3200, 420), unreal.Vector(hero_x, hero_y + 400, 760)), unreal.MathLibrary.find_look_at_rotation( unreal.Vector(hero_x - 2200, -3400, 620), unreal.Vector(hero_x + 300, hero_y, 700)), ]) shots.set_editor_property("shot_names", ["overview", "character", "scale-cubes", "first-person", "hero-facade-front", "hero-facade-oblique"]) shots.set_editor_property("quit_when_done", True) log("staged: ShotSequencer with 6 cameras") except Exception as exc: # noqa log(f"staging failed: {exc!r}") # --- save -------------------------------------------------------------------- try: world = unreal.EditorLevelLibrary.get_editor_world() saved = unreal.EditorLoadingAndSavingUtils.save_map(world, MAP_PATH) log(f"save_map {MAP_PATH}: {saved}") except Exception as exc: # noqa log(f"save_map failed: {exc!r}") with open(RESULT, "w") as f: f.write("\n".join(lines) + "\n")