Blender V4.5
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#include "BKE_subsurf.hh"
30
31#include "DEG_depsgraph.hh"
32
33#include "WM_api.hh"
34#include "WM_types.hh"
35
36#include "ED_screen.hh"
37
38#include "RNA_access.hh"
39#include "RNA_define.hh"
40
41#include "bmesh.hh"
42
43#include "mesh_brush_common.hh"
44#include "paint_intern.hh"
45#include "sculpt_automask.hh"
46#include "sculpt_gesture.hh"
47#include "sculpt_intern.hh"
48#include "sculpt_islands.hh"
49#include "sculpt_undo.hh"
50
52
53/* -------------------------------------------------------------------- */
56
58{
59 SculptSession &ss = *object.sculpt;
60 Mesh &mesh = *static_cast<Mesh *>(object.data);
61
63
64 switch (bke::object::pbvh_get(object)->type()) {
66 /* We may have adjusted the ".hide_poly" attribute, now make the hide status attributes for
67 * vertices and edges consistent. */
69 break;
70 }
72 /* In addition to making the hide status of the base mesh consistent, we also have to
73 * propagate the status to the Multires grids. */
76 break;
77 }
79 BMesh &bm = *ss.bm;
80 BMIter iter;
81 BMFace *f;
82
83 /* Hide all verts and edges attached to faces. */
84 BM_ITER_MESH (f, &iter, &bm, BM_FACES_OF_MESH) {
85 BMLoop *l = f->l_first;
86 do {
89 } while ((l = l->next) != f->l_first);
90 }
91
92 /* Unhide verts and edges attached to visible faces. */
93 BM_ITER_MESH (f, &iter, &bm, BM_FACES_OF_MESH) {
95 continue;
96 }
97
98 BMLoop *l = f->l_first;
99 do {
102 } while ((l = l->next) != f->l_first);
103 }
104 break;
105 }
106 }
107}
108
123
124void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
125{
126 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
128 Mesh &mesh = *static_cast<Mesh *>(object.data);
129 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
130 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
131
132 if (!hide_vert.is_empty()) {
133 IndexMaskMemory memory;
134 const IndexMask changed_nodes = IndexMask::from_predicate(
135 node_mask, GrainSize(1), memory, [&](const int i) {
136 const Span<int> verts = nodes[i].verts();
137 return std::any_of(
138 verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; });
139 });
140 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
141 pbvh.tag_visibility_changed(changed_nodes);
142 }
143
144 attributes.remove(".hide_vert");
146 pbvh.update_visibility(object);
147}
148
149void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
150{
151 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
153 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
154 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
155
156 if (!grid_hidden.is_empty()) {
157 IndexMaskMemory memory;
158 const IndexMask changed_nodes = IndexMask::from_predicate(
159 node_mask, GrainSize(1), memory, [&](const int i) {
160 const Span<int> grids = nodes[i].grids();
161 return std::any_of(grids.begin(), grids.end(), [&](const int i) {
162 return bits::any_bit_set(grid_hidden[i]);
163 });
164 });
165 if (changed_nodes.is_empty()) {
166 return;
167 }
168 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
169 pbvh.tag_visibility_changed(changed_nodes);
170 }
171
174 pbvh.update_visibility(object);
176}
177
179
180/* -------------------------------------------------------------------- */
184
185enum class VisAction {
186 Hide = 0,
187 Show = 1,
188};
189
190static bool action_to_hide(const VisAction action)
191{
192 return action == VisAction::Hide;
193}
194
195/* Calculates whether a face should be hidden based on all of its corner vertices. */
196static void calc_face_hide(const Span<int> node_faces,
198 const Span<int> corner_verts,
199 const Span<bool> hide_vert,
200 MutableSpan<bool> hide_face)
201{
202 for (const int i : node_faces.index_range()) {
203 Span<int> face_verts = corner_verts.slice(faces[node_faces[i]]);
204 hide_face[i] = std::any_of(
205 face_verts.begin(), face_verts.end(), [&](const int v) { return hide_vert[v]; });
206 }
207}
208
209/* Updates a node's face's visibility based on the updated vertex visibility. */
211 bke::pbvh::Tree &pbvh,
212 const IndexMask &node_mask,
213 const Span<bool> hide_vert)
214{
215 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
216
217 const OffsetIndices<int> faces = mesh.faces();
218 const Span<int> corner_verts = mesh.corner_verts();
219
221 ".hide_poly", bke::AttrDomain::Face);
222
224
225 Array<bool> node_changed(node_mask.min_array_size(), false);
226
227 struct TLS {
228 Vector<bool> new_hide;
229 };
231 node_mask.foreach_index(GrainSize(1), [&](const int i) {
232 TLS &tls = all_tls.local();
233 const Span<int> node_faces = nodes[i].faces();
234
235 tls.new_hide.resize(node_faces.size());
236 gather_data_mesh(hide_poly.span.as_span(), node_faces, tls.new_hide.as_mutable_span());
237
238 calc_face_hide(node_faces, faces, corner_verts, hide_vert, tls.new_hide.as_mutable_span());
239
240 if (array_utils::indexed_data_equal<bool>(hide_poly.span, node_faces, tls.new_hide)) {
241 return;
242 }
243
244 scatter_data_mesh(tls.new_hide.as_span(), node_faces, hide_poly.span);
245 node_changed[i] = true;
247 });
248 hide_poly.finish();
249
250 IndexMaskMemory memory;
251 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
252 if (changed_nodes.is_empty()) {
253 return;
254 }
255 pbvh.tag_visibility_changed(node_mask);
256}
257
258/* Updates a node's face's visibility based on the updated vertex visibility. */
259static void flush_face_changes(Mesh &mesh, const Span<bool> hide_vert)
260{
261 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
262
264 ".hide_poly", bke::AttrDomain::Face);
265
266 bke::mesh_face_hide_from_vert(mesh.faces(), mesh.corner_verts(), hide_vert, hide_poly.span);
267 hide_poly.finish();
268}
269
270/* Updates all of a mesh's edge visibility based on vertex visibility. */
271static void flush_edge_changes(Mesh &mesh, const Span<bool> hide_vert)
272{
273 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
274
276 ".hide_edge", bke::AttrDomain::Edge);
277 bke::mesh_edge_hide_from_vert(mesh.edges(), hide_vert, hide_edge.span);
278 hide_edge.finish();
279}
280
281static void vert_hide_update(const Depsgraph &depsgraph,
282 Object &object,
283 const IndexMask &node_mask,
284 const FunctionRef<void(Span<int>, MutableSpan<bool>)> calc_hide)
285{
286 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
288
289 Mesh &mesh = *static_cast<Mesh *>(object.data);
290 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
292 ".hide_vert", bke::AttrDomain::Point);
293
294 bool any_changed = false;
296 node_mask.foreach_index(GrainSize(1), [&](const int i) {
297 Vector<bool> &new_hide = all_new_hide.local();
298 const Span<int> verts = nodes[i].verts();
299
300 new_hide.resize(verts.size());
301 gather_data_mesh(hide_vert.span.as_span(), verts, new_hide.as_mutable_span());
302 calc_hide(verts, new_hide);
303 if (array_utils::indexed_data_equal<bool>(hide_vert.span, verts, new_hide)) {
304 return;
305 }
306
307 any_changed = true;
309 scatter_data_mesh(new_hide.as_span(), verts, hide_vert.span);
310 });
311
312 hide_vert.finish();
313 if (any_changed) {
314 /* We handle flushing ourselves at the node level instead of delegating to
315 * #bke::mesh_hide_vert_flush because we need to tag node visibility changes as well in cases
316 * where the vertices hidden are on a node boundary. */
317 flush_face_changes_node(mesh, pbvh, node_mask, hide_vert.span);
318 flush_edge_changes(mesh, hide_vert.span);
319 }
320}
321
322static void grid_hide_update(Depsgraph &depsgraph,
323 Object &object,
324 const IndexMask &node_mask,
325 const FunctionRef<void(const int, MutableBoundedBitSpan)> calc_hide)
326{
327 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
329
330 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
331 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
332
333 Array<bool> node_changed(node_mask.min_array_size(), false);
334
335 bool any_changed = false;
336 node_mask.foreach_index(GrainSize(1), [&](const int i) {
337 const Span<int> grids = nodes[i].grids();
338 BitGroupVector<> new_hide(grids.size(), grid_hidden.group_size());
339 for (const int i : grids.index_range()) {
340 new_hide[i].copy_from(grid_hidden[grids[i]].as_span());
341 }
342
343 for (const int i : grids.index_range()) {
344 calc_hide(grids[i], new_hide[i]);
345 }
346
347 if (std::all_of(grids.index_range().begin(), grids.index_range().end(), [&](const int i) {
348 return bits::spans_equal(grid_hidden[grids[i]], new_hide[i]);
349 }))
350 {
351 return;
352 }
353
354 any_changed = true;
356
357 for (const int i : grids.index_range()) {
358 grid_hidden[grids[i]].copy_from(new_hide[i].as_span());
359 }
360
361 node_changed[i] = true;
363 });
364
365 IndexMaskMemory memory;
366 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
367 if (changed_nodes.is_empty()) {
368 return;
369 }
370 pbvh.tag_visibility_changed(node_mask);
373}
374
376 const VisAction action,
377 const FunctionRef<bool(BMVert *v)> should_update,
378 bool *any_changed,
379 bool *any_visible)
380{
381 for (BMVert *v : verts) {
382 if (should_update(v)) {
383 if (action == VisAction::Hide) {
385 }
386 else {
388 }
389 (*any_changed) = true;
390 }
391
393 (*any_visible) = true;
394 }
395 }
396}
397
399{
400 for (BMFace *f : faces) {
403 }
404 else {
406 }
407 }
408}
409
410static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph,
411 Object &ob,
412 const IndexMask &node_mask,
413 const VisAction action,
414 const FunctionRef<bool(BMVert *v)> vert_test_fn)
415{
418
419 node_mask.foreach_index([&](const int i) {
420 bool any_changed = false;
421 bool any_visible = false;
422
424
426 action,
427 vert_test_fn,
428 &any_changed,
429 &any_visible);
430
432 action,
433 vert_test_fn,
434 &any_changed,
435 &any_visible);
436
437 /* Finally loop over node faces and tag the ones that are fully hidden. */
439
440 if (any_changed) {
441 BKE_pbvh_node_fully_hidden_set(nodes[i], !any_visible);
442 }
443 });
444
445 pbvh.tag_visibility_changed(node_mask);
446 pbvh.update_visibility(ob);
447}
448
450
451/* -------------------------------------------------------------------- */
455
456static void partialvis_all_update_mesh(const Depsgraph &depsgraph,
457 Object &object,
458 const VisAction action,
459 const IndexMask &node_mask)
460{
461 Mesh &mesh = *static_cast<Mesh *>(object.data);
462 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
463 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
464 /* If everything is already visible, don't do anything. */
465 return;
466 }
467
468 switch (action) {
469 case VisAction::Hide:
471 depsgraph, object, node_mask, [&](const Span<int> /*verts*/, MutableSpan<bool> hide) {
472 hide.fill(true);
473 });
474 break;
475 case VisAction::Show:
476 mesh_show_all(depsgraph, object, node_mask);
477 break;
478 }
479}
480
482 Object &object,
483 const VisAction action,
484 const IndexMask &node_mask)
485{
486 switch (action) {
487 case VisAction::Hide:
489 object,
490 node_mask,
491 [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(true); });
492 break;
493 case VisAction::Show:
494 grids_show_all(depsgraph, object, node_mask);
495 break;
496 }
497}
498
499static void partialvis_all_update_bmesh(const Depsgraph &depsgraph,
500 Object &ob,
501 const VisAction action,
502 const IndexMask &node_mask)
503{
505 depsgraph, ob, node_mask, action, [](const BMVert * /*vert*/) { return true; });
506}
507
509{
510 const Scene &scene = *CTX_data_scene(C);
513
514 const VisAction action = VisAction(RNA_enum_get(op->ptr, "action"));
515
517
518 /* Start undo. */
519 switch (action) {
520 case VisAction::Hide:
521 undo::push_begin_ex(scene, ob, "Hide area");
522 break;
523 case VisAction::Show:
524 undo::push_begin_ex(scene, ob, "Show area");
525 break;
526 }
527
528 IndexMaskMemory memory;
529 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
530
531 switch (pbvh.type()) {
533 partialvis_all_update_mesh(*depsgraph, ob, action, node_mask);
534 break;
536 partialvis_all_update_grids(*depsgraph, ob, action, node_mask);
537 break;
539 partialvis_all_update_bmesh(*depsgraph, ob, action, node_mask);
540 break;
541 }
542
543 /* End undo. */
544 undo::push_end(ob);
545
548
549 return OPERATOR_FINISHED;
550}
551
552static void partialvis_masked_update_mesh(const Depsgraph &depsgraph,
553 Object &object,
554 const VisAction action,
555 const IndexMask &node_mask)
556{
557 Mesh &mesh = *static_cast<Mesh *>(object.data);
558 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
559 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
560 /* If everything is already visible, don't do anything. */
561 return;
562 }
563
564 const bool value = action_to_hide(action);
565 const VArraySpan<float> mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
566 if (action == VisAction::Show && mask.is_empty()) {
567 mesh_show_all(depsgraph, object, node_mask);
568 }
569 else if (!mask.is_empty()) {
571 depsgraph, object, node_mask, [&](const Span<int> verts, MutableSpan<bool> hide) {
572 for (const int i : verts.index_range()) {
573 if (mask[verts[i]] > 0.5f) {
574 hide[i] = value;
575 }
576 }
577 });
578 }
579}
580
582 Object &object,
583 const VisAction action,
584 const IndexMask &node_mask)
585{
586 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
587
588 const bool value = action_to_hide(action);
589 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
590 const Span<float> masks = subdiv_ccg.masks;
591 if (masks.is_empty()) {
593 object,
594 node_mask,
595 [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(value); });
596 }
597 else {
599 depsgraph, object, node_mask, [&](const int grid, MutableBoundedBitSpan hide) {
600 const Span<float> grid_masks = masks.slice(bke::ccg::grid_range(key, grid));
601 for (const int i : grid_masks.index_range()) {
602 if (grid_masks[i] > 0.5f) {
603 hide[i].set(value);
604 }
605 }
606 });
607 }
608}
609
610static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph,
611 Object &ob,
612 const VisAction action,
613 const IndexMask &node_mask)
614{
615 BMesh *bm = ob.sculpt->bm;
616 const int mask_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
617 const auto mask_test_fn = [&](const BMVert *v) {
618 const float vmask = BM_ELEM_CD_GET_FLOAT(v, mask_offset);
619 return vmask > 0.5f;
620 };
621
622 partialvis_update_bmesh_nodes(depsgraph, ob, node_mask, action, mask_test_fn);
623}
624
626{
627 const Scene &scene = *CTX_data_scene(C);
630
631 const VisAction action = VisAction(RNA_enum_get(op->ptr, "action"));
632
634
635 /* Start undo. */
636 switch (action) {
637 case VisAction::Hide:
638 undo::push_begin_ex(scene, ob, "Hide area");
639 break;
640 case VisAction::Show:
641 undo::push_begin_ex(scene, ob, "Show area");
642 break;
643 }
644
645 IndexMaskMemory memory;
646 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
647
648 switch (pbvh.type()) {
650 partialvis_masked_update_mesh(*depsgraph, ob, action, node_mask);
651 break;
653 partialvis_masked_update_grids(*depsgraph, ob, action, node_mask);
654 break;
656 partialvis_masked_update_bmesh(*depsgraph, ob, action, node_mask);
657 break;
658 }
659
660 /* End undo. */
661 undo::push_end(ob);
662
665
666 return OPERATOR_FINISHED;
667}
668
670{
671 static const EnumPropertyItem action_items[] = {
672 {int(VisAction::Hide), "HIDE", 0, "Hide", "Hide vertices"},
673 {int(VisAction::Show), "SHOW", 0, "Show", "Show vertices"},
674 {0, nullptr, 0, nullptr, nullptr},
675 };
676
677 RNA_def_enum(ot->srna,
678 "action",
679 action_items,
680 int(VisAction::Hide),
681 "Visibility Action",
682 "Whether to hide or show vertices");
683}
684
686{
687 ot->name = "Hide/Show Masked";
688 ot->idname = "PAINT_OT_hide_show_masked";
689 ot->description = "Hide/show all masked vertices above a threshold";
690
692 /* Sculpt-only for now. */
694
695 ot->flag = OPTYPE_REGISTER;
696
698}
699
701{
702 ot->name = "Hide/Show All";
703 ot->idname = "PAINT_OT_hide_show_all";
704 ot->description = "Hide/show all vertices";
705
706 ot->exec = hide_show_all_exec;
707 /* Sculpt-only for now. */
709
710 ot->flag = OPTYPE_REGISTER;
711
713}
714
715static void invert_visibility_mesh(const Depsgraph &depsgraph,
716 Object &object,
717 const IndexMask &node_mask)
718{
719 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
721
722 Mesh &mesh = *static_cast<Mesh *>(object.data);
723 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
725 ".hide_poly", bke::AttrDomain::Face);
726
728
729 node_mask.foreach_index(GrainSize(1), [&](const int i) {
730 for (const int face : nodes[i].faces()) {
731 hide_poly.span[face] = !hide_poly.span[face];
732 }
733 });
734
735 hide_poly.finish();
737 pbvh.tag_visibility_changed(node_mask);
738 pbvh.update_visibility(object);
739}
740
741static void invert_visibility_grids(Depsgraph &depsgraph,
742 Object &object,
743 const IndexMask &node_mask)
744{
745 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
747 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
748
750
751 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
752 node_mask.foreach_index(GrainSize(1), [&](const int i) {
753 for (const int i : nodes[i].grids()) {
754 bits::invert(grid_hidden[i]);
755 }
757 });
758
759 pbvh.tag_visibility_changed(node_mask);
762}
763
764static void invert_visibility_bmesh(const Depsgraph &depsgraph,
765 Object &object,
766 const IndexMask &node_mask)
767{
768 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
771
772 node_mask.foreach_index(GrainSize(1), [&](const int i) {
773 bool fully_hidden = true;
776 fully_hidden &= BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN);
777 }
778 BKE_pbvh_node_fully_hidden_set(nodes[i], fully_hidden);
779 });
780 node_mask.foreach_index(GrainSize(1), [&](const int i) {
782 });
783 pbvh.tag_visibility_changed(node_mask);
784}
785
787{
788 const Scene &scene = *CTX_data_scene(C);
789 Object &object = *CTX_data_active_object(C);
791
793
794 IndexMaskMemory memory;
795 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
796 undo::push_begin(scene, object, op);
797 switch (pbvh.type()) {
799 invert_visibility_mesh(depsgraph, object, node_mask);
800 break;
802 invert_visibility_grids(depsgraph, object, node_mask);
803 break;
805 invert_visibility_bmesh(depsgraph, object, node_mask);
806 break;
807 }
808
809 undo::push_end(object);
810
811 islands::invalidate(*object.sculpt);
813
814 return OPERATOR_FINISHED;
815}
816
818{
819 ot->name = "Invert Visibility";
820 ot->idname = "PAINT_OT_visibility_invert";
821 ot->description = "Invert the visibility of all vertices";
822
825
826 ot->flag = OPTYPE_REGISTER;
827}
828
829/* Number of vertices per iteration step size when growing or shrinking visibility. */
830static constexpr float VERTEX_ITERATION_THRESHOLD = 50000.0f;
831
832/* Extracting the loop and comparing against / writing with a constant `false` or `true` instead of
833 * using #action_to_hide results in a nearly 600ms speedup on a mesh with 1.5m verts. */
834template<bool value>
835static void affect_visibility_mesh(const IndexRange face,
836 const Span<int> corner_verts,
837 const Span<bool> read_buffer,
838 MutableSpan<bool> write_buffer)
839{
840 for (const int corner : face) {
841 int vert = corner_verts[corner];
842 if (read_buffer[vert] != value) {
843 continue;
844 }
845
846 const int prev = bke::mesh::face_corner_prev(face, corner);
847 const int prev_vert = corner_verts[prev];
848 write_buffer[prev_vert] = value;
849
850 const int next = bke::mesh::face_corner_next(face, corner);
851 const int next_vert = corner_verts[next];
852 write_buffer[next_vert] = value;
853 }
854}
855
859
861 {
862 return count % 2 == 0 ? back.as_mutable_span() : front.as_mutable_span();
863 }
864
866 {
867 return count % 2 == 0 ? front.as_span() : back.as_span();
868 }
869};
870
873 const VArraySpan<bool> &hide_poly,
874 const VisAction action,
875 const int iterations)
876{
877 const OffsetIndices faces = mesh.faces();
878 const Span<int> corner_verts = mesh.corner_verts();
879
880 for (const int i : IndexRange(iterations)) {
881 Span<bool> read_buffer = buffers.read_buffer(i);
882 MutableSpan<bool> write_buffer = buffers.write_buffer(i);
883 threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
884 for (const int face_index : range) {
885 if (!hide_poly[face_index]) {
886 continue;
887 }
888 const IndexRange face = faces[face_index];
889 if (action == VisAction::Hide) {
890 affect_visibility_mesh<true>(face, corner_verts, read_buffer, write_buffer);
891 }
892 else {
893 affect_visibility_mesh<false>(face, corner_verts, read_buffer, write_buffer);
894 }
895 }
896 });
897
898 flush_face_changes(mesh, write_buffer);
899 }
900}
901
902static void update_undo_state(const Depsgraph &depsgraph,
903 Object &object,
904 const IndexMask &node_mask,
905 const Span<bool> old_hide_vert,
906 const Span<bool> new_hide_vert)
907{
908 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
910
911 node_mask.foreach_index(GrainSize(1), [&](const int i) {
912 for (const int vert : nodes[i].verts()) {
913 if (old_hide_vert[vert] != new_hide_vert[vert]) {
915 break;
916 }
917 }
918 });
919}
920
922 const IndexMask &node_mask,
923 const Span<bool> orig_hide_poly,
924 const Span<bool> new_hide_poly,
925 const Span<bool> hide_vert)
926{
928 Array<bool> node_changed(node_mask.min_array_size(), false);
929
930 node_mask.foreach_index(GrainSize(1), [&](const int i) {
931 bool any_changed = false;
932 const Span<int> indices = nodes[i].faces();
933 for (const int face_index : indices) {
934 if (orig_hide_poly[face_index] != new_hide_poly[face_index]) {
935 any_changed = true;
936 break;
937 }
938 }
939
940 if (any_changed) {
941 node_changed[i] = true;
943 }
944 });
945
946 IndexMaskMemory memory;
947 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
948 if (pbvh.draw_data) {
949 /* Only tag draw data. Nodes have already been updated above. */
950 pbvh.draw_data->tag_visibility_changed(changed_nodes);
951 }
952}
953
954static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph,
955 Object &object,
956 const IndexMask &node_mask,
957 const VisAction action,
958 const int iterations)
959{
960 Mesh &mesh = *static_cast<Mesh *>(object.data);
961 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
962 if (!attributes.contains(".hide_vert")) {
963 /* If the entire mesh is visible, we can neither grow nor shrink the boundary. */
964 return;
965 }
966
968 ".hide_vert", bke::AttrDomain::Point);
969 const VArraySpan hide_poly = *attributes.lookup_or_default<bool>(
970 ".hide_poly", bke::AttrDomain::Face, false);
971
973 buffers.back.reinitialize(hide_vert.span.size());
974 buffers.front.reinitialize(hide_vert.span.size());
975 array_utils::copy(hide_vert.span.as_span(), buffers.back.as_mutable_span());
976 array_utils::copy(hide_vert.span.as_span(), buffers.front.as_mutable_span());
977
978 Array<bool> orig_hide_poly(hide_poly);
979 propagate_vertex_visibility(mesh, buffers, hide_poly, action, iterations);
980
981 const Span<bool> last_buffer = buffers.write_buffer(iterations - 1);
982
983 update_undo_state(depsgraph, object, node_mask, hide_vert.span, last_buffer);
984
985 /* We can wait until after all iterations are done to flush edge changes as they are
986 * not used for coarse filtering while iterating. */
987 flush_edge_changes(mesh, last_buffer);
988
990 *bke::object::pbvh_get(object), node_mask, orig_hide_poly, hide_poly, last_buffer);
991 array_utils::copy(last_buffer, hide_vert.span);
992 hide_vert.finish();
993}
994
998
1000 {
1001 return count % 2 == 0 ? back : front;
1002 }
1003
1005 {
1006 return count % 2 == 0 ? front : back;
1007 }
1008};
1009
1011 Object &object,
1012 const IndexMask &node_mask,
1013 const VisAction action,
1014 const int iterations)
1015{
1016 SculptSession &ss = *object.sculpt;
1017 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1019
1020 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1021
1022 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
1023
1024 const bool desired_state = action_to_hide(action);
1025 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1026
1028 buffers.front = grid_hidden;
1029 buffers.back = grid_hidden;
1030
1031 Array<bool> node_changed(nodes.size(), false);
1032
1033 for (const int i : IndexRange(iterations)) {
1034 BitGroupVector<> &read_buffer = buffers.read_buffer(i);
1035 BitGroupVector<> &write_buffer = buffers.write_buffer(i);
1036
1037 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1038 for (const int grid : nodes[i].grids()) {
1039 for (const int y : IndexRange(key.grid_size)) {
1040 for (const int x : IndexRange(key.grid_size)) {
1041 const int grid_elem_idx = CCG_grid_xy_to_index(key.grid_size, x, y);
1042 if (read_buffer[grid][grid_elem_idx] != desired_state) {
1043 continue;
1044 }
1045
1046 SubdivCCGCoord coord{};
1047 coord.grid_index = grid;
1048 coord.x = x;
1049 coord.y = y;
1050
1051 SubdivCCGNeighbors neighbors;
1052 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors);
1053
1054 for (const SubdivCCGCoord neighbor : neighbors.coords) {
1055 const int neighbor_grid_elem_idx = CCG_grid_xy_to_index(
1056 key.grid_size, neighbor.x, neighbor.y);
1057
1058 write_buffer[neighbor.grid_index][neighbor_grid_elem_idx].set(desired_state);
1059 }
1060 }
1061 }
1062 }
1063
1064 node_changed[i] = true;
1065 });
1066 }
1067
1068 IndexMaskMemory memory;
1069 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
1070
1071 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
1072
1073 BitGroupVector<> &last_buffer = buffers.write_buffer(iterations - 1);
1074 grid_hidden = std::move(last_buffer);
1075
1076 pbvh.tag_visibility_changed(node_mask);
1077 pbvh.update_visibility(object);
1078
1081}
1082
1084{
1085 const SculptSession &ss = *object.sculpt;
1086 BMesh &bm = *ss.bm;
1087 Array<bool> result(bm.totvert);
1088 vert_random_access_ensure(const_cast<Object &>(object));
1089 for (const int i : result.index_range()) {
1091 }
1092 return result;
1093}
1094
1095static void grow_shrink_visibility_bmesh(const Depsgraph &depsgraph,
1096 Object &object,
1097 const IndexMask &node_mask,
1098 const VisAction action,
1099 const int iterations)
1100{
1101 for (const int i : IndexRange(iterations)) {
1102 UNUSED_VARS(i);
1103 const Array<bool> prev_visibility = duplicate_visibility_bmesh(object);
1104 partialvis_update_bmesh_nodes(depsgraph, object, node_mask, action, [&](BMVert *vert) {
1105 BMeshNeighborVerts neighbors;
1106 for (BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
1107 if (prev_visibility[BM_elem_index_get(neighbor)] == action_to_hide(action)) {
1108 return true;
1109 }
1110 }
1111 return false;
1112 });
1113 }
1114}
1115
1117{
1118 const Scene &scene = *CTX_data_scene(C);
1119 Object &object = *CTX_data_active_object(C);
1121
1123
1124 const VisAction mode = VisAction(RNA_enum_get(op->ptr, "action"));
1125
1126 IndexMaskMemory memory;
1127 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1128
1129 int num_verts = SCULPT_vertex_count_get(object);
1130
1131 int iterations = RNA_int_get(op->ptr, "iterations");
1132
1133 if (RNA_boolean_get(op->ptr, "auto_iteration_count")) {
1134 /* Automatically adjust the number of iterations based on the number
1135 * of vertices in the mesh. */
1136 iterations = int(num_verts / VERTEX_ITERATION_THRESHOLD) + 1;
1137 }
1138
1139 undo::push_begin(scene, object, op);
1140 switch (pbvh.type()) {
1142 grow_shrink_visibility_mesh(depsgraph, object, node_mask, mode, iterations);
1143 break;
1145 grow_shrink_visibility_grid(depsgraph, object, node_mask, mode, iterations);
1146 break;
1148 grow_shrink_visibility_bmesh(depsgraph, object, node_mask, mode, iterations);
1149 break;
1150 }
1151 undo::push_end(object);
1152
1153 islands::invalidate(*object.sculpt);
1155
1156 return OPERATOR_FINISHED;
1157}
1158
1160{
1161 static EnumPropertyItem actions[] = {
1162 {int(VisAction::Show),
1163 "GROW",
1164 0,
1165 "Grow Visibility",
1166 "Grow the visibility by one face based on mesh topology"},
1167 {int(VisAction::Hide),
1168 "SHRINK",
1169 0,
1170 "Shrink Visibility",
1171 "Shrink the visibility by one face based on mesh topology"},
1172 {0, nullptr, 0, nullptr, nullptr},
1173 };
1174
1175 ot->name = "Visibility Filter";
1176 ot->idname = "PAINT_OT_visibility_filter";
1177 ot->description = "Edit the visibility of the current mesh";
1178
1179 ot->exec = visibility_filter_exec;
1181
1182 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1183
1184 RNA_def_enum(ot->srna, "action", actions, int(VisAction::Show), "Action", "");
1185
1186 RNA_def_int(ot->srna,
1187 "iterations",
1188 1,
1189 1,
1190 100,
1191 "Iterations",
1192 "Number of times that the filter is going to be applied",
1193 1,
1194 100);
1196 ot->srna,
1197 "auto_iteration_count",
1198 true,
1199 "Auto Iteration Count",
1200 "Use an automatic number of iterations based on the number of vertices of the sculpt");
1201}
1202
1204
1205/* -------------------------------------------------------------------- */
1209
1215
1217{
1218 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1219 Object *object = gesture_data.vc.obact;
1220 const Depsgraph &depsgraph = *gesture_data.vc.depsgraph;
1221 const VisAction action = operation->action;
1222 const IndexMask &node_mask = gesture_data.node_mask;
1223
1224 Mesh *mesh = static_cast<Mesh *>(object->data);
1225 bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
1226 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
1227 /* If everything is already visible, don't do anything. */
1228 return;
1229 }
1230
1231 const bool value = action_to_hide(action);
1232 const Span<float3> positions = bke::pbvh::vert_positions_eval(depsgraph, *object);
1235 depsgraph, *object, node_mask, [&](const Span<int> verts, MutableSpan<bool> hide) {
1236 for (const int i : verts.index_range()) {
1237 if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) {
1238 hide[i] = value;
1239 }
1240 }
1241 });
1242}
1243
1245 gesture::GestureData &gesture_data)
1246{
1247 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1248 Object *object = gesture_data.vc.obact;
1249 const VisAction action = operation->action;
1250 const IndexMask &node_mask = gesture_data.node_mask;
1251
1252 SubdivCCG &subdiv_ccg = *object->sculpt->subdiv_ccg;
1253
1254 const bool value = action_to_hide(action);
1255 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1256 const Span<float3> positions = subdiv_ccg.positions;
1257 const Span<float3> normals = subdiv_ccg.normals;
1258 grid_hide_update(depsgraph, *object, node_mask, [&](const int grid, MutableBoundedBitSpan hide) {
1259 const Span<float3> grid_positions = positions.slice(bke::ccg::grid_range(key, grid));
1260 const Span<float3> grid_normals = normals.slice(bke::ccg::grid_range(key, grid));
1261 for (const int i : grid_positions.index_range()) {
1262 if (gesture::is_affected(gesture_data, grid_positions[i], grid_normals[i])) {
1263 hide[i].set(value);
1264 }
1265 }
1266 });
1267}
1268
1270{
1271 const auto selection_test_fn = [&](const BMVert *v) {
1272 return gesture::is_affected(gesture_data, v->co, v->no);
1273 };
1274
1275 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1276
1278 *gesture_data.vc.obact,
1279 gesture_data.node_mask,
1280 operation->action,
1281 selection_test_fn);
1282}
1283
1284static void hide_show_begin(bContext &C, wmOperator &op, gesture::GestureData & /*gesture_data*/)
1285{
1286 const Scene &scene = *CTX_data_scene(&C);
1289
1290 undo::push_begin(scene, *ob, &op);
1292}
1293
1295{
1296 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
1297
1298 switch (bke::object::pbvh_get(*gesture_data.vc.obact)->type()) {
1300 partialvis_gesture_update_mesh(gesture_data);
1301 break;
1304 break;
1306 partialvis_gesture_update_bmesh(gesture_data);
1307 break;
1308 }
1309}
1310static void hide_show_end(bContext &C, gesture::GestureData &gesture_data)
1311{
1312 islands::invalidate(*gesture_data.vc.obact->sculpt);
1314 undo::push_end(*gesture_data.vc.obact);
1315}
1316
1318 gesture::GestureData &gesture_data,
1319 wmOperator &op)
1320{
1321 gesture_data.operation = reinterpret_cast<gesture::Operation *>(
1323
1324 HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
1325
1326 operation->op.begin = hide_show_begin;
1328 operation->op.end = hide_show_end;
1329
1330 operation->action = VisAction(RNA_enum_get(op.ptr, "action"));
1331 gesture_data.selection_type = gesture::SelectionType(RNA_enum_get(op.ptr, "area"));
1332}
1333
1335{
1336 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_box(C, op);
1337 if (!gesture_data) {
1338 return OPERATOR_CANCELLED;
1339 }
1340 hide_show_init_properties(*C, *gesture_data, *op);
1341 gesture::apply(*C, *gesture_data, *op);
1342 return OPERATOR_FINISHED;
1343}
1344
1346{
1347 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_lasso(C, op);
1348 if (!gesture_data) {
1349 return OPERATOR_CANCELLED;
1350 }
1351 hide_show_init_properties(*C, *gesture_data, *op);
1352 gesture::apply(*C, *gesture_data, *op);
1353 return OPERATOR_FINISHED;
1354}
1355
1357{
1358 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_line(C, op);
1359 if (!gesture_data) {
1360 return OPERATOR_CANCELLED;
1361 }
1362 hide_show_init_properties(*C, *gesture_data, *op);
1363 gesture::apply(*C, *gesture_data, *op);
1364 return OPERATOR_FINISHED;
1365}
1366
1368{
1369 std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_polyline(C, op);
1370 if (!gesture_data) {
1371 return OPERATOR_CANCELLED;
1372 }
1373 hide_show_init_properties(*C, *gesture_data, *op);
1374 gesture::apply(*C, *gesture_data, *op);
1375 return OPERATOR_FINISHED;
1376}
1377
1379{
1380 static const EnumPropertyItem area_items[] = {
1382 "OUTSIDE",
1383 0,
1384 "Outside",
1385 "Hide or show vertices outside the selection"},
1387 "Inside",
1388 0,
1389 "Inside",
1390 "Hide or show vertices inside the selection"},
1391 {0, nullptr, 0, nullptr, nullptr},
1392 };
1393
1394 RNA_def_enum(ot->srna,
1395 "area",
1396 area_items,
1398 "Visibility Area",
1399 "Which vertices to hide or show");
1400}
1401
1403{
1404 ot->name = "Hide/Show";
1405 ot->idname = "PAINT_OT_hide_show";
1406 ot->description = "Hide/show some vertices";
1407
1408 ot->invoke = WM_gesture_box_invoke;
1409 ot->modal = WM_gesture_box_modal;
1411 /* Sculpt-only for now. */
1413
1414 ot->flag = OPTYPE_REGISTER;
1415
1420}
1421
1423{
1424 ot->name = "Hide/Show Lasso";
1425 ot->idname = "PAINT_OT_hide_show_lasso_gesture";
1426 ot->description = "Hide/show some vertices";
1427
1428 ot->invoke = WM_gesture_lasso_invoke;
1429 ot->modal = WM_gesture_lasso_modal;
1431 /* Sculpt-only for now. */
1433
1435
1440}
1441
1443{
1444 ot->name = "Hide/Show Line";
1445 ot->idname = "PAINT_OT_hide_show_line_gesture";
1446 ot->description = "Hide/show some vertices";
1447
1451 /* Sculpt-only for now. */
1453
1454 ot->flag = OPTYPE_REGISTER;
1455
1460}
1461
1463{
1464 ot->name = "Hide/Show Polyline";
1465 ot->idname = "PAINT_OT_hide_show_polyline_gesture";
1466 ot->description = "Hide/show some vertices";
1467
1471 /* Sculpt-only for now. */
1473
1475
1480}
1481
1483
1484} // 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:77
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)
void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresModifiedFlags flags)
Definition multires.cc:365
void BKE_sculpt_sync_face_visibility_to_grids(const Mesh &mesh, SubdivCCG &subdiv_ccg)
Definition paint.cc:2813
bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d)
Definition paint.cc:2928
bool paint_is_bmesh_face_hidden(const BMFace *f)
Definition paint.cc:1998
A BVH for high poly meshes.
void BKE_pbvh_node_fully_hidden_set(blender::bke::pbvh::Node &node, int fully_hidden)
Definition pbvh.cc:1527
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:2462
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)
@ MULTIRES_HIDDEN_MODIFIED
#define UNUSED_VARS(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SHADING
Definition DNA_ID.h:1002
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ 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:639
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
#define ND_DRAW
Definition WM_types.hh:458
@ 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:376
#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
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)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type)
Span< NodeT > nodes() const
std::unique_ptr< DrawCache > draw_data
void tag_visibility_changed(const IndexMask &node_mask)
Definition pbvh.cc:570
void update_visibility(const Object &object)
Definition pbvh.cc:1395
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:290
int face_corner_next(const IndexRange face, const int corner)
Definition BKE_mesh.hh:299
pbvh::Tree & pbvh_ensure(Depsgraph &depsgraph, Object &object)
Definition paint.cc:2877
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2912
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2544
void node_update_visibility_grids(const BitGroupVector<> &grid_hidden, GridsNode &node)
Definition pbvh.cc:1352
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2435
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2416
void node_update_visibility_mesh(Span< bool > hide_vert, MeshNode &node)
Definition pbvh.cc:1328
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:57
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:6183
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:142
Vector< BMVert *, 64 > BMeshNeighborVerts
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6419
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, BMeshNeighborVerts &r_neighbors)
Definition sculpt.cc:388
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6379
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:3666
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:152
BMLoop * l_first
int grid_size
Definition BKE_ccg.hh:33
struct SculptSession * sculpt
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:415
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:4225
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]