Add tests for image layer, image plane, inventory, saved layout, commands, documentation, manifest, and packaging

- 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.
This commit is contained in:
2026-09-09 22:18:59 +08:00
parent 89087fc2e2
commit f48bbb3d05
97 changed files with 436 additions and 705 deletions

View File

@@ -3,9 +3,12 @@
import bpy
from ..common.nodes import group_input as _group_input, interface_socket as _interface_socket
from ..common.nodes import prepare_node_group
from ..common.nodes import prepare_node_group, float_input
from ..common.smoothing import expand_smooth
from ..common.depth_surface import project_depth_surface, thicken_depth_surface, remove_surface_attributes
from ..common.depth_surface import (
project_depth_surface, thicken_depth_surface, remove_surface_attributes,
split_depth_surface, store_surface_camera,
)
DEPTH_PLANE_NODE_GROUP_NAME = "O Image Depth Plane"
@@ -62,6 +65,7 @@ def build_image_depth_plane_group(image_plane_group):
validity_threshold.default_value = 0.9
validity_threshold.min_value, validity_threshold.max_value = 0.0, 1.0
validity_threshold.subtype = "FACTOR"
float_input(group, "Split Threshold", 0.0, maximum=1, subtype="FACTOR", parent=options)
data = group.interface.new_panel(name="Data", default_closed=True)
uniform_scale = _interface_socket(
group,
@@ -99,33 +103,6 @@ def build_image_depth_plane_group(image_plane_group):
texture.interpolation, texture.extension = "Linear", "EXTEND"
links.new(uv.outputs["Attribute"], texture.inputs["Vector"])
links.new(texture_input.outputs["Depth Image"], texture.inputs["Image"])
depth_input = _group_input(nodes, {"Reference Depth", "Depth Scale"})
surface = project_depth_surface(
group, plane.outputs["Geometry"], texture.outputs["Color"],
scale_input.outputs["Uniform Scale"], depth_input.outputs["Reference Depth"],
depth_input.outputs["Depth Scale"],
)
shell_input = _group_input(nodes, {"Thickness", "Normal Smooth"})
shell = thicken_depth_surface(
group, surface, shell_input.outputs["Thickness"],
normal_smooth=shell_input.outputs["Normal Smooth"],
)
positive = nodes.new("ShaderNodeMath")
positive.operation = "GREATER_THAN"
links.new(shell_input.outputs["Thickness"], positive.inputs[0])
positive.inputs[1].default_value = 0
choose = nodes.new("GeometryNodeSwitch")
choose.input_type = "GEOMETRY"
links.new(positive.outputs[0], choose.inputs["Switch"])
links.new(surface, choose.inputs["False"])
links.new(shell, choose.inputs["True"])
clean = remove_surface_attributes(group, choose.outputs["Output"])
# Preserve the repeated cap input independently of its display routing.
cap = nodes.new("NodeReroute")
links.new(nodes["Store Named Attribute.001"].outputs["Geometry"], cap.inputs[0])
links.new(cap.outputs[0], nodes["Join Geometry"].inputs["Geometry"])
projection_link = next(link for link in links if link.from_socket == plane.outputs["Geometry"])
projection_input = projection_link.to_socket
threshold_input = _group_input(nodes, {"Validity Threshold"})
channels = nodes.new("FunctionNodeSeparateColor")
channels.mode = "RGB"
@@ -147,7 +124,35 @@ def build_image_depth_plane_group(image_plane_group):
links.new(cull_controls.outputs["Valid Only"], cull.inputs["Switch"])
links.new(delete.outputs["Geometry"], cull.inputs["True"])
links.new(plane.outputs["Geometry"], cull.inputs["False"])
links.new(cull.outputs["Output"], projection_input)
split_input = _group_input(nodes, {"Split Threshold"})
geometry = split_depth_surface(
group, cull.outputs["Output"], texture_input.outputs["Depth Image"],
split_input.outputs["Split Threshold"], scale_input.outputs["Uniform Scale"],
)
geometry, camera = store_surface_camera(
group, geometry, texture.outputs["Color"], split_input.outputs["Split Threshold"],
)
depth_input = _group_input(nodes, {"Reference Depth", "Depth Scale"})
surface = project_depth_surface(
group, geometry, camera,
scale_input.outputs["Uniform Scale"], depth_input.outputs["Reference Depth"],
depth_input.outputs["Depth Scale"],
)
shell_input = _group_input(nodes, {"Thickness", "Normal Smooth"})
shell = thicken_depth_surface(
group, surface, shell_input.outputs["Thickness"],
normal_smooth=shell_input.outputs["Normal Smooth"],
)
positive = nodes.new("ShaderNodeMath")
positive.operation = "GREATER_THAN"
links.new(shell_input.outputs["Thickness"], positive.inputs[0])
positive.inputs[1].default_value = 0
choose = nodes.new("GeometryNodeSwitch")
choose.input_type = "GEOMETRY"
links.new(positive.outputs[0], choose.inputs["Switch"])
links.new(surface, choose.inputs["False"])
links.new(shell, choose.inputs["True"])
clean = remove_surface_attributes(group, choose.outputs["Output"])
geometry = expand_smooth(
group, clean, iterations_name="Smooth", weight_name="Smooth Weight",
)