Blender V5.0
paint_hide.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2010 by Nicholas Bishop. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "paint_hide.hh"
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_array_utils.hh"
14#include "BLI_bit_span_ops.hh"
16#include "BLI_utildefines.h"
17#include "BLI_vector.hh"
18
19#include "DNA_object_types.h"
20
21#include "BKE_attribute.hh"
22#include "BKE_ccg.hh"
23#include "BKE_context.hh"
24#include "BKE_mesh.hh"
25#include "BKE_multires.hh"
26#include "BKE_paint.hh"
27#include "BKE_paint_bvh.hh"
28#include "BKE_subdiv_ccg.hh"
29
30#include "DEG_depsgraph.hh"
31
32#include "WM_api.hh"
33#include "WM_types.hh"
34
35#include "ED_screen.hh"
36
37#include "RNA_access.hh"
38#include "RNA_define.hh"
39
40#include "bmesh.hh"
41
42#include "mesh_brush_common.hh"
43#include "paint_intern.hh"
44#include "sculpt_gesture.hh"
45#include "sculpt_intern.hh"
46#include "sculpt_islands.hh"
47#include "sculpt_undo.hh"
48
50
51/* -------------------------------------------------------------------- */
54
56{
57 SculptSession &ss = *object.sculpt;
58 Mesh &mesh = *static_cast<Mesh *>(object.data);
59
61
62 switch (bke::object::pbvh_get(object)->type()) {
64 /* We may have adjusted the ".hide_poly" attribute, now make the hide status attributes for
65 * vertices and edges consistent. */
67 break;
68 }
70 /* In addition to making the hide status of the base mesh consistent, we also have to
71 * propagate the status to the Multires grids. */
74 break;
75 }
77 BMesh &bm = *ss.bm;
78 BMIter iter;
79 BMFace *f;
80
81 /* Hide all verts and edges attached to faces. */
82 BM_ITER_MESH (f, &iter, &bm, BM_FACES_OF_MESH) {
83 BMLoop *l = f->l_first;
84 do {
87 } while ((l = l->next) != f->l_first);
88 }
89
90 /* Unhide verts and edges attached to visible faces. */
91 BM_ITER_MESH (f, &iter, &bm, BM_FACES_OF_MESH) {
93 continue;
94 }
95
96 BMLoop *l = f->l_first;
97 do {
100 } while ((l = l->next) != f->l_first);
101 }
102 break;
103 }
104 }
105}
106
121
122void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
123{
124 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
126 Mesh &mesh = *static_cast<Mesh *>(object.data);
127 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
128 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
129
130 if (!hide_vert.is_empty()) {
131 IndexMaskMemory memory;
132 const IndexMask changed_nodes = IndexMask::from_predicate(
133 node_mask, GrainSize(1), memory, [&](const int i) {
134 const Span<int> verts = nodes[i].verts();
135 return std::any_of(
136 verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; });
137 });
138 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
139 pbvh.tag_visibility_changed(changed_nodes);
140 }
141
142 attributes.remove(".hide_vert");
144 pbvh.update_visibility(object);
145}
146
147void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
148{
149 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
151 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
152 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
153
154 if (!grid_hidden.is_empty()) {
155 IndexMaskMemory memory;
156 const IndexMask changed_nodes = IndexMask::from_predicate(
157 node_mask, GrainSize(1), memory, [&](const int i) {
158 const Span<int> grids = nodes[i].grids();
159 return std::any_of(grids.begin(), grids.end(), [&](const int i) {
160 return bits::any_bit_set(grid_hidden[i]);
161 });
162 });
163 if (changed_nodes.is_empty()) {
164 return;
165 }
166 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
167 pbvh.tag_visibility_changed(changed_nodes);
168 }
169
172 pbvh.update_visibility(object);
174}
175
177
178/* -------------------------------------------------------------------- */
182
183enum class VisAction {
184 Hide = 0,
185 Show = 1,
186};
187
188static bool action_to_hide(const VisAction action)
189{
190 return action == VisAction::Hide;
191}
192
193/* Calculates whether a face should be hidden based on all of its corner vertices. */
194static void calc_face_hide(const Span<int> node_faces,
196 const Span<int> corner_verts,
197 const Span<bool> hide_vert,
198 MutableSpan<bool> hide_face)
199{
200 for (const int i : node_faces.index_range()) {
201 Span<int> face_verts = corner_verts.slice(faces[node_faces[i]]);
202 hide_face[i] = std::any_of(
203 face_verts.begin(), face_verts.end(), [&](const int v) { return hide_vert[v]; });
204 }
205}
206
207/* Updates a node's face's visibility based on the updated vertex visibility. */
209 bke::pbvh::Tree &pbvh,
210 const IndexMask &node_mask,
211 const Span<bool> hide_vert)
212{
213 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
214
215 const OffsetIndices<int> faces = mesh.faces();
216 const Span<int> corner_verts = mesh.corner_verts();
217
219 ".hide_poly", bke::AttrDomain::Face);
220
222
223 Array<bool> node_changed(node_mask.min_array_size(), false);
224
225 struct TLS {
226 Vector<bool> new_hide;
227 };
229 node_mask.foreach_index(GrainSize(1), [&](const int i) {
230 TLS &tls = all_tls.local();
231 const Span<int> node_faces = nodes[i].faces();
232
233 tls.new_hide.resize(node_faces.size());
234 gather_data_mesh(hide_poly.span.as_span(), node_faces, tls.new_hide.as_mutable_span());
235
236 calc_face_hide(node_faces, faces, corner_verts, hide_vert, tls.new_hide.as_mutable_span());
237
238 if (array_utils::indexed_data_equal<bool>(hide_poly.span, node_faces, tls.new_hide)) {
239 return;
240 }
241
242 scatter_data_mesh(tls.new_hide.as_span(), node_faces, hide_poly.span);
243 node_changed[i] = true;
245 });
246 hide_poly.finish();
247
248 IndexMaskMemory memory;
249 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
250 if (changed_nodes.is_empty()) {
251 return;
252 }
253 pbvh.tag_visibility_changed(node_mask);
254}
255
256/* Updates a node's face's visibility based on the updated vertex visibility. */
257static void flush_face_changes(Mesh &mesh, const Span<bool> hide_vert)
258{
259 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
260
262 ".hide_poly", bke::AttrDomain::Face);
263
264 bke::mesh_face_hide_from_vert(mesh.faces(), mesh.corner_verts(), hide_vert, hide_poly.span);
265 hide_poly.finish();
266}
267
268/* Updates all of a mesh's edge visibility based on vertex visibility. */
269static void flush_edge_changes(Mesh &mesh, const Span<bool> hide_vert)
270{
271 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
272
274 ".hide_edge", bke::AttrDomain::Edge);
275 bke::mesh_edge_hide_from_vert(mesh.edges(), hide_vert, hide_edge.span);
276 hide_edge.finish();
277}
278
279static void vert_hide_update(const Depsgraph &depsgraph,
280 Object &object,
281 const IndexMask &node_mask,
282 const FunctionRef<void(Span<int>, MutableSpan<bool>)> calc_hide)
283{
284 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
286
287 Mesh &mesh = *static_cast<Mesh *>(object.data);
288 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
290 ".hide_vert", bke::AttrDomain::Point);
291
292 bool any_changed = false;
294 node_mask.foreach_index(GrainSize(1), [&](const int i) {
295 Vector<bool> &new_hide = all_new_hide.local();
296 const Span<int> verts = nodes[i].verts();
297
298 new_hide.resize(verts.size());
299 gather_data_mesh(hide_vert.span.as_span(), verts, new_hide.as_mutable_span());
300 calc_hide(verts, new_hide);
301 if (array_utils::indexed_data_equal<bool>(hide_vert.span, verts, new_hide)) {
302 return;
303 }
304
305 any_changed = true;
307 scatter_data_mesh(new_hide.as_span(), verts, hide_vert.span);
308 });
309
310 hide_vert.finish();
311 if (any_changed) {
312 /* We handle flushing ourselves at the node level instead of delegating to
313 * #bke::mesh_hide_vert_flush because we need to tag node visibility changes as well in cases
314 * where the vertices hidden are on a node boundary. */
315 flush_face_changes_node(mesh, pbvh, node_mask, hide_vert.span);
316 flush_edge_changes(mesh, hide_vert.span);
317 }
318}
319
320static void grid_hide_update(Depsgraph &depsgraph,
321 Object &object,
322 const IndexMask &node_mask,
323 const FunctionRef<void(const int, MutableBoundedBitSpan)> calc_hide)
324{
325 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
327
328 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
329 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
330
331 Array<bool> node_changed(node_mask.min_array_size(), false);
332
333 bool any_changed = false;
334 node_mask.foreach_index(GrainSize(1), [&](const int i) {
335 const Span<int> grids = nodes[i].grids();
336 BitGroupVector<> new_hide(grids.size(), grid_hidden.group_size());
337 for (const int i : grids.index_range()) {
338 new_hide[i].copy_from(grid_hidden[grids[i]].as_span());
339 }
340
341 for (const int i : grids.index_range()) {
342 calc_hide(grids[i], new_hide[i]);
343 }
344
345 if (std::all_of(grids.index_range().begin(), grids.index_range().end(), [&](const int i) {
346 return bits::spans_equal(grid_hidden[grids[i]], new_hide[i]);
347 }))
348 {
349 return;
350 }
351
352 any_changed = true;
354
355 for (const int i : grids.index_range()) {
356 grid_hidden[grids[i]].copy_from(new_hide[i].as_span());
357 }
358
359 node_changed[i] = true;
361 });
362
363 IndexMaskMemory memory;
364 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
365 if (changed_nodes.is_empty()) {
366 return;
367 }
368 pbvh.tag_visibility_changed(node_mask);
371}
372
374 const VisAction action,
375 const FunctionRef<bool(BMVert *v)> should_update,
376 bool *any_changed,
377 bool *any_visible)
378{
379 for (BMVert *v : verts) {
380 if (should_update(v)) {
381 if (action == VisAction::Hide) {
383 }
384 else {
386 }
387 (*any_changed) = true;
388 }
389
391 (*any_visible) = true;
392 }
393 }
394}
395
397{
398 for (BMFace *f : faces) {
401 }
402 else {
404 }
405 }
406}
407
408static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph,
409 Object &ob,
410 const IndexMask &node_mask,
411 const VisAction action,
412 const FunctionRef<bool(BMVert *v)> vert_test_fn)
413{
416
417 node_mask.foreach_index([&](const int i) {
418 bool any_changed = false;
419 bool any_visible = false;
420
422
424 action,
425 vert_test_fn,
426 &any_changed,
427 &any_visible);
428
430 action,
431 vert_test_fn,
432 &any_changed,
433 &any_visible);
434
435 /* Finally loop over node faces and tag the ones that are fully hidden. */
437
438 if (any_changed) {
439 BKE_pbvh_node_fully_hidden_set(nodes[i], !any_visible);
440 }
441 });
442
443 pbvh.tag_visibility_changed(node_mask);
444 pbvh.update_visibility(ob);
445}
446
448
449/* -------------------------------------------------------------------- */
453
454static void partialvis_all_update_mesh(const Depsgraph &depsgraph,
455 Object &object,
456 const VisAction action,
457 const IndexMask &node_mask)
458{
459 Mesh &mesh = *static_cast<Mesh *>(object.data);
460 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
461 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
462 /* If everything is already visible, don't do anything. */
463 return;
464 }
465
466 switch (action) {
467 case VisAction::Hide:
469 depsgraph, object, node_mask, [&](const Span<int> /*verts*/, MutableSpan<bool> hide) {
470 hide.fill(true);
471 });
472 break;
473 case VisAction::Show:
474 mesh_show_all(depsgraph, object, node_mask);
475 break;
476 }
477}
478
480 Object &object,
481 const VisAction action,
482 const IndexMask &node_mask)
483{
484 switch (action) {
485 case VisAction::Hide:
487 object,
488 node_mask,
489 [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(true); });
490 break;
491 case VisAction::Show:
492 grids_show_all(depsgraph, object, node_mask);
493 break;
494 }
495}
496
497static void partialvis_all_update_bmesh(const Depsgraph &depsgraph,
498 Object &ob,
499 const VisAction action,
500 const IndexMask &node_mask)
501{
503 depsgraph, ob, node_mask, action, [](const BMVert * /*vert*/) { return true; });
504}
505
507{
508 const Scene &scene = *CTX_data_scene(C);
511
512 const VisAction action = VisAction(RNA_enum_get(op->ptr, "action"));
513
515
516 /* Start undo. */
517 switch (action) {
518 case VisAction::Hide:
519 undo::push_begin_ex(scene, ob, "Hide area");
520 break;
521 case VisAction::Show:
522 undo::push_begin_ex(scene, ob, "Show area");
523 break;
524 }
525
526 IndexMaskMemory memory;
527 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
528
529 switch (pbvh.type()) {
531 partialvis_all_update_mesh(*depsgraph, ob, action, node_mask);
532 break;
534 partialvis_all_update_grids(*depsgraph, ob, action, node_mask);
535 break;
537 partialvis_all_update_bmesh(*depsgraph, ob, action, node_mask);
538 break;
539 }
540
541 /* End undo. */
542 undo::push_end(ob);
543
546
547 return OPERATOR_FINISHED;
548}
549
550static void partialvis_masked_update_mesh(const Depsgraph &depsgraph,
551 Object &object,
552 const VisAction action,
553 const IndexMask &node_mask)
554{
555 Mesh &mesh = *static_cast<Mesh *>(object.data);
556 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
557 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
558 /* If everything is already visible, don't do anything. */
559 return;
560 }
561
562 const bool value = action_to_hide(action);
563 const VArraySpan<float> mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
564 if (action == VisAction::Show && mask.is_empty()) {
565 mesh_show_all(depsgraph, object, node_mask);
566 }
567 else if (!mask.is_empty()) {
569 depsgraph, object, node_mask, [&](const Span<int> verts, MutableSpan<bool> hide) {
570 for (const int i : verts.index_range()) {
571 if (mask[verts[i]] > 0.5f) {
572 hide[i] = value;
573 }
574 }
575 });
576 }
577}
578
580 Object &object,
581 const VisAction action,
582 const IndexMask &node_mask)
583{
584 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
585
586 const bool value = action_to_hide(action);
587 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
588 const Span<float> masks = subdiv_ccg.masks;
589 if (masks.is_empty()) {
591 object,
592 node_mask,
593 [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(value); });
594 }
595 else {
597 depsgraph, object, node_mask, [&](const int grid, MutableBoundedBitSpan hide) {
598 const Span<float> grid_masks = masks.slice(bke::ccg::grid_range(key, grid));
599 for (const int i : grid_masks.index_range()) {
600 if (grid_masks[i] > 0.5f) {
601 hide[i].set(value);
602 }
603 }
604 });
605 }
606}
607
608static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph,
609 Object &ob,
610 const VisAction action,
611 const IndexMask &node_mask)
612{
613 BMesh *bm = ob.sculpt->bm;
614 const int mask_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
615 const auto mask_test_fn = [&](const BMVert *v) {
616 const float vmask = BM_ELEM_CD_GET_FLOAT(v, mask_offset);
617 return vmask > 0.5f;
618 };
619
620 partialvis_update_bmesh_nodes(depsgraph, ob, node_mask, action, mask_test_fn);
621}
622
624{
625 const Scene &scene = *CTX_data_scene(C);
628
629 const VisAction action = VisAction(RNA_enum_get(op->ptr, "action"));
630
632
633 /* Start undo. */
634 switch (action) {
635 case VisAction::Hide:
636 undo::push_begin_ex(scene, ob, "Hide area");
637 break;
638 case VisAction::Show:
639 undo::push_begin_ex(scene, ob, "Show area");
640 break;
641 }
642
643 IndexMaskMemory memory;
644 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
645
646 switch (pbvh.type()) {
648 partialvis_masked_update_mesh(*depsgraph, ob, action, node_mask);
649 break;
651 partialvis_masked_update_grids(*depsgraph, ob, action, node_mask);
652 break;
654 partialvis_masked_update_bmesh(*depsgraph, ob, action, node_mask);
655 break;
656 }
657
658 /* End undo. */
659 undo::push_end(ob);
660
663
664 return OPERATOR_FINISHED;
665}
666
668{
669 static const EnumPropertyItem action_items[] = {
670 {int(VisAction::Hide), "HIDE", 0, "Hide", "Hide vertices"},
671 {int(VisAction::Show), "SHOW", 0, "Show", "Show vertices"},
672 {0, nullptr, 0, nullptr, nullptr},
673 };
674
675 RNA_def_enum(ot->srna,
676 "action",
677 action_items,
678 int(VisAction::Hide),
679 "Visibility Action",
680 "Whether to hide or show vertices");
681}
682
684{
685 ot->name = "Hide/Show Masked";
686 ot->idname = "PAINT_OT_hide_show_masked";
687 ot->description = "Hide/show all masked vertices above a threshold";
688
690 /* Sculpt-only for now. */
692
693 ot->flag = OPTYPE_REGISTER;
694
696}
697
699{
700 ot->name = "Hide/Show All";
701 ot->idname = "PAINT_OT_hide_show_all";
702 ot->description = "Hide/show all vertices";
703
704 ot->exec = hide_show_all_exec;
705 /* Sculpt-only for now. */
707
708 ot->flag = OPTYPE_REGISTER;
709
711}
712
713static void invert_visibility_mesh(const Depsgraph &depsgraph,
714 Object &object,
715 const IndexMask &node_mask)
716{
717 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
719
720 Mesh &mesh = *static_cast<Mesh *>(object.data);
721 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
723 ".hide_poly", bke::AttrDomain::Face);
724
726
727 node_mask.foreach_index(GrainSize(1), [&](const int i) {
728 for (const int face : nodes[i].faces()) {
729 hide_poly.span[face] = !hide_poly.span[face];
730 }
731 });
732
733 hide_poly.finish();
735 pbvh.tag_visibility_changed(node_mask);
736 pbvh.update_visibility(object);
737}
738
739static void invert_visibility_grids(Depsgraph &depsgraph,
740 Object &object,
741 const IndexMask &node_mask)
742{
743 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
745 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
746
748
749 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
750 node_mask.foreach_index(GrainSize(1), [&](const int i) {
751 for (const int i : nodes[i].grids()) {
752 bits::invert(grid_hidden[i]);
753 }
755 });
756
757 pbvh.tag_visibility_changed(node_mask);
760}
761
762static void invert_visibility_bmesh(const Depsgraph &depsgraph,
763 Object &object,
764 const IndexMask &node_mask)
765{
766 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
769
770 node_mask.foreach_index(GrainSize(1), [&](const int i) {
771 bool fully_hidden = true;
774 fully_hidden &= BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN);
775 }
776 BKE_pbvh_node_fully_hidden_set(nodes[i], fully_hidden);
777 });
778 node_mask.foreach_index(GrainSize(1), [&](const int i) {
780 });
781 pbvh.tag_visibility_changed(node_mask);
782}
783
785{
786 const Scene &scene = *CTX_data_scene(C);
787 Object &object = *CTX_data_active_object(C);
789
791
792 IndexMaskMemory memory;
793 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
794 undo::push_begin(scene, object, op);
795 switch (pbvh.type()) {
797 invert_visibility_mesh(depsgraph, object, node_mask);
798 break;
800 invert_visibility_grids(depsgraph, object, node_mask);
801 break;
803 invert_visibility_bmesh(depsgraph, object, node_mask);
804 break;
805 }
806
807 undo::push_end(object);
808
809 islands::invalidate(*object.sculpt);
811
812 return OPERATOR_FINISHED;
813}
814
816{
817 ot->name = "Invert Visibility";
818 ot->idname = "PAINT_OT_visibility_invert";
819 ot->description = "Invert the visibility of all vertices";
820
823
824 ot->flag = OPTYPE_REGISTER;
825}
826
827/* Number of vertices per iteration step size when growing or shrinking visibility. */
828static constexpr float VERTEX_ITERATION_THRESHOLD = 50000.0f;
829
830/* Extracting the loop and comparing against / writing with a constant `false` or `true` instead of
831 * using #action_to_hide results in a nearly 600ms speedup on a mesh with 1.5m verts. */
832template<bool value>
833static void affect_visibility_mesh(const IndexRange face,
834 const Span<int> corner_verts,
835 const Span<bool> read_buffer,
836 MutableSpan<bool> write_buffer)
837{
838 for (const int corner : face) {
839 int vert = corner_verts[corner];
840 if (read_buffer[vert] != value) {
841 continue;
842 }
843
844 const int prev = bke::mesh::face_corner_prev(face, corner);
845 const int prev_vert = corner_verts[prev];
846 write_buffer[prev_vert] = value;
847
848 const int next = bke::mesh::face_corner_next(face, corner);
849 const int next_vert = corner_verts[next];
850 write_buffer[next_vert] = value;
851 }
852}
853
857
859 {
860 return count % 2 == 0 ? back.as_mutable_span() : front.as_mutable_span();
861 }
862
864 {
865 return count % 2 == 0 ? front.as_span() : back.as_span();
866 }
867};
868
871 const VArraySpan<bool> &hide_poly,
872 const VisAction action,
873 const int iterations)
874{
875 const OffsetIndices faces = mesh.faces();
876 const Span<int> corner_verts = mesh.corner_verts();
877
878 for (const int i : IndexRange(iterations)) {
879 Span<bool> read_buffer = buffers.read_buffer(i);
880 MutableSpan<bool> write_buffer = buffers.write_buffer(i);
881 threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
882 for (const int face_index : range) {
883 if (!hide_poly[face_index]) {
884 continue;
885 }
886 const IndexRange face = faces[face_index];
887 if (action == VisAction::Hide) {
888 affect_visibility_mesh<true>(face, corner_verts, read_buffer, write_buffer);
889 }
890 else {
891 affect_visibility_mesh<false>(face, corner_verts, read_buffer, write_buffer);
892 }
893 }
894 });
895
896 flush_face_changes(mesh, write_buffer);
897 }
898}
899
900static void update_undo_state(const Depsgraph &depsgraph,
901 Object &object,
902 const IndexMask &node_mask,
903 const Span<bool> old_hide_vert,
904 const Span<bool> new_hide_vert)
905{
906 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
908
909 node_mask.foreach_index(GrainSize(1), [&](const int i) {
910 for (const int vert : nodes[i].verts()) {
911 if (old_hide_vert[vert] != new_hide_vert[vert]) {
913 break;
914 }
915 }
916 });
917}
918
920 const IndexMask &node_mask,
921 const Span<bool> orig_hide_poly,
922 const Span<bool> new_hide_poly,
923 const Span<bool> hide_vert)
924{
926 Array<bool> node_changed(node_mask.min_array_size(), false);
927
928 node_mask.foreach_index(GrainSize(1), [&](const int i) {
929 bool any_changed = false;
930 const Span<int> indices = nodes[i].faces();
931 for (const int face_index : indices) {
932 if (orig_hide_poly[face_index] != new_hide_poly[face_index]) {
933 any_changed = true;
934 break;
935 }
936 }
937
938 if (any_changed) {
939 node_changed[i] = true;
941 }
942 });
943
944 IndexMaskMemory memory;
945 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
946 if (pbvh.draw_data) {
947 /* Only tag draw data. Nodes have already been updated above. */
948 pbvh.draw_data->tag_visibility_changed(changed_nodes);
949 }
950}
951
952static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph,
953 Object &object,
954 const IndexMask &node_mask,
955 const VisAction action,
956 const int iterations)
957{
958 Mesh &mesh = *static_cast<Mesh *>(object.data);
959 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
960 if (!attributes.contains(".hide_vert")) {
961 /* If the entire mesh is visible, we can neither grow nor shrink the boundary. */
962 return;
963 }
964
966 ".hide_vert", bke::AttrDomain::Point);
967 const VArraySpan hide_poly = *attributes.lookup_or_default<bool>(
968 ".hide_poly", bke::AttrDomain::Face, false);
969
971 buffers.back.reinitialize(hide_vert.span.size());
972 buffers.front.reinitialize(hide_vert.span.size());
973 array_utils::copy(hide_vert.span.as_span(), buffers.back.as_mutable_span());
974 array_utils::copy(hide_vert.span.as_span(), buffers.front.as_mutable_span());
975
976 Array<bool> orig_hide_poly(hide_poly);
977 propagate_vertex_visibility(mesh, buffers, hide_poly, action, iterations);
978
979 const Span<bool> last_buffer = buffers.write_buffer(iterations - 1);
980
981 update_undo_state(depsgraph, object, node_mask, hide_vert.span, last_buffer);
982
983 /* We can wait until after all iterations are done to flush edge changes as they are
984 * not used for coarse filtering while iterating. */
985 flush_edge_changes(mesh, last_buffer);
986
988 *bke::object::pbvh_get(object), node_mask, orig_hide_poly, hide_poly, last_buffer);
989 array_utils::copy(last_buffer, hide_vert.span);
990 hide_vert.finish();
991}
992
996
998 {
999 return count % 2 == 0 ? back : front;
1000 }
1001
1003 {
1004 return count % 2 == 0 ? front : back;
1005 }
1006};
1007
1009 Object &object,
1010 const IndexMask &node_mask,
1011 const VisAction action,
1012 const int iterations)
1013{
1014 SculptSession &ss = *object.sculpt;
1015 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1017
1018 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1019
1020 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
1021
1022 const bool desired_state = action_to_hide(action);
1023 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1024
1026 buffers.front = grid_hidden;
1027 buffers.back = grid_hidden;
1028
1029 Array<bool> node_changed(nodes.size(), false);
1030
1031 for (const int i : IndexRange(iterations)) {
1032 BitGroupVector<> &read_buffer = buffers.read_buffer(i);
1033 BitGroupVector<> &write_buffer = buffers.write_buffer(i);
1034
1035 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1036 for (const int grid : nodes[i].grids()) {
1037 for (const int y : IndexRange(key.grid_size)) {
1038 for (const int x : IndexRange(key.grid_size)) {
1039 const int grid_elem_idx = CCG_grid_xy_to_index(key.grid_size, x, y);
1040 if (read_buffer[grid][grid_elem_idx] != desired_state) {
1041 continue;
1042 }
1043
1044 SubdivCCGCoord coord{};
1045 coord.grid_index = grid;
1046 coord.x = x;
1047 coord.y = y;
1048
1049 SubdivCCGNeighbors neighbors;
1050 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors);
1051
1052 for (const SubdivCCGCoord neighbor : neighbors.coords) {
1053 const int neighbor_grid_elem_idx = CCG_grid_xy_to_index(
1054 key.grid_size, neighbor.x, neighbor.y);
1055
1056 write_buffer[neighbor.grid_index][neighbor_grid_elem_idx].set(desired_state);
1057 }
1058 }
1059 }
1060 }
1061
1062 node_changed[i] = true;
1063 });
1064 }
1065
1066 IndexMaskMemory memory;
1067 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
1068
1069 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
1070
1071 BitGroupVector<> &last_buffer = buffers.write_buffer(iterations - 1);
1072 grid_hidden = std::move(last_buffer);
1073
1074 pbvh.tag_visibility_changed(node_mask);
1075 pbvh.update_visibility(object);
1076
1079}
1080
1082{
1083 const SculptSession &ss = *object.sculpt;
1084 BMesh &bm = *ss.bm;
1085 Array<bool> result(bm.totvert);
1086 vert_random_access_ensure(const_cast<Object &>(object));
1087 for (const int i : result.index_range()) {
1089 }
1090 return result;
1091}
1092
1093static void grow_shrink_visibility_bmesh(const Depsgraph &depsgraph,
1094 Object &object,
1095 const IndexMask &node_mask,
1096 const VisAction action,
1097 const int iterations)
1098{
1099 for (const int i : IndexRange(iterations)) {
1100 UNUSED_VARS(i);
1101 const Array<bool> prev_visibility = duplicate_visibility_bmesh(object);
1102 partialvis_update_bmesh_nodes(depsgraph, object, node_mask, action, [&](BMVert *vert) {
1103 BMeshNeighborVerts neighbors;
1104 for (BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
1105 if (prev_visibility[BM_elem_index_get(neighbor)] == action_to_hide(action)) {
1106 return true;
1107 }
1108 }
1109 return false;
1110 });
1111 }
1112}
1113
1115{
1116 const Scene &scene = *CTX_data_scene(C);
1117 Object &object = *CTX_data_active_object(C);
1119
1121
1122 const VisAction mode = VisAction(RNA_enum_get(op->ptr, "action"));
1123
1124 IndexMaskMemory memory;
1125 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1126
1127 int num_verts = SCULPT_vertex_count_get(object);
1128
1129 int iterations = RNA_int_get(op->ptr, "iterations");
1130
1131 if (RNA_boolean_get(op->ptr, "auto_iteration_count")) {
1132 /* Automatically adjust the number of iterations based on the number
1133 * of vertices in the mesh. */
1134 iterations = int(num_verts / VERTEX_ITERATION_THRESHOLD) + 1;
1135 }
1136
1137 undo::push_begin(scene, object, op);
1138 switch (pbvh.type()) {
1140 grow_shrink_visibility_mesh(depsgraph, object, node_mask, mode, iterations);
1141 break;
1143 grow_shrink_visibility_grid(depsgraph, object, node_mask, mode, iterations);
1144 break;
1146 grow_shrink_visibility_bmesh(depsgraph, object, node_mask, mode, iterations);
1147 break;
1148 }
1149 undo::push_end(object);
1150
1151 islands::invalidate(*object.sculpt);
1153
1154 return OPERATOR_FINISHED;
1155}
1156
1158{
1159 static EnumPropertyItem actions[] = {
1160 {int(VisAction::Show),
1161 "GROW",
1162 0,
1163 "Grow Visibility",
1164 "Grow the visibility by one face based on mesh topology"},
1165 {int(VisAction::Hide),
1166 "SHRINK",
1167 0,
1168 "Shrink Visibility",
1169 "Shrink the visibility by one face based on mesh topology"},
1170 {0, nullptr, 0, nullptr, nullptr},
1171 };
1172
1173 ot->name = "Visibility Filter";
1174 ot->idname = "PAINT_OT_visibility_filter";
1175 ot->description = "Edit the visibility of the current mesh";
1176
1177 ot->exec = visibility_filter_exec;
1179
1180 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1181
1182 RNA_def_enum(ot->srna, "action", actions, int(VisAction::Show), "Action", "");
1183
1184 RNA_def_int(ot->srna,
1185 "iterations",
1186 1,
1187 1,
1188 100,
1189 "Iterations",
1190 "Number of times that the filter is going to be applied",
1191 1,
1192 100);
1194 ot->srna,
1195 "auto_iteration_count",
1196 true,
1197 "Auto Iteration Count",
1198 "Use an automatic number of iterations based on the number of vertices of the sculpt");
1199}
1200
1202
1203/* -------------------------------------------------------------------- */
1207
1213
1215{
1216 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1217 Object *object = gesture_data.vc.obact;
1218 const Depsgraph &depsgraph = *gesture_data.vc.depsgraph;
1219 const VisAction action = operation->action;
1220 const IndexMask &node_mask = gesture_data.node_mask;
1221
1222 Mesh *mesh = static_cast<Mesh *>(object->data);
1223 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
1224 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
1225 /* If everything is already visible, don't do anything. */
1226 return;
1227 }
1228
1229 const bool value = action_to_hide(action);
1230 const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, *object);
1233 depsgraph, *object, node_mask, [&](const Span<int> verts, MutableSpan<bool> hide) {
1234 for (const int i : verts.index_range()) {
1235 if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) {
1236 hide[i] = value;
1237 }
1238 }
1239 });
1240}
1241
1243 gesture::GestureData &gesture_data)
1244{
1245 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1246 Object *object = gesture_data.vc.obact;
1247 const VisAction action = operation->action;
1248 const IndexMask &node_mask = gesture_data.node_mask;
1249
1250 SubdivCCG &subdiv_ccg = *object->sculpt->subdiv_ccg;
1251
1252 const bool value = action_to_hide(action);
1253 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1254 const Span<float3> positions = subdiv_ccg.positions;
1255 const Span<float3> normals = subdiv_ccg.normals;
1256 grid_hide_update(depsgraph, *object, node_mask, [&](const int grid, MutableBoundedBitSpan hide) {
1257 const Span<float3> grid_positions = positions.slice(bke::ccg::grid_range(key, grid));
1258 const Span<float3> grid_normals = normals.slice(bke::ccg::grid_range(key, grid));
1259 for (const int i : grid_positions.index_range()) {
1260 if (gesture::is_affected(gesture_data, grid_positions[i], grid_normals[i])) {
1261 hide[i].set(value);
1262 }
1263 }
1264 });
1265}
1266
1268{
1269 const auto selection_test_fn = [&](const BMVert *v) {
1270 return gesture::is_affected(gesture_data, v->co, v->no);
1271 };
1272
1273 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1274
1276 *gesture_data.vc.obact,
1277 gesture_data.node_mask,
1278 operation->action,
1279 selection_test_fn);
1280}
1281
1282static void hide_show_begin(bContext &C, wmOperator &op, gesture::GestureData & /*gesture_data*/)
1283{
1284 const Scene &scene = *CTX_data_scene(&C);
1287
1288 undo::push_begin(scene, *ob, &op);
1290}
1291
1293{
1294 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
1295
1296 switch (bke::object::pbvh_get(*gesture_data.vc.obact)->type()) {
1298 partialvis_gesture_update_mesh(gesture_data);
1299 break;
1302 break;
1304 partialvis_gesture_update_bmesh(gesture_data);
1305 break;
1306 }
1307}
1308static void hide_show_end(bContext &C, gesture::GestureData &gesture_data)
1309{
1310 islands::invalidate(*gesture_data.vc.obact->sculpt);
1312 undo::push_end(*gesture_data.vc.obact);
1313}
1314
1316 gesture::GestureData &gesture_data,
1317 wmOperator &op)
1318{
1319 gesture_data.operation = reinterpret_cast<gesture::Operation *>(
1321
1322 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1323
1324 operation->op.begin = hide_show_begin;
1326 operation->op.end = hide_show_end;
1327
1328 operation->action = VisAction(RNA_enum_get(op.ptr, "action"));
1329 gesture_data.selection_type = gesture::SelectionType(RNA_enum_get(op.ptr, "area"));
1330}
1331
1333{
1334 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_box(C, op);
1335 if (!gesture_data) {
1336 return OPERATOR_CANCELLED;
1337 }
1338 hide_show_init_properties(*C, *gesture_data, *op);
1339 gesture::apply(*C, *gesture_data, *op);
1340 return OPERATOR_FINISHED;
1341}
1342
1344{
1345 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_lasso(C, op);
1346 if (!gesture_data) {
1347 return OPERATOR_CANCELLED;
1348 }
1349 hide_show_init_properties(*C, *gesture_data, *op);
1350 gesture::apply(*C, *gesture_data, *op);
1351 return OPERATOR_FINISHED;
1352}
1353
1355{
1356 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_line(C, op);
1357 if (!gesture_data) {
1358 return OPERATOR_CANCELLED;
1359 }
1360 hide_show_init_properties(*C, *gesture_data, *op);
1361 gesture::apply(*C, *gesture_data, *op);
1362 return OPERATOR_FINISHED;
1363}
1364
1366{
1367 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_polyline(C, op);
1368 if (!gesture_data) {
1369 return OPERATOR_CANCELLED;
1370 }
1371 hide_show_init_properties(*C, *gesture_data, *op);
1372 gesture::apply(*C, *gesture_data, *op);
1373 return OPERATOR_FINISHED;
1374}
1375
1377{
1378 static const EnumPropertyItem area_items[] = {
1380 "OUTSIDE",
1381 0,
1382 "Outside",
1383 "Hide or show vertices outside the selection"},
1385 "Inside",
1386 0,
1387 "Inside",
1388 "Hide or show vertices inside the selection"},
1389 {0, nullptr, 0, nullptr, nullptr},
1390 };
1391
1392 RNA_def_enum(ot->srna,
1393 "area",
1394 area_items,
1396 "Visibility Area",
1397 "Which vertices to hide or show");
1398}
1399
1401{
1402 ot->name = "Hide/Show";
1403 ot->idname = "PAINT_OT_hide_show";
1404 ot->description = "Hide/show some vertices";
1405
1406 ot->invoke = WM_gesture_box_invoke;
1407 ot->modal = WM_gesture_box_modal;
1409 /* Sculpt-only for now. */
1411
1412 ot->flag = OPTYPE_REGISTER;
1413
1418}
1419
1421{
1422 ot->name = "Hide/Show Lasso";
1423 ot->idname = "PAINT_OT_hide_show_lasso_gesture";
1424 ot->description = "Hide/show some vertices";
1425
1426 ot->invoke = WM_gesture_lasso_invoke;
1427 ot->modal = WM_gesture_lasso_modal;
1429 /* Sculpt-only for now. */
1431
1433
1438}
1439
1441{
1442 ot->name = "Hide/Show Line";
1443 ot->idname = "PAINT_OT_hide_show_line_gesture";
1444 ot->description = "Hide/show some vertices";
1445
1449 /* Sculpt-only for now. */
1451
1452 ot->flag = OPTYPE_REGISTER;
1453
1458}
1459
1461{
1462 ot->name = "Hide/Show Polyline";
1463 ot->idname = "PAINT_OT_hide_show_polyline_gesture";
1464 ot->description = "Hide/show some vertices";
1465
1469 /* Sculpt-only for now. */
1471
1473
1478}
1479
1481
1482} // namespace blender::ed::sculpt_paint::hide
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Definition BKE_ccg.hh:73
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)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
@ MULTIRES_HIDDEN_MODIFIED
void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresModifiedFlags flags)
Definition multires.cc:247
void BKE_sculpt_sync_face_visibility_to_grids(const Mesh &mesh, SubdivCCG &subdiv_ccg)
Definition paint.cc:2953
bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d)
Definition paint.cc:3068
bool paint_is_bmesh_face_hidden(const BMFace *f)
Definition paint.cc:2140
A BVH for high poly meshes.
void BKE_pbvh_node_fully_hidden_set(blender::bke::pbvh::Node &node, int fully_hidden)
Definition pbvh.cc:1711
const blender::Set< BMFace *, 0 > & BKE_pbvh_bmesh_node_faces(blender::bke::pbvh::BMeshNode *node)
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_other_verts(blender::bke::pbvh::BMeshNode *node)
void BKE_pbvh_sync_visibility_from_verts(Object &object)
Definition pbvh.cc:2546
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
blender::BitGroupVector & BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG &subdiv_ccg)
#define UNUSED_VARS(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SHADING
Definition DNA_ID.h:1094
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ CD_PROP_FLOAT
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:618
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define ND_DRAW
Definition WM_types.hh:461
@ OPTYPE_DEPENDS_ON_CURSOR
Definition WM_types.hh:218
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NC_OBJECT
Definition WM_types.hh:379
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
@ BM_ELEM_HIDDEN
#define BM_elem_index_get(ele)
#define BM_elem_flag_disable(ele, hflag)
#define BM_elem_flag_toggle(ele, hflag)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_test_bool(ele, hflag)
#define BM_elem_flag_enable(ele, hflag)
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
BMesh * bm
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr Iterator end() const
constexpr Iterator begin() const
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr const T * end() const
Definition BLI_span.hh:224
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
constexpr const T * begin() const
Definition BLI_span.hh:220
constexpr bool is_empty() const
Definition BLI_span.hh:260
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
Span< T > as_span() const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
bool contains(StringRef attribute_id) const
GAttributeReader lookup(const StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
Span< NodeT > nodes() const
std::unique_ptr< DrawCache > draw_data
void tag_visibility_changed(const IndexMask &node_mask)
Definition pbvh.cc:646
void update_visibility(const Object &object)
Definition pbvh.cc:1579
void foreach_index(Fn &&fn) const
static ushort indices[]
static float verts[][3]
static float normals[][3]
int count
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
static ulong * next
static char faces[256]
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
bool indexed_data_equal(const Span< T > all_values, const Span< int > indices, const Span< T > values)
void invert(BitSpanT &&data)
IndexRange grid_range(const int grid_area, const int grid)
int face_corner_prev(const IndexRange face, const int corner)
Definition BKE_mesh.hh:306
int face_corner_next(const IndexRange face, const int corner)
Definition BKE_mesh.hh:315
pbvh::Tree & pbvh_ensure(Depsgraph &depsgraph, Object &object)
Definition paint.cc:3017
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2628
void node_update_visibility_grids(const BitGroupVector<> &grid_hidden, GridsNode &node)
Definition pbvh.cc:1536
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1059
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1040
void node_update_visibility_mesh(Span< bool > hide_vert, MeshNode &node)
Definition pbvh.cc:1512
void mesh_face_hide_from_vert(OffsetIndices< int > faces, Span< int > corner_verts, Span< bool > hide_vert, MutableSpan< bool > hide_poly)
void mesh_hide_vert_flush(Mesh &mesh)
void mesh_hide_face_flush(Mesh &mesh)
void mesh_edge_hide_from_vert(Span< int2 > edges, Span< bool > hide_vert, MutableSpan< bool > hide_edge)
std::unique_ptr< GestureData > init_from_box(bContext *C, wmOperator *op)
void operator_properties(wmOperatorType *ot, ShapeType shapeType)
std::unique_ptr< GestureData > init_from_polyline(bContext *C, wmOperator *op)
std::unique_ptr< GestureData > init_from_line(bContext *C, const wmOperator *op)
void apply(bContext &C, GestureData &gesture_data, wmOperator &op)
std::unique_ptr< GestureData > init_from_lasso(bContext *C, wmOperator *op)
bool is_affected(const GestureData &gesture_data, const float3 &position, const float3 &normal)
static void invert_visibility_bmesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
static constexpr float VERTEX_ITERATION_THRESHOLD
static Array< bool > duplicate_visibility_bmesh(const Object &object)
static void flush_face_changes(Mesh &mesh, const Span< bool > hide_vert)
void PAINT_OT_hide_show_polyline_gesture(wmOperatorType *ot)
static void grow_shrink_visibility_bmesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const VisAction action, const int iterations)
static void partialvis_all_update_grids(Depsgraph &depsgraph, Object &object, const VisAction action, const IndexMask &node_mask)
static void partialvis_all_update_bmesh(const Depsgraph &depsgraph, Object &ob, const VisAction action, const IndexMask &node_mask)
void PAINT_OT_hide_show_masked(wmOperatorType *ot)
static void invert_visibility_mesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
void PAINT_OT_hide_show_line_gesture(wmOperatorType *ot)
static void grid_hide_update(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const FunctionRef< void(const int, MutableBoundedBitSpan)> calc_hide)
void tag_update_visibility(const bContext &C)
static wmOperatorStatus hide_show_gesture_line_exec(bContext *C, wmOperator *op)
static void hide_show_end(bContext &C, gesture::GestureData &gesture_data)
static void affect_visibility_mesh(const IndexRange face, const Span< int > corner_verts, const Span< bool > read_buffer, MutableSpan< bool > write_buffer)
static void propagate_vertex_visibility(Mesh &mesh, DualBuffer &buffers, const VArraySpan< bool > &hide_poly, const VisAction action, const int iterations)
static void partialvis_gesture_update_bmesh(gesture::GestureData &gesture_data)
static void partialvis_gesture_update_grids(Depsgraph &depsgraph, gesture::GestureData &gesture_data)
static wmOperatorStatus hide_show_all_exec(bContext *C, wmOperator *op)
static void vert_hide_update(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const FunctionRef< void(Span< int >, MutableSpan< bool >)> calc_hide)
void PAINT_OT_visibility_invert(wmOperatorType *ot)
static wmOperatorStatus visibility_invert_exec(bContext *C, wmOperator *op)
static void calc_face_hide(const Span< int > node_faces, const OffsetIndices< int > faces, const Span< int > corner_verts, const Span< bool > hide_vert, MutableSpan< bool > hide_face)
static void hide_show_apply_for_symmetry_pass(bContext &C, gesture::GestureData &gesture_data)
void PAINT_OT_hide_show_lasso_gesture(wmOperatorType *ot)
void PAINT_OT_visibility_filter(wmOperatorType *ot)
static wmOperatorStatus hide_show_gesture_lasso_exec(bContext *C, wmOperator *op)
void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
static void partialvis_masked_update_grids(Depsgraph &depsgraph, Object &object, const VisAction action, const IndexMask &node_mask)
static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph, Object &ob, const VisAction action, const IndexMask &node_mask)
static void grow_shrink_visibility_grid(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const VisAction action, const int iterations)
static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph, Object &ob, const IndexMask &node_mask, const VisAction action, const FunctionRef< bool(BMVert *v)> vert_test_fn)
static wmOperatorStatus hide_show_masked_exec(bContext *C, wmOperator *op)
static void hide_show_init_properties(bContext &, gesture::GestureData &gesture_data, wmOperator &op)
static void partialvis_update_bmesh_faces(const Set< BMFace *, 0 > &faces)
static void update_node_visibility_from_face_changes(bke::pbvh::Tree &pbvh, const IndexMask &node_mask, const Span< bool > orig_hide_poly, const Span< bool > new_hide_poly, const Span< bool > hide_vert)
void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
void PAINT_OT_hide_show_all(wmOperatorType *ot)
static void invert_visibility_grids(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
static void partialvis_all_update_mesh(const Depsgraph &depsgraph, Object &object, const VisAction action, const IndexMask &node_mask)
void sync_all_from_faces(Object &object)
Definition paint_hide.cc:55
static void flush_edge_changes(Mesh &mesh, const Span< bool > hide_vert)
static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const VisAction action, const int iterations)
static void hide_show_operator_gesture_properties(wmOperatorType *ot)
static wmOperatorStatus visibility_filter_exec(bContext *C, wmOperator *op)
static wmOperatorStatus hide_show_gesture_polyline_exec(bContext *C, wmOperator *op)
static void update_undo_state(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Span< bool > old_hide_vert, const Span< bool > new_hide_vert)
void PAINT_OT_hide_show(wmOperatorType *ot)
static wmOperatorStatus hide_show_gesture_box_exec(bContext *C, wmOperator *op)
static void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data)
static void flush_face_changes_node(Mesh &mesh, bke::pbvh::Tree &pbvh, const IndexMask &node_mask, const Span< bool > hide_vert)
static void partialvis_update_bmesh_verts(const Set< BMVert *, 0 > &verts, const VisAction action, const FunctionRef< bool(BMVert *v)> should_update, bool *any_changed, bool *any_visible)
static void partialvis_masked_update_mesh(const Depsgraph &depsgraph, Object &object, const VisAction action, const IndexMask &node_mask)
static void hide_show_begin(bContext &C, wmOperator &op, gesture::GestureData &)
static bool action_to_hide(const VisAction action)
static void hide_show_operator_properties(wmOperatorType *ot)
void invalidate(SculptSession &ss)
Definition sculpt.cc:6199
void push_nodes(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Type type)
void push_begin_ex(const Scene &, Object &ob, const char *name)
void push_node(const Depsgraph &depsgraph, const Object &object, const bke::pbvh::Node *node, const Type type)
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
void vert_random_access_ensure(Object &object)
Definition sculpt.cc:141
Vector< BMVert *, 64 > BMeshNeighborVerts
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6435
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, BMeshNeighborVerts &r_neighbors)
Definition sculpt.cc:387
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6395
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
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)
bool SCULPT_mode_poll_view3d(bContext *C)
Definition sculpt.cc:3683
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:151
BMLoop * l_first
int grid_size
Definition BKE_ccg.hh:33
struct SculptSession * sculpt
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
SubdivCCGNeighborCoords coords
blender::Array< blender::float3 > normals
blender::Array< float > masks
blender::Array< blender::float3 > positions
Object * obact
Definition ED_view3d.hh:75
Depsgraph * depsgraph
Definition ED_view3d.hh:72
void(* end)(bContext &, GestureData &)
void(* begin)(bContext &, wmOperator &, GestureData &)
void(* apply_for_symmetry_pass)(bContext &, GestureData &)
MutableSpan< bool > write_buffer(int count)
struct PointerRNA * ptr
i
Definition text_draw.cc:230
@ WM_CURSOR_EDIT
Definition wm_cursors.hh:19
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4237
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)
char * buffers[2]