70 lines
3.6 KiB
Python
70 lines
3.6 KiB
Python
"""Integration check: export/import, changed geometry/material, stable asset paths, MRQ."""
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
|
|
import unreal
|
|
|
|
from ue_workshop import Scene, Sequence, blender, camera, lighting, render
|
|
from ue_workshop.paths import PROJECT, executable
|
|
|
|
source = PROJECT / "source_assets/character/character.blend"
|
|
if not source.is_file():
|
|
raise RuntimeError("Wygeneruj przykladowa postac: blender --background --python tools/create_character.py")
|
|
mesh = blender.import_character(source, name="SmokeCharacterV1")
|
|
asset_path = mesh.get_path_name()
|
|
old_bounds = mesh.get_bounds().box_extent.z
|
|
old_materials = {str(item.material_slot_name): item.material_interface.get_path_name()
|
|
for item in mesh.static_materials}
|
|
assert len(old_materials) == 3, old_materials
|
|
assert all(old_materials.values())
|
|
|
|
# Change a COPY of the source, never the student's .blend.
|
|
variant = PROJECT / "build/smoke/character_variant.blend"
|
|
variant.parent.mkdir(parents=True, exist_ok=True)
|
|
code = ("import bpy; bpy.data.objects['Head'].scale *= 2; "
|
|
"bpy.data.materials['Head_Orange'].node_tree.nodes.get('Principled BSDF')."
|
|
"inputs['Base Color'].default_value = (0.02, 0.8, 0.05, 1); "
|
|
"image = bpy.data.images.new('BodyPattern', width=2, height=2); "
|
|
"image.pixels = [0.1, 0.3, 0.8, 1] * 4; image.pack(); "
|
|
"tree = bpy.data.materials['Body_Blue'].node_tree; "
|
|
"node = tree.nodes.new('ShaderNodeTexImage'); node.image = image; "
|
|
"tree.links.new(node.outputs['Color'], tree.nodes.get('Principled BSDF').inputs['Base Color']); "
|
|
f"bpy.ops.wm.save_as_mainfile(filepath={str(variant)!r})")
|
|
completed = subprocess.run([executable("blender"), "--background", str(source),
|
|
"--python-exit-code", "1", "--python-expr", code],
|
|
capture_output=True, text=True, timeout=120)
|
|
if completed.returncode:
|
|
raise RuntimeError((completed.stdout + completed.stderr)[-4000:])
|
|
updated = blender.import_character(variant, name="SmokeCharacterV1")
|
|
assert updated.get_path_name() == asset_path, "Import created a different mesh asset"
|
|
assert updated.get_bounds().box_extent.z > old_bounds + 5, "Geometry was not updated"
|
|
new_materials = {str(item.material_slot_name): item.material_interface.get_path_name()
|
|
for item in updated.static_materials}
|
|
assert new_materials == old_materials, "Material identities changed"
|
|
assert all(unreal.load_asset(path) for path in new_materials.values())
|
|
green_found = False
|
|
texture_found = False
|
|
for path in new_materials.values():
|
|
material = unreal.load_asset(path)
|
|
for parameter in unreal.MaterialEditingLibrary.get_vector_parameter_names(material):
|
|
color = unreal.MaterialEditingLibrary.get_material_instance_vector_parameter_value(material, parameter)
|
|
if color.g > 0.7 and color.r < 0.1 and color.b < 0.1:
|
|
green_found = True
|
|
for parameter in unreal.MaterialEditingLibrary.get_texture_parameter_names(material):
|
|
texture = unreal.MaterialEditingLibrary.get_material_instance_texture_parameter_value(material, parameter)
|
|
if texture and texture.get_path_name().startswith("/Game/Workshop/Generated/Imports/SmokeCharacterV1/"):
|
|
texture_found = True
|
|
assert green_found, "Updated green material was not imported"
|
|
assert texture_found, "Embedded Blender texture was not imported and assigned"
|
|
|
|
scene = Scene("BlenderSmoke")
|
|
actor = scene.mesh(updated, name="UpdatedCharacter")
|
|
lighting.studio(scene)
|
|
cam = camera.create(scene)
|
|
shot = Sequence(scene, frames=2)
|
|
shot.camera(cam)
|
|
shot.transform_key(actor, 0, rotation=(0, 0, 0))
|
|
shot.transform_key(actor, 1, rotation=(0, 0, 30))
|
|
render.start(shot)
|