main sync #3

Merged
Patrick Busch merged 318 commits from blender/blender:main into main 2023-03-17 15:52:21 +01:00
9 changed files with 394 additions and 237 deletions
Showing only changes of commit 2e03352492 - Show all commits

View File

@ -366,24 +366,22 @@ int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
int fcurve_result_len);
/**
* Calculate the extents of F-Curve's keyframes.
* Calculate the x range of the given F-Curve's data.
* \return true if a range has been found.
*/
bool BKE_fcurve_calc_range(
const struct FCurve *fcu, float *min, float *max, bool do_sel_only, bool do_min_length);
bool BKE_fcurve_calc_range(const struct FCurve *fcu, float *r_min, float *r_max, bool selected_keys_only);
/**
* Calculate the extents of F-Curve's data.
* \param range Only calculate the bounds of the FCurve in the given range.
* Calculate the x and y extents of F-Curve's data.
* \param frame_range Only calculate the bounds of the FCurve in the given range.
* Does the full range if NULL.
* \return true if the bounds have been found.
*/
bool BKE_fcurve_calc_bounds(const struct FCurve *fcu,
float *xmin,
float *xmax,
float *ymin,
float *ymax,
bool do_sel_only,
bool selected_keys_only,
bool include_handles,
const float range[2]);
const float frame_range[2],
struct rctf *r_bounds);
/**
* Return an array of keyed frames, rounded to `interval`.

View File

@ -1408,7 +1408,7 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
* single-keyframe curves will increase the overall length by
* a phantom frame (#50354)
*/
BKE_fcurve_calc_range(fcu, &nmin, &nmax, false, false);
BKE_fcurve_calc_range(fcu, &nmin, &nmax, false);
/* compare to the running tally */
min = min_ff(min, nmin);

View File

