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:
authormano-wii <germano.costa@ig.com.br>2019-09-05 20:34:54 +0300
committermano-wii <germano.costa@ig.com.br>2019-09-05 20:35:38 +0300
commit4e731ec97bd4b689a725f4bdcd49ab1f5c68c12c (patch)
tree2d38d51d080bc50f6e0e9d4cdc9afb0895744140 /source/blender/editors/transform/transform_convert_curve.c
parentc90b81172b30b15e4f2f9e6a9a454f1d177176ac (diff)
Transform: Split transform_conversions into multiple files.
Part of T68836 `transform conversions.c` is a file that is getting too big (almost 10,000 lines). So it's a good idea to split it into smaller files. differential revision: https://developer.blender.org/D5677
Diffstat (limited to 'source/blender/editors/transform/transform_convert_curve.c')
-rw-r--r--source/blender/editors/transform/transform_convert_curve.c422
1 files changed, 422 insertions, 0 deletions
diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c
new file mode 100644
index 00000000000..487de27aff2
--- /dev/null
+++ b/source/blender/editors/transform/transform_convert_curve.c
@@ -0,0 +1,422 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edtransform
+ */
+
+#include "DNA_curve_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_report.h"
+
+#include "transform.h"
+#include "transform_convert.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Curve/Surfaces Transform Creation
+ *
+ * \{ */
+
+/**
+ * For the purpose of transform code we need to behave as if handles are selected,
+ * even when they aren't (see special case below).
+ */
+static int bezt_select_to_transform_triple_flag(const BezTriple *bezt, const bool hide_handles)
+{
+ int flag = 0;
+
+ if (hide_handles) {
+ if (bezt->f2 & SELECT) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+ else {
+ flag = (((bezt->f1 & SELECT) ? (1 << 0) : 0) | ((bezt->f2 & SELECT) ? (1 << 1) : 0) |
+ ((bezt->f3 & SELECT) ? (1 << 2) : 0));
+ }
+
+ /* Special case for auto & aligned handles:
+ * When a center point is being moved without the handles,
+ * leaving the handles stationary makes no sense and only causes strange behavior,
+ * where one handle is arbitrarily anchored, the other one is aligned and lengthened
+ * based on where the center point is moved. Also a bug when cancelling, see: T52007.
+ *
+ * A more 'correct' solution could be to store handle locations in 'TransDataCurveHandleFlags'.
+ * However that doesn't resolve odd behavior, so best transform the handles in this case.
+ */
+ if ((flag != ((1 << 0) | (1 << 1) | (1 << 2))) && (flag & (1 << 1))) {
+ if (ELEM(bezt->h1, HD_AUTO, HD_ALIGN) && ELEM(bezt->h2, HD_AUTO, HD_ALIGN)) {
+ flag = (1 << 0) | (1 << 1) | (1 << 2);
+ }
+ }
+
+ return flag;
+}
+
+void createTransCurveVerts(TransInfo *t)
+{
+
+#define SEL_F1 (1 << 0)
+#define SEL_F2 (1 << 1)
+#define SEL_F3 (1 << 2)
+
+ t->data_len_all = 0;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ Curve *cu = tc->obedit->data;
+ BLI_assert(cu->editnurb != NULL);
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ int count = 0, countsel = 0;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ View3D *v3d = t->view;
+ short hide_handles = (v3d != NULL) ?
+ ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
+ false;
+
+ /* count total of vertices, check identical as in 2nd loop for making transdata! */
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == 0) {
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+ if (bezt_tx & SEL_F1) {
+ countsel++;
+ }
+ if (bezt_tx & SEL_F2) {
+ countsel++;
+ }
+ if (bezt_tx & SEL_F3) {
+ countsel++;
+ }
+ if (is_prop_edit) {
+ count += 3;
+ }
+ }
+ }
+ }
+ else {
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
+ if (bp->hide == 0) {
+ if (is_prop_edit) {
+ count++;
+ }
+ if (bp->f1 & SELECT) {
+ countsel++;
+ }
+ }
+ }
+ }
+ }
+ /* note: in prop mode we need at least 1 selected */
+ if (countsel == 0) {
+ tc->data_len = 0;
+ continue;
+ }
+
+ if (is_prop_edit) {
+ tc->data_len = count;
+ }
+ else {
+ tc->data_len = countsel;
+ }
+ tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Curve EditMode)");
+
+ t->data_len_all += tc->data_len;
+ }
+
+ transform_around_single_fallback(t);
+ t->data_len_all = -1;
+
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ if (tc->data_len == 0) {
+ continue;
+ }
+
+ Curve *cu = tc->obedit->data;
+ BezTriple *bezt;
+ BPoint *bp;
+ int a;
+ const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
+ View3D *v3d = t->view;
+ short hide_handles = (v3d != NULL) ?
+ ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) :
+ false;
+
+ float mtx[3][3], smtx[3][3];
+
+ copy_m3_m4(mtx, tc->obedit->obmat);
+ pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
+
+ TransData *td = tc->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ for (Nurb *nu = nurbs->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ TransData *head, *tail;
+ head = tail = td;
+ for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) {
+ if (bezt->hide == 0) {
+ TransDataCurveHandleFlags *hdata = NULL;
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bezt_calc_normal(nu, bezt, normal);
+ BKE_nurb_bezt_calc_plane(nu, bezt, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+
+ /* Elements that will be transform (not always a match to selection). */
+ const int bezt_tx = bezt_select_to_transform_triple_flag(bezt, hide_handles);
+
+ if (is_prop_edit || bezt_tx & SEL_F1) {
+ copy_v3_v3(td->iloc, bezt->vec[0]);
+ td->loc = bezt->vec[0];
+ copy_v3_v3(td->center,
+ bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
+ (bezt->f2 & SELECT)) ?
+ 1 :
+ 0]);
+ if (hide_handles) {
+ if (bezt->f2 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ }
+ else {
+ if (bezt->f1 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ }
+ td->ext = NULL;
+ td->val = NULL;
+
+ hdata = initTransDataCurveHandles(td, bezt);
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ td++;
+ tail++;
+ }
+
+ /* This is the Curve Point, the other two are handles */
+ if (is_prop_edit || bezt_tx & SEL_F2) {
+ copy_v3_v3(td->iloc, bezt->vec[1]);
+ td->loc = bezt->vec[1];
+ copy_v3_v3(td->center, td->loc);
+ if (bezt->f2 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ td->ext = NULL;
+
+ /* TODO - make points scale */
+ if (t->mode == TFM_CURVE_SHRINKFATTEN) { /* || t->mode==TFM_RESIZE) {*/
+ td->val = &(bezt->radius);
+ td->ival = bezt->radius;
+ }
+ else if (t->mode == TFM_TILT) {
+ td->val = &(bezt->tilt);
+ td->ival = bezt->tilt;
+ }
+ else {
+ td->val = NULL;
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0) {
+ /* If the middle is selected but the sides arnt, this is needed */
+ if (hdata == NULL) {
+ /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+ }
+
+ td++;
+ tail++;
+ }
+ if (is_prop_edit || bezt_tx & SEL_F3) {
+ copy_v3_v3(td->iloc, bezt->vec[2]);
+ td->loc = bezt->vec[2];
+ copy_v3_v3(td->center,
+ bezt->vec[(hide_handles || (t->around == V3D_AROUND_LOCAL_ORIGINS) ||
+ (bezt->f2 & SELECT)) ?
+ 1 :
+ 2]);
+ if (hide_handles) {
+ if (bezt->f2 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ }
+ else {
+ if (bezt->f3 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ }
+ td->ext = NULL;
+ td->val = NULL;
+
+ if (hdata == NULL) {
+ /* if the handle was not saved by the previous handle */
+ hdata = initTransDataCurveHandles(td, bezt);
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+
+ td++;
+ tail++;
+ }
+
+ (void)hdata; /* quiet warning */
+ }
+ else if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ head = tail;
+ }
+ }
+ if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+
+ /* TODO - in the case of tilt and radius we can also avoid allocating the
+ * initTransDataCurveHandles but for now just don't change handle types */
+ if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) {
+ /* sets the handles based on their selection,
+ * do this after the data is copied to the TransData */
+ BKE_nurb_handles_test(nu, !hide_handles);
+ }
+ }
+ else {
+ TransData *head, *tail;
+ head = tail = td;
+ for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a > 0; a--, bp++) {
+ if (bp->hide == 0) {
+ if (is_prop_edit || (bp->f1 & SELECT)) {
+ float axismtx[3][3];
+
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ float normal[3], plane[3];
+
+ BKE_nurb_bpoint_calc_normal(nu, bp, normal);
+ BKE_nurb_bpoint_calc_plane(nu, bp, plane);
+
+ if (createSpaceNormalTangent(axismtx, normal, plane)) {
+ /* pass */
+ }
+ else {
+ normalize_v3(normal);
+ axis_dominant_v3_to_m3(axismtx, normal);
+ invert_m3(axismtx);
+ }
+ }
+ }
+
+ copy_v3_v3(td->iloc, bp->vec);
+ td->loc = bp->vec;
+ copy_v3_v3(td->center, td->loc);
+ if (bp->f1 & SELECT) {
+ td->flag = TD_SELECTED;
+ }
+ else {
+ td->flag = 0;
+ }
+ td->ext = NULL;
+
+ if (t->mode == TFM_CURVE_SHRINKFATTEN || t->mode == TFM_RESIZE) {
+ td->val = &(bp->radius);
+ td->ival = bp->radius;
+ }
+ else {
+ td->val = &(bp->tilt);
+ td->ival = bp->tilt;
+ }
+
+ copy_m3_m3(td->smtx, smtx);
+ copy_m3_m3(td->mtx, mtx);
+ if (t->around == V3D_AROUND_LOCAL_ORIGINS) {
+ if (nu->pntsv == 1) {
+ copy_m3_m3(td->axismtx, axismtx);
+ }
+ }
+
+ td++;
+ tail++;
+ }
+ }
+ else if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ head = tail;
+ }
+ }
+ if (is_prop_edit && head != tail) {
+ calc_distanceCurveVerts(head, tail - 1);
+ }
+ }
+ }
+ }
+#undef SEL_F1
+#undef SEL_F2
+#undef SEL_F3
+}
+
+/** \} */