Blender V4.3
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_math_geom.h"
17#include "BLI_math_vector.h"
18#include "BLI_utildefines.h"
19#include "BLI_vector.hh"
20
21#include "DNA_object_types.h"
22
23#include "BKE_attribute.hh"
24#include "BKE_ccg.hh"
25#include "BKE_context.hh"
26#include "BKE_mesh.hh"
27#include "BKE_multires.hh"
28#include "BKE_paint.hh"
29#include "BKE_pbvh_api.hh"
30#include "BKE_subdiv_ccg.hh"
31#include "BKE_subsurf.hh"
32
33#include "DEG_depsgraph.hh"
34
35#include "WM_api.hh"
36#include "WM_types.hh"
37
38#include "ED_screen.hh"
39
40#include "RNA_access.hh"
41#include "RNA_define.hh"
42
43#include "bmesh.hh"
44
45#include "mesh_brush_common.hh"
46#include "paint_intern.hh"
47#include "sculpt_automask.hh"
48#include "sculpt_gesture.hh"
49#include "sculpt_intern.hh"
50#include "sculpt_islands.hh"
51#include "sculpt_undo.hh"
52
54
55/* -------------------------------------------------------------------- */
60{
61 SculptSession &ss = *object.sculpt;
62 Mesh &mesh = *static_cast<Mesh *>(object.data);
63
65
66 switch (bke::object::pbvh_get(object)->type()) {
68 /* We may have adjusted the ".hide_poly" attribute, now make the hide status attributes for
69 * vertices and edges consistent. */
71 break;
72 }
74 /* In addition to making the hide status of the base mesh consistent, we also have to
75 * propagate the status to the Multires grids. */
78 break;
79 }
81 BMesh &bm = *ss.bm;
82 BMIter iter;
83 BMFace *f;
84
85 /* Hide all verts and edges attached to faces. */
86 BM_ITER_MESH (f, &iter, &bm, BM_FACES_OF_MESH) {
87 BMLoop *l = f->l_first;
88 do {
91 } while ((l = l->next) != f->l_first);
92 }
93
94 /* Unhide verts and edges attached to visible faces. */
95 BM_ITER_MESH (f, &iter, &bm, BM_FACES_OF_MESH) {
97 continue;
98 }
99
100 BMLoop *l = f->l_first;
101 do {
104 } while ((l = l->next) != f->l_first);
105 }
106 break;
107 }
108 }
109}
110
112{
113 ARegion *region = CTX_wm_region(&C);
114 ED_region_tag_redraw(region);
115
118
120 const RegionView3D *rv3d = CTX_wm_region_view3d(&C);
121 if (!BKE_sculptsession_use_pbvh_draw(ob, rv3d)) {
123 }
124}
125
126void mesh_show_all(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
127{
128 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
130 Mesh &mesh = *static_cast<Mesh *>(object.data);
131 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
132 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
133
134 if (!hide_vert.is_empty()) {
135 IndexMaskMemory memory;
136 const IndexMask changed_nodes = IndexMask::from_predicate(
137 node_mask, GrainSize(1), memory, [&](const int i) {
138 const Span<int> verts = nodes[i].verts();
139 return std::any_of(
140 verts.begin(), verts.end(), [&](const int i) { return hide_vert[i]; });
141 });
142 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
143 pbvh.tag_visibility_changed(changed_nodes);
144 }
145
146 attributes.remove(".hide_vert");
148 bke::pbvh::update_visibility(object, pbvh);
149}
150
151void grids_show_all(Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
152{
153 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
155 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
156 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
157
158 if (!grid_hidden.is_empty()) {
159 IndexMaskMemory memory;
160 const IndexMask changed_nodes = IndexMask::from_predicate(
161 node_mask, GrainSize(1), memory, [&](const int i) {
162 const Span<int> grids = nodes[i].grids();
163 return std::any_of(grids.begin(), grids.end(), [&](const int i) {
164 return bits::any_bit_set(grid_hidden[i]);
165 });
166 });
167 if (changed_nodes.is_empty()) {
168 return;
169 }
170 undo::push_nodes(depsgraph, object, changed_nodes, undo::Type::HideVert);
171 pbvh.tag_visibility_changed(changed_nodes);
172 }
173
176 bke::pbvh::update_visibility(object, pbvh);
178}
179
182/* -------------------------------------------------------------------- */
187enum class VisAction {
188 Hide = 0,
189 Show = 1,
190};
191
192static bool action_to_hide(const VisAction action)
193{
194 return action == VisAction::Hide;
195}
196
197/* Calculates whether a face should be hidden based on all of its corner vertices.*/
198static void calc_face_hide(const Span<int> node_faces,
199 const OffsetIndices<int> faces,
200 const Span<int> corner_verts,
201 const Span<bool> hide_vert,
202 MutableSpan<bool> hide_face)
203{
204 for (const int i : node_faces.index_range()) {
205 Span<int> face_verts = corner_verts.slice(faces[node_faces[i]]);
206 hide_face[i] = std::any_of(
207 face_verts.begin(), face_verts.end(), [&](const int v) { return hide_vert[v]; });
208 }
209}
210
211/* Updates a node's face's visibility based on the updated vertex visibility. */
213 bke::pbvh::Tree &pbvh,
214 const IndexMask &node_mask,
215 const Span<bool> hide_vert)
216{
217 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
218
219 const OffsetIndices<int> faces = mesh.faces();
220 const Span<int> corner_verts = mesh.corner_verts();
221
222 bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
223 ".hide_poly", bke::AttrDomain::Face);
224
226
227 Array<bool> node_changed(node_mask.min_array_size(), false);
228
229 struct TLS {
230 Vector<bool> new_hide;
231 };
233 node_mask.foreach_index(GrainSize(1), [&](const int i) {
234 TLS &tls = all_tls.local();
235 const Span<int> node_faces = nodes[i].faces();
236
237 tls.new_hide.resize(node_faces.size());
238 gather_data_mesh(hide_poly.span.as_span(), node_faces, tls.new_hide.as_mutable_span());
239
240 calc_face_hide(node_faces, faces, corner_verts, hide_vert, tls.new_hide.as_mutable_span());
241
242 if (array_utils::indexed_data_equal<bool>(hide_poly.span, node_faces, tls.new_hide)) {
243 return;
244 }
245
246 scatter_data_mesh(tls.new_hide.as_span(), node_faces, hide_poly.span);
247 node_changed[i] = true;
248 bke::pbvh::node_update_visibility_mesh(hide_vert, nodes[i]);
249 });
250 hide_poly.finish();
251
252 IndexMaskMemory memory;
253 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
254 if (changed_nodes.is_empty()) {
255 return;
256 }
257 pbvh.tag_visibility_changed(node_mask);
258}
259
260/* Updates a node's face's visibility based on the updated vertex visibility. */
261static void flush_face_changes(Mesh &mesh, const Span<bool> hide_vert)
262{
263 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
264
265 bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
266 ".hide_poly", bke::AttrDomain::Face);
267
268 bke::mesh_face_hide_from_vert(mesh.faces(), mesh.corner_verts(), hide_vert, hide_poly.span);
269 hide_poly.finish();
270}
271
272/* Updates all of a mesh's edge visibility based on vertex visibility. */
273static void flush_edge_changes(Mesh &mesh, const Span<bool> hide_vert)
274{
275 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
276
277 bke::SpanAttributeWriter<bool> hide_edge = attributes.lookup_or_add_for_write_only_span<bool>(
278 ".hide_edge", bke::AttrDomain::Edge);
279 bke::mesh_edge_hide_from_vert(mesh.edges(), hide_vert, hide_edge.span);
280 hide_edge.finish();
281}
282
283static void vert_hide_update(const Depsgraph &depsgraph,
284 Object &object,
285 const IndexMask &node_mask,
286 const FunctionRef<void(Span<int>, MutableSpan<bool>)> calc_hide)
287{
288 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
290
291 Mesh &mesh = *static_cast<Mesh *>(object.data);
292 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
293 bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
294 ".hide_vert", bke::AttrDomain::Point);
295
296 bool any_changed = false;
298 node_mask.foreach_index(GrainSize(1), [&](const int i) {
299 Vector<bool> &new_hide = all_new_hide.local();
300 const Span<int> verts = nodes[i].verts();
301
302 new_hide.resize(verts.size());
303 gather_data_mesh(hide_vert.span.as_span(), verts, new_hide.as_mutable_span());
304 calc_hide(verts, new_hide);
305 if (array_utils::indexed_data_equal<bool>(hide_vert.span, verts, new_hide)) {
306 return;
307 }
308
309 any_changed = true;
311 scatter_data_mesh(new_hide.as_span(), verts, hide_vert.span);
312 });
313
314 hide_vert.finish();
315 if (any_changed) {
316 /* We handle flushing ourselves at the node level instead of delegating to
317 * bke::mesh_hide_vert_flush because we need to tag node visibility changes as well in cases
318 * where the vertices hidden are on a node boundary.*/
319 flush_face_changes_node(mesh, pbvh, node_mask, hide_vert.span);
320 flush_edge_changes(mesh, hide_vert.span);
321 }
322}
323
324static void grid_hide_update(Depsgraph &depsgraph,
325 Object &object,
326 const IndexMask &node_mask,
327 const FunctionRef<void(const int, MutableBoundedBitSpan)> calc_hide)
328{
329 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
331
332 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
333 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
334
335 Array<bool> node_changed(node_mask.min_array_size(), false);
336
337 bool any_changed = false;
338 node_mask.foreach_index(GrainSize(1), [&](const int i) {
339 const Span<int> grids = nodes[i].grids();
340 BitGroupVector<> new_hide(grids.size(), grid_hidden.group_size());
341 for (const int i : grids.index_range()) {
342 new_hide[i].copy_from(grid_hidden[grids[i]].as_span());
343 }
344
345 for (const int i : grids.index_range()) {
346 calc_hide(grids[i], new_hide[i]);
347 }
348
349 if (std::all_of(grids.index_range().begin(), grids.index_range().end(), [&](const int i) {
350 return bits::spans_equal(grid_hidden[grids[i]], new_hide[i]);
351 }))
352 {
353 return;
354 }
355
356 any_changed = true;
358
359 for (const int i : grids.index_range()) {
360 grid_hidden[grids[i]].copy_from(new_hide[i].as_span());
361 }
362
363 node_changed[i] = true;
364 bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]);
365 });
366
367 IndexMaskMemory memory;
368 const IndexMask changed_nodes = IndexMask::from_bools(node_changed, memory);
369 if (changed_nodes.is_empty()) {
370 return;
371 }
372 pbvh.tag_visibility_changed(node_mask);
375}
376
378 const VisAction action,
379 const FunctionRef<bool(BMVert *v)> should_update,
380 bool *any_changed,
381 bool *any_visible)
382{
383 for (BMVert *v : verts) {
384 if (should_update(v)) {
385 if (action == VisAction::Hide) {
387 }
388 else {
390 }
391 (*any_changed) = true;
392 }
393
395 (*any_visible) = true;
396 }
397 }
398}
399
401{
402 for (BMFace *f : faces) {
405 }
406 else {
408 }
409 }
410}
411
412static void partialvis_update_bmesh_nodes(const Depsgraph &depsgraph,
413 Object &ob,
414 const IndexMask &node_mask,
415 const VisAction action,
416 const FunctionRef<bool(BMVert *v)> vert_test_fn)
417{
420
421 node_mask.foreach_index([&](const int i) {
422 bool any_changed = false;
423 bool any_visible = false;
424
426
428 action,
429 vert_test_fn,
430 &any_changed,
431 &any_visible);
432
434 action,
435 vert_test_fn,
436 &any_changed,
437 &any_visible);
438
439 /* Finally loop over node faces and tag the ones that are fully hidden. */
441
442 if (any_changed) {
443 BKE_pbvh_node_fully_hidden_set(nodes[i], !any_visible);
444 }
445 });
446
447 pbvh.tag_visibility_changed(node_mask);
449}
450
453/* -------------------------------------------------------------------- */
458static void partialvis_all_update_mesh(const Depsgraph &depsgraph,
459 Object &object,
460 const VisAction action,
461 const IndexMask &node_mask)
462{
463 Mesh &mesh = *static_cast<Mesh *>(object.data);
464 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
465 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
466 /* If everything is already visible, don't do anything. */
467 return;
468 }
469
470 switch (action) {
471 case VisAction::Hide:
473 depsgraph, object, node_mask, [&](const Span<int> /*verts*/, MutableSpan<bool> hide) {
474 hide.fill(true);
475 });
476 break;
477 case VisAction::Show:
478 mesh_show_all(depsgraph, object, node_mask);
479 break;
480 }
481}
482
484 Object &object,
485 const VisAction action,
486 const IndexMask &node_mask)
487{
488 switch (action) {
489 case VisAction::Hide:
491 object,
492 node_mask,
493 [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(true); });
494 break;
495 case VisAction::Show:
496 grids_show_all(depsgraph, object, node_mask);
497 break;
498 }
499}
500
501static void partialvis_all_update_bmesh(const Depsgraph &depsgraph,
502 Object &ob,
503 const VisAction action,
504 const IndexMask &node_mask)
505{
507 depsgraph, ob, node_mask, action, [](const BMVert * /*vert*/) { return true; });
508}
509
511{
512 const Scene &scene = *CTX_data_scene(C);
515
516 const VisAction action = VisAction(RNA_enum_get(op->ptr, "action"));
517
519
520 /* Start undo. */
521 switch (action) {
522 case VisAction::Hide:
523 undo::push_begin_ex(scene, ob, "Hide area");
524 break;
525 case VisAction::Show:
526 undo::push_begin_ex(scene, ob, "Show area");
527 break;
528 }
529
530 IndexMaskMemory memory;
531 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
532
533 switch (pbvh.type()) {
535 partialvis_all_update_mesh(*depsgraph, ob, action, node_mask);
536 break;
538 partialvis_all_update_grids(*depsgraph, ob, action, node_mask);
539 break;
541 partialvis_all_update_bmesh(*depsgraph, ob, action, node_mask);
542 break;
543 }
544
545 /* End undo. */
546 undo::push_end(ob);
547
550
551 return OPERATOR_FINISHED;
552}
553
554static void partialvis_masked_update_mesh(const Depsgraph &depsgraph,
555 Object &object,
556 const VisAction action,
557 const IndexMask &node_mask)
558{
559 Mesh &mesh = *static_cast<Mesh *>(object.data);
560 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
561 if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
562 /* If everything is already visible, don't do anything. */
563 return;
564 }
565
566 const bool value = action_to_hide(action);
567 const VArraySpan<float> mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
568 if (action == VisAction::Show && mask.is_empty()) {
569 mesh_show_all(depsgraph, object, node_mask);
570 }
571 else if (!mask.is_empty()) {
573 depsgraph, object, node_mask, [&](const Span<int> verts, MutableSpan<bool> hide) {
574 for (const int i : verts.index_range()) {
575 if (mask[verts[i]] > 0.5f) {
576 hide[i] = value;
577 }
578 }
579 });
580 }
581}
582
584 Object &object,
585 const VisAction action,
586 const IndexMask &node_mask)
587{
588 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
589
590 const bool value = action_to_hide(action);
591 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
592 const Span<float> masks = subdiv_ccg.masks;
593 if (masks.is_empty()) {
595 object,
596 node_mask,
597 [&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(value); });
598 }
599 else {
601 depsgraph, object, node_mask, [&](const int grid, MutableBoundedBitSpan hide) {
602 const Span<float> grid_masks = masks.slice(bke::ccg::grid_range(key, grid));
603 for (const int i : grid_masks.index_range()) {
604 if (grid_masks[i] > 0.5f) {
605 hide[i].set(value);
606 }
607 }
608 });
609 }
610}
611
612static void partialvis_masked_update_bmesh(const Depsgraph &depsgraph,
613 Object &ob,
614 const VisAction action,
615 const IndexMask &node_mask)
616{
617 BMesh *bm = ob.sculpt->bm;
618 const int mask_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
619 const auto mask_test_fn = [&](const BMVert *v) {
620 const float vmask = BM_ELEM_CD_GET_FLOAT(v, mask_offset);
621 return vmask > 0.5f;
622 };
623
624 partialvis_update_bmesh_nodes(depsgraph, ob, node_mask, action, mask_test_fn);
625}
626
628{
629 const Scene &scene = *CTX_data_scene(C);
632
633 const VisAction action = VisAction(RNA_enum_get(op->ptr, "action"));
634
636
637 /* Start undo. */
638 switch (action) {
639 case VisAction::Hide:
640 undo::push_begin_ex(scene, ob, "Hide area");
641 break;
642 case VisAction::Show:
643 undo::push_begin_ex(scene, ob, "Show area");
644 break;
645 }
646
647 IndexMaskMemory memory;
648 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
649
650 switch (pbvh.type()) {
652 partialvis_masked_update_mesh(*depsgraph, ob, action, node_mask);
653 break;
655 partialvis_masked_update_grids(*depsgraph, ob, action, node_mask);
656 break;
658 partialvis_masked_update_bmesh(*depsgraph, ob, action, node_mask);
659 break;
660 }
661
662 /* End undo. */
663 undo::push_end(ob);
664
667
668 return OPERATOR_FINISHED;
669}
670
672{
673 static const EnumPropertyItem action_items[] = {
674 {int(VisAction::Hide), "HIDE", 0, "Hide", "Hide vertices"},
675 {int(VisAction::Show), "SHOW", 0, "Show", "Show vertices"},
676 {0, nullptr, 0, nullptr, nullptr},
677 };
678
680 "action",
681 action_items,
682 int(VisAction::Hide),
683 "Visibility Action",
684 "Whether to hide or show vertices");
685}
686
688{
689 ot->name = "Hide/Show Masked";
690 ot->idname = "PAINT_OT_hide_show_masked";
691 ot->description = "Hide/show all masked vertices above a threshold";
692
694 /* Sculpt-only for now. */
696
698
700}
701
703{
704 ot->name = "Hide/Show All";
705 ot->idname = "PAINT_OT_hide_show_all";
706 ot->description = "Hide/show all vertices";
707
709 /* Sculpt-only for now. */
711
713
715}
716
717static void invert_visibility_mesh(const Depsgraph &depsgraph,
718 Object &object,
719 const IndexMask &node_mask)
720{
721 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
723
724 Mesh &mesh = *static_cast<Mesh *>(object.data);
725 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
726 bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
727 ".hide_poly", bke::AttrDomain::Face);
728
730
731 node_mask.foreach_index(GrainSize(1), [&](const int i) {
732 for (const int face : nodes[i].faces()) {
733 hide_poly.span[face] = !hide_poly.span[face];
734 }
735 });
736
737 hide_poly.finish();
739 pbvh.tag_visibility_changed(node_mask);
741}
742
743static void invert_visibility_grids(Depsgraph &depsgraph,
744 Object &object,
745 const IndexMask &node_mask)
746{
747 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
749 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
750
752
753 BitGroupVector<> &grid_hidden = BKE_subdiv_ccg_grid_hidden_ensure(subdiv_ccg);
754 node_mask.foreach_index(GrainSize(1), [&](const int i) {
755 for (const int i : nodes[i].grids()) {
756 bits::invert(grid_hidden[i]);
757 }
758 bke::pbvh::node_update_visibility_grids(grid_hidden, nodes[i]);
759 });
760
761 pbvh.tag_visibility_changed(node_mask);
764}
765
766static void invert_visibility_bmesh(const Depsgraph &depsgraph,
767 Object &object,
768 const IndexMask &node_mask)
769{
770 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
773
774 node_mask.foreach_index(GrainSize(1), [&](const int i) {
775 bool fully_hidden = true;
776 for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
778 fully_hidden &= BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN);
779 }
780 BKE_pbvh_node_fully_hidden_set(nodes[i], fully_hidden);
781 });
782 node_mask.foreach_index(GrainSize(1), [&](const int i) {
784 });
785 pbvh.tag_visibility_changed(node_mask);
786}
787
789{
790 const Scene &scene = *CTX_data_scene(C);
791 Object &object = *CTX_data_active_object(C);
793
795
796 IndexMaskMemory memory;
797 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
798 undo::push_begin(scene, object, op);
799 switch (pbvh.type()) {
801 invert_visibility_mesh(depsgraph, object, node_mask);
802 break;
804 invert_visibility_grids(depsgraph, object, node_mask);
805 break;
807 invert_visibility_bmesh(depsgraph, object, node_mask);
808 break;
809 }
810
811 undo::push_end(object);
812
813 islands::invalidate(*object.sculpt);
815
816 return OPERATOR_FINISHED;
817}
818
820{
821 ot->name = "Invert Visibility";
822 ot->idname = "PAINT_OT_visibility_invert";
823 ot->description = "Invert the visibility of all vertices";
824
827
829}
830
831/* Number of vertices per iteration step size when growing or shrinking visibility. */
832static constexpr float VERTEX_ITERATION_THRESHOLD = 50000.0f;
833
834/* Extracting the loop and comparing against / writing with a constant `false` or `true` instead of
835 * using #action_to_hide results in a nearly 600ms speedup on a mesh with 1.5m verts. */
836template<bool value>
837static void affect_visibility_mesh(const IndexRange face,
838 const Span<int> corner_verts,
839 const Span<bool> read_buffer,
840 MutableSpan<bool> write_buffer)
841{
842 for (const int corner : face) {
843 int vert = corner_verts[corner];
844 if (read_buffer[vert] != value) {
845 continue;
846 }
847
848 const int prev = bke::mesh::face_corner_prev(face, corner);
849 const int prev_vert = corner_verts[prev];
850 write_buffer[prev_vert] = value;
851
852 const int next = bke::mesh::face_corner_next(face, corner);
853 const int next_vert = corner_verts[next];
854 write_buffer[next_vert] = value;
855 }
856}
857
861
863 {
864 return count % 2 == 0 ? back.as_mutable_span() : front.as_mutable_span();
865 }
866
868 {
869 return count % 2 == 0 ? front.as_span() : back.as_span();
870 }
871};
872
875 const VArraySpan<bool> &hide_poly,
876 const VisAction action,
877 const int iterations)
878{
879 const OffsetIndices faces = mesh.faces();
880 const Span<int> corner_verts = mesh.corner_verts();
881
882 for (const int i : IndexRange(iterations)) {
883 Span<bool> read_buffer = buffers.read_buffer(i);
884 MutableSpan<bool> write_buffer = buffers.write_buffer(i);
885 threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
886 for (const int face_index : range) {
887 if (!hide_poly[face_index]) {
888 continue;
889 }
890 const IndexRange face = faces[face_index];
891 if (action == VisAction::Hide) {
892 affect_visibility_mesh<true>(face, corner_verts, read_buffer, write_buffer);
893 }
894 else {
895 affect_visibility_mesh<false>(face, corner_verts, read_buffer, write_buffer);
896 }
897 }
898 });
899
900 flush_face_changes(mesh, write_buffer);
901 }
902}
903
904static void update_undo_state(const Depsgraph &depsgraph,
905 Object &object,
906 const IndexMask &node_mask,
907 const Span<bool> old_hide_vert,
908 const Span<bool> new_hide_vert)
909{
910 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
912
913 node_mask.foreach_index(GrainSize(1), [&](const int i) {
914 for (const int vert : nodes[i].verts()) {
915 if (old_hide_vert[vert] != new_hide_vert[vert]) {
916 undo::push_node(depsgraph, object, &nodes[i], undo::Type::HideVert);
917 break;
918 }
919 }
920 });
921}
922
924 const IndexMask &node_mask,
925 const Span<bool> orig_hide_poly,
926 const Span<bool> new_hide_poly,
927 const Span<bool> hide_vert)
928{
929 Array<bool> node_changed(node_mask.min_array_size(), false);
930
931 node_mask.foreach_index(GrainSize(1), [&](const int i) {
932 bool any_changed = false;
933 const Span<int> indices = nodes[i].faces();
934 for (const int face_index : indices) {
935 if (orig_hide_poly[face_index] != new_hide_poly[face_index]) {
936 any_changed = true;
937 break;
938 }
939 }
940
941 if (any_changed) {
942 node_changed[i] = true;
943 bke::pbvh::node_update_visibility_mesh(hide_vert, nodes[i]);
944 }
945 });
946
947 // TODO
948}
949
950static void grow_shrink_visibility_mesh(const Depsgraph &depsgraph,
951 Object &object,
952 const IndexMask &node_mask,
953 const VisAction action,
954 const int iterations)
955{
956 Mesh &mesh = *static_cast<Mesh *>(object.data);
957 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
958 if (!attributes.contains(".hide_vert")) {
959 /* If the entire mesh is visible, we can neither grow nor shrink the boundary. */
960 return;
961 }
962
963 bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
964 ".hide_vert", bke::AttrDomain::Point);
965 const VArraySpan hide_poly = *attributes.lookup_or_default<bool>(
966 ".hide_poly", bke::AttrDomain::Face, false);
967
969 buffers.back.reinitialize(hide_vert.span.size());
970 buffers.front.reinitialize(hide_vert.span.size());
971 array_utils::copy(hide_vert.span.as_span(), buffers.back.as_mutable_span());
972 array_utils::copy(hide_vert.span.as_span(), buffers.front.as_mutable_span());
973
974 Array<bool> orig_hide_poly(hide_poly);
975 propagate_vertex_visibility(mesh, buffers, hide_poly, action, iterations);
976
977 const Span<bool> last_buffer = buffers.write_buffer(iterations - 1);
978
979 update_undo_state(depsgraph, object, node_mask, hide_vert.span, last_buffer);
980
981 /* We can wait until after all iterations are done to flush edge changes as they are
982 * not used for coarse filtering while iterating.*/
983 flush_edge_changes(mesh, last_buffer);
984
986 bke::object::pbvh_get(object)->nodes<bke::pbvh::MeshNode>(),
987 node_mask,
988 orig_hide_poly,
989 hide_poly,
990 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 bke::pbvh::update_visibility(object, pbvh);
1078
1081}
1082
1084{
1085 const SculptSession &ss = *object.sculpt;
1086 BMesh &bm = *ss.bm;
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 Vector<BMVert *, 64> 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
1122 bke::pbvh::Tree &pbvh = bke::object::pbvh_ensure(depsgraph, object);
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()) {
1141 case bke::pbvh::Type::Mesh:
1142 grow_shrink_visibility_mesh(depsgraph, object, node_mask, mode, iterations);
1143 break;
1144 case bke::pbvh::Type::Grids:
1145 grow_shrink_visibility_grid(depsgraph, object, node_mask, mode, iterations);
1146 break;
1147 case bke::pbvh::Type::BMesh:
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
1181
1183
1184 RNA_def_enum(ot->srna, "action", actions, int(VisAction::Show), "Action", "");
1185
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
1205/* -------------------------------------------------------------------- */
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);
1233 const Span<float3> normals = bke::pbvh::vert_normals_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);
1291 bke::object::pbvh_ensure(*depsgraph, *ob);
1292}
1293
1295{
1296 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
1297
1298 switch (bke::object::pbvh_get(*gesture_data.vc.obact)->type()) {
1299 case bke::pbvh::Type::Mesh:
1300 partialvis_gesture_update_mesh(gesture_data);
1301 break;
1302 case bke::pbvh::Type::Grids:
1304 break;
1305 case bke::pbvh::Type::BMesh:
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 *>(
1322 MEM_cnew<HideShowOperation>(__func__));
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[] = {
1381 {int(gesture::SelectionType::Outside),
1382 "OUTSIDE",
1383 0,
1384 "Outside",
1385 "Hide or show vertices outside the selection"},
1386 {int(gesture::SelectionType::Inside),
1387 "Inside",
1388 0,
1389 "Inside",
1390 "Hide or show vertices inside the selection"},
1391 {0, nullptr, 0, nullptr, nullptr},
1392 };
1393
1395 "area",
1396 area_items,
1397 int(gesture::SelectionType::Inside),
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
1411 /* Sculpt-only for now. */
1413
1415
1419 gesture::operator_properties(ot, gesture::ShapeType::Box);
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
1431 /* Sculpt-only for now. */
1433
1435
1439 gesture::operator_properties(ot, gesture::ShapeType::Lasso);
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
1455
1459 gesture::operator_properties(ot, gesture::ShapeType::Line);
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
1479 gesture::operator_properties(ot, gesture::ShapeType::Lasso);
1480}
1481
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:373
void BKE_sculpt_sync_face_visibility_to_grids(const Mesh &mesh, SubdivCCG &subdiv_ccg)
Definition paint.cc:2747
bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d)
Definition paint.cc:2862
bool paint_is_bmesh_face_hidden(const BMFace *f)
Definition paint.cc:1951
A BVH for high poly meshes.
void BKE_pbvh_node_fully_hidden_set(blender::bke::pbvh::Node &node, int fully_hidden)
Definition pbvh.cc:1530
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:2530
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:1061
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
@ CD_PROP_FLOAT
Object is a sort of wrapper for general info.
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
Read Guarded memory(de)allocation.
@ OPTYPE_DEPENDS_ON_CURSOR
Definition WM_types.hh:198
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define ND_DRAW
Definition WM_types.hh:428
#define NC_OBJECT
Definition WM_types.hh:346
#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
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
#define BM_VERT
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
Span< T > as_span() const
Definition BLI_array.hh:232
MutableSpan< T > as_mutable_span()
Definition BLI_array.hh:237
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
constexpr Iterator end() const
constexpr Iterator begin() const
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:138
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr const T * end() const
Definition BLI_span.hh:225
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr const T * begin() const
Definition BLI_span.hh:221
constexpr bool is_empty() const
Definition BLI_span.hh:261
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
Span< T > as_span() const
void fill(const bool value)
Span< NodeT > nodes() const
void tag_visibility_changed(const IndexMask &node_mask)
Definition pbvh.cc:562
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static ushort indices[]
static float verts[][3]
int count
static ulong * next
static char faces[256]
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:243
int face_corner_next(const IndexRange face, const int corner)
Definition BKE_mesh.hh:252
pbvh::Tree & pbvh_ensure(Depsgraph &depsgraph, Object &object)
Definition paint.cc:2811
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2612
void node_update_visibility_grids(const BitGroupVector<> &grid_hidden, GridsNode &node)
Definition pbvh.cc:1334
void update_visibility(const Object &object, Tree &pbvh)
Definition pbvh.cc:1377
void node_update_visibility_mesh(Span< bool > hide_vert, MeshNode &node)
Definition pbvh.cc:1310
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)
static void invert_visibility_bmesh(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask)
static constexpr float VERTEX_ITERATION_THRESHOLD
static void update_node_visibility_from_face_changes(MutableSpan< bke::pbvh::MeshNode > nodes, const IndexMask &node_mask, const Span< bool > orig_hide_poly, const Span< bool > new_hide_poly, const Span< bool > hide_vert)
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 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 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 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 int hide_show_gesture_line_exec(bContext *C, wmOperator *op)
static int visibility_filter_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 int visibility_invert_exec(bContext *C, wmOperator *op)
static void hide_show_init_properties(bContext &, gesture::GestureData &gesture_data, wmOperator &op)
static int hide_show_gesture_box_exec(bContext *C, wmOperator *op)
static void partialvis_update_bmesh_faces(const Set< BMFace *, 0 > &faces)
static int hide_show_gesture_lasso_exec(bContext *C, wmOperator *op)
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:59
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 int hide_show_all_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 void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data)
static int hide_show_gesture_polyline_exec(bContext *C, wmOperator *op)
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 int hide_show_masked_exec(bContext *C, wmOperator *op)
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:5895
void push_nodes(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Type type)
void push_node(const Depsgraph &depsgraph, const Object &object, const bke::pbvh::Node *node, Type type)
void push_begin_ex(const Scene &, Object &ob, const char *name)
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6122
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
Definition sculpt.cc:389
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6082
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:95
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:3566
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:153
BMLoop * l_first
struct BMVert * v
struct BMEdge * e
struct BMLoop * next
float co[3]
float no[3]
int totvert
CustomData vdata
int grid_size
Definition BKE_ccg.hh:33
struct SculptSession * sculpt
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > normals
blender::Array< float > masks
blender::Array< blender::float3 > positions
Object * obact
Definition ED_view3d.hh:71
Depsgraph * depsgraph
Definition ED_view3d.hh:68
void(* end)(bContext &, GestureData &)
void(* begin)(bContext &, wmOperator &, GestureData &)
void(* apply_for_symmetry_pass)(bContext &, GestureData &)
MutableSpan< bool > write_buffer(int count)
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
StructRNA * srna
Definition WM_types.hh:1080
struct PointerRNA * ptr
@ 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:4125
int WM_gesture_polyline_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_polyline_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_straightline_oneshot_modal(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_straightline_active_side_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor)
void WM_operator_properties_border(wmOperatorType *ot)
void WM_operator_properties_gesture_lasso(wmOperatorType *ot)
void WM_operator_properties_gesture_polyline(wmOperatorType *ot)
char * buffers[2]