Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c45
-rw-r--r--source/blender/editors/animation/anim_filter.c7
-rw-r--r--source/blender/editors/animation/anim_ops.c124
-rw-r--r--source/blender/editors/animation/keyframes_general.c79
4 files changed, 222 insertions, 33 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index ebd05d8b16b..10af5b84509 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -865,7 +865,11 @@ static int acf_group_setting_flag(bAnimContext *ac, eAnimChannel_Settings settin
case ACHANNEL_SETTING_MUTE: /* muted */
return AGRP_MUTED;
-
+
+ case ACHANNEL_SETTING_MOD_OFF: /* muted */
+ *neg = 1;
+ return AGRP_MODIFIERS_OFF;
+
case ACHANNEL_SETTING_PROTECT: /* protected */
return AGRP_PROTECTED;
@@ -983,6 +987,10 @@ static int acf_fcurve_setting_flag(bAnimContext *UNUSED(ac), eAnimChannel_Settin
case ACHANNEL_SETTING_VISIBLE: /* visibility - graph editor */
return FCURVE_VISIBLE;
+ case ACHANNEL_SETTING_MOD_OFF:
+ *neg = 1;
+ return FCURVE_MOD_OFF;
+
default: /* unsupported */
return 0;
}
@@ -3977,6 +3985,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
{
short ptrsize, butType;
bool negflag;
+ bool usetoggle = true;
int flag, icon;
void *ptr;
const char *tooltip;
@@ -3998,7 +4007,13 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
else
tooltip = TIP_("Channels are visible in Graph Editor for editing");
break;
-
+
+ case ACHANNEL_SETTING_MOD_OFF: /* modifiers disabled */
+ icon = ICON_MODIFIER;
+ usetoggle = false;
+ tooltip = TIP_("F-Curve modifiers are disabled");
+ break;
+
case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
//icon = ((enabled) ? ICON_TRIA_DOWN : ICON_TRIA_RIGHT);
icon = ICON_TRIA_RIGHT;
@@ -4059,11 +4074,18 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
}
/* type of button */
- if (negflag)
- butType = UI_BTYPE_ICON_TOGGLE_N;
- else
- butType = UI_BTYPE_ICON_TOGGLE;
-
+ if (usetoggle) {
+ if (negflag)
+ butType = UI_BTYPE_ICON_TOGGLE_N;
+ else
+ butType = UI_BTYPE_ICON_TOGGLE;
+ }
+ else {
+ if (negflag)
+ butType = UI_BTYPE_TOGGLE_N;
+ else
+ butType = UI_BTYPE_TOGGLE;
+ }
/* draw button for setting */
if (ptr && flag) {
switch (ptrsize) {
@@ -4091,6 +4113,7 @@ static void draw_setting_widget(bAnimContext *ac, bAnimListElem *ale, const bAni
case ACHANNEL_SETTING_PROTECT: /* General - protection flags */
case ACHANNEL_SETTING_MUTE: /* General - muting flags */
case ACHANNEL_SETTING_PINNED: /* NLA Actions - 'map/nomap' */
+ case ACHANNEL_SETTING_MOD_OFF:
UI_but_funcN_set(but, achannel_setting_flush_widget_cb, MEM_dupallocN(ale), SET_INT_IN_POINTER(setting));
break;
@@ -4258,7 +4281,13 @@ void ANIM_channel_draw_widgets(const bContext *C, bAnimContext *ac, bAnimListEle
offset += ICON_WIDTH;
draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax - offset, ymid, ACHANNEL_SETTING_MUTE);
}
-
+
+ /* modifiers disable */
+ if (acf->has_setting(ac, ale, ACHANNEL_SETTING_MOD_OFF)) {
+ offset += ICON_WIDTH;
+ draw_setting_widget(ac, ale, acf, block, (int)v2d->cur.xmax - offset, ymid, ACHANNEL_SETTING_MOD_OFF);
+ }
+
/* ----------- */
/* pinned... */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index ca8a35e4ed9..aed32305367 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -90,6 +90,7 @@
#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_mask.h"
+#include "BKE_particle.h"
#include "BKE_sequencer.h"
#include "ED_anim_api.h"
@@ -2377,6 +2378,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
BEGIN_ANIMFILTER_SUBCHANNELS(EXPANDED_OBJC(ob))
{
Key *key = BKE_key_from_object(ob);
+ ParticleSystem *psys;
/* object-level animation */
if ((ob->adt) && !(ads->filterflag & ADS_FILTER_NOOBJ)) {
@@ -2387,6 +2389,11 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
if ((key && key->adt) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, key, filter_mode);
}
+ for (psys = ob->particlesystem.first; psys; psys = psys->next) {
+ if ((psys->key && psys->key->adt) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
+ tmp_items += animdata_filter_ds_keyanim(ac, &tmp_data, ads, ob, psys->key, filter_mode);
+ }
+ }
/* modifiers */
if ((ob->modifiers.first) && !(ads->filterflag & ADS_FILTER_NOMODIFIERS)) {
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index 2de42933dc0..86b368fe0d2 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -60,6 +60,8 @@
#include "anim_intern.h"
+#include "MEM_guardedalloc.h"
+
/* ********************** frame change operator ***************************/
/* Check if the operator can be run from the current context */
@@ -90,10 +92,11 @@ static int change_frame_poll(bContext *C)
}
/* Set the new frame number */
-static void change_frame_apply(bContext *C, wmOperator *op)
+static void change_frame_apply(bContext *C, wmOperator *op, bool final)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ ARegion *ar_op = CTX_wm_region(C);
int frame = RNA_int_get(op->ptr, "frame");
bool do_snap = RNA_boolean_get(op->ptr, "snap");
@@ -107,8 +110,44 @@ static void change_frame_apply(bContext *C, wmOperator *op)
SUBFRA = 0.0f;
/* do updates */
- BKE_sound_seek_scene(bmain, scene);
- WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+
+ if (final) {
+ BKE_sound_seek_scene(bmain, scene);
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ }
+ else
+ {
+ bScreen *screen = CTX_wm_screen(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *window;
+ ScrArea *sa;
+
+ BKE_sound_seek_scene(bmain, scene);
+
+ ED_update_for_newframe(bmain, scene, 1);
+
+ for (window = wm->windows.first; window; window = window->next) {
+ for (sa = window->screen->areabase.first; sa; sa = sa->next) {
+ ARegion *ar;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ bool redraw = false;
+ if (ar == ar_op) {
+ redraw = true;
+ }
+ else if (ED_match_region_with_redraws(sa->spacetype, ar->regiontype, screen->redraws_flag)) {
+ redraw = true;
+ }
+
+ if (redraw) {
+ ED_region_tag_redraw(ar);
+ }
+ }
+
+ if (ED_match_area_with_refresh(sa->spacetype, SPACE_TIME))
+ ED_area_tag_refresh(sa);
+ }
+ }
+ }
}
/* ---- */
@@ -116,8 +155,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
/* Non-modal callback for running operator without user input */
static int change_frame_exec(bContext *C, wmOperator *op)
{
- change_frame_apply(C, op);
-
+ change_frame_apply(C, op, true);
return OPERATOR_FINISHED;
}
@@ -154,13 +192,35 @@ static void change_frame_seq_preview_begin(bContext *C, const wmEvent *event)
}
}
}
-static void change_frame_seq_preview_end(bContext *C)
+
+typedef struct ChangeFrameData {
+ wmTimer *timer;
+ double last_duration;
+ int frame;
+ int last_frame;
+} ChangeFrameData;
+
+static void change_frame_seq_preview_end(bContext *C, wmOperator *op)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+
if (ED_sequencer_special_preview_get() != NULL) {
Scene *scene = CTX_data_scene(C);
ED_sequencer_special_preview_clear();
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
}
+
+ if (op->customdata) {
+ ChangeFrameData *data = op->customdata;
+ WM_event_remove_timer(wm, win, data->timer);
+ MEM_freeN(data);
+ op->customdata = NULL;
+ /* add here too to take care of cancelling */
+ if (win->screen)
+ win->screen->scrubbing = false;
+ }
+
}
/* Modal Operator init */
@@ -170,11 +230,22 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
* as user could click on a single frame (jump to frame) as well as
* click-dragging over a range (modal scrubbing).
*/
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ Scene *scene = CTX_data_scene(C);
+ ChangeFrameData *data = MEM_callocN(sizeof(ChangeFrameData), "changeframedata");
+
+ data->timer = WM_event_add_timer(wm, win, TIMER, FRA2TIME(1.0));
+
RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ op->customdata = data;
change_frame_seq_preview_begin(C, event);
- change_frame_apply(C, op);
+ if (win->screen)
+ win->screen->scrubbing = true;
+
+ change_frame_apply(C, op, false);
/* add temp handler */
WM_event_add_modal_handler(C, op);
@@ -182,24 +253,43 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
return OPERATOR_RUNNING_MODAL;
}
-static void change_frame_cancel(bContext *C, wmOperator *UNUSED(op))
+static void change_frame_cancel(bContext *C, wmOperator *op)
{
- change_frame_seq_preview_end(C);
+ change_frame_seq_preview_end(C, op);
}
/* Modal event handling of frame changing */
static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ChangeFrameData *data = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+
int ret = OPERATOR_RUNNING_MODAL;
/* execute the events */
switch (event->type) {
case ESCKEY:
+ WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
+ if (win->screen)
+ win->screen->scrubbing = false;
+ BKE_sound_seek_scene(bmain, scene);
ret = OPERATOR_FINISHED;
break;
case MOUSEMOVE:
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
- change_frame_apply(C, op);
+ data->frame = frame_from_event(C, event);
+ break;
+
+ case TIMER:
+ if (data->timer->duration - data->last_duration > FRA2TIME(1)) {
+ if (data->frame != data->last_frame) {
+ RNA_int_set(op->ptr, "frame", data->frame);
+ change_frame_apply(C, op, false);
+ data->last_frame = data->frame;
+ data->last_duration = data->timer->duration;
+ }
+ }
break;
case LEFTMOUSE:
@@ -208,8 +298,14 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* we check for either mouse-button to end, as checking for ACTIONMOUSE (which is used to init
* the modal op) doesn't work for some reason
*/
- if (event->val == KM_RELEASE)
+ if (event->val == KM_RELEASE) {
+ if (win->screen)
+ win->screen->scrubbing = false;
+ data->frame = frame_from_event(C, event);
+ RNA_int_set(op->ptr, "frame", data->frame);
+ change_frame_apply(C, op, true);
ret = OPERATOR_FINISHED;
+ }
break;
case LEFTCTRLKEY:
@@ -224,7 +320,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (ret != OPERATOR_RUNNING_MODAL) {
- change_frame_seq_preview_end(C);
+ change_frame_seq_preview_end(C, op);
}
return ret;
@@ -247,7 +343,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->poll = change_frame_poll;
/* flags */
- ot->flag = OPTYPE_BLOCKING | OPTYPE_UNDO | OPTYPE_GRAB_CURSOR;
+ ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
/* rna */
ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index b3dc0021f00..5d2c0077dee 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -179,17 +179,37 @@ void duplicate_fcurve_keys(FCurve *fcu)
/* **************************************************** */
/* Various Tools */
-/* Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only */
-void clean_fcurve(FCurve *fcu, float thresh)
+static void copy_bezt_ipo(BezTriple *bezdst, BezTriple *bezsrc)
{
+ bezdst->back = bezsrc->back;
+ bezdst->ipo = bezsrc->ipo;
+ bezdst->easing = bezsrc->easing;
+ bezdst->amplitude = bezsrc->amplitude;
+ bezdst->period = bezsrc->period;
+ bezdst->h1 = bezsrc->h1;
+ bezdst->h2 = bezsrc->h2;
+ bezdst->vec[0][0] = bezsrc->vec[0][0];
+ bezdst->vec[0][1] = bezsrc->vec[0][1];
+ bezdst->vec[2][0] = bezsrc->vec[2][0];
+ bezdst->vec[2][1] = bezsrc->vec[2][1];
+}
+
+/* Basic F-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only
+ * optionally clears up curve if one keyframe with default value remains */
+void clean_fcurve(struct bAnimContext *ac, bAnimListElem *ale, float thresh, bool cleardefault)
+{
+ FCurve *fcu = (FCurve *)ale->key_data;
BezTriple *old_bezts, *bezt, *beztn;
BezTriple *lastb;
int totCount, i;
/* check if any points */
- if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert <= 1))
+ if ((fcu == NULL) || (fcu->bezt == NULL) || (fcu->totvert == 0) ||
+ (!cleardefault && fcu->totvert == 1))
+ {
return;
-
+ }
+
/* make a copy of the old BezTriples, and clear F-Curve */
old_bezts = fcu->bezt;
totCount = fcu->totvert;
@@ -227,7 +247,8 @@ void clean_fcurve(FCurve *fcu, float thresh)
cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1];
if (!(bezt->f2 & SELECT)) {
- insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ insert_vert_fcurve(fcu, cur[0], cur[1], INSERTKEY_FAST);
+ copy_bezt_ipo((fcu->bezt + (fcu->totvert - 1)), bezt);
lastb = (fcu->bezt + (fcu->totvert - 1));
lastb->f1 = lastb->f2 = lastb->f3 = 0;
continue;
@@ -246,7 +267,8 @@ void clean_fcurve(FCurve *fcu, float thresh)
if (cur[1] > next[1]) {
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ insert_vert_fcurve(fcu, cur[0], cur[1], INSERTKEY_FAST);
+ copy_bezt_ipo((fcu->bezt + (fcu->totvert - 1)), bezt);
}
}
}
@@ -254,7 +276,8 @@ void clean_fcurve(FCurve *fcu, float thresh)
/* only add if values are a considerable distance apart */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ insert_vert_fcurve(fcu, cur[0], cur[1], INSERTKEY_FAST);
+ copy_bezt_ipo((fcu->bezt + (fcu->totvert - 1)), bezt);
}
}
}
@@ -264,26 +287,60 @@ void clean_fcurve(FCurve *fcu, float thresh)
/* does current have same value as previous and next? */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe*/
- insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ insert_vert_fcurve(fcu, cur[0], cur[1], INSERTKEY_FAST);
+ copy_bezt_ipo((fcu->bezt + (fcu->totvert - 1)), bezt);
}
else if (IS_EQT(cur[1], next[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ insert_vert_fcurve(fcu, cur[0], cur[1], INSERTKEY_FAST);
+ copy_bezt_ipo((fcu->bezt + (fcu->totvert - 1)), bezt);
}
}
else {
/* add if value doesn't equal that of previous */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_fcurve(fcu, cur[0], cur[1], 0);
+ insert_vert_fcurve(fcu, cur[0], cur[1], INSERTKEY_FAST);
+ copy_bezt_ipo((fcu->bezt + (fcu->totvert - 1)), bezt);
}
}
}
}
-
+
+ /* skip doing this, handles should be already sorted since we are copying in forward order only */
+ /* calchandles_fcurve(fcu); */
+
/* now free the memory used by the old BezTriples */
if (old_bezts)
MEM_freeN(old_bezts);
+
+ /* final step, if there is just one key in fcurve, check if it's
+ * the default value and if is, remove fcurve completely. */
+ if (cleardefault && fcu->totvert == 1) {
+ float default_value = 0.0f;
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ RNA_id_pointer_create(ale->id, &id_ptr);
+
+ /* get property to read from, and get value as appropriate */
+ if (RNA_path_resolve_property(&id_ptr, fcu->rna_path, &ptr, &prop)) {
+ if (RNA_property_type(prop) == PROP_FLOAT)
+ default_value = RNA_property_float_get_default_index(&ptr, prop, fcu->array_index);
+ }
+
+ if (fcu->bezt->vec[1][1] == default_value) {
+ clear_fcurve_keys(fcu);
+
+ /* check if curve is really unused and if it is, return signal for deletion */
+ if ((list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) &&
+ (fcu->driver == NULL))
+ {
+ AnimData *adt = ale->adt;
+ ANIM_fcurve_delete_from_animdata(ac, adt, fcu);
+ ale->key_data = NULL;
+ }
+ }
+ }
}
/* ---------------- */