Files
2026-10-31 17:03:41 +01:00

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)