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:
@@ -6,7 +6,7 @@ from node_graph import expand_smooth
|
||||
|
||||
from anyimage.operators.cutout_tool.shape import (
|
||||
BALLOON_ATTRIBUTE_NAME,
|
||||
CUTOUT_AXIS_TO_SOURCE,
|
||||
CUTOUT_Z_TO_X,
|
||||
CUTOUT_NODE_GROUP_NAME,
|
||||
CUTOUT_NODE_GROUP_NAMES,
|
||||
CUTOUT_SHAPE_LABELS,
|
||||
@@ -178,20 +178,20 @@ def _extrude_layers(group, geometry, location):
|
||||
node = group.nodes.new("GeometryNodeExtrudeMesh")
|
||||
node.mode = "FACES"
|
||||
node.inputs["Individual"].default_value = False
|
||||
node.inputs["Offset"].default_value = (1.0, 0.0, 0.0)
|
||||
# Keep distinct front and back vertices before overriding their X positions.
|
||||
node.inputs["Offset"].default_value = (0.0, 0.0, 1.0)
|
||||
# Keep distinct front and back vertices before overriding their Z positions.
|
||||
node.inputs["Offset Scale"].default_value = 1.0
|
||||
node.location = location
|
||||
group.links.new(geometry, node.inputs["Mesh"])
|
||||
return node
|
||||
|
||||
|
||||
def _offset_geometry_x(group, geometry, x_value, location):
|
||||
def _offset_geometry_z(group, geometry, z_value, location):
|
||||
nodes = group.nodes
|
||||
links = group.links
|
||||
offset = nodes.new("ShaderNodeCombineXYZ")
|
||||
offset.location = location
|
||||
links.new(x_value, offset.inputs["X"])
|
||||
links.new(z_value, offset.inputs["Z"])
|
||||
set_position = nodes.new("GeometryNodeSetPosition")
|
||||
set_position.location = (location[0] + 200.0, location[1])
|
||||
links.new(geometry, set_position.inputs["Geometry"])
|
||||
@@ -199,15 +199,15 @@ def _offset_geometry_x(group, geometry, x_value, location):
|
||||
return set_position.outputs["Geometry"]
|
||||
|
||||
|
||||
def _set_layer_x(group, geometry, extrude, front_x, back_x, location):
|
||||
def _set_layer_z(group, geometry, extrude, front_z, back_z, location):
|
||||
nodes = group.nodes
|
||||
links = group.links
|
||||
choose_x = nodes.new("GeometryNodeSwitch")
|
||||
choose_x.input_type = "FLOAT"
|
||||
choose_x.location = (location[0], location[1] - 200.0)
|
||||
links.new(extrude.outputs["Top"], choose_x.inputs["Switch"])
|
||||
links.new(front_x, choose_x.inputs["False"])
|
||||
links.new(back_x, choose_x.inputs["True"])
|
||||
choose_z = nodes.new("GeometryNodeSwitch")
|
||||
choose_z.input_type = "FLOAT"
|
||||
choose_z.location = (location[0], location[1] - 200.0)
|
||||
links.new(extrude.outputs["Top"], choose_z.inputs["Switch"])
|
||||
links.new(front_z, choose_z.inputs["False"])
|
||||
links.new(back_z, choose_z.inputs["True"])
|
||||
position = nodes.new("GeometryNodeInputPosition")
|
||||
position.location = (location[0], location[1] + 150.0)
|
||||
separate = nodes.new("ShaderNodeSeparateXYZ")
|
||||
@@ -215,9 +215,9 @@ def _set_layer_x(group, geometry, extrude, front_x, back_x, location):
|
||||
links.new(position.outputs["Position"], separate.inputs["Vector"])
|
||||
combine = nodes.new("ShaderNodeCombineXYZ")
|
||||
combine.location = (location[0] + 400.0, location[1])
|
||||
links.new(choose_x.outputs["Output"], combine.inputs["X"])
|
||||
links.new(separate.outputs["X"], combine.inputs["X"])
|
||||
links.new(separate.outputs["Y"], combine.inputs["Y"])
|
||||
links.new(separate.outputs["Z"], combine.inputs["Z"])
|
||||
links.new(choose_z.outputs["Output"], combine.inputs["Z"])
|
||||
set_position = nodes.new("GeometryNodeSetPosition")
|
||||
set_position.location = (location[0] + 600.0, location[1])
|
||||
links.new(extrude.outputs["Mesh"], set_position.inputs["Geometry"])
|
||||
@@ -231,11 +231,11 @@ def _set_layer_x(group, geometry, extrude, front_x, back_x, location):
|
||||
flip_side = nodes.new("GeometryNodeFlipFaces")
|
||||
flip_side.location = (location[0] + 850.0, location[1] + 400.0)
|
||||
links.new(side.outputs["Selection"], flip_side.inputs["Mesh"])
|
||||
front = _offset_geometry_x(
|
||||
group, geometry, front_x, (location[0], location[1] - 450.0)
|
||||
front = _offset_geometry_z(
|
||||
group, geometry, front_z, (location[0], location[1] - 450.0)
|
||||
)
|
||||
back = _offset_geometry_x(
|
||||
group, geometry, back_x, (location[0], location[1] - 700.0)
|
||||
back = _offset_geometry_z(
|
||||
group, geometry, back_z, (location[0], location[1] - 700.0)
|
||||
)
|
||||
flip_back = nodes.new("GeometryNodeFlipFaces")
|
||||
flip_back.location = (location[0] + 500.0, location[1] - 700.0)
|
||||
@@ -254,11 +254,11 @@ def _set_layer_x(group, geometry, extrude, front_x, back_x, location):
|
||||
return merge.outputs["Geometry"]
|
||||
|
||||
|
||||
def _set_segmented_layer_x(
|
||||
def _set_segmented_layer_z(
|
||||
group,
|
||||
geometry,
|
||||
front_x,
|
||||
back_x,
|
||||
front_z,
|
||||
back_z,
|
||||
thickness,
|
||||
location,
|
||||
):
|
||||
@@ -310,7 +310,7 @@ def _set_segmented_layer_x(
|
||||
links.new(thickness, step.inputs[0])
|
||||
links.new(segment_limit.outputs[0], step.inputs[1])
|
||||
|
||||
front = _offset_geometry_x(group, geometry, front_x, (x, y + 100.0))
|
||||
front = _offset_geometry_z(group, geometry, front_z, (x, y + 100.0))
|
||||
repeat_output = nodes.new("GeometryNodeRepeatOutput")
|
||||
repeat_output.location = (x + 2380.0, y + 100.0)
|
||||
repeat_input = nodes.new("GeometryNodeRepeatInput")
|
||||
@@ -343,17 +343,17 @@ def _set_segmented_layer_x(
|
||||
links.new(split_extrude.outputs["Inverted"], repeat_output.inputs["Geometry"])
|
||||
links.new(join_sides.outputs["Geometry"], repeat_output.inputs["Sides"])
|
||||
|
||||
positioned_side = _offset_geometry_x(
|
||||
positioned_side = _offset_geometry_z(
|
||||
group,
|
||||
repeat_output.outputs["Sides"],
|
||||
front_x,
|
||||
front_z,
|
||||
(x + 2450.0, y + 350.0),
|
||||
)
|
||||
flip_side = nodes.new("GeometryNodeFlipFaces")
|
||||
flip_side.location = (x + 2850.0, y + 350.0)
|
||||
links.new(positioned_side, flip_side.inputs["Mesh"])
|
||||
|
||||
back = _offset_geometry_x(group, geometry, back_x, (x + 2450.0, y - 400.0))
|
||||
back = _offset_geometry_z(group, geometry, back_z, (x + 2450.0, y - 400.0))
|
||||
flip_back = nodes.new("GeometryNodeFlipFaces")
|
||||
flip_back.location = (x + 2850.0, y - 400.0)
|
||||
links.new(back, flip_back.inputs["Mesh"])
|
||||
@@ -370,7 +370,7 @@ def _set_segmented_layer_x(
|
||||
return merge.outputs["Geometry"]
|
||||
|
||||
|
||||
def _set_geometry_x(group, geometry, x_value, location):
|
||||
def _set_geometry_z(group, geometry, z_value, location):
|
||||
nodes = group.nodes
|
||||
links = group.links
|
||||
position = nodes.new("GeometryNodeInputPosition")
|
||||
@@ -380,9 +380,9 @@ def _set_geometry_x(group, geometry, x_value, location):
|
||||
links.new(position.outputs["Position"], separate.inputs["Vector"])
|
||||
combine = nodes.new("ShaderNodeCombineXYZ")
|
||||
combine.location = (location[0] + 400.0, location[1])
|
||||
links.new(x_value, combine.inputs["X"])
|
||||
links.new(separate.outputs["X"], combine.inputs["X"])
|
||||
links.new(separate.outputs["Y"], combine.inputs["Y"])
|
||||
links.new(separate.outputs["Z"], combine.inputs["Z"])
|
||||
links.new(z_value, combine.inputs["Z"])
|
||||
set_position = nodes.new("GeometryNodeSetPosition")
|
||||
set_position.location = (location[0] + 600.0, location[1])
|
||||
links.new(geometry, set_position.inputs["Geometry"])
|
||||
@@ -517,29 +517,19 @@ def _plane_depth(group, direction, reference_depth, location):
|
||||
position_components = nodes.new("ShaderNodeSeparateXYZ")
|
||||
position_components.location = (location[0] + 220.0, location[1] + 450.0)
|
||||
links.new(position.outputs["Position"], position_components.inputs["Vector"])
|
||||
direction_x = _math(
|
||||
nodes,
|
||||
"MULTIPLY",
|
||||
(location[0] + 440.0, location[1] + 850.0),
|
||||
)
|
||||
direction_x.inputs[1].default_value = -1.0
|
||||
links.new(normal_components.outputs["X"], direction_x.inputs[0])
|
||||
y_term = _math(nodes, "MULTIPLY", (location[0] + 440.0, location[1] + 500.0))
|
||||
x_term = _math(nodes, "MULTIPLY", (location[0] + 440.0, location[1] + 850.0))
|
||||
links.new(position_components.outputs["X"], x_term.inputs[0])
|
||||
links.new(normal_components.outputs["X"], x_term.inputs[1])
|
||||
y_term = _math(nodes, "MULTIPLY", (location[0] + 440.0, location[1] + 350.0))
|
||||
links.new(position_components.outputs["Y"], y_term.inputs[0])
|
||||
links.new(direction_x.outputs[0], y_term.inputs[1])
|
||||
z_term = _math(nodes, "MULTIPLY", (location[0] + 440.0, location[1] + 250.0))
|
||||
links.new(position_components.outputs["Z"], z_term.inputs[0])
|
||||
links.new(normal_components.outputs["Y"], z_term.inputs[1])
|
||||
links.new(normal_components.outputs["Y"], y_term.inputs[1])
|
||||
point_dot = _math(nodes, "ADD", (location[0] + 660.0, location[1] + 400.0))
|
||||
links.new(y_term.outputs[0], point_dot.inputs[0])
|
||||
links.new(z_term.outputs[0], point_dot.inputs[1])
|
||||
local_x = _math(nodes, "MULTIPLY", (location[0] + 660.0, location[1]))
|
||||
local_x.inputs[1].default_value = -1.0
|
||||
links.new(normal_components.outputs["Z"], local_x.inputs[0])
|
||||
links.new(x_term.outputs[0], point_dot.inputs[0])
|
||||
links.new(y_term.outputs[0], point_dot.inputs[1])
|
||||
divide = _math(nodes, "DIVIDE", (location[0] + 880.0, location[1] + 200.0))
|
||||
links.new(point_dot.outputs[0], divide.inputs[0])
|
||||
links.new(local_x.outputs[0], divide.inputs[1])
|
||||
plane = _math(nodes, "SUBTRACT", (location[0] + 1100.0, location[1] + 200.0))
|
||||
links.new(normal_components.outputs["Z"], divide.inputs[1])
|
||||
plane = _math(nodes, "ADD", (location[0] + 1100.0, location[1] + 200.0))
|
||||
links.new(reference_depth, plane.inputs[0])
|
||||
links.new(divide.outputs[0], plane.inputs[1])
|
||||
return plane.outputs[0]
|
||||
@@ -562,14 +552,14 @@ def _build_cutout(group, geometry, thickness):
|
||||
half = _math(nodes, "MULTIPLY", (-200.0, 50.0))
|
||||
half.inputs[1].default_value = 0.5
|
||||
links.new(thickness, half.inputs[0])
|
||||
front = _math(nodes, "MULTIPLY", (20.0, 0.0))
|
||||
front.inputs[1].default_value = -1.0
|
||||
links.new(half.outputs[0], front.inputs[0])
|
||||
shaped = _set_segmented_layer_x(
|
||||
back = _math(nodes, "MULTIPLY", (20.0, 0.0))
|
||||
back.inputs[1].default_value = -1.0
|
||||
links.new(half.outputs[0], back.inputs[0])
|
||||
shaped = _set_segmented_layer_z(
|
||||
group,
|
||||
geometry,
|
||||
front.outputs[0],
|
||||
half.outputs[0],
|
||||
back.outputs[0],
|
||||
thickness,
|
||||
(250.0, 300.0),
|
||||
)
|
||||
@@ -580,22 +570,22 @@ def _build_balloon(group, geometry, thickness):
|
||||
nodes = group.nodes
|
||||
links = group.links
|
||||
profile, _profile_factor = _profile_field(group, geometry, (-200.0, 0.0))
|
||||
front = _math(nodes, "MULTIPLY", (2400.0, 500.0))
|
||||
front.inputs[1].default_value = -1.0
|
||||
links.new(profile, front.inputs[0])
|
||||
front_scale = _math(nodes, "MULTIPLY", (2600.0, 500.0))
|
||||
links.new(front.outputs[0], front_scale.inputs[0])
|
||||
links.new(profile, front_scale.inputs[0])
|
||||
links.new(thickness, front_scale.inputs[1])
|
||||
back = _math(nodes, "MULTIPLY", (2600.0, 300.0))
|
||||
links.new(profile, back.inputs[0])
|
||||
links.new(thickness, back.inputs[1])
|
||||
negative_back = _math(nodes, "MULTIPLY", (2800.0, 300.0))
|
||||
negative_back.inputs[1].default_value = -1.0
|
||||
links.new(back.outputs[0], negative_back.inputs[0])
|
||||
extrude = _extrude_layers(group, geometry, (2400.0, 750.0))
|
||||
shaped = _set_layer_x(
|
||||
shaped = _set_layer_z(
|
||||
group,
|
||||
geometry,
|
||||
extrude,
|
||||
front_scale.outputs[0],
|
||||
back.outputs[0],
|
||||
negative_back.outputs[0],
|
||||
(2850.0, 650.0),
|
||||
)
|
||||
return _remove_zero_thickness(group, geometry, shaped, thickness, (4400.0, 650.0))
|
||||
@@ -637,25 +627,23 @@ def _build_depth_balloon(
|
||||
scaled_depth = _math(nodes, "MULTIPLY", (2150.0, -250.0))
|
||||
links.new(nonnegative_depth.outputs[0], scaled_depth.inputs[0])
|
||||
links.new(depth_scale, scaled_depth.inputs[1])
|
||||
front_depth = _math(nodes, "MULTIPLY", (2350.0, -250.0))
|
||||
front_depth.inputs[1].default_value = -1.0
|
||||
links.new(scaled_depth.outputs[0], front_depth.inputs[0])
|
||||
front_depth = scaled_depth.outputs[0]
|
||||
base_front = _math(nodes, "MULTIPLY", (2400.0, 500.0))
|
||||
links.new(profile, base_front.inputs[0])
|
||||
links.new(thickness, base_front.inputs[1])
|
||||
negate_front = _math(nodes, "MULTIPLY", (2600.0, 500.0))
|
||||
negate_front.inputs[1].default_value = -1.0
|
||||
links.new(base_front.outputs[0], negate_front.inputs[0])
|
||||
base_back = _math(nodes, "MULTIPLY", (2600.0, 300.0))
|
||||
links.new(profile, base_back.inputs[0])
|
||||
links.new(thickness, base_back.inputs[1])
|
||||
negate_back = _math(nodes, "MULTIPLY", (2800.0, 300.0))
|
||||
negate_back.inputs[1].default_value = -1.0
|
||||
links.new(base_back.outputs[0], negate_back.inputs[0])
|
||||
front_mix = nodes.new("ShaderNodeMix")
|
||||
front_mix.data_type = "FLOAT"
|
||||
front_mix.clamp_factor = True
|
||||
front_mix.location = (2600.0, 50.0)
|
||||
links.new(profile_factor, front_mix.inputs["Factor"])
|
||||
links.new(negate_front.outputs[0], front_mix.inputs["A"])
|
||||
links.new(front_depth.outputs[0], front_mix.inputs["B"])
|
||||
links.new(base_front.outputs[0], front_mix.inputs["A"])
|
||||
links.new(front_depth, front_mix.inputs["B"])
|
||||
mirrored_front = _math(nodes, "MULTIPLY", (2850.0, -150.0))
|
||||
mirrored_front.inputs[1].default_value = -1.0
|
||||
links.new(front_mix.outputs["Result"], mirrored_front.inputs[0])
|
||||
@@ -663,10 +651,10 @@ def _build_depth_balloon(
|
||||
back_choice.input_type = "FLOAT"
|
||||
back_choice.location = (3050.0, 100.0)
|
||||
links.new(double_sided, back_choice.inputs["Switch"])
|
||||
links.new(base_back.outputs[0], back_choice.inputs["False"])
|
||||
links.new(negate_back.outputs[0], back_choice.inputs["False"])
|
||||
links.new(mirrored_front.outputs[0], back_choice.inputs["True"])
|
||||
extrude = _extrude_layers(group, geometry, (2400.0, 750.0))
|
||||
shaped = _set_layer_x(
|
||||
shaped = _set_layer_z(
|
||||
group,
|
||||
geometry,
|
||||
extrude,
|
||||
@@ -674,7 +662,7 @@ def _build_depth_balloon(
|
||||
back_choice.outputs["Output"],
|
||||
(3300.0, 650.0),
|
||||
)
|
||||
front_only = _set_geometry_x(
|
||||
front_only = _set_geometry_z(
|
||||
group, geometry, front_mix.outputs["Result"], (3500.0, 100.0)
|
||||
)
|
||||
return _remove_zero_thickness(group, front_only, shaped, thickness, (4850.0, 600.0))
|
||||
@@ -708,22 +696,19 @@ def _build_depth_surface(
|
||||
separate.location = (3300.0, -100.0)
|
||||
links.new(scaled.outputs["Vector"], separate.inputs["Vector"])
|
||||
relative_depth = _math(nodes, "SUBTRACT", (3500.0, -100.0))
|
||||
links.new(separate.outputs["Z"], relative_depth.inputs[0])
|
||||
links.new(reference_depth, relative_depth.inputs[1])
|
||||
links.new(reference_depth, relative_depth.inputs[0])
|
||||
links.new(separate.outputs["Z"], relative_depth.inputs[1])
|
||||
front = _math(nodes, "MULTIPLY", (3700.0, -100.0))
|
||||
links.new(relative_depth.outputs[0], front.inputs[0])
|
||||
links.new(depth_scale, front.inputs[1])
|
||||
|
||||
negative_x = _math(nodes, "MULTIPLY", (3500.0, -350.0))
|
||||
negative_x.inputs[1].default_value = -1.0
|
||||
links.new(separate.outputs["X"], negative_x.inputs[0])
|
||||
negative_y = _math(nodes, "MULTIPLY", (3500.0, -600.0))
|
||||
negative_y.inputs[1].default_value = -1.0
|
||||
links.new(separate.outputs["Y"], negative_y.inputs[0])
|
||||
projected = nodes.new("ShaderNodeCombineXYZ")
|
||||
projected.location = (3700.0, -450.0)
|
||||
links.new(negative_x.outputs[0], projected.inputs["Y"])
|
||||
links.new(negative_y.outputs[0], projected.inputs["Z"])
|
||||
links.new(separate.outputs["X"], projected.inputs["X"])
|
||||
links.new(negative_y.outputs[0], projected.inputs["Y"])
|
||||
current_position = nodes.new("GeometryNodeInputPosition")
|
||||
current_position.location = (3500.0, -850.0)
|
||||
blend = nodes.new("ShaderNodeMix")
|
||||
@@ -738,9 +723,9 @@ def _build_depth_surface(
|
||||
links.new(blend.outputs["Result"], blended_axes.inputs["Vector"])
|
||||
surface_position = nodes.new("ShaderNodeCombineXYZ")
|
||||
surface_position.location = (4100.0, -200.0)
|
||||
links.new(front.outputs[0], surface_position.inputs["X"])
|
||||
links.new(blended_axes.outputs["X"], surface_position.inputs["X"])
|
||||
links.new(blended_axes.outputs["Y"], surface_position.inputs["Y"])
|
||||
links.new(blended_axes.outputs["Z"], surface_position.inputs["Z"])
|
||||
links.new(front.outputs[0], surface_position.inputs["Z"])
|
||||
project_geometry = nodes.new("GeometryNodeSetPosition")
|
||||
project_geometry.location = (4400.0, 400.0)
|
||||
links.new(geometry, project_geometry.inputs["Geometry"])
|
||||
@@ -754,20 +739,20 @@ def _build_depth_surface(
|
||||
stretch_limit,
|
||||
(4700.0, 400.0),
|
||||
)
|
||||
zero_x = nodes.new("ShaderNodeValue")
|
||||
zero_x.location = (7100.0, 100.0)
|
||||
zero_x.outputs["Value"].default_value = 0.0
|
||||
geometry = _set_geometry_x(
|
||||
zero_z = nodes.new("ShaderNodeValue")
|
||||
zero_z.location = (7100.0, 100.0)
|
||||
zero_z.outputs["Value"].default_value = 0.0
|
||||
geometry = _set_geometry_z(
|
||||
group,
|
||||
geometry,
|
||||
zero_x.outputs["Value"],
|
||||
zero_z.outputs["Value"],
|
||||
(7200.0, 400.0),
|
||||
)
|
||||
|
||||
back = _math(nodes, "ADD", (3900.0, -100.0))
|
||||
back = _math(nodes, "SUBTRACT", (3900.0, -100.0))
|
||||
links.new(front.outputs[0], back.inputs[0])
|
||||
links.new(thickness, back.inputs[1])
|
||||
shaped = _set_segmented_layer_x(
|
||||
shaped = _set_segmented_layer_z(
|
||||
group,
|
||||
geometry,
|
||||
front.outputs[0],
|
||||
@@ -775,7 +760,7 @@ def _build_depth_surface(
|
||||
thickness,
|
||||
(8300.0, 400.0),
|
||||
)
|
||||
front_only = _set_geometry_x(
|
||||
front_only = _set_geometry_z(
|
||||
group,
|
||||
geometry,
|
||||
front.outputs[0],
|
||||
@@ -812,7 +797,7 @@ def build_node_group(shape):
|
||||
depth_scale.description = "Scale the fitted-plane-corrected metric depth"
|
||||
double_sided = _bool_input(group, "Double Sided", False)
|
||||
double_sided.description = (
|
||||
"Mirror the complete front surface across the local YZ plane"
|
||||
"Mirror the complete front surface across the local XY plane"
|
||||
)
|
||||
elif shape == "DEPTH_SURFACE":
|
||||
depth_scale = _float_input(group, "Depth Scale", 1.0)
|
||||
@@ -970,7 +955,7 @@ def build_cutout_modifier_group(shape_groups):
|
||||
depth_scale.description = "Scale metric image depth"
|
||||
double_sided = _bool_input(group, "Double Sided", False)
|
||||
double_sided.description = (
|
||||
"Mirror the complete Depth Balloon front surface across the local YZ plane"
|
||||
"Mirror the complete Depth Balloon front surface across the local XY plane"
|
||||
)
|
||||
|
||||
iterations = _socket(group, "Smooth Iterations", "INPUT", "NodeSocketInt")
|
||||
@@ -1111,7 +1096,7 @@ def build_cutout_modifier_group(shape_groups):
|
||||
from mathutils import Matrix
|
||||
|
||||
orient = group.nodes.new("GeometryNodeTransform")
|
||||
orient.inputs["Rotation"].default_value = Matrix(CUTOUT_AXIS_TO_SOURCE).to_euler()
|
||||
orient.inputs["Rotation"].default_value = Matrix(CUTOUT_Z_TO_X).to_euler()
|
||||
orient.location = (3300.0, 350.0)
|
||||
group.links.new(geometry, orient.inputs["Geometry"])
|
||||
|
||||
@@ -1126,8 +1111,8 @@ def build_cutout_modifier_group(shape_groups):
|
||||
{"Inward Axis"},
|
||||
)
|
||||
group.links.new(axis_controls.outputs["Inward Axis"], axis_switch.inputs["Menu"])
|
||||
group.links.new(orient.outputs["Geometry"], axis_switch.inputs["-Z"])
|
||||
group.links.new(geometry, axis_switch.inputs["+X"])
|
||||
group.links.new(geometry, axis_switch.inputs["-Z"])
|
||||
group.links.new(orient.outputs["Geometry"], axis_switch.inputs["+X"])
|
||||
_shade_output(group, axis_switch.outputs["Output"], (3850.0, 550.0))
|
||||
group.color_tag = "GEOMETRY"
|
||||
group.description = (
|
||||
|
||||
@@ -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)
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user