86 lines
3.8 KiB
Python
86 lines
3.8 KiB
Python
"""Integration test in real Blender, including geometry edits, pruning and undo.
|
|
|
|
blender -b --factory-startup --python tests/blender_roundtrip.py
|
|
Writes a verified demonstration and report to out/.
|
|
"""
|
|
import importlib.util
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
import bpy
|
|
|
|
root = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(root))
|
|
from spatial_lab.examples import demo_project
|
|
from spatial_lab.project import Project, write_json
|
|
|
|
spec = importlib.util.spec_from_file_location('bridge', root / 'blender/bridge.py')
|
|
bridge = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(bridge)
|
|
scene = bridge.create_scene('Spatial Lab / Braided atrium')
|
|
bpy.context.window.scene = scene
|
|
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
path = Path(temporary) / 'study.json'
|
|
write_json(path, demo_project())
|
|
project = Project(path)
|
|
original = project.build()
|
|
bridge.import_bundle(original, scene)
|
|
original_check = bridge.verify_bundle(original, scene)
|
|
assert original_check['passed'], original_check
|
|
obj = next(o for o in scene.objects if o.get('spatial_lab_id') == 'braided-galleries/0000/main')
|
|
pointer = obj.as_pointer()
|
|
original_material = obj.material_slots[0].material
|
|
modifier = obj.modifiers.new('Artist bevel', 'BEVEL')
|
|
artist_material = bpy.data.materials.new('Artist material')
|
|
obj.material_slots[0].material = artist_material
|
|
marker = bpy.data.objects.new('Unrelated object', None)
|
|
scene.collection.objects.link(marker)
|
|
|
|
changed = project.apply([
|
|
{'action': 'set_parameter', 'name': 'width', 'value': 1.8},
|
|
{'action': 'set_parameter', 'name': 'levels', 'value': 2},
|
|
])
|
|
assert changed['geometries'] != original['geometries']
|
|
updated = bridge.import_bundle(changed, scene)
|
|
changed_check = bridge.verify_bundle(changed, scene)
|
|
assert changed_check['passed'], changed_check
|
|
assert updated['created'] == 0 and updated['updated'] == 16 and len(updated['removed']) == 1
|
|
assert obj.as_pointer() == pointer and obj.modifiers.get(modifier.name).as_pointer() == modifier.as_pointer()
|
|
assert obj.material_slots[0].material == artist_material and marker.name in scene.objects
|
|
|
|
restored = project.travel('undo')
|
|
assert restored == original
|
|
bridge.import_bundle(restored, scene)
|
|
undo_check = bridge.verify_bundle(restored, scene)
|
|
assert undo_check['passed'], undo_check
|
|
assert obj.as_pointer() == pointer and obj.material_slots[0].material == artist_material
|
|
obj.modifiers.remove(modifier)
|
|
obj.material_slots[0].material = original_material
|
|
bpy.data.objects.remove(marker, do_unlink=True)
|
|
bpy.data.materials.remove(artist_material)
|
|
|
|
out = root / 'out'
|
|
write_json(out / 'braided_atrium.bundle.json', restored)
|
|
write_json(out / 'blender_verification.json', {
|
|
'blender_version': bpy.app.version_string,
|
|
'initial': original_check, 'edited': changed_check, 'undo': undo_check,
|
|
'changed_import': updated,
|
|
'preserved_object_identity_modifiers_materials_and_unrelated_objects': True,
|
|
'undo_restored_identical_bundle': True,
|
|
})
|
|
from mathutils import Vector
|
|
target = Vector((0, 0, 4.5))
|
|
rotation = (target - Vector((45, -55, 35))).to_track_quat('-Z', 'Y')
|
|
for screen in bpy.data.screens:
|
|
for area in screen.areas:
|
|
if area.type == 'VIEW_3D':
|
|
view = area.spaces.active
|
|
bridge.enum_set(view.shading, 'type', 'SOLID')
|
|
bridge.enum_set(view.shading, 'color_type', 'MATERIAL')
|
|
view.region_3d.view_location = target
|
|
view.region_3d.view_distance = 62
|
|
view.region_3d.view_rotation = rotation
|
|
bpy.ops.wm.save_as_mainfile(filepath=str(out / 'Braided_Atrium.blend'))
|
|
print('PASS: changed geometry, pruned instance, preserved artist work, exact undo, Blender parity.')
|