diff options
author | mano-wii <germano.costa@ig.com.br> | 2019-09-05 20:34:54 +0300 |
---|---|---|
committer | mano-wii <germano.costa@ig.com.br> | 2019-09-05 20:35:38 +0300 |
commit | 4e731ec97bd4b689a725f4bdcd49ab1f5c68c12c (patch) | |
tree | 2d38d51d080bc50f6e0e9d4cdc9afb0895744140 /source/blender/editors/transform/transform_convert_curve.c | |
parent | c90b81172b30b15e4f2f9e6a9a454f1d177176ac (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.c | 422 |
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 +} + +/** \} */ |