Compare commits
4 Commits
geometry-n
...
temp-angav
Author | SHA1 | Date | |
---|---|---|---|
efb558fc8b | |||
dfc187d411 | |||
de27f054af | |||
bd66965f31 |
@@ -97,6 +97,8 @@ class TIME_HT_header(Header):
|
|||||||
row.operator("anim.keyframe_insert", text="", icon='KEY_HLT')
|
row.operator("anim.keyframe_insert", text="", icon='KEY_HLT')
|
||||||
row.operator("anim.keyframe_delete", text="", icon='KEY_DEHLT')
|
row.operator("anim.keyframe_delete", text="", icon='KEY_DEHLT')
|
||||||
|
|
||||||
|
layout.prop(toolsettings, "use_keyframe_cycle_aware", text="", toggle=True)
|
||||||
|
|
||||||
|
|
||||||
class TIME_MT_editor_menus(Menu):
|
class TIME_MT_editor_menus(Menu):
|
||||||
bl_idname = "TIME_MT_editor_menus"
|
bl_idname = "TIME_MT_editor_menus"
|
||||||
|
@@ -269,6 +269,14 @@ bool BKE_fcurve_is_protected(struct FCurve *fcu);
|
|||||||
/* The curve is an infinite cycle via Cycles modifier */
|
/* The curve is an infinite cycle via Cycles modifier */
|
||||||
bool BKE_fcurve_is_cyclic(struct FCurve *fcu);
|
bool BKE_fcurve_is_cyclic(struct FCurve *fcu);
|
||||||
|
|
||||||
|
typedef enum eFCU_Cycle_Type {
|
||||||
|
FCU_CYCLE_NONE = 0,
|
||||||
|
FCU_CYCLE_PERFECT,
|
||||||
|
FCU_CYCLE_OFFSET
|
||||||
|
} eFCU_Cycle_Type;
|
||||||
|
|
||||||
|
eFCU_Cycle_Type BKE_fcurve_get_cycle_type(struct FCurve *fcu);
|
||||||
|
|
||||||
/* -------- Curve Sanity -------- */
|
/* -------- Curve Sanity -------- */
|
||||||
|
|
||||||
void calchandles_fcurve(struct FCurve *fcu);
|
void calchandles_fcurve(struct FCurve *fcu);
|
||||||
@@ -278,6 +286,14 @@ short test_time_fcurve(struct FCurve *fcu);
|
|||||||
|
|
||||||
void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]);
|
void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]);
|
||||||
|
|
||||||
|
/* Adjust bezier handles as bezt is being inserted between prev and next.
|
||||||
|
* - pdelta: outputs Y difference between bezt and old curve value at its X position.
|
||||||
|
*/
|
||||||
|
bool BKE_bezt_subdivide_handles(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, float *pdelta);
|
||||||
|
|
||||||
|
/* Try to revert prev & next handle adjustment performed by subdivide_handles. */
|
||||||
|
bool BKE_bezt_unsubdivide_handles(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next);
|
||||||
|
|
||||||
/* -------- Evaluation -------- */
|
/* -------- Evaluation -------- */
|
||||||
|
|
||||||
/* evaluate fcurve */
|
/* evaluate fcurve */
|
||||||
|
@@ -883,24 +883,37 @@ void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSample
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Checks if the F-Curve has a Cycles modifier with simple settings that warrant transition smoothing */
|
/* Checks if the F-Curve has a Cycles modifier with simple settings that warrant transition smoothing */
|
||||||
bool BKE_fcurve_is_cyclic(FCurve *fcu)
|
eFCU_Cycle_Type BKE_fcurve_get_cycle_type(FCurve *fcu)
|
||||||
{
|
{
|
||||||
FModifier *fcm = fcu->modifiers.first;
|
FModifier *fcm = fcu->modifiers.first;
|
||||||
|
|
||||||
if (!fcm || fcm->type != FMODIFIER_TYPE_CYCLES)
|
if (!fcm || fcm->type != FMODIFIER_TYPE_CYCLES)
|
||||||
return false;
|
return FCU_CYCLE_NONE;
|
||||||
|
|
||||||
if (fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED))
|
if (fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED))
|
||||||
return false;
|
return FCU_CYCLE_NONE;
|
||||||
|
|
||||||
if (fcm->flag & (FMODIFIER_FLAG_RANGERESTRICT | FMODIFIER_FLAG_USEINFLUENCE))
|
if (fcm->flag & (FMODIFIER_FLAG_RANGERESTRICT | FMODIFIER_FLAG_USEINFLUENCE))
|
||||||
return false;
|
return FCU_CYCLE_NONE;
|
||||||
|
|
||||||
FMod_Cycles *data = (FMod_Cycles *)fcm->data;
|
FMod_Cycles *data = (FMod_Cycles *)fcm->data;
|
||||||
|
|
||||||
return data && data->after_cycles == 0 && data->before_cycles == 0 &&
|
if (data && data->after_cycles == 0 && data->before_cycles == 0)
|
||||||
ELEM(data->before_mode, FCM_EXTRAPOLATE_CYCLIC, FCM_EXTRAPOLATE_CYCLIC_OFFSET) &&
|
{
|
||||||
ELEM(data->after_mode, FCM_EXTRAPOLATE_CYCLIC, FCM_EXTRAPOLATE_CYCLIC_OFFSET);
|
if (data->before_mode == FCM_EXTRAPOLATE_CYCLIC && data->after_mode == FCM_EXTRAPOLATE_CYCLIC)
|
||||||
|
return FCU_CYCLE_PERFECT;
|
||||||
|
|
||||||
|
if (ELEM(data->before_mode, FCM_EXTRAPOLATE_CYCLIC, FCM_EXTRAPOLATE_CYCLIC_OFFSET) &&
|
||||||
|
ELEM(data->after_mode, FCM_EXTRAPOLATE_CYCLIC, FCM_EXTRAPOLATE_CYCLIC_OFFSET))
|
||||||
|
return FCU_CYCLE_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FCU_CYCLE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BKE_fcurve_is_cyclic(FCurve *fcu)
|
||||||
|
{
|
||||||
|
return BKE_fcurve_get_cycle_type(fcu) != FCU_CYCLE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Shifts 'in' by the difference in coordinates between 'to' and 'from', using 'out' as the output buffer.
|
/* Shifts 'in' by the difference in coordinates between 'to' and 'from', using 'out' as the output buffer.
|
||||||
@@ -2076,17 +2089,12 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find root ('zero') */
|
/* find roots of cubic equation */
|
||||||
static int findzero(float x, float q0, float q1, float q2, float q3, float *o)
|
static int solve_cubic(float c0, float c1, float c2, float c3, float *o)
|
||||||
{
|
{
|
||||||
double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
|
double a, b, c, p, q, d, t, phi;
|
||||||
int nr = 0;
|
int nr = 0;
|
||||||
|
|
||||||
c0 = q0 - x;
|
|
||||||
c1 = 3.0f * (q1 - q0);
|
|
||||||
c2 = 3.0f * (q0 - 2.0f * q1 + q2);
|
|
||||||
c3 = q3 - q0 + 3.0f * (q1 - q2);
|
|
||||||
|
|
||||||
if (c3 != 0.0) {
|
if (c3 != 0.0) {
|
||||||
a = c2 / c3;
|
a = c2 / c3;
|
||||||
b = c1 / c3;
|
b = c1 / c3;
|
||||||
@@ -2171,6 +2179,19 @@ static int findzero(float x, float q0, float q1, float q2, float q3, float *o)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find root ('zero') */
|
||||||
|
static int findzero(float x, float q0, float q1, float q2, float q3, float *o)
|
||||||
|
{
|
||||||
|
double c0, c1, c2, c3;
|
||||||
|
|
||||||
|
c0 = q0 - x;
|
||||||
|
c1 = 3.0f * (q1 - q0);
|
||||||
|
c2 = 3.0f * (q0 - 2.0f * q1 + q2);
|
||||||
|
c3 = q3 - q0 + 3.0f * (q1 - q2);
|
||||||
|
|
||||||
|
return solve_cubic(c0, c1, c2, c3, o);
|
||||||
|
}
|
||||||
|
|
||||||
static void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
|
static void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
|
||||||
{
|
{
|
||||||
float t, c0, c1, c2, c3;
|
float t, c0, c1, c2, c3;
|
||||||
@@ -2205,6 +2226,104 @@ static void berekenx(float *f, float *o, int b)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* recompute handles to neatly subdivide the prev-next range at bezt */
|
||||||
|
bool BKE_bezt_subdivide_handles(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, float *pdelta)
|
||||||
|
{
|
||||||
|
float *P0 = prev->vec[1], *P1 = prev->vec[2], *P2 = next->vec[0], *P3 = next->vec[1];
|
||||||
|
float *ML = bezt->vec[0], *MM = bezt->vec[1], *MR = bezt->vec[2];
|
||||||
|
|
||||||
|
if (MM[0] <= P0[0] || MM[0] >= P3[0])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* find bezier parameter */
|
||||||
|
correct_bezpart(P0, P1, P2, P3);
|
||||||
|
|
||||||
|
float keys[4];
|
||||||
|
|
||||||
|
if (!findzero(MM[0], P0[0], P1[0], P2[0], P3[0], keys))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float t = keys[0];
|
||||||
|
|
||||||
|
if (t <= 0.0f || t >= 1.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* de-Casteljau split */
|
||||||
|
float M1[3][2], M2[2][2], M3[2], D[2];
|
||||||
|
|
||||||
|
interp_v2_v2v2(M1[0], P0, P1, t);
|
||||||
|
interp_v2_v2v2(M1[1], P1, P2, t);
|
||||||
|
interp_v2_v2v2(M1[2], P2, P3, t);
|
||||||
|
interp_v2_v2v2(M2[0], M1[0], M1[1], t);
|
||||||
|
interp_v2_v2v2(M2[1], M1[1], M1[2], t);
|
||||||
|
interp_v2_v2v2(M3, M2[0], M2[1], t);
|
||||||
|
|
||||||
|
/* overwrite the handles */
|
||||||
|
copy_v2_v2(P1, M1[0]);
|
||||||
|
copy_v2_v2(P2, M1[2]);
|
||||||
|
|
||||||
|
sub_v2_v2v2(D, MM, M3);
|
||||||
|
add_v2_v2v2(ML, M2[0], D);
|
||||||
|
add_v2_v2v2(MR, M2[1], D);
|
||||||
|
|
||||||
|
*pdelta = D[1];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to restore handles before deletion of bezt */
|
||||||
|
bool BKE_bezt_unsubdivide_handles(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next)
|
||||||
|
{
|
||||||
|
float *P0 = prev->vec[1], *P1 = prev->vec[2], *P2 = next->vec[0], *P3 = next->vec[1];
|
||||||
|
float *ML = bezt->vec[0], *MM = bezt->vec[1], *MR = bezt->vec[2];
|
||||||
|
|
||||||
|
if (MM[0] <= P0[0] || MM[0] >= P3[0])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Solve equation to undo P1 & P2 rescaling, assuming basically that
|
||||||
|
* prev and next were adjusted by BKE_bezt_subdivide_handles before.
|
||||||
|
* The equation tries to find t that was used at that time.
|
||||||
|
*/
|
||||||
|
correct_bezpart(P0, P1, ML, MM);
|
||||||
|
correct_bezpart(MM, MR, P2, P3);
|
||||||
|
|
||||||
|
float c0, c1, c2, c3, keys[4];
|
||||||
|
|
||||||
|
c0 = 3.0f * P1[0] - 2.0f * P0[0] - MM[0];
|
||||||
|
c1 = 6.0f * (P0[0] - P1[0]);
|
||||||
|
c2 = 3.0f * (P1[0] + P2[0]) - 6.0f * P0[0];
|
||||||
|
c3 = 2.0f * (P0[0] - P3[0]);
|
||||||
|
|
||||||
|
float t, tx = (MM[0] - P0[0]) / (P3[0] - P0[0]);
|
||||||
|
|
||||||
|
int n = solve_cubic(c0, c1, c2, c3, keys);
|
||||||
|
|
||||||
|
if (n < 1) {
|
||||||
|
/* if the equation failed, just use the X coordinate ratio */
|
||||||
|
t = tx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* find the best solution given by the equation */
|
||||||
|
t = keys[0];
|
||||||
|
|
||||||
|
for (int i = 1; i < n; i++)
|
||||||
|
if (fabsf(keys[i] - tx) < fabsf(t - tx))
|
||||||
|
t = keys[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t <= 0.0f || t >= 1.0f)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* rescale handles */
|
||||||
|
float tmp[2];
|
||||||
|
|
||||||
|
sub_v2_v2v2(tmp, P1, P0);
|
||||||
|
madd_v2_v2v2fl(P1, P0, tmp, 1.0f / t);
|
||||||
|
|
||||||
|
sub_v2_v2v2(tmp, P2, P3);
|
||||||
|
madd_v2_v2v2fl(P2, P3, tmp, 1.0f / (1.0f - t));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------- */
|
/* -------------------------- */
|
||||||
|
|
||||||
|
@@ -99,6 +99,29 @@ static short compare_ak_bezt(void *node, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static eKeyframeInterpolationDrawOpts bezt_interpolation_type(BezTriple *bezt)
|
||||||
|
{
|
||||||
|
switch (bezt->ipo)
|
||||||
|
{
|
||||||
|
case BEZT_IPO_CONST:
|
||||||
|
return KEYFRAME_IPOTYPE_CONST;
|
||||||
|
case BEZT_IPO_LIN:
|
||||||
|
return KEYFRAME_IPOTYPE_LINEAR;
|
||||||
|
case BEZT_IPO_BEZ:
|
||||||
|
if (bezt->h1 == HD_AUTO_ANIM && bezt->h2 == HD_AUTO_ANIM)
|
||||||
|
return KEYFRAME_IPOTYPE_BEZ_AUTO_CLAMP;
|
||||||
|
else if (ELEM(bezt->h1, HD_AUTO_ANIM, HD_AUTO) && ELEM(bezt->h2, HD_AUTO_ANIM, HD_AUTO))
|
||||||
|
return KEYFRAME_IPOTYPE_BEZ_AUTO;
|
||||||
|
else if (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT)
|
||||||
|
return KEYFRAME_IPOTYPE_BEZ_VECTOR;
|
||||||
|
else
|
||||||
|
return KEYFRAME_IPOTYPE_BEZ_MANUAL;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return KEYFRAME_IPOTYPE_EASING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* New node callback used for building ActKeyColumns from BezTriples */
|
/* New node callback used for building ActKeyColumns from BezTriples */
|
||||||
static DLRBT_Node *nalloc_ak_bezt(void *data)
|
static DLRBT_Node *nalloc_ak_bezt(void *data)
|
||||||
{
|
{
|
||||||
@@ -109,6 +132,7 @@ static DLRBT_Node *nalloc_ak_bezt(void *data)
|
|||||||
ak->cfra = bezt->vec[1][0];
|
ak->cfra = bezt->vec[1][0];
|
||||||
ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
|
ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
|
||||||
ak->key_type = BEZKEYTYPE(bezt);
|
ak->key_type = BEZKEYTYPE(bezt);
|
||||||
|
ak->ipo_type = bezt_interpolation_type(bezt);
|
||||||
|
|
||||||
/* set 'modified', since this is used to identify long keyframes */
|
/* set 'modified', since this is used to identify long keyframes */
|
||||||
ak->modified = 1;
|
ak->modified = 1;
|
||||||
@@ -129,6 +153,8 @@ static void nupdate_ak_bezt(void *node, void *data)
|
|||||||
/* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
|
/* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
|
||||||
if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
|
if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
|
||||||
ak->key_type = BEZT_KEYTYPE_KEYFRAME;
|
ak->key_type = BEZT_KEYTYPE_KEYFRAME;
|
||||||
|
|
||||||
|
ak->ipo_type = MAX2(ak->ipo_type, bezt_interpolation_type(bezt));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ......... */
|
/* ......... */
|
||||||
@@ -471,8 +497,99 @@ static const float _unit_diamond_shape[4][2] = {
|
|||||||
{-1.0f, 0.0f} /* mid-left */
|
{-1.0f, 0.0f} /* mid-left */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const float _unit_mini_diamond_shape[4][2] = {
|
||||||
|
{0.0f, 0.1f}, /* top vert */
|
||||||
|
{0.1f, 0.0f}, /* mid-right */
|
||||||
|
{0.0f, -0.1f}, /* bottom vert */
|
||||||
|
{-0.1f, 0.0f} /* mid-left */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const float _unit_ipo_top_left[2] = {-0.5f, 0.5f};
|
||||||
|
static const float _unit_ipo_top_right[2] = {0.5f, 0.5f};
|
||||||
|
static const float _unit_ipo_bottom_left[2] = {-0.5f, -0.5f};
|
||||||
|
static const float _unit_ipo_bottom_right[2] = {0.5f, -0.5f};
|
||||||
|
static const float _unit_ipo_middle[2] = {0.0f, 0.0f};
|
||||||
|
|
||||||
|
static void draw_ipo_type(short ipo_type)
|
||||||
|
{
|
||||||
|
static GLuint ipo_disps[10] = { 0 };
|
||||||
|
|
||||||
|
if (ipo_type == KEYFRAME_IPOTYPE_NONE || ipo_type == KEYFRAME_IPOTYPE_BEZ_AUTO_CLAMP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ipo_disps[ipo_type] == 0) {
|
||||||
|
ipo_disps[ipo_type] = glGenLists(1);
|
||||||
|
glNewList(ipo_disps[ipo_type], GL_COMPILE);
|
||||||
|
|
||||||
|
switch (ipo_type) {
|
||||||
|
case KEYFRAME_IPOTYPE_CONST: // <|>
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2fv(_unit_diamond_shape[0]);
|
||||||
|
glVertex2fv(_unit_diamond_shape[2]);
|
||||||
|
glEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYFRAME_IPOTYPE_LINEAR: // <->
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2fv(_unit_diamond_shape[1]);
|
||||||
|
glVertex2fv(_unit_diamond_shape[3]);
|
||||||
|
glEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYFRAME_IPOTYPE_EASING: // <+>
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2fv(_unit_diamond_shape[0]);
|
||||||
|
glVertex2fv(_unit_diamond_shape[2]);
|
||||||
|
glVertex2fv(_unit_diamond_shape[1]);
|
||||||
|
glVertex2fv(_unit_diamond_shape[3]);
|
||||||
|
glEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYFRAME_IPOTYPE_BEZ_AUTO: // <.>
|
||||||
|
glBegin(GL_LINE_LOOP);
|
||||||
|
glVertex2fv(_unit_mini_diamond_shape[0]);
|
||||||
|
glVertex2fv(_unit_mini_diamond_shape[1]);
|
||||||
|
glVertex2fv(_unit_mini_diamond_shape[2]);
|
||||||
|
glVertex2fv(_unit_mini_diamond_shape[3]);
|
||||||
|
glEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*case KEYFRAME_IPOTYPE_BEZ_AUTO: // </>
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2fv(_unit_ipo_bottom_left);
|
||||||
|
glVertex2fv(_unit_ipo_top_right);
|
||||||
|
glEnd();
|
||||||
|
break;*/
|
||||||
|
|
||||||
|
case KEYFRAME_IPOTYPE_BEZ_VECTOR: // <v>
|
||||||
|
glBegin(GL_LINE_STRIP);
|
||||||
|
glVertex2fv(_unit_ipo_top_left);
|
||||||
|
glVertex2fv(_unit_ipo_middle);
|
||||||
|
glVertex2fv(_unit_ipo_top_right);
|
||||||
|
glEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEYFRAME_IPOTYPE_BEZ_MANUAL: // <X>
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2fv(_unit_ipo_top_left);
|
||||||
|
glVertex2fv(_unit_ipo_bottom_right);
|
||||||
|
glVertex2fv(_unit_ipo_bottom_left);
|
||||||
|
glVertex2fv(_unit_ipo_top_right);
|
||||||
|
glEnd();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
|
||||||
|
glCallList(ipo_disps[ipo_type]);
|
||||||
|
}
|
||||||
|
|
||||||
/* draw a simple diamond shape with OpenGL */
|
/* draw a simple diamond shape with OpenGL */
|
||||||
void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha)
|
void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha, short ipo_type)
|
||||||
{
|
{
|
||||||
static GLuint displist1 = 0;
|
static GLuint displist1 = 0;
|
||||||
static GLuint displist2 = 0;
|
static GLuint displist2 = 0;
|
||||||
@@ -599,6 +716,8 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel,
|
|||||||
border_col[3] *= alpha;
|
border_col[3] *= alpha;
|
||||||
glColor4fv(border_col);
|
glColor4fv(border_col);
|
||||||
|
|
||||||
|
draw_ipo_type(ipo_type);
|
||||||
|
|
||||||
glCallList(displist1);
|
glCallList(displist1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,7 +801,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
|
|||||||
/* draw using OpenGL - uglier but faster */
|
/* draw using OpenGL - uglier but faster */
|
||||||
/* NOTE1: a previous version of this didn't work nice for some intel cards
|
/* NOTE1: a previous version of this didn't work nice for some intel cards
|
||||||
* NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
|
* NOTE2: if we wanted to go back to icons, these are icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
|
||||||
draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha);
|
draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha, ak->ipo_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -71,6 +71,18 @@
|
|||||||
|
|
||||||
/* **************************************************** */
|
/* **************************************************** */
|
||||||
|
|
||||||
|
static void unsubdivide_nonauto_handles(BezTriple *bezt, BezTriple *prev, BezTriple *next)
|
||||||
|
{
|
||||||
|
if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ELEM(prev->h2, HD_AUTO, HD_AUTO_ANIM, HD_VECT) &&
|
||||||
|
ELEM(next->h1, HD_AUTO, HD_AUTO_ANIM, HD_VECT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BKE_bezt_unsubdivide_handles(bezt, prev, next);
|
||||||
|
}
|
||||||
|
|
||||||
/* Only delete the nominated keyframe from provided F-Curve.
|
/* Only delete the nominated keyframe from provided F-Curve.
|
||||||
* Not recommended to be used many times successively. For that
|
* Not recommended to be used many times successively. For that
|
||||||
* there is delete_fcurve_keys().
|
* there is delete_fcurve_keys().
|
||||||
@@ -90,6 +102,10 @@ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
|
|||||||
else if (index < 0)
|
else if (index < 0)
|
||||||
index += fcu->totvert;
|
index += fcu->totvert;
|
||||||
|
|
||||||
|
/* resize surrounding non-auto bezier handles */
|
||||||
|
if (do_recalc && index > 0 && index < fcu->totvert - 1)
|
||||||
|
unsubdivide_nonauto_handles(&fcu->bezt[index], &fcu->bezt[index - 1], &fcu->bezt[index + 1]);
|
||||||
|
|
||||||
/* Delete this keyframe */
|
/* Delete this keyframe */
|
||||||
memmove(&fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1));
|
memmove(&fcu->bezt[index], &fcu->bezt[index + 1], sizeof(BezTriple) * (fcu->totvert - index - 1));
|
||||||
fcu->totvert--;
|
fcu->totvert--;
|
||||||
@@ -105,8 +121,19 @@ void delete_fcurve_key(FCurve *fcu, int index, bool do_recalc)
|
|||||||
calchandles_fcurve(fcu);
|
calchandles_fcurve(fcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Checks if all keys are selected in an fcurve */
|
||||||
|
static bool check_if_all_keys_sel(struct FCurve *fcu)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fcu->totvert; i++)
|
||||||
|
{
|
||||||
|
if (!(fcu->bezt[i].f2 & SELECT))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete selected keyframes in given F-Curve */
|
/* Delete selected keyframes in given F-Curve */
|
||||||
bool delete_fcurve_keys(FCurve *fcu)
|
bool delete_fcurve_keys(FCurve *fcu, bool resize_handles)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
@@ -114,9 +141,19 @@ bool delete_fcurve_keys(FCurve *fcu)
|
|||||||
if (fcu->bezt == NULL) /* ignore baked curves */
|
if (fcu->bezt == NULL) /* ignore baked curves */
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Clear if everything is selected */
|
||||||
|
if (check_if_all_keys_sel(fcu)) {
|
||||||
|
clear_fcurve_keys(fcu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Delete selected BezTriples */
|
/* Delete selected BezTriples */
|
||||||
for (i = 0; i < fcu->totvert; i++) {
|
for (i = 0; i < fcu->totvert; i++) {
|
||||||
if (fcu->bezt[i].f2 & SELECT) {
|
if (fcu->bezt[i].f2 & SELECT) {
|
||||||
|
/* resize surrounding non-auto bezier handles */
|
||||||
|
if (resize_handles && i > 0 && i < fcu->totvert - 1)
|
||||||
|
unsubdivide_nonauto_handles(&fcu->bezt[i], &fcu->bezt[i-1], &fcu->bezt[i+1]);
|
||||||
|
|
||||||
memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1));
|
memmove(&fcu->bezt[i], &fcu->bezt[i + 1], sizeof(BezTriple) * (fcu->totvert - i - 1));
|
||||||
fcu->totvert--;
|
fcu->totvert--;
|
||||||
i--;
|
i--;
|
||||||
@@ -860,7 +897,7 @@ static void paste_animedit_keys_fcurve(FCurve *fcu, tAnimCopybufItem *aci, float
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* remove frames in the range */
|
/* remove frames in the range */
|
||||||
delete_fcurve_keys(fcu);
|
delete_fcurve_keys(fcu, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -112,6 +112,10 @@ short ANIM_get_keyframing_flags(Scene *scene, short incl_mode)
|
|||||||
/* keyframing mode - only replace existing keyframes */
|
/* keyframing mode - only replace existing keyframes */
|
||||||
if (IS_AUTOKEY_MODE(scene, EDITKEYS))
|
if (IS_AUTOKEY_MODE(scene, EDITKEYS))
|
||||||
flag |= INSERTKEY_REPLACE;
|
flag |= INSERTKEY_REPLACE;
|
||||||
|
|
||||||
|
/* cycle-aware keyframe insertion - preserve cycle period and flow */
|
||||||
|
if (IS_AUTOKEY_FLAG(scene, CYCLEAWARE))
|
||||||
|
flag |= INSERTKEY_CYCLE_AWARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flag;
|
return flag;
|
||||||
@@ -293,8 +297,57 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
|
|||||||
/* ************************************************** */
|
/* ************************************************** */
|
||||||
/* KEYFRAME INSERTION */
|
/* KEYFRAME INSERTION */
|
||||||
|
|
||||||
|
static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, float *py)
|
||||||
|
{
|
||||||
|
if (fcu->totvert < 2 || !fcu->bezt)
|
||||||
|
return FCU_CYCLE_NONE;
|
||||||
|
|
||||||
|
eFCU_Cycle_Type type = BKE_fcurve_get_cycle_type(fcu);
|
||||||
|
if (!type)
|
||||||
|
return FCU_CYCLE_NONE;
|
||||||
|
|
||||||
|
BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert-1];
|
||||||
|
float start = first->vec[1][0], end = last->vec[1][0];
|
||||||
|
if (start >= end)
|
||||||
|
return FCU_CYCLE_NONE;
|
||||||
|
|
||||||
|
if (*px < start || *px > end) {
|
||||||
|
float period = end - start;
|
||||||
|
float step = floorf((*px - start) / period);
|
||||||
|
*px -= step * period;
|
||||||
|
|
||||||
|
if (type == FCU_CYCLE_OFFSET) {
|
||||||
|
/* nasty check to handle the case when the modes are different better */
|
||||||
|
FMod_Cycles *data = (FMod_Cycles *)((FModifier*)fcu->modifiers.first)->data;
|
||||||
|
|
||||||
|
if ((step >= 0 ? data->after_mode : data->before_mode) == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
|
||||||
|
*py -= step * (last->vec[1][1] - first->vec[1][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------- BezTriple Insertion -------------------- */
|
/* -------------- BezTriple Insertion -------------------- */
|
||||||
|
|
||||||
|
static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
|
||||||
|
{
|
||||||
|
/* just change the values when replacing, so as to not overwrite handles */
|
||||||
|
float dy = bezt->vec[1][1] - dst->vec[1][1];
|
||||||
|
|
||||||
|
/* just apply delta value change to the handle values */
|
||||||
|
dst->vec[0][1] += dy;
|
||||||
|
dst->vec[1][1] += dy;
|
||||||
|
dst->vec[2][1] += dy;
|
||||||
|
|
||||||
|
dst->f1 = bezt->f1;
|
||||||
|
dst->f2 = bezt->f2;
|
||||||
|
dst->f3 = bezt->f3;
|
||||||
|
|
||||||
|
/* TODO: perform some other operations? */
|
||||||
|
}
|
||||||
|
|
||||||
/* This function adds a given BezTriple to an F-Curve. It will allocate
|
/* This function adds a given BezTriple to an F-Curve. It will allocate
|
||||||
* memory for the array if needed, and will insert the BezTriple into a
|
* memory for the array if needed, and will insert the BezTriple into a
|
||||||
* suitable place in chronological order.
|
* suitable place in chronological order.
|
||||||
@@ -319,20 +372,13 @@ int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
|
|||||||
fcu->bezt[i] = *bezt;
|
fcu->bezt[i] = *bezt;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* just change the values when replacing, so as to not overwrite handles */
|
replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt);
|
||||||
BezTriple *dst = (fcu->bezt + i);
|
}
|
||||||
float dy = bezt->vec[1][1] - dst->vec[1][1];
|
|
||||||
|
/* if replacing an end point of a cyclic curve without offset, modify the other end too. */
|
||||||
/* just apply delta value change to the handle values */
|
if ((flag & INSERTKEY_CYCLE_AWARE) && (i == 0 || i == fcu->totvert-1) &&
|
||||||
dst->vec[0][1] += dy;
|
(BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT)) {
|
||||||
dst->vec[1][1] += dy;
|
replace_bezt_keyframe_ypos(&fcu->bezt[(fcu->totvert-1) - i], bezt);
|
||||||
dst->vec[2][1] += dy;
|
|
||||||
|
|
||||||
dst->f1 = bezt->f1;
|
|
||||||
dst->f2 = bezt->f2;
|
|
||||||
dst->f3 = bezt->f3;
|
|
||||||
|
|
||||||
/* TODO: perform some other operations? */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,6 +430,47 @@ int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This checks whether it is necessary to apply bezier subdivision due to involvement of non-auto handles.
|
||||||
|
* - bezt: key being inserted
|
||||||
|
* - prev, next: old keys surrounding the location
|
||||||
|
*/
|
||||||
|
static void subdivide_nonauto_handles(FCurve *fcu, BezTriple *bezt, BezTriple *prev, BezTriple *next)
|
||||||
|
{
|
||||||
|
if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* don't change vector handles, or completely auto regions */
|
||||||
|
bool bezt_auto = BEZT_IS_AUTOH(bezt) || (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT);
|
||||||
|
bool prev_auto = BEZT_IS_AUTOH(prev) || (prev->h2 == HD_VECT);
|
||||||
|
bool next_auto = BEZT_IS_AUTOH(next) || (next->h1 == HD_VECT);
|
||||||
|
|
||||||
|
if (bezt_auto && prev_auto && next_auto)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* subdivide the curve */
|
||||||
|
float delta;
|
||||||
|
|
||||||
|
if (!BKE_bezt_subdivide_handles(bezt, prev, next, &delta))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* decide when to force auto to manual */
|
||||||
|
if (BEZT_IS_AUTOH(bezt) && fabsf(delta) < 0.001f) {
|
||||||
|
bool auto_works_well = false;
|
||||||
|
|
||||||
|
if (fcu->auto_smoothing == FCURVE_SMOOTH_CONT_ACCEL) {
|
||||||
|
float hx = bezt->vec[1][0] - bezt->vec[0][0];
|
||||||
|
float dx = bezt->vec[1][0] - prev->vec[1][0];
|
||||||
|
|
||||||
|
/* this mode always uses 1/3 of key distance for handle x size */
|
||||||
|
auto_works_well = fabsf(hx - dx/3.0f) < 0.001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!auto_works_well || !(prev_auto || next_auto)) {
|
||||||
|
bezt->h1 = bezt->h2 = HD_ALIGN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is a wrapper for insert_bezt_fcurve_internal(), and should be used when
|
* This function is a wrapper for insert_bezt_fcurve_internal(), and should be used when
|
||||||
* adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet.
|
* adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet.
|
||||||
@@ -456,13 +543,6 @@ int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType ke
|
|||||||
*/
|
*/
|
||||||
if (a < 0) return -1;
|
if (a < 0) return -1;
|
||||||
|
|
||||||
/* don't recalculate handles if fast is set
|
|
||||||
* - this is a hack to make importers faster
|
|
||||||
* - we may calculate twice (due to autohandle needing to be calculated twice)
|
|
||||||
*/
|
|
||||||
if ((flag & INSERTKEY_FAST) == 0)
|
|
||||||
calchandles_fcurve(fcu);
|
|
||||||
|
|
||||||
/* set handletype and interpolation */
|
/* set handletype and interpolation */
|
||||||
if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
|
if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
|
||||||
BezTriple *bezt = (fcu->bezt + a);
|
BezTriple *bezt = (fcu->bezt + a);
|
||||||
@@ -476,15 +556,17 @@ int insert_vert_fcurve(FCurve *fcu, float x, float y, eBezTriple_KeyframeType ke
|
|||||||
bezt->ipo = (bezt - 1)->ipo;
|
bezt->ipo = (bezt - 1)->ipo;
|
||||||
else if (a < fcu->totvert - 1)
|
else if (a < fcu->totvert - 1)
|
||||||
bezt->ipo = (bezt + 1)->ipo;
|
bezt->ipo = (bezt + 1)->ipo;
|
||||||
|
|
||||||
|
if ((a > 0) && (a < fcu->totvert - 1) && (flag & INSERTKEY_OVERWRITE_FULL) == 0)
|
||||||
|
subdivide_nonauto_handles(fcu, bezt, bezt - 1, bezt + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't recalculate handles if fast is set
|
|
||||||
* - this is a hack to make importers faster
|
|
||||||
* - we may calculate twice (due to autohandle needing to be calculated twice)
|
|
||||||
*/
|
|
||||||
if ((flag & INSERTKEY_FAST) == 0)
|
|
||||||
calchandles_fcurve(fcu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* don't recalculate handles if fast is set
|
||||||
|
* - this is a hack to make importers faster
|
||||||
|
*/
|
||||||
|
if ((flag & INSERTKEY_FAST) == 0)
|
||||||
|
calchandles_fcurve(fcu);
|
||||||
|
|
||||||
/* return the index at which the keyframe was added */
|
/* return the index at which the keyframe was added */
|
||||||
return a;
|
return a;
|
||||||
@@ -960,6 +1042,14 @@ bool insert_keyframe_direct(ReportList *reports, PointerRNA ptr, PropertyRNA *pr
|
|||||||
curval = setting_get_rna_value(&ptr, prop, fcu->array_index);
|
curval = setting_get_rna_value(&ptr, prop, fcu->array_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* adjust coordinates for cycle aware insertion */
|
||||||
|
if (flag & INSERTKEY_CYCLE_AWARE) {
|
||||||
|
if (remap_cyclic_keyframe_location(fcu, &cfra, &curval) != FCU_CYCLE_PERFECT) {
|
||||||
|
/* inhibit action from insert_vert_fcurve unless it's a perfect cycle */
|
||||||
|
flag &= ~INSERTKEY_CYCLE_AWARE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* only insert keyframes where they are needed */
|
/* only insert keyframes where they are needed */
|
||||||
if (flag & INSERTKEY_NEEDED) {
|
if (flag & INSERTKEY_NEEDED) {
|
||||||
short insert_mode;
|
short insert_mode;
|
||||||
|
@@ -923,7 +923,8 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
|
|||||||
/* Determine which keying flags apply based on the override flags */
|
/* Determine which keying flags apply based on the override flags */
|
||||||
static short keyingset_apply_keying_flags(const short base_flags, const short overrides, const short own_flags)
|
static short keyingset_apply_keying_flags(const short base_flags, const short overrides, const short own_flags)
|
||||||
{
|
{
|
||||||
short result = 0;
|
/* Pass through all flags by default (i.e. even not explicitly listed ones). */
|
||||||
|
short result = base_flags;
|
||||||
|
|
||||||
/* The logic for whether a keying flag applies is as follows:
|
/* The logic for whether a keying flag applies is as follows:
|
||||||
* - If the flag in question is set in "overrides", that means that the
|
* - If the flag in question is set in "overrides", that means that the
|
||||||
@@ -933,12 +934,10 @@ static short keyingset_apply_keying_flags(const short base_flags, const short ov
|
|||||||
*/
|
*/
|
||||||
#define APPLY_KEYINGFLAG_OVERRIDE(kflag) \
|
#define APPLY_KEYINGFLAG_OVERRIDE(kflag) \
|
||||||
if (overrides & kflag) { \
|
if (overrides & kflag) { \
|
||||||
|
result &= ~kflag; \
|
||||||
result |= (own_flags & kflag); \
|
result |= (own_flags & kflag); \
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
result |= (base_flags & kflag); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply the flags one by one...
|
/* Apply the flags one by one...
|
||||||
* (See rna_def_common_keying_flags() for the supported flags)
|
* (See rna_def_common_keying_flags() for the supported flags)
|
||||||
*/
|
*/
|
||||||
|
@@ -61,6 +61,7 @@ typedef struct ActKeyColumn {
|
|||||||
|
|
||||||
/* keyframe info */
|
/* keyframe info */
|
||||||
char key_type; /* eBezTripe_KeyframeType */
|
char key_type; /* eBezTripe_KeyframeType */
|
||||||
|
char ipo_type; /* eKeyframeInterpolationDrawOpts */
|
||||||
short sel;
|
short sel;
|
||||||
float cfra;
|
float cfra;
|
||||||
|
|
||||||
@@ -108,8 +109,22 @@ typedef enum eKeyframeShapeDrawOpts {
|
|||||||
KEYFRAME_SHAPE_BOTH
|
KEYFRAME_SHAPE_BOTH
|
||||||
} eKeyframeShapeDrawOpts;
|
} eKeyframeShapeDrawOpts;
|
||||||
|
|
||||||
|
/* interpolation type */
|
||||||
|
typedef enum eKeyframeInterpolationDrawOpts {
|
||||||
|
/* don't draw */
|
||||||
|
KEYFRAME_IPOTYPE_NONE = 0,
|
||||||
|
/* various marks */
|
||||||
|
KEYFRAME_IPOTYPE_CONST,
|
||||||
|
KEYFRAME_IPOTYPE_LINEAR,
|
||||||
|
KEYFRAME_IPOTYPE_EASING,
|
||||||
|
KEYFRAME_IPOTYPE_BEZ_AUTO_CLAMP,
|
||||||
|
KEYFRAME_IPOTYPE_BEZ_AUTO,
|
||||||
|
KEYFRAME_IPOTYPE_BEZ_VECTOR,
|
||||||
|
KEYFRAME_IPOTYPE_BEZ_MANUAL,
|
||||||
|
} eKeyframeInterpolationDrawOpts;
|
||||||
|
|
||||||
/* draw simple diamond-shape keyframe (with OpenGL) */
|
/* draw simple diamond-shape keyframe (with OpenGL) */
|
||||||
void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha);
|
void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha, short ipo_type);
|
||||||
|
|
||||||
/* ******************************* Methods ****************************** */
|
/* ******************************* Methods ****************************** */
|
||||||
|
|
||||||
|
@@ -282,7 +282,7 @@ bool keyframe_region_circle_test(
|
|||||||
/* Destructive Editing API (keyframes_general.c) */
|
/* Destructive Editing API (keyframes_general.c) */
|
||||||
|
|
||||||
void delete_fcurve_key(struct FCurve *fcu, int index, bool do_recalc);
|
void delete_fcurve_key(struct FCurve *fcu, int index, bool do_recalc);
|
||||||
bool delete_fcurve_keys(struct FCurve *fcu);
|
bool delete_fcurve_keys(struct FCurve *fcu, bool resize_handles);
|
||||||
void clear_fcurve_keys(struct FCurve *fcu);
|
void clear_fcurve_keys(struct FCurve *fcu);
|
||||||
void duplicate_fcurve_keys(struct FCurve *fcu);
|
void duplicate_fcurve_keys(struct FCurve *fcu);
|
||||||
|
|
||||||
|
@@ -256,7 +256,7 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
|
|||||||
* - yscale: 0.3 * h (found out experimentally... dunno why!)
|
* - yscale: 0.3 * h (found out experimentally... dunno why!)
|
||||||
* - sel: true (so that "keyframe" state shows the iconic yellow icon)
|
* - sel: true (so that "keyframe" state shows the iconic yellow icon)
|
||||||
*/
|
*/
|
||||||
draw_keyframe_shape(xco, yco, 1.0f, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha);
|
draw_keyframe_shape(xco, yco, 1.0f, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha, KEYFRAME_IPOTYPE_NONE);
|
||||||
|
|
||||||
UI_Theme_Restore(&theme_state);
|
UI_Theme_Restore(&theme_state);
|
||||||
}
|
}
|
||||||
|
@@ -688,6 +688,9 @@ static void insert_action_keys(bAnimContext *ac, short mode)
|
|||||||
/* init keyframing flag */
|
/* init keyframing flag */
|
||||||
flag = ANIM_get_keyframing_flags(scene, 1);
|
flag = ANIM_get_keyframing_flags(scene, 1);
|
||||||
|
|
||||||
|
/* ignore cycle aware setting in action editor for now */
|
||||||
|
flag &= ~INSERTKEY_CYCLE_AWARE;
|
||||||
|
|
||||||
/* insert keyframes */
|
/* insert keyframes */
|
||||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||||
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
|
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
|
||||||
@@ -906,7 +909,7 @@ static bool delete_action_keys(bAnimContext *ac)
|
|||||||
AnimData *adt = ale->adt;
|
AnimData *adt = ale->adt;
|
||||||
|
|
||||||
/* delete selected keyframes only */
|
/* delete selected keyframes only */
|
||||||
changed = delete_fcurve_keys(fcu);
|
changed = delete_fcurve_keys(fcu, true);
|
||||||
|
|
||||||
/* Only delete curve too if it won't be doing anything anymore */
|
/* Only delete curve too if it won't be doing anything anymore */
|
||||||
if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) {
|
if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) {
|
||||||
|
@@ -550,6 +550,9 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
|
|||||||
|
|
||||||
/* init keyframing flag */
|
/* init keyframing flag */
|
||||||
flag = ANIM_get_keyframing_flags(scene, 1);
|
flag = ANIM_get_keyframing_flags(scene, 1);
|
||||||
|
|
||||||
|
/* ignore cycle aware setting in graph editor for now */
|
||||||
|
flag &= ~INSERTKEY_CYCLE_AWARE;
|
||||||
|
|
||||||
/* insert keyframes */
|
/* insert keyframes */
|
||||||
if (mode & GRAPHKEYS_INSERTKEY_CURSOR) {
|
if (mode & GRAPHKEYS_INSERTKEY_CURSOR) {
|
||||||
@@ -1014,7 +1017,7 @@ static bool delete_graph_keys(bAnimContext *ac)
|
|||||||
bool changed;
|
bool changed;
|
||||||
|
|
||||||
/* delete selected keyframes only */
|
/* delete selected keyframes only */
|
||||||
changed = delete_fcurve_keys(fcu);
|
changed = delete_fcurve_keys(fcu, true);
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
ale->update |= ANIM_UPDATE_DEFAULT;
|
ale->update |= ANIM_UPDATE_DEFAULT;
|
||||||
|
@@ -139,7 +139,7 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d,
|
|||||||
* - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
|
* - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
|
||||||
*/
|
*/
|
||||||
for (ak = keys.first; ak; ak = ak->next)
|
for (ak = keys.first; ak; ak = ak->next)
|
||||||
draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f);
|
draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f, KEYFRAME_IPOTYPE_NONE);
|
||||||
|
|
||||||
/* free icons */
|
/* free icons */
|
||||||
BLI_dlrbTree_free(&keys);
|
BLI_dlrbTree_free(&keys);
|
||||||
|
@@ -852,6 +852,7 @@ typedef enum eInsertKeyFlags {
|
|||||||
* Used by copy/paste code. */
|
* Used by copy/paste code. */
|
||||||
INSERTKEY_OVERWRITE_FULL = (1<<7),
|
INSERTKEY_OVERWRITE_FULL = (1<<7),
|
||||||
INSERTKEY_DRIVER = (1<<8), /* for driver FCurves, use driver's "input" value - for easier corrective driver setup */
|
INSERTKEY_DRIVER = (1<<8), /* for driver FCurves, use driver's "input" value - for easier corrective driver setup */
|
||||||
|
INSERTKEY_CYCLE_AWARE = (1<<9), /* for cyclic FCurves, adjust key timing to preserve the cycle period and flow */
|
||||||
} eInsertKeyFlags;
|
} eInsertKeyFlags;
|
||||||
|
|
||||||
/* ************************************************ */
|
/* ************************************************ */
|
||||||
|
@@ -744,6 +744,7 @@ typedef enum eAutokey_Flag {
|
|||||||
/* toolsettings->autokey_flag */
|
/* toolsettings->autokey_flag */
|
||||||
AUTOKEY_FLAG_ONLYKEYINGSET = (1 << 6),
|
AUTOKEY_FLAG_ONLYKEYINGSET = (1 << 6),
|
||||||
AUTOKEY_FLAG_NOWARNING = (1 << 7),
|
AUTOKEY_FLAG_NOWARNING = (1 << 7),
|
||||||
|
AUTOKEY_FLAG_CYCLEAWARE = (1 << 8),
|
||||||
ANIMRECORD_FLAG_WITHNLA = (1 << 10),
|
ANIMRECORD_FLAG_WITHNLA = (1 << 10),
|
||||||
} eAutokey_Flag;
|
} eAutokey_Flag;
|
||||||
|
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
#include "BLT_translation.h"
|
#include "BLT_translation.h"
|
||||||
|
|
||||||
#include "BKE_action.h"
|
#include "BKE_action.h"
|
||||||
|
#include "BKE_fcurve.h"
|
||||||
|
|
||||||
#include "RNA_access.h"
|
#include "RNA_access.h"
|
||||||
#include "RNA_define.h"
|
#include "RNA_define.h"
|
||||||
@@ -394,6 +395,13 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value)
|
|||||||
fcu->rna_path = NULL;
|
fcu->rna_path = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rna_FCurve_is_cyclic_get(PointerRNA *ptr)
|
||||||
|
{
|
||||||
|
FCurve *fcu = (FCurve *)ptr->data;
|
||||||
|
|
||||||
|
return BKE_fcurve_is_cyclic(fcu);
|
||||||
|
}
|
||||||
|
|
||||||
static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value)
|
static void rna_FCurve_group_set(PointerRNA *ptr, PointerRNA value)
|
||||||
{
|
{
|
||||||
ID *pid = (ID *)ptr->id.data;
|
ID *pid = (ID *)ptr->id.data;
|
||||||
@@ -1986,6 +1994,12 @@ static void rna_def_fcurve(BlenderRNA *brna)
|
|||||||
"when evaluating");
|
"when evaluating");
|
||||||
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
|
RNA_def_property_update(prop, NC_ANIMATION | ND_KEYFRAME_PROP, NULL);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "is_cyclic", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_funcs(prop, "rna_FCurve_is_cyclic_get", NULL);
|
||||||
|
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||||
|
RNA_def_property_ui_text(prop, "Is Cyclic",
|
||||||
|
"True when the curve is a simple infinite cycle because of the Cycles modifier");
|
||||||
|
|
||||||
/* Collections */
|
/* Collections */
|
||||||
prop = RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE);
|
prop = RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE);
|
||||||
RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert");
|
RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert");
|
||||||
|
@@ -2843,7 +2843,13 @@ static void rna_def_tool_settings(BlenderRNA *brna)
|
|||||||
RNA_def_property_ui_text(prop, "Auto Keyframe Insert Keying Set",
|
RNA_def_property_ui_text(prop, "Auto Keyframe Insert Keying Set",
|
||||||
"Automatic keyframe insertion using active Keying Set only");
|
"Automatic keyframe insertion using active Keying Set only");
|
||||||
RNA_def_property_ui_icon(prop, ICON_KEYINGSET, 0);
|
RNA_def_property_ui_icon(prop, ICON_KEYINGSET, 0);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "use_keyframe_cycle_aware", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_boolean_sdna(prop, NULL, "autokey_flag", AUTOKEY_FLAG_CYCLEAWARE);
|
||||||
|
RNA_def_property_ui_text(prop, "Cycle-Aware Keying",
|
||||||
|
"Keyframe insertion takes care to preserve Cyclic F-Curve period and continuity");
|
||||||
|
RNA_def_property_ui_icon(prop, ICON_PROP_CON, 0);
|
||||||
|
|
||||||
/* Keyframing */
|
/* Keyframing */
|
||||||
prop = RNA_def_property(srna, "keyframe_type", PROP_ENUM, PROP_NONE);
|
prop = RNA_def_property(srna, "keyframe_type", PROP_ENUM, PROP_NONE);
|
||||||
RNA_def_property_enum_sdna(prop, NULL, "keyframe_type");
|
RNA_def_property_enum_sdna(prop, NULL, "keyframe_type");
|
||||||
|
Reference in New Issue
Block a user