From 46e0ec05ef1fb75fb3e5b4a713a5302ace49e546 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Tue, 9 Jun 2020 20:27:40 -0300 Subject: Cleanup: Move each special_aftertrans_update to their respective TransData file --- .../editors/transform/transform_convert_graph.c | 273 +++++++++++++++++++++ 1 file changed, 273 insertions(+) (limited to 'source/blender/editors/transform/transform_convert_graph.c') diff --git a/source/blender/editors/transform/transform_convert_graph.c b/source/blender/editors/transform/transform_convert_graph.c index 0e77c991300..8886be9ac85 100644 --- a/source/blender/editors/transform/transform_convert_graph.c +++ b/source/blender/editors/transform/transform_convert_graph.c @@ -34,6 +34,7 @@ #include "BKE_report.h" #include "ED_anim_api.h" +#include "ED_keyframes_edit.h" #include "ED_markers.h" #include "UI_view2d.h" @@ -751,6 +752,213 @@ static void flushTransGraphData(TransInfo *t) } } +/* struct for use in re-sorting BezTriples during Graph Editor transform */ +typedef struct BeztMap { + BezTriple *bezt; + uint oldIndex; /* index of bezt in fcu->bezt array before sorting */ + uint newIndex; /* index of bezt in fcu->bezt array after sorting */ + short swapHs; /* swap order of handles (-1=clear; 0=not checked, 1=swap) */ + char pipo, cipo; /* interpolation of current and next segments */ +} BeztMap; + +/* This function converts an FCurve's BezTriple array to a BeztMap array + * NOTE: this allocates memory that will need to get freed later + */ +static BeztMap *bezt_to_beztmaps(BezTriple *bezts, int totvert) +{ + BezTriple *bezt = bezts; + BezTriple *prevbezt = NULL; + BeztMap *bezm, *bezms; + int i; + + /* allocate memory for this array */ + if (totvert == 0 || bezts == NULL) { + return NULL; + } + bezm = bezms = MEM_callocN(sizeof(BeztMap) * totvert, "BeztMaps"); + + /* assign beztriples to beztmaps */ + for (i = 0; i < totvert; i++, bezm++, prevbezt = bezt, bezt++) { + bezm->bezt = bezt; + + bezm->oldIndex = i; + bezm->newIndex = i; + + bezm->pipo = (prevbezt) ? prevbezt->ipo : bezt->ipo; + bezm->cipo = bezt->ipo; + } + + return bezms; +} + +/* This function copies the code of sort_time_ipocurve, but acts on BeztMap structs instead */ +static void sort_time_beztmaps(BeztMap *bezms, int totvert) +{ + BeztMap *bezm; + int i, ok = 1; + + /* keep repeating the process until nothing is out of place anymore */ + while (ok) { + ok = 0; + + bezm = bezms; + i = totvert; + while (i--) { + /* is current bezm out of order (i.e. occurs later than next)? */ + if (i > 0) { + if (bezm->bezt->vec[1][0] > (bezm + 1)->bezt->vec[1][0]) { + bezm->newIndex++; + (bezm + 1)->newIndex--; + + SWAP(BeztMap, *bezm, *(bezm + 1)); + + ok = 1; + } + } + + /* do we need to check if the handles need to be swapped? + * optimization: this only needs to be performed in the first loop + */ + if (bezm->swapHs == 0) { + if ((bezm->bezt->vec[0][0] > bezm->bezt->vec[1][0]) && + (bezm->bezt->vec[2][0] < bezm->bezt->vec[1][0])) { + /* handles need to be swapped */ + bezm->swapHs = 1; + } + else { + /* handles need to be cleared */ + bezm->swapHs = -1; + } + } + + bezm++; + } + } +} + +/* This function firstly adjusts the pointers that the transdata has to each BezTriple */ +static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert) +{ + BezTriple *bezts = fcu->bezt; + BeztMap *bezm; + TransData2D *td2d; + TransData *td; + int i, j; + char *adjusted; + + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); + + /* dynamically allocate an array of chars to mark whether an TransData's + * pointers have been fixed already, so that we don't override ones that are + * already done + */ + adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map"); + + /* for each beztmap item, find if it is used anywhere */ + bezm = bezms; + for (i = 0; i < totvert; i++, bezm++) { + /* loop through transdata, testing if we have a hit + * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped... + */ + td2d = tc->data_2d; + td = tc->data; + for (j = 0; j < tc->data_len; j++, td2d++, td++) { + /* skip item if already marked */ + if (adjusted[j] != 0) { + continue; + } + + /* update all transdata pointers, no need to check for selections etc, + * since only points that are really needed were created as transdata + */ + if (td2d->loc2d == bezm->bezt->vec[0]) { + if (bezm->swapHs == 1) { + td2d->loc2d = (bezts + bezm->newIndex)->vec[2]; + } + else { + td2d->loc2d = (bezts + bezm->newIndex)->vec[0]; + } + adjusted[j] = 1; + } + else if (td2d->loc2d == bezm->bezt->vec[2]) { + if (bezm->swapHs == 1) { + td2d->loc2d = (bezts + bezm->newIndex)->vec[0]; + } + else { + td2d->loc2d = (bezts + bezm->newIndex)->vec[2]; + } + adjusted[j] = 1; + } + else if (td2d->loc2d == bezm->bezt->vec[1]) { + td2d->loc2d = (bezts + bezm->newIndex)->vec[1]; + + /* if only control point is selected, the handle pointers need to be updated as well */ + if (td2d->h1) { + td2d->h1 = (bezts + bezm->newIndex)->vec[0]; + } + if (td2d->h2) { + td2d->h2 = (bezts + bezm->newIndex)->vec[2]; + } + + adjusted[j] = 1; + } + + /* the handle type pointer has to be updated too */ + if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) { + if (bezm->swapHs == 1) { + td->hdata->h1 = &(bezts + bezm->newIndex)->h2; + td->hdata->h2 = &(bezts + bezm->newIndex)->h1; + } + else { + td->hdata->h1 = &(bezts + bezm->newIndex)->h1; + td->hdata->h2 = &(bezts + bezm->newIndex)->h2; + } + } + } + } + + /* free temp memory used for 'adjusted' array */ + MEM_freeN(adjusted); +} + +/* This function is called by recalcData during the Transform loop to recalculate + * the handles of curves and sort the keyframes so that the curves draw correctly. + * It is only called if some keyframes have moved out of order. + * + * anim_data is the list of channels (F-Curves) retrieved already containing the + * channels to work on. It should not be freed here as it may still need to be used. + */ +static void remake_graph_transdata(TransInfo *t, ListBase *anim_data) +{ + SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; + bAnimListElem *ale; + const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0; + + /* sort and reassign verts */ + for (ale = anim_data->first; ale; ale = ale->next) { + FCurve *fcu = (FCurve *)ale->key_data; + + if (fcu->bezt) { + BeztMap *bezm; + + /* adjust transform-data pointers */ + /* note, none of these functions use 'use_handle', it could be removed */ + bezm = bezt_to_beztmaps(fcu->bezt, fcu->totvert); + sort_time_beztmaps(bezm, fcu->totvert); + beztmap_to_data(t, fcu, bezm, fcu->totvert); + + /* free mapping stuff */ + MEM_freeN(bezm); + + /* re-sort actual beztriples (perhaps this could be done using the beztmaps to save time?) */ + sort_time_fcurve(fcu); + + /* make sure handles are all set correctly */ + testhandles_fcurve(fcu, BEZT_FLAG_TEMP_TAG, use_handle); + } + } +} + /* helper for recalcData() - for Graph Editor transforms */ void recalcData_graphedit(TransInfo *t) { @@ -820,3 +1028,68 @@ void recalcData_graphedit(TransInfo *t) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Special After Transform Graph + * \{ */ + +void special_aftertrans_update__graph(bContext *C, TransInfo *t) +{ + SpaceGraph *sipo = (SpaceGraph *)t->area->spacedata.first; + bAnimContext ac; + const bool use_handle = (sipo->flag & SIPO_NOHANDLES) == 0; + + const bool canceled = (t->state == TRANS_CANCEL); + const bool duplicate = (t->mode == TFM_TIME_DUPLICATE); + + /* initialize relevant anim-context 'context' data */ + if (ANIM_animdata_get_context(C, &ac) == 0) { + return; + } + + if (ac.datatype) { + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_CURVE_VISIBLE); + + /* get channels to work on */ + ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ANIM_nla_mapping_get(&ac, ale); + FCurve *fcu = (FCurve *)ale->key_data; + + /* 3 cases here for curve cleanups: + * 1) NOTRANSKEYCULL on -> cleanup of duplicates shouldn't be done + * 2) canceled == 0 -> user confirmed the transform, + * so duplicates should be removed + * 3) canceled + duplicate -> user canceled the transform, + * but we made duplicates, so get rid of these + */ + if ((sipo->flag & SIPO_NOTRANSKEYCULL) == 0 && ((canceled == 0) || (duplicate))) { + if (adt) { + ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0); + posttrans_fcurve_clean(fcu, BEZT_FLAG_TEMP_TAG, use_handle); + ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0); + } + else { + posttrans_fcurve_clean(fcu, BEZT_FLAG_TEMP_TAG, use_handle); + } + } + } + + /* free temp memory */ + ANIM_animdata_freelist(&anim_data); + } + + /* Make sure all F-Curves are set correctly, but not if transform was + * canceled, since then curves were already restored to initial state. + * Note: if the refresh is really needed after cancel then some way + * has to be added to not update handle types (see bug 22289). + */ + if (!canceled) { + ANIM_editkeyframes_refresh(&ac); + } +} + +/** \} */ -- cgit v1.2.3