- Introduced tests for boundary smoothing in `test_boundary_smoothing.py`, verifying that smoothing reduces stair-step artifacts while preserving boundary integrity. - Added tests for cutout boundary behavior in `test_cutout_boundary.py`, ensuring proper handling of boundary triangles and normal blending. - Created `test_temporary_attributes.py` to check the cleanup of temporary attributes across depth modifier branches, ensuring no warnings are raised. - Implemented point culling functionality in `test_validity.py`, confirming that invalid points are removed without affecting adjacent geometry. - Developed boundary smoothing logic in `boundary_smoothing.py`, allowing for depth smoothing while maintaining edge integrity. - Added cutout boundary management in `cutout_boundary.py`, including functions for removing boundary triangles and tapering thickness profiles. - Implemented validity checks in `validity.py` to ensure proper deletion of invalid vertices and associated wire edges.
62 lines
2.8 KiB
Python
62 lines
2.8 KiB
Python
"""Check the saved library's public inventory and persistence."""
|
|
import bpy
|
|
import pytest
|
|
from anyimage.common.node import load_node_group, node_asset_path
|
|
from tools.nodes.check import GEOMETRY_NAMES, SHADER_NAMES
|
|
|
|
|
|
def test_saved_asset_inventory():
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
with bpy.data.libraries.load(str(node_asset_path())) as (source, _):
|
|
assert set(source.node_groups) == GEOMETRY_NAMES | SHADER_NAMES
|
|
for name in sorted(GEOMETRY_NAMES | SHADER_NAMES):
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
node_group = load_node_group(name)
|
|
assert node_group.bl_idname == ("GeometryNodeTree" if name in GEOMETRY_NAMES else "ShaderNodeTree")
|
|
assert node_group.use_fake_user and node_group.users > 0
|
|
if name in GEOMETRY_NAMES:
|
|
assert node_group.is_modifier
|
|
if bpy.app.version >= (5, 0, 0):
|
|
assert node_group.library is not None
|
|
if name in {"O Image Depth Layer", "O Shadeless"}:
|
|
expected = ["Color", "Alpha", "Depth", "Bump Scale"] if name == "O Image Depth Layer" else ["Color", "Alpha"]
|
|
assert [item.name for item in node_group.interface.items_tree
|
|
if item.item_type == "SOCKET" and item.in_out == "INPUT"] == expected
|
|
|
|
|
|
@pytest.mark.parametrize("source", ["definition", "asset"])
|
|
def test_geometry_attribute_contract_includes_nested_groups(source):
|
|
from tools.nodes.build import build_node_groups
|
|
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
if source == "definition":
|
|
pending = build_node_groups()
|
|
else:
|
|
with bpy.data.libraries.load(str(node_asset_path())) as (library, target):
|
|
target.node_groups = list(library.node_groups)
|
|
pending = list(target.node_groups)
|
|
seen = set()
|
|
allowed = {
|
|
"UVMap": ("FLOAT2", "CORNER"),
|
|
"o_balloon": ("FLOAT", "POINT"),
|
|
".o_anyimage_depth_cut": ("BOOLEAN", "CORNER"),
|
|
}
|
|
while pending:
|
|
group = pending.pop()
|
|
if group in seen or group.bl_idname != "GeometryNodeTree":
|
|
continue
|
|
seen.add(group)
|
|
for node in group.nodes:
|
|
assert node.bl_idname != "GeometryNodeCaptureAttribute", group.name
|
|
if node.bl_idname == "GeometryNodeGroup" and node.node_tree:
|
|
pending.append(node.node_tree)
|
|
if node.bl_idname != "GeometryNodeStoreNamedAttribute":
|
|
continue
|
|
name = node.inputs["Name"].default_value
|
|
if name == "o_normal_scale":
|
|
assert node.data_type == "FLOAT" and node.domain in {"POINT", "FACE"}
|
|
else:
|
|
assert name in allowed, (group.name, name)
|
|
assert (node.data_type, node.domain) == allowed[name]
|
|
assert {group.name for group in seen} == GEOMETRY_NAMES
|