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:
@@ -3,11 +3,50 @@ import importlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import Mock, patch
|
||||
from tests.support.blender import BlenderTestCase
|
||||
|
||||
|
||||
class CutoutOperatorsTest(BlenderTestCase):
|
||||
def test_cutout_gestures_start_on_empty_pick_and_lasso_finishes_on_release(self):
|
||||
viewport = importlib.import_module("anyimage.common.viewport")
|
||||
source = SimpleNamespace(name="Source", matrix_world="matrix", data=object())
|
||||
context = SimpleNamespace(
|
||||
area=SimpleNamespace(as_pointer=lambda: 1, tag_redraw=Mock()),
|
||||
region=SimpleNamespace(as_pointer=lambda: 2),
|
||||
workspace=SimpleNamespace(status_text_set=Mock()),
|
||||
window_manager=SimpleNamespace(modal_handler_add=Mock()),
|
||||
scene=SimpleNamespace(anyimage_settings=SimpleNamespace(mask_gesture="BRUSH")),
|
||||
)
|
||||
event = SimpleNamespace(type="LEFTMOUSE", value="PRESS", mouse_region_x=12, mouse_region_y=18)
|
||||
with (
|
||||
patch.object(viewport, "resolve_image_edit_click", return_value=(source, True)),
|
||||
patch.object(viewport, "is_animated_image", return_value=False),
|
||||
patch.object(viewport, "serialize_matrix", return_value="matrix"),
|
||||
patch.object(viewport, "active_view3d_tool_id", return_value=None),
|
||||
patch.object(self.fake_bpy.types, "SpaceView3D", SimpleNamespace(draw_handler_add=Mock()), create=True),
|
||||
):
|
||||
for gesture in ("LASSO", "POLYLINE"):
|
||||
with self.subTest(gesture=gesture):
|
||||
context.scene.anyimage_settings.cutout_gesture = gesture
|
||||
operator = self.cutout_main.SelectCutoutSelection()
|
||||
operator.report = Mock()
|
||||
self.assertEqual(operator.invoke(context, event), {"RUNNING_MODAL"})
|
||||
self.assertEqual(operator._path, [(12.0, 18.0)])
|
||||
self.assertEqual(operator.gesture, gesture)
|
||||
self.assertEqual(context.scene.anyimage_settings.mask_gesture, "BRUSH")
|
||||
operator._complete = Mock(return_value={"FINISHED"})
|
||||
release = SimpleNamespace(type="LEFTMOUSE", value="RELEASE", mouse_region_x=20, mouse_region_y=30)
|
||||
result = operator.modal(context, release)
|
||||
if gesture == "LASSO":
|
||||
self.assertEqual(result, {"FINISHED"})
|
||||
operator._complete.assert_called_once_with(context)
|
||||
else:
|
||||
operator._complete.assert_not_called()
|
||||
status = context.workspace.status_text_set.call_args.args[0]
|
||||
self.assertIn("Polyline", status)
|
||||
self.assertIn("Backspace", status)
|
||||
|
||||
def test_flat_and_solid_without_ai_build_locally(self):
|
||||
import numpy as np
|
||||
|
||||
@@ -29,6 +68,7 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
{"points": [[1, 1], [9, 1], [9, 9], [1, 9]]}
|
||||
),
|
||||
shape=shape,
|
||||
gesture="POLYLINE",
|
||||
point_spacing=32,
|
||||
alpha_threshold=0.25,
|
||||
fine_outline=False,
|
||||
@@ -43,7 +83,7 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
return_value=source,
|
||||
),
|
||||
patch.object(
|
||||
self.cutout_main, "video_total_frames", return_value=1
|
||||
self.cutout_main, "is_animated_image", return_value=False
|
||||
),
|
||||
patch.object(
|
||||
self.cutout_main, "image_rgba", return_value=source_rgba
|
||||
@@ -91,10 +131,10 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
32.0,
|
||||
selection_mask.values,
|
||||
selection_mask.bounds,
|
||||
inward_axis="NEGATIVE_Z",
|
||||
alpha_threshold=0.25,
|
||||
fine_outline=False,
|
||||
color_image="Color",
|
||||
gesture="POLYLINE",
|
||||
)
|
||||
|
||||
|
||||
@@ -131,7 +171,7 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
"require_image_empty",
|
||||
return_value=source,
|
||||
),
|
||||
patch.object(self.cutout_main, "video_total_frames", return_value=1),
|
||||
patch.object(self.cutout_main, "is_animated_image", return_value=False),
|
||||
patch.object(
|
||||
self.cutout_main,
|
||||
"image_rgba",
|
||||
@@ -212,7 +252,7 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
"require_image_empty",
|
||||
return_value=source,
|
||||
),
|
||||
patch.object(self.cutout_main, "video_total_frames", return_value=1),
|
||||
patch.object(self.cutout_main, "is_animated_image", return_value=False),
|
||||
patch.object(self.cutout_main, "image_rgba"),
|
||||
patch.object(
|
||||
self.cutout_main,
|
||||
@@ -278,9 +318,6 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
self.assertTrue(parameters["generate_depth"])
|
||||
self.assertEqual(parameters["alpha_threshold"], 0.25)
|
||||
self.assertEqual(parameters["normal_mode"], "OBJECT")
|
||||
self.assertNotIn("polygon", parameters)
|
||||
self.assertNotIn("shape", parameters)
|
||||
self.assertNotIn("normal_analysis", parameters)
|
||||
|
||||
|
||||
def test_cutout_geometry_settings_use_configured_moge(self):
|
||||
@@ -339,12 +376,12 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
self.assertEqual(
|
||||
layout.events,
|
||||
[
|
||||
setup,
|
||||
("prop", "cutout_generate_normal", False),
|
||||
("prop", "cutout_gesture", True),
|
||||
("prop", "cutout_mesh_detail", True),
|
||||
("prop", "cutout_fine_outline", True),
|
||||
("prop", "cutout_alpha_threshold", True),
|
||||
("prop", "cutout_inward_axis", True),
|
||||
setup,
|
||||
("prop", "cutout_generate_normal", False),
|
||||
],
|
||||
)
|
||||
|
||||
@@ -356,7 +393,7 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
self.assertTrue(all(event[2] for event in layout.events))
|
||||
|
||||
|
||||
def test_cutout_ai_response_reuses_bounds_color_and_lasso(self):
|
||||
def test_cutout_ai_response_reuses_bounds_color_and_gesture_snapshot(self):
|
||||
import numpy as np
|
||||
|
||||
source = SimpleNamespace(data=SimpleNamespace())
|
||||
@@ -375,6 +412,7 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
operator.input_path = __file__
|
||||
operator.color_path = __file__
|
||||
operator.shape = "FLAT"
|
||||
operator.gesture = "POLYLINE"
|
||||
operator.point_spacing = 32
|
||||
operator.generate_normal = True
|
||||
operator._selection_mask = selection_mask
|
||||
@@ -397,7 +435,10 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
) as color_result,
|
||||
patch.object(self.cutout_main, "create_cutout_shape") as create_shape,
|
||||
):
|
||||
message = operator.response(SimpleNamespace(), result)
|
||||
context = SimpleNamespace(scene=SimpleNamespace(
|
||||
anyimage_settings=SimpleNamespace(cutout_gesture="LASSO")
|
||||
))
|
||||
message = operator.response(context, result)
|
||||
|
||||
color_result.assert_called_once_with(
|
||||
__file__,
|
||||
@@ -405,6 +446,7 @@ class CutoutOperatorsTest(BlenderTestCase):
|
||||
)
|
||||
|
||||
self.assertEqual(message, "Flat is ready")
|
||||
self.assertEqual(create_shape.call_args.kwargs["gesture"], "POLYLINE")
|
||||
content_values = create_shape.call_args.args[4]
|
||||
np.testing.assert_array_equal(content_values, pure_values)
|
||||
self.assertEqual(create_shape.call_args.args[5], selection_mask.bounds)
|
||||
|
||||
Reference in New Issue
Block a user