diff options
Diffstat (limited to 'source/blender/editors/transform/transform_convert_mask.c')
-rw-r--r-- | source/blender/editors/transform/transform_convert_mask.c | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c new file mode 100644 index 00000000000..32152442acf --- /dev/null +++ b/source/blender/editors/transform/transform_convert_mask.c @@ -0,0 +1,442 @@ +/* + * 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_mask_types.h" +#include "DNA_space_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_context.h" +#include "BKE_mask.h" +#include "BKE_report.h" + +#include "ED_clip.h" +#include "ED_mask.h" + +#include "transform.h" +#include "transform_convert.h" + +typedef struct TransDataMasking { + bool is_handle; + + float handle[2], orig_handle[2]; + float vec[3][3]; + struct MaskSplinePoint *point; + float parent_matrix[3][3]; + float parent_inverse_matrix[3][3]; + char orig_handle_type; + + eMaskWhichHandle which_handle; +} TransDataMasking; + +/* -------------------------------------------------------------------- */ +/** \name Masking Transform Creation + * + * \{ */ + +static void MaskHandleToTransData(MaskSplinePoint *point, + eMaskWhichHandle which_handle, + TransData *td, + TransData2D *td2d, + TransDataMasking *tdm, + const float asp[2], + /*const*/ const float parent_matrix[3][3], + /*const*/ const float parent_inverse_matrix[3][3]) +{ + BezTriple *bezt = &point->bezt; + const bool is_sel_any = MASKPOINT_ISSEL_ANY(point); + + tdm->point = point; + copy_m3_m3(tdm->vec, bezt->vec); + + tdm->is_handle = true; + copy_m3_m3(tdm->parent_matrix, parent_matrix); + copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix); + + BKE_mask_point_handle(point, which_handle, tdm->handle); + tdm->which_handle = which_handle; + + copy_v2_v2(tdm->orig_handle, tdm->handle); + + mul_v2_m3v2(td2d->loc, parent_matrix, tdm->handle); + td2d->loc[0] *= asp[0]; + td2d->loc[1] *= asp[1]; + td2d->loc[2] = 0.0f; + + td2d->loc2d = tdm->handle; + + td->flag = 0; + td->loc = td2d->loc; + mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]); + td->center[0] *= asp[0]; + td->center[1] *= asp[1]; + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext = NULL; + td->val = NULL; + + if (is_sel_any) { + td->flag |= TD_SELECTED; + } + + td->dist = 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + if (which_handle == MASK_WHICH_HANDLE_LEFT) { + tdm->orig_handle_type = bezt->h1; + } + else if (which_handle == MASK_WHICH_HANDLE_RIGHT) { + tdm->orig_handle_type = bezt->h2; + } +} + +static void MaskPointToTransData(Scene *scene, + MaskSplinePoint *point, + TransData *td, + TransData2D *td2d, + TransDataMasking *tdm, + const bool is_prop_edit, + const float asp[2]) +{ + BezTriple *bezt = &point->bezt; + const bool is_sel_point = MASKPOINT_ISSEL_KNOT(point); + const bool is_sel_any = MASKPOINT_ISSEL_ANY(point); + float parent_matrix[3][3], parent_inverse_matrix[3][3]; + + BKE_mask_point_parent_matrix_get(point, CFRA, parent_matrix); + invert_m3_m3(parent_inverse_matrix, parent_matrix); + + if (is_prop_edit || is_sel_point) { + int i; + + tdm->point = point; + copy_m3_m3(tdm->vec, bezt->vec); + + for (i = 0; i < 3; i++) { + copy_m3_m3(tdm->parent_matrix, parent_matrix); + copy_m3_m3(tdm->parent_inverse_matrix, parent_inverse_matrix); + + /* CV coords are scaled by aspects. this is needed for rotations and + * proportional editing to be consistent with the stretched CV coords + * that are displayed. this also means that for display and numinput, + * and when the CV coords are flushed, these are converted each time */ + mul_v2_m3v2(td2d->loc, parent_matrix, bezt->vec[i]); + td2d->loc[0] *= asp[0]; + td2d->loc[1] *= asp[1]; + td2d->loc[2] = 0.0f; + + td2d->loc2d = bezt->vec[i]; + + td->flag = 0; + td->loc = td2d->loc; + mul_v2_m3v2(td->center, parent_matrix, bezt->vec[1]); + td->center[0] *= asp[0]; + td->center[1] *= asp[1]; + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext = NULL; + + if (i == 1) { + /* scaling weights */ + td->val = &bezt->weight; + td->ival = *td->val; + } + else { + td->val = NULL; + } + + if (is_sel_any) { + td->flag |= TD_SELECTED; + } + td->dist = 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + if (i == 0) { + tdm->orig_handle_type = bezt->h1; + } + else if (i == 2) { + tdm->orig_handle_type = bezt->h2; + } + + td++; + td2d++; + tdm++; + } + } + else { + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { + MaskHandleToTransData(point, + MASK_WHICH_HANDLE_STICK, + td, + td2d, + tdm, + asp, + parent_matrix, + parent_inverse_matrix); + + td++; + td2d++; + tdm++; + } + else { + if (bezt->f1 & SELECT) { + MaskHandleToTransData(point, + MASK_WHICH_HANDLE_LEFT, + td, + td2d, + tdm, + asp, + parent_matrix, + parent_inverse_matrix); + + if (bezt->h1 == HD_VECT) { + bezt->h1 = HD_FREE; + } + else if (bezt->h1 == HD_AUTO) { + bezt->h1 = HD_ALIGN_DOUBLESIDE; + bezt->h2 = HD_ALIGN_DOUBLESIDE; + } + + td++; + td2d++; + tdm++; + } + if (bezt->f3 & SELECT) { + MaskHandleToTransData(point, + MASK_WHICH_HANDLE_RIGHT, + td, + td2d, + tdm, + asp, + parent_matrix, + parent_inverse_matrix); + + if (bezt->h2 == HD_VECT) { + bezt->h2 = HD_FREE; + } + else if (bezt->h2 == HD_AUTO) { + bezt->h1 = HD_ALIGN_DOUBLESIDE; + bezt->h2 = HD_ALIGN_DOUBLESIDE; + } + + td++; + td2d++; + tdm++; + } + } + } +} + +void createTransMaskingData(bContext *C, TransInfo *t) +{ + Scene *scene = CTX_data_scene(C); + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *masklay; + TransData *td = NULL; + TransData2D *td2d = NULL; + TransDataMasking *tdm = NULL; + int count = 0, countsel = 0; + const bool is_prop_edit = (t->flag & T_PROP_EDIT); + float asp[2]; + + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); + + tc->data_len = 0; + + if (!mask) { + return; + } + + if (t->spacetype == SPACE_CLIP) { + SpaceClip *sc = t->sa->spacedata.first; + MovieClip *clip = ED_space_clip_get_clip(sc); + if (!clip) { + return; + } + } + + /* count */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (MASKPOINT_ISSEL_ANY(point)) { + if (MASKPOINT_ISSEL_KNOT(point)) { + countsel += 3; + } + else { + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { + countsel += 1; + } + else { + BezTriple *bezt = &point->bezt; + if (bezt->f1 & SELECT) { + countsel++; + } + if (bezt->f3 & SELECT) { + countsel++; + } + } + } + } + + if (is_prop_edit) { + count += 3; + } + } + } + } + + /* note: in prop mode we need at least 1 selected */ + if (countsel == 0) { + return; + } + + ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]); + + tc->data_len = (is_prop_edit) ? count : countsel; + td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransObData(Mask Editing)"); + /* for each 2d uv coord a 3d vector is allocated, so that they can be + * treated just as if they were 3d verts */ + td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), + "TransObData2D(Mask Editing)"); + tc->custom.type.data = tdm = MEM_callocN(tc->data_len * sizeof(TransDataMasking), + "TransDataMasking(Mask Editing)"); + tc->custom.type.use_free = true; + + /* create data */ + for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + MaskSpline *spline; + + if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + + for (spline = masklay->splines.first; spline; spline = spline->next) { + int i; + + for (i = 0; i < spline->tot_point; i++) { + MaskSplinePoint *point = &spline->points[i]; + + if (is_prop_edit || MASKPOINT_ISSEL_ANY(point)) { + MaskPointToTransData(scene, point, td, td2d, tdm, is_prop_edit, asp); + + if (is_prop_edit || MASKPOINT_ISSEL_KNOT(point)) { + td += 3; + td2d += 3; + tdm += 3; + } + else { + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { + td++; + td2d++; + tdm++; + } + else { + BezTriple *bezt = &point->bezt; + if (bezt->f1 & SELECT) { + td++; + td2d++; + tdm++; + } + if (bezt->f3 & SELECT) { + td++; + td2d++; + tdm++; + } + } + } + } + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Masking Transform Flush + * + * \{ */ + +void flushTransMasking(TransInfo *t) +{ + TransData2D *td; + TransDataMasking *tdm; + int a; + float asp[2], inv[2]; + + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); + + ED_mask_get_aspect(t->sa, t->ar, &asp[0], &asp[1]); + inv[0] = 1.0f / asp[0]; + inv[1] = 1.0f / asp[1]; + + /* flush to 2d vector from internally used 3d vector */ + for (a = 0, td = tc->data_2d, tdm = tc->custom.type.data; a < tc->data_len; a++, td++, tdm++) { + td->loc2d[0] = td->loc[0] * inv[0]; + td->loc2d[1] = td->loc[1] * inv[1]; + mul_m3_v2(tdm->parent_inverse_matrix, td->loc2d); + + if (tdm->is_handle) { + BKE_mask_point_set_handle(tdm->point, + tdm->which_handle, + td->loc2d, + (t->flag & T_ALT_TRANSFORM) != 0, + tdm->orig_handle, + tdm->vec); + } + + if (t->state == TRANS_CANCEL) { + if (tdm->which_handle == MASK_WHICH_HANDLE_LEFT) { + tdm->point->bezt.h1 = tdm->orig_handle_type; + } + else if (tdm->which_handle == MASK_WHICH_HANDLE_RIGHT) { + tdm->point->bezt.h2 = tdm->orig_handle_type; + } + } + } +} + +/** \} */ |