@ -556,252 +556,236 @@ int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[],
/* ...................................... */
/* Helper for calc_fcurve_* functions -> find first and last BezTriple to be used. */
static bool get_fcurve_end_keyframes(const FCurve *fcu,
BezTriple **first,
BezTriple **last,
const bool do_sel_only,
const float range[2])
/* Get the first and last index to the bezt array that satisfies the given parameters.
* \param selected_keys_only Only accept indices of bezt that are selected. Is a subset of
* frame_range. \param frame_range Only consider keyframes in that frame interval. Can be NULL.
*/
static bool get_bounding_bezt_indices(const FCurve *fcu,
const bool selected_keys_only,
const float frame_range[2],
int *r_first,
int *r_last)
{
bool found = false;
/* Init outputs. */
*first = NULL;
*last = NULL;
/* Sanity checks. */
if (fcu->bezt == NULL) {
return found;
return false;
}
int first_index = 0;
int last_index = fcu->totvert - 1;
*r_first = 0;
*r_last = fcu->totvert - 1;
if (range != NULL) {
bool found = false;
if (frame_range != NULL) {
/* If a range is passed in find the first and last keyframe within that range. */
bool replace = false;
first_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[0], fcu->totvert, &replace);
last_index = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, range[1], fcu->totvert, &replace);
*r_first = BKE_fcurve_bezt_binarysearch_index(
fcu->bezt, frame_range[0], fcu->totvert, &replace);
*r_last = BKE_fcurve_bezt_binarysearch_index(
fcu->bezt, frame_range[1], fcu->totvert, &replace);
/* If first and last index are the same, no keyframes were found in the range. */
if (first_index == last_index) {
return found;
if (*r_first == *r_last) {
return false;
}
/* The binary search returns an index where a keyframe would be inserted,
* so it needs to be clamped to ensure it is in range of the array. */
first_index = clamp_i(first_index, 0, fcu->totvert - 1);
last_index = clamp_i(last_index - 1, 0, fcu->totvert - 1);
*r_first = clamp_i(*r_first, 0, fcu->totvert - 1);
*r_last = clamp_i(*r_last - 1, 0, fcu->totvert - 1);
}
/* Only include selected items? */
if (do_sel_only) {
if (selected_keys_only) {
/* Find first selected. */
for (int i = first_index; i <= last_index; i++) {
for (int i = *r_first; i <= *r_last; i++) {
BezTriple *bezt = &fcu->bezt[i];
if (BEZT_ISSEL_ANY(bezt)) {
*first = bezt;
*r_first = i;
found = true;
break;
}
}
/* Find last selected. */
for (int i = last_index; i >= first_index; i--) {
for (int i = *r_last; i >= *r_first; i--) {
BezTriple *bezt = &fcu->bezt[i];
if (BEZT_ISSEL_ANY(bezt)) {
*last = bezt;
*r_last = i;
found = true;
break;
}
}
}
else {
*first = &fcu->bezt[first_index];
*last = &fcu->bezt[last_index];
found = true;
}
return found;
}
bool BKE_fcurve_calc_bounds(const FCurve *fcu,
float *xmin,
float *xmax,
float *ymin,
float *ymax,
const bool do_sel_only,
static void calculate_bezt_bounds_x(BezTriple *bezt_array,
const int index_range[2],
const bool include_handles,
const float range[2])
float *r_min,
float *r_max)
{
float xminv = 999999999.0f, xmaxv = -999999999.0f;
float yminv = 999999999.0f, ymaxv = -999999999.0f;
bool foundvert = false;
*r_min = bezt_array[index_range[0]].vec[1][0];
*r_max = bezt_array[index_range[1]].vec[1][0];
const bool use_range = range != NULL;
if (fcu->totvert) {
if (fcu->bezt) {
if (xmin || xmax) {
BezTriple *bezt_first = NULL, *bezt_last = NULL;
foundvert = get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only, range);
if (bezt_first) {
BLI_assert(bezt_last != NULL);
foundvert = true;
if (include_handles) {
xminv = min_fff(xminv, bezt_first->vec[0][0], bezt_first->vec[1][0]);
xmaxv = max_fff(xmaxv, bezt_last->vec[1][0], bezt_last->vec[2][0]);
}
else {
xminv = min_ff(xminv, bezt_first->vec[1][0]);
xmaxv = max_ff(xmaxv, bezt_last->vec[1][0]);
/* Need to check all handles because they might extend beyond their neighboring keys. */
for (int i = index_range[0]; i <= index_range[1]; i++) {
const BezTriple *bezt = &bezt_array[i];
*r_min = min_fff(*r_min, bezt->vec[0][0], bezt->vec[1][0]);
*r_max = max_fff(*r_max, bezt->vec[1][0], bezt->vec[2][0]);
}
}
}
/* Only loop over keyframes to find extents for values if needed. */
if (ymin || ymax) {
BezTriple *bezt, *prevbezt = NULL;
static void calculate_bezt_bounds_y(BezTriple *bezt_array,
const int index_range[2],
const bool selected_keys_only,
const bool include_handles,
float *r_min,
float *r_max)
{
*r_min = bezt_array[index_range[0]].vec[1][1];
*r_max = bezt_array[index_range[0]].vec[1][1];
int i;
for (bezt = fcu->bezt, i = 0; i < fcu->totvert; prevbezt = bezt, bezt++, i++) {
if (use_range && (bezt->vec[1][0] < range[0] || bezt->vec[1][0] > range[1])) {
for (int i = index_range[0]; i <= index_range[1]; i++) {
const BezTriple *bezt = &bezt_array[i];
if (selected_keys_only && !BEZT_ISSEL_ANY(bezt)) {
continue;
}
if ((do_sel_only == false) || BEZT_ISSEL_ANY(bezt)) {
/* Keyframe itself. */
yminv = min_ff(yminv, bezt->vec[1][1]);
ymaxv = max_ff(ymaxv, bezt->vec[1][1]);
*r_min = min_ff(*r_min, bezt->vec[1][1]);
*r_max = max_ff(*r_max, bezt->vec[1][1]);
if (include_handles) {
/* Left handle - only if applicable.
* NOTE: for the very first keyframe,
* the left handle actually has no bearings on anything. */
if (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ)) {
yminv = min_ff(yminv, bezt->vec[0][1]);
ymaxv = max_ff(ymaxv, bezt->vec[0][1]);
}
/* Right handle - only if applicable. */
if (bezt->ipo == BEZT_IPO_BEZ) {
yminv = min_ff(yminv, bezt->vec[2][1]);
ymaxv = max_ff(ymaxv, bezt->vec[2][1]);
}
}
foundvert = true;
}
}
}
}
else if (fcu->fpt) {
/* Frame range can be directly calculated from end verts. */
if (xmin || xmax) {
xminv = min_ff(xminv, fcu->fpt[0].vec[0]);
xmaxv = max_ff(xmaxv, fcu->fpt[fcu->totvert - 1].vec[0]);
}
/* Only loop over keyframes to find extents for values if needed. */
if (ymin || ymax) {
int i = 0;
for (FPoint *fpt = fcu->fpt; i < fcu->totvert; fpt++, i++) {
if (fpt->vec[1] < yminv) {
yminv = fpt->vec[1];
}
if (fpt->vec[1] > ymaxv) {
ymaxv = fpt->vec[1];
}
foundvert = true;
}
*r_min = min_fff(*r_min, bezt->vec[0][1], bezt->vec[2][1]);
*r_max = max_fff(*r_max, bezt->vec[0][1], bezt->vec[2][1]);
}
}
}
if (foundvert) {
if (xmin) {
*xmin = xminv;
}
if (xmax) {
*xmax = xmaxv;
}
if (ymin) {
*ymin = yminv;
}
if (ymax) {
*ymax = ymaxv;
}
}
else {
if (G.debug & G_DEBUG) {
printf("F-Curve calc bounds didn't find anything, so assuming minimum bounds of 1.0\n");
}
if (xmin) {
*xmin = use_range ? range[0] : 0.0f;
}
if (xmax) {
*xmax = use_range ? range[1] : 1.0f;
}
if (ymin) {
*ymin = 0.0f;
}
if (ymax) {
*ymax = 1.0f;
}
}
return foundvert;
}
bool BKE_fcurve_calc_range(
const FCurve *fcu, float *start, float *end, const bool do_sel_only, const bool do_min_length)
static bool calculate_bezt_bounds(const FCurve *fcu,
const bool selected_keys_only,
const bool include_handles,
const float frame_range[2],
rctf *r_bounds)
{
float min = 999999999.0f, max = -999999999.0f;
int index_range[2];
const bool found_indices = get_bounding_bezt_indices(
fcu, selected_keys_only, frame_range, &index_range[0], &index_range[1]);
if (!found_indices) {
return false;
}
calculate_bezt_bounds_x(
fcu->bezt, index_range, include_handles, &r_bounds->xmin, &r_bounds->xmax);
calculate_bezt_bounds_y(fcu->bezt,
index_range,
selected_keys_only,
include_handles,
&r_bounds->ymin,
&r_bounds->ymax);
return true;
}
static bool calculate_fpt_bounds(const FCurve *fcu, const float frame_range[2], rctf *r_bounds)
{
r_bounds->xmin = INFINITY;
r_bounds->xmax = -INFINITY;
r_bounds->ymin = INFINITY;
r_bounds->ymax = -INFINITY;
const int first_index = 0;
const int last_index = fcu->totvert - 1;
int start_index = first_index;
int end_index = last_index;
if (frame_range != NULL) {
/* Start index can be calculated because fpt has a key on every full frame. */
const float start_index_f = frame_range[0] - fcu->fpt[0].vec[0];
const float end_index_f = start_index_f + frame_range[1] - frame_range[0];
if (start_index_f > fcu->totvert - 1 || end_index_f < 0) {
/* Range is outside of keyframe samples. */
return false;
}
/* Range might be partially covering keyframe samples. */
start_index = clamp_i(start_index_f, 0, fcu->totvert - 1);
end_index = clamp_i(end_index_f, 0, fcu->totvert - 1);
}
/* X range can be directly calculated from end verts. */
r_bounds->xmin = fcu->fpt[start_index].vec[0];
r_bounds->xmax = fcu->fpt[end_index].vec[0];
for (int i = start_index; i <= end_index; i++) {
r_bounds->ymin = min_ff(r_bounds->ymin, fcu->fpt[i].vec[1]);
r_bounds->ymax = max_ff(r_bounds->ymax, fcu->fpt[i].vec[1]);
}
return BLI_rctf_is_valid(r_bounds);
}
bool BKE_fcurve_calc_bounds(const FCurve *fcu,
const bool selected_keys_only,
const bool include_handles,
const float frame_range[2],
rctf *r_bounds)
{
if (fcu->totvert == 0) {
return false;
}
if (fcu->bezt) {
const bool found_bounds = calculate_bezt_bounds(
fcu, selected_keys_only, include_handles, frame_range, r_bounds);
return found_bounds;
}
if (fcu->fpt) {
const bool founds_bounds = calculate_fpt_bounds(fcu, frame_range, r_bounds);
return founds_bounds;
}
return false;
}
bool BKE_fcurve_calc_range(const FCurve *fcu,
float *r_start,
float *r_end,
const bool selected_keys_only)
{
float min, max = 0.0f;
bool foundvert = false;
if (fcu->totvert) {
if (fcu->bezt) {
BezTriple *bezt_first = NULL, *bezt_last = NULL;
/* Get endpoint keyframes. */
get_fcurve_end_keyframes(fcu, &bezt_first, &bezt_last, do_sel_only, NULL);
if (bezt_first) {
BLI_assert(bezt_last != NULL);
min = min_ff(min, bezt_first->vec[1][0]);
max = max_ff(max, bezt_last->vec[1][0]);
foundvert = true;
if (fcu->totvert == 0) {
return false;
}
if (fcu->bezt) {
int index_range[2];
foundvert = get_bounding_bezt_indices(
fcu, selected_keys_only, NULL, &index_range[0], &index_range[1]);
if (!foundvert) {
return false;
}
const bool include_handles = false;
calculate_bezt_bounds_x(fcu->bezt, index_range, include_handles, &min, &max);
}
else if (fcu->fpt) {
min = min_ff(min, fcu->fpt[0].vec[0]);
max = max_ff(max, fcu->fpt[fcu->totvert - 1].vec[0]);
min = fcu->fpt[0].vec[0];
max = fcu->fpt[fcu->totvert - 1].vec[0];
foundvert = true;
}
}
if (foundvert == false) {
min = max = 0.0f;
}
if (do_min_length) {
/* Minimum length is 1 frame. */
if (min == max) {
max += 1.0f;
}
}
*start = min;
*end = max;
*r_start = min;
*r_end = max;
return foundvert;
}

View File

@ -346,4 +346,189 @@ TEST(BKE_fcurve, BKE_fcurve_keyframe_move_value_with_handles)
BKE_fcurve_free(fcu);
}
TEST(BKE_fcurve, BKE_fcurve_calc_range)
{
FCurve *fcu = BKE_fcurve_create();
insert_vert_fcurve(fcu, 1.0f, 7.5f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 4.0f, -15.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 8.0f, 15.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 14.0f, 8.2f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 18.2f, -20.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
for (int i = 0; i < fcu->totvert; i++) {
fcu->bezt[i].f1 &= ~SELECT;
fcu->bezt[i].f2 &= ~SELECT;
fcu->bezt[i].f3 &= ~SELECT;
}
float min, max;
bool success;
/* All keys. */
success = BKE_fcurve_calc_range(fcu, &min, &max, false);
EXPECT_TRUE(success) << "A non-empty FCurve should have a range.";
EXPECT_FLOAT_EQ(fcu->bezt[0].vec[1][0], min);
EXPECT_FLOAT_EQ(fcu->bezt[4].vec[1][0], max);
/* Only selected. */
success = BKE_fcurve_calc_range(fcu, &min, &max, true);
EXPECT_FALSE(success)
<< "Using selected keyframes only should not find a range if nothing is selected.";
fcu->bezt[1].f2 |= SELECT;
fcu->bezt[3].f2 |= SELECT;
success = BKE_fcurve_calc_range(fcu, &min, &max, true);
EXPECT_TRUE(success) << "Range of selected keyframes should have been found.";
EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][0], min);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[1][0], max);
/* Curve samples. */
const int sample_start = 1;
const int sample_end = 20;
fcurve_store_samples(fcu, NULL, sample_start, sample_end, fcurve_samplingcb_evalcurve);
success = BKE_fcurve_calc_range(fcu, &min, &max, true);
EXPECT_TRUE(success) << "FCurve samples should have a range.";
EXPECT_FLOAT_EQ(sample_start, min);
EXPECT_FLOAT_EQ(sample_end, max);
BKE_fcurve_free(fcu);
}
TEST(BKE_fcurve, BKE_fcurve_calc_bounds)
{
FCurve *fcu = BKE_fcurve_create();
insert_vert_fcurve(fcu, 1.0f, 7.5f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 4.0f, -15.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 8.0f, 15.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 14.0f, 8.2f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
insert_vert_fcurve(fcu, 18.2f, -20.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
for (int i = 0; i < fcu->totvert; i++) {
fcu->bezt[i].f1 &= ~SELECT;
fcu->bezt[i].f2 &= ~SELECT;
fcu->bezt[i].f3 &= ~SELECT;
}
fcu->bezt[0].vec[0][0] = -5.0f;
fcu->bezt[4].vec[2][0] = 25.0f;
rctf bounds;
bool success;
/* All keys. */
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, false /* include handles */, NULL /* frame range */, &bounds);
EXPECT_TRUE(success) << "A non-empty FCurve should have bounds.";
EXPECT_FLOAT_EQ(fcu->bezt[0].vec[1][0], bounds.xmin);
EXPECT_FLOAT_EQ(fcu->bezt[4].vec[1][0], bounds.xmax);
EXPECT_FLOAT_EQ(fcu->bezt[4].vec[1][1], bounds.ymin);
EXPECT_FLOAT_EQ(fcu->bezt[2].vec[1][1], bounds.ymax);
/* Only selected. */
success = BKE_fcurve_calc_bounds(
fcu, true /* sel only */, false /* include handles */, NULL /* frame range */, &bounds);
EXPECT_FALSE(success)
<< "Using selected keyframes only should not find bounds if nothing is selected.";
fcu->bezt[1].f2 |= SELECT;
fcu->bezt[3].f2 |= SELECT;
success = BKE_fcurve_calc_bounds(
fcu, true /* sel only */, false /* include handles */, NULL /* frame range */, &bounds);
EXPECT_TRUE(success) << "Selected keys should have been found.";
EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][0], bounds.xmin);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[1][0], bounds.xmax);
EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][1], bounds.ymin);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[1][1], bounds.ymax);
/* Including handles. */
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, true /* include handles */, NULL /* frame range */, &bounds);
EXPECT_TRUE(success) << "A non-empty FCurve should have bounds including handles.";
EXPECT_FLOAT_EQ(fcu->bezt[0].vec[0][0], bounds.xmin);
EXPECT_FLOAT_EQ(fcu->bezt[4].vec[2][0], bounds.xmax);
EXPECT_FLOAT_EQ(fcu->bezt[4].vec[1][1], bounds.ymin);
EXPECT_FLOAT_EQ(fcu->bezt[2].vec[1][1], bounds.ymax);
/* Range. */
float range[2];
range[0] = 25;
range[1] = 30;
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
EXPECT_FALSE(success) << "A frame range outside the range of keyframes should not find bounds.";
range[0] = 0;
range[1] = 18.2f;
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
EXPECT_TRUE(success) << "A frame range within the range of keyframes should find bounds.";
EXPECT_FLOAT_EQ(fcu->bezt[0].vec[1][0], bounds.xmin);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[1][0], bounds.xmax);
EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][1], bounds.ymin);
EXPECT_FLOAT_EQ(fcu->bezt[2].vec[1][1], bounds.ymax);
/* Range and handles. */
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, true /* include handles */, range /* frame range */, &bounds);
EXPECT_TRUE(success)
<< "A frame range within the range of keyframes should find bounds with handles.";
EXPECT_FLOAT_EQ(fcu->bezt[0].vec[0][0], bounds.xmin);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[2][0], bounds.xmax);
EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][1], bounds.ymin);
EXPECT_FLOAT_EQ(fcu->bezt[2].vec[1][1], bounds.ymax);
/* Range, handles and only selection. */
range[0] = 8.0f;
range[1] = 18.2f;
success = BKE_fcurve_calc_bounds(
fcu, true /* sel only */, true /* include handles */, range /* frame range */, &bounds);
EXPECT_TRUE(success)
<< "A frame range within the range of keyframes should find bounds of selected keyframes.";
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[0][0], bounds.xmin);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[2][0], bounds.xmax);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[2][1], bounds.ymin);
EXPECT_FLOAT_EQ(fcu->bezt[3].vec[0][1], bounds.ymax);
/* Curve samples. */
const int sample_start = 1;
const int sample_end = 20;
fcurve_store_samples(fcu, NULL, sample_start, sample_end, fcurve_samplingcb_evalcurve);
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, false /* include handles */, NULL /* frame range */, &bounds);
EXPECT_TRUE(success) << "FCurve samples should have a range.";
EXPECT_FLOAT_EQ(sample_start, bounds.xmin);
EXPECT_FLOAT_EQ(sample_end, bounds.xmax);
EXPECT_FLOAT_EQ(-20.0f, bounds.ymin);
EXPECT_FLOAT_EQ(15.0f, bounds.ymax);
range[0] = 8.0f;
range[1] = 20.0f;
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
EXPECT_TRUE(success) << "FCurve samples should have a range.";
EXPECT_FLOAT_EQ(range[0], bounds.xmin);
EXPECT_FLOAT_EQ(range[1], bounds.xmax);
EXPECT_FLOAT_EQ(-20.0f, bounds.ymin);
EXPECT_FLOAT_EQ(15.0f, bounds.ymax);
range[0] = 20.1f;
range[1] = 30.0f;
success = BKE_fcurve_calc_bounds(
fcu, false /* sel only */, false /* include handles */, range /* frame range */, &bounds);
EXPECT_FALSE(success)
<< "A frame range outside the range of keyframe samples should not have bounds.";
BKE_fcurve_free(fcu);
}
} // namespace blender::bke::tests

