88#define SCULPT_EXPAND_VERTEX_NONE -1
91#define EXPAND_ACTIVE_COMPONENT_NONE -1
96#define SCULPT_EXPAND_TEXTURE_DISTORTION_STEP 0.01f
103#define SCULPT_EXPAND_LOOP_THRESHOLD 0.00001f
110#define SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY 300
144 const Cache &expand_cache,
161 const Cache &expand_cache,
186 const Cache &expand_cache,
201 expand_cache.
scene, brush, mtex, position, rgba, 0, ss.
tex_pool);
219 if (!mask_tex->
tex) {
228 const Cache &expand_cache,
233 const float loop_len = (max_falloff_factor / expand_cache.
loop_count) +
238 const float falloff_factor =
fmod(vertex_falloff_factor, loop_len);
240 return falloff_factor < active_factor;
252 const Cache &expand_cache,
255 if (!hide_poly.
is_empty() && hide_poly[face]) {
264 if (expand_cache.
invert) {
281 const float falloff_factor =
fmod(expand_cache.
face_falloff[face], loop_len);
282 enabled = falloff_factor < active_factor;
291 if (expand_cache.
invert) {
303 const Cache &expand_cache,
312 const float loop_len = (max_falloff_factor / expand_cache.
loop_count) +
317 const float falloff_factor =
fmod(vertex_falloff_factor, loop_len);
319 float linear_falloff;
321 if (expand_cache.
invert) {
324 BLI_assert((loop_len - active_factor) != 0.0f);
325 linear_falloff = (falloff_factor - active_factor) / (loop_len - active_factor);
328 linear_falloff = 1.0f - (falloff_factor / active_factor);
332 return linear_falloff;
346 const Cache &expand_cache)
352 if (!expand_cache.
invert) {
353 enabled_verts.
fill(
true);
355 return enabled_verts;
359 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
368 for (
const int vert : range) {
369 if (!hide_vert.
is_empty() && hide_vert[vert]) {
375 if (expand_cache.
snap) {
377 vert_to_face_map, face_sets, vert);
381 enabled_verts[vert].set(
388 const Mesh &base_mesh = *
static_cast<const Mesh *
>(
object.data);
394 const Span<int> grid_to_face_map = subdiv_ccg.grid_to_face_map;
398 for (
const int grid :
IndexRange(subdiv_ccg.grids_num)) {
400 const int face_set = face_sets[grid_to_face_map[grid]];
402 const int vert = start + offset;
406 if (expand_cache.
snap) {
410 enabled_verts[vert].set(
426 if (expand_cache.
snap) {
437 if (expand_cache.
invert) {
440 return enabled_verts;
450 const bool use_mesh_boundary,
461 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
470 faces, corner_verts, vert_to_face_map, hide_poly, vert, neighbors))
472 if (!enabled_verts[neighbor]) {
477 if (use_mesh_boundary &&
487 const Mesh &base_mesh = *
static_cast<const Mesh *
>(
object.data);
489 const Span<int> corner_verts = base_mesh.corner_verts();
498 if (!enabled_verts[neighbor.
to_index(key)]) {
503 if (use_mesh_boundary &&
560 const int original_vert,
561 const float max_distance)
565 const bool use_original =
false;
568 symm_verts.
append(original_vert);
570 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
575 const float3 location = positions[original_vert];
576 for (
int symm_it = 1; symm_it <= symm; symm_it++) {
582 pbvh, positions, hide_vert, symm_location, max_distance, use_original);
586 symm_verts.
append(*nearest);
589 std::sort(symm_verts.
begin(), symm_verts.
end());
594 const int original_vert,
595 const float max_distance)
599 const bool use_original =
false;
602 symm_verts.
append(original_vert);
608 const float3 location = positions[original_vert];
609 for (
int symm_it = 1; symm_it <= symm; symm_it++) {
615 pbvh, subdiv_ccg, symm_location, max_distance, use_original);
619 symm_verts.
append(nearest->to_index(key));
622 std::sort(symm_verts.
begin(), symm_verts.
end());
627 const int original_vert,
628 const float max_distance)
632 const bool use_original =
false;
635 symm_verts.
append(original_vert);
640 const float3 location = original_bm_vert->
co;
641 for (
int symm_it = 1; symm_it <= symm; symm_it++) {
647 pbvh, symm_location, max_distance, use_original);
654 std::sort(symm_verts.
begin(), symm_verts.
end());
660 const int original_vert,
661 const float max_distance)
664 switch (pbvh.
type()) {
698 if (ss.edge_to_face_map.is_empty()) {
700 faces, corner_edges, edges.
size(), ss.edge_to_face_offsets, ss.edge_to_face_indices);
702 if (ss.vert_to_edge_map.is_empty()) {
704 edges,
mesh.verts_num, ss.vert_to_edge_offsets, ss.vert_to_edge_indices);
722 const int initial_vert)
746 switch (pbvh.
type()) {
750 flood.
execute(ob, vert_to_face_map, [&](
const int from_vert,
const int to_vert) {
751 distances[to_vert] = distances[from_vert] + 1.0f;
769 const int from_vert = from.
to_index(key);
770 const int to_vert = to.
to_index(key);
772 distances[to_vert] = distances[from_vert];
775 distances[to_vert] = distances[from_vert] + 1.0f;
789 distances[to_vert] = distances[from_vert] + 1.0f;
799 const int initial_vert)
819 const float edge_sensitivity,
820 const int blur_steps)
828 switch (pbvh.
type()) {
834 const float3 orig_normal = vert_normals[vert];
837 flood.
execute(ob, vert_to_face_map, [&](
const int from_vert,
const int to_vert) {
838 const float3 &from_normal = vert_normals[from_vert];
839 const float3 &to_normal = vert_normals[to_vert];
840 const float from_edge_factor = edge_factors[from_vert];
841 const float dist =
math::dot(orig_normal, to_normal) *
842 powf(from_edge_factor, edge_sensitivity);
843 edge_factors[to_vert] =
math::dot(to_normal, from_normal) * from_edge_factor;
844 dists[to_vert] = std::clamp(dist, 0.0f, 1.0f);
860 const int from_vert = from.
to_index(key);
861 const int to_vert = to.
to_index(key);
863 edge_factors[to_vert] = edge_factors[from_vert];
864 dists[to_vert] = dists[from_vert];
869 const float from_edge_factor = edge_factors[from_vert];
870 const float dist =
math::dot(orig_normal, to_normal) *
871 powf(from_edge_factor, edge_sensitivity);
872 edge_factors[to_vert] =
math::dot(to_normal, from_normal) * from_edge_factor;
873 dists[to_vert] = std::clamp(dist, 0.0f, 1.0f);
882 const float3 orig_normal = orig_vert->
no;
885 const float3 from_normal = from_bm_vert->
no;
886 const float3 to_normal = to_bm_vert->
no;
889 const float from_edge_factor = edge_factors[from_vert];
890 const float dist =
math::dot(orig_normal, to_normal) *
891 powf(from_edge_factor, edge_sensitivity);
892 edge_factors[to_vert] =
math::dot(to_normal, from_normal) * from_edge_factor;
893 dists[to_vert] = std::clamp(dist, 0.0f, 1.0f);
902 for (
int i = 0;
i < totvert;
i++) {
903 dists[
i] = 1.0 - dists[
i];
923 switch (pbvh.
type()) {
931 for (const int vert : range) {
932 float dist = std::numeric_limits<float>::max();
933 for (const float3 &location : locations) {
934 dist = std::min(dist, math::distance(positions[vert], location));
947 locations[
i] = positions[symm_verts[
i]];
951 for (const int vert : range) {
952 float dist = std::numeric_limits<float>::max();
953 for (const float3 &location : locations) {
954 dist = std::min(dist, math::distance(positions[vert], location));
965 for (
const int i : symm_verts.index_range()) {
970 for (const int vert : range) {
971 float dist = std::numeric_limits<float>::max();
972 for (const float3 &location : locations) {
973 dist = std::min(dist,
974 math::distance(float3(BM_vert_at_index(&bm, vert)->co), location));
993 const int inititial_vert)
998 for (
const int vert : symm_verts) {
1002 for (
const int vert :
boundary->verts) {
1003 boundary_verts[vert].set();
1044 std::queue<int> queue;
1045 for (
const int vert : symm_verts) {
1047 visited_verts[vert].set();
1050 if (queue.empty()) {
1055 while (!queue.empty()) {
1056 const int next_vert = queue.front();
1059 for (
const int face : vert_to_face_map[next_vert]) {
1060 for (
const int vert : corner_verts.
slice(
faces[face])) {
1061 if (visited_verts[vert]) {
1064 dists[vert] = dists[next_vert] + 1.0f;
1065 visited_verts[vert].set();
1084 std::numeric_limits<float>::lowest(),
1086 for (
const int vert : range) {
1097 [](
const float a,
const float b) {
return std::max(a,
b); });
1109 faces.index_range(),
1111 std::numeric_limits<float>::lowest(),
1113 for (const int face : range) {
1114 if (expand_cache.face_falloff[face] == FLT_MAX) {
1117 if (!is_face_in_active_component(object, faces, corner_verts, expand_cache, face)) {
1120 max = std::max(max, expand_cache.face_falloff[face]);
1124 [](
const float a,
const float b) {
return std::max(a,
b); });
1139 for (const int face : range) {
1141 for (const int corner : faces[face]) {
1142 const int grid_loop_index = corner * key.grid_area;
1143 for (int g = 0; g < key.grid_area; g++) {
1144 accum += expand_cache.vert_falloff[grid_loop_index + g];
1147 expand_cache.face_falloff[face] = accum / (faces[face].size() * key.grid_area);
1158 for (const int face : range) {
1159 const Span<int> face_verts = corner_verts.slice(faces[face]);
1161 for (const int vert : face_verts) {
1162 accum += expand_cache.vert_falloff[vert];
1164 expand_cache.face_falloff[face] = accum / face_verts.size();
1199 Cache &expand_cache,
1217 Cache &expand_cache,
1236 Cache &expand_cache,
1251 switch (recursion_type) {
1276 Cache &expand_cache,
1277 const int active_face_set,
1278 const bool internal_falloff)
1285 switch (pbvh.
type()) {
1293 for (
const int vert : range) {
1295 vert_to_face_map, face_sets, vert, active_face_set);
1297 vert_to_face_map, face_sets, vert);
1303 const Mesh &base_mesh = *
static_cast<const Mesh *
>(ob.
data);
1305 const Span<int> corner_verts = base_mesh.corner_verts();
1313 for (
const int vert : range) {
1316 subdiv_ccg, face_sets, coord.
grid_index, active_face_set);
1318 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, coord);
1328 for (
const int vert : range) {
1339 for (
int i = 0;
i < totvert;
i++) {
1340 if (!vert_has_unique_face_set[
i]) {
1343 if (!vert_has_face_set[
i]) {
1346 enabled_verts[
i].set();
1356 if (internal_falloff) {
1357 for (
int i = 0;
i < totvert;
i++) {
1358 if (!(vert_has_face_set[
i] && vert_has_unique_face_set[
i])) {
1365 for (
int i = 0;
i < totvert;
i++) {
1369 const float additional_falloff =
fabsf(min_factor);
1370 for (
int i = 0;
i < totvert;
i++) {
1375 for (
int i = 0;
i < totvert;
i++) {
1376 if (!vert_has_face_set[
i]) {
1389 Cache &expand_cache,
1399 switch (falloff_type) {
1453 Cache &expand_cache)
1459 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
1464 const bool prev_snap_state = expand_cache.
snap;
1465 const bool prev_invert_state = expand_cache.
invert;
1466 expand_cache.
snap =
false;
1467 expand_cache.
invert =
false;
1471 for (
const int i :
faces.index_range()) {
1476 for (
const int i :
faces.index_range()) {
1478 const bool any_disabled = std::any_of(face_verts.
begin(),
1480 [&](
const int vert) { return !enabled_verts[vert]; });
1487 expand_cache.
snap = prev_snap_state;
1488 expand_cache.
invert = prev_invert_state;
1506 *
static_cast<Mesh *
>(
object.
data));
1535 color_attribute.
span);
1539 color_attribute.
finish();
1548 switch (pbvh.
type()) {
1552 attributes.
remove(
".sculpt_mask");
1553 attributes.
add<
float>(
".sculpt_mask",
1563 for (
const int i :
mask.index_range()) {
1583 switch (expand_cache.
target) {
1628 for (
const int i :
verts.index_range()) {
1629 const int vert =
verts[
i];
1630 const bool enabled = enabled_verts[vert];
1644 if (expand_cache.
invert) {
1666 bool any_changed =
false;
1667 for (
const int grid : node.
grids()) {
1669 const float initial_mask = masks[vert];
1677 if (enabled_verts[vert]) {
1685 if (expand_cache.
invert) {
1693 if (new_mask == initial_mask) {
1697 masks[vert] =
clamp_f(new_mask, 0.0f, 1.0f);
1709 const int mask_offset,
1714 bool any_changed =
false;
1725 if (enabled_verts[vert_index]) {
1733 if (expand_cache.
invert) {
1741 if (new_mask == initial_mask) {
1765 for (
const int f : face_sets.
span.index_range()) {
1767 object,
faces, corner_verts, hide_poly, face_sets.
span, expand_cache, f);
1804 bool any_changed =
false;
1806 for (
const int i :
verts.index_range()) {
1807 const int vert =
verts[
i];
1808 if (!hide_vert.
is_empty() && hide_vert[vert]) {
1813 faces, corner_verts, vert_to_face_map, color_attribute.
span, color_attribute.
domain, vert);
1817 if (enabled_verts[vert]) {
1824 if (!
mask.is_empty()) {
1837 if (initial_color == final_color) {
1847 color_attribute.
span);
1879 for (
int i = 0;
i < totvert;
i++) {
1881 faces, corner_verts, vert_to_face_map, colors, color_attribute.
domain,
i);
1895 for (
const int i :
faces.index_range()) {
1938 switch (expand_cache.
target) {
1940 switch (pbvh.
type()) {
2012 mesh.active_color_attribute);
2014 color_attribute.finish();
2032 return std::nullopt;
2045 const bool initial_invert_state = expand_cache.
invert;
2046 expand_cache.
invert =
false;
2056 ob, enabled_verts, use_mesh_boundary, memory);
2060 expand_cache.
invert = initial_invert_state;
2072 const float3 &position = positions[vert];
2089 const float3 position = positions[vert];
2151 Cache &expand_cache,
2152 const int initial_vertex)
2163 int valid_index = 0;
2164 for (
int symm_it = 0; symm_it <= symm; symm_it++) {
2169 symm_verts[valid_index]);
2180 Cache &expand_cache,
2181 const float mval[2])
2187 if (!initial_vert) {
2196 if (last_active_vert_index == -1) {
2199 initial_vert = last_active_vert_index;
2231 Cache &expand_cache)
2234 const float mval_fl[2] = {float(event->
mval[0]), float(event->
mval[1])};
2307 const float mval_fl[2] = {float(event->
mval[0]), float(event->
mval[1])};
2313 switch (event->
val) {
2338 if (expand_cache.
snap) {
2339 expand_cache.
snap =
false;
2345 expand_cache.
snap =
true;
2352 if (expand_cache.
move) {
2353 expand_cache.
move =
false;
2361 expand_cache.
move =
true;
2437 if (mask_tex->
tex ==
nullptr) {
2440 "Active brush does not contain any texture to distort the expand boundary");
2446 "Texture mapping not set to 3D, results may be unpredictable");
2462 if (expand_cache.
move) {
2467 if (expand_cache.
snap) {
2494 bool all_same_id =
true;
2495 for (
const int i :
faces.index_range()) {
2499 if (r_face_sets[
i] != delete_id) {
2500 all_same_id =
false;
2514 for (
const int i :
faces.index_range()) {
2515 if (r_face_sets[
i] == delete_id) {
2521 bool any_updated =
false;
2524 int other_id = delete_id;
2525 for (
const int vert : corner_verts.
slice(
faces[f_index])) {
2526 for (
const int neighbor_face_index : vert_to_face_map[vert]) {
2531 if (r_face_sets[neighbor_face_index] != delete_id) {
2532 other_id = r_face_sets[neighbor_face_index];
2537 if (other_id != delete_id) {
2539 r_face_sets[f_index] = other_id;
2598 switch (expand_cache.
target) {
2617 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
2620 if (
mask.is_empty()) {
2624 mask.begin(),
mask.end(), [&](
const float value) { return value > 0.0f; });
2629 if (
mask.is_empty()) {
2633 mask.begin(),
mask.end(), [&](
const float value) { return value > 0.0f; });
2713 const float mouse[2] = {float(event->
mval[0]), float(event->
mval[1])};
2747 switch (pbvh.
type()) {
2761 const Mesh &base_mesh = *
static_cast<const Mesh *
>(ob.
data);
2763 const Span<int> corner_verts = base_mesh.corner_verts();
2810 "RECURSION_STEP_GEODESIC",
2812 "Geodesic recursion step",
2815 "RECURSION_STEP_TOPOLOGY",
2817 "Topology recursion Step",
2823 "FALLOFF_TOPOLOGY_DIAGONALS",
2825 "Diagonals Falloff",
2830 "LOOP_COUNT_INCREASE",
2832 "Loop Count Increase",
2835 "LOOP_COUNT_DECREASE",
2837 "Loop Count Decrease",
2840 "BRUSH_GRADIENT_TOGGLE",
2842 "Toggle Brush Gradient",
2845 "TEXTURE_DISTORTION_INCREASE",
2847 "Texture Distortion Increase",
2850 "TEXTURE_DISTORTION_DECREASE",
2852 "Texture Distortion Decrease",
2854 {0,
nullptr, 0,
nullptr,
nullptr},
2857 static const char *name =
"Sculpt Expand Modal";
2871 ot->name =
"Expand";
2872 ot->idname =
"SCULPT_OT_expand";
2873 ot->description =
"Generic sculpt expand operator";
2891 {0,
nullptr, 0,
nullptr,
nullptr},
2898 {0,
nullptr, 0,
nullptr,
nullptr},
2903 prop_sculpt_expand_target_type_items,
2906 "Data that is going to be modified in the expand operation");
2910 prop_sculpt_expand_falloff_type_items,
2913 "Initial falloff of the expand operation");
2916 ot->srna,
"invert",
false,
"Invert",
"Invert the expand active elements");
2918 "use_mask_preserve",
2920 "Preserve Previous",
2921 "Preserve the previous state of the target data");
2923 "use_falloff_gradient",
2926 "Expand Using a linear falloff");
2929 "use_modify_active",
2932 "Modify the active Face Set instead of creating a new one");
2936 "use_reposition_pivot",
2939 "Reposition the sculpt transform pivot to the boundary of the expand active area");
2942 "max_geodesic_move_preview",
2946 "Max Vertex Count for Geodesic Move Preview",
2947 "Maximum number of vertices in the mesh for using geodesic falloff when "
2948 "moving the origin of expand. If the total number of vertices is greater "
2949 "than this value, the falloff will be set to spherical when moving",
2956 "Fill in mask if nothing is already masked");
2958 "normal_falloff_smooth",
2963 "Blurring steps for normal falloff",
float BKE_brush_curve_strength(eBrushCurvePreset preset, const CurveMapping *cumap, float distance, float brush_radius)
float BKE_brush_sample_tex_3d(const Scene *scene, const Brush *br, const MTex *mtex, const float point[3], float rgba[4], int thread, ImagePool *pool)
const float * BKE_brush_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
const MTex * BKE_brush_mask_texture_get(const Brush *brush, eObjectMode object_mode)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
ImagePool * BKE_image_pool_new()
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
#define SCULPT_FACE_SET_NONE
const Brush * BKE_paint_brush_for_read(const Paint *paint)
MultiresModifierData * BKE_sculpt_multires_active(const Scene *scene, Object *ob)
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
void BKE_sculpt_color_layer_create_if_needed(Object *object)
Paint * BKE_paint_get_active_from_context(const bContext *C)
void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, Main *bmain, Object *ob, MultiresModifierData *mmd)
A BVH for high poly meshes.
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
void BKE_report(ReportList *reports, eReportType type, const char *message)
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG &subdiv_ccg, const int grid_index)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_foreach_visible_grid_vert(const CCGKey &key, const blender::BitGroupVector<> &grid_hidden, const int grid, const Fn &fn)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
#define BLI_assert_unreachable()
BLI_LINKSTACK_*** wrapper macros for using a LinkNode to store a stack of pointers,...
#define BLI_LINKSTACK_PUSH(var, ptr)
#define BLI_LINKSTACK_DECLARE(var, type)
#define BLI_LINKSTACK_SIZE(var)
#define BLI_LINKSTACK_FREE(var)
#define BLI_LINKSTACK_INIT(var)
#define BLI_LINKSTACK_POP(var)
#define BLI_LINKSTACK_SWAP(var_a, var_b)
MINLINE float max_ff(float a, float b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void copy_v4_fl(float r[4], float f)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
Object is a sort of wrapper for general info.
void ED_workspace_status_text(bContext *C, const char *str)
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
void IMB_blend_color_float(float dst[4], const float src1[4], const float src2[4], IMB_BlendMode mode)
Read Guarded memory(de)allocation.
@ OPTYPE_DEPENDS_ON_CURSOR
#define BM_ELEM_CD_SET_FLOAT(ele, offset, f)
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
BMesh const char void * data
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
bool BM_vert_is_boundary(const BMVert *v)
BPy_StructRNA * depsgraph
MutableSpan< T > as_mutable_span()
void fill(const T &value) const
void reinitialize(const int64_t new_size)
static IndexMask from_bits(BitSpan bits, IndexMaskMemory &memory)
constexpr void copy_from(Span< T > values) const
MutableSpan< T > as_mutable_span()
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_bits(BitSpan bits, IndexMaskMemory &memory)
static IndexMask from_indices(Span< T > indices, IndexMaskMemory &memory)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr const T * end() const
constexpr IndexRange index_range() const
constexpr const T * begin() const
constexpr bool is_empty() const
static VArray ForSpan(Span< T > values)
void append(const T &value)
IndexRange index_range() const
Span< T > as_span() const
void fill(const bool value)
GAttributeReader lookup(const StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
Span< NodeT > nodes() const
void tag_face_sets_changed(const IndexMask &node_mask)
void tag_masks_changed(const IndexMask &node_mask)
int64_t min_array_size() const
void foreach_index(Fn &&fn) const
static float normals[][3]
VecBase< float, 3 > float3
ccl_device_inline float2 fmod(const float2 a, const float b)
ccl_device_inline float average(const float2 a)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
static constexpr int64_t BitsPerInt
void invert(BitSpanT &&data)
IndexRange grid_range(const int grid_area, const int grid)
GroupedSpan< int > build_edge_to_face_map(OffsetIndices< int > faces, Span< int > corner_edges, int edges_num, Array< int > &r_offsets, Array< int > &r_indices)
GroupedSpan< int > build_vert_to_edge_map(Span< int2 > edges, int verts_num, Array< int > &r_offsets, Array< int > &r_indices)
pbvh::Tree * pbvh_get(Object &object)
void update_mask_bmesh(const BMesh &bm, const IndexMask &node_mask, Tree &pbvh)
void update_mask_mesh(const Mesh &mesh, const IndexMask &node_mask, Tree &pbvh)
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
void node_update_mask_bmesh(int mask_offset, BMeshNode &node)
void node_update_mask_grids(const CCGKey &key, Span< float > masks, GridsNode &node)
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
void update_mask_grids(const SubdivCCG &subdiv_ccg, const IndexMask &node_mask, Tree &pbvh)
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
std::unique_ptr< SculptBoundary > data_init(const Depsgraph &depsgraph, Object &object, const Brush *brush, const int initial_vert, const float radius)
bool vert_is_boundary(const GroupedSpan< int > vert_to_face_map, const Span< bool > hide_poly, const BitSpan boundary, const int vert)
void ensure_boundary_info(Object &object)
bke::GSpanAttributeWriter active_color_attribute_for_write(Mesh &mesh)
float4 color_vert_get(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, GSpan color_attribute, bke::AttrDomain color_domain, int vert)
void color_vert_set(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, bke::AttrDomain color_domain, int vert, const float4 &color, GMutableSpan color_attribute)
bke::GAttributeReader active_color_attribute(const Mesh &mesh)
static Array< float > geodesic_falloff_create(const Depsgraph &depsgraph, Object &ob, const IndexMask &initial_verts)
static void calc_falloff_from_vert_and_symmetry(const Depsgraph &depsgraph, Cache &expand_cache, Object &ob, const int vert, FalloffType falloff_type)
static bool any_nonzero_mask(const Object &object)
static void ensure_sculptsession_data(Object &ob)
static void vert_to_face_falloff_mesh(Mesh *mesh, Cache &expand_cache)
static Array< float > spherical_falloff_create(const Depsgraph &depsgraph, const Object &object, const int vert)
static wmOperatorStatus sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void calc_topology_falloff_from_verts(Object &ob, const IndexMask &initial_verts, MutableSpan< float > distances)
static void geodesics_from_state_boundary(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache, const BitSpan enabled_verts)
static void undo_push(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache)
static void topology_from_state_boundary(Object &ob, Cache &expand_cache, const BitSpan enabled_verts)
static void move_propagation_origin(bContext *C, Object &ob, const wmEvent *event, Cache &expand_cache)
static void check_topology_islands(Object &ob, FalloffType falloff_type)
static BitVector enabled_state_to_bitmap(const Depsgraph &depsgraph, const Object &object, const Cache &expand_cache)
static float falloff_value_vertex_get(const SculptSession &ss, const Cache &expand_cache, const float3 &position, const int vert)
static wmOperatorStatus sculpt_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void original_state_store(Object &ob, Cache &expand_cache)
static void finish(bContext *C)
static void update_max_vert_falloff_value(const Object &object, Cache &expand_cache)
static void vert_to_face_falloff(Object &object, Mesh *mesh, Cache &expand_cache)
void modal_keymap(wmKeyConfig *keyconf)
static bool update_mask_grids(const SculptSession &ss, const BitSpan enabled_verts, bke::pbvh::GridsNode &node, SubdivCCG &subdiv_ccg)
static bool update_mask_bmesh(SculptSession &ss, const BitSpan enabled_verts, const int mask_offset, bke::pbvh::BMeshNode *node)
static void init_from_face_set_boundary(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache, const int active_face_set, const bool internal_falloff)
static std::optional< int > target_vert_update_and_get(bContext *C, Object &ob, const float mval[2])
static void restore_color_data(Object &ob, Cache &expand_cache)
static bool face_state_get(const Object &object, const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< bool > hide_poly, const Span< int > face_sets, const Cache &expand_cache, const int face)
static bool is_vert_in_active_component(const SculptSession &ss, const Cache &expand_cache, const int vert)
static void expand_cache_free(SculptSession &ss)
static Array< float > normals_falloff_create(const Depsgraph &depsgraph, Object &ob, const int vert, const float edge_sensitivity, const int blur_steps)
static void delete_face_set_id(int *r_face_sets, Object &object, Cache &expand_cache, Mesh *mesh, const int delete_id)
static void reposition_pivot(bContext *C, Object &ob, Cache &expand_cache)
static void update_for_vert(bContext *C, Object &ob, const std::optional< int > vertex)
static void face_sets_restore(Object &object, Cache &expand_cache)
static void calc_new_mask_mesh(const SculptSession &ss, const Span< float3 > positions, const BitSpan enabled_verts, const Span< int > verts, const MutableSpan< float > mask)
static void face_sets_update(Object &object, Cache &expand_cache)
static void find_active_connected_components_from_vert(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache, const int initial_vertex)
void SCULPT_OT_expand(wmOperatorType *ot)
static void update_max_face_falloff_factor(const Object &object, Mesh &mesh, Cache &expand_cache)
static void vert_to_face_falloff_grids(SculptSession &ss, Mesh *mesh, Cache &expand_cache)
static bool is_face_in_active_component(const Object &object, const OffsetIndices< int > faces, const Span< int > corner_verts, const Cache &expand_cache, const int f)
static Array< float > diagonals_falloff_create(const Depsgraph &depsgraph, Object &ob, const int vert)
static void restore_original_state(bContext *C, Object &ob, Cache &expand_cache)
static Array< float > topology_falloff_create(const Depsgraph &depsgraph, Object &ob, const int initial_vert)
static void resursion_step_add(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache, const RecursionType recursion_type)
static IndexMask boundary_from_enabled(Object &object, const BitSpan enabled_verts, const bool use_mesh_boundary, IndexMaskMemory &memory)
static void cache_initial_config_set(bContext *C, wmOperator *op, Cache &expand_cache)
static float gradient_value_get(const SculptSession &ss, const Cache &expand_cache, const float3 &position, const int vert)
static bool vert_falloff_is_enabled(const SculptSession &ss, const Cache &expand_cache, const float3 &position, const int vert)
static bool colors_update_task(const Depsgraph &depsgraph, Object &object, const Span< float3 > vert_positions, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const Span< bool > hide_vert, const Span< float > mask, bke::pbvh::MeshNode *node, bke::GSpanAttributeWriter &color_attribute)
static void restore_face_set_data(Object &object, Cache &expand_cache)
static void sculpt_expand_cancel(bContext *C, wmOperator *)
static void snap_init_from_enabled(const Depsgraph &depsgraph, const Object &object, Cache &expand_cache)
static Array< float > boundary_topology_falloff_create(const Depsgraph &depsgraph, Object &ob, const int inititial_vert)
static int active_face_set_id_get(Object &object, Cache &expand_cache)
static float max_vert_falloff_get(const Cache &expand_cache)
static void write_mask_data(Object &object, const Span< float > mask)
@ SCULPT_EXPAND_MODAL_GRADIENT_TOGGLE
@ SCULPT_EXPAND_MODAL_RECURSION_STEP_TOPOLOGY
@ SCULPT_EXPAND_MODAL_BRUSH_GRADIENT_TOGGLE
@ SCULPT_EXPAND_MODAL_FALLOFF_CYCLE
@ SCULPT_EXPAND_MODAL_LOOP_COUNT_INCREASE
@ SCULPT_EXPAND_MODAL_FALLOFF_SPHERICAL
@ SCULPT_EXPAND_MODAL_FALLOFF_GEODESIC
@ SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY
@ SCULPT_EXPAND_MODAL_LOOP_COUNT_DECREASE
@ SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_DECREASE
@ SCULPT_EXPAND_MODAL_SNAP_TOGGLE
@ SCULPT_EXPAND_MODAL_PRESERVE_TOGGLE
@ SCULPT_EXPAND_MODAL_CANCEL
@ SCULPT_EXPAND_MODAL_RECURSION_STEP_GEODESIC
@ SCULPT_EXPAND_MODAL_INVERT
@ SCULPT_EXPAND_MODAL_TEXTURE_DISTORTION_INCREASE
@ SCULPT_EXPAND_MODAL_FALLOFF_TOPOLOGY_DIAGONALS
@ SCULPT_EXPAND_MODAL_CONFIRM
@ SCULPT_EXPAND_MODAL_MOVE_TOGGLE
static bool set_initial_components_for_mouse(bContext *C, Object &ob, Cache &expand_cache, const float mval[2])
int vert_face_set_get(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert)
int find_next_available_id(Object &object)
bool vert_has_unique_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, int vert)
bool vert_has_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert, const int face_set)
bool create_face_sets_mesh(Object &object)
Array< int > duplicate_face_sets(const Mesh &mesh)
bke::SpanAttributeWriter< int > ensure_face_sets_mesh(Mesh &mesh)
int active_face_set_get(const Object &object)
Array< float > distances_create(const Span< float3 > vert_positions, const Span< int2 > edges, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_edge_map, const GroupedSpan< int > edge_to_face_map, const Span< bool > hide_poly, const Set< int > &initial_verts, const float limit_radius)
void ensure_cache(Object &object)
int vert_id_get(const SculptSession &ss, const int vert)
void update_mask_mesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, FunctionRef< void(MutableSpan< float >, Span< int >)> update_fn)
Array< float > duplicate_mask(const Object &object)
void clamp_mask(const MutableSpan< float > masks)
void blur_geometry_data_array(const Object &object, const int iterations, const MutableSpan< float > data)
void push_end(Object &ob)
void push_nodes(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Type type)
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
void vert_random_access_ensure(Object &object)
std::optional< int > nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh, const Span< float3 > vert_positions, const Span< bool > hide_vert, const float3 &location, const float max_distance, const bool use_original)
Vector< int > find_symm_verts_grids(const Object &object, const int original_vert, const float max_distance)
Vector< BMVert *, 64 > BMeshNeighborVerts
float3 symmetry_flip(const float3 &src, const ePaintSymmetryFlags symm)
Vector< int > find_symm_verts_mesh(const Depsgraph &depsgraph, const Object &object, const int original_vert, const float max_distance)
bool cursor_geometry_info_update(bContext *C, CursorGeometryInfo *out, const float2 &mval, const bool use_sampled_normal)
void flush_update_done(const bContext *C, Object &ob, const UpdateType update_type)
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, BMeshNeighborVerts &r_neighbors)
void flush_update_step(const bContext *C, const UpdateType update_type)
std::optional< BMVert * > nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh, const float3 &location, const float max_distance, const bool use_original)
std::optional< SubdivCCGCoord > nearest_vert_calc_grids(const bke::pbvh::Tree &pbvh, const SubdivCCG &subdiv_ccg, const float3 &location, const float max_distance, const bool use_original)
Vector< int > find_symm_verts(const Depsgraph &depsgraph, const Object &object, const int original_vert, const float max_distance)
Span< int > vert_neighbors_get_mesh(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face, const Span< bool > hide_poly, const int vert, Vector< int > &r_neighbors)
Vector< int > find_symm_verts_bmesh(const Object &object, const int original_vert, const float max_distance)
bool is_symmetry_iteration_valid(const char i, const char symm)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void parallel_for_aligned(const IndexRange range, const int64_t grain_size, const int64_t alignment, const Function &function)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
VecBase< float, 4 > float4
VecBase< double, 3 > double3
VecBase< float, 3 > float3
CCL_NAMESPACE_BEGIN ccl_device float fade(const float t)
int RNA_int_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, const int default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
ePaintSymmetryFlags SCULPT_mesh_symmetry_xyz_get(const Object &object)
bool SCULPT_mode_poll(bContext *C)
int SCULPT_vertex_count_get(const Object &object)
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
void SCULPT_tag_update_overlays(bContext *C)
#define SCULPT_EXPAND_LOOP_THRESHOLD
#define SCULPT_EXPAND_TEXTURE_DISTORTION_STEP
#define EXPAND_ACTIVE_COMPONENT_NONE
#define SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY
#define EXPAND_SYMM_AREAS
struct CurveMapping * curve
struct SculptSession * sculpt
std::optional< int > active_grid_index
std::optional< int > active_face_index
SculptVertexInfo vertex_info
blender::float3 pivot_pos
int last_active_vert_index() const
blender::ed::sculpt_paint::expand::Cache * expand_cache
int active_vert_index() const
blender::BitVector boundary
int to_index(const CCGKey &key) const
static SubdivCCGCoord from_index(const CCGKey &key, int index)
SubdivCCGNeighborCoords coords
blender::Array< blender::float3 > normals
blender::Array< float > masks
blender::Array< blender::float3 > positions
MutableVArraySpan< T > span
Span< int > grids() const
Span< int > verts() const
float2 original_mouse_move
std::unique_ptr< Set< int > > snap_enabled_face_sets
float2 initial_mouse_move
bool modify_active_face_set
FalloffType move_original_falloff_type
Array< float > face_falloff
int initial_active_face_set
Array< int > original_face_sets
Array< float > vert_falloff
Array< float4 > original_colors
Array< int > initial_face_sets
int normal_falloff_blur_steps
IndexMaskMemory node_mask_memory
FalloffType move_preview_falloff_type
int active_connected_islands[EXPAND_SYMM_AREAS]
int max_geodesic_move_preview
float texture_distortion_strength
Array< float > original_mask
void add_initial(BMVert *vertex)
void add_and_skip_initial(BMVert *vertex, int index)
void execute(Object &object, FunctionRef< bool(BMVert *from_v, BMVert *to_v)> func)
void execute(Object &object, const SubdivCCG &subdiv_ccg, FunctionRef< bool(SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate)> func)
void add_initial(SubdivCCGCoord vertex)
void add_and_skip_initial(SubdivCCGCoord vertex, int index)
void execute(Object &object, GroupedSpan< int > vert_to_face_map, FunctionRef< bool(int from_v, int to_v)> func)
void add_and_skip_initial(int vertex)
void add_initial(int vertex)
struct ReportList * reports
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)