89#define SCULPT_EXPAND_VERTEX_NONE -1
92#define EXPAND_ACTIVE_COMPONENT_NONE -1
97#define SCULPT_EXPAND_TEXTURE_DISTORTION_STEP 0.01f
104#define SCULPT_EXPAND_LOOP_THRESHOLD 0.00001f
111#define SCULPT_EXPAND_NORMALS_FALLOFF_EDGE_SENSITIVITY 300
145 const Cache &expand_cache,
162 const Cache &expand_cache,
187 const Cache &expand_cache,
202 expand_cache.
scene, brush, mtex, position, rgba, 0, ss.
tex_pool);
220 if (!mask_tex->
tex) {
229 const Cache &expand_cache,
234 const float loop_len = (max_falloff_factor / expand_cache.
loop_count) +
239 const float falloff_factor =
fmod(vertex_falloff_factor, loop_len);
241 return falloff_factor < active_factor;
253 const Cache &expand_cache,
256 if (!hide_poly.
is_empty() && hide_poly[face]) {
265 if (expand_cache.
invert) {
271 bool enabled =
false;
282 const float falloff_factor =
fmod(expand_cache.
face_falloff[face], loop_len);
283 enabled = falloff_factor < active_factor;
292 if (expand_cache.
invert) {
304 const Cache &expand_cache,
313 const float loop_len = (max_falloff_factor / expand_cache.
loop_count) +
318 const float falloff_factor =
fmod(vertex_falloff_factor, loop_len);
320 float linear_falloff;
322 if (expand_cache.
invert) {
325 BLI_assert((loop_len - active_factor) != 0.0f);
326 linear_falloff = (falloff_factor - active_factor) / (loop_len - active_factor);
329 linear_falloff = 1.0f - (falloff_factor / active_factor);
333 return linear_falloff;
347 const Cache &expand_cache)
353 if (!expand_cache.
invert) {
354 enabled_verts.
fill(
true);
356 return enabled_verts;
360 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
365 const VArraySpan face_sets = *attributes.lookup_or_default<
int>(
369 for (
const int vert :
range) {
370 if (!hide_vert.
is_empty() && hide_vert[vert]) {
376 if (expand_cache.
snap) {
378 vert_to_face_map, face_sets, vert);
382 enabled_verts[vert].set(
389 const Mesh &base_mesh = *
static_cast<const Mesh *
>(
object.data);
391 const VArraySpan face_sets = *attributes.lookup_or_default<
int>(
395 const Span<int> grid_to_face_map = subdiv_ccg.grid_to_face_map;
399 for (
const int grid :
IndexRange(subdiv_ccg.grids_num)) {
401 const int face_set = face_sets[grid_to_face_map[grid]];
403 const int vert = start + offset;
407 if (expand_cache.
snap) {
408 enabled_verts[vert].set(expand_cache.snap_enabled_face_sets->contains(face_set));
411 enabled_verts[vert].set(
427 if (expand_cache.
snap) {
429 const int face_set = 0;
438 if (expand_cache.
invert) {
441 return enabled_verts;
451 const bool use_mesh_boundary,
462 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
464 const Span<int> corner_verts = mesh.corner_verts();
471 faces, corner_verts, vert_to_face_map, hide_poly, vert, neighbors))
473 if (!enabled_verts[neighbor]) {
478 if (use_mesh_boundary &&
488 const Mesh &base_mesh = *
static_cast<const Mesh *
>(
object.data);
490 const Span<int> corner_verts = base_mesh.corner_verts();
499 if (!enabled_verts[neighbor.to_index(key)]) {
504 if (use_mesh_boundary &&
561 const int original_vert,
562 const float max_distance)
566 const bool use_original =
false;
569 symm_verts.
append(original_vert);
571 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
576 const float3 location = positions[original_vert];
577 for (
char symm_it = 1; symm_it <= symm; symm_it++) {
583 pbvh, positions, hide_vert, symm_location, max_distance, use_original);
587 symm_verts.
append(*nearest);
590 std::sort(symm_verts.
begin(), symm_verts.
end());
595 const int original_vert,
596 const float max_distance)
600 const bool use_original =
false;
603 symm_verts.
append(original_vert);
609 const float3 location = positions[original_vert];
610 for (
char symm_it = 1; symm_it <= symm; symm_it++) {
616 pbvh, subdiv_ccg, symm_location, max_distance, use_original);
620 symm_verts.
append(nearest->to_index(key));
623 std::sort(symm_verts.
begin(), symm_verts.
end());
628 const int original_vert,
629 const float max_distance)
633 const bool use_original =
false;
636 symm_verts.
append(original_vert);
641 const float3 location = original_bm_vert->
co;
642 for (
char symm_it = 1; symm_it <= symm; symm_it++) {
648 pbvh, symm_location, max_distance, use_original);
655 std::sort(symm_verts.
begin(), symm_verts.
end());
661 const int original_vert,
662 const float max_distance)
665 switch (pbvh.
type()) {
693 const Span<int> corner_verts = mesh.corner_verts();
694 const Span<int> corner_edges = mesh.corner_edges();
699 if (ss.edge_to_face_map.is_empty()) {
701 faces, corner_edges, edges.
size(), ss.edge_to_face_offsets, ss.edge_to_face_indices);
703 if (ss.vert_to_edge_map.is_empty()) {
705 edges, mesh.verts_num, ss.vert_to_edge_offsets, ss.vert_to_edge_indices);
723 const int initial_vert)
747 switch (pbvh.
type()) {
751 flood.
execute(ob, vert_to_face_map, [&](
const int from_vert,
const int to_vert) {
752 distances[to_vert] = distances[from_vert] + 1.0f;
770 const int from_vert = from.to_index(key);
771 const int to_vert = to.to_index(key);
773 distances[to_vert] = distances[from_vert];
776 distances[to_vert] = distances[from_vert] + 1.0f;
790 distances[to_vert] = distances[from_vert] + 1.0f;
800 const int initial_vert)
820 const float edge_sensitivity,
821 const int blur_steps)
829 switch (pbvh.
type()) {
835 const float3 orig_normal = vert_normals[vert];
838 flood.
execute(ob, vert_to_face_map, [&](
const int from_vert,
const int to_vert) {
839 const float3 &from_normal = vert_normals[from_vert];
840 const float3 &to_normal = vert_normals[to_vert];
841 const float from_edge_factor = edge_factors[from_vert];
842 const float dist =
math::dot(orig_normal, to_normal) *
843 powf(from_edge_factor, edge_sensitivity);
844 edge_factors[to_vert] =
math::dot(to_normal, from_normal) * from_edge_factor;
845 dists[to_vert] = std::clamp(dist, 0.0f, 1.0f);
854 const float3 orig_normal = normals[vert];
861 const int from_vert = from.to_index(key);
862 const int to_vert = to.to_index(key);
864 edge_factors[to_vert] = edge_factors[from_vert];
865 dists[to_vert] = dists[from_vert];
868 const float3 &from_normal = normals[from_vert];
869 const float3 &to_normal = normals[to_vert];
870 const float from_edge_factor = edge_factors[from_vert];
871 const float dist =
math::dot(orig_normal, to_normal) *
872 powf(from_edge_factor, edge_sensitivity);
873 edge_factors[to_vert] =
math::dot(to_normal, from_normal) * from_edge_factor;
874 dists[to_vert] = std::clamp(dist, 0.0f, 1.0f);
883 const float3 orig_normal = orig_vert->
no;
886 const float3 &from_normal = from_bm_vert->
no;
887 const float3 &to_normal = to_bm_vert->
no;
890 const float from_edge_factor = edge_factors[from_vert];
891 const float dist =
math::dot(orig_normal, to_normal) *
892 powf(from_edge_factor, edge_sensitivity);
893 edge_factors[to_vert] =
math::dot(to_normal, from_normal) * from_edge_factor;
894 dists[to_vert] = std::clamp(dist, 0.0f, 1.0f);
903 for (
int i = 0; i < totvert; i++) {
904 dists[i] = 1.0 - dists[i];
924 switch (pbvh.
type()) {
932 for (const int vert : range) {
933 float dist = std::numeric_limits<float>::max();
934 for (const float3 &location : locations) {
935 dist = std::min(dist, math::distance(positions[vert], location));
948 locations[i] = positions[symm_verts[i]];
952 for (const int vert : range) {
953 float dist = std::numeric_limits<float>::max();
954 for (const float3 &location : locations) {
955 dist = std::min(dist, math::distance(positions[vert], location));
966 for (
const int i : symm_verts.index_range()) {
971 for (const int vert : range) {
972 float dist = std::numeric_limits<float>::max();
973 for (const float3 &location : locations) {
974 dist = std::min(dist,
975 math::distance(float3(BM_vert_at_index(&bm, vert)->co), location));
994 const int inititial_vert)
999 for (
const int vert : symm_verts) {
1000 if (std::unique_ptr<boundary::SculptBoundary> boundary = boundary::data_init(
1003 for (
const int vert : boundary->verts) {
1004 boundary_verts[vert].set();
1010 const IndexMask boundary_mask = IndexMask::from_bits(boundary_verts, memory);
1027 const Mesh &mesh = *
static_cast<const Mesh *
>(ob.
data);
1029 const Span<int> corner_verts = mesh.corner_verts();
1037 if (pbvh.
type() != bke::pbvh::Type::Mesh) {
1045 std::queue<int> queue;
1046 for (
const int vert : symm_verts) {
1048 visited_verts[vert].set();
1051 if (queue.empty()) {
1056 while (!queue.empty()) {
1057 const int next_vert = queue.front();
1060 for (
const int face : vert_to_face_map[next_vert]) {
1061 for (
const int vert : corner_verts.
slice(faces[face])) {
1062 if (visited_verts[vert]) {
1065 dists[vert] = dists[next_vert] + 1.0f;
1066 visited_verts[vert].set();
1085 std::numeric_limits<float>::lowest(),
1087 for (
const int vert :
range) {
1098 [](
const float a,
const float b) {
return std::max(a,
b); });
1108 const Span<int> corner_verts = mesh.corner_verts();
1110 faces.index_range(),
1112 std::numeric_limits<float>::lowest(),
1114 for (const int face : range) {
1115 if (expand_cache.face_falloff[face] == FLT_MAX) {
1118 if (!is_face_in_active_component(object, faces, corner_verts, expand_cache, face)) {
1121 max = std::max(max, expand_cache.face_falloff[face]);
1125 [](
const float a,
const float b) {
return std::max(a,
b); });
1139 threading::parallel_for(faces.index_range(), 1024, [&](
const IndexRange range) {
1140 for (const int face : range) {
1142 for (const int corner : faces[face]) {
1143 const int grid_loop_index = corner * key.grid_area;
1144 for (int g = 0; g < key.grid_area; g++) {
1145 accum += expand_cache.vert_falloff[grid_loop_index + g];
1148 expand_cache.face_falloff[face] = accum / (faces[face].size() * key.grid_area);
1156 const Span<int> corner_verts = mesh->corner_verts();
1158 threading::parallel_for(faces.index_range(), 1024, [&](
const IndexRange range) {
1159 for (const int face : range) {
1160 const Span<int> face_verts = corner_verts.slice(faces[face]);
1162 for (const int vert : face_verts) {
1163 accum += expand_cache.vert_falloff[vert];
1165 expand_cache.face_falloff[face] = accum / face_verts.size();
1180 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
1183 else if (pbvh.
type() == bke::pbvh::Type::Grids) {
1200 Cache &expand_cache,
1203 BLI_assert(bke::object::pbvh_get(ob)->type() == bke::pbvh::Type::Mesh);
1218 Cache &expand_cache,
1237 Cache &expand_cache,
1241 if (pbvh.
type() != bke::pbvh::Type::Mesh) {
1252 switch (recursion_type) {
1253 case RecursionType::Geodesic:
1256 case RecursionType::Topology:
1262 if (expand_cache.
target == TargetType::FaceSets) {
1277 Cache &expand_cache,
1278 const int active_face_set,
1279 const bool internal_falloff)
1286 switch (pbvh.
type()) {
1287 case bke::pbvh::Type::Mesh: {
1288 const Mesh &mesh = *
static_cast<const Mesh *
>(ob.
data);
1291 const VArraySpan face_sets = *attributes.lookup<
int>(
".sculpt_face_set",
1292 bke::AttrDomain::Face);
1294 for (
const int vert :
range) {
1295 vert_has_face_set[vert] = face_set::vert_has_face_set(
1296 vert_to_face_map, face_sets, vert, active_face_set);
1297 vert_has_unique_face_set[vert] = face_set::vert_has_unique_face_set(
1298 vert_to_face_map, face_sets, vert);
1303 case bke::pbvh::Type::Grids: {
1304 const Mesh &base_mesh = *
static_cast<const Mesh *
>(ob.
data);
1306 const Span<int> corner_verts = base_mesh.corner_verts();
1309 const VArraySpan face_sets = *attributes.lookup<
int>(
".sculpt_face_set",
1310 bke::AttrDomain::Face);
1314 for (
const int vert :
range) {
1316 vert_has_face_set[vert] = face_set::vert_has_face_set(
1317 subdiv_ccg, face_sets, coord.
grid_index, active_face_set);
1318 vert_has_unique_face_set[vert] = face_set::vert_has_unique_face_set(
1319 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, coord);
1324 case bke::pbvh::Type::BMesh: {
1329 for (
const int vert :
range) {
1331 vert_has_face_set[vert] = face_set::vert_has_face_set(offset, *bm_vert, active_face_set);
1332 vert_has_unique_face_set[vert] = face_set::vert_has_unique_face_set(offset, *bm_vert);
1340 for (
int i = 0; i < totvert; i++) {
1341 if (!vert_has_unique_face_set[i]) {
1344 if (!vert_has_face_set[i]) {
1347 enabled_verts[i].set();
1350 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
1357 if (internal_falloff) {
1358 for (
int i = 0; i < totvert; i++) {
1359 if (!(vert_has_face_set[i] && vert_has_unique_face_set[i])) {
1366 for (
int i = 0; i < totvert; i++) {
1370 const float additional_falloff =
fabsf(min_factor);
1371 for (
int i = 0; i < totvert; i++) {
1376 for (
int i = 0; i < totvert; i++) {
1377 if (!vert_has_face_set[i]) {
1390 Cache &expand_cache,
1398 const bool has_topology_info = pbvh.
type() == bke::pbvh::Type::Mesh;
1400 switch (falloff_type) {
1401 case FalloffType::Geodesic:
1406 case FalloffType::Topology:
1409 case FalloffType::TopologyNormals:
1414 case FalloffType::Normals:
1422 case FalloffType::Sphere:
1425 case FalloffType::BoundaryTopology:
1428 case FalloffType::BoundaryFaceSet:
1432 case FalloffType::ActiveFaceSet:
1440 if (expand_cache.
target == TargetType::FaceSets) {
1454 Cache &expand_cache)
1457 if (pbvh.
type() != bke::pbvh::Type::Mesh) {
1460 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
1462 const Span<int> corner_verts = mesh.corner_verts();
1465 const bool prev_snap_state = expand_cache.
snap;
1466 const bool prev_invert_state = expand_cache.
invert;
1467 expand_cache.
snap =
false;
1468 expand_cache.
invert =
false;
1472 for (
const int i : faces.index_range()) {
1477 for (
const int i : faces.index_range()) {
1479 const bool any_disabled = std::any_of(face_verts.
begin(),
1481 [&](
const int vert) { return !enabled_verts[vert]; });
1488 expand_cache.
snap = prev_snap_state;
1489 expand_cache.
invert = prev_invert_state;
1507 *
static_cast<Mesh *
>(
object.data));
1512 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1522 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1525 const Span<int> corner_verts = mesh.corner_verts();
1529 for (
const int vert : nodes[i].verts()) {
1530 color::color_vert_set(faces,
1536 color_attribute.
span);
1540 color_attribute.
finish();
1548 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1549 switch (pbvh.
type()) {
1550 case bke::pbvh::Type::Mesh: {
1551 Mesh &mesh = *
static_cast<Mesh *
>(
object.data);
1553 attributes.
remove(
".sculpt_mask");
1554 attributes.add<
float>(
".sculpt_mask",
1555 bke::AttrDomain::Point,
1557 bke::pbvh::update_mask_mesh(mesh, node_mask, pbvh);
1560 case bke::pbvh::Type::BMesh: {
1564 for (
const int i : mask.index_range()) {
1567 bke::pbvh::update_mask_bmesh(
bm, node_mask, pbvh);
1570 case bke::pbvh::Type::Grids: {
1573 bke::pbvh::update_mask_grids(subdiv_ccg, node_mask, pbvh);
1584 switch (expand_cache.
target) {
1585 case TargetType::Mask:
1591 case TargetType::FaceSets:
1597 case TargetType::Colors:
1629 for (
const int i :
verts.index_range()) {
1630 const int vert =
verts[i];
1631 const bool enabled = enabled_verts[vert];
1645 if (expand_cache.
invert) {
1654 mask::clamp_mask(mask);
1667 bool any_changed =
false;
1668 for (
const int grid : node.grids()) {
1669 for (
const int vert : bke::ccg::grid_range(key, grid)) {
1670 const float initial_mask = masks[vert];
1678 if (enabled_verts[vert]) {
1686 if (expand_cache.
invert) {
1694 if (new_mask == initial_mask) {
1698 masks[vert] =
clamp_f(new_mask, 0.0f, 1.0f);
1703 bke::pbvh::node_update_mask_grids(key, masks, node);
1710 const int mask_offset,
1715 bool any_changed =
false;
1726 if (enabled_verts[vert_index]) {
1734 if (expand_cache.
invert) {
1742 if (new_mask == initial_mask) {
1750 bke::pbvh::node_update_mask_bmesh(mask_offset, *node);
1760 Mesh &mesh = *
static_cast<Mesh *
>(
object.data);
1763 const Span<int> corner_verts = mesh.corner_verts();
1765 const VArraySpan<bool> hide_poly = *attributes.lookup<
bool>(
".hide_poly", bke::AttrDomain::Face);
1766 for (
const int f : face_sets.
span.index_range()) {
1768 object, faces, corner_verts, hide_poly, face_sets.
span, expand_cache, f);
1805 bool any_changed =
false;
1807 for (
const int i :
verts.index_range()) {
1808 const int vert =
verts[i];
1809 if (!hide_vert.
is_empty() && hide_vert[vert]) {
1813 float4 initial_color = color::color_vert_get(
1814 faces, corner_verts, vert_to_face_map, color_attribute.
span, color_attribute.
domain, vert);
1818 if (enabled_verts[vert]) {
1825 if (!mask.is_empty()) {
1826 fade *= 1.0f - mask[vert];
1838 if (initial_color == final_color) {
1842 color::color_vert_set(faces,
1848 color_attribute.
span);
1861 face_set::create_face_sets_mesh(ob);
1867 if (expand_cache.
target == TargetType::Mask) {
1871 if (expand_cache.
target == TargetType::Colors) {
1872 const Mesh &mesh = *
static_cast<const Mesh *
>(ob.
data);
1874 const Span<int> corner_verts = mesh.corner_verts();
1880 for (
int i = 0; i < totvert; i++) {
1882 faces, corner_verts, vert_to_face_map, colors, color_attribute.
domain, i);
1892 Mesh &mesh = *
static_cast<Mesh *
>(
object.data);
1894 const Span<int> corner_verts = mesh.corner_verts();
1896 for (
const int i : faces.index_range()) {
1929 if (expand_cache.
target == TargetType::FaceSets) {
1939 switch (expand_cache.
target) {
1940 case TargetType::Mask: {
1941 switch (pbvh.
type()) {
1942 case bke::pbvh::Type::Mesh: {
1944 mask::update_mask_mesh(
1950 case bke::pbvh::Type::Grids: {
1955 node_changed[i] = update_mask_grids(ss, enabled_verts, nodes[i], *ss.
subdiv_ccg);
1962 case bke::pbvh::Type::BMesh: {
1969 node_changed[i] = update_mask_bmesh(ss, enabled_verts, mask_offset, &nodes[i]);
1980 case TargetType::FaceSets:
1984 case TargetType::Colors: {
1988 const Span<int> corner_verts = mesh.corner_verts();
1991 const VArraySpan hide_vert = *attributes.lookup<
bool>(
".hide_vert", bke::AttrDomain::Point);
1992 const VArraySpan mask = *attributes.lookup<
float>(
".sculpt_mask", bke::AttrDomain::Point);
2013 mesh.active_color_attribute);
2015 color_attribute.finish();
2033 return std::nullopt;
2046 const bool initial_invert_state = expand_cache.
invert;
2047 expand_cache.
invert =
false;
2053 const float use_mesh_boundary = expand_cache.
falloff_type != FalloffType::BoundaryTopology;
2057 ob, enabled_verts, use_mesh_boundary, memory);
2061 expand_cache.
invert = initial_invert_state;
2065 switch (bke::object::pbvh_get(ob)->type()) {
2066 case bke::pbvh::Type::Mesh: {
2073 const float3 &position = positions[vert];
2082 case bke::pbvh::Type::Grids: {
2090 const float3 position = positions[vert];
2099 case bke::pbvh::Type::BMesh: {
2131 case TargetType::Mask:
2134 case TargetType::FaceSets:
2137 case TargetType::Colors:
2152 Cache &expand_cache,
2153 const int initial_vertex)
2164 int valid_index = 0;
2165 for (
char symm_it = 0; symm_it <= symm; symm_it++) {
2170 symm_verts[valid_index]);
2181 Cache &expand_cache,
2182 const float mval[2])
2188 if (!initial_vert) {
2197 if (last_active_vert_index == -1) {
2200 initial_vert = last_active_vert_index;
2212 expand_cache.
next_face_set = face_set::active_face_set_get(ob);
2215 expand_cache.
next_face_set = face_set::find_next_available_id(ob);
2232 Cache &expand_cache)
2256 islands::ensure_cache(ob);
2258 boundary::ensure_boundary_info(ob);
2270 switch (bke::object::pbvh_get(
object)->type()) {
2271 case bke::pbvh::Type::Mesh:
2276 case bke::pbvh::Type::Grids: {
2284 case bke::pbvh::Type::BMesh: {
2314 switch (event->
val) {
2339 if (expand_cache.
snap) {
2340 expand_cache.
snap =
false;
2346 expand_cache.
snap =
true;
2353 if (expand_cache.
move) {
2354 expand_cache.
move =
false;
2362 expand_cache.
move =
true;
2366 if (expand_cache.
falloff_type == FalloffType::Geodesic &&
2417 FalloffType::TopologyNormals);
2438 if (mask_tex->
tex ==
nullptr) {
2441 "Active brush does not contain any texture to distort the expand boundary");
2447 "Texture mapping not set to 3D, results may be unpredictable");
2463 if (expand_cache.
move) {
2468 if (expand_cache.
snap) {
2487 int *r_face_sets,
Object &
object,
Cache &expand_cache,
Mesh *mesh,
const int delete_id)
2491 const Span<int> corner_verts = mesh->corner_verts();
2495 bool all_same_id =
true;
2496 for (
const int i : faces.index_range()) {
2500 if (r_face_sets[i] != delete_id) {
2501 all_same_id =
false;
2515 for (
const int i : faces.index_range()) {
2516 if (r_face_sets[i] == delete_id) {
2522 bool any_updated =
false;
2525 int other_id = delete_id;
2526 for (
const int vert : corner_verts.
slice(faces[f_index])) {
2527 for (
const int neighbor_face_index : vert_to_face_map[vert]) {
2532 if (r_face_sets[neighbor_face_index] != delete_id) {
2533 other_id = r_face_sets[neighbor_face_index];
2538 if (other_id != delete_id) {
2540 r_face_sets[f_index] = other_id;
2597 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*bke::object::pbvh_get(ob), memory);
2599 switch (expand_cache.
target) {
2600 case TargetType::Mask:
2601 undo::push_nodes(
depsgraph, ob, node_mask, undo::Type::Mask);
2603 case TargetType::FaceSets:
2604 undo::push_nodes(
depsgraph, ob, node_mask, undo::Type::FaceSet);
2606 case TargetType::Colors: {
2607 undo::push_nodes(
depsgraph, ob, node_mask, undo::Type::Color);
2616 switch (bke::object::pbvh_get(
object)->type()) {
2617 case bke::pbvh::Type::Mesh: {
2618 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
2620 const VArraySpan mask = *attributes.lookup<
float>(
".sculpt_mask");
2621 if (mask.is_empty()) {
2625 mask.begin(), mask.end(), [&](
const float value) { return value > 0.0f; });
2627 case bke::pbvh::Type::Grids: {
2630 if (mask.is_empty()) {
2634 mask.begin(), mask.end(), [&](
const float value) { return value > 0.0f; });
2636 case bke::pbvh::Type::BMesh: {
2725 undo::push_begin(scene, ob, op);
2748 switch (pbvh.
type()) {
2749 case bke::pbvh::Type::Mesh: {
2750 const Mesh &mesh = *
static_cast<const Mesh *
>(ob.
data);
2753 const VArraySpan hide_poly = *attributes.lookup<
bool>(
".hide_poly", bke::AttrDomain::Face);
2754 if (boundary::vert_is_boundary(
2757 falloff_type = FalloffType::BoundaryTopology;
2761 case bke::pbvh::Type::Grids: {
2762 const Mesh &base_mesh = *
static_cast<const Mesh *
>(ob.
data);
2764 const Span<int> corner_verts = base_mesh.corner_verts();
2766 const VArraySpan face_sets = *attributes.lookup_or_default<
int>(
2767 ".sculpt_face_set", bke::AttrDomain::Face, 0);
2770 if (boundary::vert_is_boundary(faces,
2776 falloff_type = FalloffType::BoundaryTopology;
2780 case bke::pbvh::Type::BMesh: {
2784 falloff_type = FalloffType::BoundaryTopology;
2811 "RECURSION_STEP_GEODESIC",
2813 "Geodesic recursion step",
2816 "RECURSION_STEP_TOPOLOGY",
2818 "Topology recursion Step",
2824 "FALLOFF_TOPOLOGY_DIAGONALS",
2826 "Diagonals Falloff",
2831 "LOOP_COUNT_INCREASE",
2833 "Loop Count Increase",
2836 "LOOP_COUNT_DECREASE",
2838 "Loop Count Decrease",
2841 "BRUSH_GRADIENT_TOGGLE",
2843 "Toggle Brush Gradient",
2846 "TEXTURE_DISTORTION_INCREASE",
2848 "Texture Distortion Increase",
2851 "TEXTURE_DISTORTION_DECREASE",
2853 "Texture Distortion Decrease",
2855 {0,
nullptr, 0,
nullptr,
nullptr},
2858 static const char *name =
"Sculpt Expand Modal";
2884 {
int(FalloffType::Geodesic),
"GEODESIC", 0,
"Geodesic",
""},
2885 {
int(FalloffType::Topology),
"TOPOLOGY", 0,
"Topology",
""},
2886 {
int(FalloffType::TopologyNormals),
"TOPOLOGY_DIAGONALS", 0,
"Topology Diagonals",
""},
2887 {
int(FalloffType::Normals),
"NORMALS", 0,
"Normals",
""},
2888 {
int(FalloffType::Sphere),
"SPHERICAL", 0,
"Spherical",
""},
2889 {
int(FalloffType::BoundaryTopology),
"BOUNDARY_TOPOLOGY", 0,
"Boundary Topology",
""},
2890 {
int(FalloffType::BoundaryFaceSet),
"BOUNDARY_FACE_SET", 0,
"Boundary Face Set",
""},
2891 {
int(FalloffType::ActiveFaceSet),
"ACTIVE_FACE_SET", 0,
"Active Face Set",
""},
2892 {0,
nullptr, 0,
nullptr,
nullptr},
2896 {
int(TargetType::Mask),
"MASK", 0,
"Mask",
""},
2897 {
int(TargetType::FaceSets),
"FACE_SETS", 0,
"Face Sets",
""},
2898 {
int(TargetType::Colors),
"COLOR", 0,
"Color",
""},
2899 {0,
nullptr, 0,
nullptr,
nullptr},
2904 prop_sculpt_expand_target_type_items,
2905 int(TargetType::Mask),
2907 "Data that is going to be modified in the expand operation");
2911 prop_sculpt_expand_falloff_type_items,
2912 int(FalloffType::Geodesic),
2914 "Initial falloff of the expand operation");
2917 ot->
srna,
"invert",
false,
"Invert",
"Invert the expand active elements");
2919 "use_mask_preserve",
2921 "Preserve Previous",
2922 "Preserve the previous state of the target data");
2924 "use_falloff_gradient",
2927 "Expand Using a linear falloff");
2930 "use_modify_active",
2933 "Modify the active Face Set instead of creating a new one");
2937 "use_reposition_pivot",
2940 "Reposition the sculpt transform pivot to the boundary of the expand active area");
2943 "max_geodesic_move_preview",
2947 "Max Vertex Count for Geodesic Move Preview",
2948 "Maximum number of vertices in the mesh for using geodesic falloff when "
2949 "moving the origin of expand. If the total number of vertices is greater "
2950 "than this value, the falloff will be set to spherical when moving",
2957 "Fill in mask if nothing is already masked");
2959 "normal_falloff_smooth",
2964 "Blurring steps for normal falloff",
const MTex * BKE_brush_mask_texture_get(const Brush *brush, const eObjectMode object_mode)
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)
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(void)
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)
ATTR_WARN_UNUSED_RESULT BMesh * bm
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)
MutableSpan< T > as_mutable_span()
void fill(const T &value) const
void reinitialize(const int64_t new_size)
constexpr void copy_from(Span< T > values) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr const T * end() const
constexpr const T * begin() const
constexpr bool is_empty() const
void append(const T &value)
IndexRange index_range() const
Span< T > as_span() const
void fill(const bool value)
bool remove(const StringRef attribute_id)
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)
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)
int64_t min_array_size() const
void foreach_index(Fn &&fn) const
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
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)
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)
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
bool vert_is_boundary(const GroupedSpan< int > vert_to_face_map, const Span< bool > hide_poly, const BitSpan boundary, const int vert)
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 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 int 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 void init_from_face_set_boundary(const Depsgraph &depsgraph, Object &ob, Cache &expand_cache, const int active_face_set, const bool internal_falloff)
@ 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 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 int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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)
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)
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 blur_geometry_data_array(const Object &object, const int iterations, const MutableSpan< float > data)
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)
void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
float3 symmetry_flip(const float3 &src, const ePaintSymmetryFlags symm)
void flush_update_step(bContext *C, UpdateType update_type)
Vector< int > find_symm_verts_mesh(const Depsgraph &depsgraph, const Object &object, const int original_vert, const float max_distance)
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
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)
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)
CCL_NAMESPACE_BEGIN ccl_device float fade(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_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
void SCULPT_vertex_random_access_ensure(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::GroupedSpan< int > edge_to_face_map
blender::ed::sculpt_paint::expand::Cache * expand_cache
int active_vert_index() const
blender::BitVector boundary
static SubdivCCGCoord from_index(const CCGKey &key, int index)
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > normals
blender::Array< float > masks
blender::Array< blender::float3 > positions
MutableVArraySpan< T > span
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)
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
void(* cancel)(bContext *C, wmOperator *op)
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)