diff options
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r-- | source/blender/editors/animation/anim_channels_defines.c | 45 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_filter.c | 7 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_ops.c | 124 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_general.c | 79 |
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; + } + } + } } /* ---------------- */ |