static int actkeys_paste_exec(bContext *C, wmOperator *op) { bAnimContext ac; const eKeyPasteOffset offset_mode= RNA_enum_get(op->ptr, "offset"); const eKeyMergeMode merge_mode= RNA_enum_get(op->ptr, "merge"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; if(ac.reports==NULL) { ac.reports= op->reports; } /* paste keyframes */ if (ac.datatype == ANIMCONT_GPENCIL) { // FIXME... } else { if (paste_action_keys(&ac, offset_mode, merge_mode)) { BKE_report(op->reports, RPT_ERROR, "No keyframes to paste"); return OPERATOR_CANCELLED; } } /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL); return OPERATOR_FINISHED; }
static int actkeys_copy_exec(bContext *C, wmOperator *op) { bAnimContext ac; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* copy keyframes */ if (ac.datatype == ANIMCONT_GPENCIL) { /* FIXME... */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil mode"); return OPERATOR_CANCELLED; } else if (ac.datatype == ANIMCONT_MASK) { /* FIXME... */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for mask mode"); return OPERATOR_CANCELLED; } else { if (copy_action_keys(&ac)) { BKE_report(op->reports, RPT_ERROR, "No keyframes copied to keyframes copy/paste buffer"); return OPERATOR_CANCELLED; } } return OPERATOR_FINISHED; }
static int graph_panel_context(const bContext *C, bAnimListElem **ale, FCurve **fcu) { bAnimContext ac; bAnimListElem *elem = NULL; /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools) * to work correctly is able to be correctly retrieved. There's no point showing empty panels? */ if (ANIM_animdata_get_context(C, &ac) == 0) return 0; /* try to find 'active' F-Curve */ elem = get_active_fcurve_channel(&ac); if (elem == NULL) return 0; if (fcu) *fcu = (FCurve *)elem->data; if (ale) *ale = elem; else MEM_freeN(elem); return 1; }
/* has selected F-Curve that's editable */ int graphop_selected_fcurve_poll(bContext *C) { bAnimContext ac; ListBase anim_data = {NULL, NULL}; ScrArea *sa = CTX_wm_area(C); size_t items; int filter; /* firstly, check if in Graph Editor */ // TODO: also check for region? if ((sa == NULL) || (sa->spacetype != SPACE_IPO)) return 0; /* try to init Anim-Context stuff ourselves and check */ if (ANIM_animdata_get_context(C, &ac) == 0) return 0; /* get the editable + selected F-Curves, and as long as we got some, we can return * NOTE: curve-visible flag isn't included, otherwise selecting a curve via list to edit is too cumbersome */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_FOREDIT); items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); if (items == 0) return 0; /* cleanup and return findings */ BLI_freelistN(&anim_data); return 1; }
static int actkeys_paste_exec(bContext *C, wmOperator *op) { bAnimContext ac; const eKeyPasteOffset offset_mode = RNA_enum_get(op->ptr, "offset"); const eKeyMergeMode merge_mode = RNA_enum_get(op->ptr, "merge"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* ac.reports by default will be the global reports list, which won't show warnings */ ac.reports = op->reports; /* paste keyframes */ if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { /* FIXME... */ BKE_report(op->reports, RPT_ERROR, "Keyframe pasting is not available for grease pencil or mask mode"); return OPERATOR_CANCELLED; } else { /* non-zero return means an error occurred while trying to paste */ if (paste_action_keys(&ac, offset_mode, merge_mode)) { return OPERATOR_CANCELLED; } } /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); return OPERATOR_FINISHED; }
static int actkeys_paste_exec(bContext *C, wmOperator *op) { bAnimContext ac; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* paste keyframes */ if (ac.datatype == ANIMCONT_GPENCIL) { // FIXME... } else { if (paste_action_keys(&ac)) { BKE_report(op->reports, RPT_ERROR, "No keyframes to paste"); return OPERATOR_CANCELLED; } } /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME_EDIT, NULL); return OPERATOR_FINISHED; }
/* has active F-Curve that's editable */ int graphop_active_fcurve_poll(bContext *C) { bAnimContext ac; bAnimListElem *ale; ScrArea *sa = CTX_wm_area(C); bool has_fcurve = 0; /* firstly, check if in Graph Editor */ // TODO: also check for region? if ((sa == NULL) || (sa->spacetype != SPACE_IPO)) return 0; /* try to init Anim-Context stuff ourselves and check */ if (ANIM_animdata_get_context(C, &ac) == 0) return 0; /* try to get the Active F-Curve */ ale = get_active_fcurve_channel(&ac); if (ale == NULL) return 0; /* free temp data... */ has_fcurve = ((ale->data) && (ale->type == ANIMTYPE_FCURVE)); if (has_fcurve) { FCurve *fcu = (FCurve *)ale->data; has_fcurve = (fcu->flag & FCURVE_VISIBLE) != 0; } MEM_freeN(ale); /* return success */ return has_fcurve; }
/* handle clicking */ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; short selectmode; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* select mode is either replace (deselect all, then add) or add/extend */ if (RNA_boolean_get(op->ptr, "extend")) selectmode = SELECT_INVERT; else selectmode = SELECT_REPLACE; /* figure out action to take */ if (RNA_boolean_get(op->ptr, "column")) { /* select all keyframes in the same frame as the one that was under the mouse */ graphkeys_mselect_column(&ac, event->mval, selectmode); } else if (RNA_boolean_get(op->ptr, "curves")) { /* select all keyframes in the same F-Curve as the one under the mouse */ mouse_graph_keys(&ac, event->mval, selectmode, 1); } else { /* select keyframe under mouse */ mouse_graph_keys(&ac, event->mval, selectmode, 0); } /* set notifier that keyframe selection (and also channel selection in some cases) has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; }
static int actkeys_insertkey_exec(bContext *C, wmOperator *op) { bAnimContext ac; short mode; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_CANCELLED; /* what channels to affect? */ mode = RNA_enum_get(op->ptr, "type"); /* insert keyframes */ insert_action_keys(&ac, mode); /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); return OPERATOR_FINISHED; }
static int actkeys_clean_exec(bContext *C, wmOperator *op) { bAnimContext ac; float thresh; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get cleaning threshold */ thresh = RNA_float_get(op->ptr, "threshold"); /* clean keyframes */ clean_action_keys(&ac, thresh); /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); return OPERATOR_FINISHED; }
/* handle clicking */ static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; /* ARegion *ar; */ /* UNUSED */ short selectmode; bool column, channel; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* get useful pointers from animation context data */ /* ar = ac.ar; */ /* UNUSED */ /* select mode is either replace (deselect all, then add) or add/extend */ if (RNA_boolean_get(op->ptr, "extend")) selectmode = SELECT_INVERT; else selectmode = SELECT_REPLACE; /* column selection */ column = RNA_boolean_get(op->ptr, "column"); channel = RNA_boolean_get(op->ptr, "channel"); /* select keyframe(s) based upon mouse position*/ mouse_action_keys(&ac, event->mval, selectmode, column, channel); /* set notifier that keyframe selection (and channels too) have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; }
static int action_circle_select_exec(bContext *C, wmOperator *op) { bAnimContext ac; const bool select = !RNA_boolean_get(op->ptr, "deselect"); const short selectmode = select ? SELECT_ADD : SELECT_SUBTRACT; KeyframeEdit_CircleData data = {0}; rctf rect_fl; float x = RNA_int_get(op->ptr, "x"); float y = RNA_int_get(op->ptr, "y"); float radius = RNA_int_get(op->ptr, "radius"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; data.mval[0] = x; data.mval[1] = y; data.radius_squared = radius * radius; data.rectf_view = &rect_fl; rect_fl.xmin = x - radius; rect_fl.xmax = x + radius; rect_fl.ymin = y - radius; rect_fl.ymax = y + radius; /* apply region select action */ region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_CIRCLE, selectmode, &data); /* send notifier that keyframe selection has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); return OPERATOR_FINISHED; }
/* handle clicking */ static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; /* Scene *scene; */ /* UNUSED */ /* ARegion *ar; */ /* UNUSED */ // View2D *v2d; /*UNUSED*/ short selectmode; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* get useful pointers from animation context data */ /* scene= ac.scene; */ /* UNUSED */ /* ar= ac.ar; */ /* UNUSED */ // v2d= &ar->v2d; /* select mode is either replace (deselect all, then add) or add/extend */ if (RNA_boolean_get(op->ptr, "extend")) selectmode = SELECT_INVERT; else selectmode = SELECT_REPLACE; /* select strips based upon mouse position */ mouse_nla_strips(C, &ac, event->mval, selectmode); /* set notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; }
static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op) { bAnimContext ac; short leftright = RNA_enum_get(op->ptr, "mode"); short selectmode; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* select mode is either replace (deselect all, then add) or add/extend */ if (RNA_boolean_get(op->ptr, "extend")) selectmode = SELECT_INVERT; else selectmode = SELECT_REPLACE; /* if "test" mode is set, we don't have any info to set this with */ if (leftright == GRAPHKEYS_LRSEL_TEST) return OPERATOR_CANCELLED; /* do the selecting now */ graphkeys_select_leftright(&ac, leftright, selectmode); /* set notifier that keyframe selection (and channels too) have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | ND_ANIMCHAN | NA_SELECTED, NULL); return OPERATOR_FINISHED; }
static int actkeys_keytype_exec(bContext *C, wmOperator *op) { bAnimContext ac; short mode; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; if (ac.datatype == ANIMCONT_MASK) { BKE_report(op->reports, RPT_ERROR, "Not implemented for Masks"); return OPERATOR_PASS_THROUGH; } /* get handle setting mode */ mode = RNA_enum_get(op->ptr, "type"); /* set handle type */ if (ac.datatype == ANIMCONT_GPENCIL) { setkeytype_gpencil_keys(&ac, mode); } else { setkeytype_action_keys(&ac, mode); } /* set notifier that keyframe properties have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; }
static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; short leftright = RNA_enum_get(op->ptr, "mode"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* handle mode-based testing */ if (leftright == GRAPHKEYS_LRSEL_TEST) { Scene *scene = ac.scene; ARegion *ar = ac.ar; View2D *v2d = &ar->v2d; float x; /* determine which side of the current frame mouse is on */ x = UI_view2d_region_to_view_x(v2d, event->mval[0]); if (x < CFRA) RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_LEFT); else RNA_enum_set(op->ptr, "mode", GRAPHKEYS_LRSEL_RIGHT); } /* perform selection */ return graphkeys_select_leftright_exec(C, op); }
/* Main call to be exported to animation editors */ void ANIM_sync_animchannels_to_data (const bContext *C) { bAnimContext ac; ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; /* get animation context info for filtering the channels */ // TODO: check on whether we need to set the area specially instead, since active area might not be ok? if (ANIM_animdata_get_context(C, &ac) == 0) return; /* filter data */ /* NOTE: we want all channels, since we want to be able to set selection status on some of them even when collapsed */ filter= ANIMFILTER_CHANNELS; ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); /* flush settings as appropriate depending on the types of the channels */ for (ale= anim_data.first; ale; ale= ale->next) { switch (ale->type) { case ANIMTYPE_GROUP: animchan_sync_group(&ac, ale); break; case ANIMTYPE_FCURVE: animchan_sync_fcurve(&ac, ale); break; } } BLI_freelistN(&anim_data); }
static int actkeys_viewall(bContext *C, const short onlySel) { bAnimContext ac; View2D *v2d; float extra; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; v2d= &ac.ar->v2d; /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ get_keyframe_extents(&ac, &v2d->cur.xmin, &v2d->cur.xmax, onlySel); extra= 0.1f * (v2d->cur.xmax - v2d->cur.xmin); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; /* set vertical range */ v2d->cur.ymax= 0.0f; v2d->cur.ymin= (float)-(v2d->mask.ymax - v2d->mask.ymin); /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); /* just redraw this view */ ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; }
static int actkeys_previewrange_exec(bContext *C, wmOperator *UNUSED(op)) { bAnimContext ac; Scene *scene; float min, max; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; if (ac.scene == NULL) return OPERATOR_CANCELLED; else scene = ac.scene; /* set the range directly */ get_keyframe_extents(&ac, &min, &max, FALSE); scene->r.flag |= SCER_PRV_RANGE; scene->r.psfra = (int)floor(min + 0.5f); scene->r.pefra = (int)floor(max + 0.5f); /* set notifier that things have changed */ // XXX err... there's nothing for frame ranges yet, but this should do fine too WM_event_add_notifier(C, NC_SCENE | ND_FRAME, ac.scene); return OPERATOR_FINISHED; }
static int actkeys_keytype_exec(bContext *C, wmOperator *op) { bAnimContext ac; short mode; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) return OPERATOR_PASS_THROUGH; /* get handle setting mode */ mode = RNA_enum_get(op->ptr, "type"); /* set handle type */ setkeytype_action_keys(&ac, mode); /* validate keyframes after editing */ ANIM_editkeyframes_refresh(&ac); /* set notifier that keyframe properties have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); return OPERATOR_FINISHED; }
static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op) { bAnimContext ac; bool above_sel = RNA_boolean_get(op->ptr, "above_selected"); bool op_done = false; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* perform adding in two passes - existing first so that we don't double up for empty */ op_done |= nlaedit_add_tracks_existing(&ac, above_sel); op_done |= nlaedit_add_tracks_empty(&ac); /* done? */ if (op_done) { /* set notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); /* done */ return OPERATOR_FINISHED; } else { /* failed to add any tracks */ BKE_report(op->reports, RPT_WARNING, "Select an existing NLA Track or an empty action line first"); /* not done */ return OPERATOR_CANCELLED; } }
static int actkeys_clean_exec(bContext *C, wmOperator *op) { bAnimContext ac; float thresh; bool clean_chan; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) { BKE_report(op->reports, RPT_ERROR, "Not implemented"); return OPERATOR_PASS_THROUGH; } /* get cleaning threshold */ thresh = RNA_float_get(op->ptr, "threshold"); clean_chan = RNA_boolean_get(op->ptr, "channels"); /* clean keyframes */ clean_action_keys(&ac, thresh, clean_chan); /* set notifier that keyframes have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); return OPERATOR_FINISHED; }
static int graphkeys_borderselect_exec(bContext *C, wmOperator *op) { bAnimContext ac; rcti rect; rctf rect_fl; short mode = 0, selectmode = 0; bool incl_handles; bool extend; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* clear all selection if not extending selection */ extend = RNA_boolean_get(op->ptr, "extend"); if (!extend) deselect_graph_keys(&ac, 1, SELECT_SUBTRACT, true); /* get select mode * - 'gesture_mode' from the operator specifies how to select * - 'include_handles' from the operator specifies whether to include handles in the selection */ if (RNA_int_get(op->ptr, "gesture_mode") == GESTURE_MODAL_SELECT) selectmode = SELECT_ADD; else selectmode = SELECT_SUBTRACT; incl_handles = RNA_boolean_get(op->ptr, "include_handles"); /* get settings from operator */ WM_operator_properties_border_to_rcti(op, &rect); /* selection 'mode' depends on whether borderselect region only matters on one axis */ if (RNA_boolean_get(op->ptr, "axis_range")) { /* mode depends on which axis of the range is larger to determine which axis to use * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often * used for tweaking timing when "blocking", while channels is not that useful... */ if ((BLI_rcti_size_x(&rect)) >= (BLI_rcti_size_y(&rect))) mode = BEZT_OK_FRAMERANGE; else mode = BEZT_OK_VALUERANGE; } else mode = BEZT_OK_REGION; BLI_rctf_rcti_copy(&rect_fl, &rect); /* apply borderselect action */ borderselect_graphkeys(&ac, &rect_fl, mode, selectmode, incl_handles, NULL); /* send notifier that keyframe selection has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); return OPERATOR_FINISHED; }
static int graphview_curves_reveal_exec(bContext *C, wmOperator *op) { bAnimContext ac; ListBase anim_data = {NULL, NULL}; ListBase all_data = {NULL, NULL}; bAnimListElem *ale; int filter; const bool select = RNA_boolean_get(op->ptr, "select"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* get list of all channels that selection may need to be flushed to * - hierarchy must not affect what we have access to here... */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_CHANNELS | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &all_data, filter, ac.data, ac.datatype); /* filter data * - just go through all visible channels, ensuring that everything is set to be curve-visible */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); for (ale = anim_data.first; ale; ale = ale->next) { /* hack: skip object channels for now, since flushing those will always flush everything, but they are always included */ /* TODO: find out why this is the case, and fix that */ if (ale->type == ANIMTYPE_OBJECT) continue; /* select if it is not visible */ if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE) == 0) { ANIM_channel_setting_set( &ac, ale, ACHANNEL_SETTING_SELECT, select ? ACHANNEL_SETFLAG_ADD : ACHANNEL_SETFLAG_CLEAR); } /* change the visibility setting */ ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, ACHANNEL_SETFLAG_ADD); /* now, also flush selection status up/down as appropriate */ ANIM_flush_setting_anim_channels(&ac, &all_data, ale, ACHANNEL_SETTING_VISIBLE, true); } /* cleanup */ ANIM_animdata_freelist(&anim_data); BLI_freelistN(&all_data); /* send notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); return OPERATOR_FINISHED; }
static int actkeys_viewall(bContext *C, const bool only_sel) { bAnimContext ac; View2D *v2d; float extra, min, max; bool found; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; v2d = &ac.ar->v2d; /* set the horizontal range, with an extra offset so that the extreme keys will be in view */ found = get_keyframe_extents(&ac, &min, &max, only_sel); if (only_sel && (found == false)) return OPERATOR_CANCELLED; v2d->cur.xmin = min; v2d->cur.xmax = max; extra = 0.1f * BLI_rctf_size_x(&v2d->cur); v2d->cur.xmin -= extra; v2d->cur.xmax += extra; /* set vertical range */ if (only_sel == false) { /* view all -> the summary channel is usually the shows everything, and resides right at the top... */ v2d->cur.ymax = 0.0f; v2d->cur.ymin = (float)-BLI_rcti_size_y(&v2d->mask); } else { /* locate first selected channel (or the active one), and frame those */ float ymin = v2d->cur.ymin; float ymax = v2d->cur.ymax; if (actkeys_channels_get_selected_extents(&ac, &ymin, &ymax)) { /* recenter the view so that this range is in the middle */ float ymid = (ymax - ymin) / 2.0f + ymin; float x_center; UI_view2d_center_get(v2d, &x_center, NULL); UI_view2d_center_set(v2d, x_center, ymid); } } /* do View2D syncing */ UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY); /* just redraw this view */ ED_area_tag_redraw(CTX_wm_area(C)); return OPERATOR_FINISHED; }
static int graph_circle_select_exec(bContext *C, wmOperator *op) { bAnimContext ac; const int gesture_mode = RNA_int_get(op->ptr, "gesture_mode"); short selectmode; bool incl_handles; rctf rect_fl; struct KeyframeEdit_CircleData data; float x = RNA_int_get(op->ptr, "x"); float y = RNA_int_get(op->ptr, "y"); float radius = RNA_int_get(op->ptr, "radius"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; data.mval[0] = x; data.mval[1] = y; data.radius_squared = radius * radius; data.rectf_view = &rect_fl; if (gesture_mode == GESTURE_MODAL_SELECT) selectmode = SELECT_ADD; else selectmode = SELECT_SUBTRACT; rect_fl.xmin = x - radius; rect_fl.xmax = x + radius; rect_fl.ymin = y - radius; rect_fl.ymax = y + radius; if (ac.spacetype == SPACE_IPO) { SpaceIpo *sipo = (SpaceIpo *)ac.sl; if (selectmode == SELECT_ADD) { incl_handles = ((sipo->flag & SIPO_SELVHANDLESONLY) || (sipo->flag & SIPO_NOHANDLES)) == 0; } else { incl_handles = (sipo->flag & SIPO_NOHANDLES) == 0; } } else { incl_handles = false; } /* apply borderselect action */ borderselect_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_CIRCLE, selectmode, incl_handles, &data); /* send notifier that keyframe selection has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); return OPERATOR_FINISHED; }
static int actkeys_borderselect_exec(bContext *C, wmOperator *op) { bAnimContext ac; rcti rect; short mode=0, selectmode=0; int gesture_mode, extend; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* clear all selection if not extending selection */ extend= RNA_boolean_get(op->ptr, "extend"); if (!extend) deselect_action_keys(&ac, 1, SELECT_SUBTRACT); /* get settings from operator */ rect.xmin= RNA_int_get(op->ptr, "xmin"); rect.ymin= RNA_int_get(op->ptr, "ymin"); rect.xmax= RNA_int_get(op->ptr, "xmax"); rect.ymax= RNA_int_get(op->ptr, "ymax"); gesture_mode= RNA_int_get(op->ptr, "gesture_mode"); if (gesture_mode == GESTURE_MODAL_SELECT) selectmode = SELECT_ADD; else selectmode = SELECT_SUBTRACT; /* selection 'mode' depends on whether borderselect region only matters on one axis */ if (RNA_boolean_get(op->ptr, "axis_range")) { /* mode depends on which axis of the range is larger to determine which axis to use * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size * - the frame-range select option is favoured over the channel one (x over y), as frame-range one is often * used for tweaking timing when "blocking", while channels is not that useful... */ if ((rect.xmax - rect.xmin) >= (rect.ymax - rect.ymin)) mode= ACTKEYS_BORDERSEL_FRAMERANGE; else mode= ACTKEYS_BORDERSEL_CHANNELS; } else mode= ACTKEYS_BORDERSEL_ALLKEYS; /* apply borderselect action */ borderselect_action(&ac, rect, mode, selectmode); /* set notifier that keyframe selection have changed */ WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|NA_SELECTED, NULL); return OPERATOR_FINISHED; }
static int nlaedit_borderselect_exec(bContext *C, wmOperator *op) { bAnimContext ac; rcti rect; short mode = 0, selectmode = 0; const bool select = !RNA_boolean_get(op->ptr, "deselect"); const bool extend = RNA_boolean_get(op->ptr, "extend"); /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* clear all selection if not extending selection */ if (!extend) { deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_SUBTRACT); } /* get settings from operator */ WM_operator_properties_border_to_rcti(op, &rect); if (select) { selectmode = SELECT_ADD; } else { selectmode = SELECT_SUBTRACT; } /* selection 'mode' depends on whether borderselect region only matters on one axis */ if (RNA_boolean_get(op->ptr, "axis_range")) { /* mode depends on which axis of the range is larger to determine which axis to use * - checking this in region-space is fine, as it's fundamentally still going to be a different rect size * - the frame-range select option is favored over the channel one (x over y), as frame-range one is often * used for tweaking timing when "blocking", while channels is not that useful... */ if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect)) mode = NLA_BORDERSEL_FRAMERANGE; else mode = NLA_BORDERSEL_CHANNELS; } else mode = NLA_BORDERSEL_ALLSTRIPS; /* apply borderselect action */ borderselect_nla_strips(&ac, rect, mode, selectmode); /* set notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL); return OPERATOR_FINISHED; }
/* Check if there are any visible + editable keyframes (for editing tools) */ int graphop_editable_keyframes_poll(bContext *C) { bAnimContext ac; bAnimListElem *ale; ListBase anim_data = {NULL, NULL}; ScrArea *sa = CTX_wm_area(C); size_t items; int filter; short found = 0; /* firstly, check if in Graph Editor */ // TODO: also check for region? if ((sa == NULL) || (sa->spacetype != SPACE_IPO)) return 0; /* try to init Anim-Context stuff ourselves and check */ if (ANIM_animdata_get_context(C, &ac) == 0) return 0; /* loop over the editable F-Curves, and see if they're suitable * stopping on the first successful match */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); items = ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); if (items == 0) return 0; for (ale = anim_data.first; ale; ale = ale->next) { FCurve *fcu = (FCurve *)ale->data; /* editable curves must fulfill the following criteria: * - it has bezier keyframes * - it must not be protected from editing (this is already checked for with the foredit flag * - F-Curve modifiers do not interfere with the result too much * (i.e. the modifier-control drawing check returns false) */ if (fcu->bezt == NULL) continue; if (fcurve_is_keyframable(fcu)) { found = 1; break; } } /* cleanup and return findings */ BLI_freelistN(&anim_data); return found; }
/* handle clicking */ static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event) { bAnimContext ac; Scene *scene; ARegion *ar; View2D *v2d; short selectmode; int mval[2]; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; /* get useful pointers from animation context data */ scene= ac.scene; ar= ac.ar; v2d= &ar->v2d; /* get mouse coordinates (in region coordinates) */ mval[0]= (event->x - ar->winrct.xmin); mval[1]= (event->y - ar->winrct.ymin); /* select mode is either replace (deselect all, then add) or add/extend */ if (RNA_boolean_get(op->ptr, "extend")) selectmode= SELECT_INVERT; else selectmode= SELECT_REPLACE; /* figure out action to take */ if (RNA_boolean_get(op->ptr, "column")) { /* select all keyframes in the same frame as the one that was under the mouse */ graphkeys_mselect_column(&ac, mval, selectmode); } else if (RNA_boolean_get(op->ptr, "curves")) { /* select all keyframes in the same F-Curve as the one under the mouse */ mouse_graph_keys(&ac, mval, selectmode, 1); } else { /* select keyframe under mouse */ mouse_graph_keys(&ac, mval, selectmode, 0); } /* set notifier that keyframe selection (and also channel selection in some cases) has changed */ WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME|ND_ANIMCHAN|NA_SELECTED, NULL); /* for tweak grab to work */ return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH; }