| """Run inside Unreal Editor's Python console or Execute Python Script. | |
| Imports the supplied Phase 3 reference plates and places them as emissive | |
| gallery panels in the pax-coder repository sandbox. This is a visual reference | |
| scene, not a photogrammetry reconstruction. | |
| """ | |
| import pathlib | |
| import unreal | |
| PROJECT_DIR = pathlib.Path(unreal.Paths.project_dir()) | |
| SOURCE_DIR = PROJECT_DIR / "ReferenceSource" / "NeonReflections" | |
| DESTINATION = "/Game/RealityScene/NeonReflections" | |
| REPOSITORY_ID = "pax-coder" | |
| REFERENCE_SET_ID = "neon-reflections-v15" | |
| IMAGE_FILES = ["3087.webp", "3089.webp", "3090.webp", "3092.jpg"] | |
| def import_reference_images(): | |
| asset_tools = unreal.AssetToolsHelpers.get_asset_tools() | |
| imported = [] | |
| for file_name in IMAGE_FILES: | |
| source_file = SOURCE_DIR / file_name | |
| if not source_file.is_file(): | |
| unreal.log_warning("Missing reference plate: %s" % source_file) | |
| continue | |
| task = unreal.AssetImportTask() | |
| task.set_editor_property("filename", str(source_file)) | |
| task.set_editor_property("destination_path", DESTINATION) | |
| task.set_editor_property("destination_name", pathlib.Path(file_name).stem) | |
| task.set_editor_property("automated", True) | |
| task.set_editor_property("replace_existing", True) | |
| task.set_editor_property("save", True) | |
| asset_tools.import_asset_tasks([task]) | |
| imported.extend(task.get_editor_property("imported_object_paths")) | |
| return [unreal.load_asset(path) for path in imported] | |
| def make_emissive_material(texture, name): | |
| asset_tools = unreal.AssetToolsHelpers.get_asset_tools() | |
| package_path = DESTINATION + "/Materials" | |
| factory = unreal.MaterialFactoryNew() | |
| material = asset_tools.create_asset(name, package_path, unreal.Material, factory) | |
| if not material: | |
| return None | |
| material.set_editor_property("two_sided", True) | |
| material.set_editor_property("shading_model", unreal.MaterialShadingModel.MSM_UNLIT) | |
| sample = unreal.MaterialEditingLibrary.create_material_expression( | |
| material, unreal.MaterialExpressionTextureSampleParameter2D, -400, 0 | |
| ) | |
| sample.set_editor_property("parameter_name", "ReferenceTexture") | |
| sample.set_editor_property("texture", texture) | |
| unreal.MaterialEditingLibrary.connect_material_property( | |
| sample, "RGB", unreal.MaterialProperty.MP_EMISSIVE_COLOR | |
| ) | |
| unreal.MaterialEditingLibrary.layout_material_expressions(material) | |
| unreal.EditorAssetLibrary.save_loaded_asset(material) | |
| return material | |
| def place_gallery_panel(mesh, material, location, rotation, scale, label): | |
| actor = unreal.EditorLevelLibrary.spawn_actor_from_object( | |
| mesh, unreal.Vector(*location), unreal.Rotator(*rotation) | |
| ) | |
| actor.set_actor_label(label) | |
| actor.set_actor_scale3d(unreal.Vector(*scale)) | |
| component = actor.get_component_by_class(unreal.StaticMeshComponent) | |
| if component and material: | |
| component.set_material(0, material) | |
| return actor | |
| def run(): | |
| textures = import_reference_images() | |
| if not textures: | |
| raise RuntimeError("No reference plates imported from %s" % SOURCE_DIR) | |
| plane = unreal.load_asset("/Engine/BasicShapes/Plane.Plane") | |
| if not plane: | |
| raise RuntimeError("Engine plane mesh is unavailable") | |
| placements = [ | |
| ((0.0, 1800.0, 900.0), (90.0, 0.0, 0.0), (12.0, 8.0), "NeonRef_North"), | |
| ((0.0, -1800.0, 900.0), (-90.0, 0.0, 180.0), (12.0, 8.0), "NeonRef_South"), | |
| ((1800.0, 0.0, 900.0), (90.0, 0.0, 90.0), (12.0, 8.0), "NeonRef_East"), | |
| ((-1800.0, 0.0, 900.0), (90.0, 0.0, -90.0), (12.0, 8.0), "NeonRef_West"), | |
| ] | |
| for texture, placement in zip(textures, placements): | |
| material = make_emissive_material(texture, "MI_" + texture.get_name()) | |
| place_gallery_panel(plane, material, *placement) | |
| repo_class = unreal.load_class(None, "/Script/GitWorldUnreal.GitWorldRepoWorld") | |
| if repo_class: | |
| repo_actor = next( | |
| ( | |
| actor | |
| for actor in unreal.EditorLevelLibrary.get_all_level_actors() | |
| if actor.is_a(repo_class) | |
| and actor.get_editor_property("repository_id") == REPOSITORY_ID | |
| ), | |
| None, | |
| ) | |
| if repo_actor: | |
| repo_actor.set_editor_property("reference_set_id", REFERENCE_SET_ID) | |
| repo_actor.set_editor_property("reference_images", textures) | |
| unreal.EditorAssetLibrary.save_loaded_asset(repo_actor) | |
| unreal.EditorLevelLibrary.save_current_level() | |
| unreal.log("GitWorld Phase 3 reference gallery placed: %s" % REFERENCE_SET_ID) | |
| run() | |