/* common code for exec() methods */ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) { /* settings should have been set up ok for applying, so just apply! */ pose_slide_apply(C, pso); /* insert keyframes if needed */ pose_slide_autoKeyframe(C, pso); /* cleanup and done */ pose_slide_exit(op); return OPERATOR_FINISHED; }
/* common code for invoke() methods */ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *pso) { tPChanFCurveLink *pfl; AnimData *adt = pso->ob->adt; wmWindow *win = CTX_wm_window(C); /* for each link, add all its keyframes to the search tree */ for (pfl = pso->pfLinks.first; pfl; pfl = pfl->next) { LinkData *ld; /* do this for each F-Curve */ for (ld = pfl->fcurves.first; ld; ld = ld->next) { FCurve *fcu = (FCurve *)ld->data; fcurve_to_keylist(adt, fcu, &pso->keys, NULL); } } /* consolidate these keyframes, and figure out the nearest ones */ BLI_dlrbTree_linkedlist_sync(&pso->keys); /* cancel if no keyframes found... */ if (pso->keys.root) { ActKeyColumn *ak; float cframe = (float)pso->cframe; /* firstly, check if the current frame is a keyframe... */ ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(&pso->keys, compare_ak_cfraPtr, &cframe); if (ak == NULL) { /* current frame is not a keyframe, so search */ ActKeyColumn *pk = (ActKeyColumn *)BLI_dlrbTree_search_prev(&pso->keys, compare_ak_cfraPtr, &cframe); ActKeyColumn *nk = (ActKeyColumn *)BLI_dlrbTree_search_next(&pso->keys, compare_ak_cfraPtr, &cframe); /* new set the frames */ /* prev frame */ pso->prevFrame = (pk) ? (pk->cfra) : (pso->cframe - 1); RNA_int_set(op->ptr, "prev_frame", pso->prevFrame); /* next frame */ pso->nextFrame = (nk) ? (nk->cfra) : (pso->cframe + 1); RNA_int_set(op->ptr, "next_frame", pso->nextFrame); } else { /* current frame itself is a keyframe, so just take keyframes on either side */ /* prev frame */ pso->prevFrame = (ak->prev) ? (ak->prev->cfra) : (pso->cframe - 1); RNA_int_set(op->ptr, "prev_frame", pso->prevFrame); /* next frame */ pso->nextFrame = (ak->next) ? (ak->next->cfra) : (pso->cframe + 1); RNA_int_set(op->ptr, "next_frame", pso->nextFrame); } } else { BKE_report(op->reports, RPT_ERROR, "No keyframes to slide between"); pose_slide_exit(op); return OPERATOR_CANCELLED; } /* initial apply for operator... */ /* TODO: need to calculate percentage for initial round too... */ pose_slide_apply(C, pso); /* depsgraph updates + redraws */ pose_slide_refresh(C, pso); /* set cursor to indicate modal */ WM_cursor_modal_set(win, BC_EW_SCROLLCURSOR); /* header print */ pose_slide_draw_status(pso); /* add a modal handler for this operator */ WM_event_add_modal_handler(C, op); return OPERATOR_RUNNING_MODAL; }
/* common code for modal() */ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso = op->customdata; wmWindow *win = CTX_wm_window(C); switch (event->type) { case LEFTMOUSE: /* confirm */ case RETKEY: { /* return to normal cursor and header status */ ED_area_headerprint(pso->sa, NULL); WM_cursor_modal_restore(win); /* insert keyframes as required... */ pose_slide_autoKeyframe(C, pso); pose_slide_exit(op); /* done! */ return OPERATOR_FINISHED; } case ESCKEY: /* cancel */ case RIGHTMOUSE: { /* return to normal cursor and header status */ ED_area_headerprint(pso->sa, NULL); WM_cursor_modal_restore(win); /* reset transforms back to original state */ pose_slide_reset(pso); /* depsgraph updates + redraws */ pose_slide_refresh(C, pso); /* clean up temp data */ pose_slide_exit(op); /* canceled! */ return OPERATOR_CANCELLED; } case MOUSEMOVE: /* calculate new position */ { /* calculate percentage based on position of mouse (we only use x-axis for now. * since this is more convenient for users to do), and store new percentage value */ pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx); RNA_float_set(op->ptr, "percentage", pso->percentage); /* update percentage indicator in header */ pose_slide_draw_status(pso); /* reset transforms (to avoid accumulation errors) */ pose_slide_reset(pso); /* apply... */ pose_slide_apply(C, pso); break; } default: /* unhandled event (maybe it was some view manip? */ /* allow to pass through */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } /* still running... */ return OPERATOR_RUNNING_MODAL; }
/* common code for modal() */ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso = op->customdata; wmWindow *win = CTX_wm_window(C); const bool has_numinput = hasNumInput(&pso->num); switch (event->type) { case LEFTMOUSE: /* confirm */ case RETKEY: case PADENTER: { /* return to normal cursor and header status */ ED_area_headerprint(pso->sa, NULL); WM_cursor_modal_restore(win); /* insert keyframes as required... */ pose_slide_autoKeyframe(C, pso); pose_slide_exit(op); /* done! */ return OPERATOR_FINISHED; } case ESCKEY: /* cancel */ case RIGHTMOUSE: { /* return to normal cursor and header status */ ED_area_headerprint(pso->sa, NULL); WM_cursor_modal_restore(win); /* reset transforms back to original state */ pose_slide_reset(pso); /* depsgraph updates + redraws */ pose_slide_refresh(C, pso); /* clean up temp data */ pose_slide_exit(op); /* canceled! */ return OPERATOR_CANCELLED; } case MOUSEMOVE: /* calculate new position */ { /* only handle mousemove if not doing numinput */ if (has_numinput == false) { /* update percentage based on position of mouse */ pose_slide_mouse_update_percentage(pso, op, event); /* update percentage indicator in header */ pose_slide_draw_status(pso); /* reset transforms (to avoid accumulation errors) */ pose_slide_reset(pso); /* apply... */ pose_slide_apply(C, pso); } break; } default: if ((event->val == KM_PRESS) && handleNumInput(C, &pso->num, event)) { float value; /* Grab percentage from numeric input, and store this new value for redo * NOTE: users see ints, while internally we use a 0-1 float */ value = pso->percentage * 100.0f; applyNumInput(&pso->num, &value); pso->percentage = value / 100.0f; CLAMP(pso->percentage, 0.0f, 1.0f); RNA_float_set(op->ptr, "percentage", pso->percentage); /* update percentage indicator in header */ pose_slide_draw_status(pso); /* reset transforms (to avoid accumulation errors) */ pose_slide_reset(pso); /* apply... */ pose_slide_apply(C, pso); break; } else { /* unhandled event - maybe it was some view manip? */ /* allow to pass through */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } } /* still running... */ return OPERATOR_RUNNING_MODAL; }