mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Tests: Add UI test for common mask operations in sculpt mode
This test exercises a common pair of mask operations in sculpt mode, a dense mesh is created, the sculpt expand operator is used to mask a region starting from the center, and then this region is inverted. Pull Request: https://projects.blender.org/blender/blender/pulls/151875
This commit is contained in:
parent
9387f42887
commit
ee680df0b2
2 changed files with 79 additions and 0 deletions
|
|
@ -1492,6 +1492,7 @@ if(WITH_UI_TESTS)
|
|||
# list explicitly so changes bisecting/updated are sure to re-run CMake.
|
||||
set(_ui_tests
|
||||
test_sculpt.asset_shelf_brush_selection
|
||||
test_sculpt.mask_expand_and_invert
|
||||
test_tools.sculpt_mode_toolbar
|
||||
test_undo.compositor_make_group
|
||||
test_undo.text_editor_edit_mode_mix
|
||||
|
|
|
|||
|
|
@ -86,3 +86,81 @@ def asset_shelf_brush_selection():
|
|||
import bpy
|
||||
current_brush = bpy.context.tool_settings.sculpt.brush
|
||||
t.assertEqual(current_brush.name, "Blob")
|
||||
|
||||
|
||||
def _view3d_startup_area_maximized(e):
|
||||
"""
|
||||
Set the 3D viewport and set the area full-screen so no other regions.
|
||||
"""
|
||||
yield e.shift.f5() # 3D Viewport.
|
||||
yield e.ctrl.alt.space() # Full-screen.
|
||||
yield e.a() # Select all.
|
||||
yield e.delete().ret() # Delete all.
|
||||
|
||||
|
||||
def _subdivide_mesh(e, times):
|
||||
yield e.tab() # Enter Edit mode.
|
||||
for i in range(times):
|
||||
yield e.ctrl.e().d() # Subdivide.
|
||||
yield e.tab() # Leave Edit mode.
|
||||
|
||||
|
||||
def _cursor_motion_data_x(e, start_position, pixels):
|
||||
for x in range(pixels // 10):
|
||||
position = (start_position[0] + x * 10, start_position[1])
|
||||
yield e.cursor_position_set(*position, move=True)
|
||||
|
||||
|
||||
def _num_fully_masked_vertices():
|
||||
import bpy
|
||||
import numpy as np
|
||||
|
||||
mesh = bpy.context.object.data
|
||||
|
||||
if not mesh.attributes.get('.sculpt_mask'):
|
||||
return 0
|
||||
|
||||
mask_attr = mesh.attributes['.sculpt_mask']
|
||||
|
||||
num_vertices = mesh.attributes.domain_size('POINT')
|
||||
|
||||
mask_data = np.zeros(num_vertices, dtype=np.float32)
|
||||
mask_attr.data.foreach_get('value', mask_data)
|
||||
|
||||
return np.count_nonzero(mask_data == 1.0)
|
||||
|
||||
|
||||
def mask_expand_and_invert():
|
||||
e, t = _test_vars(window := _test_window())
|
||||
yield from _view3d_startup_area_maximized(e)
|
||||
|
||||
yield from _call_menu(e, "Add -> Mesh -> Monkey")
|
||||
yield e.numpad_period() # View monkey
|
||||
|
||||
yield from _subdivide_mesh(e, 3)
|
||||
|
||||
yield e.ctrl.tab().s() # Sculpt via pie menu.
|
||||
|
||||
area = _window_area_get_by_type(window, 'VIEW_3D')
|
||||
position = (area.x + area.width // 2, area.y + area.height // 2)
|
||||
yield e.cursor_position_set(*position, move=True) # Move mouse to center
|
||||
|
||||
yield e.shift.a() # Expand operator
|
||||
|
||||
yield from _cursor_motion_data_x(e, position, 200)
|
||||
e.leftmouse.tap()
|
||||
yield
|
||||
|
||||
initial_masked_verts = _num_fully_masked_vertices()
|
||||
t.assertEqual(initial_masked_verts, 8548)
|
||||
|
||||
yield e.a() # Mask pie menu
|
||||
yield e.i() # Invert
|
||||
|
||||
inverted_masked_verts = _num_fully_masked_vertices()
|
||||
t.assertEqual(inverted_masked_verts, 22598)
|
||||
|
||||
import bpy
|
||||
mesh = bpy.context.object.data
|
||||
total_verts = mesh.attributes.domain_size('POINT')
|
||||
t.assertEqual(initial_masked_verts + inverted_masked_verts, total_verts)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue