Replace template meshes with native placeholders
This commit is contained in:
@@ -17,17 +17,29 @@ LANDSCAPE_MIN_XY = -50000.0
|
||||
|
||||
FOLIAGE_LABEL = "AGR_GroundZeroFoliage_FirstPass"
|
||||
FOLIAGE_RANDOM_SEED = 4160544
|
||||
PLACEHOLDER_MESH_FOLDER = "/Game/Agrarian/Environment/PlaceholderMeshes"
|
||||
PLACEHOLDER_MESH_SOURCES = {
|
||||
"SM_AGR_Placeholder_Cube": "/Game/LevelPrototyping/Meshes/SM_Cube",
|
||||
"SM_AGR_Placeholder_ChamferCube": "/Game/LevelPrototyping/Meshes/SM_ChamferCube",
|
||||
"SM_AGR_Placeholder_Cylinder": "/Game/LevelPrototyping/Meshes/SM_Cylinder",
|
||||
"SM_AGR_Placeholder_QuarterCylinder": "/Game/LevelPrototyping/Meshes/SM_QuarterCylinder",
|
||||
"SM_AGR_Placeholder_Plane": "/Game/LevelPrototyping/Meshes/SM_Plane",
|
||||
}
|
||||
PLACEHOLDER_MESHES = {
|
||||
name: f"{PLACEHOLDER_MESH_FOLDER}/{name}"
|
||||
for name in PLACEHOLDER_MESH_SOURCES
|
||||
}
|
||||
FOLIAGE_MESHES = {
|
||||
"tree": "/Game/LevelPrototyping/Meshes/SM_Cylinder",
|
||||
"shrub": "/Game/LevelPrototyping/Meshes/SM_Cube",
|
||||
"grass": "/Game/LevelPrototyping/Meshes/SM_Cylinder",
|
||||
"tree": PLACEHOLDER_MESHES["SM_AGR_Placeholder_Cylinder"],
|
||||
"shrub": PLACEHOLDER_MESHES["SM_AGR_Placeholder_Cube"],
|
||||
"grass": PLACEHOLDER_MESHES["SM_AGR_Placeholder_Cylinder"],
|
||||
}
|
||||
VARIATION_MESHES = {
|
||||
"cube": "/Game/LevelPrototyping/Meshes/SM_Cube",
|
||||
"chamfer_cube": "/Game/LevelPrototyping/Meshes/SM_ChamferCube",
|
||||
"cylinder": "/Game/LevelPrototyping/Meshes/SM_Cylinder",
|
||||
"quarter_cylinder": "/Game/LevelPrototyping/Meshes/SM_QuarterCylinder",
|
||||
"plane": "/Game/LevelPrototyping/Meshes/SM_Plane",
|
||||
"cube": PLACEHOLDER_MESHES["SM_AGR_Placeholder_Cube"],
|
||||
"chamfer_cube": PLACEHOLDER_MESHES["SM_AGR_Placeholder_ChamferCube"],
|
||||
"cylinder": PLACEHOLDER_MESHES["SM_AGR_Placeholder_Cylinder"],
|
||||
"quarter_cylinder": PLACEHOLDER_MESHES["SM_AGR_Placeholder_QuarterCylinder"],
|
||||
"plane": PLACEHOLDER_MESHES["SM_AGR_Placeholder_Plane"],
|
||||
}
|
||||
MATERIAL_FOLDER = "/Game/Agrarian/Materials"
|
||||
ENVIRONMENT_MATERIALS = {
|
||||
@@ -405,6 +417,19 @@ def load_required_asset(path):
|
||||
return asset
|
||||
|
||||
|
||||
def ensure_native_placeholder_meshes():
|
||||
unreal.EditorAssetLibrary.make_directory(PLACEHOLDER_MESH_FOLDER)
|
||||
for asset_name, source_path in PLACEHOLDER_MESH_SOURCES.items():
|
||||
destination_path = f"{PLACEHOLDER_MESH_FOLDER}/{asset_name}"
|
||||
if unreal.EditorAssetLibrary.does_asset_exist(destination_path):
|
||||
continue
|
||||
|
||||
if not unreal.EditorAssetLibrary.duplicate_asset(source_path, destination_path):
|
||||
raise RuntimeError(f"Could not create native placeholder mesh {destination_path} from {source_path}")
|
||||
unreal.EditorAssetLibrary.save_asset(destination_path)
|
||||
unreal.log(f"Created native placeholder mesh: {destination_path}")
|
||||
|
||||
|
||||
def ensure_environment_materials():
|
||||
if not unreal.EditorAssetLibrary.does_directory_exist(MATERIAL_FOLDER):
|
||||
unreal.EditorAssetLibrary.make_directory(MATERIAL_FOLDER)
|
||||
@@ -669,6 +694,8 @@ def main():
|
||||
if not unreal.EditorLevelLibrary.load_level(MAP_PATH):
|
||||
raise RuntimeError(f"Could not load map: {MAP_PATH}")
|
||||
|
||||
ensure_native_placeholder_meshes()
|
||||
|
||||
labels = {spec["label"] for spec in DEMO_ACTORS}
|
||||
labels.update(LEGACY_DEMO_LIGHTING_LABELS)
|
||||
labels.update(spec["label"] for spec in BIOME_RESOURCE_ACTORS)
|
||||
|
||||
@@ -11,8 +11,17 @@ WOOD_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Wood"
|
||||
FIBER_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Fiber"
|
||||
STONE_ITEM_PATH = "/Game/Agrarian/DataAssets/Items/DA_Item_Stone"
|
||||
|
||||
MESH_CUBE_PATH = "/Game/LevelPrototyping/Meshes/SM_Cube"
|
||||
MESH_CYLINDER_PATH = "/Game/LevelPrototyping/Meshes/SM_Cylinder"
|
||||
PLACEHOLDER_MESH_FOLDER = "/Game/Agrarian/Environment/PlaceholderMeshes"
|
||||
PLACEHOLDER_MESH_SOURCES = {
|
||||
"SM_AGR_Placeholder_Cube": "/Game/LevelPrototyping/Meshes/SM_Cube",
|
||||
"SM_AGR_Placeholder_Cylinder": "/Game/LevelPrototyping/Meshes/SM_Cylinder",
|
||||
}
|
||||
PLACEHOLDER_MESHES = {
|
||||
name: f"{PLACEHOLDER_MESH_FOLDER}/{name}"
|
||||
for name in PLACEHOLDER_MESH_SOURCES
|
||||
}
|
||||
MESH_CUBE_PATH = PLACEHOLDER_MESHES["SM_AGR_Placeholder_Cube"]
|
||||
MESH_CYLINDER_PATH = PLACEHOLDER_MESHES["SM_AGR_Placeholder_Cylinder"]
|
||||
|
||||
BLUEPRINTS = [
|
||||
{
|
||||
@@ -125,6 +134,19 @@ def load_required_asset(path):
|
||||
return asset
|
||||
|
||||
|
||||
def ensure_native_placeholder_meshes():
|
||||
unreal.EditorAssetLibrary.make_directory(PLACEHOLDER_MESH_FOLDER)
|
||||
for asset_name, source_path in PLACEHOLDER_MESH_SOURCES.items():
|
||||
destination_path = f"{PLACEHOLDER_MESH_FOLDER}/{asset_name}"
|
||||
if unreal.EditorAssetLibrary.does_asset_exist(destination_path):
|
||||
continue
|
||||
|
||||
if not unreal.EditorAssetLibrary.duplicate_asset(source_path, destination_path):
|
||||
raise RuntimeError(f"Could not create native placeholder mesh {destination_path} from {source_path}")
|
||||
unreal.EditorAssetLibrary.save_asset(destination_path)
|
||||
unreal.log(f"Created native placeholder mesh: {destination_path}")
|
||||
|
||||
|
||||
def create_or_load_blueprint(asset_name, folder, parent_class):
|
||||
path = f"{folder}/{asset_name}"
|
||||
existing = unreal.EditorAssetLibrary.load_asset(path)
|
||||
@@ -177,6 +199,8 @@ def apply_defaults(blueprint, config):
|
||||
|
||||
|
||||
def main():
|
||||
ensure_native_placeholder_meshes()
|
||||
|
||||
for folder in (RESOURCE_FOLDER, STRUCTURE_FOLDER, WILDLIFE_FOLDER, WORLD_FOLDER):
|
||||
unreal.EditorAssetLibrary.make_directory(folder)
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
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"
|
||||
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 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_native_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_native_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()
|
||||
Reference in New Issue
Block a user