from pathlib import Path import unreal MAP_PATH = "/Game/Agrarian/Maps/L_GroundZeroTerrain_Test" PROJECT_ROOT = Path(unreal.Paths.convert_relative_path_to_full(unreal.Paths.project_dir())) PLACEHOLDER_MESH_FOLDER = "/Game/Agrarian/Environment/PlaceholderMeshes" VEGETATION_MESH_FOLDER = "/Game/Agrarian/Environment/Vegetation" PLACEHOLDER_MESHES = { "SM_AGR_Placeholder_Cube", "SM_AGR_Placeholder_ChamferCube", "SM_AGR_Placeholder_Cylinder", "SM_AGR_Placeholder_QuarterCylinder", "SM_AGR_Placeholder_Plane", } BLUEPRINT_PATHS = [ "/Game/Agrarian/Blueprints/Resources/BP_WoodResourceNode", "/Game/Agrarian/Blueprints/Resources/BP_FiberResourceNode", "/Game/Agrarian/Blueprints/Resources/BP_StoneResourceNode", "/Game/Agrarian/Blueprints/Structures/BP_Campfire", "/Game/Agrarian/Blueprints/Structures/BP_PrimitiveShelter", "/Game/Agrarian/Blueprints/World/BP_FreshWaterSource", ] DOC_SNIPPETS = [ (PROJECT_ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md", "[x] Replace `LevelPrototyping` cube/cylinder mesh dependencies"), (PROJECT_ROOT / "Docs" / "Terrain" / "GroundZeroNaturalEnvironmentPass.md", "Agrarian-native placeholder"), ] def asset_path(asset): if not asset: return "" return asset.get_path_name().split(".", 1)[0] def get_actor_label(actor): try: return actor.get_actor_label() except Exception: return actor.get_name() def assert_native_mesh(path, failures): if not path.startswith(PLACEHOLDER_MESH_FOLDER): failures.append(f"expected native Agrarian placeholder mesh, got {path}") if "LevelPrototyping" in path: failures.append(f"template mesh reference remains: {path}") def assert_agrarian_environment_mesh(path, failures): if not path.startswith((PLACEHOLDER_MESH_FOLDER, VEGETATION_MESH_FOLDER)): failures.append(f"expected native Agrarian environment mesh, got {path}") if "LevelPrototyping" in path or path.startswith("/Engine/BasicShapes/"): failures.append(f"template/basic mesh reference remains: {path}") def main(): failures = [] for mesh_name in PLACEHOLDER_MESHES: mesh_path = f"{PLACEHOLDER_MESH_FOLDER}/{mesh_name}" if not unreal.EditorAssetLibrary.does_asset_exist(mesh_path): failures.append(f"missing native placeholder mesh asset: {mesh_path}") for blueprint_path in BLUEPRINT_PATHS: generated_class = unreal.EditorAssetLibrary.load_blueprint_class(blueprint_path) if not generated_class: failures.append(f"could not load Blueprint class: {blueprint_path}") continue cdo = unreal.get_default_object(generated_class) mesh_component = cdo.get_editor_property("mesh") assert_native_mesh(asset_path(mesh_component.get_editor_property("static_mesh")), failures) if not unreal.EditorLevelLibrary.load_level(MAP_PATH): failures.append(f"could not load map: {MAP_PATH}") else: actors = unreal.EditorLevelLibrary.get_all_level_actors() foliage_actors = [ actor for actor in actors if get_actor_label(actor) == "AGR_GroundZeroFoliage_FirstPass" ] if len(foliage_actors) != 1: failures.append(f"expected one AGR_GroundZeroFoliage_FirstPass, found {len(foliage_actors)}") else: for property_name in ("tree_instances", "shrub_instances", "grass_instances"): component = foliage_actors[0].get_editor_property(property_name) assert_agrarian_environment_mesh(asset_path(component.get_editor_property("static_mesh")), failures) for actor in actors: label = get_actor_label(actor) if not label.startswith("AGR_GZ_EnvVar_"): continue mesh_components = actor.get_components_by_class(unreal.StaticMeshComponent) if not mesh_components: failures.append(f"{label} has no static mesh component") continue assert_agrarian_environment_mesh(asset_path(mesh_components[0].get_editor_property("static_mesh")), failures) for path, snippet in DOC_SNIPPETS: text = path.read_text(encoding="utf-8") if snippet not in text: failures.append(f"{path} missing `{snippet}`") if failures: raise RuntimeError("Native placeholder mesh verification failed: " + "; ".join(failures)) unreal.log( "Native placeholder mesh verification complete: " f"{len(PLACEHOLDER_MESHES)} Agrarian mesh assets, {len(BLUEPRINT_PATHS)} Blueprint meshes, " "foliage meshes, and environment variation meshes use native paths." ) main()