Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2020-06-10 02:27:40 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2020-06-10 02:27:51 +0300
commit46e0ec05ef1fb75fb3e5b4a713a5302ace49e546 (patch)
tree8eff449f33050c445ee3367c941da57b8b61882e /source/blender/editors/transform/transform_convert_graph.c
parent63a40ed422bc61e9cd952282a636c53a9d8f3fde (diff)
Cleanup: Move each special_aftertrans_update to their respective TransData file
Diffstat (limited to 'source/blender/editors/transform/transform_convert_graph.c')
-rw-r--r--source/blender/editors/transform/transform_convert_graph.c273
1 files changed, 273 insertions, 0 deletions
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);
+ }
+}
+
+/** \} */