63 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
65 const VArray mask = *attributes.lookup_or_default<
float>(
68 mask.materialize(result);
76 return subdiv_ccg.
masks;
87 for (
const int i : result.index_range()) {
105 for (
const int i : masks.index_range()) {
106 masks[i] += (new_masks[i] - masks[i]) * factors[i];
112 for (
float &mask : masks) {
113 mask = std::clamp(mask, 0.0f, 1.0f);
119 for (
float &mask : masks) {
198 Mesh &mesh = *
static_cast<Mesh *
>(
object.data);
227 node_changed[i] =
true;
244 return std::all_of(range.begin(), range.end(), [&](
const int i) {
245 return masks.slice(bke::ccg::grid_range(key, grids[i])) ==
246 values.slice(bke::ccg::grid_range(key, i));
292 "Set mask to the level specified by the 'value' property"},
297 "Set mask to the level specified by the inverted 'value' property"},
312 indices.resize(
verts.size());
313 const int *end = std::copy_if(
verts.begin(),
verts.end(), indices.begin(), [&](
const int vert) {
314 return hide_vert[vert];
316 indices.resize(end - indices.begin());
326 Mesh &mesh = *
static_cast<Mesh *
>(
object.data);
329 if (mask.is_empty()) {
352 if (std::any_of(
verts.begin(),
verts.end(), [&](
int i) { return mask[i] > 0.0f; })) {
360 if (hidden_masked_verts) {
366 node_mask,
GrainSize(1), memory, [&](
const int i) {
369 verts.begin(),
verts.end(), [&](
const int i) { return mask[i] != 0.0f; });
373 attributes.remove(
".sculpt_mask");
378 pbvh.tag_masks_changed(changed_nodes);
390 Mesh &mesh = *
static_cast<Mesh *
>(
object.data);
392 const VArraySpan hide_vert = *attributes.lookup<
bool>(
".hide_vert", bke::AttrDomain::Point);
400 ".sculpt_mask", bke::AttrDomain::Point);
407 const Span<int> verts = hide::node_visible_verts(nodes[i], hide_vert, index_data);
408 if (std::all_of(
verts.begin(),
verts.end(), [&](
int i) { return mask.span[i] == value; })) {
411 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::Mask);
412 mask.span.fill_indices(
verts, value);
413 node_changed[i] =
true;
417 const IndexMask changed_nodes = IndexMask::from_bools(node_mask, node_changed, memory);
455 const Span<int> grid_indices = nodes[i].grids();
456 if (std::all_of(grid_indices.
begin(), grid_indices.
end(), [&](
const int grid) {
457 const Span<float> grid_masks = masks.slice(bke::ccg::grid_range(key, grid));
458 return std::all_of(grid_masks.begin(), grid_masks.end(), [&](const float mask) {
459 return mask == value;
465 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::Mask);
468 for (
const int grid : grid_indices) {
469 masks.slice(bke::ccg::grid_range(key, grid)).fill(value);
473 for (
const int grid : grid_indices) {
475 bits::foreach_0_index(grid_hidden[grid], [&](
const int i) { grid_masks[i] = value; });
478 node_changed[i] =
true;
482 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
483 if (node_changed.is_empty()) {
486 pbvh.tag_masks_changed(changed_nodes);
505 if (value == 0.0f && offset == -1) {
514 undo::push_nodes(
depsgraph,
object, node_mask, undo::Type::Mask);
519 bool changed =
false;
529 node_changed[i] =
true;
533 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
549 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
550 switch (pbvh.
type()) {
551 case bke::pbvh::Type::Mesh:
554 case bke::pbvh::Type::Grids:
557 case bke::pbvh::Type::BMesh:
574 undo::push_nodes(
depsgraph,
object, node_mask, undo::Type::Mask);
584 const Span<int> grid_indices = nodes[i].grids();
586 for (const int grid : grid_indices) {
587 for (float &value : masks.slice(bke::ccg::grid_range(key, grid))) {
588 value = 1.0f - value;
593 for (
const int grid : grid_indices) {
595 bits::foreach_0_index(grid_hidden[grid],
596 [&](
const int i) { grid_masks[i] = 1.0f - grid_masks[i]; });
599 bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
601 pbvh.tag_masks_changed(node_mask);
612 BMesh &
bm = *
object.sculpt->bm;
619 undo::push_nodes(
depsgraph,
object, node_mask, undo::Type::Mask);
626 bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
634 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(*bke::object::pbvh_get(
object), memory);
635 switch (bke::object::pbvh_get(
object)->type()) {
636 case bke::pbvh::Type::Mesh:
639 for (
const int vert :
verts) {
640 mask[vert] = 1.0f - mask[vert];
644 case bke::pbvh::Type::Grids:
647 case bke::pbvh::Type::BMesh:
665 undo::push_begin(scene,
object, op);
667 case FloodFillMode::Value:
670 case FloodFillMode::InverseValue:
673 case FloodFillMode::InverseMeshValue:
678 undo::push_end(
object);
688 ot->
name =
"Mask Flood Fill";
689 ot->
idname =
"PAINT_OT_mask_flood_fill";
690 ot->
description =
"Fill the whole mask with a given value, or invert its values";
707 "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
731 undo::push_begin(scene, *gesture_data.
vc.
obact, &op);
737 case FloodFillMode::Value:
739 case FloodFillMode::InverseValue:
741 case FloodFillMode::InverseMeshValue:
754 switch (bke::object::pbvh_get(
object)->type()) {
755 case bke::pbvh::Type::Mesh: {
760 for (
const int i :
verts.index_range()) {
761 const int vert =
verts[i];
762 if (gesture::is_affected(gesture_data, positions[vert], normals[vert])) {
769 case bke::pbvh::Type::Grids: {
783 bool any_changed =
false;
784 for (
const int grid : node.grids()) {
785 const int vert_start = grid * key.
grid_area;
787 const int vert = vert_start + i;
788 if (gesture::is_affected(gesture_data, positions[vert], normals[vert])) {
789 float &mask = masks[vert];
792 undo::push_node(
depsgraph,
object, &node, undo::Type::Mask);
798 bke::pbvh::node_update_mask_grids(key, masks, node);
799 node_changed[node_index] =
true;
808 case bke::pbvh::Type::BMesh: {
817 bool any_changed =
false;
819 if (gesture::is_affected(gesture_data, vert->co, vert->no)) {
823 undo::push_node(
depsgraph,
object, &nodes[i], undo::Type::Mask);
830 bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
831 node_changed[i] =
true;
846 if (bke::object::pbvh_get(
object)->type() == bke::pbvh::Type::Grids) {
849 undo::push_end(
object);
855 MEM_cnew<MaskOperation>(__func__));
882 "Mask level to use when mode is 'Value'; zero means no masking and one is fully masked",
889 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_box(C, op);
894 gesture::apply(*C, *gesture_data, *op);
900 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_lasso(C, op);
905 gesture::apply(*C, *gesture_data, *op);
911 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_line(C, op);
916 gesture::apply(*C, *gesture_data, *op);
922 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_polyline(C, op);
927 gesture::apply(*C, *gesture_data, *op);
933 ot->
name =
"Mask Lasso Gesture";
934 ot->
idname =
"PAINT_OT_mask_lasso_gesture";
935 ot->
description =
"Mask within a shape defined by the cursor";
946 gesture::operator_properties(
ot, gesture::ShapeType::Lasso);
953 ot->
name =
"Mask Box Gesture";
954 ot->
idname =
"PAINT_OT_mask_box_gesture";
955 ot->
description =
"Mask within a rectangle defined by the cursor";
966 gesture::operator_properties(
ot, gesture::ShapeType::Box);
973 ot->
name =
"Mask Line Gesture";
974 ot->
idname =
"PAINT_OT_mask_line_gesture";
975 ot->
description =
"Mask to one side of a line defined by the cursor";
986 gesture::operator_properties(
ot, gesture::ShapeType::Line);
993 ot->
name =
"Mask Polyline Gesture";
994 ot->
idname =
"PAINT_OT_mask_polyline_gesture";
995 ot->
description =
"Mask within a shape defined by the cursor";
1006 gesture::operator_properties(
ot, gesture::ShapeType::Lasso);
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)
Main * CTX_data_main(const bContext *C)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresModifiedFlags flags)
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_mask_layers_ensure(Depsgraph *depsgraph, Main *bmain, Object *ob, MultiresModifierData *mmd)
A BVH for high poly meshes.
bool BKE_pbvh_node_fully_hidden_get(const blender::bke::pbvh::Node &node)
void BKE_pbvh_node_fully_unmasked_set(blender::bke::pbvh::Node &node, int fully_masked)
void BKE_pbvh_node_fully_masked_set(blender::bke::pbvh::Node &node, int fully_masked)
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
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)
@ MULTIRES_COORDS_MODIFIED
#define BLI_assert_unreachable()
Object is a sort of wrapper for general info.
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_flag_test(ele, hflag)
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)
static T sum(const btAlignedObjectArray< T > &items)
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr void fill(const T &value) 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
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
Span< T > as_span() const
Span< NodeT > nodes() const
void tag_masks_changed(const IndexMask &node_mask)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
IndexMask slice(IndexRange range) const
int64_t min_array_size() const
IndexRange index_range() const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
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
bool indexed_data_equal(const Span< T > all_values, const Span< int > indices, const Span< T > values)
pbvh::Tree * pbvh_get(Object &object)
void node_update_mask_mesh(Span< float > mask, MeshNode &node)
Span< int > node_visible_verts(const bke::pbvh::MeshNode &node, const Span< bool > hide_vert, Vector< int > &indices)
bool mask_equals_array_bmesh(const int mask_offset, const Set< BMVert *, 0 > &verts, const Span< float > values)
void scatter_mask_grids(const Span< float > mask, SubdivCCG &subdiv_ccg, const Span< int > grids)
static void gesture_end(bContext &C, gesture::GestureData &gesture_data)
static int gesture_box_exec(bContext *C, wmOperator *op)
static float average_masks(const int mask_offset, const Span< const BMVert * > verts)
void PAINT_OT_mask_polyline_gesture(wmOperatorType *ot)
bool mask_equals_array_grids(const Span< float > masks, const CCGKey &key, const Span< int > grids, const Span< float > values)
void PAINT_OT_mask_line_gesture(wmOperatorType *ot)
void write_mask_mesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, FunctionRef< void(MutableSpan< float >, Span< int >)> write_fn)
static const EnumPropertyItem mode_items[]
static int gesture_polyline_exec(bContext *C, wmOperator *op)
void mix_new_masks(const Span< float > new_masks, const Span< float > factors, const MutableSpan< float > masks)
static void fill_mask_grids(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, const float value, const IndexMask &node_mask)
static void invert_mask_bmesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
void update_mask_mesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, FunctionRef< void(MutableSpan< float >, Span< int >)> update_fn)
static void init_operation(bContext &C, gesture::GestureData &gesture_data, wmOperator &op)
static int gesture_lasso_exec(bContext *C, wmOperator *op)
static bool try_remove_mask_mesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
void scatter_mask_bmesh(const Span< float > mask, const BMesh &bm, const Set< BMVert *, 0 > &verts)
static void gesture_apply_for_symmetry_pass(bContext &, gesture::GestureData &gesture_data)
void gather_mask_bmesh(const BMesh &bm, const Set< BMVert *, 0 > &verts, const MutableSpan< float > r_mask)
static int mask_flood_fill_exec(bContext *C, wmOperator *op)
static void gesture_begin(bContext &C, wmOperator &op, gesture::GestureData &gesture_data)
Array< float > duplicate_mask(const Object &object)
static Span< int > get_hidden_verts(const bke::pbvh::MeshNode &node, const Span< bool > hide_vert, Vector< int > &indices)
static void fill_mask(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, const float value)
void invert_mask(const MutableSpan< float > masks)
void gather_mask_grids(const SubdivCCG &subdiv_ccg, const Span< int > grids, const MutableSpan< float > r_mask)
static int gesture_line_exec(bContext *C, wmOperator *op)
static void fill_mask_bmesh(const Depsgraph &depsgraph, Object &object, const float value, const IndexMask &node_mask)
static float mask_gesture_get_new_value(const float elem, FloodFillMode mode, float value)
static void gesture_operator_properties(wmOperatorType *ot)
void PAINT_OT_mask_box_gesture(wmOperatorType *ot)
static void invert_mask_grids(Main &bmain, const Scene &scene, Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
void PAINT_OT_mask_lasso_gesture(wmOperatorType *ot)
void clamp_mask(const MutableSpan< float > masks)
void PAINT_OT_mask_flood_fill(wmOperatorType *ot)
void average_neighbor_mask_bmesh(const int mask_offset, const Set< BMVert *, 0 > &verts, const MutableSpan< float > new_masks)
static void fill_mask_mesh(const Depsgraph &depsgraph, Object &object, const float value, const IndexMask &node_mask)
void push_nodes(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Type type)
void push_node(const Depsgraph &depsgraph, const Object &object, const bke::pbvh::Node *node, Type type)
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
float RNA_float_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)
bool SCULPT_mode_poll_view3d(bContext *C)
bool SCULPT_mode_poll(bContext *C)
void SCULPT_tag_update_overlays(bContext *C)
blender::Array< float > masks
blender::Array< blender::float3 > positions
void(* end)(bContext &, GestureData &)
void(* begin)(bContext &, wmOperator &, GestureData &)
void(* apply_for_symmetry_pass)(bContext &, GestureData &)
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
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
int WM_gesture_polyline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_polyline_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_straightline_active_side_invoke(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)