91 for (const int id : face_sets.slice(range)) {
92 max = std::max(max, id);
96 [](
const int a,
const int b) {
return std::max(a,
b); });
103 if (cd_offset == -1) {
107 int next_face_set = 1;
112 next_face_set = std::max(next_face_set, fset);
115 return next_face_set + 1;
131 for (
const int i : face_sets.
span.index_range()) {
133 face_sets.
span[i] = new_id;
157 if (attributes.
contains(
".sculpt_face_set")) {
160 attributes.
add<
int>(
".sculpt_face_set",
161 bke::AttrDomain::Face,
170 if (!attributes.
contains(
".sculpt_face_set")) {
171 attributes.
add<
int>(
".sculpt_face_set",
172 bke::AttrDomain::Face,
205 ".sculpt_face_set", bke::AttrDomain::Face, 0);
219 for (
const int i :
verts.index_range()) {
220 if (unique == face_set::vert_has_unique_face_set(vert_to_face_map, face_sets,
verts[i])) {
239 const int node_start = i *
key.grid_area;
243 const int node_vert = node_start + offset;
244 if (factors[node_vert] == 0.0f) {
252 if (unique == face_set::vert_has_unique_face_set(
253 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, coord))
255 factors[node_vert] = 0.0f;
271 if (unique == face_set::vert_has_unique_face_set(face_set_offset, *vert)) {
304 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
307 TLS &tls = all_tls.
local();
310 tls.new_face_sets.resize(
faces.size());
313 calc_face_sets(
faces, new_face_sets);
314 if (array_utils::indexed_data_equal<int>(face_sets.
span,
faces, new_face_sets)) {
318 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::FaceSet);
320 node_changed[i] =
true;
323 else if (pbvh.
type() == bke::pbvh::Type::Grids) {
326 TLS &tls = all_tls.
local();
330 tls.new_face_sets.resize(
faces.size());
333 calc_face_sets(
faces, new_face_sets);
334 if (array_utils::indexed_data_equal<int>(face_sets.
span,
faces, new_face_sets)) {
338 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::FaceSet);
340 node_changed[i] =
true;
360 if (!attributes.
contains(
".sculpt_face_set")) {
369 const VArraySpan face_sets = *attributes.
lookup<
int>(
".sculpt_face_set", bke::AttrDomain::Face);
370 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
374 if (std::any_of(
faces.begin(),
faces.end(), [&](
const int face) {
375 return face_sets[face] != default_face_set;
378 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::FaceSet);
379 node_changed[i] =
true;
383 else if (pbvh.
type() == bke::pbvh::Type::Grids) {
390 if (std::any_of(
faces.begin(),
faces.end(), [&](
const int face) {
391 return face_sets[face] != default_face_set;
394 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::FaceSet);
395 node_changed[i] =
true;
401 attributes.
remove(
".sculpt_face_set");
419 if (pbvh.
type() == bke::pbvh::Type::BMesh) {
429 undo::push_begin(
scene,
object, op);
434 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
436 case CreateMode::Masked: {
437 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
441 bke::AttrDomain::Face);
443 bke::AttrDomain::Point);
444 if (!
mask.is_empty()) {
449 for (
const int i :
indices.index_range()) {
454 if (!std::any_of(face_verts.
begin(),
456 [&](
const int vert) { return mask[vert] > 0.5f; }))
460 face_sets[i] = next_face_set;
465 else if (pbvh.
type() == bke::pbvh::Type::Grids) {
469 const int grid_area = subdiv_ccg.
grid_area;
471 bke::AttrDomain::Face);
473 if (!masks.is_empty()) {
478 for (
const int i :
indices.index_range()) {
485 if (!std::any_of(face_masks.
begin(),
487 [&](
const float mask) { return mask > 0.5f; }))
491 face_sets[i] = next_face_set;
498 case CreateMode::Visible: {
499 const VArray<bool> hide_poly = *attributes.
lookup<
bool>(
".hide_poly", bke::AttrDomain::Face);
500 switch (array_utils::booleans_mix_calc(hide_poly)) {
501 case array_utils::BooleanMix::None:
502 case array_utils::BooleanMix::AllTrue:
503 case array_utils::BooleanMix::AllFalse:
509 case array_utils::BooleanMix::Mixed:
515 for (
const int i :
indices.index_range()) {
516 if (!hide_poly_span[
indices[i]]) {
517 face_sets[i] = next_face_set;
525 case CreateMode::All: {
530 face_sets.
fill(next_face_set);
534 case CreateMode::Selection: {
536 ".select_poly", bke::AttrDomain::Face,
false);
538 bke::AttrDomain::Face);
542 for (
const int i :
indices.index_range()) {
544 if (!hide_poly.is_empty() && hide_poly[i]) {
547 face_sets[i] = next_face_set;
556 undo::push_end(
object);
565 ot->
name =
"Create Face Set";
566 ot->
idname =
"SCULPT_OT_face_sets_create";
575 {int(CreateMode::Masked),
578 "Face Set from Masked",
579 "Create a new Face Set from the masked faces"},
580 {int(CreateMode::Visible),
583 "Face Set from Visible",
584 "Create a new Face Set from the visible vertices"},
585 {int(CreateMode::All),
588 "Face Set Full Mesh",
589 "Create an unique Face Set with all faces in the sculpt"},
590 {int(CreateMode::Selection),
593 "Face Set from Edit Mode Selection",
594 "Create an Face Set corresponding to the Edit Mode face selection"},
595 {0,
nullptr, 0,
nullptr,
nullptr},
635 int next_face_set = 1;
637 for (
const int i :
faces.index_range()) {
638 if (!hide_poly.
is_empty() && hide_poly[i]) {
641 if (visited_faces[i]) {
644 std::queue<int> queue;
646 while (hidden_face_sets.contains(next_face_set)) {
649 face_sets.
span[i] = next_face_set;
650 visited_faces[i].set(
true);
653 while (!queue.empty()) {
654 const int face_i = queue.front();
657 for (
const int edge_i : corner_edges.
slice(
faces[face_i])) {
659 if (neighbor_i == face_i) {
662 if (visited_faces[neighbor_i]) {
665 if (!hide_poly.
is_empty() && hide_poly[neighbor_i]) {
668 if (!test_fn(face_i, edge_i, neighbor_i)) {
672 face_sets.
span[neighbor_i] = next_face_set;
673 visited_faces[neighbor_i].set(
true);
674 queue.push(neighbor_i);
694 hidden_face_sets.
add(face_sets[i]);
698 return hidden_face_sets;
719 if (pbvh.
type() == bke::pbvh::Type::BMesh) {
724 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
729 undo::push_begin(
scene, ob, op);
730 undo::push_nodes(*
depsgraph, ob, node_mask, undo::Type::FaceSet);
738 case InitMode::LooseParts: {
740 ".hide_poly", bke::AttrDomain::Face,
false);
741 init_flood_fill(ob, [&](
const int from_face,
const int ,
const int to_face) {
742 return hide_poly[from_face] == hide_poly[to_face];
746 case InitMode::Materials: {
749 "material_index", bke::AttrDomain::Face, 0);
751 bke::AttrDomain::Face);
753 if (!hide_poly.is_empty() && hide_poly[i]) {
759 face_sets.
span[i] = material_indices[i] + 1;
765 case InitMode::Normals: {
767 init_flood_fill(ob, [&](
const int from_face,
const int ,
const int to_face) ->
bool {
768 return std::abs(
math::dot(face_normals[from_face], face_normals[to_face])) > threshold;
772 case InitMode::UVSeams: {
774 "uv_seam", bke::AttrDomain::Edge,
false);
776 [&](
const int ,
const int edge,
const int ) ->
bool {
777 return !uv_seams[edge];
781 case InitMode::Creases: {
783 "crease_edge", bke::AttrDomain::Edge, 0.0f);
785 [&](
const int ,
const int edge,
const int ) ->
bool {
786 return creases[edge] < threshold;
790 case InitMode::SharpEdges: {
792 "sharp_edge", bke::AttrDomain::Edge,
false);
794 [&](
const int ,
const int edge,
const int ) ->
bool {
795 return !sharp_edges[edge];
799 case InitMode::BevelWeight: {
801 "bevel_weight_edge", bke::AttrDomain::Edge, 0.0f);
803 [&](
const int ,
const int edge,
const int ) ->
bool {
804 return bevel_weights[edge] < threshold;
808 case InitMode::FaceSetBoundaries: {
810 init_flood_fill(ob, [&](
const int from_face,
const int ,
const int to_face) ->
bool {
811 return face_sets_copy[from_face] == face_sets_copy[to_face];
828 ot->
name =
"Init Face Sets";
829 ot->
idname =
"SCULPT_OT_face_sets_init";
838 {int(InitMode::LooseParts),
841 "Face Sets from Loose Parts",
842 "Create a Face Set per loose part in the mesh"},
843 {int(InitMode::Materials),
846 "Face Sets from Material Slots",
847 "Create a Face Set per Material Slot"},
848 {int(InitMode::Normals),
851 "Face Sets from Mesh Normals",
852 "Create Face Sets for Faces that have similar normal"},
853 {int(InitMode::UVSeams),
856 "Face Sets from UV Seams",
857 "Create Face Sets using UV Seams as boundaries"},
858 {int(InitMode::Creases),
861 "Face Sets from Edge Creases",
862 "Create Face Sets using Edge Creases as boundaries"},
863 {int(InitMode::BevelWeight),
866 "Face Sets from Bevel Weight",
867 "Create Face Sets using Bevel Weights as boundaries"},
868 {int(InitMode::SharpEdges),
871 "Face Sets from Sharp Edges",
872 "Create Face Sets using Sharp Edges as boundaries"},
873 {int(InitMode::FaceSetBoundaries),
874 "FACE_SET_BOUNDARIES",
876 "Face Sets from Face Set Boundaries",
877 "Create a Face Set per isolated Face Set"},
878 {0,
nullptr, 0,
nullptr,
nullptr},
888 "Minimum value to consider a certain attribute a boundary when creating the Face Sets",
909 ".hide_poly", bke::AttrDomain::Face);
919 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
922 TLS &tls = all_tls.
local();
925 tls.new_hide.resize(
faces.size());
928 calc_hide(
faces, new_hide);
929 if (array_utils::indexed_data_equal<bool>(hide_poly.
span,
faces, new_hide)) {
933 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::HideFace);
935 node_changed[i] =
true;
938 else if (pbvh.
type() == bke::pbvh::Type::Grids) {
941 TLS &tls = all_tls.
local();
945 tls.new_hide.resize(
faces.size());
948 calc_hide(
faces, new_hide);
949 if (array_utils::indexed_data_equal<bool>(hide_poly.
span,
faces, new_hide)) {
953 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::HideFace);
955 node_changed[i] =
true;
962 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
966 hide::sync_all_from_faces(
object);
972 switch (bke::object::pbvh_get(
object)->type()) {
973 case bke::pbvh::Type::Mesh:
974 hide::mesh_show_all(
depsgraph,
object, node_mask);
976 case bke::pbvh::Type::Grids:
977 hide::grids_show_all(
depsgraph,
object, node_mask);
979 case bke::pbvh::Type::BMesh:
997 if (pbvh.
type() == bke::pbvh::Type::BMesh) {
1005 undo::push_begin(
scene,
object, op);
1008 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1013 bke::AttrDomain::Face);
1016 case VisibilityMode::Toggle: {
1017 if (hide_poly.
contains(
true) || face_sets.is_empty()) {
1024 hide[i] = face_sets[
faces[i]] != active_face_set;
1030 case VisibilityMode::ShowActive:
1031 if (face_sets.is_empty()) {
1038 if (face_sets[
faces[i]] == active_face_set) {
1045 case VisibilityMode::HideActive:
1046 if (face_sets.is_empty()) {
1056 if (face_sets[
faces[i]] == active_face_set) {
1067 if (
ELEM(mode, VisibilityMode::Toggle, VisibilityMode::ShowActive)) {
1069 if (std::holds_alternative<std::monostate>(ss.
active_vert())) {
1082 undo::push_end(
object);
1086 islands::invalidate(*
object.sculpt);
1087 hide::tag_update_visibility(*C);
1105 const float mval_fl[2] = {float(event->
mval[0]), float(event->
mval[1])};
1114 ot->
name =
"Face Sets Visibility";
1115 ot->
idname =
"SCULPT_OT_face_set_change_visibility";
1116 ot->
description =
"Change the visibility of the Face Sets of the sculpt";
1125 {int(VisibilityMode::Toggle),
1128 "Toggle Visibility",
1129 "Hide all Face Sets except for the active one"},
1130 {int(VisibilityMode::ShowActive),
1133 "Show Active Face Set",
1134 "Show Active Face Set"},
1135 {int(VisibilityMode::HideActive),
1138 "Hide Active Face Sets",
1139 "Hide Active Face Sets"},
1140 {0,
nullptr, 0,
nullptr,
nullptr},
1158 if (pbvh.
type() == bke::pbvh::Type::BMesh) {
1165 if (!attributes.
contains(
".sculpt_face_set")) {
1169 const VArray<int> face_sets = *attributes.
lookup<
int>(
".sculpt_face_set", bke::AttrDomain::Face);
1178 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1188 ot->
name =
"Randomize Face Sets Colors";
1189 ot->
idname =
"SCULPT_OT_face_sets_randomize_colors";
1190 ot->
description =
"Generates a new set of random colors to render the Face Sets in the viewport";
1210 const int active_face_set_id,
1211 const bool modify_hidden,
1226 undo::push_begin(
scene,
object, op);
1229 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1232 for (
const int i :
indices.index_range()) {
1234 if (!modify_hidden && !hide_poly.
is_empty() && hide_poly[face]) {
1237 if (mode == EditMode::Grow) {
1238 for (
const int vert : corner_verts.
slice(
faces[face])) {
1239 for (
const int neighbor_face_index : vert_to_face_map[vert]) {
1240 if (neighbor_face_index == face) {
1243 if (prev_face_sets[neighbor_face_index] == active_face_set_id) {
1244 face_sets[i] = active_face_set_id;
1250 if (prev_face_sets[face] == active_face_set_id) {
1251 for (
const int vert_i : corner_verts.
slice(
faces[face])) {
1252 for (
const int neighbor_face_index : vert_to_face_map[vert_i]) {
1253 if (neighbor_face_index == face) {
1256 if (prev_face_sets[neighbor_face_index] != active_face_set_id) {
1257 face_sets[i] = prev_face_sets[neighbor_face_index];
1266 undo::push_end(
object);
1271 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
1275 bke::AttrDomain::Face);
1277 if (face_sets.is_empty()) {
1281 if (check_visible_only) {
1282 for (
const int i : face_sets.index_range()) {
1283 if (!hide_poly.
is_empty() && hide_poly[i]) {
1286 first_face_set = face_sets[i];
1291 first_face_set = face_sets[0];
1298 for (
const int i : face_sets.index_range()) {
1299 if (check_visible_only && !hide_poly.
is_empty() && hide_poly[i]) {
1302 if (face_sets[i] != first_face_set) {
1315 bke::AttrDomain::Face);
1324 convert_params.calc_face_normal =
true;
1334 if (!modify_hidden && !hide_poly.
is_empty() && hide_poly[face_index]) {
1352 const int active_face_set_id,
1354 const float strength)
1359 boundary::ensure_boundary_info(ob);
1366 const VArraySpan hide_poly = *attributes.
lookup<
bool>(
".hide_poly", bke::AttrDomain::Face);
1367 const VArraySpan face_sets = *attributes.
lookup<
int>(
".sculpt_face_set", bke::AttrDomain::Face);
1371 if (boundary::vert_is_boundary(vert_to_face_map, hide_poly, boundary_verts, vert)) {
1374 if (!
vert_has_face_set(vert_to_face_map, face_sets, vert, active_face_set_id)) {
1380 fair_verts[vert] =
true;
1391 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1396 LocalData &tls = all_tls.local();
1398 tls.translations.resize(
verts.size());
1400 for (
const int i :
verts.index_range()) {
1401 translations[i] = new_positions[
verts[i]] - positions[
verts[i]];
1411 const bool modify_hidden)
1414 if (pbvh.
type() == bke::pbvh::Type::BMesh) {
1419 if (mode == EditMode::DeleteGeometry) {
1420 if (pbvh.
type() == bke::pbvh::Type::Grids) {
1434 if (
ELEM(mode, EditMode::FairPositions, EditMode::FairTangency)) {
1435 if (pbvh.
type() == bke::pbvh::Type::Grids) {
1443 if (
ELEM(mode, EditMode::Grow, EditMode::Shrink)) {
1444 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
1447 if (!attributes.
contains(
".sculpt_face_set")) {
1463 undo::geometry_begin(
scene, ob, op);
1465 undo::geometry_end(ob);
1480 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1484 undo::push_begin(
scene, ob, op);
1485 undo::push_nodes(
depsgraph, ob, node_mask, undo::Type::Position);
1488 case EditMode::FairPositions:
1491 case EditMode::FairTangency:
1531 const int active_face_set =
RNA_int_get(op->
ptr,
"active_face_set");
1536 case EditMode::DeleteGeometry:
1539 case EditMode::Grow:
1540 case EditMode::Shrink:
1543 case EditMode::FairPositions:
1544 case EditMode::FairTangency:
1570 const float mval_fl[2] = {float(event->
mval[0]), float(event->
mval[1])};
1582 ot->
name =
"Edit Face Set";
1583 ot->
idname =
"SCULPT_OT_face_set_edit";
1593 ot->
srna,
"active_face_set", 1, 0, INT_MAX,
"Active Face Set",
"", 0, 64);
1597 {int(EditMode::Grow),
1601 "Grows the Face Sets boundary by one face based on mesh topology"},
1602 {int(EditMode::Shrink),
1606 "Shrinks the Face Sets boundary by one face based on mesh topology"},
1607 {int(EditMode::DeleteGeometry),
1611 "Deletes the faces that are assigned to the Face Set"},
1612 {int(EditMode::FairPositions),
1616 "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
1617 "vertex positions"},
1618 {int(EditMode::FairTangency),
1622 "Creates a smooth as possible geometry patch from the Face Set minimizing changes in "
1624 {0,
nullptr, 0,
nullptr,
nullptr},
1634 "Apply the edit operation to hidden geometry");
1682 if (pbvh.
type() == bke::pbvh::Type::Mesh) {
1685 undo::push_node(
depsgraph, *gesture_data.
vc.
obact, &nodes[i], undo::Type::FaceSet);
1686 bool any_updated =
false;
1687 for (
const int face : nodes[i].faces()) {
1688 if (!hide_poly.
is_empty() && hide_poly[face]) {
1692 const float3 face_center = bke::mesh::face_center_calc(positions, face_verts);
1693 const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts);
1694 if (!gesture::is_affected(gesture_data, face_center, face_normal)) {
1697 face_sets.span[face] = new_face_set;
1701 node_changed[i] =
true;
1705 else if (pbvh.
type() == bke::pbvh::Type::Grids) {
1708 TLS &tls = all_tls.
local();
1709 undo::push_node(
depsgraph, *gesture_data.
vc.
obact, &nodes[i], undo::Type::FaceSet);
1710 const Span<int> node_faces = bke::pbvh::node_face_indices_calc_grids(
1713 bool any_updated =
false;
1714 for (
const int face : node_faces) {
1715 if (!hide_poly.
is_empty() && hide_poly[face]) {
1719 const float3 face_center = bke::mesh::face_center_calc(positions, face_verts);
1720 const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts);
1721 if (!gesture::is_affected(gesture_data, face_center, face_normal)) {
1724 face_sets.span[face] = new_face_set;
1728 node_changed[i] =
true;
1745 const int offset = face_set::ensure_face_sets_bmesh(*gesture_data.
vc.
obact);
1750 undo::push_node(
depsgraph, *gesture_data.
vc.
obact, &nodes[i], undo::Type::FaceSet);
1752 bool any_updated =
false;
1759 if (!gesture::is_affected(gesture_data, center, face->no)) {
1767 node_changed[i] =
true;
1772 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
1781 switch (bke::object::pbvh_get(*gesture_data.
vc.
obact)->type()) {
1782 case bke::pbvh::Type::Grids:
1783 case bke::pbvh::Type::Mesh:
1786 case bke::pbvh::Type::BMesh:
1794 undo::push_end(*gesture_data.
vc.
obact);
1809 face_set_operation->
new_face_set_id = face_set::find_next_available_id(
object);
1825 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_box(C, op);
1826 if (!gesture_data) {
1830 gesture::apply(*C, *gesture_data, *op);
1847 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_lasso(C, op);
1848 if (!gesture_data) {
1852 gesture::apply(*C, *gesture_data, *op);
1869 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_line(C, op);
1870 if (!gesture_data) {
1874 gesture::apply(*C, *gesture_data, *op);
1891 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_polyline(C, op);
1892 if (!gesture_data) {
1896 gesture::apply(*C, *gesture_data, *op);
1902 ot->
name =
"Face Set Lasso Gesture";
1903 ot->
idname =
"SCULPT_OT_face_set_polyline_gesture";
1904 ot->
description =
"Add a face set in a shape defined by the cursor";
1915 gesture::operator_properties(
ot, gesture::ShapeType::Lasso);
1920 ot->
name =
"Face Set Box Gesture";
1921 ot->
idname =
"SCULPT_OT_face_set_box_gesture";
1922 ot->
description =
"Add a face set in a rectangle defined by the cursor";
1933 gesture::operator_properties(
ot, gesture::ShapeType::Box);
1938 ot->
name =
"Face Set Lasso Gesture";
1939 ot->
idname =
"SCULPT_OT_face_set_lasso_gesture";
1940 ot->
description =
"Add a face set in a shape defined by the cursor";
1951 gesture::operator_properties(
ot, gesture::ShapeType::Lasso);
1956 ot->
name =
"Face Set Line Gesture";
1957 ot->
idname =
"SCULPT_OT_face_set_line_gesture";
1958 ot->
description =
"Add a face set to one side of a line defined by the cursor";
1969 gesture::operator_properties(
ot, gesture::ShapeType::Line);
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
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)
ToolSettings * CTX_data_tool_settings(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_has_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
void BKE_mesh_batch_cache_dirty_tag(Mesh *mesh, eMeshBatchDirtyMode mode)
@ BKE_MESH_BATCH_DIRTY_ALL
@ MESH_FAIRING_DEPTH_POSITION
@ MESH_FAIRING_DEPTH_TANGENCY
void BKE_mesh_prefair_and_fair_verts(Mesh *mesh, blender::MutableSpan< blender::float3 > deform_vert_positions, const bool affected_verts[], eMeshFairingDepth depth)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_original_mesh(const Object *object)
#define SCULPT_FACE_SET_NONE
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
void BKE_sculptsession_free_pbvh(Object &object)
A BVH for high poly meshes.
const blender::Set< BMFace *, 0 > & BKE_pbvh_bmesh_node_faces(blender::bke::pbvh::BMeshNode *node)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
#define BLI_assert_unreachable()
BLI_INLINE float BLI_hash_int_01(unsigned int k)
MINLINE int max_ii(int a, int b)
MINLINE int clamp_i(int value, int min, int max)
void mul_m4_v3(const float M[4][4], float r[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define POINTER_OFFSET(v, ofs)
#define BLT_I18NCONTEXT_AMOUNT
void DEG_id_tag_update(ID *id, unsigned int flags)
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
@ OPTYPE_DEPENDS_ON_CURSOR
#define BM_ELEM_CD_SET_INT(ele, offset, f)
void BM_mesh_delete_hflag_context(BMesh *bm, const char hflag, const int type)
#define BM_elem_index_get(ele)
#define BM_elem_flag_set(ele, hflag, val)
#define BM_elem_flag_test(ele, hflag)
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const StringRef name)
#define BM_ITER_MESH(ele, iter, bm, itype)
void BM_mesh_elem_hflag_disable_all(BMesh *bm, const char htype, const char hflag, const bool respecthide)
void BM_mesh_free(BMesh *bm)
BMesh Free Mesh.
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_table_init(BMesh *bm, const char htype)
BMesh * BM_mesh_create(const BMAllocTemplate *allocsize, const BMeshCreateParams *params)
BMesh Make Mesh.
#define BMALLOC_TEMPLATE_FROM_ME(...)
void BM_mesh_bm_from_me(BMesh *bm, const Mesh *mesh, const BMeshFromMeshParams *params)
void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *mesh, const BMeshToMeshParams *params)
void BM_face_calc_center_median(const BMFace *f, float r_cent[3])
MutableSpan< T > as_mutable_span()
constexpr int64_t size() const
constexpr void fill(const T &value) const
constexpr Span< T > as_span() const
constexpr IndexRange index_range() const
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
constexpr bool contains(const T &value) const
bool contains(StringRef attribute_id) const
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
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
void tag_positions_changed(const IndexMask &node_mask)
Span< NodeT > nodes() const
void update_bounds(const Depsgraph &depsgraph, const Object &object)
void tag_face_sets_changed(const IndexMask &node_mask)
void tag_visibility_changed(const IndexMask &node_mask)
void update_visibility(const Object &object)
int64_t min_array_size() const
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
void * MEM_callocN(size_t len, const char *str)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
pbvh::Tree * pbvh_get(Object &object)
static void face_hide_update(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const FunctionRef< void(Span< int >, MutableSpan< bool >)> calc_hide)
static bool edit_is_operation_valid(const Object &object, const EditMode mode, const bool modify_hidden)
void filter_verts_with_unique_face_sets_mesh(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const bool unique, const Span< int > verts, const MutableSpan< float > factors)
int find_next_available_id(Object &object)
int ensure_face_sets_bmesh(Object &object)
static void gesture_apply_for_symmetry_pass(bContext &, gesture::GestureData &gesture_data)
static wmOperatorStatus init_op_exec(bContext *C, wmOperator *op)
static wmOperatorStatus gesture_box_exec(bContext *C, wmOperator *op)
static void edit_fairing(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const int active_face_set_id, const eMeshFairingDepth fair_order, const float strength)
static wmOperatorStatus gesture_line_exec(bContext *C, wmOperator *op)
static wmOperatorStatus change_visibility_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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)
void SCULPT_OT_face_set_lasso_gesture(wmOperatorType *ot)
static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &gesture_data)
bool create_face_sets_mesh(Object &object)
void initialize_none_to_id(Mesh *mesh, int new_id)
static bool edit_op_init(bContext *C, wmOperator *op)
static wmOperatorStatus randomize_colors_exec(bContext *C, wmOperator *)
void SCULPT_OT_face_set_line_gesture(wmOperatorType *ot)
void SCULPT_OT_face_set_polyline_gesture(wmOperatorType *ot)
static void clear_face_sets(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
static void delete_geometry(Object &ob, const int active_face_set_id, const bool modify_hidden)
static wmOperatorStatus change_visibility_exec(bContext *C, wmOperator *op)
void SCULPT_OT_face_sets_init(wmOperatorType *ot)
int active_update_and_get(bContext *C, Object &ob, const float mval_fl[2])
static wmOperatorStatus gesture_lasso_exec(bContext *C, wmOperator *op)
static void edit_grow_shrink(const Depsgraph &depsgraph, const Scene &scene, Object &object, const EditMode mode, const int active_face_set_id, const bool modify_hidden, wmOperator *op)
static wmOperatorStatus edit_op_exec(bContext *C, wmOperator *op)
void filter_verts_with_unique_face_sets_bmesh(int face_set_offset, const bool unique, const Set< BMVert *, 0 > &verts, const MutableSpan< float > factors)
static void show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
Array< int > duplicate_face_sets(const Mesh &mesh)
static wmOperatorStatus gesture_polyline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SCULPT_OT_face_sets_create(wmOperatorType *ot)
Set< int > gather_hidden_face_sets(const Span< bool > hide_poly, const Span< int > face_sets)
static void gesture_apply_mesh(gesture::GestureData &gesture_data, const IndexMask &node_mask)
void SCULPT_OT_face_set_change_visibility(wmOperatorType *ot)
void filter_verts_with_unique_face_sets_grids(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const SubdivCCG &subdiv_ccg, const bool unique, const Span< int > grids, const MutableSpan< float > factors)
void SCULPT_OT_face_sets_randomize_colors(wmOperatorType *ot)
static bool check_single_face_set(const Object &object, const bool check_visible_only)
bke::SpanAttributeWriter< int > ensure_face_sets_mesh(Mesh &mesh)
static void face_sets_update(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const FunctionRef< void(Span< int >, MutableSpan< int >)> calc_face_sets)
static wmOperatorStatus gesture_line_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static wmOperatorStatus gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SCULPT_OT_face_sets_edit(wmOperatorType *ot)
static void gesture_end(bContext &, gesture::GestureData &gesture_data)
static void gesture_apply_bmesh(gesture::GestureData &gesture_data, const IndexMask &node_mask)
static wmOperatorStatus create_op_exec(bContext *C, wmOperator *op)
static void init_operation(gesture::GestureData &gesture_data, wmOperator &)
static wmOperatorStatus edit_op_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void SCULPT_OT_face_set_box_gesture(wmOperatorType *ot)
static void edit_modify_coordinates(bContext *C, Object &ob, const int active_face_set, const EditMode mode, wmOperator *op)
static wmOperatorStatus gesture_polyline_exec(bContext *C, wmOperator *op)
static void init_flood_fill(Object &ob, const FaceSetsFloodFillFn &test_fn)
static wmOperatorStatus gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int active_face_set_get(const Object &object)
static void edit_modify_geometry(bContext *C, Object &ob, const int active_face_set, const bool modify_hidden, wmOperator *op)
void vert_random_access_ensure(Object &object)
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
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)
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
void flush_update_step(const bContext *C, const UpdateType update_type)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
int RNA_int_get(PointerRNA *ptr, const char *name)
float RNA_float_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_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
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)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
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)
bool SCULPT_mode_poll_view3d(bContext *C)
bool SCULPT_mode_poll(bContext *C)
void SCULPT_tag_update_overlays(bContext *C)
int face_sets_color_default
struct SculptSession * sculpt
SculptVertexInfo vertex_info
ActiveVert active_vert() const
blender::Array< int > edge_to_face_offsets
blender::float3 active_vert_position(const Depsgraph &depsgraph, const Object &object) const
blender::GroupedSpan< int > edge_to_face_map
blender::Array< int > edge_to_face_indices
blender::BitVector boundary
blender::Array< float > masks
float average_stroke_accum[3]
int average_stroke_counter
MutableVArraySpan< T > span
void(* end)(bContext &, GestureData &)
void(* begin)(bContext &, wmOperator &, GestureData &)
void(* apply_for_symmetry_pass)(bContext &, GestureData &)
wmOperatorStatus(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
wmOperatorStatus(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
wmOperatorStatus(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorStatus WM_gesture_polyline_modal(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_straightline_active_side_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_polyline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorStatus WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
void WM_operator_properties_border(wmOperatorType *ot)
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
void WM_operator_properties_gesture_polyline(wmOperatorType *ot)