View File

@ -3651,17 +3651,7 @@ static bool get_normalized_fcurve_bounds(FCurve *fcu,
rctf *r_bounds)
{
const bool fcu_selection_only = false;
const bool found_bounds = BKE_fcurve_calc_bounds(fcu,
&r_bounds->xmin,
&r_bounds->xmax,
&r_bounds->ymin,
&r_bounds->ymax,
fcu_selection_only,
include_handles,
range);
if (!found_bounds) {
return false;
}
BKE_fcurve_calc_bounds(fcu, fcu_selection_only, include_handles, range, r_bounds);
const short mapping_flag = ANIM_get_normalization_flags(ac);
@ -3736,8 +3726,8 @@ static void get_view_range(Scene *scene, const bool use_preview_range, float r_r
r_range[1] = scene->r.pefra;
}
else {
r_range[0] = -FLT_MAX;
r_range[1] = FLT_MAX;
r_range[0] = scene->r.sfra;
r_range[1] = scene->r.efra;
}
}
@ -3879,6 +3869,7 @@ static int graphkeys_channel_view_pick_invoke(bContext *C, wmOperator *op, const
float range[2];
const bool use_preview_range = RNA_boolean_get(op->ptr, "use_preview_range");
get_view_range(ac.scene, use_preview_range, range);
rctf bounds;

View File

@ -203,7 +203,7 @@ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const
float tmin, tmax;
/* get range and apply necessary scaling before processing */
if (BKE_fcurve_calc_range(fcu, &tmin, &tmax, onlySel, false)) {
if (BKE_fcurve_calc_range(fcu, &tmin, &tmax, onlySel)) {
if (adt) {
tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP);

View File

@ -632,7 +632,7 @@ static void draw_fcurve_curve(bAnimContext *ac,
if (!draw_extrapolation) {
float fcu_start = 0;
float fcu_end = 0;
BKE_fcurve_calc_range(fcu_, &fcu_start, &fcu_end, false, false);
BKE_fcurve_calc_range(fcu_, &fcu_start, &fcu_end, false);
fcu_start = BKE_nla_tweakedit_remap(adt, fcu_start, NLATIME_CONVERT_MAP);
fcu_end = BKE_nla_tweakedit_remap(adt, fcu_end, NLATIME_CONVERT_MAP);

View File

@ -85,40 +85,39 @@ void get_graph_keyframe_extents(bAnimContext *ac,
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
FCurve *fcu = (FCurve *)ale->key_data;
float txmin, txmax, tymin, tymax;
rctf bounds;
float unitFac, offset;
/* Get range. */
if (BKE_fcurve_calc_bounds(
fcu, &txmin, &txmax, &tymin, &tymax, do_sel_only, include_handles, NULL)) {
if (BKE_fcurve_calc_bounds(fcu, do_sel_only, include_handles, NULL, &bounds)) {
short mapping_flag = ANIM_get_normalization_flags(ac);
/* Apply NLA scaling. */
if (adt) {
txmin = BKE_nla_tweakedit_remap(adt, txmin, NLATIME_CONVERT_MAP);
txmax = BKE_nla_tweakedit_remap(adt, txmax, NLATIME_CONVERT_MAP);
bounds.xmin = BKE_nla_tweakedit_remap(adt, bounds.xmin, NLATIME_CONVERT_MAP);
bounds.xmax = BKE_nla_tweakedit_remap(adt, bounds.xmax, NLATIME_CONVERT_MAP);
}
/* Apply unit corrections. */
unitFac = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
tymin += offset;
tymax += offset;
tymin *= unitFac;
tymax *= unitFac;
bounds.ymin += offset;
bounds.ymax += offset;
bounds.ymin *= unitFac;
bounds.ymax *= unitFac;
/* Try to set cur using these values, if they're more extreme than previously set values.
*/
if ((xmin) && (txmin < *xmin)) {
*xmin = txmin;
if ((xmin) && (bounds.xmin < *xmin)) {
*xmin = bounds.xmin;
}
if ((xmax) && (txmax > *xmax)) {
*xmax = txmax;
if ((xmax) && (bounds.xmax > *xmax)) {
*xmax = bounds.xmax;
}
if ((ymin) && (tymin < *ymin)) {
*ymin = tymin;
if ((ymin) && (bounds.ymin < *ymin)) {
*ymin = bounds.ymin;
}
if ((ymax) && (tymax > *ymax)) {
*ymax = tymax;
if ((ymax) && (bounds.ymax > *ymax)) {
*ymax = bounds.ymax;
}
foundBounds = true;

View File

@ -600,7 +600,7 @@ static void rna_FCurve_group_set(PointerRNA *ptr,
/* calculate time extents of F-Curve */
static void rna_FCurve_range(FCurve *fcu, float range[2])
{
BKE_fcurve_calc_range(fcu, range, range + 1, false, false);
BKE_fcurve_calc_range(fcu, range, range + 1, false);
}
static bool rna_FCurve_is_empty_get(PointerRNA *ptr)