|
|
|
@ -491,6 +491,557 @@ void ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
float s_curve(float x, float slope, float width, float height, float xshift, float yshift) {
|
|
|
|
|
/* Formula for 'S' curve we use for the "ease" sliders. The shift values move the curve vertiacly or horizontaly.
|
|
|
|
|
* The range of the curve used is from 0 to 1 on "x" and "y" so we can scale it (width and height) and move it (xshift and y yshift)
|
|
|
|
|
* to crop the part of the curve we need. Slope determins how curvy the shape is */
|
|
|
|
|
float curve = height * pow((x - xshift), slope) / (pow((x - xshift), slope) + pow((width - (x - xshift)), slope)) + yshift;
|
|
|
|
|
|
|
|
|
|
/* The curve has some noise beyond our margins so we clamp the values */
|
|
|
|
|
if (x > xshift + width) {
|
|
|
|
|
curve = height + yshift;
|
|
|
|
|
} else if (x < xshift) {
|
|
|
|
|
curve = yshift;
|
|
|
|
|
}
|
|
|
|
|
return curve;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ease_ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float long_factor = factor * 2 - 1;
|
|
|
|
|
|
|
|
|
|
/* this values use the entire curve to get the "S" shape. The value 2.0 on the slope makes it a bit sharper. */
|
|
|
|
|
float slope = 2.0;
|
|
|
|
|
float width = 1.0;
|
|
|
|
|
float height = 1.0;
|
|
|
|
|
float yshift = 0.0;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
/* For easy calculation of the curve, the values are normalized. */
|
|
|
|
|
const float normalized_x = (fcu->bezt[i].vec[1][0] - left_key->vec[1][0]) / key_x_range;
|
|
|
|
|
|
|
|
|
|
/* Using the factor on the xshift we are basicaly moving the curve horizontaly. */
|
|
|
|
|
float ease = s_curve(normalized_x, slope, width, height, -long_factor, yshift);
|
|
|
|
|
|
|
|
|
|
/* The ease variable basicaly as a mask to molde the shape of the curve. */
|
|
|
|
|
const float key_y_value = left_key->vec[1][1] + key_y_range * ease;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void ease_b_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The calculation needs diferent values for each side of the slider. */
|
|
|
|
|
const bool slider_right_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) * 5;
|
|
|
|
|
|
|
|
|
|
/* by duplicating the size of the curve we get only half of the "S" shape (kind of a "C" shape). */
|
|
|
|
|
float width = 2.0;
|
|
|
|
|
float height = 2.0;
|
|
|
|
|
float xshift = 0.0;
|
|
|
|
|
float yshift = 0.0;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
/* For easy calculation of the curve, the values are normalized. */
|
|
|
|
|
const float normalized_x = (fcu->bezt[i].vec[1][0] - left_key->vec[1][0]) / key_x_range;
|
|
|
|
|
|
|
|
|
|
/* for values on the right side of the slider we need the other half of the "S" shape. */
|
|
|
|
|
if (slider_right_side) {
|
|
|
|
|
xshift = -1.0;
|
|
|
|
|
yshift = -1.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We use the factor for affect the slope of the the "C" shape. */
|
|
|
|
|
float ease = s_curve(normalized_x, ping_pong_factor, width, height, xshift, yshift);
|
|
|
|
|
|
|
|
|
|
const float key_y_value = left_key->vec[1][1] + key_y_range * ease;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void blend_ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The calculation needs diferent values for each side of the slider. */
|
|
|
|
|
const bool slider_right_side = factor > 0.5;
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float long_factor = factor * 2 - 1;
|
|
|
|
|
|
|
|
|
|
float y_delta = 0;
|
|
|
|
|
float base = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
/* For easy calculation of the curve, the values are normalized. */
|
|
|
|
|
const float normalized_x = (fcu->bezt[i].vec[1][0] - left_key->vec[1][0]) / key_x_range;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (slider_right_side) {
|
|
|
|
|
float ease = s_curve(normalized_x, 3, 2.0, 2.0, -1.0, -1.0);
|
|
|
|
|
base = left_key->vec[1][1] + key_y_range * ease;
|
|
|
|
|
y_delta = base - fcu->bezt[i].vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
float ease = s_curve(normalized_x, 3, 2.0, 2.0, 0.0, 0.0);
|
|
|
|
|
base = left_key->vec[1][1] + key_y_range * ease;
|
|
|
|
|
y_delta = fcu->bezt[i].vec[1][1] - base;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + y_delta * long_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void blend_neighbor_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The calculation needs diferent values for each side of the slider. */
|
|
|
|
|
const bool slider_right_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);
|
|
|
|
|
|
|
|
|
|
float y_delta = 0;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
|
|
|
|
|
if (slider_right_side) {
|
|
|
|
|
y_delta = right_key->vec[1][1] - fcu->bezt[i].vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
y_delta = left_key->vec[1][1] - fcu->bezt[i].vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + y_delta * ping_pong_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void blend_infinity_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
/* We need the one key on the outside side of the neighboring keys 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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
|
float x_delta = 0;
|
|
|
|
|
float y_delta = 0;
|
|
|
|
|
|
|
|
|
|
/* this delta values are used to know the relationship between the bookend keys and the reference keys beyong those. */
|
|
|
|
|
if(slider_right_side){
|
|
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
else if(slider_left_side){
|
|
|
|
|
y_delta = beyond_left_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
x_delta = beyond_left_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
y_delta = 1;
|
|
|
|
|
x_delta = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
|
|
|
|
|
float new_x_delta = 0;
|
|
|
|
|
float new_y_delta = 0;
|
|
|
|
|
float refe = 0;
|
|
|
|
|
|
|
|
|
|
/* This new deltas are used to determin the relationship between the current key and the bookend ones. */
|
|
|
|
|
if (slider_right_side) {
|
|
|
|
|
new_x_delta = fcu->bezt[i].vec[1][0] - right_key->vec[1][0];
|
|
|
|
|
refe = right_key->vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
new_x_delta = fcu->bezt[i].vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
refe = left_key->vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float delta = refe + 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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void blend_offset_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const BezTriple *segment_first_key = fcurve_segment_start_get(fcu, segment->start_index + 1);
|
|
|
|
|
const BezTriple *segment_last_key = fcurve_segment_end_get(fcu, segment->start_index + segment->length - 1);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The calculation needs diferent values for each side of the slider. */
|
|
|
|
|
const bool slider_right_side = factor > 0.5;
|
|
|
|
|
|
|
|
|
|
/* For this tool the calculations are made easier if each side of the slider goes from 0 to porisive 1. */
|
|
|
|
|
const float ping_pong_factor = fabs(factor * 2 - 1);
|
|
|
|
|
|
|
|
|
|
float y_delta = 0;
|
|
|
|
|
|
|
|
|
|
if (slider_right_side) {
|
|
|
|
|
y_delta = right_key->vec[1][1] - segment_last_key->vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
y_delta = left_key->vec[1][1] - segment_first_key->vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + y_delta * ping_pong_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void time_offset_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float long_factor = factor * 2 - 1;
|
|
|
|
|
|
|
|
|
|
/* We need the two bookend keys of the fcurve to be able to cycle the values. */
|
|
|
|
|
const BezTriple *last_key = &fcu->bezt[fcu->totvert - 1];
|
|
|
|
|
const BezTriple *first_key = &fcu->bezt[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int fcu_x_range = last_key->vec[1][0] - first_key->vec[1][0];
|
|
|
|
|
float delta_y;
|
|
|
|
|
|
|
|
|
|
/* If we operate directly on the fcurve there will be a feedback loop
|
|
|
|
|
* so we need to capture the "y" values on an array to then apply them on a second loop*/
|
|
|
|
|
float y_values[segment->length];
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
|
|
|
|
|
/* This simulates the fcu curve moving in time. */
|
|
|
|
|
float time = fcu->bezt[i].vec[1][0] + fcu_x_range * long_factor;
|
|
|
|
|
|
|
|
|
|
/* The values need to go back to the ones at the other end of the fcurve
|
|
|
|
|
* every time we get to the last or the first key. */
|
|
|
|
|
if(time > last_key->vec[1][0]){
|
|
|
|
|
int offset_frame = fcu->bezt[i].vec[1][0] - fcu_x_range;
|
|
|
|
|
time = offset_frame + fcu_x_range * long_factor;
|
|
|
|
|
delta_y = last_key->vec[1][1] - first_key->vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
else if(time < first_key->vec[1][0]){
|
|
|
|
|
int offset_frame = fcu->bezt[i].vec[1][0] + fcu_x_range;
|
|
|
|
|
time = offset_frame + fcu_x_range * long_factor;
|
|
|
|
|
delta_y = first_key->vec[1][1] - last_key->vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
delta_y = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const float key_y_value = evaluate_fcurve(fcu, time) + delta_y;
|
|
|
|
|
int index_from_zero = i-segment->start_index;
|
|
|
|
|
y_values[index_from_zero] = key_y_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++){
|
|
|
|
|
int index_from_zero = i-segment->start_index;
|
|
|
|
|
move_key(&fcu->bezt[i], y_values[index_from_zero]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void shear_left_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float long_factor = factor * 2 - 1;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
/* For easy calculation of the curve, the values are normalized. */
|
|
|
|
|
const float normalized_x = (fcu->bezt[i].vec[1][0] - left_key->vec[1][0]) / key_x_range;
|
|
|
|
|
|
|
|
|
|
const float lineal = key_y_range * normalized_x;
|
|
|
|
|
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + lineal * long_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void shear_right_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float long_factor = factor * 2 - 1;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
/* For easy calculation of the curve, the values are normalized. */
|
|
|
|
|
const float normalized_x = (right_key->vec[1][0] - fcu->bezt[i].vec[1][0]) / key_x_range;
|
|
|
|
|
|
|
|
|
|
const float lineal = key_y_range * normalized_x;
|
|
|
|
|
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + lineal * long_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void tween_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
const float key_y_value = left_key->vec[1][1] + key_y_range * factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void push_pull_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
const float key_y_range = right_key->vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
/* For easy calculation of the curve, the values are normalized. */
|
|
|
|
|
const float normalized_x = (fcu->bezt[i].vec[1][0] - left_key->vec[1][0]) / key_x_range;
|
|
|
|
|
|
|
|
|
|
const float lineal = left_key->vec[1][1] + key_y_range * normalized_x;
|
|
|
|
|
|
|
|
|
|
const float delta = fcu->bezt[i].vec[1][1] - lineal;
|
|
|
|
|
|
|
|
|
|
/* We multiply the factor by 2 just to increase the effect. */
|
|
|
|
|
const float key_y_value = lineal + delta * factor * 2;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void scale_left_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float long_factor = factor * 2 - 1;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
const float delta = fcu->bezt[i].vec[1][1] - left_key->vec[1][1];
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + delta * long_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void scale_right_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float long_factor = factor * 2 - 1;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
const float delta = fcu->bezt[i].vec[1][1] - right_key->vec[1][1];
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + delta * long_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void scale_average_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const float key_x_range = right_key->vec[1][0] - left_key->vec[1][0];
|
|
|
|
|
|
|
|
|
|
/* Happens if there is only 1 key on the FCurve. Needs to be skipped because it
|
|
|
|
|
* would be a divide by 0. */
|
|
|
|
|
if (IS_EQF(key_x_range, 0.0f)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The factor goes from 0 to 1, but for this tool it needs to go from -1 to 1. */
|
|
|
|
|
const float mirrored_factor = factor * 2 - 1;
|
|
|
|
|
float y = 0;
|
|
|
|
|
|
|
|
|
|
/* We firt find the average of the y values to then use it in the final calculation. */
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
y = y + fcu->bezt[i].vec[1][1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float y_average = y/segment->length;
|
|
|
|
|
|
|
|
|
|
for (int i = segment->start_index; i < segment->start_index + segment->length; i++) {
|
|
|
|
|
const float delta = fcu->bezt[i].vec[1][1] - y_average;
|
|
|
|
|
const float key_y_value = fcu->bezt[i].vec[1][1] + delta * mirrored_factor;
|
|
|
|
|
move_key(&fcu->bezt[i], key_y_value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- */
|
|
|
|
|
|
|
|
|
|
void breakdown_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
|
|
|
|
|
{
|
|
|
|
|
const BezTriple *left_bezt = fcurve_segment_start_get(fcu, segment->start_index);
|
|
|
|
|