feat: Update version to 0.13.0 in project files and adjust dependencies

This commit is contained in:
2026-09-02 19:50:55 +08:00
parent 8d279e9ab3
commit a6041cbe03
47 changed files with 1204 additions and 587 deletions

View File

@@ -60,6 +60,7 @@ def _create_cutout_shape(
depth_image=None,
depth_metadata=None,
selection_values=None,
inward_axis=cutout_object.CutoutInwardAxis.POSITIVE_X,
):
if bounds is None:
bounds = (0, 0, *tuple(int(value) for value in source.data.size))
@@ -90,6 +91,7 @@ def _create_cutout_shape(
base_shape,
depth_image=depth_image,
depth_metadata=depth_metadata,
inward_axis=inward_axis,
color_image=color_image,
)
@@ -123,6 +125,101 @@ def _depth_metadata(intrinsics, image_size, reference_depth):
}
def test_keep_original_places_and_activates_result_copy():
bpy.ops.wm.read_factory_settings(use_empty=True)
source_image = bpy.data.images.new("Crop Source", width=8, height=4, alpha=True)
result_image = bpy.data.images.new("Crop Result", width=4, height=2, alpha=True)
source = bpy.data.objects.new("Crop Source", None)
source.empty_display_type = "IMAGE"
source.data = source_image
source.empty_display_size = 3.0
source.empty_image_offset = (0.2, -0.1)
source.matrix_world = Matrix.Translation((1.0, 2.0, 3.0))
bpy.context.collection.objects.link(source)
source.select_set(True)
bpy.context.view_layer.objects.active = source
placed = image_data.place_empty_image_result(
bpy.context,
source,
result_image,
placement_bounds=(2, 1, 6, 3),
keep_original=True,
)
assert placed is not source
assert source.data == source_image
assert placed.data == result_image
assert placed.users_collection[:] == source.users_collection[:]
assert np.allclose(placed.matrix_world, source.matrix_world)
assert not source.select_get()
assert placed.select_get()
assert bpy.context.view_layer.objects.active == placed
def test_object_normal_image_follows_cutout_inward_axis():
bpy.ops.wm.read_factory_settings(use_empty=True)
image = bpy.data.images.new(
"Object Normal",
width=1,
height=1,
alpha=True,
float_buffer=True,
)
decoded = np.asarray((0.2, -0.4, 0.8), dtype=np.float32)
encoded = decoded * 0.5 + 0.5
image.pixels.foreach_set((*encoded, 0.3))
cutout_object.orient_object_normal_image(
image,
cutout_object.CutoutInwardAxis.NEGATIVE_Z,
)
actual = np.empty(4, dtype=np.float32)
image.pixels.foreach_get(actual)
expected = np.asarray((0.4, 0.8, -0.2), dtype=np.float32) * 0.5 + 0.5
assert np.allclose(actual[:3], expected, atol=1e-6)
assert np.isclose(actual[3], 0.3)
@pytest.mark.parametrize("shape", ("SURFACE", "BALLOON"))
def test_cutout_axes_produce_the_same_world_geometry(shape):
bpy.ops.wm.read_factory_settings(use_empty=True)
image = bpy.data.images.new("Axis Source", width=32, height=16, alpha=True)
source = bpy.data.objects.new("Axis Source", None)
source.empty_display_type = "IMAGE"
source.data = image
source.empty_display_size = 2.0
source.matrix_world = (
Matrix.Translation((2.0, -3.0, 1.0))
@ Matrix.Rotation(0.35, 4, "Y")
@ Matrix.Diagonal((1.5, 0.75, 2.0, 1.0))
)
bpy.context.collection.objects.link(source)
positive_x = _create_cutout_shape(
source,
shape,
8,
inward_axis=cutout_object.CutoutInwardAxis.POSITIVE_X,
)
negative_z = _create_cutout_shape(
source,
shape,
8,
inward_axis=cutout_object.CutoutInwardAxis.NEGATIVE_Z,
)
def world_positions(obj):
local = _evaluated_positions(obj)
return np.asarray([tuple(obj.matrix_world @ Vector(point)) for point in local])
expected = np.asarray(sorted(map(tuple, world_positions(positive_x))))
actual = np.asarray(sorted(map(tuple, world_positions(negative_z))))
assert np.allclose(actual, expected, atol=2e-6)
assert np.allclose(negative_z.matrix_world, source.matrix_world)
def test_depth_result_image_loads_server_vector_exr_and_keeps_data_name(tmp_path):
bpy.ops.wm.read_factory_settings(use_empty=True)
source_image = bpy.data.images.new("Source.png", width=2, height=2)
@@ -202,6 +299,7 @@ def test_cutout_modifier_wraps_four_menu_controlled_shape_groups():
assert _inputs(cutout) == [
"Geometry",
"Shape",
"Inward Axis",
"Thickness",
"Depth Scale",
"Double Sided",
@@ -1024,6 +1122,11 @@ def _add_cutout_modifier(obj, shape):
object_data.modifier_input_identifier(group, "Shape"),
cutout_shape.CUTOUT_SHAPE_INDICES[shape],
)
object_data.set_modifier_input(
modifier,
object_data.modifier_input_identifier(group, "Inward Axis"),
1,
)
object_data.set_modifier_input(
modifier,
object_data.modifier_input_identifier(group, "Cleanup"),