Curves: Add support for proportional editing #104620

Closed
Falk David wants to merge 15 commits from filedescriptor:curves-proportional-editing into blender-v3.5-release

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
1 changed files with 25 additions and 20 deletions
Showing only changes of commit d487602e35 - Show all commits

View File

@ -29,15 +29,15 @@ static void calculate_curve_point_distances_for_proportional_editing(
{
Array<bool> visited(positions.size(), false);
filedescriptor marked this conversation as resolved
Review

prop -> proportional? Curious what you think about that-- saving a few characters doesn't help so much here.

`prop` -> `proportional`? Curious what you think about that-- saving a few characters doesn't help so much here.
InplacePriorityQueue<float> queue(r_distances);
InplacePriorityQueue<float, std::less<float>> queue(r_distances);
while (!queue.is_empty()) {
int64_t idx = queue.pop_index();
if (!visited[idx]) {
if (visited[idx]) {
continue;
}
visited[idx] = true;
if (idx > 0) {
if (idx > 0 && !visited[idx - 1]) {
filedescriptor marked this conversation as resolved
Review

Tiny thing, but fairly sure this will end up in a cleanup commit by Campbell to remove the space between TODO and (Falk) :P

I'd remove your name or the space

Tiny thing, but fairly sure this will end up in a cleanup commit by Campbell to remove the space between `TODO` and `(Falk)` :P I'd remove your name or the space
int adj = idx - 1;
float dist = r_distances[idx] + math::distance(positions[idx], positions[adj]);
if (dist < r_distances[adj]) {
@ -45,7 +45,7 @@ static void calculate_curve_point_distances_for_proportional_editing(
queue.priority_changed(adj);
}
}
if (idx < positions.size() - 1) {
if (idx < positions.size() - 1 && !visited[idx + 1]) {
int adj = idx + 1;
float dist = r_distances[idx] + math::distance(positions[idx], positions[adj]);
if (dist < r_distances[adj]) {
@ -106,41 +106,46 @@ static void createTransCurvesVerts(bContext * /*C*/, TransInfo *t)
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange range) {
for (const int curve_i : range) {
bool has_any_selected = false;
const IndexRange points = points_by_curve[curve_i];
Span<float3> positions_curve = positions_read.slice(points_by_curve[curve_i]);
Array<float> closest_distances(positions_curve.size(), FLT_MAX);
for (const int point_i : points_by_curve[curve_i]) {
TransData *td = &tc.data[point_i];
for (const int i : IndexRange(points.size())) {
const int point_i = points[i];
TransData &td = tc.data[point_i];
float *elem = reinterpret_cast<float *>(&positions[point_i]);
copy_v3_v3(td->iloc, elem);
copy_v3_v3(td->center, td->iloc);
td->loc = elem;
copy_v3_v3(td.iloc, elem);
copy_v3_v3(td.center, td.iloc);
td.loc = elem;
filedescriptor marked this conversation as resolved
Review

for (const int point_i : points) {

`for (const int point_i : points) {`
td.flag = 0;
if (selection[point_i]) {
has_any_selected = true;
closest_distances[point_i - points_by_curve[curve_i].start()] = 0.0f;
closest_distances[i] = 0.0f;
td.flag = TD_SELECTED;
}
td->flag = (selection[point_i]) ? TD_SELECTED : 0;
td->ext = nullptr;
td.ext = nullptr;
copy_m3_m3(td->smtx, smtx);
copy_m3_m3(td->mtx, mtx);
copy_m3_m3(td.smtx, smtx);
filedescriptor marked this conversation as resolved
Review

This array makes things a bit more readable, but it isn't really necessary considering all the data will go into TransData.dist right after. It might be worth skipping the array, since this will be an allocation and free for every single curve.

This array makes things a bit more readable, but it isn't really necessary considering all the data will go into `TransData.dist` right after. It might be worth skipping the array, since this will be an allocation and free for every single curve.
Review

I am not sure how I would rewrite the code to not use an array in this case. The td->dist values are not sequential, so I can't write to them directly. But the implementation needs some container that I can build the InplacePriorityQueue on top of.

I am not sure how I would rewrite the code to not use an array in this case. The `td->dist` values are not sequential, so I can't write to them directly. But the implementation needs some container that I can build the `InplacePriorityQueue` on top of.
Review

Ah right! That's totally fine, it was just a thought.

Ah right! That's totally fine, it was just a thought.
copy_m3_m3(td.mtx, mtx);
}
if (is_prop_connected) {
if (is_prop_connected && has_any_selected) {
calculate_curve_point_distances_for_proportional_editing(
positions_curve, closest_distances.as_mutable_span());
for (const int point_i : points_by_curve[curve_i]) {
TransData *td = &tc.data[point_i];
td->dist = closest_distances[point_i - points_by_curve[curve_i].start()];
for (const int i : IndexRange(points.size())) {
TransData &td = tc.data[points[i]];
td.dist = closest_distances[i];
}
}
if (!has_any_selected) {
for (const int point_i : points_by_curve[curve_i]) {
TransData *td = &tc.data[point_i];
td->flag |= TD_NOTCONNECTED;
TransData &td = tc.data[point_i];
td.flag |= TD_NOTCONNECTED;
td.dist = FLT_MAX;
}
}
}