Add comprehensive tests for image processing and mask functionalities

- Introduced tests for color image handling, ensuring source preservation and premultiplied alpha usage.
- Implemented tests for brush stroke operations, validating segment boundaries and brush anti-aliasing.
- Added tests for frame anti-aliasing, confirming correct rendering behavior with various alpha values and depth settings.
- Created tests for frame projection, ensuring accurate overlap calculations and half-plane clipping.
- Developed tests for image premultiplied retention, verifying behavior during loading and packing processes.
- Added undo functionality tests for mask operations, ensuring single transaction behavior during edits.
This commit is contained in:
2026-09-05 21:33:11 +08:00
parent bbaa4bff46
commit 1994d38ccd
111 changed files with 7691 additions and 2341 deletions

View File

@@ -33,18 +33,18 @@ def input_names(group):
def grid_object(name):
vertices = [(0.0, float(y), float(z)) for z in range(3) for y in range(3)]
vertices = [(float(x), float(y), 0.0) for y in range(3) for x in range(3)]
faces = []
for z in range(2):
for y in range(2):
a = z * 3 + y
faces.extend(((a, a + 4, a + 1), (a, a + 3, a + 4)))
for y in range(2):
for x in range(2):
a = y * 3 + x
faces.extend(((a, a + 1, a + 4), (a, a + 4, a + 3)))
data = bpy.data.meshes.new(name)
data.from_pydata(vertices, (), faces)
uv_layer = data.uv_layers.new(name="UVMap")
for loop in data.loops:
coordinate = data.vertices[loop.vertex_index].co
uv_layer.data[loop.index].uv = (coordinate.y * 0.5, coordinate.z * 0.5)
uv_layer.data[loop.index].uv = (coordinate.x * 0.5, coordinate.y * 0.5)
obj = bpy.data.objects.new(name, data)
bpy.context.scene.collection.objects.link(obj)
return obj
@@ -56,7 +56,7 @@ def add_modifier(obj, shape, thickness):
modifier.node_group = group
for name, value in (
("Shape", shapes.CUTOUT_SHAPE_INDICES[shape]),
("Inward Axis", 1),
("Inward Axis", 0),
("Cleanup", 0.0),
("Smooth", 0.0),
("Smooth Iterations", 0),
@@ -116,6 +116,23 @@ def main():
)
for axis in ("-Z", "+X")
)
negative_z_link = next(
link
for link in wrapper.links
if link.to_node == axis_switch and link.to_socket.name == "-Z"
)
positive_x_link = next(
link
for link in wrapper.links
if link.to_node == axis_switch and link.to_socket.name == "+X"
)
assert positive_x_link.from_node.bl_idname == "GeometryNodeTransform"
assert any(
link.from_socket == negative_z_link.from_socket
and link.to_node == positive_x_link.from_node
and link.to_socket.name == "Geometry"
for link in wrapper.links
)
child_nodes = {
node.node_tree: node
for node in wrapper.nodes
@@ -355,7 +372,7 @@ def main():
assert len(result.vertices) == 34
assert len(result.polygons) == 40
side_faces = [
polygon for polygon in result.polygons if abs(polygon.normal.x) < 0.1
polygon for polygon in result.polygons if abs(polygon.normal.z) < 0.1
]
assert len(side_faces) == 24
finally:
@@ -373,7 +390,7 @@ def main():
evaluated, result = evaluated_mesh(balloon)
try:
initial_faces = len(result.polygons)
initial_extent = max(abs(vertex.co.x) for vertex in result.vertices)
initial_extent = max(abs(vertex.co.z) for vertex in result.vertices)
finally:
evaluated.to_mesh_clear()
set_modifier_input(
@@ -386,7 +403,7 @@ def main():
evaluated, result = evaluated_mesh(balloon)
try:
assert len(result.polygons) == initial_faces
extent = max(abs(vertex.co.x) for vertex in result.vertices)
extent = max(abs(vertex.co.z) for vertex in result.vertices)
assert abs(extent - initial_extent * 2.0) < 1e-5
finally:
evaluated.to_mesh_clear()
@@ -433,9 +450,9 @@ def main():
bpy.context.view_layer.update()
evaluated, result = evaluated_mesh(depth_balloon)
try:
x_values = [vertex.co.x for vertex in result.vertices]
assert abs(min(x_values) + 0.5) < 1e-5
assert abs(max(x_values)) < 1e-5
z_values = [vertex.co.z for vertex in result.vertices]
assert abs(min(z_values)) < 1e-5
assert abs(max(z_values) - 0.5) < 1e-5
finally:
evaluated.to_mesh_clear()
@@ -446,9 +463,9 @@ def main():
bpy.context.view_layer.update()
evaluated, result = evaluated_mesh(depth_balloon)
try:
x_values = [vertex.co.x for vertex in result.vertices]
assert abs(min(x_values) + 0.5) < 1e-5
assert abs(max(x_values)) < 1e-5
z_values = [vertex.co.z for vertex in result.vertices]
assert abs(min(z_values)) < 1e-5
assert abs(max(z_values) - 0.5) < 1e-5
finally:
evaluated.to_mesh_clear()
@@ -464,10 +481,10 @@ def main():
point_image.colorspace_settings.name = "Non-Color"
point_image.alpha_mode = "CHANNEL_PACKED"
pixels = []
for z in range(3):
for y in range(3):
depth = 7.0 if (y, z) == (0, 0) else 2.0 + y * 0.25
pixels.extend((-y * 0.5, -z * 0.5, depth, 0.0))
for y in range(3):
for x in range(3):
depth = 7.0 if (x, y) == (0, 0) else 2.0 + x * 0.25
pixels.extend((x * 0.5, -y * 0.5, depth, 0.0))
point_image.pixels.foreach_set(pixels)
for name, value in (
("Depth Image", point_image),
@@ -494,12 +511,12 @@ def main():
coordinates,
(
(
5.0 if (y, z) == (0, 0) else y * 0.25,
x * 0.5,
y * 0.5,
z * 0.5,
-5.0 if (x, y) == (0, 0) else -x * 0.25,
)
for z in range(3)
for y in range(3)
for x in range(3)
),
)
)