Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_convert_graph.c
| Show All 34 Lines | |||||
| #include "ED_anim_api.h" | #include "ED_anim_api.h" | ||||
| #include "ED_markers.h" | #include "ED_markers.h" | ||||
| #include "UI_view2d.h" | #include "UI_view2d.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| #include "transform_convert.h" | #include "transform_convert.h" | ||||
| #include "transform_data.h" | |||||
| typedef struct TransDataGraph { | typedef struct TransDataGraph { | ||||
| float unit_scale; | float unit_scale; | ||||
| float offset; | float offset; | ||||
| } TransDataGraph; | } TransDataGraph; | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Graph Editor Transform Creation | /** \name Graph Editor Transform Creation | ||||
| * | * | ||||
| * \{ */ | * \{ */ | ||||
| /* Helper function for createTransGraphEditData, which is responsible for associating | /* Helper function for createTransGraphEditData, which is responsible for associating | ||||
| * source data with transform data | * source data with transform data | ||||
| */ | */ | ||||
| static void bezt_to_transdata(TransData *td, | static void bezt_to_transdata(TransData *td, | ||||
| const int tdi, | |||||
| TransData2D *td2d, | TransData2D *td2d, | ||||
| TransDataGraph *tdg, | TransDataGraph *tdg, | ||||
| AnimData *adt, | AnimData *adt, | ||||
| BezTriple *bezt, | BezTriple *bezt, | ||||
| int bi, | int bi, | ||||
| bool selected, | bool selected, | ||||
| bool ishandle, | bool ishandle, | ||||
| bool intvals, | bool intvals, | ||||
| Show All 13 Lines | static void bezt_to_transdata(TransData *td, | ||||
| */ | */ | ||||
| if (adt) { | if (adt) { | ||||
| td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP); | td2d->loc[0] = BKE_nla_tweakedit_remap(adt, loc[0], NLATIME_CONVERT_MAP); | ||||
| td2d->loc[1] = (loc[1] + offset) * unit_scale; | td2d->loc[1] = (loc[1] + offset) * unit_scale; | ||||
| td2d->loc[2] = 0.0f; | td2d->loc[2] = 0.0f; | ||||
| td2d->loc2d = loc; | td2d->loc2d = loc; | ||||
| td->loc = td2d->loc; | td->basic[tdi].loc = td2d->loc; | ||||
| td->center[0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP); | td->center[tdi][0] = BKE_nla_tweakedit_remap(adt, cent[0], NLATIME_CONVERT_MAP); | ||||
| td->center[1] = (cent[1] + offset) * unit_scale; | td->center[tdi][1] = (cent[1] + offset) * unit_scale; | ||||
| td->center[2] = 0.0f; | td->center[tdi][2] = 0.0f; | ||||
| copy_v3_v3(td->iloc, td->loc); | copy_v3_v3(td->basic[tdi].iloc, td2d->loc); | ||||
| } | } | ||||
| else { | else { | ||||
| td2d->loc[0] = loc[0]; | td2d->loc[0] = loc[0]; | ||||
| td2d->loc[1] = (loc[1] + offset) * unit_scale; | td2d->loc[1] = (loc[1] + offset) * unit_scale; | ||||
| td2d->loc[2] = 0.0f; | td2d->loc[2] = 0.0f; | ||||
| td2d->loc2d = loc; | td2d->loc2d = loc; | ||||
| td->loc = td2d->loc; | td->basic[tdi].loc = td2d->loc; | ||||
| copy_v3_v3(td->center, cent); | copy_v3_v3(td->center[tdi], cent); | ||||
| td->center[1] = (td->center[1] + offset) * unit_scale; | td->center[tdi][1] = (cent[1] + offset) * unit_scale; | ||||
| copy_v3_v3(td->iloc, td->loc); | copy_v3_v3(td->basic[tdi].iloc, td2d->loc); | ||||
| } | } | ||||
| if (!ishandle) { | if (!ishandle) { | ||||
| td2d->h1 = bezt->vec[0]; | td2d->h1 = bezt->vec[0]; | ||||
| td2d->h2 = bezt->vec[2]; | td2d->h2 = bezt->vec[2]; | ||||
| copy_v2_v2(td2d->ih1, td2d->h1); | copy_v2_v2(td2d->ih1, td2d->h1); | ||||
| copy_v2_v2(td2d->ih2, td2d->h2); | copy_v2_v2(td2d->ih2, td2d->h2); | ||||
| } | } | ||||
| else { | else { | ||||
| td2d->h1 = NULL; | td2d->h1 = NULL; | ||||
| td2d->h2 = NULL; | td2d->h2 = NULL; | ||||
| } | } | ||||
| memset(td->axismtx, 0, sizeof(td->axismtx)); | const float axismtx[3][3] = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}}; | ||||
| td->axismtx[2][2] = 1.0f; | copy_m3_m3(td->space[tdi].axismtx, axismtx); | ||||
| td->ext = NULL; | td->special[tdi].val = NULL; | ||||
| td->val = NULL; | |||||
| /* store AnimData info in td->extra, for applying mapping when flushing */ | /* store AnimData info in td->basic[tdi].extra, for applying mapping when flushing */ | ||||
| td->extra = adt; | td->basic[tdi].extra = adt; | ||||
| if (selected) { | if (selected) { | ||||
| td->flag |= TD_SELECTED; | td->basic[tdi].flag |= TD_SELECTED; | ||||
| td->dist = 0.0f; | td->prop[tdi].dist = 0.0f; | ||||
| } | } | ||||
| else { | else { | ||||
| td->dist = FLT_MAX; | td->prop[tdi].dist = FLT_MAX; | ||||
| } | } | ||||
| if (ishandle) { | if (ishandle) { | ||||
| td->flag |= TD_NOTIMESNAP; | td->basic[tdi].flag |= TD_NOTIMESNAP; | ||||
| } | } | ||||
| if (intvals) { | if (intvals) { | ||||
| td->flag |= TD_INTVALUES; | td->basic[tdi].flag |= TD_INTVALUES; | ||||
| } | } | ||||
| /* copy space-conversion matrices for dealing with non-uniform scales */ | /* copy space-conversion matrices for dealing with non-uniform scales */ | ||||
| copy_m3_m3(td->mtx, mtx); | copy_m3_m3(td->space[tdi].mtx, mtx); | ||||
| copy_m3_m3(td->smtx, smtx); | copy_m3_m3(td->space[tdi].smtx, smtx); | ||||
| tdg->unit_scale = unit_scale; | tdg->unit_scale = unit_scale; | ||||
| tdg->offset = offset; | tdg->offset = offset; | ||||
| } | } | ||||
| static bool graph_edit_is_translation_mode(TransInfo *t) | static bool graph_edit_is_translation_mode(TransInfo *t) | ||||
| { | { | ||||
| return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE); | return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE); | ||||
| Show All 34 Lines | if (key) { | ||||
| left = right = true; | left = right = true; | ||||
| } | } | ||||
| *r_key = key; | *r_key = key; | ||||
| *r_left_handle = left; | *r_left_handle = left; | ||||
| *r_right_handle = right; | *r_right_handle = right; | ||||
| } | } | ||||
| static void graph_key_shortest_dist( | static void graph_key_shortest_dist(TransInfo *t, | ||||
| TransInfo *t, FCurve *fcu, TransData *td_start, TransData *td, int cfra, bool use_handle) | FCurve *fcu, | ||||
| const TransData *td, | |||||
| int tdi_start, | |||||
| const int tdi, | |||||
| int cfra, | |||||
| bool use_handle) | |||||
| { | { | ||||
| int j = 0; | int j = 0; | ||||
| TransData *td_iter = td_start; | int tdi_iter = tdi_start; | ||||
| bool sel_key, sel_left, sel_right; | bool sel_key, sel_left, sel_right; | ||||
| td->dist = FLT_MAX; | td->prop[tdi].dist = FLT_MAX; | ||||
| for (; j < fcu->totvert; j++) { | for (; j < fcu->totvert; j++) { | ||||
| BezTriple *bezt = fcu->bezt + j; | BezTriple *bezt = fcu->bezt + j; | ||||
| if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | ||||
| graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | ||||
| if (sel_left || sel_key || sel_right) { | if (sel_left || sel_key || sel_right) { | ||||
| td->dist = td->rdist = min_ff(td->dist, fabs(td_iter->center[0] - td->center[0])); | td->prop[tdi].dist = td->prop[tdi].rdist = min_ff( | ||||
| td->prop[tdi].dist, fabs(td->center[tdi_iter][0] - td->center[tdi][0])); | |||||
| } | } | ||||
| td_iter += 3; | tdi_iter += 3; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * It is important to note that this doesn't always act on the selection (like it's usually done), | * It is important to note that this doesn't always act on the selection (like it's usually done), | ||||
| * it acts on a subset of it. E.g. the selection code may leave a hint that we just dragged on a | * it acts on a subset of it. E.g. the selection code may leave a hint that we just dragged on a | ||||
| * left or right handle (SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT/RIGHT) and then we only transform the | * left or right handle (SIPO_RUNTIME_FLAG_TWEAK_HANDLES_LEFT/RIGHT) and then we only transform the | ||||
| * selected left or right handles accordingly. | * selected left or right handles accordingly. | ||||
| * The points to be transformed are tagged with BEZT_FLAG_TEMP_TAG; some lower level curve | * The points to be transformed are tagged with BEZT_FLAG_TEMP_TAG; some lower level curve | ||||
| * functions may need to be made aware of this. It's ugly that these act based on selection state | * functions may need to be made aware of this. It's ugly that these act based on selection state | ||||
| * anyway. | * anyway. | ||||
| */ | */ | ||||
| void createTransGraphEditData(bContext *C, TransInfo *t) | void createTransGraphEditData(bContext *C, TransInfo *t) | ||||
| { | { | ||||
| SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; | SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; | ||||
| Scene *scene = t->scene; | Scene *scene = t->scene; | ||||
| ARegion *region = t->region; | ARegion *region = t->region; | ||||
| View2D *v2d = ®ion->v2d; | View2D *v2d = ®ion->v2d; | ||||
| TransData *td = NULL; | |||||
| TransData2D *td2d = NULL; | TransData2D *td2d = NULL; | ||||
| TransDataGraph *tdg = NULL; | TransDataGraph *tdg = NULL; | ||||
| bAnimContext ac; | bAnimContext ac; | ||||
| ListBase anim_data = {NULL, NULL}; | ListBase anim_data = {NULL, NULL}; | ||||
| bAnimListElem *ale; | bAnimListElem *ale; | ||||
| int filter; | int filter; | ||||
| ▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | if (count == 0) { | ||||
| ANIM_animdata_freelist(&anim_data); | ANIM_animdata_freelist(&anim_data); | ||||
| return; | return; | ||||
| } | } | ||||
| TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | ||||
| /* allocate memory for data */ | /* allocate memory for data */ | ||||
| tc->data_len = count; | tc->data_len = count; | ||||
| TransData *td = tc->data = transform_data_alloc(tc->data_len, TD_BASIC_COMP); | |||||
| int tdi = 0; | |||||
| tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData (Graph Editor)"); | |||||
| /* For each 2d vert a 3d vector is allocated, | /* For each 2d vert a 3d vector is allocated, | ||||
| * so that they can be treated just as if they were 3d verts. */ | * so that they can be treated just as if they were 3d verts. */ | ||||
| tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)"); | tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)"); | ||||
| tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph"); | tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph"); | ||||
| tc->custom.type.use_free = true; | tc->custom.type.use_free = true; | ||||
| td = tc->data; | |||||
| td2d = tc->data_2d; | td2d = tc->data_2d; | ||||
| tdg = tc->custom.type.data; | tdg = tc->custom.type.data; | ||||
| /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */ | /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */ | ||||
| unit_m3(mtx); | unit_m3(mtx); | ||||
| unit_m3(smtx); | unit_m3(smtx); | ||||
| if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) { | if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE)) { | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | ||||
| if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | ||||
| TransDataCurveHandleFlags *hdata = NULL; | TransDataCurveHandleFlags *hdata = NULL; | ||||
| graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | ||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| bool is_sel = (sel_key || sel_left || sel_right); | bool is_sel = (sel_key || sel_left || sel_right); | ||||
| /* we always select all handles for proportional editing if central handle is selected */ | /* we always select all handles for proportional editing if central handle is selected */ | ||||
| initTransDataCurveHandles(td, bezt); | initTransDataCurveHandles(td, tdi, bezt); | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td, | ||||
| tdi, | |||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 0, | 0, | ||||
| is_sel, | is_sel, | ||||
| true, | true, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| initTransDataCurveHandles(td, bezt); | tdi++; | ||||
| bezt_to_transdata(td++, | |||||
| initTransDataCurveHandles(td, tdi, bezt); | |||||
| bezt_to_transdata(td, | |||||
| tdi, | |||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 1, | 1, | ||||
| is_sel, | is_sel, | ||||
| false, | false, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| initTransDataCurveHandles(td, bezt); | tdi++; | ||||
| bezt_to_transdata(td++, | |||||
| initTransDataCurveHandles(td, tdi, bezt); | |||||
| bezt_to_transdata(td, | |||||
| tdi, | |||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 2, | 2, | ||||
| is_sel, | is_sel, | ||||
| true, | true, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| tdi++; | |||||
| if (is_sel) { | if (is_sel) { | ||||
| bezt->f1 |= BEZT_FLAG_TEMP_TAG; | bezt->f1 |= BEZT_FLAG_TEMP_TAG; | ||||
| bezt->f2 |= BEZT_FLAG_TEMP_TAG; | bezt->f2 |= BEZT_FLAG_TEMP_TAG; | ||||
| bezt->f3 |= BEZT_FLAG_TEMP_TAG; | bezt->f3 |= BEZT_FLAG_TEMP_TAG; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* only include handles if selected, irrespective of the interpolation modes. | /* only include handles if selected, irrespective of the interpolation modes. | ||||
| * also, only treat handles specially if the center point isn't selected. | * also, only treat handles specially if the center point isn't selected. | ||||
| */ | */ | ||||
| if (sel_left) { | if (sel_left) { | ||||
| hdata = initTransDataCurveHandles(td, bezt); | hdata = initTransDataCurveHandles(td, tdi, bezt); | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td, | ||||
| tdi, | |||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 0, | 0, | ||||
| sel_left, | sel_left, | ||||
| true, | true, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| tdi++; | |||||
| bezt->f1 |= BEZT_FLAG_TEMP_TAG; | bezt->f1 |= BEZT_FLAG_TEMP_TAG; | ||||
| } | } | ||||
| if (sel_right) { | if (sel_right) { | ||||
| if (hdata == NULL) { | if (hdata == NULL) { | ||||
| hdata = initTransDataCurveHandles(td, bezt); | hdata = initTransDataCurveHandles(td, tdi, bezt); | ||||
| } | } | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td, | ||||
| tdi, | |||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 2, | 2, | ||||
| sel_right, | sel_right, | ||||
| true, | true, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| tdi++; | |||||
| bezt->f3 |= BEZT_FLAG_TEMP_TAG; | bezt->f3 |= BEZT_FLAG_TEMP_TAG; | ||||
| } | } | ||||
| /* only include main vert if selected */ | /* only include main vert if selected */ | ||||
| if (sel_key && !use_local_center) { | if (sel_key && !use_local_center) { | ||||
| /* move handles relative to center */ | /* move handles relative to center */ | ||||
| if (graph_edit_is_translation_mode(t)) { | if (graph_edit_is_translation_mode(t)) { | ||||
| if (sel_left) { | if (sel_left) { | ||||
| td->flag |= TD_MOVEHANDLE1; | td->basic[tdi].flag |= TD_MOVEHANDLE1; | ||||
| } | } | ||||
| if (sel_right) { | if (sel_right) { | ||||
| td->flag |= TD_MOVEHANDLE2; | td->basic[tdi].flag |= TD_MOVEHANDLE2; | ||||
| } | } | ||||
| } | } | ||||
| /* if handles were not selected, store their selection status */ | /* if handles were not selected, store their selection status */ | ||||
| if (!(sel_left) || !(sel_right)) { | if (!(sel_left) || !(sel_right)) { | ||||
| if (hdata == NULL) { | if (hdata == NULL) { | ||||
| hdata = initTransDataCurveHandles(td, bezt); | hdata = initTransDataCurveHandles(td, tdi, bezt); | ||||
| } | } | ||||
| } | } | ||||
| bezt_to_transdata(td++, | bezt_to_transdata(td, | ||||
| tdi, | |||||
| td2d++, | td2d++, | ||||
| tdg++, | tdg++, | ||||
| adt, | adt, | ||||
| bezt, | bezt, | ||||
| 1, | 1, | ||||
| sel_key, | sel_key, | ||||
| false, | false, | ||||
| intvals, | intvals, | ||||
| mtx, | mtx, | ||||
| smtx, | smtx, | ||||
| unit_scale, | unit_scale, | ||||
| offset); | offset); | ||||
| tdi++; | |||||
| bezt->f2 |= BEZT_FLAG_TEMP_TAG; | bezt->f2 |= BEZT_FLAG_TEMP_TAG; | ||||
| } | } | ||||
| /* Special hack (must be done after #initTransDataCurveHandles(), | /* Special hack (must be done after #initTransDataCurveHandles(), | ||||
| * as that stores handle settings to restore...): | * as that stores handle settings to restore...): | ||||
| * | * | ||||
| * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, | * - Check if we've got entire BezTriple selected and we're scaling/rotating that point, | ||||
| * then check if we're using auto-handles. | * then check if we're using auto-handles. | ||||
| * - If so, change them auto-handles to aligned handles so that handles get affected too | * - If so, change them auto-handles to aligned handles so that handles get affected too | ||||
| Show All 10 Lines | for (ale = anim_data.first; ale; ale = ale->next) { | ||||
| } | } | ||||
| /* Sets handles based on the selection */ | /* Sets handles based on the selection */ | ||||
| testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle); | testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle); | ||||
| } | } | ||||
| if (is_prop_edit) { | if (is_prop_edit) { | ||||
| /* loop 2: build transdata arrays */ | /* loop 2: build transdata arrays */ | ||||
| td = tc->data; | tdi = 0; | ||||
| 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); | ||||
| FCurve *fcu = (FCurve *)ale->key_data; | FCurve *fcu = (FCurve *)ale->key_data; | ||||
| TransData *td_start = td; | int tdi_start = tdi; | ||||
| float cfra; | float cfra; | ||||
| /* F-Curve may not have any keyframes */ | /* F-Curve may not have any keyframes */ | ||||
| if (fcu->bezt == NULL || (ale->tag == 0)) { | if (fcu->bezt == NULL || (ale->tag == 0)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* convert current-frame to action-time (slightly less accurate, especially under | /* convert current-frame to action-time (slightly less accurate, especially under | ||||
| * higher scaling ratios, but is faster than converting all points) | * higher scaling ratios, but is faster than converting all points) | ||||
| */ | */ | ||||
| if (adt) { | if (adt) { | ||||
| cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); | cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); | ||||
| } | } | ||||
| else { | else { | ||||
| cfra = (float)CFRA; | cfra = (float)CFRA; | ||||
| } | } | ||||
| for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { | ||||
| /* only include BezTriples whose 'keyframe' occurs on the | /* only include BezTriples whose 'keyframe' occurs on the | ||||
| * same side of the current frame as mouse (if applicable) */ | * same side of the current frame as mouse (if applicable) */ | ||||
| if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | if (FrameOnMouseSide(t->frame_side, bezt->vec[1][0], cfra)) { | ||||
| graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | graph_bezt_get_transform_selection(t, bezt, use_handle, &sel_left, &sel_key, &sel_right); | ||||
| if (sel_left || sel_key) { | if (sel_left || sel_key) { | ||||
| td->dist = td->rdist = 0.0f; | td->prop[tdi].dist = td->prop[tdi].rdist = 0.0f; | ||||
| } | } | ||||
| else { | else { | ||||
| graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | graph_key_shortest_dist(t, fcu, td, tdi_start, tdi, cfra, use_handle); | ||||
| } | } | ||||
| td++; | tdi++; | ||||
| if (sel_key) { | if (sel_key) { | ||||
| td->dist = td->rdist = 0.0f; | td->prop[tdi].dist = td->prop[tdi].rdist = 0.0f; | ||||
| } | } | ||||
| else { | else { | ||||
| graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | graph_key_shortest_dist(t, fcu, td, tdi_start, tdi, cfra, use_handle); | ||||
| } | } | ||||
| td++; | tdi++; | ||||
| if (sel_right || sel_key) { | if (sel_right || sel_key) { | ||||
| td->dist = td->rdist = 0.0f; | td->prop[tdi].dist = td->prop[tdi].rdist = 0.0f; | ||||
| } | } | ||||
| else { | else { | ||||
| graph_key_shortest_dist(t, fcu, td_start, td, cfra, use_handle); | graph_key_shortest_dist(t, fcu, td, tdi_start, tdi, cfra, use_handle); | ||||
| } | } | ||||
| td++; | tdi++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* cleanup temp list */ | /* cleanup temp list */ | ||||
| ANIM_animdata_freelist(&anim_data); | ANIM_animdata_freelist(&anim_data); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Graph Editor Transform Flush | /** \name Graph Editor Transform Flush | ||||
| * | * | ||||
| * \{ */ | * \{ */ | ||||
| /* this function is called on recalcData to apply the transforms applied | /* this function is called on recalcData to apply the transforms applied | ||||
| * to the transdata on to the actual keyframe data | * to the transdata on to the actual keyframe data | ||||
| */ | */ | ||||
| void flushTransGraphData(TransInfo *t) | void flushTransGraphData(TransInfo *t) | ||||
| { | { | ||||
| SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; | SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; | ||||
| TransData *td; | |||||
| TransData2D *td2d; | TransData2D *td2d; | ||||
| TransDataGraph *tdg; | TransDataGraph *tdg; | ||||
| Scene *scene = t->scene; | Scene *scene = t->scene; | ||||
| double secf = FPS; | double secf = FPS; | ||||
| int a; | int tdi; | ||||
| TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | ||||
| /* flush to 2d vector from internally used 3d vector */ | /* flush to 2d vector from internally used 3d vector */ | ||||
| for (a = 0, td = tc->data, td2d = tc->data_2d, tdg = tc->custom.type.data; a < tc->data_len; | TransData *td = tc->data; | ||||
| a++, td++, td2d++, tdg++) { | for (tdi = 0, td2d = tc->data_2d, tdg = tc->custom.type.data; tdi < tc->data_len; | ||||
| /* pointers to relevant AnimData blocks are stored in the td->extra pointers */ | td2d++, tdg++, tdi++) { | ||||
| AnimData *adt = (AnimData *)td->extra; | /* pointers to relevant AnimData blocks are stored in the td->basic[tdi].extra pointers */ | ||||
| AnimData *adt = (AnimData *)td->basic[tdi].extra; | |||||
| float inv_unit_scale = 1.0f / tdg->unit_scale; | float inv_unit_scale = 1.0f / tdg->unit_scale; | ||||
| /* Handle snapping for time values: | /* Handle snapping for time values: | ||||
| * - We should still be in NLA-mapping time-space. | * - We should still be in NLA-mapping time-space. | ||||
| * - Only apply to keyframes (but never to handles). | * - Only apply to keyframes (but never to handles). | ||||
| * - Don't do this when canceling, or else these changes won't go away. | * - Don't do this when canceling, or else these changes won't go away. | ||||
| */ | */ | ||||
| if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0) { | if ((t->state != TRANS_CANCEL) && (td->basic[tdi].flag & TD_NOTIMESNAP) == 0) { | ||||
| switch (sipo->autosnap) { | switch (sipo->autosnap) { | ||||
| case SACTSNAP_FRAME: /* snap to nearest frame */ | case SACTSNAP_FRAME: /* snap to nearest frame */ | ||||
| td2d->loc[0] = floor((double)td2d->loc[0] + 0.5); | td2d->loc[0] = floor((double)td2d->loc[0] + 0.5); | ||||
| break; | break; | ||||
| case SACTSNAP_SECOND: /* snap to nearest second */ | case SACTSNAP_SECOND: /* snap to nearest second */ | ||||
| td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf; | td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf; | ||||
| break; | break; | ||||
| Show All 12 Lines | for (tdi = 0, td2d = tc->data_2d, tdg = tc->custom.type.data; tdi < tc->data_len; | ||||
| else { | else { | ||||
| td2d->loc2d[0] = td2d->loc[0]; | td2d->loc2d[0] = td2d->loc[0]; | ||||
| } | } | ||||
| /** Time-stepping auto-snapping modes don't get applied for Graph Editor transforms, | /** Time-stepping auto-snapping modes don't get applied for Graph Editor transforms, | ||||
| * as these use the generic transform modes which don't account for this sort of thing. | * as these use the generic transform modes which don't account for this sort of thing. | ||||
| * These ones aren't affected by NLA mapping, so we do this after the conversion... | * These ones aren't affected by NLA mapping, so we do this after the conversion... | ||||
| * | * | ||||
| * \note We also have to apply to td->loc, | * \note We also have to apply to td->basic[tdi].loc, | ||||
| * as that's what the handle-adjustment step below looks to, | * as that's what the handle-adjustment step below looks to, | ||||
| * otherwise we get "swimming handles". | * otherwise we get "swimming handles". | ||||
| * | * | ||||
| * \note We don't do this when canceling transforms, or else these changes don't go away. | * \note We don't do this when canceling transforms, or else these changes don't go away. | ||||
| */ | */ | ||||
| if ((t->state != TRANS_CANCEL) && (td->flag & TD_NOTIMESNAP) == 0 && | if ((t->state != TRANS_CANCEL) && (td->basic[tdi].flag & TD_NOTIMESNAP) == 0 && | ||||
| ELEM(sipo->autosnap, SACTSNAP_STEP, SACTSNAP_TSTEP)) { | ELEM(sipo->autosnap, SACTSNAP_STEP, SACTSNAP_TSTEP)) { | ||||
| switch (sipo->autosnap) { | switch (sipo->autosnap) { | ||||
| case SACTSNAP_STEP: /* frame step */ | case SACTSNAP_STEP: /* frame step */ | ||||
| td2d->loc2d[0] = floor((double)td2d->loc[0] + 0.5); | td2d->loc2d[0] = floor((double)td2d->loc[0] + 0.5); | ||||
| td->loc[0] = floor((double)td->loc[0] + 0.5); | td->basic[tdi].loc[0] = floor((double)td->basic[tdi].loc[0] + 0.5); | ||||
| break; | break; | ||||
| case SACTSNAP_TSTEP: /* second step */ | case SACTSNAP_TSTEP: /* second step */ | ||||
| /* XXX: the handle behavior in this case is still not quite right... */ | /* XXX: the handle behavior in this case is still not quite right... */ | ||||
| td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf; | td2d->loc[0] = floor(((double)td2d->loc[0] / secf) + 0.5) * secf; | ||||
| td->loc[0] = floor(((double)td->loc[0] / secf) + 0.5) * secf; | td->basic[tdi].loc[0] = floor(((double)td->basic[tdi].loc[0] / secf) + 0.5) * secf; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| /* if int-values only, truncate to integers */ | /* if int-values only, truncate to integers */ | ||||
| if (td->flag & TD_INTVALUES) { | if (td->basic[tdi].flag & TD_INTVALUES) { | ||||
| td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f); | td2d->loc2d[1] = floorf(td2d->loc[1] * inv_unit_scale - tdg->offset + 0.5f); | ||||
| } | } | ||||
| else { | else { | ||||
| td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset; | td2d->loc2d[1] = td2d->loc[1] * inv_unit_scale - tdg->offset; | ||||
| } | } | ||||
| if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { | if ((td->basic[tdi].flag & TD_MOVEHANDLE1) && td2d->h1) { | ||||
| td2d->h1[0] = td2d->ih1[0] + td->loc[0] - td->iloc[0]; | td2d->h1[0] = td2d->ih1[0] + td->basic[tdi].loc[0] - td->basic[tdi].iloc[0]; | ||||
| td2d->h1[1] = td2d->ih1[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale; | td2d->h1[1] = td2d->ih1[1] + | ||||
| (td->basic[tdi].loc[1] - td->basic[tdi].iloc[1]) * inv_unit_scale; | |||||
| } | } | ||||
| if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { | if ((td->basic[tdi].flag & TD_MOVEHANDLE2) && td2d->h2) { | ||||
| td2d->h2[0] = td2d->ih2[0] + td->loc[0] - td->iloc[0]; | td2d->h2[0] = td2d->ih2[0] + td->basic[tdi].loc[0] - td->basic[tdi].iloc[0]; | ||||
| td2d->h2[1] = td2d->ih2[1] + (td->loc[1] - td->iloc[1]) * inv_unit_scale; | td2d->h2[1] = td2d->ih2[1] + | ||||
| (td->basic[tdi].loc[1] - td->basic[tdi].iloc[1]) * inv_unit_scale; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||