WIP: Animation&Rigging: Extra operators for the sliders #106281

Closed
AresDeveaux wants to merge 6 commits from AresDeveaux/blender:animaide into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 1982 additions and 3 deletions

View File

@ -326,11 +326,25 @@ class GRAPH_MT_slider(Menu):
def draw(self, _context):
layout = self.layout
layout.operator_context = "INVOKE_DEFAULT"
layout.operator("graph.breakdown", text="Breakdown")
layout.operator("graph.blend_ease", text="Blend to Ease")
layout.operator("graph.blend_to_neighbor", text="Blend to Neighbor")
layout.operator("graph.blend_to_default", text="Blend to Default Value")
layout.operator("graph.blend_infinity", text="Blend to Infinity")
layout.operator("graph.blend_offset", text="Blend Offset")
layout.separator()
layout.operator("graph.ease", text="Ease")
layout.operator("graph.gaussian_smooth", text="Smooth")
layout.operator("graph.ease_ease", text="Ease Ease")
layout.separator()
layout.operator("graph.scale_left", text="Scale Left")
layout.operator("graph.scale_right", text="Scale Right")
layout.operator("graph.scale_average", text="Scale Average")
layout.separator()
layout.operator("graph.shear_left", text="Shear Left")
layout.operator("graph.shear_right", text="Shear Right")
layout.separator()
layout.operator("graph.push_pull", text="Push Pull")
layout.operator("graph.time_offset", text="Time Offset")
layout.operator("graph.breakdown", text="Breakdown")
class GRAPH_MT_view_pie(Menu):

View File

@ -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);

View File

@ -437,6 +437,21 @@ void smooth_fcurve_segment(struct FCurve *fcu,
int kernel_size,
double *kernel);
void ease_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
float s_curve(float x, float slope, float width, float height, float xshift, float yshift);
void ease_ease_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void ease_b_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void blend_ease_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void blend_neighbor_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void blend_infinity_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void blend_offset_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void time_offset_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void tween_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void push_pull_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void shear_left_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void shear_right_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void scale_left_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void scale_right_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
void scale_average_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
bool decimate_fcurve(struct bAnimListElem *ale, float remove_ratio, float error_sq_max);
void blend_to_default_fcurve(struct PointerRNA *id_ptr, struct FCurve *fcu, float factor);
/**

View File

@ -114,6 +114,17 @@ void GRAPH_OT_clean(struct wmOperatorType *ot);
void GRAPH_OT_blend_to_neighbor(struct wmOperatorType *ot);
void GRAPH_OT_breakdown(struct wmOperatorType *ot);
void GRAPH_OT_ease(struct wmOperatorType *ot);
void GRAPH_OT_ease_ease(struct wmOperatorType *ot);
void GRAPH_OT_push_pull(struct wmOperatorType *ot);
void GRAPH_OT_scale_left(struct wmOperatorType *ot);
void GRAPH_OT_scale_right(struct wmOperatorType *ot);
void GRAPH_OT_scale_average(struct wmOperatorType *ot);
void GRAPH_OT_blend_ease(struct wmOperatorType *ot);
void GRAPH_OT_blend_offset(struct wmOperatorType *ot);
void GRAPH_OT_shear_left(struct wmOperatorType *ot);
void GRAPH_OT_shear_right(struct wmOperatorType *ot);
void GRAPH_OT_blend_infinity(struct wmOperatorType *ot);
void GRAPH_OT_time_offset(struct wmOperatorType *ot);
void GRAPH_OT_decimate(struct wmOperatorType *ot);
void GRAPH_OT_blend_to_default(struct wmOperatorType *ot);
void GRAPH_OT_gaussian_smooth(struct wmOperatorType *ot);

View File

@ -465,6 +465,17 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_ease);
WM_operatortype_append(GRAPH_OT_blend_to_default);
WM_operatortype_append(GRAPH_OT_gaussian_smooth);
WM_operatortype_append(GRAPH_OT_ease_ease);
WM_operatortype_append(GRAPH_OT_push_pull);
WM_operatortype_append(GRAPH_OT_scale_left);
WM_operatortype_append(GRAPH_OT_scale_right);
WM_operatortype_append(GRAPH_OT_scale_average);
WM_operatortype_append(GRAPH_OT_blend_ease);
WM_operatortype_append(GRAPH_OT_blend_offset);
WM_operatortype_append(GRAPH_OT_shear_left);
WM_operatortype_append(GRAPH_OT_shear_right);
WM_operatortype_append(GRAPH_OT_blend_infinity);
WM_operatortype_append(GRAPH_OT_time_offset);
WM_operatortype_append(GRAPH_OT_euler_filter);
WM_operatortype_append(GRAPH_OT_delete);
WM_operatortype_append(GRAPH_OT_duplicate);

File diff suppressed because it is too large Load Diff

View File

@ -122,7 +122,7 @@ typedef struct ModifierData {
void *runtime;
} ModifierData;
typedef enum {
typedef enum {
/** This modifier has been inserted in local override, and hence can be fully edited. */
eModifierFlag_OverrideLibrary_Local = (1 << 0),
/** This modifier does not own its caches, but instead shares them with another modifier. */