- Implement tests for image layer functionality including alpha curve and depth layer behavior. - Create tests for image plane evaluation and modifier input handling. - Add tests to verify the saved asset inventory and its persistence. - Introduce tests for the documentation command to ensure correct project version deployment. - Validate the extension manifest structure and required permissions. - Develop tests for the packaging process, ensuring correct platform handling and dependency management. - Enhance image depth plane group functionality with new split threshold input and surface processing.
114 lines
3.5 KiB
Python
114 lines
3.5 KiB
Python
"""Behavior checks for face separation and connected Depth Surface shells."""
|
|
|
|
from collections import Counter
|
|
import bpy
|
|
import numpy as np
|
|
|
|
|
|
from tests.support.nodes import CUTOUT_BUILDERS
|
|
|
|
|
|
def surface(*, step=6.0, size=1.0, resolution=2, wrapper=False):
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
group = CUTOUT_BUILDERS["DEPTH_SOLID"]()
|
|
# Two columns with a complete depth jump along their common boundary.
|
|
points = [
|
|
(x * size / resolution, y * size / resolution, 0)
|
|
for y in range(resolution + 1)
|
|
for x in range(2 * resolution + 1)
|
|
]
|
|
stride = 2 * resolution + 1
|
|
faces = [
|
|
(
|
|
y * stride + x,
|
|
y * stride + x + 1,
|
|
(y + 1) * stride + x + 1,
|
|
(y + 1) * stride + x,
|
|
)
|
|
for y in range(resolution)
|
|
for x in range(2 * resolution)
|
|
]
|
|
mesh = bpy.data.meshes.new("Step")
|
|
mesh.from_pydata(points, [], faces)
|
|
uv = mesh.uv_layers.new(name="UVMap")
|
|
for loop in mesh.loops:
|
|
x, y, _ = points[loop.vertex_index]
|
|
uv.data[loop.index].uv = (x / (2 * size), y / size)
|
|
obj = bpy.data.objects.new("Step", mesh)
|
|
bpy.context.collection.objects.link(obj)
|
|
image = bpy.data.images.new("Camera", width=64, height=32, float_buffer=True)
|
|
image.colorspace_settings.name = "Non-Color"
|
|
image.alpha_mode = "CHANNEL_PACKED"
|
|
yy, xx = np.mgrid[:32, :64]
|
|
pixels = np.ones((32, 64, 4), np.float32)
|
|
pixels[..., 0] = (xx + 0.5) / 32
|
|
pixels[..., 1] = -(yy + 0.5) / 32
|
|
pixels[..., 2] = 1 + (xx >= 32) * step
|
|
image.pixels.foreach_set(pixels.ravel())
|
|
modifier = obj.modifiers.new("Depth Surface", "NODES")
|
|
modifier.node_group = group
|
|
inputs = {
|
|
s.name: s.identifier
|
|
for s in group.interface.items_tree
|
|
if s.item_type == "SOCKET" and s.in_out == "INPUT"
|
|
}
|
|
|
|
def set_value(name, value):
|
|
modifier[inputs[name]] = value
|
|
obj.update_tag(refresh={"DATA"})
|
|
bpy.context.view_layer.update()
|
|
|
|
for name, value in (
|
|
("Depth Image", image),
|
|
("Uniform Scale", size),
|
|
("Reference Depth", size),
|
|
("Depth Scale", 1.0),
|
|
("Thickness", 0.0),
|
|
("Front Inflation", 0.0),
|
|
("Split Threshold", 0.0),
|
|
("Mode", 1),
|
|
("Smooth", 0),
|
|
):
|
|
set_value(name, value)
|
|
if wrapper:
|
|
set_value("Cleanup Threshold", 0.0)
|
|
set_value("Inward Axis", 0)
|
|
set_value("Smooth", 0)
|
|
return obj, set_value
|
|
|
|
|
|
def evaluated(obj):
|
|
result = obj.evaluated_get(bpy.context.evaluated_depsgraph_get())
|
|
mesh = result.to_mesh()
|
|
try:
|
|
return np.array([v.co[:] for v in mesh.vertices]), [
|
|
tuple(p.vertices) for p in mesh.polygons
|
|
]
|
|
finally:
|
|
result.to_mesh_clear()
|
|
|
|
|
|
def assert_closed(faces):
|
|
edges = Counter(
|
|
tuple(sorted((a, b))) for f in faces for a, b in zip(f, (*f[1:], f[0]))
|
|
)
|
|
assert edges and set(edges.values()) == {2}, Counter(edges.values())
|
|
|
|
|
|
def component_count(faces):
|
|
adjacency = {}
|
|
for face in faces:
|
|
for a, b in zip(face, (*face[1:], face[0])):
|
|
adjacency.setdefault(a, set()).add(b)
|
|
adjacency.setdefault(b, set()).add(a)
|
|
remaining = set(adjacency)
|
|
count = 0
|
|
while remaining:
|
|
count += 1
|
|
pending = [remaining.pop()]
|
|
while pending:
|
|
for neighbor in adjacency[pending.pop()] & remaining:
|
|
remaining.remove(neighbor)
|
|
pending.append(neighbor)
|
|
return count
|