Refactor: Sculpt: Make sculpt undo node definition private
This allows more flexibility about how we store undo data. Potentially we wouldn't need to store everything segmented per-node if we didn't expose the `undo::Node` struct. Part of #118145. Pull Request: https://projects.blender.org/blender/blender/pulls/127116
This commit is contained in:
@@ -929,6 +929,17 @@ const float *BM_log_find_original_vert_co(BMLog *log, BMVert *v)
|
|||||||
return lv == nullptr ? nullptr : lv->co;
|
return lv == nullptr ? nullptr : lv->co;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const float *BM_log_find_original_vert_mask(BMLog *log, BMVert *v)
|
||||||
|
{
|
||||||
|
BMLogEntry *entry = log->current_entry;
|
||||||
|
const BMLogVert *lv;
|
||||||
|
uint v_id = bm_log_vert_id_get(log, v);
|
||||||
|
void *key = POINTER_FROM_UINT(v_id);
|
||||||
|
|
||||||
|
lv = static_cast<const BMLogVert *>(BLI_ghash_lookup(entry->modified_verts, key));
|
||||||
|
return lv == nullptr ? nullptr : &lv->mask;
|
||||||
|
}
|
||||||
|
|
||||||
const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
|
const float *BM_log_original_vert_co(BMLog *log, BMVert *v)
|
||||||
{
|
{
|
||||||
BMLogEntry *entry = log->current_entry;
|
BMLogEntry *entry = log->current_entry;
|
||||||
|
|||||||
@@ -189,6 +189,15 @@ void BM_log_before_all_removed(BMesh *bm, BMLog *log);
|
|||||||
*/
|
*/
|
||||||
const float *BM_log_find_original_vert_co(BMLog *log, BMVert *v);
|
const float *BM_log_find_original_vert_co(BMLog *log, BMVert *v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search the log for the original vertex mask.
|
||||||
|
*
|
||||||
|
* Does not modify the log or the vertex.
|
||||||
|
*
|
||||||
|
* \return the pointer or nullptr if the vertex isn't found.
|
||||||
|
*/
|
||||||
|
const float *BM_log_find_original_vert_mask(BMLog *log, BMVert *v);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the logged coordinates of a vertex.
|
* Get the logged coordinates of a vertex.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1180,9 +1180,11 @@ static void restore_mask_from_undo_step(Object &object)
|
|||||||
bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
|
bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
|
||||||
".sculpt_mask", bke::AttrDomain::Point);
|
".sculpt_mask", bke::AttrDomain::Point);
|
||||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||||
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Mask)) {
|
if (const std::optional<Span<float>> orig_data = orig_mask_data_lookup_mesh(object,
|
||||||
|
nodes[i]))
|
||||||
|
{
|
||||||
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
|
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
|
||||||
array_utils::scatter(unode->mask.as_span(), verts, mask.span);
|
array_utils::scatter(*orig_data, verts, mask.span);
|
||||||
BKE_pbvh_node_mark_update_mask(nodes[i]);
|
BKE_pbvh_node_mark_update_mask(nodes[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1193,13 +1195,12 @@ static void restore_mask_from_undo_step(Object &object)
|
|||||||
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
|
MutableSpan<bke::pbvh::BMeshNode> nodes = ss.pbvh->nodes<bke::pbvh::BMeshNode>();
|
||||||
const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
|
const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
|
||||||
if (offset != -1) {
|
if (offset != -1) {
|
||||||
node_mask.foreach_index([&](const int i) {
|
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||||
if (undo::get_node(&nodes[i], undo::Type::Mask)) {
|
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
|
||||||
for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
|
if (const float *orig_mask = BM_log_find_original_vert_mask(ss.bm_log, vert)) {
|
||||||
const float orig_mask = BM_log_original_mask(ss.bm_log, vert);
|
BM_ELEM_CD_SET_FLOAT(vert, offset, *orig_mask);
|
||||||
BM_ELEM_CD_SET_FLOAT(vert, offset, orig_mask);
|
BKE_pbvh_node_mark_update_mask(nodes[i]);
|
||||||
}
|
}
|
||||||
BKE_pbvh_node_mark_update_mask(nodes[i]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1212,13 +1213,15 @@ static void restore_mask_from_undo_step(Object &object)
|
|||||||
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
|
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
|
||||||
const Span<CCGElem *> grids = subdiv_ccg.grids;
|
const Span<CCGElem *> grids = subdiv_ccg.grids;
|
||||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||||
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Mask)) {
|
if (const std::optional<Span<float>> orig_data = orig_mask_data_lookup_grids(object,
|
||||||
|
nodes[i]))
|
||||||
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (const int grid : unode->grids) {
|
for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) {
|
||||||
CCGElem *elem = grids[grid];
|
CCGElem *elem = grids[grid];
|
||||||
for (const int i : IndexRange(key.grid_area)) {
|
for (const int i : IndexRange(key.grid_area)) {
|
||||||
if (grid_hidden.is_empty() || !grid_hidden[grid][i]) {
|
if (grid_hidden.is_empty() || !grid_hidden[grid][i]) {
|
||||||
CCG_elem_offset_mask(key, elem, i) = unode->mask[index];
|
CCG_elem_offset_mask(key, elem, i) = (*orig_data)[index];
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -1245,7 +1248,9 @@ static void restore_color_from_undo_step(Object &object)
|
|||||||
const GroupedSpan<int> vert_to_face_map = ss.vert_to_face_map;
|
const GroupedSpan<int> vert_to_face_map = ss.vert_to_face_map;
|
||||||
bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh);
|
bke::GSpanAttributeWriter color_attribute = color::active_color_attribute_for_write(mesh);
|
||||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||||
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Color)) {
|
if (const std::optional<Span<float4>> orig_data = orig_color_data_lookup_mesh(object,
|
||||||
|
nodes[i]))
|
||||||
|
{
|
||||||
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
|
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
|
||||||
for (const int i : verts.index_range()) {
|
for (const int i : verts.index_range()) {
|
||||||
color::color_vert_set(faces,
|
color::color_vert_set(faces,
|
||||||
@@ -1253,7 +1258,7 @@ static void restore_color_from_undo_step(Object &object)
|
|||||||
vert_to_face_map,
|
vert_to_face_map,
|
||||||
color_attribute.domain,
|
color_attribute.domain,
|
||||||
verts[i],
|
verts[i],
|
||||||
unode->col[i],
|
(*orig_data)[i],
|
||||||
color_attribute.span);
|
color_attribute.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1269,13 +1274,18 @@ static void restore_face_set_from_undo_step(Object &object)
|
|||||||
|
|
||||||
switch (ss.pbvh->type()) {
|
switch (ss.pbvh->type()) {
|
||||||
case bke::pbvh::Type::Mesh: {
|
case bke::pbvh::Type::Mesh: {
|
||||||
|
const Mesh &mesh = *static_cast<const Mesh *>(object.data);
|
||||||
|
const Span<int> tri_faces = mesh.corner_tri_faces();
|
||||||
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
|
MutableSpan<bke::pbvh::MeshNode> nodes = ss.pbvh->nodes<bke::pbvh::MeshNode>();
|
||||||
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
|
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
|
||||||
|
threading::EnumerableThreadSpecific<Vector<int>> all_tls;
|
||||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||||
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::FaceSet)) {
|
Vector<int> &tls = all_tls.local();
|
||||||
const Span<int> faces = unode->face_indices;
|
if (const std::optional<Span<int>> orig_data = orig_face_set_data_lookup_mesh(object,
|
||||||
const Span<int> face_sets = unode->face_sets;
|
nodes[i]))
|
||||||
blender::array_utils::scatter(face_sets, faces, attribute.span);
|
{
|
||||||
|
const Span<int> faces = bke::pbvh::node_face_indices_calc_mesh(tri_faces, nodes[i], tls);
|
||||||
|
scatter_data_mesh(*orig_data, faces, attribute.span);
|
||||||
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
|
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1283,13 +1293,18 @@ static void restore_face_set_from_undo_step(Object &object)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case bke::pbvh::Type::Grids: {
|
case bke::pbvh::Type::Grids: {
|
||||||
|
const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
|
||||||
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
|
MutableSpan<bke::pbvh::GridsNode> nodes = ss.pbvh->nodes<bke::pbvh::GridsNode>();
|
||||||
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
|
bke::SpanAttributeWriter<int> attribute = face_set::ensure_face_sets_mesh(object);
|
||||||
|
threading::EnumerableThreadSpecific<Vector<int>> all_tls;
|
||||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||||
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::FaceSet)) {
|
Vector<int> &tls = all_tls.local();
|
||||||
const Span<int> faces = unode->face_indices;
|
if (const std::optional<Span<int>> orig_data = orig_face_set_data_lookup_grids(object,
|
||||||
const Span<int> face_sets = unode->face_sets;
|
nodes[i]))
|
||||||
blender::array_utils::scatter(face_sets, faces, attribute.span);
|
{
|
||||||
|
const Span<int> faces = bke::pbvh::node_face_indices_calc_grids(
|
||||||
|
subdiv_ccg, nodes[i], tls);
|
||||||
|
scatter_data_mesh(*orig_data, faces, attribute.span);
|
||||||
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
|
BKE_pbvh_node_mark_update_face_sets(nodes[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1325,9 +1340,11 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
|
|||||||
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
|
threading::parallel_for(node_mask.index_range(), 1, [&](const IndexRange range) {
|
||||||
LocalData &tls = all_tls.local();
|
LocalData &tls = all_tls.local();
|
||||||
node_mask.slice(range).foreach_index([&](const int i) {
|
node_mask.slice(range).foreach_index([&](const int i) {
|
||||||
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Position)) {
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_mesh(
|
||||||
|
object, nodes[i]))
|
||||||
|
{
|
||||||
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
|
const Span<int> verts = bke::pbvh::node_unique_verts(nodes[i]);
|
||||||
const Span<float3> undo_positions = unode->position.as_span().take_front(verts.size());
|
const Span<float3> undo_positions = orig_data->positions;
|
||||||
if (need_translations) {
|
if (need_translations) {
|
||||||
tls.translations.resize(verts.size());
|
tls.translations.resize(verts.size());
|
||||||
translations_from_new_positions(
|
translations_from_new_positions(
|
||||||
@@ -1388,13 +1405,15 @@ void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
|
|||||||
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
|
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
|
||||||
const Span<CCGElem *> grids = subdiv_ccg.grids;
|
const Span<CCGElem *> grids = subdiv_ccg.grids;
|
||||||
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
node_mask.foreach_index(GrainSize(1), [&](const int i) {
|
||||||
if (const undo::Node *unode = undo::get_node(&nodes[i], undo::Type::Position)) {
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(
|
||||||
|
object, nodes[i]))
|
||||||
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (const int grid : unode->grids) {
|
for (const int grid : bke::pbvh::node_grid_indices(nodes[i])) {
|
||||||
CCGElem *elem = grids[grid];
|
CCGElem *elem = grids[grid];
|
||||||
for (const int i : IndexRange(key.grid_area)) {
|
for (const int i : IndexRange(key.grid_area)) {
|
||||||
if (grid_hidden.is_empty() || !grid_hidden[grid][i]) {
|
if (grid_hidden.is_empty() || !grid_hidden[grid][i]) {
|
||||||
CCG_elem_offset_co(key, elem, i) = unode->position[index];
|
CCG_elem_offset_co(key, elem, i) = orig_data->positions[index];
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -1693,9 +1712,11 @@ static void calc_area_normal_and_center_node_mesh(const Object &object,
|
|||||||
const Span<int> verts = bke::pbvh::node_unique_verts(node);
|
const Span<int> verts = bke::pbvh::node_unique_verts(node);
|
||||||
|
|
||||||
if (ss.cache && !ss.cache->accum) {
|
if (ss.cache && !ss.cache->accum) {
|
||||||
if (const undo::Node *unode = undo::get_node(&node, undo::Type::Position)) {
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_get_mesh(object,
|
||||||
const Span<float3> orig_positions = unode->position.as_span().take_front(verts.size());
|
node))
|
||||||
const Span<float3> orig_normals = unode->normal.as_span().take_front(verts.size());
|
{
|
||||||
|
const Span<float3> orig_positions = orig_data->positions;
|
||||||
|
const Span<float3> orig_normals = orig_data->normals;
|
||||||
|
|
||||||
tls.distances.reinitialize(verts.size());
|
tls.distances.reinitialize(verts.size());
|
||||||
const MutableSpan<float> distances_sq = tls.distances;
|
const MutableSpan<float> distances_sq = tls.distances;
|
||||||
@@ -1780,9 +1801,11 @@ static void calc_area_normal_and_center_node_grids(const Object &object,
|
|||||||
const Span<int> grids = bke::pbvh::node_grid_indices(node);
|
const Span<int> grids = bke::pbvh::node_grid_indices(node);
|
||||||
|
|
||||||
if (ss.cache && !ss.cache->accum) {
|
if (ss.cache && !ss.cache->accum) {
|
||||||
if (const undo::Node *unode = undo::get_node(&node, undo::Type::Position)) {
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_get_grids(object,
|
||||||
const Span<float3> orig_positions = unode->position.as_span();
|
node))
|
||||||
const Span<float3> orig_normals = unode->normal.as_span();
|
{
|
||||||
|
const Span<float3> orig_positions = orig_data->positions;
|
||||||
|
const Span<float3> orig_normals = orig_data->normals;
|
||||||
|
|
||||||
tls.distances.reinitialize(orig_positions.size());
|
tls.distances.reinitialize(orig_positions.size());
|
||||||
const MutableSpan<float> distances_sq = tls.distances;
|
const MutableSpan<float> distances_sq = tls.distances;
|
||||||
@@ -1877,13 +1900,9 @@ static void calc_area_normal_and_center_node_bmesh(const Object &object,
|
|||||||
const float normal_radius_sq = normal_radius * normal_radius;
|
const float normal_radius_sq = normal_radius * normal_radius;
|
||||||
const float normal_radius_inv = math::rcp(normal_radius);
|
const float normal_radius_inv = math::rcp(normal_radius);
|
||||||
|
|
||||||
const undo::Node *unode = nullptr;
|
|
||||||
bool use_original = false;
|
bool use_original = false;
|
||||||
if (ss.cache && !ss.cache->accum) {
|
if (ss.cache && !ss.cache->accum) {
|
||||||
unode = undo::get_node(&node, undo::Type::Position);
|
use_original = undo::get_bmesh_log_entry() != nullptr;
|
||||||
if (unode) {
|
|
||||||
use_original = undo::get_bmesh_log_entry() != nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the mesh is edited we can't rely on original coords
|
/* When the mesh is edited we can't rely on original coords
|
||||||
@@ -2904,6 +2923,7 @@ static void sculpt_pbvh_update_pixels(const Depsgraph &depsgraph,
|
|||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
struct SculptRaycastData {
|
struct SculptRaycastData {
|
||||||
|
const Object *object;
|
||||||
SculptSession *ss;
|
SculptSession *ss;
|
||||||
const float *ray_start;
|
const float *ray_start;
|
||||||
const float *ray_normal;
|
const float *ray_normal;
|
||||||
@@ -2927,6 +2947,7 @@ struct SculptRaycastData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct SculptFindNearestToRayData {
|
struct SculptFindNearestToRayData {
|
||||||
|
const Object *object;
|
||||||
SculptSession *ss;
|
SculptSession *ss;
|
||||||
const float *ray_start, *ray_normal;
|
const float *ray_start, *ray_normal;
|
||||||
bool hit;
|
bool hit;
|
||||||
@@ -4761,18 +4782,30 @@ static void sculpt_raycast_cb(blender::bke::pbvh::Node &node, SculptRaycastData
|
|||||||
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
|
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_origco = false;
|
bool use_origco = false;
|
||||||
Span<float3> origco;
|
Span<float3> origco;
|
||||||
if (srd.original && srd.ss->cache) {
|
if (srd.original && srd.ss->cache) {
|
||||||
if (srd.ss->pbvh->type() == bke::pbvh::Type::BMesh) {
|
switch (srd.ss->pbvh->type()) {
|
||||||
use_origco = true;
|
case bke::pbvh::Type::Mesh:
|
||||||
}
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_mesh(
|
||||||
else {
|
*srd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
|
||||||
/* Intersect with coordinates from before we started stroke. */
|
{
|
||||||
if (const undo::Node *unode = undo::get_node(&node, undo::Type::Position)) {
|
use_origco = true;
|
||||||
|
origco = orig_data->positions;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case bke::pbvh::Type::Grids:
|
||||||
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(
|
||||||
|
*srd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
|
||||||
|
{
|
||||||
|
use_origco = true;
|
||||||
|
origco = orig_data->positions;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case bke::pbvh::Type::BMesh:
|
||||||
use_origco = true;
|
use_origco = true;
|
||||||
origco = unode->position.as_span();
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4808,18 +4841,31 @@ static void sculpt_find_nearest_to_ray_cb(blender::bke::pbvh::Node &node,
|
|||||||
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
|
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_origco = false;
|
bool use_origco = false;
|
||||||
Span<float3> origco;
|
Span<float3> origco;
|
||||||
if (srd.original && srd.ss->cache) {
|
if (srd.original && srd.ss->cache) {
|
||||||
if (srd.ss->pbvh->type() == bke::pbvh::Type::BMesh) {
|
switch (srd.ss->pbvh->type()) {
|
||||||
use_origco = true;
|
case bke::pbvh::Type::Mesh:
|
||||||
}
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_mesh(
|
||||||
else {
|
*srd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
|
||||||
/* Intersect with coordinates from before we started stroke. */
|
{
|
||||||
if (const undo::Node *unode = undo::get_node(&node, undo::Type::Position)) {
|
use_origco = true;
|
||||||
|
origco = orig_data->positions;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case bke::pbvh::Type::Grids:
|
||||||
|
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(
|
||||||
|
*srd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
|
||||||
|
{
|
||||||
|
use_origco = true;
|
||||||
|
origco = orig_data->positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case bke::pbvh::Type::BMesh:
|
||||||
use_origco = true;
|
use_origco = true;
|
||||||
origco = unode->position.as_span();
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4922,6 +4968,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
|||||||
|
|
||||||
SculptRaycastData srd{};
|
SculptRaycastData srd{};
|
||||||
srd.original = original;
|
srd.original = original;
|
||||||
|
srd.object = &ob;
|
||||||
srd.ss = ob.sculpt;
|
srd.ss = ob.sculpt;
|
||||||
srd.hit = false;
|
srd.hit = false;
|
||||||
if (ss.pbvh->type() == bke::pbvh::Type::Mesh) {
|
if (ss.pbvh->type() == bke::pbvh::Type::Mesh) {
|
||||||
@@ -5097,6 +5144,7 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
|
|||||||
bool hit = false;
|
bool hit = false;
|
||||||
{
|
{
|
||||||
SculptRaycastData srd;
|
SculptRaycastData srd;
|
||||||
|
srd.object = &ob;
|
||||||
srd.ss = ob.sculpt;
|
srd.ss = ob.sculpt;
|
||||||
srd.ray_start = ray_start;
|
srd.ray_start = ray_start;
|
||||||
srd.ray_normal = ray_normal;
|
srd.ray_normal = ray_normal;
|
||||||
@@ -5139,6 +5187,7 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
|
|||||||
|
|
||||||
SculptFindNearestToRayData srd{};
|
SculptFindNearestToRayData srd{};
|
||||||
srd.original = original;
|
srd.original = original;
|
||||||
|
srd.object = &ob;
|
||||||
srd.ss = ob.sculpt;
|
srd.ss = ob.sculpt;
|
||||||
srd.hit = false;
|
srd.hit = false;
|
||||||
if (ss.pbvh->type() == bke::pbvh::Type::Mesh) {
|
if (ss.pbvh->type() == bke::pbvh::Type::Mesh) {
|
||||||
@@ -6208,6 +6257,7 @@ bool SCULPT_vertex_is_occluded(const Object &object, const float3 &position, boo
|
|||||||
|
|
||||||
SculptRaycastData srd = {nullptr};
|
SculptRaycastData srd = {nullptr};
|
||||||
srd.original = original;
|
srd.original = original;
|
||||||
|
srd.object = &object;
|
||||||
srd.ss = &ss;
|
srd.ss = &ss;
|
||||||
srd.hit = false;
|
srd.hit = false;
|
||||||
srd.ray_start = ray_start;
|
srd.ray_start = ray_start;
|
||||||
|
|||||||
@@ -625,8 +625,8 @@ void calc_vert_factors(const Depsgraph &depsgraph,
|
|||||||
{
|
{
|
||||||
Span<float3> orig_normals;
|
Span<float3> orig_normals;
|
||||||
if (cache.settings.flags & (BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL)) {
|
if (cache.settings.flags & (BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL)) {
|
||||||
if (const undo::Node *unode = undo::get_node(&node, undo::Type::Position)) {
|
if (std::optional<OrigPositionData> orig_data = orig_position_data_lookup_mesh(object, node)) {
|
||||||
orig_normals = unode->normal.as_span();
|
orig_normals = orig_data->normals;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,8 +672,9 @@ void calc_grids_factors(const Depsgraph &depsgraph,
|
|||||||
|
|
||||||
Span<float3> orig_normals;
|
Span<float3> orig_normals;
|
||||||
if (cache.settings.flags & (BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL)) {
|
if (cache.settings.flags & (BRUSH_AUTOMASKING_BRUSH_NORMAL | BRUSH_AUTOMASKING_VIEW_NORMAL)) {
|
||||||
if (const undo::Node *unode = undo::get_node(&node, undo::Type::Position)) {
|
if (std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(object, node))
|
||||||
orig_normals = unode->normal.as_span();
|
{
|
||||||
|
orig_normals = orig_data->normals;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -718,16 +718,45 @@ struct OrigPositionData {
|
|||||||
* Retrieve positions from the latest undo state. This is often used for modal actions that depend
|
* Retrieve positions from the latest undo state. This is often used for modal actions that depend
|
||||||
* on the initial state of the geometry from before the start of the action.
|
* on the initial state of the geometry from before the start of the action.
|
||||||
*/
|
*/
|
||||||
OrigPositionData orig_position_data_get_mesh(const Object &object,
|
std::optional<OrigPositionData> orig_position_data_lookup_mesh(const Object &object,
|
||||||
const bke::pbvh::MeshNode &node);
|
const bke::pbvh::MeshNode &node);
|
||||||
OrigPositionData orig_position_data_get_grids(const Object &object,
|
inline OrigPositionData orig_position_data_get_mesh(const Object &object,
|
||||||
const bke::pbvh::GridsNode &node);
|
const bke::pbvh::MeshNode &node)
|
||||||
|
{
|
||||||
|
return *orig_position_data_lookup_mesh(object, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<OrigPositionData> orig_position_data_lookup_grids(const Object &object,
|
||||||
|
const bke::pbvh::GridsNode &node);
|
||||||
|
inline OrigPositionData orig_position_data_get_grids(const Object &object,
|
||||||
|
const bke::pbvh::GridsNode &node)
|
||||||
|
{
|
||||||
|
return *orig_position_data_lookup_grids(object, node);
|
||||||
|
}
|
||||||
|
|
||||||
void orig_position_data_gather_bmesh(const BMLog &bm_log,
|
void orig_position_data_gather_bmesh(const BMLog &bm_log,
|
||||||
const Set<BMVert *, 0> &verts,
|
const Set<BMVert *, 0> &verts,
|
||||||
MutableSpan<float3> positions,
|
MutableSpan<float3> positions,
|
||||||
MutableSpan<float3> normals);
|
MutableSpan<float3> normals);
|
||||||
|
|
||||||
Span<float4> orig_color_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node);
|
std::optional<Span<float4>> orig_color_data_lookup_mesh(const Object &object,
|
||||||
|
const bke::pbvh::MeshNode &node);
|
||||||
|
inline Span<float4> orig_color_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
|
||||||
|
{
|
||||||
|
return *orig_color_data_lookup_mesh(object, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Span<int>> orig_face_set_data_lookup_mesh(const Object &object,
|
||||||
|
const bke::pbvh::MeshNode &node);
|
||||||
|
|
||||||
|
std::optional<Span<int>> orig_face_set_data_lookup_grids(const Object &object,
|
||||||
|
const bke::pbvh::GridsNode &node);
|
||||||
|
|
||||||
|
std::optional<Span<float>> orig_mask_data_lookup_mesh(const Object &object,
|
||||||
|
const bke::pbvh::MeshNode &node);
|
||||||
|
|
||||||
|
std::optional<Span<float>> orig_mask_data_lookup_grids(const Object &object,
|
||||||
|
const bke::pbvh::GridsNode &node);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,37 @@ namespace blender::ed::sculpt_paint::undo {
|
|||||||
|
|
||||||
#define NO_ACTIVE_LAYER bke::AttrDomain::Auto
|
#define NO_ACTIVE_LAYER bke::AttrDomain::Auto
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
Array<float3, 0> position;
|
||||||
|
Array<float3, 0> orig_position;
|
||||||
|
Array<float3, 0> normal;
|
||||||
|
Array<float4, 0> col;
|
||||||
|
Array<float, 0> mask;
|
||||||
|
|
||||||
|
Array<float4, 0> loop_col;
|
||||||
|
|
||||||
|
/* Mesh. */
|
||||||
|
|
||||||
|
Array<int, 0> vert_indices;
|
||||||
|
int unique_verts_num;
|
||||||
|
|
||||||
|
Array<int, 0> corner_indices;
|
||||||
|
|
||||||
|
BitVector<0> vert_hidden;
|
||||||
|
BitVector<0> face_hidden;
|
||||||
|
|
||||||
|
/* Multires. */
|
||||||
|
|
||||||
|
/** Indices of grids in the pbvh::Tree node. */
|
||||||
|
Array<int, 0> grids;
|
||||||
|
BitGroupVector<0> grid_hidden;
|
||||||
|
|
||||||
|
/* Sculpt Face Sets */
|
||||||
|
Array<int, 0> face_sets;
|
||||||
|
|
||||||
|
Vector<int> face_indices;
|
||||||
|
};
|
||||||
|
|
||||||
struct SculptAttrRef {
|
struct SculptAttrRef {
|
||||||
bke::AttrDomain domain;
|
bke::AttrDomain domain;
|
||||||
eCustomDataType type;
|
eCustomDataType type;
|
||||||
@@ -1129,7 +1160,13 @@ static void free_step_data(StepData &step_data)
|
|||||||
step_data.~StepData();
|
step_data.~StepData();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Node *get_node(const bke::pbvh::Node *node, const Type type)
|
/**
|
||||||
|
* Retrieve the undo data of a given type for the active undo step. For example, this is used to
|
||||||
|
* access "original" data from before the current stroke.
|
||||||
|
*
|
||||||
|
* This is only possible when building an undo step, in between #push_begin and #push_end.
|
||||||
|
*/
|
||||||
|
static const Node *get_node(const bke::pbvh::Node *node, const Type type)
|
||||||
{
|
{
|
||||||
StepData *step_data = get_step_data();
|
StepData *step_data = get_step_data();
|
||||||
if (!step_data) {
|
if (!step_data) {
|
||||||
@@ -2124,19 +2161,25 @@ void push_multires_mesh_end(bContext *C, const char *str)
|
|||||||
|
|
||||||
namespace blender::ed::sculpt_paint {
|
namespace blender::ed::sculpt_paint {
|
||||||
|
|
||||||
OrigPositionData orig_position_data_get_mesh(const Object & /*object*/,
|
std::optional<OrigPositionData> orig_position_data_lookup_mesh(const Object & /*object*/,
|
||||||
const bke::pbvh::MeshNode &node)
|
const bke::pbvh::MeshNode &node)
|
||||||
{
|
{
|
||||||
const undo::Node *unode = undo::get_node(&node, undo::Type::Position);
|
const undo::Node *unode = undo::get_node(&node, undo::Type::Position);
|
||||||
return {unode->position.as_span().take_front(unode->unique_verts_num),
|
if (!unode) {
|
||||||
unode->normal.as_span().take_front(unode->unique_verts_num)};
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return OrigPositionData{unode->position.as_span().take_front(unode->unique_verts_num),
|
||||||
|
unode->normal.as_span().take_front(unode->unique_verts_num)};
|
||||||
}
|
}
|
||||||
|
|
||||||
OrigPositionData orig_position_data_get_grids(const Object & /*object*/,
|
std::optional<OrigPositionData> orig_position_data_lookup_grids(const Object & /*object*/,
|
||||||
const bke::pbvh::GridsNode &node)
|
const bke::pbvh::GridsNode &node)
|
||||||
{
|
{
|
||||||
const undo::Node *unode = undo::get_node(&node, undo::Type::Position);
|
const undo::Node *unode = undo::get_node(&node, undo::Type::Position);
|
||||||
return {unode->position.as_span(), unode->normal.as_span()};
|
if (!unode) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return OrigPositionData{unode->position.as_span(), unode->normal.as_span()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void orig_position_data_gather_bmesh(const BMLog &bm_log,
|
void orig_position_data_gather_bmesh(const BMLog &bm_log,
|
||||||
@@ -2159,10 +2202,54 @@ void orig_position_data_gather_bmesh(const BMLog &bm_log,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<float4> orig_color_data_get_mesh(const Object & /*object*/, const bke::pbvh::MeshNode &node)
|
std::optional<Span<float4>> orig_color_data_lookup_mesh(const Object & /*object*/,
|
||||||
|
const bke::pbvh::MeshNode &node)
|
||||||
{
|
{
|
||||||
const undo::Node *unode = undo::get_node(&node, undo::Type::Color);
|
const undo::Node *unode = undo::get_node(&node, undo::Type::Color);
|
||||||
|
if (!unode) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
return unode->col.as_span();
|
return unode->col.as_span();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<Span<int>> orig_face_set_data_lookup_mesh(const Object & /*object*/,
|
||||||
|
const bke::pbvh::MeshNode &node)
|
||||||
|
{
|
||||||
|
const undo::Node *unode = undo::get_node(&node, undo::Type::FaceSet);
|
||||||
|
if (!unode) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return unode->face_sets.as_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Span<int>> orig_face_set_data_lookup_grids(const Object & /*object*/,
|
||||||
|
const bke::pbvh::GridsNode &node)
|
||||||
|
{
|
||||||
|
const undo::Node *unode = undo::get_node(&node, undo::Type::FaceSet);
|
||||||
|
if (!unode) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return unode->face_sets.as_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Span<float>> orig_mask_data_lookup_mesh(const Object & /*object*/,
|
||||||
|
const bke::pbvh::MeshNode &node)
|
||||||
|
{
|
||||||
|
const undo::Node *unode = undo::get_node(&node, undo::Type::Mask);
|
||||||
|
if (!unode) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return unode->mask.as_span();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Span<float>> orig_mask_data_lookup_grids(const Object & /*object*/,
|
||||||
|
const bke::pbvh::GridsNode &node)
|
||||||
|
{
|
||||||
|
const undo::Node *unode = undo::get_node(&node, undo::Type::Mask);
|
||||||
|
if (!unode) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return unode->mask.as_span();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::ed::sculpt_paint
|
} // namespace blender::ed::sculpt_paint
|
||||||
|
|||||||
@@ -45,37 +45,6 @@ enum class Type : int8_t {
|
|||||||
Color,
|
Color,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Node {
|
|
||||||
Array<float3, 0> position;
|
|
||||||
Array<float3, 0> orig_position;
|
|
||||||
Array<float3, 0> normal;
|
|
||||||
Array<float4, 0> col;
|
|
||||||
Array<float, 0> mask;
|
|
||||||
|
|
||||||
Array<float4, 0> loop_col;
|
|
||||||
|
|
||||||
/* Mesh. */
|
|
||||||
|
|
||||||
Array<int, 0> vert_indices;
|
|
||||||
int unique_verts_num;
|
|
||||||
|
|
||||||
Array<int, 0> corner_indices;
|
|
||||||
|
|
||||||
BitVector<0> vert_hidden;
|
|
||||||
BitVector<0> face_hidden;
|
|
||||||
|
|
||||||
/* Multires. */
|
|
||||||
|
|
||||||
/** Indices of grids in the pbvh::Tree node. */
|
|
||||||
Array<int, 0> grids;
|
|
||||||
BitGroupVector<0> grid_hidden;
|
|
||||||
|
|
||||||
/* Sculpt Face Sets */
|
|
||||||
Array<int, 0> face_sets;
|
|
||||||
|
|
||||||
Vector<int> face_indices;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Storage of geometry for the undo node.
|
/* Storage of geometry for the undo node.
|
||||||
* Is used as a storage for either original or modified geometry. */
|
* Is used as a storage for either original or modified geometry. */
|
||||||
struct NodeGeometry {
|
struct NodeGeometry {
|
||||||
@@ -95,6 +64,8 @@ struct NodeGeometry {
|
|||||||
int faces_num;
|
int faces_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Node;
|
||||||
|
|
||||||
struct StepData {
|
struct StepData {
|
||||||
/**
|
/**
|
||||||
* The type of data stored in this undo step. For historical reasons this is often set when the
|
* The type of data stored in this undo step. For historical reasons this is often set when the
|
||||||
@@ -177,14 +148,6 @@ void push_nodes(const Depsgraph &depsgraph,
|
|||||||
const IndexMask &node_mask,
|
const IndexMask &node_mask,
|
||||||
undo::Type type);
|
undo::Type type);
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the undo data of a given type for the active undo step. For example, this is used to
|
|
||||||
* access "original" data from before the current stroke.
|
|
||||||
*
|
|
||||||
* This is only possible when building an undo step, in between #push_begin and #push_end.
|
|
||||||
*/
|
|
||||||
const undo::Node *get_node(const bke::pbvh::Node *node, undo::Type type);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pushes an undo step using the operator name. This is necessary for
|
* Pushes an undo step using the operator name. This is necessary for
|
||||||
* redo panels to work; operators that do not support that may use
|
* redo panels to work; operators that do not support that may use
|
||||||
|
|||||||
Reference in New Issue
Block a user