Add new functionality for image rectification and depth metadata handling

- Implemented a preview tool for rectifying images with interactive aspect controls in `preview.py`.
- Added tests for depth metadata loading to ensure consistent schema usage in `test_depth_metadata.py`.
- Developed comprehensive tests for cutout calibration processes in `test_cutout_calibration.py`, including stability checks and depth calibration.
- Created tests for frame compositing operations in `test_frame_compositing.py`, ensuring correct handling of depth and transparency.
- Introduced material slot inheritance functionality in `material_slots.py` to manage geometry material assignments.
- Built shared shader nodes for material processing in `shader.py`, including roughness and bump mapping setups.
This commit is contained in:
2026-09-12 19:20:06 +08:00
parent e8268504c2
commit 938d95db0f
175 changed files with 3812 additions and 6864 deletions

View File

@@ -7,20 +7,6 @@ from tests.support.blender import BlenderTestCase
class InputPreparationTest(BlenderTestCase):
def test_sequence_format_is_checked_before_copy(self):
with tempfile.TemporaryDirectory() as directory:
path = Path(directory) / "frame.0001.exr"
path.touch()
image = SimpleNamespace(source="SEQUENCE")
with (
patch.object(self.image_data, "image_path", return_value=path),
patch.object(self.image_data, "image_is_packed", return_value=False),
patch.object(self.image_data.tempfile, "mkdtemp") as create,
):
with self.assertRaisesRegex(RuntimeError, "Unsupported input format: .exr"):
self.image_data.prepare_image_input(image, None)
create.assert_not_called()
self.assertTrue(path.exists())
def test_packed_export_failure_removes_temporary_directory(self):
for failure in (OSError("disk full"), None):
@@ -34,21 +20,11 @@ class InputPreparationTest(BlenderTestCase):
self.assertEqual(image.file_format, "OPEN_EXR")
self.assertFalse(output.exists())
def test_sequence_copy_failure_preserves_originals(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
source = root / "frame.0001.png"
source.write_bytes(b"source")
output = root / "prepared"
output.mkdir()
with (
patch.object(self.image_data, "image_path", return_value=source),
patch.object(self.image_data, "image_is_packed", return_value=False),
patch.object(self.image_data, "collect_sequence_frames", return_value=[source]),
patch.object(self.image_data.tempfile, "mkdtemp", return_value=str(output)),
patch.object(self.image_data.shutil, "copy2", side_effect=OSError("disk full")),
):
with self.assertRaises(OSError):
self.image_data.prepare_image_input(SimpleNamespace(source="SEQUENCE"), None)
self.assertFalse(output.exists())
self.assertEqual(source.read_bytes(), b"source")
def test_animated_inputs_are_rejected_before_export(self):
for source in ("MOVIE", "SEQUENCE"):
with self.subTest(source=source), patch.object(self.image_data, "save_packed_image") as export:
image = SimpleNamespace(source=source, packed_file=object())
with self.assertRaisesRegex(RuntimeError, "Only still images"):
self.image_data.prepare_image_input(image, None)
export.assert_not_called()