Animation: blend to infinity slider #106517

Closed
AresDeveaux wants to merge 15 commits from AresDeveaux/blender:blend_to_infinity_slider into main

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 30 deletions
Showing only changes of commit 5a4881e529 - Show all commits

View File

@ -496,69 +496,64 @@ void blend_to_infinity_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const
const BezTriple *left_key = fcurve_segment_start_get(fcu, segment->start_index);
const BezTriple *right_key = fcurve_segment_end_get(fcu, segment->start_index + segment->length);
/* One key on the outside of the neighboring keys is needed to use as reference. */
const BezTriple *beyond_left_key = fcurve_segment_start_get(fcu, segment->start_index - 1);
const BezTriple *beyond_right_key = fcurve_segment_end_get(
fcu, segment->start_index + segment->length + 1);
/* The calculation needs diferent values for each side of the slider. */
const bool slider_right_side = factor >= 0.5;
const bool slider_left_side = factor < 0.5;
/* The factor goes from 0 to 1, but for this tool it needs to go from 0 to 1 on each side of the
* slider. */
const float ping_pong_factor = fabs(factor * 2 - 1);

I think instead of splitting the vector into its two components it would be better to keep it as a vector and use the functions in math_vector_inline.c

This will potentially simplify your code quite a lot.

I think instead of splitting the vector into its two components it would be better to keep it as a vector and use the functions in `math_vector_inline.c` This will potentially simplify your code quite a lot.
float x_delta = 0;
float y_delta = 0;
float x_delta = 1;
float y_delta = 1;
/* This delta values are used to know the relationship between the bookend keys and the
/* This delta values are used to get the relationship between the bookend keys and the
* reference keys beyong those. */
if (slider_right_side) {
/* Stop the fucntion if there is no key beyond the the right neighboring one. */
if (factor >= 0.5) {
/* Stop the function if there is no key beyond the the right neighboring one. */
if (segment->start_index + segment->length == fcu->totvert) {
return;
}
const BezTriple *beyond_right_key = fcurve_segment_end_get(

this can also be clearer.
segment->start_index + segment->length > fcu->totvert

this can also be clearer. `segment->start_index + segment->length > fcu->totvert`

I tried this change as well as the next one and it doesn't work as it should. Remember, we need 2 keys before and after the segment, the way you suggest just account for one. If I don't prevent not having 2 keys at each side of the segment the tool goes crazy.

I tried this change as well as the next one and it doesn't work as it should. Remember, we need 2 keys before and after the segment, the way you suggest just account for one. If I don't prevent not having 2 keys at each side of the segment the tool goes crazy.
fcu, segment->start_index + segment->length + 1);
y_delta = beyond_right_key->vec[1][1] - right_key->vec[1][1];
x_delta = beyond_right_key->vec[1][0] - right_key->vec[1][0];

I don't think you need this. At least I can't see it being used other than the check for 0.0f

If it is required that there is more than 1 key selected, update the comment because there is no potential divide by 0

I don't think you need this. At least I can't see it being used other than the check for 0.0f If it is required that there is more than 1 key selected, update the comment because there is no potential divide by 0
}
else if (slider_left_side) {
/* Stop the fucntion if there is no key beyond the left neighboring one. */
else {
/* Stop the function if there is no key beyond the left neighboring one. */
if (segment->start_index == 0) {
return;
}

This would be clearer if you checked explicitly to 0
segment->start_index == 0

the start index will never be smaller than 0

This would be clearer if you checked explicitly to 0 `segment->start_index == 0` the start index will never be smaller than 0

I am glad you didn't listen to me here, because I just realized what I suggested is wrong 🤦

I am glad you didn't listen to me here, because I just realized what I suggested is wrong 🤦
const BezTriple *beyond_left_key = fcurve_segment_start_get(fcu, segment->start_index - 1);
y_delta = beyond_left_key->vec[1][1] - left_key->vec[1][1];

shouldn't this return false?
also now that I think about it, I am not sure x_delta can ever be 0. It would only be 0 if the beyond key and the reference key are the same, which they cannot be since you are getting different indices.
Hm ok writing this now, you can have the curve in a state where two keys are at the same point in time. Shouldn't happen, but could...

Anyway, the function should return true if it ran and false if it didn't. Since you are exiting early here, I think it should return false.

shouldn't this return false? also now that I think about it, I am not sure x_delta can ever be 0. It would only be 0 if the beyond key and the reference key are the same, which they cannot be since you are getting different indices. Hm ok writing this now, you can have the curve in a state where two keys are at the same point in time. Shouldn't happen, but could... Anyway, the function should return true if it ran and false if it didn't. Since you are exiting early here, I think it should return false.
x_delta = beyond_left_key->vec[1][0] - left_key->vec[1][0];
}
else {
y_delta = 1;
x_delta = 1;
/* Avoids dividing by 0. */
if (x_delta == 0) {

since this is now outside of the if else, you can to
const float y_delta = ...
and then remove the lines 503 and 504

since this is now outside of the if else, you can to `const float y_delta = ...` and then remove the lines 503 and 504
return;
}
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
float new_x_delta = 0;
float new_y_delta = 0;
float reference_y = 0;
float new_x_delta;
float new_y_delta;
const BezTriple *reference_key;

this can move into the for loop and you can then call it
const float new_x_delta = ...

this can move into the for loop and you can then call it `const float new_x_delta = ...`
/* These new deltas are used to determine the relationship between the current key and the
* bookend ones. */

this code can be moved to the first if else

this code can be moved to the first `if else`
if (slider_right_side) {
if (factor >= 0.5) {
new_x_delta = fcu->bezt[i].vec[1][0] - right_key->vec[1][0];
reference_y = right_key->vec[1][1];
reference_key = right_key;
}
else {
new_x_delta = fcu->bezt[i].vec[1][0] - left_key->vec[1][0];
reference_y = left_key->vec[1][1];
reference_key = left_key;
}
/* We use compound rule of 3 to find the "Y" delta we are missing using the other deltas we
* know. */
if (x_delta != 0) {
new_y_delta = new_x_delta * y_delta / x_delta;
}
* know. */
new_y_delta = new_x_delta * y_delta / x_delta;
const float delta = reference_y + new_y_delta - fcu->bezt[i].vec[1][1];
const float delta = reference_key->vec[1][1] + new_y_delta - fcu->bezt[i].vec[1][1];
const float key_y_value = fcu->bezt[i].vec[1][1] + delta * ping_pong_factor;
move_key(&fcu->bezt[i], key_y_value);