Cleanup: Add doxygen and restructure paint_hide.cc #119929
@ -51,6 +51,10 @@
|
|||||||
|
|
||||||
namespace blender::ed::sculpt_paint::hide {
|
namespace blender::ed::sculpt_paint::hide {
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Public API
|
||||||
|
* \{ */
|
||||||
|
|
||||||
void sync_all_from_faces(Object &object)
|
void sync_all_from_faces(Object &object)
|
||||||
{
|
{
|
||||||
SculptSession &ss = *object.sculpt;
|
SculptSession &ss = *object.sculpt;
|
||||||
@ -118,22 +122,6 @@ void tag_update_visibility(const bContext &C)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class VisAction {
|
|
||||||
Hide = 0,
|
|
||||||
Show = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HideShowOperation {
|
|
||||||
gesture::Operation op;
|
|
||||||
|
|
||||||
VisAction action;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool action_to_hide(const VisAction action)
|
|
||||||
{
|
|
||||||
return action == VisAction::Hide;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mesh_show_all(Object &object, const Span<PBVHNode *> nodes)
|
void mesh_show_all(Object &object, const Span<PBVHNode *> nodes)
|
||||||
{
|
{
|
||||||
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
||||||
@ -159,6 +147,56 @@ void mesh_show_all(Object &object, const Span<PBVHNode *> nodes)
|
|||||||
bke::mesh_hide_vert_flush(mesh);
|
bke::mesh_hide_vert_flush(mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void grids_show_all(Depsgraph &depsgraph, Object &object, const Span<PBVHNode *> nodes)
|
||||||
|
{
|
||||||
|
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
||||||
|
PBVH &pbvh = *object.sculpt->pbvh;
|
||||||
|
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
|
||||||
|
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
|
||||||
|
bool any_changed = false;
|
||||||
|
if (!grid_hidden.is_empty()) {
|
||||||
|
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
|
||||||
|
for (PBVHNode *node : nodes.slice(range)) {
|
||||||
|
const Span<int> grids = BKE_pbvh_node_get_grid_indices(*node);
|
||||||
|
if (std::any_of(grids.begin(), grids.end(), [&](const int i) {
|
||||||
|
return bits::any_bit_set(grid_hidden[i]);
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
any_changed = true;
|
||||||
|
undo::push_node(&object, node, undo::Type::HideVert);
|
||||||
|
BKE_pbvh_node_mark_rebuild_draw(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!any_changed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (PBVHNode *node : nodes) {
|
||||||
|
BKE_pbvh_node_fully_hidden_set(node, false);
|
||||||
|
}
|
||||||
|
BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg);
|
||||||
|
BKE_pbvh_sync_visibility_from_verts(&pbvh, &mesh);
|
||||||
|
multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Internal Visibility Utilities
|
||||||
|
* Functions that assist with applying changes to the different PBVH types.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
enum class VisAction {
|
||||||
|
Hide = 0,
|
||||||
|
Show = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool action_to_hide(const VisAction action)
|
||||||
|
{
|
||||||
|
return action == VisAction::Hide;
|
||||||
|
}
|
||||||
|
|
||||||
static void vert_hide_update(Object &object,
|
static void vert_hide_update(Object &object,
|
||||||
const Span<PBVHNode *> nodes,
|
const Span<PBVHNode *> nodes,
|
||||||
const FunctionRef<void(Span<int>, MutableSpan<bool>)> calc_hide)
|
const FunctionRef<void(Span<int>, MutableSpan<bool>)> calc_hide)
|
||||||
@ -197,116 +235,6 @@ static void vert_hide_update(Object &object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void partialvis_all_update_mesh(Object &object,
|
|
||||||
const VisAction action,
|
|
||||||
const Span<PBVHNode *> nodes)
|
|
||||||
{
|
|
||||||
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
|
||||||
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
|
||||||
if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
|
|
||||||
/* If everything is already visible, don't do anything. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case VisAction::Hide:
|
|
||||||
vert_hide_update(object, nodes, [&](const Span<int> /*verts*/, MutableSpan<bool> hide) {
|
|
||||||
hide.fill(true);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case VisAction::Show:
|
|
||||||
mesh_show_all(object, nodes);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void partialvis_masked_update_mesh(Object &object,
|
|
||||||
const VisAction action,
|
|
||||||
const Span<PBVHNode *> nodes)
|
|
||||||
{
|
|
||||||
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
|
||||||
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
|
||||||
if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
|
|
||||||
/* If everything is already visible, don't do anything. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool value = action_to_hide(action);
|
|
||||||
const VArraySpan<float> mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
|
|
||||||
if (action == VisAction::Show && mask.is_empty()) {
|
|
||||||
mesh_show_all(object, nodes);
|
|
||||||
}
|
|
||||||
else if (!mask.is_empty()) {
|
|
||||||
vert_hide_update(object, nodes, [&](const Span<int> verts, MutableSpan<bool> hide) {
|
|
||||||
for (const int i : verts.index_range()) {
|
|
||||||
if (mask[verts[i]] > 0.5f) {
|
|
||||||
hide[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data)
|
|
||||||
{
|
|
||||||
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
|
||||||
Object *object = gesture_data.vc.obact;
|
|
||||||
const VisAction action = operation->action;
|
|
||||||
const Span<PBVHNode *> nodes = gesture_data.nodes;
|
|
||||||
|
|
||||||
PBVH *pbvh = object->sculpt->pbvh;
|
|
||||||
Mesh *mesh = static_cast<Mesh *>(object->data);
|
|
||||||
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
|
||||||
if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
|
|
||||||
/* If everything is already visible, don't do anything. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool value = action_to_hide(action);
|
|
||||||
const Span<float3> positions = BKE_pbvh_get_vert_positions(pbvh);
|
|
||||||
const Span<float3> normals = BKE_pbvh_get_vert_normals(pbvh);
|
|
||||||
vert_hide_update(*object, nodes, [&](const Span<int> verts, MutableSpan<bool> hide) {
|
|
||||||
for (const int i : verts.index_range()) {
|
|
||||||
if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) {
|
|
||||||
hide[i] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void grids_show_all(Depsgraph &depsgraph, Object &object, const Span<PBVHNode *> nodes)
|
|
||||||
{
|
|
||||||
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
|
||||||
PBVH &pbvh = *object.sculpt->pbvh;
|
|
||||||
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
|
|
||||||
const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
|
|
||||||
bool any_changed = false;
|
|
||||||
if (!grid_hidden.is_empty()) {
|
|
||||||
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
|
|
||||||
for (PBVHNode *node : nodes.slice(range)) {
|
|
||||||
const Span<int> grids = BKE_pbvh_node_get_grid_indices(*node);
|
|
||||||
if (std::any_of(grids.begin(), grids.end(), [&](const int i) {
|
|
||||||
return bits::any_bit_set(grid_hidden[i]);
|
|
||||||
}))
|
|
||||||
{
|
|
||||||
any_changed = true;
|
|
||||||
undo::push_node(&object, node, undo::Type::HideVert);
|
|
||||||
BKE_pbvh_node_mark_rebuild_draw(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!any_changed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (PBVHNode *node : nodes) {
|
|
||||||
BKE_pbvh_node_fully_hidden_set(node, false);
|
|
||||||
}
|
|
||||||
BKE_subdiv_ccg_grid_hidden_free(subdiv_ccg);
|
|
||||||
BKE_pbvh_sync_visibility_from_verts(&pbvh, &mesh);
|
|
||||||
multires_mark_as_modified(&depsgraph, &object, MULTIRES_HIDDEN_MODIFIED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void grid_hide_update(Depsgraph &depsgraph,
|
static void grid_hide_update(Depsgraph &depsgraph,
|
||||||
Object &object,
|
Object &object,
|
||||||
const Span<PBVHNode *> nodes,
|
const Span<PBVHNode *> nodes,
|
||||||
@ -355,86 +283,6 @@ static void grid_hide_update(Depsgraph &depsgraph,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void partialvis_all_update_grids(Depsgraph &depsgraph,
|
|
||||||
Object &object,
|
|
||||||
const VisAction action,
|
|
||||||
const Span<PBVHNode *> nodes)
|
|
||||||
{
|
|
||||||
switch (action) {
|
|
||||||
case VisAction::Hide:
|
|
||||||
grid_hide_update(depsgraph,
|
|
||||||
object,
|
|
||||||
nodes,
|
|
||||||
[&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(true); });
|
|
||||||
break;
|
|
||||||
case VisAction::Show:
|
|
||||||
grids_show_all(depsgraph, object, nodes);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void partialvis_masked_update_grids(Depsgraph &depsgraph,
|
|
||||||
Object &object,
|
|
||||||
const VisAction action,
|
|
||||||
const Span<PBVHNode *> nodes)
|
|
||||||
{
|
|
||||||
PBVH &pbvh = *object.sculpt->pbvh;
|
|
||||||
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
|
|
||||||
|
|
||||||
const bool value = action_to_hide(action);
|
|
||||||
const CCGKey key = *BKE_pbvh_get_grid_key(&pbvh);
|
|
||||||
const Span<CCGElem *> grids = subdiv_ccg.grids;
|
|
||||||
if (!key.has_mask) {
|
|
||||||
grid_hide_update(depsgraph,
|
|
||||||
object,
|
|
||||||
nodes,
|
|
||||||
[&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(value); });
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
grid_hide_update(
|
|
||||||
depsgraph, object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) {
|
|
||||||
CCGElem *grid = grids[grid_index];
|
|
||||||
for (const int y : IndexRange(key.grid_size)) {
|
|
||||||
for (const int x : IndexRange(key.grid_size)) {
|
|
||||||
CCGElem *elem = CCG_grid_elem(&key, grid, x, y);
|
|
||||||
if (*CCG_elem_mask(&key, elem) > 0.5f) {
|
|
||||||
hide[y * key.grid_size + x].set(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void partialvis_gesture_update_grids(Depsgraph &depsgraph,
|
|
||||||
gesture::GestureData &gesture_data)
|
|
||||||
{
|
|
||||||
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
|
||||||
Object *object = gesture_data.vc.obact;
|
|
||||||
const VisAction action = operation->action;
|
|
||||||
const Span<PBVHNode *> nodes = gesture_data.nodes;
|
|
||||||
|
|
||||||
PBVH *pbvh = object->sculpt->pbvh;
|
|
||||||
SubdivCCG *subdiv_ccg = object->sculpt->subdiv_ccg;
|
|
||||||
|
|
||||||
const bool value = action_to_hide(action);
|
|
||||||
const CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
|
|
||||||
const Span<CCGElem *> grids = subdiv_ccg->grids;
|
|
||||||
grid_hide_update(
|
|
||||||
depsgraph, *object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) {
|
|
||||||
CCGElem *grid = grids[grid_index];
|
|
||||||
for (const int y : IndexRange(key.grid_size)) {
|
|
||||||
for (const int x : IndexRange(key.grid_size)) {
|
|
||||||
CCGElem *elem = CCG_grid_elem(&key, grid, x, y);
|
|
||||||
if (gesture::is_affected(
|
|
||||||
gesture_data, CCG_elem_co(&key, elem), CCG_elem_no(&key, elem))) {
|
|
||||||
hide[y * key.grid_size + x].set(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static void partialvis_update_bmesh_verts(const Set<BMVert *, 0> &verts,
|
static void partialvis_update_bmesh_verts(const Set<BMVert *, 0> &verts,
|
||||||
const VisAction action,
|
const VisAction action,
|
||||||
const FunctionRef<bool(const BMVert *v)> should_update,
|
const FunctionRef<bool(const BMVert *v)> should_update,
|
||||||
@ -497,19 +345,52 @@ static void partialvis_update_bmesh_nodes(Object *ob,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void partialvis_masked_update_bmesh(Object *ob,
|
/** \} */
|
||||||
PBVH *pbvh,
|
|
||||||
const VisAction action,
|
|
||||||
const Span<PBVHNode *> nodes)
|
|
||||||
{
|
|
||||||
BMesh *bm = BKE_pbvh_get_bmesh(pbvh);
|
|
||||||
const int mask_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
|
|
||||||
const auto mask_test_fn = [&](const BMVert *v) {
|
|
||||||
const float vmask = BM_ELEM_CD_GET_FLOAT(v, mask_offset);
|
|
||||||
return vmask > 0.5f;
|
|
||||||
};
|
|
||||||
|
|
||||||
partialvis_update_bmesh_nodes(ob, nodes, action, mask_test_fn);
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Global Visibility Operators
|
||||||
|
* Operators that act upon the entirety of a given object's mesh.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
static void partialvis_all_update_mesh(Object &object,
|
||||||
|
const VisAction action,
|
||||||
|
const Span<PBVHNode *> nodes)
|
||||||
|
{
|
||||||
|
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
||||||
|
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
||||||
|
if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
|
||||||
|
/* If everything is already visible, don't do anything. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case VisAction::Hide:
|
||||||
|
vert_hide_update(object, nodes, [&](const Span<int> /*verts*/, MutableSpan<bool> hide) {
|
||||||
|
hide.fill(true);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case VisAction::Show:
|
||||||
|
mesh_show_all(object, nodes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void partialvis_all_update_grids(Depsgraph &depsgraph,
|
||||||
|
Object &object,
|
||||||
|
const VisAction action,
|
||||||
|
const Span<PBVHNode *> nodes)
|
||||||
|
{
|
||||||
|
switch (action) {
|
||||||
|
case VisAction::Hide:
|
||||||
|
grid_hide_update(depsgraph,
|
||||||
|
object,
|
||||||
|
nodes,
|
||||||
|
[&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(true); });
|
||||||
|
break;
|
||||||
|
case VisAction::Show:
|
||||||
|
grids_show_all(depsgraph, object, nodes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void partialvis_all_update_bmesh(Object *ob,
|
static void partialvis_all_update_bmesh(Object *ob,
|
||||||
@ -519,65 +400,6 @@ static void partialvis_all_update_bmesh(Object *ob,
|
|||||||
partialvis_update_bmesh_nodes(ob, nodes, action, [](const BMVert * /*vert*/) { return true; });
|
partialvis_update_bmesh_nodes(ob, nodes, action, [](const BMVert * /*vert*/) { return true; });
|
||||||
}
|
}
|
||||||
|
|
||||||
static void partialvis_gesture_update_bmesh(gesture::GestureData &gesture_data)
|
|
||||||
{
|
|
||||||
const auto selection_test_fn = [&](const BMVert *v) {
|
|
||||||
return gesture::is_affected(gesture_data, v->co, v->no);
|
|
||||||
};
|
|
||||||
|
|
||||||
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
|
||||||
|
|
||||||
partialvis_update_bmesh_nodes(
|
|
||||||
gesture_data.vc.obact, gesture_data.nodes, operation->action, selection_test_fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hide_show_begin(bContext &C, gesture::GestureData & /*gesture_data*/)
|
|
||||||
{
|
|
||||||
Object *ob = CTX_data_active_object(&C);
|
|
||||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(&C);
|
|
||||||
|
|
||||||
BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hide_show_apply_for_symmetry_pass(bContext &C, gesture::GestureData &gesture_data)
|
|
||||||
{
|
|
||||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
|
|
||||||
|
|
||||||
switch (BKE_pbvh_type(gesture_data.ss->pbvh)) {
|
|
||||||
case PBVH_FACES:
|
|
||||||
partialvis_gesture_update_mesh(gesture_data);
|
|
||||||
break;
|
|
||||||
case PBVH_GRIDS:
|
|
||||||
partialvis_gesture_update_grids(*depsgraph, gesture_data);
|
|
||||||
break;
|
|
||||||
case PBVH_BMESH:
|
|
||||||
partialvis_gesture_update_bmesh(gesture_data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static void hide_show_end(bContext &C, gesture::GestureData &gesture_data)
|
|
||||||
{
|
|
||||||
SCULPT_topology_islands_invalidate(gesture_data.vc.obact->sculpt);
|
|
||||||
tag_update_visibility(C);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hide_show_init_properties(bContext & /*C*/,
|
|
||||||
gesture::GestureData &gesture_data,
|
|
||||||
wmOperator &op)
|
|
||||||
{
|
|
||||||
gesture_data.operation = reinterpret_cast<gesture::Operation *>(
|
|
||||||
MEM_cnew<HideShowOperation>(__func__));
|
|
||||||
|
|
||||||
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
|
||||||
|
|
||||||
operation->op.begin = hide_show_begin;
|
|
||||||
operation->op.apply_for_symmetry_pass = hide_show_apply_for_symmetry_pass;
|
|
||||||
operation->op.end = hide_show_end;
|
|
||||||
|
|
||||||
operation->action = VisAction(RNA_enum_get(op.ptr, "action"));
|
|
||||||
gesture_data.selection_type = gesture::SelectionType(RNA_enum_get(op.ptr, "area"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hide_show_all_exec(bContext *C, wmOperator *op)
|
static int hide_show_all_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *ob = CTX_data_active_object(C);
|
Object *ob = CTX_data_active_object(C);
|
||||||
@ -621,6 +443,81 @@ static int hide_show_all_exec(bContext *C, wmOperator *op)
|
|||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void partialvis_masked_update_mesh(Object &object,
|
||||||
|
const VisAction action,
|
||||||
|
const Span<PBVHNode *> nodes)
|
||||||
|
{
|
||||||
|
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
||||||
|
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
||||||
|
if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
|
||||||
|
/* If everything is already visible, don't do anything. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool value = action_to_hide(action);
|
||||||
|
const VArraySpan<float> mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
|
||||||
|
if (action == VisAction::Show && mask.is_empty()) {
|
||||||
|
mesh_show_all(object, nodes);
|
||||||
|
}
|
||||||
|
else if (!mask.is_empty()) {
|
||||||
|
vert_hide_update(object, nodes, [&](const Span<int> verts, MutableSpan<bool> hide) {
|
||||||
|
for (const int i : verts.index_range()) {
|
||||||
|
if (mask[verts[i]] > 0.5f) {
|
||||||
|
hide[i] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void partialvis_masked_update_grids(Depsgraph &depsgraph,
|
||||||
|
Object &object,
|
||||||
|
const VisAction action,
|
||||||
|
const Span<PBVHNode *> nodes)
|
||||||
|
{
|
||||||
|
PBVH &pbvh = *object.sculpt->pbvh;
|
||||||
|
SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
|
||||||
|
|
||||||
|
const bool value = action_to_hide(action);
|
||||||
|
const CCGKey key = *BKE_pbvh_get_grid_key(&pbvh);
|
||||||
|
const Span<CCGElem *> grids = subdiv_ccg.grids;
|
||||||
|
if (!key.has_mask) {
|
||||||
|
grid_hide_update(depsgraph,
|
||||||
|
object,
|
||||||
|
nodes,
|
||||||
|
[&](const int /*verts*/, MutableBoundedBitSpan hide) { hide.fill(value); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
grid_hide_update(
|
||||||
|
depsgraph, object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) {
|
||||||
|
CCGElem *grid = grids[grid_index];
|
||||||
|
for (const int y : IndexRange(key.grid_size)) {
|
||||||
|
for (const int x : IndexRange(key.grid_size)) {
|
||||||
|
CCGElem *elem = CCG_grid_elem(&key, grid, x, y);
|
||||||
|
if (*CCG_elem_mask(&key, elem) > 0.5f) {
|
||||||
|
hide[y * key.grid_size + x].set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void partialvis_masked_update_bmesh(Object *ob,
|
||||||
|
PBVH *pbvh,
|
||||||
|
const VisAction action,
|
||||||
|
const Span<PBVHNode *> nodes)
|
||||||
|
{
|
||||||
|
BMesh *bm = BKE_pbvh_get_bmesh(pbvh);
|
||||||
|
const int mask_offset = CustomData_get_offset_named(&bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
|
||||||
|
const auto mask_test_fn = [&](const BMVert *v) {
|
||||||
|
const float vmask = BM_ELEM_CD_GET_FLOAT(v, mask_offset);
|
||||||
|
return vmask > 0.5f;
|
||||||
|
};
|
||||||
|
|
||||||
|
partialvis_update_bmesh_nodes(ob, nodes, action, mask_test_fn);
|
||||||
|
}
|
||||||
|
|
||||||
static int hide_show_masked_exec(bContext *C, wmOperator *op)
|
static int hide_show_masked_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *ob = CTX_data_active_object(C);
|
Object *ob = CTX_data_active_object(C);
|
||||||
@ -664,28 +561,6 @@ static int hide_show_masked_exec(bContext *C, wmOperator *op)
|
|||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hide_show_gesture_box_exec(bContext *C, wmOperator *op)
|
|
||||||
{
|
|
||||||
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_box(C, op);
|
|
||||||
if (!gesture_data) {
|
|
||||||
return OPERATOR_CANCELLED;
|
|
||||||
}
|
|
||||||
hide_show_init_properties(*C, *gesture_data, *op);
|
|
||||||
gesture::apply(*C, *gesture_data, *op);
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hide_show_gesture_lasso_exec(bContext *C, wmOperator *op)
|
|
||||||
{
|
|
||||||
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_lasso(C, op);
|
|
||||||
if (!gesture_data) {
|
|
||||||
return OPERATOR_CANCELLED;
|
|
||||||
}
|
|
||||||
hide_show_init_properties(*C, *gesture_data, *op);
|
|
||||||
gesture::apply(*C, *gesture_data, *op);
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hide_show_operator_properties(wmOperatorType *ot)
|
static void hide_show_operator_properties(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
static const EnumPropertyItem action_items[] = {
|
static const EnumPropertyItem action_items[] = {
|
||||||
@ -702,30 +577,6 @@ static void hide_show_operator_properties(wmOperatorType *ot)
|
|||||||
"Whether to hide or show vertices");
|
"Whether to hide or show vertices");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hide_show_operator_gesture_properties(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
static const EnumPropertyItem area_items[] = {
|
|
||||||
{int(gesture::SelectionType::Outside),
|
|
||||||
"OUTSIDE",
|
|
||||||
0,
|
|
||||||
"Outside",
|
|
||||||
"Hide or show vertices outside the selection"},
|
|
||||||
{int(gesture::SelectionType::Inside),
|
|
||||||
"Inside",
|
|
||||||
0,
|
|
||||||
"Inside",
|
|
||||||
"Hide or show vertices inside the selection"},
|
|
||||||
{0, nullptr, 0, nullptr, nullptr},
|
|
||||||
};
|
|
||||||
|
|
||||||
RNA_def_enum(ot->srna,
|
|
||||||
"area",
|
|
||||||
area_items,
|
|
||||||
int(gesture::SelectionType::Inside),
|
|
||||||
"Visibility Area",
|
|
||||||
"Which vertices to hide or show");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PAINT_OT_hide_show_masked(wmOperatorType *ot)
|
void PAINT_OT_hide_show_masked(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
ot->name = "Hide/Show Masked";
|
ot->name = "Hide/Show Masked";
|
||||||
@ -756,46 +607,6 @@ void PAINT_OT_hide_show_all(wmOperatorType *ot)
|
|||||||
hide_show_operator_properties(ot);
|
hide_show_operator_properties(ot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PAINT_OT_hide_show(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
ot->name = "Hide/Show";
|
|
||||||
ot->idname = "PAINT_OT_hide_show";
|
|
||||||
ot->description = "Hide/show some vertices";
|
|
||||||
|
|
||||||
ot->invoke = WM_gesture_box_invoke;
|
|
||||||
ot->modal = WM_gesture_box_modal;
|
|
||||||
ot->exec = hide_show_gesture_box_exec;
|
|
||||||
/* Sculpt-only for now. */
|
|
||||||
ot->poll = SCULPT_mode_poll_view3d;
|
|
||||||
|
|
||||||
ot->flag = OPTYPE_REGISTER;
|
|
||||||
|
|
||||||
WM_operator_properties_border(ot);
|
|
||||||
hide_show_operator_properties(ot);
|
|
||||||
hide_show_operator_gesture_properties(ot);
|
|
||||||
gesture::operator_properties(ot, gesture::ShapeType::Box);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PAINT_OT_hide_show_lasso_gesture(wmOperatorType *ot)
|
|
||||||
{
|
|
||||||
ot->name = "Hide/Show Lasso";
|
|
||||||
ot->idname = "PAINT_OT_hide_show_lasso_gesture";
|
|
||||||
ot->description = "Hide/show some vertices";
|
|
||||||
|
|
||||||
ot->invoke = WM_gesture_lasso_invoke;
|
|
||||||
ot->modal = WM_gesture_lasso_modal;
|
|
||||||
ot->exec = hide_show_gesture_lasso_exec;
|
|
||||||
/* Sculpt-only for now. */
|
|
||||||
ot->poll = SCULPT_mode_poll_view3d;
|
|
||||||
|
|
||||||
ot->flag = OPTYPE_REGISTER | OPTYPE_DEPENDS_ON_CURSOR;
|
|
||||||
|
|
||||||
WM_operator_properties_gesture_lasso(ot);
|
|
||||||
hide_show_operator_properties(ot);
|
|
||||||
hide_show_operator_gesture_properties(ot);
|
|
||||||
gesture::operator_properties(ot, gesture::ShapeType::Lasso);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void invert_visibility_mesh(Object &object, const Span<PBVHNode *> nodes)
|
static void invert_visibility_mesh(Object &object, const Span<PBVHNode *> nodes)
|
||||||
{
|
{
|
||||||
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
||||||
@ -906,4 +717,220 @@ void PAINT_OT_visibility_invert(wmOperatorType *ot)
|
|||||||
ot->flag = OPTYPE_REGISTER;
|
ot->flag = OPTYPE_REGISTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
/** \name Gesture-based Visibility Operators
|
||||||
|
* Operators that act upon a user-selected area.
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
struct HideShowOperation {
|
||||||
|
gesture::Operation op;
|
||||||
|
|
||||||
|
VisAction action;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void partialvis_gesture_update_mesh(gesture::GestureData &gesture_data)
|
||||||
|
{
|
||||||
|
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
||||||
|
Object *object = gesture_data.vc.obact;
|
||||||
|
const VisAction action = operation->action;
|
||||||
|
const Span<PBVHNode *> nodes = gesture_data.nodes;
|
||||||
|
|
||||||
|
PBVH *pbvh = object->sculpt->pbvh;
|
||||||
|
Mesh *mesh = static_cast<Mesh *>(object->data);
|
||||||
|
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
|
||||||
|
if (action == VisAction::Show && !attributes.contains(".hide_vert")) {
|
||||||
|
/* If everything is already visible, don't do anything. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool value = action_to_hide(action);
|
||||||
|
const Span<float3> positions = BKE_pbvh_get_vert_positions(pbvh);
|
||||||
|
const Span<float3> normals = BKE_pbvh_get_vert_normals(pbvh);
|
||||||
|
vert_hide_update(*object, nodes, [&](const Span<int> verts, MutableSpan<bool> hide) {
|
||||||
|
for (const int i : verts.index_range()) {
|
||||||
|
if (gesture::is_affected(gesture_data, positions[verts[i]], normals[verts[i]])) {
|
||||||
|
hide[i] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void partialvis_gesture_update_grids(Depsgraph &depsgraph,
|
||||||
|
gesture::GestureData &gesture_data)
|
||||||
|
{
|
||||||
|
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
||||||
|
Object *object = gesture_data.vc.obact;
|
||||||
|
const VisAction action = operation->action;
|
||||||
|
const Span<PBVHNode *> nodes = gesture_data.nodes;
|
||||||
|
|
||||||
|
PBVH *pbvh = object->sculpt->pbvh;
|
||||||
|
SubdivCCG *subdiv_ccg = object->sculpt->subdiv_ccg;
|
||||||
|
|
||||||
|
const bool value = action_to_hide(action);
|
||||||
|
const CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
|
||||||
|
const Span<CCGElem *> grids = subdiv_ccg->grids;
|
||||||
|
grid_hide_update(
|
||||||
|
depsgraph, *object, nodes, [&](const int grid_index, MutableBoundedBitSpan hide) {
|
||||||
|
CCGElem *grid = grids[grid_index];
|
||||||
|
for (const int y : IndexRange(key.grid_size)) {
|
||||||
|
for (const int x : IndexRange(key.grid_size)) {
|
||||||
|
CCGElem *elem = CCG_grid_elem(&key, grid, x, y);
|
||||||
|
if (gesture::is_affected(
|
||||||
|
gesture_data, CCG_elem_co(&key, elem), CCG_elem_no(&key, elem))) {
|
||||||
|
hide[y * key.grid_size + x].set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void partialvis_gesture_update_bmesh(gesture::GestureData &gesture_data)
|
||||||
|
{
|
||||||
|
const auto selection_test_fn = [&](const BMVert *v) {
|
||||||
|
return gesture::is_affected(gesture_data, v->co, v->no);
|
||||||
|
};
|
||||||
|
|
||||||
|
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
||||||
|
|
||||||
|
partialvis_update_bmesh_nodes(
|
||||||
|
gesture_data.vc.obact, gesture_data.nodes, operation->action, selection_test_fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hide_show_begin(bContext &C, gesture::GestureData & /*gesture_data*/)
|
||||||
|
{
|
||||||
|
Object *ob = CTX_data_active_object(&C);
|
||||||
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(&C);
|
||||||
|
|
||||||
|
BKE_sculpt_object_pbvh_ensure(depsgraph, ob);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hide_show_apply_for_symmetry_pass(bContext &C, gesture::GestureData &gesture_data)
|
||||||
|
{
|
||||||
|
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
|
||||||
|
|
||||||
|
switch (BKE_pbvh_type(gesture_data.ss->pbvh)) {
|
||||||
|
case PBVH_FACES:
|
||||||
|
partialvis_gesture_update_mesh(gesture_data);
|
||||||
|
break;
|
||||||
|
case PBVH_GRIDS:
|
||||||
|
partialvis_gesture_update_grids(*depsgraph, gesture_data);
|
||||||
|
break;
|
||||||
|
case PBVH_BMESH:
|
||||||
|
partialvis_gesture_update_bmesh(gesture_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void hide_show_end(bContext &C, gesture::GestureData &gesture_data)
|
||||||
|
{
|
||||||
|
SCULPT_topology_islands_invalidate(gesture_data.vc.obact->sculpt);
|
||||||
|
tag_update_visibility(C);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hide_show_init_properties(bContext & /*C*/,
|
||||||
|
gesture::GestureData &gesture_data,
|
||||||
|
wmOperator &op)
|
||||||
|
{
|
||||||
|
gesture_data.operation = reinterpret_cast<gesture::Operation *>(
|
||||||
|
MEM_cnew<HideShowOperation>(__func__));
|
||||||
|
|
||||||
|
HideShowOperation *operation = reinterpret_cast<HideShowOperation *>(gesture_data.operation);
|
||||||
|
|
||||||
|
operation->op.begin = hide_show_begin;
|
||||||
|
operation->op.apply_for_symmetry_pass = hide_show_apply_for_symmetry_pass;
|
||||||
|
operation->op.end = hide_show_end;
|
||||||
|
|
||||||
|
operation->action = VisAction(RNA_enum_get(op.ptr, "action"));
|
||||||
|
gesture_data.selection_type = gesture::SelectionType(RNA_enum_get(op.ptr, "area"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hide_show_gesture_box_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_box(C, op);
|
||||||
|
if (!gesture_data) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
hide_show_init_properties(*C, *gesture_data, *op);
|
||||||
|
gesture::apply(*C, *gesture_data, *op);
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hide_show_gesture_lasso_exec(bContext *C, wmOperator *op)
|
||||||
|
{
|
||||||
|
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_lasso(C, op);
|
||||||
|
if (!gesture_data) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
hide_show_init_properties(*C, *gesture_data, *op);
|
||||||
|
gesture::apply(*C, *gesture_data, *op);
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hide_show_operator_gesture_properties(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
static const EnumPropertyItem area_items[] = {
|
||||||
|
{int(gesture::SelectionType::Outside),
|
||||||
|
"OUTSIDE",
|
||||||
|
0,
|
||||||
|
"Outside",
|
||||||
|
"Hide or show vertices outside the selection"},
|
||||||
|
{int(gesture::SelectionType::Inside),
|
||||||
|
"Inside",
|
||||||
|
0,
|
||||||
|
"Inside",
|
||||||
|
"Hide or show vertices inside the selection"},
|
||||||
|
{0, nullptr, 0, nullptr, nullptr},
|
||||||
|
};
|
||||||
|
|
||||||
|
RNA_def_enum(ot->srna,
|
||||||
|
"area",
|
||||||
|
area_items,
|
||||||
|
int(gesture::SelectionType::Inside),
|
||||||
|
"Visibility Area",
|
||||||
|
"Which vertices to hide or show");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PAINT_OT_hide_show(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Hide/Show";
|
||||||
|
ot->idname = "PAINT_OT_hide_show";
|
||||||
|
ot->description = "Hide/show some vertices";
|
||||||
|
|
||||||
|
ot->invoke = WM_gesture_box_invoke;
|
||||||
|
ot->modal = WM_gesture_box_modal;
|
||||||
|
ot->exec = hide_show_gesture_box_exec;
|
||||||
|
/* Sculpt-only for now. */
|
||||||
|
ot->poll = SCULPT_mode_poll_view3d;
|
||||||
|
|
||||||
|
ot->flag = OPTYPE_REGISTER;
|
||||||
|
|
||||||
|
WM_operator_properties_border(ot);
|
||||||
|
hide_show_operator_properties(ot);
|
||||||
|
hide_show_operator_gesture_properties(ot);
|
||||||
|
gesture::operator_properties(ot, gesture::ShapeType::Box);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PAINT_OT_hide_show_lasso_gesture(wmOperatorType *ot)
|
||||||
|
{
|
||||||
|
ot->name = "Hide/Show Lasso";
|
||||||
|
ot->idname = "PAINT_OT_hide_show_lasso_gesture";
|
||||||
|
ot->description = "Hide/show some vertices";
|
||||||
|
|
||||||
|
ot->invoke = WM_gesture_lasso_invoke;
|
||||||
|
ot->modal = WM_gesture_lasso_modal;
|
||||||
|
ot->exec = hide_show_gesture_lasso_exec;
|
||||||
|
/* Sculpt-only for now. */
|
||||||
|
ot->poll = SCULPT_mode_poll_view3d;
|
||||||
|
|
||||||
|
ot->flag = OPTYPE_REGISTER | OPTYPE_DEPENDS_ON_CURSOR;
|
||||||
|
|
||||||
|
WM_operator_properties_gesture_lasso(ot);
|
||||||
|
hide_show_operator_properties(ot);
|
||||||
|
hide_show_operator_gesture_properties(ot);
|
||||||
|
gesture::operator_properties(ot, gesture::ShapeType::Lasso);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
} // namespace blender::ed::sculpt_paint::hide
|
} // namespace blender::ed::sculpt_paint::hide
|
||||||
|
Loading…
Reference in New Issue
Block a user