diff options
Diffstat (limited to 'source/blender/editors/transform/transform.c')
-rw-r--r-- | source/blender/editors/transform/transform.c | 15383 |
1 files changed, 7794 insertions, 7589 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 1358b526bca..944c6436dfb 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -35,7 +35,7 @@ #include "DNA_mask_types.h" #include "DNA_mesh_types.h" #include "DNA_movieclip_types.h" -#include "DNA_scene_types.h" /* PET modes */ +#include "DNA_scene_types.h" /* PET modes */ #include "DNA_workspace_types.h" #include "DNA_gpencil_types.h" @@ -107,7 +107,8 @@ static void drawEdgeSlide(TransInfo *t); static void drawVertSlide(TransInfo *t); static void postInputRotation(TransInfo *t, float values[3]); -static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around); +static void ElementRotation( + TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around); static void initSnapSpatial(TransInfo *t, float r_snap[3]); static void storeCustomLNorValue(TransDataContainer *t, BMesh *bm); @@ -175,7 +176,8 @@ static void applyBoneEnvelope(TransInfo *t, const int mval[2]); static void initBoneRoll(TransInfo *t); static void applyBoneRoll(TransInfo *t, const int mval[2]); -static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp); +static void initEdgeSlide_ex( + TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp); static void initEdgeSlide(TransInfo *t); static eRedrawFlag handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event); static void applyEdgeSlide(TransInfo *t, const int mval[2]); @@ -210,496 +212,489 @@ static void initGPOpacity(TransInfo *t); static void applyGPOpacity(TransInfo *t, const int mval[2]); /* end transform callbacks */ - static bool transdata_check_local_center(TransInfo *t, short around) { - return ((around == V3D_AROUND_LOCAL_ORIGINS) && ( - (t->flag & (T_OBJECT | T_POSE)) || - /* implicit: (t->flag & T_EDIT) */ - (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) || - (t->spacetype == SPACE_GRAPH) || - (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE))) - ); + return ((around == V3D_AROUND_LOCAL_ORIGINS) && + ((t->flag & (T_OBJECT | T_POSE)) || + /* implicit: (t->flag & T_EDIT) */ + (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) || + (t->spacetype == SPACE_GRAPH) || + (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE)))); } bool transdata_check_local_islands(TransInfo *t, short around) { - return ((around == V3D_AROUND_LOCAL_ORIGINS) && ( - (ELEM(t->obedit_type, OB_MESH)))); + return ((around == V3D_AROUND_LOCAL_ORIGINS) && ((ELEM(t->obedit_type, OB_MESH)))); } /* ************************** SPACE DEPENDENT CODE **************************** */ void setTransformViewMatrices(TransInfo *t) { - if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) { - RegionView3D *rv3d = t->ar->regiondata; + if (t->spacetype == SPACE_VIEW3D && t->ar && t->ar->regiontype == RGN_TYPE_WINDOW) { + RegionView3D *rv3d = t->ar->regiondata; - copy_m4_m4(t->viewmat, rv3d->viewmat); - copy_m4_m4(t->viewinv, rv3d->viewinv); - copy_m4_m4(t->persmat, rv3d->persmat); - copy_m4_m4(t->persinv, rv3d->persinv); - t->persp = rv3d->persp; - } - else { - unit_m4(t->viewmat); - unit_m4(t->viewinv); - unit_m4(t->persmat); - unit_m4(t->persinv); - t->persp = RV3D_ORTHO; - } + copy_m4_m4(t->viewmat, rv3d->viewmat); + copy_m4_m4(t->viewinv, rv3d->viewinv); + copy_m4_m4(t->persmat, rv3d->persmat); + copy_m4_m4(t->persinv, rv3d->persinv); + t->persp = rv3d->persp; + } + else { + unit_m4(t->viewmat); + unit_m4(t->viewinv); + unit_m4(t->persmat); + unit_m4(t->persinv); + t->persp = RV3D_ORTHO; + } - calculateCenter2D(t); - calculateCenterLocal(t, t->center_global); + calculateCenter2D(t); + calculateCenterLocal(t, t->center_global); } void setTransformViewAspect(TransInfo *t, float r_aspect[3]) { - copy_v3_fl(r_aspect, 1.0f); - - if (t->spacetype == SPACE_IMAGE) { - SpaceImage *sima = t->sa->spacedata.first; - - if (t->options & CTX_MASK) { - ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]); - } - else if (t->options & CTX_PAINT_CURVE) { - /* pass */ - } - else { - ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]); - } - } - else if (t->spacetype == SPACE_CLIP) { - SpaceClip *sclip = t->sa->spacedata.first; - - if (t->options & CTX_MOVIECLIP) { - ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]); - } - else { - ED_space_clip_get_aspect(sclip, &r_aspect[0], &r_aspect[1]); - } - } - else if (t->spacetype == SPACE_GRAPH) { - /* depemds on context of usage */ - } + copy_v3_fl(r_aspect, 1.0f); + + if (t->spacetype == SPACE_IMAGE) { + SpaceImage *sima = t->sa->spacedata.first; + + if (t->options & CTX_MASK) { + ED_space_image_get_aspect(sima, &r_aspect[0], &r_aspect[1]); + } + else if (t->options & CTX_PAINT_CURVE) { + /* pass */ + } + else { + ED_space_image_get_uv_aspect(sima, &r_aspect[0], &r_aspect[1]); + } + } + else if (t->spacetype == SPACE_CLIP) { + SpaceClip *sclip = t->sa->spacedata.first; + + if (t->options & CTX_MOVIECLIP) { + ED_space_clip_get_aspect_dimension_aware(sclip, &r_aspect[0], &r_aspect[1]); + } + else { + ED_space_clip_get_aspect(sclip, &r_aspect[0], &r_aspect[1]); + } + } + else if (t->spacetype == SPACE_GRAPH) { + /* depemds on context of usage */ + } } static void convertViewVec2D(View2D *v2d, float r_vec[3], int dx, int dy) { - float divx = BLI_rcti_size_x(&v2d->mask); - float divy = BLI_rcti_size_y(&v2d->mask); + float divx = BLI_rcti_size_x(&v2d->mask); + float divy = BLI_rcti_size_y(&v2d->mask); - r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx; - r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy; - r_vec[2] = 0.0f; + r_vec[0] = BLI_rctf_size_x(&v2d->cur) * dx / divx; + r_vec[1] = BLI_rctf_size_y(&v2d->cur) * dy / divy; + r_vec[2] = 0.0f; } static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy) { - float divx = BLI_rcti_size_x(&v2d->mask); - float divy = BLI_rcti_size_y(&v2d->mask); + float divx = BLI_rcti_size_x(&v2d->mask); + float divy = BLI_rcti_size_y(&v2d->mask); - float mulx = BLI_rctf_size_x(&v2d->cur); - float muly = BLI_rctf_size_y(&v2d->cur); + float mulx = BLI_rctf_size_x(&v2d->cur); + float muly = BLI_rctf_size_y(&v2d->cur); - /* difference with convertViewVec2D */ - /* clamp w/h, mask only */ - if (mulx / divx < muly / divy) { - divy = divx; - muly = mulx; - } - else { - divx = divy; - mulx = muly; - } - /* end difference */ + /* difference with convertViewVec2D */ + /* clamp w/h, mask only */ + if (mulx / divx < muly / divy) { + divy = divx; + muly = mulx; + } + else { + divx = divy; + mulx = muly; + } + /* end difference */ - r_vec[0] = mulx * dx / divx; - r_vec[1] = muly * dy / divy; - r_vec[2] = 0.0f; + r_vec[0] = mulx * dx / divx; + r_vec[1] = muly * dy / divy; + r_vec[2] = 0.0f; } void convertViewVec(TransInfo *t, float r_vec[3], double dx, double dy) { - if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) { - if (t->options & CTX_PAINT_CURVE) { - r_vec[0] = dx; - r_vec[1] = dy; - } - else { - const float mval_f[2] = {(float)dx, (float)dy}; - ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac); - } - } - else if (t->spacetype == SPACE_IMAGE) { - if (t->options & CTX_MASK) { - convertViewVec2D_mask(t->view, r_vec, dx, dy); - } - else if (t->options & CTX_PAINT_CURVE) { - r_vec[0] = dx; - r_vec[1] = dy; - } - else { - convertViewVec2D(t->view, r_vec, dx, dy); - } - - r_vec[0] *= t->aspect[0]; - r_vec[1] *= t->aspect[1]; - } - else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { - convertViewVec2D(t->view, r_vec, dx, dy); - } - else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { - convertViewVec2D(&t->ar->v2d, r_vec, dx, dy); - } - else if (t->spacetype == SPACE_CLIP) { - if (t->options & CTX_MASK) { - convertViewVec2D_mask(t->view, r_vec, dx, dy); - } - else { - convertViewVec2D(t->view, r_vec, dx, dy); - } - - r_vec[0] *= t->aspect[0]; - r_vec[1] *= t->aspect[1]; - } - else { - printf("%s: called in an invalid context\n", __func__); - zero_v3(r_vec); - } + if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) { + if (t->options & CTX_PAINT_CURVE) { + r_vec[0] = dx; + r_vec[1] = dy; + } + else { + const float mval_f[2] = {(float)dx, (float)dy}; + ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac); + } + } + else if (t->spacetype == SPACE_IMAGE) { + if (t->options & CTX_MASK) { + convertViewVec2D_mask(t->view, r_vec, dx, dy); + } + else if (t->options & CTX_PAINT_CURVE) { + r_vec[0] = dx; + r_vec[1] = dy; + } + else { + convertViewVec2D(t->view, r_vec, dx, dy); + } + + r_vec[0] *= t->aspect[0]; + r_vec[1] *= t->aspect[1]; + } + else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { + convertViewVec2D(t->view, r_vec, dx, dy); + } + else if (ELEM(t->spacetype, SPACE_NODE, SPACE_SEQ)) { + convertViewVec2D(&t->ar->v2d, r_vec, dx, dy); + } + else if (t->spacetype == SPACE_CLIP) { + if (t->options & CTX_MASK) { + convertViewVec2D_mask(t->view, r_vec, dx, dy); + } + else { + convertViewVec2D(t->view, r_vec, dx, dy); + } + + r_vec[0] *= t->aspect[0]; + r_vec[1] *= t->aspect[1]; + } + else { + printf("%s: called in an invalid context\n", __func__); + zero_v3(r_vec); + } } void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag) { - if (t->spacetype == SPACE_VIEW3D) { - if (t->ar->regiontype == RGN_TYPE_WINDOW) { - if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { - /* this is what was done in 2.64, perhaps we can be smarter? */ - adr[0] = (int)2140000000.0f; - adr[1] = (int)2140000000.0f; - } - } - } - else if (t->spacetype == SPACE_IMAGE) { - SpaceImage *sima = t->sa->spacedata.first; - - if (t->options & CTX_MASK) { - float v[2]; - - v[0] = vec[0] / t->aspect[0]; - v[1] = vec[1] / t->aspect[1]; - - BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v); - - ED_image_point_pos__reverse(sima, t->ar, v, v); - - adr[0] = v[0]; - adr[1] = v[1]; - } - else if (t->options & CTX_PAINT_CURVE) { - adr[0] = vec[0]; - adr[1] = vec[1]; - } - else { - float v[2]; - - v[0] = vec[0] / t->aspect[0]; - v[1] = vec[1] / t->aspect[1]; - - UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]); - } - } - else if (t->spacetype == SPACE_ACTION) { - int out[2] = {0, 0}; + if (t->spacetype == SPACE_VIEW3D) { + if (t->ar->regiontype == RGN_TYPE_WINDOW) { + if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { + /* this is what was done in 2.64, perhaps we can be smarter? */ + adr[0] = (int)2140000000.0f; + adr[1] = (int)2140000000.0f; + } + } + } + else if (t->spacetype == SPACE_IMAGE) { + SpaceImage *sima = t->sa->spacedata.first; + + if (t->options & CTX_MASK) { + float v[2]; + + v[0] = vec[0] / t->aspect[0]; + v[1] = vec[1] / t->aspect[1]; + + BKE_mask_coord_to_image(sima->image, &sima->iuser, v, v); + + ED_image_point_pos__reverse(sima, t->ar, v, v); + + adr[0] = v[0]; + adr[1] = v[1]; + } + else if (t->options & CTX_PAINT_CURVE) { + adr[0] = vec[0]; + adr[1] = vec[1]; + } + else { + float v[2]; + + v[0] = vec[0] / t->aspect[0]; + v[1] = vec[1] / t->aspect[1]; + + UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]); + } + } + else if (t->spacetype == SPACE_ACTION) { + int out[2] = {0, 0}; #if 0 - SpaceAction *sact = t->sa->spacedata.first; - - if (sact->flag & SACTION_DRAWTIME) { - //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base)); - /* same as below */ - UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); - } - else + SpaceAction *sact = t->sa->spacedata.first; + + if (sact->flag & SACTION_DRAWTIME) { + //vec[0] = vec[0]/((t->scene->r.frs_sec / t->scene->r.frs_sec_base)); + /* same as below */ + UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); + } + else #endif - { - UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); - } - - adr[0] = out[0]; - adr[1] = out[1]; - } - else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { - int out[2] = {0, 0}; - - UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); - adr[0] = out[0]; - adr[1] = out[1]; - } - else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should work */ - int out[2] = {0, 0}; - - UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); - adr[0] = out[0]; - adr[1] = out[1]; - } - else if (t->spacetype == SPACE_CLIP) { - SpaceClip *sc = t->sa->spacedata.first; - - if (t->options & CTX_MASK) { - MovieClip *clip = ED_space_clip_get_clip(sc); - - if (clip) { - float v[2]; - - v[0] = vec[0] / t->aspect[0]; - v[1] = vec[1] / t->aspect[1]; - - BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v); - - ED_clip_point_stable_pos__reverse(sc, t->ar, v, v); - - adr[0] = v[0]; - adr[1] = v[1]; - } - else { - adr[0] = 0; - adr[1] = 0; - } - } - else if (t->options & CTX_MOVIECLIP) { - float v[2]; - - v[0] = vec[0] / t->aspect[0]; - v[1] = vec[1] / t->aspect[1]; - - UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]); - } - else { - BLI_assert(0); - } - } - else if (t->spacetype == SPACE_NODE) { - UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &adr[0], &adr[1]); - } + { + UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); + } + + adr[0] = out[0]; + adr[1] = out[1]; + } + else if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { + int out[2] = {0, 0}; + + UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); + adr[0] = out[0]; + adr[1] = out[1]; + } + else if (t->spacetype == SPACE_SEQ) { /* XXX not tested yet, but should work */ + int out[2] = {0, 0}; + + UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &out[0], &out[1]); + adr[0] = out[0]; + adr[1] = out[1]; + } + else if (t->spacetype == SPACE_CLIP) { + SpaceClip *sc = t->sa->spacedata.first; + + if (t->options & CTX_MASK) { + MovieClip *clip = ED_space_clip_get_clip(sc); + + if (clip) { + float v[2]; + + v[0] = vec[0] / t->aspect[0]; + v[1] = vec[1] / t->aspect[1]; + + BKE_mask_coord_to_movieclip(sc->clip, &sc->user, v, v); + + ED_clip_point_stable_pos__reverse(sc, t->ar, v, v); + + adr[0] = v[0]; + adr[1] = v[1]; + } + else { + adr[0] = 0; + adr[1] = 0; + } + } + else if (t->options & CTX_MOVIECLIP) { + float v[2]; + + v[0] = vec[0] / t->aspect[0]; + v[1] = vec[1] / t->aspect[1]; + + UI_view2d_view_to_region(t->view, v[0], v[1], &adr[0], &adr[1]); + } + else { + BLI_assert(0); + } + } + else if (t->spacetype == SPACE_NODE) { + UI_view2d_view_to_region((View2D *)t->view, vec[0], vec[1], &adr[0], &adr[1]); + } } void projectIntView(TransInfo *t, const float vec[3], int adr[2]) { - projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); + projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); } void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag) { - switch (t->spacetype) { - case SPACE_VIEW3D: - { - if (t->options & CTX_PAINT_CURVE) { - adr[0] = vec[0]; - adr[1] = vec[1]; - } - else if (t->ar->regiontype == RGN_TYPE_WINDOW) { - /* allow points behind the view [#33643] */ - if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { - /* XXX, 2.64 and prior did this, weak! */ - adr[0] = t->ar->winx / 2.0f; - adr[1] = t->ar->winy / 2.0f; - } - return; - } - break; - } - default: - { - int a[2] = {0, 0}; - projectIntView(t, vec, a); - adr[0] = a[0]; - adr[1] = a[1]; - break; - } - } + switch (t->spacetype) { + case SPACE_VIEW3D: { + if (t->options & CTX_PAINT_CURVE) { + adr[0] = vec[0]; + adr[1] = vec[1]; + } + else if (t->ar->regiontype == RGN_TYPE_WINDOW) { + /* allow points behind the view [#33643] */ + if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { + /* XXX, 2.64 and prior did this, weak! */ + adr[0] = t->ar->winx / 2.0f; + adr[1] = t->ar->winy / 2.0f; + } + return; + } + break; + } + default: { + int a[2] = {0, 0}; + projectIntView(t, vec, a); + adr[0] = a[0]; + adr[1] = a[1]; + break; + } + } } void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) { - projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); + projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); } void applyAspectRatio(TransInfo *t, float vec[2]) { - if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && !(t->options & CTX_PAINT_CURVE)) { - SpaceImage *sima = t->sa->spacedata.first; + if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && + !(t->options & CTX_PAINT_CURVE)) { + SpaceImage *sima = t->sa->spacedata.first; - if ((sima->flag & SI_COORDFLOATS) == 0) { - int width, height; - ED_space_image_get_size(sima, &width, &height); + if ((sima->flag & SI_COORDFLOATS) == 0) { + int width, height; + ED_space_image_get_size(sima, &width, &height); - vec[0] *= width; - vec[1] *= height; - } + vec[0] *= width; + vec[1] *= height; + } - vec[0] /= t->aspect[0]; - vec[1] /= t->aspect[1]; - } - else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) { - if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - vec[0] /= t->aspect[0]; - vec[1] /= t->aspect[1]; - } - } + vec[0] /= t->aspect[0]; + vec[1] /= t->aspect[1]; + } + else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { + vec[0] /= t->aspect[0]; + vec[1] /= t->aspect[1]; + } + } } void removeAspectRatio(TransInfo *t, float vec[2]) { - if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) { - SpaceImage *sima = t->sa->spacedata.first; + if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) { + SpaceImage *sima = t->sa->spacedata.first; - if ((sima->flag & SI_COORDFLOATS) == 0) { - int width, height; - ED_space_image_get_size(sima, &width, &height); + if ((sima->flag & SI_COORDFLOATS) == 0) { + int width, height; + ED_space_image_get_size(sima, &width, &height); - vec[0] /= width; - vec[1] /= height; - } + vec[0] /= width; + vec[1] /= height; + } - vec[0] *= t->aspect[0]; - vec[1] *= t->aspect[1]; - } - else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) { - if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - vec[0] *= t->aspect[0]; - vec[1] *= t->aspect[1]; - } - } + vec[0] *= t->aspect[0]; + vec[1] *= t->aspect[1]; + } + else if ((t->spacetype == SPACE_CLIP) && (t->mode == TFM_TRANSLATION)) { + if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { + vec[0] *= t->aspect[0]; + vec[1] *= t->aspect[1]; + } + } } static void viewRedrawForce(const bContext *C, TransInfo *t) { - if (t->options & CTX_GPENCIL_STROKES) { - bGPdata *gpd = ED_gpencil_data_get_active(C); - if (gpd) { - DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); - } - WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); - } - else if (t->spacetype == SPACE_VIEW3D) { - if (t->options & CTX_PAINT_CURVE) { - wmWindow *window = CTX_wm_window(C); - WM_paint_cursor_tag_redraw(window, t->ar); - } - else { - /* Do we need more refined tags? */ - if (t->flag & T_POSE) - WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); - else - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - - /* For real-time animation record - send notifiers recognized by animation editors */ - // XXX: is this notifier a lame duck? - if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL); - - } - } - else if (t->spacetype == SPACE_ACTION) { - //SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - } - else if (t->spacetype == SPACE_GRAPH) { - //SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first; - WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - } - else if (t->spacetype == SPACE_NLA) { - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); - } - else if (t->spacetype == SPACE_NODE) { - //ED_area_tag_redraw(t->sa); - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - } - else if (t->spacetype == SPACE_SEQ) { - WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL); - } - else if (t->spacetype == SPACE_IMAGE) { - if (t->options & CTX_MASK) { - Mask *mask = CTX_data_edit_mask(C); - - WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - } - else if (t->options & CTX_PAINT_CURVE) { - wmWindow *window = CTX_wm_window(C); - WM_paint_cursor_tag_redraw(window, t->ar); - } - else if (t->flag & T_CURSOR) { - ED_area_tag_redraw(t->sa); - } - else { - // XXX how to deal with lock? - SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; - if (sima->lock) { - WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data); - } - else { - ED_area_tag_redraw(t->sa); - } - } - } - else if (t->spacetype == SPACE_CLIP) { - SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first; - - if (ED_space_clip_check_show_trackedit(sc)) { - MovieClip *clip = ED_space_clip_get_clip(sc); - - /* objects could be parented to tracking data, so send this for viewport refresh */ - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - - WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); - } - else if (ED_space_clip_check_show_maskedit(sc)) { - Mask *mask = CTX_data_edit_mask(C); - - WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); - } - } + if (t->options & CTX_GPENCIL_STROKES) { + bGPdata *gpd = ED_gpencil_data_get_active(C); + if (gpd) { + DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); + } + WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); + } + else if (t->spacetype == SPACE_VIEW3D) { + if (t->options & CTX_PAINT_CURVE) { + wmWindow *window = CTX_wm_window(C); + WM_paint_cursor_tag_redraw(window, t->ar); + } + else { + /* Do we need more refined tags? */ + if (t->flag & T_POSE) + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); + else + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + + /* For real-time animation record - send notifiers recognized by animation editors */ + // XXX: is this notifier a lame duck? + if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, NULL); + } + } + else if (t->spacetype == SPACE_ACTION) { + //SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + } + else if (t->spacetype == SPACE_GRAPH) { + //SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first; + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + } + else if (t->spacetype == SPACE_NLA) { + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + } + else if (t->spacetype == SPACE_NODE) { + //ED_area_tag_redraw(t->sa); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); + } + else if (t->spacetype == SPACE_SEQ) { + WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL); + } + else if (t->spacetype == SPACE_IMAGE) { + if (t->options & CTX_MASK) { + Mask *mask = CTX_data_edit_mask(C); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + } + else if (t->options & CTX_PAINT_CURVE) { + wmWindow *window = CTX_wm_window(C); + WM_paint_cursor_tag_redraw(window, t->ar); + } + else if (t->flag & T_CURSOR) { + ED_area_tag_redraw(t->sa); + } + else { + // XXX how to deal with lock? + SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; + if (sima->lock) { + WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data); + } + else { + ED_area_tag_redraw(t->sa); + } + } + } + else if (t->spacetype == SPACE_CLIP) { + SpaceClip *sc = (SpaceClip *)t->sa->spacedata.first; + + if (ED_space_clip_check_show_trackedit(sc)) { + MovieClip *clip = ED_space_clip_get_clip(sc); + + /* objects could be parented to tracking data, so send this for viewport refresh */ + WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); + + WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); + } + else if (ED_space_clip_check_show_maskedit(sc)) { + Mask *mask = CTX_data_edit_mask(C); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + } + } } static void viewRedrawPost(bContext *C, TransInfo *t) { - ED_area_status_text(t->sa, NULL); - - if (t->spacetype == SPACE_VIEW3D) { - /* if autokeying is enabled, send notifiers that keyframes were added */ - if (IS_AUTOKEY_ON(t->scene)) - WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); - - /* redraw UV editor */ - if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) && - (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) - { - WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); - } - - /* XXX temp, first hack to get auto-render in compositor work (ton) */ - WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C)); - - } - -#if 0 // TRANSFORM_FIX_ME - if (t->spacetype == SPACE_VIEW3D) { - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - } - else if (t->spacetype == SPACE_IMAGE) { - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWVIEW3D, 0); - } - else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)) { - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWBUTSOBJECT, 0); - } - - scrarea_queue_headredraw(curarea); + ED_area_status_text(t->sa, NULL); + + if (t->spacetype == SPACE_VIEW3D) { + /* if autokeying is enabled, send notifiers that keyframes were added */ + if (IS_AUTOKEY_ON(t->scene)) + WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* redraw UV editor */ + if (ELEM(t->mode, TFM_VERT_SLIDE, TFM_EDGE_SLIDE) && + (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); + } + + /* XXX temp, first hack to get auto-render in compositor work (ton) */ + WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C)); + } + +#if 0 // TRANSFORM_FIX_ME + if (t->spacetype == SPACE_VIEW3D) { + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); + } + else if (t->spacetype == SPACE_IMAGE) { + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWVIEW3D, 0); + } + else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_GRAPH)) { + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWTIME, 0); + allqueue(REDRAWBUTSOBJECT, 0); + } + + scrarea_queue_headredraw(curarea); #endif } @@ -707,81 +702,81 @@ static void viewRedrawPost(bContext *C, TransInfo *t) static void view_editmove(unsigned short UNUSED(event)) { -#if 0 // TRANSFORM_FIX_ME - int refresh = 0; - /* Regular: Zoom in */ - /* Shift: Scroll up */ - /* Ctrl: Scroll right */ - /* Alt-Shift: Rotate up */ - /* Alt-Ctrl: Rotate right */ - - /* only work in 3D window for now - * In the end, will have to send to event to a 2D window handler instead - */ - if (Trans.flag & T_2D_EDIT) - return; - - switch (event) { - case WHEELUPMOUSE: - if (G.qual & LR_SHIFTKEY) { - if (G.qual & LR_ALTKEY) { - G.qual &= ~LR_SHIFTKEY; - persptoetsen(PAD2); - G.qual |= LR_SHIFTKEY; - } - else { - persptoetsen(PAD2); - } - } - else if (G.qual & LR_CTRLKEY) { - if (G.qual & LR_ALTKEY) { - G.qual &= ~LR_CTRLKEY; - persptoetsen(PAD4); - G.qual |= LR_CTRLKEY; - } - else { - persptoetsen(PAD4); - } - } - else if (U.uiflag & USER_WHEELZOOMDIR) - persptoetsen(PADMINUS); - else - persptoetsen(PADPLUSKEY); - - refresh = 1; - break; - case WHEELDOWNMOUSE: - if (G.qual & LR_SHIFTKEY) { - if (G.qual & LR_ALTKEY) { - G.qual &= ~LR_SHIFTKEY; - persptoetsen(PAD8); - G.qual |= LR_SHIFTKEY; - } - else { - persptoetsen(PAD8); - } - } - else if (G.qual & LR_CTRLKEY) { - if (G.qual & LR_ALTKEY) { - G.qual &= ~LR_CTRLKEY; - persptoetsen(PAD6); - G.qual |= LR_CTRLKEY; - } - else { - persptoetsen(PAD6); - } - } - else if (U.uiflag & USER_WHEELZOOMDIR) - persptoetsen(PADPLUSKEY); - else - persptoetsen(PADMINUS); - - refresh = 1; - break; - } - - if (refresh) - setTransformViewMatrices(&Trans); +#if 0 // TRANSFORM_FIX_ME + int refresh = 0; + /* Regular: Zoom in */ + /* Shift: Scroll up */ + /* Ctrl: Scroll right */ + /* Alt-Shift: Rotate up */ + /* Alt-Ctrl: Rotate right */ + + /* only work in 3D window for now + * In the end, will have to send to event to a 2D window handler instead + */ + if (Trans.flag & T_2D_EDIT) + return; + + switch (event) { + case WHEELUPMOUSE: + if (G.qual & LR_SHIFTKEY) { + if (G.qual & LR_ALTKEY) { + G.qual &= ~LR_SHIFTKEY; + persptoetsen(PAD2); + G.qual |= LR_SHIFTKEY; + } + else { + persptoetsen(PAD2); + } + } + else if (G.qual & LR_CTRLKEY) { + if (G.qual & LR_ALTKEY) { + G.qual &= ~LR_CTRLKEY; + persptoetsen(PAD4); + G.qual |= LR_CTRLKEY; + } + else { + persptoetsen(PAD4); + } + } + else if (U.uiflag & USER_WHEELZOOMDIR) + persptoetsen(PADMINUS); + else + persptoetsen(PADPLUSKEY); + + refresh = 1; + break; + case WHEELDOWNMOUSE: + if (G.qual & LR_SHIFTKEY) { + if (G.qual & LR_ALTKEY) { + G.qual &= ~LR_SHIFTKEY; + persptoetsen(PAD8); + G.qual |= LR_SHIFTKEY; + } + else { + persptoetsen(PAD8); + } + } + else if (G.qual & LR_CTRLKEY) { + if (G.qual & LR_ALTKEY) { + G.qual &= ~LR_CTRLKEY; + persptoetsen(PAD6); + G.qual |= LR_CTRLKEY; + } + else { + persptoetsen(PAD6); + } + } + else if (U.uiflag & USER_WHEELZOOMDIR) + persptoetsen(PADPLUSKEY); + else + persptoetsen(PADMINUS); + + refresh = 1; + break; + } + + if (refresh) + setTransformViewMatrices(&Trans); #endif } @@ -789,885 +784,898 @@ static void view_editmove(unsigned short UNUSED(event)) /* NOTE: these defines are saved in keymap files, do not change values but just add new ones */ enum { - TFM_MODAL_CANCEL = 1, - TFM_MODAL_CONFIRM = 2, - TFM_MODAL_TRANSLATE = 3, - TFM_MODAL_ROTATE = 4, - TFM_MODAL_RESIZE = 5, - TFM_MODAL_SNAP_INV_ON = 6, - TFM_MODAL_SNAP_INV_OFF = 7, - TFM_MODAL_SNAP_TOGGLE = 8, - TFM_MODAL_AXIS_X = 9, - TFM_MODAL_AXIS_Y = 10, - TFM_MODAL_AXIS_Z = 11, - TFM_MODAL_PLANE_X = 12, - TFM_MODAL_PLANE_Y = 13, - TFM_MODAL_PLANE_Z = 14, - TFM_MODAL_CONS_OFF = 15, - TFM_MODAL_ADD_SNAP = 16, - TFM_MODAL_REMOVE_SNAP = 17, - -/* 18 and 19 used by numinput, defined in transform.h */ - - TFM_MODAL_PROPSIZE_UP = 20, - TFM_MODAL_PROPSIZE_DOWN = 21, - TFM_MODAL_AUTOIK_LEN_INC = 22, - TFM_MODAL_AUTOIK_LEN_DEC = 23, - - TFM_MODAL_EDGESLIDE_UP = 24, - TFM_MODAL_EDGESLIDE_DOWN = 25, - -/* for analog input, like trackpad */ - TFM_MODAL_PROPSIZE = 26, -/* node editor insert offset (aka auto-offset) direction toggle */ - TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27, + TFM_MODAL_CANCEL = 1, + TFM_MODAL_CONFIRM = 2, + TFM_MODAL_TRANSLATE = 3, + TFM_MODAL_ROTATE = 4, + TFM_MODAL_RESIZE = 5, + TFM_MODAL_SNAP_INV_ON = 6, + TFM_MODAL_SNAP_INV_OFF = 7, + TFM_MODAL_SNAP_TOGGLE = 8, + TFM_MODAL_AXIS_X = 9, + TFM_MODAL_AXIS_Y = 10, + TFM_MODAL_AXIS_Z = 11, + TFM_MODAL_PLANE_X = 12, + TFM_MODAL_PLANE_Y = 13, + TFM_MODAL_PLANE_Z = 14, + TFM_MODAL_CONS_OFF = 15, + TFM_MODAL_ADD_SNAP = 16, + TFM_MODAL_REMOVE_SNAP = 17, + + /* 18 and 19 used by numinput, defined in transform.h */ + + TFM_MODAL_PROPSIZE_UP = 20, + TFM_MODAL_PROPSIZE_DOWN = 21, + TFM_MODAL_AUTOIK_LEN_INC = 22, + TFM_MODAL_AUTOIK_LEN_DEC = 23, + + TFM_MODAL_EDGESLIDE_UP = 24, + TFM_MODAL_EDGESLIDE_DOWN = 25, + + /* for analog input, like trackpad */ + TFM_MODAL_PROPSIZE = 26, + /* node editor insert offset (aka auto-offset) direction toggle */ + TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27, }; static bool transform_modal_item_poll(const wmOperator *op, int value) { - const TransInfo *t = op->customdata; - switch (value) { - case TFM_MODAL_CANCEL: - { - if ((t->flag & T_RELEASE_CONFIRM) && ISMOUSE(t->launch_event)) { - return false; - } - break; - } - case TFM_MODAL_PROPSIZE: - case TFM_MODAL_PROPSIZE_UP: - case TFM_MODAL_PROPSIZE_DOWN: - { - if ((t->flag & T_PROP_EDIT) == 0) { - return false; - } - break; - } - case TFM_MODAL_ADD_SNAP: - case TFM_MODAL_REMOVE_SNAP: - { - if (t->spacetype != SPACE_VIEW3D) { - return false; - } - else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) { - return false; - } - else if (!validSnap(t)) { - return false; - } - break; - } - case TFM_MODAL_AXIS_X: - case TFM_MODAL_AXIS_Y: - case TFM_MODAL_AXIS_Z: - case TFM_MODAL_PLANE_X: - case TFM_MODAL_PLANE_Y: - case TFM_MODAL_PLANE_Z: - { - if (t->flag & T_NO_CONSTRAINT) { - return false; - } - if (!ELEM(value, TFM_MODAL_AXIS_X, TFM_MODAL_AXIS_Y)) { - if (t->flag & T_2D_EDIT) { - return false; - } - } - break; - } - case TFM_MODAL_CONS_OFF: - { - if ((t->con.mode & CON_APPLY) == 0) { - return false; - } - break; - } - case TFM_MODAL_EDGESLIDE_UP: - case TFM_MODAL_EDGESLIDE_DOWN: - { - if (t->mode != TFM_EDGE_SLIDE) { - return false; - } - break; - } - case TFM_MODAL_INSERTOFS_TOGGLE_DIR: - { - if (t->spacetype != SPACE_NODE) { - return false; - } - break; - } - case TFM_MODAL_AUTOIK_LEN_INC: - case TFM_MODAL_AUTOIK_LEN_DEC: - { - if ((t->flag & T_AUTOIK) == 0) { - return false; - } - break; - } - } - return true; + const TransInfo *t = op->customdata; + switch (value) { + case TFM_MODAL_CANCEL: { + if ((t->flag & T_RELEASE_CONFIRM) && ISMOUSE(t->launch_event)) { + return false; + } + break; + } + case TFM_MODAL_PROPSIZE: + case TFM_MODAL_PROPSIZE_UP: + case TFM_MODAL_PROPSIZE_DOWN: { + if ((t->flag & T_PROP_EDIT) == 0) { + return false; + } + break; + } + case TFM_MODAL_ADD_SNAP: + case TFM_MODAL_REMOVE_SNAP: { + if (t->spacetype != SPACE_VIEW3D) { + return false; + } + else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) { + return false; + } + else if (!validSnap(t)) { + return false; + } + break; + } + case TFM_MODAL_AXIS_X: + case TFM_MODAL_AXIS_Y: + case TFM_MODAL_AXIS_Z: + case TFM_MODAL_PLANE_X: + case TFM_MODAL_PLANE_Y: + case TFM_MODAL_PLANE_Z: { + if (t->flag & T_NO_CONSTRAINT) { + return false; + } + if (!ELEM(value, TFM_MODAL_AXIS_X, TFM_MODAL_AXIS_Y)) { + if (t->flag & T_2D_EDIT) { + return false; + } + } + break; + } + case TFM_MODAL_CONS_OFF: { + if ((t->con.mode & CON_APPLY) == 0) { + return false; + } + break; + } + case TFM_MODAL_EDGESLIDE_UP: + case TFM_MODAL_EDGESLIDE_DOWN: { + if (t->mode != TFM_EDGE_SLIDE) { + return false; + } + break; + } + case TFM_MODAL_INSERTOFS_TOGGLE_DIR: { + if (t->spacetype != SPACE_NODE) { + return false; + } + break; + } + case TFM_MODAL_AUTOIK_LEN_INC: + case TFM_MODAL_AUTOIK_LEN_DEC: { + if ((t->flag & T_AUTOIK) == 0) { + return false; + } + break; + } + } + return true; } /* called in transform_ops.c, on each regeneration of keymaps */ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) { - static const EnumPropertyItem modal_items[] = { - {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, - {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, - {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""}, - {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""}, - {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""}, - {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""}, - {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""}, - {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""}, - {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""}, - {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""}, - {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""}, - {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""}, - {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""}, - {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""}, - {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""}, - {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""}, - {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""}, - {TFM_MODAL_PROPSIZE_DOWN, "PROPORTIONAL_SIZE_DOWN", 0, "Decrease Proportional Influence", ""}, - {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""}, - {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""}, - {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""}, - {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""}, - {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""}, - {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, "Toggle Direction for Node Auto-offset", ""}, - {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""}, - {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""}, - {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""}, - {0, NULL, 0, NULL, NULL}, - }; - - wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map"); - - keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items); - keymap->poll_modal_item = transform_modal_item_poll; - - return keymap; + static const EnumPropertyItem modal_items[] = { + {TFM_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, + {TFM_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, + {TFM_MODAL_AXIS_X, "AXIS_X", 0, "X axis", ""}, + {TFM_MODAL_AXIS_Y, "AXIS_Y", 0, "Y axis", ""}, + {TFM_MODAL_AXIS_Z, "AXIS_Z", 0, "Z axis", ""}, + {TFM_MODAL_PLANE_X, "PLANE_X", 0, "X plane", ""}, + {TFM_MODAL_PLANE_Y, "PLANE_Y", 0, "Y plane", ""}, + {TFM_MODAL_PLANE_Z, "PLANE_Z", 0, "Z plane", ""}, + {TFM_MODAL_CONS_OFF, "CONS_OFF", 0, "Clear Constraints", ""}, + {TFM_MODAL_SNAP_INV_ON, "SNAP_INV_ON", 0, "Snap Invert", ""}, + {TFM_MODAL_SNAP_INV_OFF, "SNAP_INV_OFF", 0, "Snap Invert (Off)", ""}, + {TFM_MODAL_SNAP_TOGGLE, "SNAP_TOGGLE", 0, "Snap Toggle", ""}, + {TFM_MODAL_ADD_SNAP, "ADD_SNAP", 0, "Add Snap Point", ""}, + {TFM_MODAL_REMOVE_SNAP, "REMOVE_SNAP", 0, "Remove Last Snap Point", ""}, + {NUM_MODAL_INCREMENT_UP, "INCREMENT_UP", 0, "Numinput Increment Up", ""}, + {NUM_MODAL_INCREMENT_DOWN, "INCREMENT_DOWN", 0, "Numinput Increment Down", ""}, + {TFM_MODAL_PROPSIZE_UP, "PROPORTIONAL_SIZE_UP", 0, "Increase Proportional Influence", ""}, + {TFM_MODAL_PROPSIZE_DOWN, + "PROPORTIONAL_SIZE_DOWN", + 0, + "Decrease Proportional Influence", + ""}, + {TFM_MODAL_AUTOIK_LEN_INC, "AUTOIK_CHAIN_LEN_UP", 0, "Increase Max AutoIK Chain Length", ""}, + {TFM_MODAL_AUTOIK_LEN_DEC, + "AUTOIK_CHAIN_LEN_DOWN", + 0, + "Decrease Max AutoIK Chain Length", + ""}, + {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""}, + {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""}, + {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""}, + {TFM_MODAL_INSERTOFS_TOGGLE_DIR, + "INSERTOFS_TOGGLE_DIR", + 0, + "Toggle Direction for Node Auto-offset", + ""}, + {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""}, + {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""}, + {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""}, + {0, NULL, 0, NULL, NULL}, + }; + + wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map"); + + keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items); + keymap->poll_modal_item = transform_modal_item_poll; + + return keymap; } static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cmode, bool is_plane) { - if (!(t->flag & T_NO_CONSTRAINT)) { - int constraint_axis, constraint_plane; - const bool edit_2d = (t->flag & T_2D_EDIT) != 0; - const char *msg1 = "", *msg2 = "", *msg3 = ""; - char axis; - - /* Initialize */ - switch (key_type) { - case XKEY: - msg1 = IFACE_("along X"); - msg2 = IFACE_("along %s X"); - msg3 = IFACE_("locking %s X"); - axis = 'X'; - constraint_axis = CON_AXIS0; - break; - case YKEY: - msg1 = IFACE_("along Y"); - msg2 = IFACE_("along %s Y"); - msg3 = IFACE_("locking %s Y"); - axis = 'Y'; - constraint_axis = CON_AXIS1; - break; - case ZKEY: - msg1 = IFACE_("along Z"); - msg2 = IFACE_("along %s Z"); - msg3 = IFACE_("locking %s Z"); - axis = 'Z'; - constraint_axis = CON_AXIS2; - break; - default: - /* Invalid key */ - return; - } - constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis)); - - if (edit_2d && (key_type != ZKEY)) { - if (cmode == axis) { - stopConstraint(t); - } - else { - setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1); - } - } - else if (!edit_2d) { - if (cmode != axis) { - /* First press, constraint to an axis. */ - t->orientation.index = 0; - const short *orientation_ptr = t->orientation.types[t->orientation.index]; - const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; - if (is_plane == false) { - setUserConstraint(t, orientation, constraint_axis, msg2); - } - else { - setUserConstraint(t, orientation, constraint_plane, msg3); - } - } - else { - /* Successive presses on existing axis, cycle orientation modes. */ - t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types); - - if (t->orientation.index == 0) { - stopConstraint(t); - } - else { - const short *orientation_ptr = t->orientation.types[t->orientation.index]; - const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; - if (is_plane == false) { - setUserConstraint(t, orientation, constraint_axis, msg2); - } - else { - setUserConstraint(t, orientation, constraint_plane, msg3); - } - } - } - } - t->redraw |= TREDRAW_HARD; - } + if (!(t->flag & T_NO_CONSTRAINT)) { + int constraint_axis, constraint_plane; + const bool edit_2d = (t->flag & T_2D_EDIT) != 0; + const char *msg1 = "", *msg2 = "", *msg3 = ""; + char axis; + + /* Initialize */ + switch (key_type) { + case XKEY: + msg1 = IFACE_("along X"); + msg2 = IFACE_("along %s X"); + msg3 = IFACE_("locking %s X"); + axis = 'X'; + constraint_axis = CON_AXIS0; + break; + case YKEY: + msg1 = IFACE_("along Y"); + msg2 = IFACE_("along %s Y"); + msg3 = IFACE_("locking %s Y"); + axis = 'Y'; + constraint_axis = CON_AXIS1; + break; + case ZKEY: + msg1 = IFACE_("along Z"); + msg2 = IFACE_("along %s Z"); + msg3 = IFACE_("locking %s Z"); + axis = 'Z'; + constraint_axis = CON_AXIS2; + break; + default: + /* Invalid key */ + return; + } + constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis)); + + if (edit_2d && (key_type != ZKEY)) { + if (cmode == axis) { + stopConstraint(t); + } + else { + setUserConstraint(t, V3D_ORIENT_GLOBAL, constraint_axis, msg1); + } + } + else if (!edit_2d) { + if (cmode != axis) { + /* First press, constraint to an axis. */ + t->orientation.index = 0; + const short *orientation_ptr = t->orientation.types[t->orientation.index]; + const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; + if (is_plane == false) { + setUserConstraint(t, orientation, constraint_axis, msg2); + } + else { + setUserConstraint(t, orientation, constraint_plane, msg3); + } + } + else { + /* Successive presses on existing axis, cycle orientation modes. */ + t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types); + + if (t->orientation.index == 0) { + stopConstraint(t); + } + else { + const short *orientation_ptr = t->orientation.types[t->orientation.index]; + const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; + if (is_plane == false) { + setUserConstraint(t, orientation, constraint_axis, msg2); + } + else { + setUserConstraint(t, orientation, constraint_plane, msg3); + } + } + } + } + t->redraw |= TREDRAW_HARD; + } } int transformEvent(TransInfo *t, const wmEvent *event) { - char cmode = constraintModeToChar(t); - bool handled = false; - const int modifiers_prev = t->modifiers; - - t->redraw |= handleMouseInput(t, &t->mouse, event); - - /* Handle modal numinput events first, if already activated. */ - if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && - hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event)) - { - t->redraw |= TREDRAW_HARD; - handled = true; - } - else if (event->type == MOUSEMOVE) { - if (t->modifiers & MOD_CONSTRAINT_SELECT) - t->con.mode |= CON_SELECT; - - copy_v2_v2_int(t->mval, event->mval); - - /* Use this for soft redraw. Might cause flicker in object mode */ - // t->redraw |= TREDRAW_SOFT; - t->redraw |= TREDRAW_HARD; - - if (t->state == TRANS_STARTING) { - t->state = TRANS_RUNNING; - } - - applyMouseInput(t, &t->mouse, t->mval, t->values); - - // Snapping mouse move events - t->redraw |= handleSnapping(t, event); - handled = true; - } - /* handle modal keymap first */ - else if (event->type == EVT_MODAL_MAP) { - switch (event->val) { - case TFM_MODAL_CANCEL: - t->state = TRANS_CANCEL; - handled = true; - break; - case TFM_MODAL_CONFIRM: - t->state = TRANS_CONFIRM; - handled = true; - break; - case TFM_MODAL_TRANSLATE: - /* only switch when... */ - if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - initTranslation(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - WM_event_add_mousemove(t->context); - handled = true; - } - else if (t->mode == TFM_SEQ_SLIDE) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - else { - if (t->obedit_type == OB_MESH) { - if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - - /* first try edge slide */ - initEdgeSlide(t); - /* if that fails, do vertex slide */ - if (t->state == TRANS_CANCEL) { - resetTransModal(t); - t->state = TRANS_STARTING; - initVertSlide(t); - } - /* vert slide can fail on unconnected vertices (rare but possible) */ - if (t->state == TRANS_CANCEL) { - resetTransModal(t); - t->mode = TFM_TRANSLATION; - t->state = TRANS_STARTING; - restoreTransObjects(t); - resetTransRestrictions(t); - initTranslation(t); - } - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; - WM_event_add_mousemove(t->context); - } - } - else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - if (t->mode == TFM_TRANSLATION) { - restoreTransObjects(t); - - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - } - } - break; - case TFM_MODAL_ROTATE: - /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { - if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - - if (t->mode == TFM_ROTATION) { - initTrackball(t); - } - else { - initRotation(t); - } - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; - } - } - break; - case TFM_MODAL_RESIZE: - /* only switch when... */ - if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { - - /* Scale isn't normally very useful after extrude along normals, see T39756 */ - if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) { - stopConstraint(t); - } - - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - initResize(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; - } - else if (t->mode == TFM_SHRINKFATTEN) { - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - else if (t->mode == TFM_RESIZE) { - if (t->options & CTX_MOVIECLIP) { - restoreTransObjects(t); - - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - } - break; - - case TFM_MODAL_SNAP_INV_ON: - t->modifiers |= MOD_SNAP_INVERT; - t->redraw |= TREDRAW_HARD; - handled = true; - break; - case TFM_MODAL_SNAP_INV_OFF: - t->modifiers &= ~MOD_SNAP_INVERT; - t->redraw |= TREDRAW_HARD; - handled = true; - break; - case TFM_MODAL_SNAP_TOGGLE: - t->modifiers ^= MOD_SNAP; - t->redraw |= TREDRAW_HARD; - handled = true; - break; - case TFM_MODAL_AXIS_X: - if (!(t->flag & T_NO_CONSTRAINT)) { - transform_event_xyz_constraint(t, XKEY, cmode, false); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_AXIS_Y: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - transform_event_xyz_constraint(t, YKEY, cmode, false); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_AXIS_Z: - if ((t->flag & (T_NO_CONSTRAINT)) == 0) { - transform_event_xyz_constraint(t, ZKEY, cmode, false); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_PLANE_X: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, XKEY, cmode, true); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_PLANE_Y: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, YKEY, cmode, true); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_PLANE_Z: - if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, ZKEY, cmode, true); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_CONS_OFF: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - stopConstraint(t); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_ADD_SNAP: - addSnapPoint(t); - t->redraw |= TREDRAW_HARD; - handled = true; - break; - case TFM_MODAL_REMOVE_SNAP: - removeSnapPoint(t); - t->redraw |= TREDRAW_HARD; - handled = true; - break; - case TFM_MODAL_PROPSIZE: - /* MOUSEPAN usage... */ - if (t->flag & T_PROP_EDIT) { - float fac = 1.0f + 0.005f *(event->y - event->prevy); - t->prop_size *= fac; - if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) { - t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end), T_PROP_SIZE_MIN); - } - else { - t->prop_size = max_ff(min_ff(t->prop_size, T_PROP_SIZE_MAX), T_PROP_SIZE_MIN); - } - calculatePropRatio(t); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_PROPSIZE_UP: - if (t->flag & T_PROP_EDIT) { - t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; - if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) { - t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end); - } - else { - t->prop_size = min_ff(t->prop_size, T_PROP_SIZE_MAX); - } - calculatePropRatio(t); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_PROPSIZE_DOWN: - if (t->flag & T_PROP_EDIT) { - t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; - t->prop_size = max_ff(t->prop_size, T_PROP_SIZE_MIN); - calculatePropRatio(t); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_AUTOIK_LEN_INC: - if (t->flag & T_AUTOIK) { - transform_autoik_update(t, 1); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_AUTOIK_LEN_DEC: - if (t->flag & T_AUTOIK) { - transform_autoik_update(t, -1); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case TFM_MODAL_INSERTOFS_TOGGLE_DIR: - if (t->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first; - - BLI_assert(t->sa->spacetype == t->spacetype); - - if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) { - snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT; - } - else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) { - snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT; - } - else { - BLI_assert(0); - } - - t->redraw |= TREDRAW_SOFT; - } - break; - /* Those two are only handled in transform's own handler, see T44634! */ - case TFM_MODAL_EDGESLIDE_UP: - case TFM_MODAL_EDGESLIDE_DOWN: - default: - break; - } - } - /* else do non-mapped events */ - else if (event->val == KM_PRESS) { - switch (event->type) { - case RIGHTMOUSE: - t->state = TRANS_CANCEL; - handled = true; - break; - /* enforce redraw of transform when modifiers are used */ - case LEFTSHIFTKEY: - case RIGHTSHIFTKEY: - t->modifiers |= MOD_CONSTRAINT_PLANE; - t->redraw |= TREDRAW_HARD; - handled = true; - break; - - case SPACEKEY: - t->state = TRANS_CONFIRM; - handled = true; - break; - - case MIDDLEMOUSE: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - /* exception for switching to dolly, or trackball, in camera view */ - if (t->flag & T_CAMERA) { - if (t->mode == TFM_TRANSLATION) - setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z")); - else if (t->mode == TFM_ROTATION) { - restoreTransObjects(t); - initTrackball(t); - } - } - else { - t->modifiers |= MOD_CONSTRAINT_SELECT; - if (t->con.mode & CON_APPLY) { - stopConstraint(t); - } - else { - if (event->shift) { - /* bit hackish... but it prevents mmb select to print the - * orientation from menu */ - float mati[3][3]; - strcpy(t->spacename, "global"); - unit_m3(mati); - initSelectConstraint(t, mati); - } - else { - initSelectConstraint(t, t->spacemtx); - } - postSelectConstraint(t); - } - } - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case ESCKEY: - t->state = TRANS_CANCEL; - handled = true; - break; - case PADENTER: - case RETKEY: - t->state = TRANS_CONFIRM; - handled = true; - break; - case GKEY: - /* only switch when... */ - if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - initTranslation(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case SKEY: - /* only switch when... */ - if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - initResize(t); - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case RKEY: - /* only switch when... */ - if (!(t->options & CTX_TEXTURE)) { - if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - - if (t->mode == TFM_ROTATION) { - initTrackball(t); - } - else { - initRotation(t); - } - initSnapping(t, NULL); // need to reinit after mode change - t->redraw |= TREDRAW_HARD; - handled = true; - } - } - break; - case CKEY: - if (event->alt) { - if (!(t->options & CTX_NO_PET)) { - t->flag ^= T_PROP_CONNECTED; - sort_trans_data_dist(t); - calculatePropRatio(t); - t->redraw = TREDRAW_HARD; - handled = true; - } - } - break; - case OKEY: - if (t->flag & T_PROP_EDIT && event->shift) { - t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX; - calculatePropRatio(t); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case PADPLUSKEY: - if (event->alt && t->flag & T_PROP_EDIT) { - t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; - if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) - t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end); - calculatePropRatio(t); - t->redraw = TREDRAW_HARD; - handled = true; - } - break; - case PAGEUPKEY: - case WHEELDOWNMOUSE: - if (t->flag & T_AUTOIK) { - transform_autoik_update(t, 1); - } - else { - view_editmove(event->type); - } - t->redraw = TREDRAW_HARD; - handled = true; - break; - case PADMINUS: - if (event->alt && t->flag & T_PROP_EDIT) { - t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; - calculatePropRatio(t); - t->redraw = TREDRAW_HARD; - handled = true; - } - break; - case PAGEDOWNKEY: - case WHEELUPMOUSE: - if (t->flag & T_AUTOIK) { - transform_autoik_update(t, -1); - } - else { - view_editmove(event->type); - } - t->redraw = TREDRAW_HARD; - handled = true; - break; - case LEFTALTKEY: - case RIGHTALTKEY: - if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { - t->flag |= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case NKEY: - if (ELEM(t->mode, TFM_ROTATION)) { - if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { - restoreTransObjects(t); - resetTransModal(t); - resetTransRestrictions(t); - initNormalRotation(t); - t->redraw = TREDRAW_HARD; - handled = true; - } - } - break; - default: - break; - } - - /* Snapping key events */ - t->redraw |= handleSnapping(t, event); - } - else if (event->val == KM_RELEASE) { - switch (event->type) { - case LEFTSHIFTKEY: - case RIGHTSHIFTKEY: - t->modifiers &= ~MOD_CONSTRAINT_PLANE; - t->redraw |= TREDRAW_HARD; - handled = true; - break; - - case MIDDLEMOUSE: - if ((t->flag & T_NO_CONSTRAINT) == 0) { - t->modifiers &= ~MOD_CONSTRAINT_SELECT; - postSelectConstraint(t); - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - case LEFTALTKEY: - case RIGHTALTKEY: - if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { - t->flag &= ~T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; - handled = true; - } - break; - default: - break; - } - - /* confirm transform if launch key is released after mouse move */ - if (t->flag & T_RELEASE_CONFIRM) { - /* XXX Keyrepeat bug in Xorg messes this up, will test when fixed */ - if ((event->type == t->launch_event) && ISMOUSE(t->launch_event)) { - t->state = TRANS_CONFIRM; - } - } - } - - /* if we change snap options, get the unsnapped values back */ - if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) != - (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT))) - { - applyMouseInput(t, &t->mouse, t->mval, t->values); - } - - /* Per transform event, if present */ - if (t->handleEvent && - (!handled || - /* Needed for vertex slide, see [#38756] */ - (event->type == MOUSEMOVE))) - { - t->redraw |= t->handleEvent(t, event); - } - - /* Try to init modal numinput now, if possible. */ - if (!(handled || t->redraw) && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && - handleNumInput(t->context, &(t->num), event)) - { - t->redraw |= TREDRAW_HARD; - handled = true; - } - - if (t->redraw && - !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) - { - WM_window_status_area_tag_redraw(CTX_wm_window(t->context)); - } - - if (handled || t->redraw) { - return 0; - } - else { - return OPERATOR_PASS_THROUGH; - } + char cmode = constraintModeToChar(t); + bool handled = false; + const int modifiers_prev = t->modifiers; + + t->redraw |= handleMouseInput(t, &t->mouse, event); + + /* Handle modal numinput events first, if already activated. */ + if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && hasNumInput(&t->num) && + handleNumInput(t->context, &(t->num), event)) { + t->redraw |= TREDRAW_HARD; + handled = true; + } + else if (event->type == MOUSEMOVE) { + if (t->modifiers & MOD_CONSTRAINT_SELECT) + t->con.mode |= CON_SELECT; + + copy_v2_v2_int(t->mval, event->mval); + + /* Use this for soft redraw. Might cause flicker in object mode */ + // t->redraw |= TREDRAW_SOFT; + t->redraw |= TREDRAW_HARD; + + if (t->state == TRANS_STARTING) { + t->state = TRANS_RUNNING; + } + + applyMouseInput(t, &t->mouse, t->mval, t->values); + + // Snapping mouse move events + t->redraw |= handleSnapping(t, event); + handled = true; + } + /* handle modal keymap first */ + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case TFM_MODAL_CANCEL: + t->state = TRANS_CANCEL; + handled = true; + break; + case TFM_MODAL_CONFIRM: + t->state = TRANS_CONFIRM; + handled = true; + break; + case TFM_MODAL_TRANSLATE: + /* only switch when... */ + if (ELEM(t->mode, + TFM_ROTATION, + TFM_RESIZE, + TFM_TRACKBALL, + TFM_EDGE_SLIDE, + TFM_VERT_SLIDE)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + initTranslation(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); + handled = true; + } + else if (t->mode == TFM_SEQ_SLIDE) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + else { + if (t->obedit_type == OB_MESH) { + if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + + /* first try edge slide */ + initEdgeSlide(t); + /* if that fails, do vertex slide */ + if (t->state == TRANS_CANCEL) { + resetTransModal(t); + t->state = TRANS_STARTING; + initVertSlide(t); + } + /* vert slide can fail on unconnected vertices (rare but possible) */ + if (t->state == TRANS_CANCEL) { + resetTransModal(t); + t->mode = TFM_TRANSLATION; + t->state = TRANS_STARTING; + restoreTransObjects(t); + resetTransRestrictions(t); + initTranslation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + WM_event_add_mousemove(t->context); + } + } + else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { + if (t->mode == TFM_TRANSLATION) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + } + } + break; + case TFM_MODAL_ROTATE: + /* only switch when... */ + if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { + if (ELEM(t->mode, + TFM_ROTATION, + TFM_RESIZE, + TFM_TRACKBALL, + TFM_TRANSLATION, + TFM_EDGE_SLIDE, + TFM_VERT_SLIDE)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + + if (t->mode == TFM_ROTATION) { + initTrackball(t); + } + else { + initRotation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + } + break; + case TFM_MODAL_RESIZE: + /* only switch when... */ + if (ELEM(t->mode, + TFM_ROTATION, + TFM_TRANSLATION, + TFM_TRACKBALL, + TFM_EDGE_SLIDE, + TFM_VERT_SLIDE)) { + + /* Scale isn't normally very useful after extrude along normals, see T39756 */ + if ((t->con.mode & CON_APPLY) && (t->con.orientation == V3D_ORIENT_NORMAL)) { + stopConstraint(t); + } + + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + initResize(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + else if (t->mode == TFM_SHRINKFATTEN) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + else if (t->mode == TFM_RESIZE) { + if (t->options & CTX_MOVIECLIP) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + } + break; + + case TFM_MODAL_SNAP_INV_ON: + t->modifiers |= MOD_SNAP_INVERT; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_SNAP_INV_OFF: + t->modifiers &= ~MOD_SNAP_INVERT; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_SNAP_TOGGLE: + t->modifiers ^= MOD_SNAP; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_AXIS_X: + if (!(t->flag & T_NO_CONSTRAINT)) { + transform_event_xyz_constraint(t, XKEY, cmode, false); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_AXIS_Y: + if ((t->flag & T_NO_CONSTRAINT) == 0) { + transform_event_xyz_constraint(t, YKEY, cmode, false); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_AXIS_Z: + if ((t->flag & (T_NO_CONSTRAINT)) == 0) { + transform_event_xyz_constraint(t, ZKEY, cmode, false); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_PLANE_X: + if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { + transform_event_xyz_constraint(t, XKEY, cmode, true); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_PLANE_Y: + if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { + transform_event_xyz_constraint(t, YKEY, cmode, true); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_PLANE_Z: + if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { + transform_event_xyz_constraint(t, ZKEY, cmode, true); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_CONS_OFF: + if ((t->flag & T_NO_CONSTRAINT) == 0) { + stopConstraint(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_ADD_SNAP: + addSnapPoint(t); + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_REMOVE_SNAP: + removeSnapPoint(t); + t->redraw |= TREDRAW_HARD; + handled = true; + break; + case TFM_MODAL_PROPSIZE: + /* MOUSEPAN usage... */ + if (t->flag & T_PROP_EDIT) { + float fac = 1.0f + 0.005f * (event->y - event->prevy); + t->prop_size *= fac; + if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) { + t->prop_size = max_ff(min_ff(t->prop_size, ((View3D *)t->view)->clip_end), + T_PROP_SIZE_MIN); + } + else { + t->prop_size = max_ff(min_ff(t->prop_size, T_PROP_SIZE_MAX), T_PROP_SIZE_MIN); + } + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_PROPSIZE_UP: + if (t->flag & T_PROP_EDIT) { + t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; + if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) { + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end); + } + else { + t->prop_size = min_ff(t->prop_size, T_PROP_SIZE_MAX); + } + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_PROPSIZE_DOWN: + if (t->flag & T_PROP_EDIT) { + t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; + t->prop_size = max_ff(t->prop_size, T_PROP_SIZE_MIN); + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_AUTOIK_LEN_INC: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, 1); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_AUTOIK_LEN_DEC: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, -1); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case TFM_MODAL_INSERTOFS_TOGGLE_DIR: + if (t->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first; + + BLI_assert(t->sa->spacetype == t->spacetype); + + if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) { + snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_LEFT; + } + else if (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_LEFT) { + snode->insert_ofs_dir = SNODE_INSERTOFS_DIR_RIGHT; + } + else { + BLI_assert(0); + } + + t->redraw |= TREDRAW_SOFT; + } + break; + /* Those two are only handled in transform's own handler, see T44634! */ + case TFM_MODAL_EDGESLIDE_UP: + case TFM_MODAL_EDGESLIDE_DOWN: + default: + break; + } + } + /* else do non-mapped events */ + else if (event->val == KM_PRESS) { + switch (event->type) { + case RIGHTMOUSE: + t->state = TRANS_CANCEL; + handled = true; + break; + /* enforce redraw of transform when modifiers are used */ + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: + t->modifiers |= MOD_CONSTRAINT_PLANE; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + + case SPACEKEY: + t->state = TRANS_CONFIRM; + handled = true; + break; + + case MIDDLEMOUSE: + if ((t->flag & T_NO_CONSTRAINT) == 0) { + /* exception for switching to dolly, or trackball, in camera view */ + if (t->flag & T_CAMERA) { + if (t->mode == TFM_TRANSLATION) + setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z")); + else if (t->mode == TFM_ROTATION) { + restoreTransObjects(t); + initTrackball(t); + } + } + else { + t->modifiers |= MOD_CONSTRAINT_SELECT; + if (t->con.mode & CON_APPLY) { + stopConstraint(t); + } + else { + if (event->shift) { + /* bit hackish... but it prevents mmb select to print the + * orientation from menu */ + float mati[3][3]; + strcpy(t->spacename, "global"); + unit_m3(mati); + initSelectConstraint(t, mati); + } + else { + initSelectConstraint(t, t->spacemtx); + } + postSelectConstraint(t); + } + } + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case ESCKEY: + t->state = TRANS_CANCEL; + handled = true; + break; + case PADENTER: + case RETKEY: + t->state = TRANS_CONFIRM; + handled = true; + break; + case GKEY: + /* only switch when... */ + if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + initTranslation(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case SKEY: + /* only switch when... */ + if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + initResize(t); + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case RKEY: + /* only switch when... */ + if (!(t->options & CTX_TEXTURE)) { + if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + + if (t->mode == TFM_ROTATION) { + initTrackball(t); + } + else { + initRotation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + handled = true; + } + } + break; + case CKEY: + if (event->alt) { + if (!(t->options & CTX_NO_PET)) { + t->flag ^= T_PROP_CONNECTED; + sort_trans_data_dist(t); + calculatePropRatio(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + } + break; + case OKEY: + if (t->flag & T_PROP_EDIT && event->shift) { + t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX; + calculatePropRatio(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case PADPLUSKEY: + if (event->alt && t->flag & T_PROP_EDIT) { + t->prop_size *= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; + if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->clip_end); + calculatePropRatio(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + break; + case PAGEUPKEY: + case WHEELDOWNMOUSE: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, 1); + } + else { + view_editmove(event->type); + } + t->redraw = TREDRAW_HARD; + handled = true; + break; + case PADMINUS: + if (event->alt && t->flag & T_PROP_EDIT) { + t->prop_size /= (t->modifiers & MOD_PRECISION) ? 1.01f : 1.1f; + calculatePropRatio(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + break; + case PAGEDOWNKEY: + case WHEELUPMOUSE: + if (t->flag & T_AUTOIK) { + transform_autoik_update(t, -1); + } + else { + view_editmove(event->type); + } + t->redraw = TREDRAW_HARD; + handled = true; + break; + case LEFTALTKEY: + case RIGHTALTKEY: + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { + t->flag |= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case NKEY: + if (ELEM(t->mode, TFM_ROTATION)) { + if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + initNormalRotation(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + } + break; + default: + break; + } + + /* Snapping key events */ + t->redraw |= handleSnapping(t, event); + } + else if (event->val == KM_RELEASE) { + switch (event->type) { + case LEFTSHIFTKEY: + case RIGHTSHIFTKEY: + t->modifiers &= ~MOD_CONSTRAINT_PLANE; + t->redraw |= TREDRAW_HARD; + handled = true; + break; + + case MIDDLEMOUSE: + if ((t->flag & T_NO_CONSTRAINT) == 0) { + t->modifiers &= ~MOD_CONSTRAINT_SELECT; + postSelectConstraint(t); + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + case LEFTALTKEY: + case RIGHTALTKEY: + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { + t->flag &= ~T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + handled = true; + } + break; + default: + break; + } + + /* confirm transform if launch key is released after mouse move */ + if (t->flag & T_RELEASE_CONFIRM) { + /* XXX Keyrepeat bug in Xorg messes this up, will test when fixed */ + if ((event->type == t->launch_event) && ISMOUSE(t->launch_event)) { + t->state = TRANS_CONFIRM; + } + } + } + + /* if we change snap options, get the unsnapped values back */ + if ((t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) != + (modifiers_prev & (MOD_SNAP | MOD_SNAP_INVERT))) { + applyMouseInput(t, &t->mouse, t->mval, t->values); + } + + /* Per transform event, if present */ + if (t->handleEvent && (!handled || + /* Needed for vertex slide, see [#38756] */ + (event->type == MOUSEMOVE))) { + t->redraw |= t->handleEvent(t, event); + } + + /* Try to init modal numinput now, if possible. */ + if (!(handled || t->redraw) && ((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && + handleNumInput(t->context, &(t->num), event)) { + t->redraw |= TREDRAW_HARD; + handled = true; + } + + if (t->redraw && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) { + WM_window_status_area_tag_redraw(CTX_wm_window(t->context)); + } + + if (handled || t->redraw) { + return 0; + } + else { + return OPERATOR_PASS_THROUGH; + } } bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], float cent2d[2]) { - TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data"); - bool success; - - t->context = C; + TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data"); + bool success; - t->state = TRANS_RUNNING; + t->context = C; - /* avoid calculating PET */ - t->options = CTX_NO_PET; + t->state = TRANS_RUNNING; - t->mode = TFM_DUMMY; + /* avoid calculating PET */ + t->options = CTX_NO_PET; - initTransInfo(C, t, NULL, NULL); + t->mode = TFM_DUMMY; - /* avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set) */ - t->around = V3D_AROUND_CENTER_BOUNDS; + initTransInfo(C, t, NULL, NULL); - createTransData(C, t); // make TransData structs from selection + /* avoid doing connectivity lookups (when V3D_AROUND_LOCAL_ORIGINS is set) */ + t->around = V3D_AROUND_CENTER_BOUNDS; - t->around = centerMode; // override userdefined mode + createTransData(C, t); // make TransData structs from selection - if (t->data_len_all == 0) { - success = false; - } - else { - success = true; + t->around = centerMode; // override userdefined mode - calculateCenter(t); + if (t->data_len_all == 0) { + success = false; + } + else { + success = true; - if (cent2d) { - copy_v2_v2(cent2d, t->center2d); - } + calculateCenter(t); - if (cent3d) { - // Copy center from constraint center. Transform center can be local - copy_v3_v3(cent3d, t->center_global); - } - } + if (cent2d) { + copy_v2_v2(cent2d, t->center2d); + } + if (cent3d) { + // Copy center from constraint center. Transform center can be local + copy_v3_v3(cent3d, t->center_global); + } + } - /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */ - special_aftertrans_update(C, t); + /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */ + special_aftertrans_update(C, t); - postTrans(C, t); + postTrans(C, t); - MEM_freeN(t); + MEM_freeN(t); - return success; + return success; } typedef enum { - UP, - DOWN, - LEFT, - RIGHT, + UP, + DOWN, + LEFT, + RIGHT, } ArrowDirection; #define POS_INDEX 0 @@ -1677,382 +1685,384 @@ typedef enum { static void drawArrow(ArrowDirection d, short offset, short length, short size) { - immBegin(GPU_PRIM_LINES, 6); - - switch (d) { - case LEFT: - offset = -offset; - length = -length; - size = -size; - ATTR_FALLTHROUGH; - case RIGHT: - immVertex2f(POS_INDEX, offset, 0); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length - size, -size); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length - size, size); - break; - - case DOWN: - offset = -offset; - length = -length; - size = -size; - ATTR_FALLTHROUGH; - case UP: - immVertex2f(POS_INDEX, 0, offset); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, -size, offset + length - size); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, size, offset + length - size); - break; - } - - immEnd(); + immBegin(GPU_PRIM_LINES, 6); + + switch (d) { + case LEFT: + offset = -offset; + length = -length; + size = -size; + ATTR_FALLTHROUGH; + case RIGHT: + immVertex2f(POS_INDEX, offset, 0); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length - size, -size); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length - size, size); + break; + + case DOWN: + offset = -offset; + length = -length; + size = -size; + ATTR_FALLTHROUGH; + case UP: + immVertex2f(POS_INDEX, 0, offset); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, -size, offset + length - size); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, size, offset + length - size); + break; + } + + immEnd(); } static void drawArrowHead(ArrowDirection d, short size) { - immBegin(GPU_PRIM_LINES, 4); - - switch (d) { - case LEFT: - size = -size; - ATTR_FALLTHROUGH; - case RIGHT: - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, -size); - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, size); - break; - - case DOWN: - size = -size; - ATTR_FALLTHROUGH; - case UP: - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, -size); - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, size, -size); - break; - } - - immEnd(); + immBegin(GPU_PRIM_LINES, 4); + + switch (d) { + case LEFT: + size = -size; + ATTR_FALLTHROUGH; + case RIGHT: + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, -size); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, size); + break; + + case DOWN: + size = -size; + ATTR_FALLTHROUGH; + case UP: + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, -size); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, size, -size); + break; + } + + immEnd(); } static void drawArc(float size, float angle_start, float angle_end, int segments) { - float delta = (angle_end - angle_start) / segments; - float angle; - int a; + float delta = (angle_end - angle_start) / segments; + float angle; + int a; - immBegin(GPU_PRIM_LINE_STRIP, segments + 1); + immBegin(GPU_PRIM_LINE_STRIP, segments + 1); - for (angle = angle_start, a = 0; a < segments; angle += delta, a++) { - immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size); - } - immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size); + for (angle = angle_start, a = 0; a < segments; angle += delta, a++) { + immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size); + } + immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size); - immEnd(); + immEnd(); } static bool helpline_poll(bContext *C) { - ARegion *ar = CTX_wm_region(C); + ARegion *ar = CTX_wm_region(C); - if (ar && ar->regiontype == RGN_TYPE_WINDOW) - return 1; - return 0; + if (ar && ar->regiontype == RGN_TYPE_WINDOW) + return 1; + return 0; } static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) { - TransInfo *t = (TransInfo *)customdata; - - if (t->helpline != HLP_NONE) { - float cent[2]; - float mval[3] = { - x, - y, - 0.0f, - }; - float tmval[2] = { - (float)t->mval[0], - (float)t->mval[1], - }; - - projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); - /* Offset the values for the area region. */ - const float offset[2] = { - t->ar->winrct.xmin, - t->ar->winrct.ymin, - }; - - for (int i = 0; i < 2; i++) { - cent[i] += offset[i]; - tmval[i] += offset[i]; - } - - GPU_matrix_push(); - - /* Dashed lines first. */ - if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */ - BLI_assert(shdr_pos == POS_INDEX); - - GPU_line_width(1.0f); + TransInfo *t = (TransInfo *)customdata; + + if (t->helpline != HLP_NONE) { + float cent[2]; + float mval[3] = { + x, + y, + 0.0f, + }; + float tmval[2] = { + (float)t->mval[0], + (float)t->mval[1], + }; + + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + /* Offset the values for the area region. */ + const float offset[2] = { + t->ar->winrct.xmin, + t->ar->winrct.ymin, + }; + + for (int i = 0; i < 2; i++) { + cent[i] += offset[i]; + tmval[i] += offset[i]; + } + + GPU_matrix_push(); + + /* Dashed lines first. */ + if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */ + BLI_assert(shdr_pos == POS_INDEX); + + GPU_line_width(1.0f); - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniformThemeColor(TH_VIEW_OVERLAY); - immUniform1f("dash_width", 6.0f); - immUniform1f("dash_factor", 0.5f); - - immBegin(GPU_PRIM_LINES, 2); - immVertex2fv(POS_INDEX, cent); - immVertex2f(POS_INDEX, tmval[0], tmval[1]); - immEnd(); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniformThemeColor(TH_VIEW_OVERLAY); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - immUnbindProgram(); - } + immBegin(GPU_PRIM_LINES, 2); + immVertex2fv(POS_INDEX, cent); + immVertex2f(POS_INDEX, tmval[0], tmval[1]); + immEnd(); - /* And now, solid lines. */ - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - UNUSED_VARS_NDEBUG(pos); /* silence warning */ - BLI_assert(pos == POS_INDEX); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUnbindProgram(); + } - switch (t->helpline) { - case HLP_SPRING: - immUniformThemeColor(TH_VIEW_OVERLAY); + /* And now, solid lines. */ + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + UNUSED_VARS_NDEBUG(pos); /* silence warning */ + BLI_assert(pos == POS_INDEX); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - GPU_matrix_translate_3fv(mval); - GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); + switch (t->helpline) { + case HLP_SPRING: + immUniformThemeColor(TH_VIEW_OVERLAY); - GPU_line_width(3.0f); - drawArrow(UP, 5, 10, 5); - drawArrow(DOWN, 5, 10, 5); - break; - case HLP_HARROW: - immUniformThemeColor(TH_VIEW_OVERLAY); - GPU_matrix_translate_3fv(mval); + GPU_matrix_translate_3fv(mval); + GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); - GPU_line_width(3.0f); - drawArrow(RIGHT, 5, 10, 5); - drawArrow(LEFT, 5, 10, 5); - break; - case HLP_VARROW: - immUniformThemeColor(TH_VIEW_OVERLAY); + GPU_line_width(3.0f); + drawArrow(UP, 5, 10, 5); + drawArrow(DOWN, 5, 10, 5); + break; + case HLP_HARROW: + immUniformThemeColor(TH_VIEW_OVERLAY); + GPU_matrix_translate_3fv(mval); - GPU_matrix_translate_3fv(mval); + GPU_line_width(3.0f); + drawArrow(RIGHT, 5, 10, 5); + drawArrow(LEFT, 5, 10, 5); + break; + case HLP_VARROW: + immUniformThemeColor(TH_VIEW_OVERLAY); - GPU_line_width(3.0f); - drawArrow(UP, 5, 10, 5); - drawArrow(DOWN, 5, 10, 5); - break; - case HLP_CARROW: - { - /* Draw arrow based on direction defined by custom-points. */ - immUniformThemeColor(TH_VIEW_OVERLAY); + GPU_matrix_translate_3fv(mval); - GPU_matrix_translate_3fv(mval); + GPU_line_width(3.0f); + drawArrow(UP, 5, 10, 5); + drawArrow(DOWN, 5, 10, 5); + break; + case HLP_CARROW: { + /* Draw arrow based on direction defined by custom-points. */ + immUniformThemeColor(TH_VIEW_OVERLAY); - GPU_line_width(3.0f); + GPU_matrix_translate_3fv(mval); - const int *data = t->mouse.data; - const float dx = data[2] - data[0], dy = data[3] - data[1]; - const float angle = -atan2f(dx, dy); + GPU_line_width(3.0f); - GPU_matrix_push(); + const int *data = t->mouse.data; + const float dx = data[2] - data[0], dy = data[3] - data[1]; + const float angle = -atan2f(dx, dy); - GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + GPU_matrix_push(); - drawArrow(UP, 5, 10, 5); - drawArrow(DOWN, 5, 10, 5); + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); - GPU_matrix_pop(); - break; - } - case HLP_ANGLE: - { - float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1]; - float angle = atan2f(dy, dx); - float dist = hypotf(dx, dy); - float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f); - float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f); + drawArrow(UP, 5, 10, 5); + drawArrow(DOWN, 5, 10, 5); - immUniformThemeColor(TH_VIEW_OVERLAY); + GPU_matrix_pop(); + break; + } + case HLP_ANGLE: { + float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1]; + float angle = atan2f(dy, dx); + float dist = hypotf(dx, dy); + float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f); + float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f); - GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0); + immUniformThemeColor(TH_VIEW_OVERLAY); - GPU_line_width(3.0f); - drawArc(dist, angle - delta_angle, angle - spacing_angle, 10); - drawArc(dist, angle + spacing_angle, angle + delta_angle, 10); + GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0); - GPU_matrix_push(); + GPU_line_width(3.0f); + drawArc(dist, angle - delta_angle, angle - spacing_angle, 10); + drawArc(dist, angle + spacing_angle, angle + delta_angle, 10); - GPU_matrix_translate_3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); - GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z'); + GPU_matrix_push(); - drawArrowHead(DOWN, 5); + GPU_matrix_translate_3f( + cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z'); - GPU_matrix_pop(); + drawArrowHead(DOWN, 5); - GPU_matrix_translate_3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); - GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z'); + GPU_matrix_pop(); - drawArrowHead(UP, 5); - break; - } - case HLP_TRACKBALL: - { - unsigned char col[3], col2[3]; - UI_GetThemeColor3ubv(TH_GRID, col); + GPU_matrix_translate_3f( + cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z'); - GPU_matrix_translate_3fv(mval); + drawArrowHead(UP, 5); + break; + } + case HLP_TRACKBALL: { + unsigned char col[3], col2[3]; + UI_GetThemeColor3ubv(TH_GRID, col); - GPU_line_width(3.0f); + GPU_matrix_translate_3fv(mval); - UI_make_axis_color(col, col2, 'X'); - immUniformColor3ubv(col2); + GPU_line_width(3.0f); - drawArrow(RIGHT, 5, 10, 5); - drawArrow(LEFT, 5, 10, 5); + UI_make_axis_color(col, col2, 'X'); + immUniformColor3ubv(col2); - UI_make_axis_color(col, col2, 'Y'); - immUniformColor3ubv(col2); + drawArrow(RIGHT, 5, 10, 5); + drawArrow(LEFT, 5, 10, 5); - drawArrow(UP, 5, 10, 5); - drawArrow(DOWN, 5, 10, 5); - break; - } - } + UI_make_axis_color(col, col2, 'Y'); + immUniformColor3ubv(col2); - immUnbindProgram(); - GPU_matrix_pop(); - } + drawArrow(UP, 5, 10, 5); + drawArrow(DOWN, 5, 10, 5); + break; + } + } + + immUnbindProgram(); + GPU_matrix_pop(); + } } static bool transinfo_show_overlay(const struct bContext *C, TransInfo *t, ARegion *ar) { - /* Don't show overlays when not the active view and when overlay is disabled: T57139 */ - bool ok = false; - if (ar == t->ar) { - ok = true; - } - else { - ScrArea *sa = CTX_wm_area(C); - if (sa->spacetype == SPACE_VIEW3D) { - View3D *v3d = sa->spacedata.first; - if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) { - ok = true; - } - } - } - return ok; + /* Don't show overlays when not the active view and when overlay is disabled: T57139 */ + bool ok = false; + if (ar == t->ar) { + ok = true; + } + else { + ScrArea *sa = CTX_wm_area(C); + if (sa->spacetype == SPACE_VIEW3D) { + View3D *v3d = sa->spacedata.first; + if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) { + ok = true; + } + } + } + return ok; } static void drawTransformView(const struct bContext *C, ARegion *ar, void *arg) { - TransInfo *t = arg; + TransInfo *t = arg; - if (!transinfo_show_overlay(C, t, ar)) { - return; - } + if (!transinfo_show_overlay(C, t, ar)) { + return; + } - GPU_line_width(1.0f); + GPU_line_width(1.0f); - drawConstraint(t); - drawPropCircle(C, t); - drawSnapping(C, t); + drawConstraint(t); + drawPropCircle(C, t); + drawSnapping(C, t); - if (ar == t->ar) { - /* edge slide, vert slide */ - drawEdgeSlide(t); - drawVertSlide(t); + if (ar == t->ar) { + /* edge slide, vert slide */ + drawEdgeSlide(t); + drawVertSlide(t); - /* Rotation */ - drawDial3d(t); - } + /* Rotation */ + drawDial3d(t); + } } /* just draw a little warning message in the top-right corner of the viewport * to warn that autokeying is enabled */ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) { - rcti rect; - const char *printable = IFACE_("Auto Keying On"); - float printable_size[2]; - int xco, yco; + rcti rect; + const char *printable = IFACE_("Auto Keying On"); + float printable_size[2]; + int xco, yco; - ED_region_visible_rect(ar, &rect); + ED_region_visible_rect(ar, &rect); - const int font_id = BLF_default(); - BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); + const int font_id = BLF_default(); + BLF_width_and_height( + font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; - yco = (rect.ymax - U.widget_unit); + xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; + yco = (rect.ymax - U.widget_unit); - /* warning text (to clarify meaning of overlays) - * - original color was red to match the icon, but that clashes badly with a less nasty border - */ - unsigned char color[3]; - UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color); - BLF_color3ubv(font_id, color); + /* warning text (to clarify meaning of overlays) + * - original color was red to match the icon, but that clashes badly with a less nasty border + */ + unsigned char color[3]; + UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color); + BLF_color3ubv(font_id, color); #ifdef WITH_INTERNATIONAL - BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); + BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #else - BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); + BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #endif - /* autokey recording icon... */ - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); + /* autokey recording icon... */ + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); - xco -= U.widget_unit; - yco -= (int)printable_size[1] / 2; + xco -= U.widget_unit; + yco -= (int)printable_size[1] / 2; - UI_icon_draw(xco, yco, ICON_REC); + UI_icon_draw(xco, yco, ICON_REC); - GPU_blend(false); + GPU_blend(false); } static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg) { - TransInfo *t = arg; - - if (!transinfo_show_overlay(C, t, ar)) { - return; - } - - if (ar == t->ar) { - Scene *scene = t->scene; - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); - - /* draw auto-key-framing hint in the corner - * - only draw if enabled (advanced users may be distracted/annoyed), - * for objects that will be autokeyframed (no point otherwise), - * AND only for the active region (as showing all is too overwhelming) - */ - if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) { - if (ar == t->ar) { - if (t->flag & (T_OBJECT | T_POSE)) { - if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) { - drawAutoKeyWarning(t, ar); - } - } - } - } - } + TransInfo *t = arg; + + if (!transinfo_show_overlay(C, t, ar)) { + return; + } + + if (ar == t->ar) { + Scene *scene = t->scene; + ViewLayer *view_layer = t->view_layer; + Object *ob = OBACT(view_layer); + + /* draw auto-key-framing hint in the corner + * - only draw if enabled (advanced users may be distracted/annoyed), + * for objects that will be autokeyframed (no point otherwise), + * AND only for the active region (as showing all is too overwhelming) + */ + if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) { + if (ar == t->ar) { + if (t->flag & (T_OBJECT | T_POSE)) { + if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) { + drawAutoKeyWarning(t, ar); + } + } + } + } + } } /** @@ -2060,235 +2070,231 @@ static void drawTransformPixel(const struct bContext *C, ARegion *ar, void *arg) */ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) { - ToolSettings *ts = CTX_data_tool_settings(C); - int proportional = 0; - PropertyRNA *prop; - - // Save back mode in case we're in the generic operator - if ((prop = RNA_struct_find_property(op->ptr, "mode"))) { - RNA_property_enum_set(op->ptr, prop, t->mode); - } - - if ((prop = RNA_struct_find_property(op->ptr, "value"))) { - float values[4]; - - copy_v4_v4(values, (t->flag & T_AUTOVALUES) ? t->auto_values : t->values); - - if (RNA_property_array_check(prop)) { - RNA_property_float_set_array(op->ptr, prop, values); - } - else { - RNA_property_float_set(op->ptr, prop, values[0]); - } - } - - /* convert flag to enum */ - switch (t->flag & T_PROP_EDIT_ALL) { - case T_PROP_EDIT: - proportional = PROP_EDIT_ON; - break; - case (T_PROP_EDIT | T_PROP_CONNECTED): - proportional = PROP_EDIT_CONNECTED; - break; - case (T_PROP_EDIT | T_PROP_PROJECTED): - proportional = PROP_EDIT_PROJECTED; - break; - default: - proportional = PROP_EDIT_OFF; - break; - } - - // If modal, save settings back in scene if not set as operator argument - if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) { - /* save settings if not set in operator */ - - /* skip saving proportional edit if it was not actually used */ - if (!(t->options & CTX_NO_PET)) { - if ((prop = RNA_struct_find_property(op->ptr, "proportional")) && - !RNA_property_is_set(op->ptr, prop)) - { - if (t->spacetype == SPACE_GRAPH) - ts->proportional_fcurve = proportional; - else if (t->spacetype == SPACE_ACTION) - ts->proportional_action = proportional; - else if (t->obedit_type != -1) - ts->proportional = proportional; - else if (t->options & CTX_MASK) - ts->proportional_mask = (proportional != PROP_EDIT_OFF); - else - ts->proportional_objects = (proportional != PROP_EDIT_OFF); - } - - if ((prop = RNA_struct_find_property(op->ptr, "proportional_size"))) { - ts->proportional_size = - RNA_property_is_set(op->ptr, prop) ? RNA_property_float_get(op->ptr, prop) : t->prop_size; - } - - if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) && - !RNA_property_is_set(op->ptr, prop)) - { - ts->prop_mode = t->prop_mode; - } - } - - /* do we check for parameter? */ - if (transformModeUseSnap(t)) { - if (t->modifiers & MOD_SNAP) { - ts->snap_flag |= SCE_SNAP; - } - else { - ts->snap_flag &= ~SCE_SNAP; - } - } - - if (t->spacetype == SPACE_VIEW3D) { - if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && - !RNA_property_is_set(op->ptr, prop) && - (t->orientation.user != V3D_ORIENT_CUSTOM_MATRIX)) - { - TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; - orient_slot->type = t->orientation.user; - BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) || - (BKE_scene_transform_orientation_get_index( - t->scene, t->orientation.custom) == orient_slot->index_custom)); - } - } - } - - if ((prop = RNA_struct_find_property(op->ptr, "proportional"))) { - RNA_property_enum_set(op->ptr, prop, proportional); - RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode); - RNA_float_set(op->ptr, "proportional_size", t->prop_size); - } - - if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) { - RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0); - } - - /* Orientation used for redo. */ - const bool use_orient_axis = ( - t->orient_matrix_is_set && - (RNA_struct_find_property(op->ptr, "orient_axis") != NULL)); - short orientation; - if (t->con.mode & CON_APPLY) { - orientation = t->con.orientation; - if (orientation == V3D_ORIENT_CUSTOM) { - const int orientation_index_custom = BKE_scene_transform_orientation_get_index( - t->scene, t->orientation.custom); - /* Maybe we need a t->con.custom_orientation? - * Seems like it would always match t->orientation.custom. */ - orientation = V3D_ORIENT_CUSTOM + orientation_index_custom; - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - } - } - else if ((t->orientation.user == V3D_ORIENT_CUSTOM_MATRIX) && - (prop = RNA_struct_find_property(op->ptr, "orient_matrix_type"))) - { - orientation = RNA_property_enum_get(op->ptr, prop); - } - else if (use_orient_axis) { - /* We're not using an orientation, use the fallback. */ - orientation = t->orientation.unset; - } - else { - orientation = V3D_ORIENT_GLOBAL; - } - - - if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { - if (t->flag & T_MODAL) { - if (t->con.mode & CON_APPLY) { - int orient_axis = constraintModeToIndex(t); - if (orient_axis != -1) { - RNA_property_enum_set(op->ptr, prop, orient_axis); - } - } - else { - RNA_property_enum_set(op->ptr, prop, t->orient_axis); - } - } - } - if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { - if (t->flag & T_MODAL) { - RNA_property_enum_set(op->ptr, prop, t->orient_axis_ortho); - } - } - - if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix"))) { - if (t->flag & T_MODAL) { - if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { - if (t->flag & T_MODAL) { - RNA_enum_set(op->ptr, "orient_matrix_type", orientation); - } - } - if (t->con.mode & CON_APPLY) { - RNA_float_set_array(op->ptr, "orient_matrix", &t->con.mtx[0][0]); - } - else if (use_orient_axis) { - RNA_float_set_array(op->ptr, "orient_matrix", &t->orient_matrix[0][0]); - } - else { - RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]); - } - } - } - - if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) { - /* constraint orientation can be global, even if user selects something else - * so use the orientation in the constraint if set */ - - /* Use 'orient_matrix' instead. */ - if (t->flag & T_MODAL) { - if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { - RNA_property_enum_set(op->ptr, prop, orientation); - } - } - } - - if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { - bool constraint_axis[3] = {false, false, false}; - if (t->flag & T_MODAL) { - /* Only set if needed, so we can hide in the UI when nothing is set. - * See 'transform_poll_property'. */ - if (t->con.mode & CON_APPLY) { - if (t->con.mode & CON_AXIS0) { - constraint_axis[0] = true; - } - if (t->con.mode & CON_AXIS1) { - constraint_axis[1] = true; - } - if (t->con.mode & CON_AXIS2) { - constraint_axis[2] = true; - } - } - if (ELEM(true, UNPACK3(constraint_axis))) { - RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); - } - } - } - - { - const char *prop_id = NULL; - bool prop_state = true; - if (t->mode == TFM_SHRINKFATTEN) { - prop_id = "use_even_offset"; - prop_state = false; - } - - if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) { - RNA_property_boolean_set(op->ptr, prop, ((t->flag & T_ALT_TRANSFORM) == 0) == prop_state); - } - } - - if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) { - RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0); - } - - if (t->mode == TFM_SHEAR) { - prop = RNA_struct_find_property(op->ptr, "shear_axis"); - t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop)); - RNA_property_enum_set(op->ptr, prop, POINTER_AS_INT(t->custom.mode.data)); - } + ToolSettings *ts = CTX_data_tool_settings(C); + int proportional = 0; + PropertyRNA *prop; + + // Save back mode in case we're in the generic operator + if ((prop = RNA_struct_find_property(op->ptr, "mode"))) { + RNA_property_enum_set(op->ptr, prop, t->mode); + } + + if ((prop = RNA_struct_find_property(op->ptr, "value"))) { + float values[4]; + + copy_v4_v4(values, (t->flag & T_AUTOVALUES) ? t->auto_values : t->values); + + if (RNA_property_array_check(prop)) { + RNA_property_float_set_array(op->ptr, prop, values); + } + else { + RNA_property_float_set(op->ptr, prop, values[0]); + } + } + + /* convert flag to enum */ + switch (t->flag & T_PROP_EDIT_ALL) { + case T_PROP_EDIT: + proportional = PROP_EDIT_ON; + break; + case (T_PROP_EDIT | T_PROP_CONNECTED): + proportional = PROP_EDIT_CONNECTED; + break; + case (T_PROP_EDIT | T_PROP_PROJECTED): + proportional = PROP_EDIT_PROJECTED; + break; + default: + proportional = PROP_EDIT_OFF; + break; + } + + // If modal, save settings back in scene if not set as operator argument + if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) { + /* save settings if not set in operator */ + + /* skip saving proportional edit if it was not actually used */ + if (!(t->options & CTX_NO_PET)) { + if ((prop = RNA_struct_find_property(op->ptr, "proportional")) && + !RNA_property_is_set(op->ptr, prop)) { + if (t->spacetype == SPACE_GRAPH) + ts->proportional_fcurve = proportional; + else if (t->spacetype == SPACE_ACTION) + ts->proportional_action = proportional; + else if (t->obedit_type != -1) + ts->proportional = proportional; + else if (t->options & CTX_MASK) + ts->proportional_mask = (proportional != PROP_EDIT_OFF); + else + ts->proportional_objects = (proportional != PROP_EDIT_OFF); + } + + if ((prop = RNA_struct_find_property(op->ptr, "proportional_size"))) { + ts->proportional_size = RNA_property_is_set(op->ptr, prop) ? + RNA_property_float_get(op->ptr, prop) : + t->prop_size; + } + + if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) && + !RNA_property_is_set(op->ptr, prop)) { + ts->prop_mode = t->prop_mode; + } + } + + /* do we check for parameter? */ + if (transformModeUseSnap(t)) { + if (t->modifiers & MOD_SNAP) { + ts->snap_flag |= SCE_SNAP; + } + else { + ts->snap_flag &= ~SCE_SNAP; + } + } + + if (t->spacetype == SPACE_VIEW3D) { + if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && + !RNA_property_is_set(op->ptr, prop) && + (t->orientation.user != V3D_ORIENT_CUSTOM_MATRIX)) { + TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; + orient_slot->type = t->orientation.user; + BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) || + (BKE_scene_transform_orientation_get_index(t->scene, t->orientation.custom) == + orient_slot->index_custom)); + } + } + } + + if ((prop = RNA_struct_find_property(op->ptr, "proportional"))) { + RNA_property_enum_set(op->ptr, prop, proportional); + RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode); + RNA_float_set(op->ptr, "proportional_size", t->prop_size); + } + + if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) { + RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0); + } + + /* Orientation used for redo. */ + const bool use_orient_axis = (t->orient_matrix_is_set && + (RNA_struct_find_property(op->ptr, "orient_axis") != NULL)); + short orientation; + if (t->con.mode & CON_APPLY) { + orientation = t->con.orientation; + if (orientation == V3D_ORIENT_CUSTOM) { + const int orientation_index_custom = BKE_scene_transform_orientation_get_index( + t->scene, t->orientation.custom); + /* Maybe we need a t->con.custom_orientation? + * Seems like it would always match t->orientation.custom. */ + orientation = V3D_ORIENT_CUSTOM + orientation_index_custom; + BLI_assert(orientation >= V3D_ORIENT_CUSTOM); + } + } + else if ((t->orientation.user == V3D_ORIENT_CUSTOM_MATRIX) && + (prop = RNA_struct_find_property(op->ptr, "orient_matrix_type"))) { + orientation = RNA_property_enum_get(op->ptr, prop); + } + else if (use_orient_axis) { + /* We're not using an orientation, use the fallback. */ + orientation = t->orientation.unset; + } + else { + orientation = V3D_ORIENT_GLOBAL; + } + + if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { + if (t->flag & T_MODAL) { + if (t->con.mode & CON_APPLY) { + int orient_axis = constraintModeToIndex(t); + if (orient_axis != -1) { + RNA_property_enum_set(op->ptr, prop, orient_axis); + } + } + else { + RNA_property_enum_set(op->ptr, prop, t->orient_axis); + } + } + } + if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { + if (t->flag & T_MODAL) { + RNA_property_enum_set(op->ptr, prop, t->orient_axis_ortho); + } + } + + if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix"))) { + if (t->flag & T_MODAL) { + if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { + if (t->flag & T_MODAL) { + RNA_enum_set(op->ptr, "orient_matrix_type", orientation); + } + } + if (t->con.mode & CON_APPLY) { + RNA_float_set_array(op->ptr, "orient_matrix", &t->con.mtx[0][0]); + } + else if (use_orient_axis) { + RNA_float_set_array(op->ptr, "orient_matrix", &t->orient_matrix[0][0]); + } + else { + RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]); + } + } + } + + if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) { + /* constraint orientation can be global, even if user selects something else + * so use the orientation in the constraint if set */ + + /* Use 'orient_matrix' instead. */ + if (t->flag & T_MODAL) { + if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { + RNA_property_enum_set(op->ptr, prop, orientation); + } + } + } + + if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { + bool constraint_axis[3] = {false, false, false}; + if (t->flag & T_MODAL) { + /* Only set if needed, so we can hide in the UI when nothing is set. + * See 'transform_poll_property'. */ + if (t->con.mode & CON_APPLY) { + if (t->con.mode & CON_AXIS0) { + constraint_axis[0] = true; + } + if (t->con.mode & CON_AXIS1) { + constraint_axis[1] = true; + } + if (t->con.mode & CON_AXIS2) { + constraint_axis[2] = true; + } + } + if (ELEM(true, UNPACK3(constraint_axis))) { + RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + } + } + } + + { + const char *prop_id = NULL; + bool prop_state = true; + if (t->mode == TFM_SHRINKFATTEN) { + prop_id = "use_even_offset"; + prop_state = false; + } + + if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) { + RNA_property_boolean_set(op->ptr, prop, ((t->flag & T_ALT_TRANSFORM) == 0) == prop_state); + } + } + + if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) { + RNA_property_boolean_set( + op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0); + } + + if (t->mode == TFM_SHEAR) { + prop = RNA_struct_find_property(op->ptr, "shear_axis"); + t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop)); + RNA_property_enum_set(op->ptr, prop, POINTER_AS_INT(t->custom.mode.data)); + } } /** @@ -2298,896 +2304,896 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) */ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode) { - int options = 0; - PropertyRNA *prop; - - t->context = C; - - /* added initialize, for external calls to set stuff in TransInfo, like undo string */ - - t->state = TRANS_STARTING; - - if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) && RNA_property_is_set(op->ptr, prop)) { - if (RNA_property_boolean_get(op->ptr, prop)) { - options |= CTX_CURSOR; - } - } - - if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) { - if (RNA_property_boolean_get(op->ptr, prop)) { - options |= CTX_TEXTURE; - } - } - - if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) && RNA_property_is_set(op->ptr, prop)) { - if (RNA_property_boolean_get(op->ptr, prop)) { - options |= CTX_GPENCIL_STROKES; - } - } - - t->options = options; - - t->mode = mode; - - /* Needed to translate tweak events to mouse buttons. */ - t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1; - - // XXX Remove this when wm_operator_call_internal doesn't use window->eventstate (which can have type = 0) - // For gizmo only, so assume LEFTMOUSE - if (t->launch_event == 0) { - t->launch_event = LEFTMOUSE; - } - - unit_m3(t->spacemtx); - - initTransInfo(C, t, op, event); - initTransformOrientation(C, t); - - if (t->spacetype == SPACE_VIEW3D) { - t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW); - t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), - SPACE_TYPE_ANY, RGN_TYPE_ANY, - helpline_poll, drawHelpline, t); - } - else if (t->spacetype == SPACE_IMAGE) { - t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), - SPACE_TYPE_ANY, RGN_TYPE_ANY, - helpline_poll, drawHelpline, t); - } - else if (t->spacetype == SPACE_CLIP) { - t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), - SPACE_TYPE_ANY, RGN_TYPE_ANY, - helpline_poll, drawHelpline, t); - } - else if (t->spacetype == SPACE_NODE) { - /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/ - t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), - SPACE_TYPE_ANY, RGN_TYPE_ANY, - helpline_poll, drawHelpline, t); - } - else if (t->spacetype == SPACE_GRAPH) { - t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), - SPACE_TYPE_ANY, RGN_TYPE_ANY, - helpline_poll, drawHelpline, t); - } - else if (t->spacetype == SPACE_ACTION) { - t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), - SPACE_TYPE_ANY, RGN_TYPE_ANY, - helpline_poll, drawHelpline, t); - } - - createTransData(C, t); // make TransData structs from selection - - if (t->data_len_all == 0) { - postTrans(C, t); - return 0; - } - - if (event) { - /* keymap for shortcut header prints */ - t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); - - /* Stupid code to have Ctrl-Click on gizmo work ok. - * - * Do this only for translation/rotation/resize because only these - * modes are available from gizmo and doing such check could - * lead to keymap conflicts for other modes (see #31584) - */ - if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { - wmKeyMapItem *kmi; - - for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) { - if (kmi->flag & KMI_INACTIVE) { - continue; - } - - if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) { - if ((ELEM(kmi->type, LEFTCTRLKEY, RIGHTCTRLKEY) && event->ctrl) || - (ELEM(kmi->type, LEFTSHIFTKEY, RIGHTSHIFTKEY) && event->shift) || - (ELEM(kmi->type, LEFTALTKEY, RIGHTALTKEY) && event->alt) || - ((kmi->type == OSKEY) && event->oskey) ) - { - t->modifiers |= MOD_SNAP_INVERT; - } - break; - } - } - } - } - - initSnapping(t, op); // Initialize snapping data AFTER mode flags - - initSnapSpatial(t, t->snap_spatial); - - /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. - * will be removed (ton) */ - - /* EVIL2: we gave as argument also texture space context bit... was cleared */ - - /* EVIL3: extend mode for animation editors also switches modes... - * but is best way to avoid duplicate code */ - mode = t->mode; - - calculatePropRatio(t); - calculateCenter(t); - - /* Overwrite initial values if operator supplied a non-null vector. - * - * Run before init functions so 'values_modal_offset' can be applied on mouse input. - */ - BLI_assert(is_zero_v4(t->values_modal_offset)); - if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { - float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ - - if (RNA_property_array_check(prop)) { - RNA_float_get_array(op->ptr, "value", values); - } - else { - values[0] = RNA_float_get(op->ptr, "value"); - } - - copy_v4_v4(t->values, values); - - if (t->flag & T_MODAL) { - copy_v4_v4(t->values_modal_offset, values); - t->redraw = TREDRAW_HARD; - } - else { - copy_v4_v4(t->auto_values, values); - t->flag |= T_AUTOVALUES; - } - } - - if (event) { - /* Initialize accurate transform to settings requested by keymap. */ - bool use_accurate = false; - if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) && RNA_property_is_set(op->ptr, prop)) { - if (RNA_property_boolean_get(op->ptr, prop)) { - use_accurate = true; - } - } - initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate); - } - - switch (mode) { - case TFM_TRANSLATION: - initTranslation(t); - break; - case TFM_ROTATION: - initRotation(t); - break; - case TFM_RESIZE: - initResize(t); - break; - case TFM_SKIN_RESIZE: - initSkinResize(t); - break; - case TFM_TOSPHERE: - initToSphere(t); - break; - case TFM_SHEAR: - prop = RNA_struct_find_property(op->ptr, "shear_axis"); - t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop)); - initShear(t); - break; - case TFM_BEND: - initBend(t); - break; - case TFM_SHRINKFATTEN: - initShrinkFatten(t); - break; - case TFM_TILT: - initTilt(t); - break; - case TFM_CURVE_SHRINKFATTEN: - initCurveShrinkFatten(t); - break; - case TFM_MASK_SHRINKFATTEN: - initMaskShrinkFatten(t); - break; - case TFM_GPENCIL_SHRINKFATTEN: - initGPShrinkFatten(t); - break; - case TFM_TRACKBALL: - initTrackball(t); - break; - case TFM_PUSHPULL: - initPushPull(t); - break; - case TFM_CREASE: - initCrease(t); - break; - case TFM_BONESIZE: - { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */ - /* Note: we have to pick one, use the active object. */ - TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t); - bArmature *arm = tc->poseobj->data; - if (arm->drawtype == ARM_ENVELOPE) { - initBoneEnvelope(t); - t->mode = TFM_BONE_ENVELOPE_DIST; - } - else { - initBoneSize(t); - } - break; - } - case TFM_BONE_ENVELOPE: - initBoneEnvelope(t); - break; - case TFM_BONE_ENVELOPE_DIST: - initBoneEnvelope(t); - t->mode = TFM_BONE_ENVELOPE_DIST; - break; - case TFM_EDGE_SLIDE: - case TFM_VERT_SLIDE: - { - const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false); - const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false); - const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true); - if (mode == TFM_EDGE_SLIDE) { - const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true); - initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp); - } - else { - initVertSlide_ex(t, use_even, flipped, use_clamp); - } - break; - } - case TFM_BONE_ROLL: - initBoneRoll(t); - break; - case TFM_TIME_TRANSLATE: - initTimeTranslate(t); - break; - case TFM_TIME_SLIDE: - initTimeSlide(t); - break; - case TFM_TIME_SCALE: - initTimeScale(t); - break; - case TFM_TIME_DUPLICATE: - /* same as TFM_TIME_EXTEND, but we need the mode info for later - * so that duplicate-culling will work properly - */ - if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) - initTranslation(t); - else - initTimeTranslate(t); - t->mode = mode; - break; - case TFM_TIME_EXTEND: - /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation - * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION - * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement) - * depending on which editor this was called from - */ - if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) - initTranslation(t); - else - initTimeTranslate(t); - break; - case TFM_BAKE_TIME: - initBakeTime(t); - break; - case TFM_MIRROR: - initMirror(t); - break; - case TFM_BWEIGHT: - initBevelWeight(t); - break; - case TFM_ALIGN: - initAlign(t); - break; - case TFM_SEQ_SLIDE: - initSeqSlide(t); - break; - case TFM_NORMAL_ROTATION: - initNormalRotation(t); - break; - case TFM_GPENCIL_OPACITY: - initGPOpacity(t); - break; - } - - if (t->state == TRANS_CANCEL) { - postTrans(C, t); - return 0; - } - - /* Transformation axis from operator */ - if ((prop = RNA_struct_find_property(op->ptr, "orient_axis")) && - RNA_property_is_set(op->ptr, prop)) - { - t->orient_axis = RNA_property_enum_get(op->ptr, prop); - } - if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho")) && - RNA_property_is_set(op->ptr, prop)) - { - t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); - } - - /* Constraint init from operator */ - if ((t->flag & T_MODAL) || - /* For mirror operator the constraint axes are effectively the values. */ - (RNA_struct_find_property(op->ptr, "values") == NULL)) - { - if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) && - RNA_property_is_set(op->ptr, prop)) - { - bool constraint_axis[3]; - - RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); - - if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { - t->con.mode |= CON_APPLY; - - if (constraint_axis[0]) { - t->con.mode |= CON_AXIS0; - } - if (constraint_axis[1]) { - t->con.mode |= CON_AXIS1; - } - if (constraint_axis[2]) { - t->con.mode |= CON_AXIS2; - } - - setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); - } - } - } - else { - /* So we can adjust in non global orientation. */ - if (t->orientation.user != V3D_ORIENT_GLOBAL) { - t->con.mode |= CON_APPLY | CON_AXIS0 | CON_AXIS1 | CON_AXIS2; - setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); - } - } - - /* Don't write into the values when non-modal because they are already set from operator redo values. */ - if (t->flag & T_MODAL) { - /* Setup the mouse input with initial values. */ - applyMouseInput(t, &t->mouse, t->mouse.imval, t->values); - } - - if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) { - if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { - - FOREACH_TRANS_DATA_CONTAINER(t, tc) { - if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) { - BMEditMesh *em = NULL;// BKE_editmesh_from_object(t->obedit); - bool do_skip = false; - - /* Currently only used for two of three most frequent transform ops, - * can include more ops. - * Note that scaling cannot be included here, - * non-uniform scaling will affect normals. */ - if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) { - if (em->bm->totvertsel == em->bm->totvert) { - /* No need to invalidate if whole mesh is selected. */ - do_skip = true; - } - } - - if (t->flag & T_MODAL) { - RNA_property_boolean_set(op->ptr, prop, false); - } - else if (!do_skip) { - const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); - if (preserve_clnor) { - BKE_editmesh_lnorspace_update(em); - t->flag |= T_CLNOR_REBUILD; - } - BM_lnorspace_invalidate(em->bm, true); - } - } - } - } - } - - t->context = NULL; - - return 1; + int options = 0; + PropertyRNA *prop; + + t->context = C; + + /* added initialize, for external calls to set stuff in TransInfo, like undo string */ + + t->state = TRANS_STARTING; + + if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) && + RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + options |= CTX_CURSOR; + } + } + + if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && + RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + options |= CTX_TEXTURE; + } + } + + if ((prop = RNA_struct_find_property(op->ptr, "gpencil_strokes")) && + RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + options |= CTX_GPENCIL_STROKES; + } + } + + t->options = options; + + t->mode = mode; + + /* Needed to translate tweak events to mouse buttons. */ + t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1; + + // XXX Remove this when wm_operator_call_internal doesn't use window->eventstate (which can have type = 0) + // For gizmo only, so assume LEFTMOUSE + if (t->launch_event == 0) { + t->launch_event = LEFTMOUSE; + } + + unit_m3(t->spacemtx); + + initTransInfo(C, t, op, event); + initTransformOrientation(C, t); + + if (t->spacetype == SPACE_VIEW3D) { + t->draw_handle_apply = ED_region_draw_cb_activate( + t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW); + t->draw_handle_view = ED_region_draw_cb_activate( + t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + t->draw_handle_pixel = ED_region_draw_cb_activate( + t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t); + } + else if (t->spacetype == SPACE_IMAGE) { + t->draw_handle_view = ED_region_draw_cb_activate( + t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t); + } + else if (t->spacetype == SPACE_CLIP) { + t->draw_handle_view = ED_region_draw_cb_activate( + t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t); + } + else if (t->spacetype == SPACE_NODE) { + /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/ + t->draw_handle_view = ED_region_draw_cb_activate( + t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t); + } + else if (t->spacetype == SPACE_GRAPH) { + t->draw_handle_view = ED_region_draw_cb_activate( + t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t); + } + else if (t->spacetype == SPACE_ACTION) { + t->draw_handle_view = ED_region_draw_cb_activate( + t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); + //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, helpline_poll, drawHelpline, t); + } + + createTransData(C, t); // make TransData structs from selection + + if (t->data_len_all == 0) { + postTrans(C, t); + return 0; + } + + if (event) { + /* keymap for shortcut header prints */ + t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); + + /* Stupid code to have Ctrl-Click on gizmo work ok. + * + * Do this only for translation/rotation/resize because only these + * modes are available from gizmo and doing such check could + * lead to keymap conflicts for other modes (see #31584) + */ + if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { + wmKeyMapItem *kmi; + + for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) { + if (kmi->flag & KMI_INACTIVE) { + continue; + } + + if (kmi->propvalue == TFM_MODAL_SNAP_INV_ON && kmi->val == KM_PRESS) { + if ((ELEM(kmi->type, LEFTCTRLKEY, RIGHTCTRLKEY) && event->ctrl) || + (ELEM(kmi->type, LEFTSHIFTKEY, RIGHTSHIFTKEY) && event->shift) || + (ELEM(kmi->type, LEFTALTKEY, RIGHTALTKEY) && event->alt) || + ((kmi->type == OSKEY) && event->oskey)) { + t->modifiers |= MOD_SNAP_INVERT; + } + break; + } + } + } + } + + initSnapping(t, op); // Initialize snapping data AFTER mode flags + + initSnapSpatial(t, t->snap_spatial); + + /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. + * will be removed (ton) */ + + /* EVIL2: we gave as argument also texture space context bit... was cleared */ + + /* EVIL3: extend mode for animation editors also switches modes... + * but is best way to avoid duplicate code */ + mode = t->mode; + + calculatePropRatio(t); + calculateCenter(t); + + /* Overwrite initial values if operator supplied a non-null vector. + * + * Run before init functions so 'values_modal_offset' can be applied on mouse input. + */ + BLI_assert(is_zero_v4(t->values_modal_offset)); + if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { + float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ + + if (RNA_property_array_check(prop)) { + RNA_float_get_array(op->ptr, "value", values); + } + else { + values[0] = RNA_float_get(op->ptr, "value"); + } + + copy_v4_v4(t->values, values); + + if (t->flag & T_MODAL) { + copy_v4_v4(t->values_modal_offset, values); + t->redraw = TREDRAW_HARD; + } + else { + copy_v4_v4(t->auto_values, values); + t->flag |= T_AUTOVALUES; + } + } + + if (event) { + /* Initialize accurate transform to settings requested by keymap. */ + bool use_accurate = false; + if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) && + RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + use_accurate = true; + } + } + initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate); + } + + switch (mode) { + case TFM_TRANSLATION: + initTranslation(t); + break; + case TFM_ROTATION: + initRotation(t); + break; + case TFM_RESIZE: + initResize(t); + break; + case TFM_SKIN_RESIZE: + initSkinResize(t); + break; + case TFM_TOSPHERE: + initToSphere(t); + break; + case TFM_SHEAR: + prop = RNA_struct_find_property(op->ptr, "shear_axis"); + t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop)); + initShear(t); + break; + case TFM_BEND: + initBend(t); + break; + case TFM_SHRINKFATTEN: + initShrinkFatten(t); + break; + case TFM_TILT: + initTilt(t); + break; + case TFM_CURVE_SHRINKFATTEN: + initCurveShrinkFatten(t); + break; + case TFM_MASK_SHRINKFATTEN: + initMaskShrinkFatten(t); + break; + case TFM_GPENCIL_SHRINKFATTEN: + initGPShrinkFatten(t); + break; + case TFM_TRACKBALL: + initTrackball(t); + break; + case TFM_PUSHPULL: + initPushPull(t); + break; + case TFM_CREASE: + initCrease(t); + break; + case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */ + /* Note: we have to pick one, use the active object. */ + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t); + bArmature *arm = tc->poseobj->data; + if (arm->drawtype == ARM_ENVELOPE) { + initBoneEnvelope(t); + t->mode = TFM_BONE_ENVELOPE_DIST; + } + else { + initBoneSize(t); + } + break; + } + case TFM_BONE_ENVELOPE: + initBoneEnvelope(t); + break; + case TFM_BONE_ENVELOPE_DIST: + initBoneEnvelope(t); + t->mode = TFM_BONE_ENVELOPE_DIST; + break; + case TFM_EDGE_SLIDE: + case TFM_VERT_SLIDE: { + const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false); + const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false); + const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true); + if (mode == TFM_EDGE_SLIDE) { + const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true); + initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp); + } + else { + initVertSlide_ex(t, use_even, flipped, use_clamp); + } + break; + } + case TFM_BONE_ROLL: + initBoneRoll(t); + break; + case TFM_TIME_TRANSLATE: + initTimeTranslate(t); + break; + case TFM_TIME_SLIDE: + initTimeSlide(t); + break; + case TFM_TIME_SCALE: + initTimeScale(t); + break; + case TFM_TIME_DUPLICATE: + /* same as TFM_TIME_EXTEND, but we need the mode info for later + * so that duplicate-culling will work properly + */ + if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) + initTranslation(t); + else + initTimeTranslate(t); + t->mode = mode; + break; + case TFM_TIME_EXTEND: + /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation + * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION + * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement) + * depending on which editor this was called from + */ + if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) + initTranslation(t); + else + initTimeTranslate(t); + break; + case TFM_BAKE_TIME: + initBakeTime(t); + break; + case TFM_MIRROR: + initMirror(t); + break; + case TFM_BWEIGHT: + initBevelWeight(t); + break; + case TFM_ALIGN: + initAlign(t); + break; + case TFM_SEQ_SLIDE: + initSeqSlide(t); + break; + case TFM_NORMAL_ROTATION: + initNormalRotation(t); + break; + case TFM_GPENCIL_OPACITY: + initGPOpacity(t); + break; + } + + if (t->state == TRANS_CANCEL) { + postTrans(C, t); + return 0; + } + + /* Transformation axis from operator */ + if ((prop = RNA_struct_find_property(op->ptr, "orient_axis")) && + RNA_property_is_set(op->ptr, prop)) { + t->orient_axis = RNA_property_enum_get(op->ptr, prop); + } + if ((prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho")) && + RNA_property_is_set(op->ptr, prop)) { + t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); + } + + /* Constraint init from operator */ + if ((t->flag & T_MODAL) || + /* For mirror operator the constraint axes are effectively the values. */ + (RNA_struct_find_property(op->ptr, "values") == NULL)) { + if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) && + RNA_property_is_set(op->ptr, prop)) { + bool constraint_axis[3]; + + RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); + + if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { + t->con.mode |= CON_APPLY; + + if (constraint_axis[0]) { + t->con.mode |= CON_AXIS0; + } + if (constraint_axis[1]) { + t->con.mode |= CON_AXIS1; + } + if (constraint_axis[2]) { + t->con.mode |= CON_AXIS2; + } + + setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); + } + } + } + else { + /* So we can adjust in non global orientation. */ + if (t->orientation.user != V3D_ORIENT_GLOBAL) { + t->con.mode |= CON_APPLY | CON_AXIS0 | CON_AXIS1 | CON_AXIS2; + setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); + } + } + + /* Don't write into the values when non-modal because they are already set from operator redo values. */ + if (t->flag & T_MODAL) { + /* Setup the mouse input with initial values. */ + applyMouseInput(t, &t->mouse, t->mouse.imval, t->values); + } + + if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) { + if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) { + BMEditMesh *em = NULL; // BKE_editmesh_from_object(t->obedit); + bool do_skip = false; + + /* Currently only used for two of three most frequent transform ops, + * can include more ops. + * Note that scaling cannot be included here, + * non-uniform scaling will affect normals. */ + if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) { + if (em->bm->totvertsel == em->bm->totvert) { + /* No need to invalidate if whole mesh is selected. */ + do_skip = true; + } + } + + if (t->flag & T_MODAL) { + RNA_property_boolean_set(op->ptr, prop, false); + } + else if (!do_skip) { + const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); + if (preserve_clnor) { + BKE_editmesh_lnorspace_update(em); + t->flag |= T_CLNOR_REBUILD; + } + BM_lnorspace_invalidate(em->bm, true); + } + } + } + } + } + + t->context = NULL; + + return 1; } void transformApply(bContext *C, TransInfo *t) { - t->context = C; + t->context = C; - if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) { - selectConstraint(t); - if (t->transform) { - t->transform(t, t->mval); // calls recalcData() - viewRedrawForce(C, t); - } - t->redraw = TREDRAW_NOTHING; - } - else if (t->redraw & TREDRAW_SOFT) { - viewRedrawForce(C, t); - } + if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT))) { + selectConstraint(t); + if (t->transform) { + t->transform(t, t->mval); // calls recalcData() + viewRedrawForce(C, t); + } + t->redraw = TREDRAW_NOTHING; + } + else if (t->redraw & TREDRAW_SOFT) { + viewRedrawForce(C, t); + } - /* If auto confirm is on, break after one pass */ - if (t->options & CTX_AUTOCONFIRM) { - t->state = TRANS_CONFIRM; - } + /* If auto confirm is on, break after one pass */ + if (t->options & CTX_AUTOCONFIRM) { + t->state = TRANS_CONFIRM; + } - t->context = NULL; + t->context = NULL; } static void drawTransformApply(const bContext *C, ARegion *UNUSED(ar), void *arg) { - TransInfo *t = arg; + TransInfo *t = arg; - if (t->redraw & TREDRAW_SOFT) { - t->redraw |= TREDRAW_HARD; - transformApply((bContext *)C, t); - } + if (t->redraw & TREDRAW_SOFT) { + t->redraw |= TREDRAW_HARD; + transformApply((bContext *)C, t); + } } int transformEnd(bContext *C, TransInfo *t) { - int exit_code = OPERATOR_RUNNING_MODAL; + int exit_code = OPERATOR_RUNNING_MODAL; - t->context = C; + t->context = C; - if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING) { - /* handle restoring objects */ - if (t->state == TRANS_CANCEL) { - /* exception, edge slide transformed UVs too */ - if (t->mode == TFM_EDGE_SLIDE) { - doEdgeSlide(t, 0.0f); - } - else if (t->mode == TFM_VERT_SLIDE) { - doVertSlide(t, 0.0f); - } + if (t->state != TRANS_STARTING && t->state != TRANS_RUNNING) { + /* handle restoring objects */ + if (t->state == TRANS_CANCEL) { + /* exception, edge slide transformed UVs too */ + if (t->mode == TFM_EDGE_SLIDE) { + doEdgeSlide(t, 0.0f); + } + else if (t->mode == TFM_VERT_SLIDE) { + doVertSlide(t, 0.0f); + } - exit_code = OPERATOR_CANCELLED; - restoreTransObjects(t); // calls recalcData() - } - else { - if (t->flag & T_CLNOR_REBUILD) { - FOREACH_TRANS_DATA_CONTAINER(t, tc) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BM_lnorspace_rebuild(em->bm, true); - } - } - exit_code = OPERATOR_FINISHED; - } + exit_code = OPERATOR_CANCELLED; + restoreTransObjects(t); // calls recalcData() + } + else { + if (t->flag & T_CLNOR_REBUILD) { + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BM_lnorspace_rebuild(em->bm, true); + } + } + exit_code = OPERATOR_FINISHED; + } - /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */ - special_aftertrans_update(C, t); + /* aftertrans does insert keyframes, and clears base flags; doesn't read transdata */ + special_aftertrans_update(C, t); - /* free data */ - postTrans(C, t); + /* free data */ + postTrans(C, t); - /* send events out for redraws */ - viewRedrawPost(C, t); + /* send events out for redraws */ + viewRedrawPost(C, t); - viewRedrawForce(C, t); - } + viewRedrawForce(C, t); + } - t->context = NULL; + t->context = NULL; - return exit_code; + return exit_code; } /* ************************** TRANSFORM LOCKS **************************** */ static void protectedTransBits(short protectflag, float vec[3]) { - if (protectflag & OB_LOCK_LOCX) - vec[0] = 0.0f; - if (protectflag & OB_LOCK_LOCY) - vec[1] = 0.0f; - if (protectflag & OB_LOCK_LOCZ) - vec[2] = 0.0f; + if (protectflag & OB_LOCK_LOCX) + vec[0] = 0.0f; + if (protectflag & OB_LOCK_LOCY) + vec[1] = 0.0f; + if (protectflag & OB_LOCK_LOCZ) + vec[2] = 0.0f; } static void protectedSizeBits(short protectflag, float size[3]) { - if (protectflag & OB_LOCK_SCALEX) - size[0] = 1.0f; - if (protectflag & OB_LOCK_SCALEY) - size[1] = 1.0f; - if (protectflag & OB_LOCK_SCALEZ) - size[2] = 1.0f; + if (protectflag & OB_LOCK_SCALEX) + size[0] = 1.0f; + if (protectflag & OB_LOCK_SCALEY) + size[1] = 1.0f; + if (protectflag & OB_LOCK_SCALEZ) + size[2] = 1.0f; } static void protectedRotateBits(short protectflag, float eul[3], const float oldeul[3]) { - if (protectflag & OB_LOCK_ROTX) - eul[0] = oldeul[0]; - if (protectflag & OB_LOCK_ROTY) - eul[1] = oldeul[1]; - if (protectflag & OB_LOCK_ROTZ) - eul[2] = oldeul[2]; + if (protectflag & OB_LOCK_ROTX) + eul[0] = oldeul[0]; + if (protectflag & OB_LOCK_ROTY) + eul[1] = oldeul[1]; + if (protectflag & OB_LOCK_ROTZ) + eul[2] = oldeul[2]; } - /* this function only does the delta rotation */ /* axis-angle is usually internally stored as quats... */ -static void protectedAxisAngleBits(short protectflag, float axis[3], float *angle, float oldAxis[3], float oldAngle) -{ - /* check that protection flags are set */ - if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) - return; - - if (protectflag & OB_LOCK_ROT4D) { - /* axis-angle getting limited as 4D entities that they are... */ - if (protectflag & OB_LOCK_ROTW) - *angle = oldAngle; - if (protectflag & OB_LOCK_ROTX) - axis[0] = oldAxis[0]; - if (protectflag & OB_LOCK_ROTY) - axis[1] = oldAxis[1]; - if (protectflag & OB_LOCK_ROTZ) - axis[2] = oldAxis[2]; - } - else { - /* axis-angle get limited with euler... */ - float eul[3], oldeul[3]; - - axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, axis, *angle); - axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngle); - - if (protectflag & OB_LOCK_ROTX) - eul[0] = oldeul[0]; - if (protectflag & OB_LOCK_ROTY) - eul[1] = oldeul[1]; - if (protectflag & OB_LOCK_ROTZ) - eul[2] = oldeul[2]; - - eulO_to_axis_angle(axis, angle, eul, EULER_ORDER_DEFAULT); - - /* when converting to axis-angle, we need a special exception for the case when there is no axis */ - if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) { - /* for now, rotate around y-axis then (so that it simply becomes the roll) */ - axis[1] = 1.0f; - } - } +static void protectedAxisAngleBits( + short protectflag, float axis[3], float *angle, float oldAxis[3], float oldAngle) +{ + /* check that protection flags are set */ + if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) + return; + + if (protectflag & OB_LOCK_ROT4D) { + /* axis-angle getting limited as 4D entities that they are... */ + if (protectflag & OB_LOCK_ROTW) + *angle = oldAngle; + if (protectflag & OB_LOCK_ROTX) + axis[0] = oldAxis[0]; + if (protectflag & OB_LOCK_ROTY) + axis[1] = oldAxis[1]; + if (protectflag & OB_LOCK_ROTZ) + axis[2] = oldAxis[2]; + } + else { + /* axis-angle get limited with euler... */ + float eul[3], oldeul[3]; + + axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, axis, *angle); + axis_angle_to_eulO(oldeul, EULER_ORDER_DEFAULT, oldAxis, oldAngle); + + if (protectflag & OB_LOCK_ROTX) + eul[0] = oldeul[0]; + if (protectflag & OB_LOCK_ROTY) + eul[1] = oldeul[1]; + if (protectflag & OB_LOCK_ROTZ) + eul[2] = oldeul[2]; + + eulO_to_axis_angle(axis, angle, eul, EULER_ORDER_DEFAULT); + + /* when converting to axis-angle, we need a special exception for the case when there is no axis */ + if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) { + /* for now, rotate around y-axis then (so that it simply becomes the roll) */ + axis[1] = 1.0f; + } + } } /* this function only does the delta rotation */ static void protectedQuaternionBits(short protectflag, float quat[4], const float oldquat[4]) { - /* check that protection flags are set */ - if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) - return; - - if (protectflag & OB_LOCK_ROT4D) { - /* quaternions getting limited as 4D entities that they are... */ - if (protectflag & OB_LOCK_ROTW) - quat[0] = oldquat[0]; - if (protectflag & OB_LOCK_ROTX) - quat[1] = oldquat[1]; - if (protectflag & OB_LOCK_ROTY) - quat[2] = oldquat[2]; - if (protectflag & OB_LOCK_ROTZ) - quat[3] = oldquat[3]; - } - else { - /* quaternions get limited with euler... (compatibility mode) */ - float eul[3], oldeul[3], nquat[4], noldquat[4]; - float qlen; - - qlen = normalize_qt_qt(nquat, quat); - normalize_qt_qt(noldquat, oldquat); - - quat_to_eul(eul, nquat); - quat_to_eul(oldeul, noldquat); - - if (protectflag & OB_LOCK_ROTX) - eul[0] = oldeul[0]; - if (protectflag & OB_LOCK_ROTY) - eul[1] = oldeul[1]; - if (protectflag & OB_LOCK_ROTZ) - eul[2] = oldeul[2]; - - eul_to_quat(quat, eul); - - /* restore original quat size */ - mul_qt_fl(quat, qlen); - - /* quaternions flip w sign to accumulate rotations correctly */ - if ((nquat[0] < 0.0f && quat[0] > 0.0f) || - (nquat[0] > 0.0f && quat[0] < 0.0f)) - { - mul_qt_fl(quat, -1.0f); - } - } + /* check that protection flags are set */ + if ((protectflag & (OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ | OB_LOCK_ROTW)) == 0) + return; + + if (protectflag & OB_LOCK_ROT4D) { + /* quaternions getting limited as 4D entities that they are... */ + if (protectflag & OB_LOCK_ROTW) + quat[0] = oldquat[0]; + if (protectflag & OB_LOCK_ROTX) + quat[1] = oldquat[1]; + if (protectflag & OB_LOCK_ROTY) + quat[2] = oldquat[2]; + if (protectflag & OB_LOCK_ROTZ) + quat[3] = oldquat[3]; + } + else { + /* quaternions get limited with euler... (compatibility mode) */ + float eul[3], oldeul[3], nquat[4], noldquat[4]; + float qlen; + + qlen = normalize_qt_qt(nquat, quat); + normalize_qt_qt(noldquat, oldquat); + + quat_to_eul(eul, nquat); + quat_to_eul(oldeul, noldquat); + + if (protectflag & OB_LOCK_ROTX) + eul[0] = oldeul[0]; + if (protectflag & OB_LOCK_ROTY) + eul[1] = oldeul[1]; + if (protectflag & OB_LOCK_ROTZ) + eul[2] = oldeul[2]; + + eul_to_quat(quat, eul); + + /* restore original quat size */ + mul_qt_fl(quat, qlen); + + /* quaternions flip w sign to accumulate rotations correctly */ + if ((nquat[0] < 0.0f && quat[0] > 0.0f) || (nquat[0] > 0.0f && quat[0] < 0.0f)) { + mul_qt_fl(quat, -1.0f); + } + } } /* ******************* TRANSFORM LIMITS ********************** */ static void constraintTransLim(TransInfo *t, TransData *td) { - if (td->con) { - const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_LOCLIMIT); - const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_DISTLIMIT); - - bConstraintOb cob = {NULL}; - bConstraint *con; - float ctime = (float)(t->scene->r.cfra); - - /* Make a temporary bConstraintOb for using these limit constraints - * - they only care that cob->matrix is correctly set ;-) - * - current space should be local - */ - unit_m4(cob.matrix); - copy_v3_v3(cob.matrix[3], td->loc); - - /* Evaluate valid constraints */ - for (con = td->con; con; con = con->next) { - const bConstraintTypeInfo *cti = NULL; - ListBase targets = {NULL, NULL}; - - /* only consider constraint if enabled */ - if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue; - if (con->enforce == 0.0f) continue; - - /* only use it if it's tagged for this purpose (and the right type) */ - if (con->type == CONSTRAINT_TYPE_LOCLIMIT) { - bLocLimitConstraint *data = con->data; - - if ((data->flag2 & LIMIT_TRANSFORM) == 0) - continue; - cti = ctiLoc; - } - else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) { - bDistLimitConstraint *data = con->data; - - if ((data->flag & LIMITDIST_TRANSFORM) == 0) - continue; - cti = ctiDist; - } - - if (cti) { - /* do space conversions */ - if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->mtx (this should be ok) */ - mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); - } - else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { - /* skip... incompatible spacetype */ - continue; - } - - /* get constraint targets if needed */ - BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime); - - /* do constraint */ - cti->evaluate_constraint(con, &cob, &targets); - - /* convert spaces again */ - if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->smtx (this should be ok) */ - mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); - } - - /* free targets list */ - BLI_freelistN(&targets); - } - } - - /* copy results from cob->matrix */ - copy_v3_v3(td->loc, cob.matrix[3]); - } + if (td->con) { + const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type( + CONSTRAINT_TYPE_LOCLIMIT); + const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type( + CONSTRAINT_TYPE_DISTLIMIT); + + bConstraintOb cob = {NULL}; + bConstraint *con; + float ctime = (float)(t->scene->r.cfra); + + /* Make a temporary bConstraintOb for using these limit constraints + * - they only care that cob->matrix is correctly set ;-) + * - current space should be local + */ + unit_m4(cob.matrix); + copy_v3_v3(cob.matrix[3], td->loc); + + /* Evaluate valid constraints */ + for (con = td->con; con; con = con->next) { + const bConstraintTypeInfo *cti = NULL; + ListBase targets = {NULL, NULL}; + + /* only consider constraint if enabled */ + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) + continue; + if (con->enforce == 0.0f) + continue; + + /* only use it if it's tagged for this purpose (and the right type) */ + if (con->type == CONSTRAINT_TYPE_LOCLIMIT) { + bLocLimitConstraint *data = con->data; + + if ((data->flag2 & LIMIT_TRANSFORM) == 0) + continue; + cti = ctiLoc; + } + else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) { + bDistLimitConstraint *data = con->data; + + if ((data->flag & LIMITDIST_TRANSFORM) == 0) + continue; + cti = ctiDist; + } + + if (cti) { + /* do space conversions */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); + } + else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { + /* skip... incompatible spacetype */ + continue; + } + + /* get constraint targets if needed */ + BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime); + + /* do constraint */ + cti->evaluate_constraint(con, &cob, &targets); + + /* convert spaces again */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->smtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); + } + + /* free targets list */ + BLI_freelistN(&targets); + } + } + + /* copy results from cob->matrix */ + copy_v3_v3(td->loc, cob.matrix[3]); + } } static void constraintob_from_transdata(bConstraintOb *cob, TransData *td) { - /* Make a temporary bConstraintOb for use by limit constraints - * - they only care that cob->matrix is correctly set ;-) - * - current space should be local - */ - memset(cob, 0, sizeof(bConstraintOb)); - if (td->ext) { - if (td->ext->rotOrder == ROT_MODE_QUAT) { - /* quats */ - /* objects and bones do normalization first too, otherwise - * we don't necessarily end up with a rotation matrix, and - * then conversion back to quat gives a different result */ - float quat[4]; - normalize_qt_qt(quat, td->ext->quat); - quat_to_mat4(cob->matrix, quat); - } - else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { - /* axis angle */ - axis_angle_to_mat4(cob->matrix, td->ext->rotAxis, *td->ext->rotAngle); - } - else { - /* eulers */ - eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder); - } - } + /* Make a temporary bConstraintOb for use by limit constraints + * - they only care that cob->matrix is correctly set ;-) + * - current space should be local + */ + memset(cob, 0, sizeof(bConstraintOb)); + if (td->ext) { + if (td->ext->rotOrder == ROT_MODE_QUAT) { + /* quats */ + /* objects and bones do normalization first too, otherwise + * we don't necessarily end up with a rotation matrix, and + * then conversion back to quat gives a different result */ + float quat[4]; + normalize_qt_qt(quat, td->ext->quat); + quat_to_mat4(cob->matrix, quat); + } + else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { + /* axis angle */ + axis_angle_to_mat4(cob->matrix, td->ext->rotAxis, *td->ext->rotAngle); + } + else { + /* eulers */ + eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder); + } + } } static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) { - if (td->con) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT); - bConstraintOb cob; - bConstraint *con; - bool do_limit = false; - - /* Evaluate valid constraints */ - for (con = td->con; con; con = con->next) { - /* only consider constraint if enabled */ - if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue; - if (con->enforce == 0.0f) continue; - - /* we're only interested in Limit-Rotation constraints */ - if (con->type == CONSTRAINT_TYPE_ROTLIMIT) { - bRotLimitConstraint *data = con->data; - - /* only use it if it's tagged for this purpose */ - if ((data->flag2 & LIMIT_TRANSFORM) == 0) - continue; - - /* skip incompatible spacetypes */ - if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) - continue; - - /* only do conversion if necessary, to preserve quats and eulers */ - if (do_limit == false) { - constraintob_from_transdata(&cob, td); - do_limit = true; - } - - /* do space conversions */ - if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->mtx (this should be ok) */ - mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); - } - - /* do constraint */ - cti->evaluate_constraint(con, &cob, NULL); - - /* convert spaces again */ - if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->smtx (this should be ok) */ - mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); - } - } - } - - if (do_limit) { - /* copy results from cob->matrix */ - if (td->ext->rotOrder == ROT_MODE_QUAT) { - /* quats */ - mat4_to_quat(td->ext->quat, cob.matrix); - } - else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { - /* axis angle */ - mat4_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, cob.matrix); - } - else { - /* eulers */ - mat4_to_eulO(td->ext->rot, td->ext->rotOrder, cob.matrix); - } - } - } + if (td->con) { + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT); + bConstraintOb cob; + bConstraint *con; + bool do_limit = false; + + /* Evaluate valid constraints */ + for (con = td->con; con; con = con->next) { + /* only consider constraint if enabled */ + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) + continue; + if (con->enforce == 0.0f) + continue; + + /* we're only interested in Limit-Rotation constraints */ + if (con->type == CONSTRAINT_TYPE_ROTLIMIT) { + bRotLimitConstraint *data = con->data; + + /* only use it if it's tagged for this purpose */ + if ((data->flag2 & LIMIT_TRANSFORM) == 0) + continue; + + /* skip incompatible spacetypes */ + if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) + continue; + + /* only do conversion if necessary, to preserve quats and eulers */ + if (do_limit == false) { + constraintob_from_transdata(&cob, td); + do_limit = true; + } + + /* do space conversions */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); + } + + /* do constraint */ + cti->evaluate_constraint(con, &cob, NULL); + + /* convert spaces again */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->smtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); + } + } + } + + if (do_limit) { + /* copy results from cob->matrix */ + if (td->ext->rotOrder == ROT_MODE_QUAT) { + /* quats */ + mat4_to_quat(td->ext->quat, cob.matrix); + } + else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { + /* axis angle */ + mat4_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, cob.matrix); + } + else { + /* eulers */ + mat4_to_eulO(td->ext->rot, td->ext->rotOrder, cob.matrix); + } + } + } } static void constraintSizeLim(TransInfo *t, TransData *td) { - if (td->con && td->ext) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); - bConstraintOb cob = {NULL}; - bConstraint *con; - float size_sign[3], size_abs[3]; - int i; - - /* Make a temporary bConstraintOb for using these limit constraints - * - they only care that cob->matrix is correctly set ;-) - * - current space should be local - */ - if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { - /* scale val and reset size */ - return; // TODO: fix this case - } - else { - /* Reset val if SINGLESIZE but using a constraint */ - if (td->flag & TD_SINGLESIZE) - return; - - /* separate out sign to apply back later */ - for (i = 0; i < 3; i++) { - size_sign[i] = signf(td->ext->size[i]); - size_abs[i] = fabsf(td->ext->size[i]); - } - - size_to_mat4(cob.matrix, size_abs); - } - - /* Evaluate valid constraints */ - for (con = td->con; con; con = con->next) { - /* only consider constraint if enabled */ - if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue; - if (con->enforce == 0.0f) continue; - - /* we're only interested in Limit-Scale constraints */ - if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { - bSizeLimitConstraint *data = con->data; - - /* only use it if it's tagged for this purpose */ - if ((data->flag2 & LIMIT_TRANSFORM) == 0) - continue; - - /* do space conversions */ - if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->mtx (this should be ok) */ - mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); - } - else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { - /* skip... incompatible spacetype */ - continue; - } - - /* do constraint */ - cti->evaluate_constraint(con, &cob, NULL); - - /* convert spaces again */ - if (con->ownspace == CONSTRAINT_SPACE_WORLD) { - /* just multiply by td->smtx (this should be ok) */ - mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); - } - } - } - - /* copy results from cob->matrix */ - if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { - /* scale val and reset size */ - return; // TODO: fix this case - } - else { - /* Reset val if SINGLESIZE but using a constraint */ - if (td->flag & TD_SINGLESIZE) - return; - - /* extrace scale from matrix and apply back sign */ - mat4_to_size(td->ext->size, cob.matrix); - mul_v3_v3(td->ext->size, size_sign); - } - } + if (td->con && td->ext) { + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); + bConstraintOb cob = {NULL}; + bConstraint *con; + float size_sign[3], size_abs[3]; + int i; + + /* Make a temporary bConstraintOb for using these limit constraints + * - they only care that cob->matrix is correctly set ;-) + * - current space should be local + */ + if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { + /* scale val and reset size */ + return; // TODO: fix this case + } + else { + /* Reset val if SINGLESIZE but using a constraint */ + if (td->flag & TD_SINGLESIZE) + return; + + /* separate out sign to apply back later */ + for (i = 0; i < 3; i++) { + size_sign[i] = signf(td->ext->size[i]); + size_abs[i] = fabsf(td->ext->size[i]); + } + + size_to_mat4(cob.matrix, size_abs); + } + + /* Evaluate valid constraints */ + for (con = td->con; con; con = con->next) { + /* only consider constraint if enabled */ + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) + continue; + if (con->enforce == 0.0f) + continue; + + /* we're only interested in Limit-Scale constraints */ + if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { + bSizeLimitConstraint *data = con->data; + + /* only use it if it's tagged for this purpose */ + if ((data->flag2 & LIMIT_TRANSFORM) == 0) + continue; + + /* do space conversions */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->mtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); + } + else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { + /* skip... incompatible spacetype */ + continue; + } + + /* do constraint */ + cti->evaluate_constraint(con, &cob, NULL); + + /* convert spaces again */ + if (con->ownspace == CONSTRAINT_SPACE_WORLD) { + /* just multiply by td->smtx (this should be ok) */ + mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); + } + } + } + + /* copy results from cob->matrix */ + if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { + /* scale val and reset size */ + return; // TODO: fix this case + } + else { + /* Reset val if SINGLESIZE but using a constraint */ + if (td->flag & TD_SINGLESIZE) + return; + + /* extrace scale from matrix and apply back sign */ + mat4_to_size(td->ext->size, cob.matrix); + mul_v3_v3(td->ext->size, size_sign); + } + } } - /* -------------------------------------------------------------------- */ /* Transform (Bend) */ @@ -3195,246 +3201,258 @@ static void constraintSizeLim(TransInfo *t, TransData *td) * \{ */ struct BendCustomData { - /* All values are in global space. */ - float warp_sta[3]; - float warp_end[3]; + /* All values are in global space. */ + float warp_sta[3]; + float warp_end[3]; - float warp_nor[3]; - float warp_tan[3]; + float warp_nor[3]; + float warp_tan[3]; - /* for applying the mouse distance */ - float warp_init_dist; + /* for applying the mouse distance */ + float warp_init_dist; }; static void initBend(TransInfo *t) { - const float mval_fl[2] = {UNPACK2(t->mval)}; - const float *curs; - float tvec[3]; - struct BendCustomData *data; + const float mval_fl[2] = {UNPACK2(t->mval)}; + const float *curs; + float tvec[3]; + struct BendCustomData *data; - t->mode = TFM_BEND; - t->transform = Bend; - t->handleEvent = handleEventBend; + t->mode = TFM_BEND; + t->transform = Bend; + t->handleEvent = handleEventBend; - setInputPostFct(&t->mouse, postInputRotation); - initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING); + setInputPostFct(&t->mouse, postInputRotation); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING); - t->idx_max = 1; - t->num.idx_max = 1; - t->snap[0] = 0.0f; - t->snap[1] = SNAP_INCREMENTAL_ANGLE; - t->snap[2] = t->snap[1] * 0.2; + t->idx_max = 1; + t->num.idx_max = 1; + t->snap[0] = 0.0f; + t->snap[1] = SNAP_INCREMENTAL_ANGLE; + t->snap[2] = t->snap[1] * 0.2; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); - t->num.unit_type[0] = B_UNIT_ROTATION; - t->num.unit_type[1] = B_UNIT_LENGTH; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; + t->num.unit_type[1] = B_UNIT_LENGTH; - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; - //copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view)); - if ((t->flag & T_OVERRIDE_CENTER) == 0) { - calculateCenterCursor(t, t->center_global); - } - calculateCenterLocal(t, t->center_global); + //copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view)); + if ((t->flag & T_OVERRIDE_CENTER) == 0) { + calculateCenterCursor(t, t->center_global); + } + calculateCenterLocal(t, t->center_global); - t->val = 0.0f; + t->val = 0.0f; - data = MEM_callocN(sizeof(*data), __func__); + data = MEM_callocN(sizeof(*data), __func__); - curs = t->scene->cursor.location; - copy_v3_v3(data->warp_sta, curs); - ED_view3d_win_to_3d(t->sa->spacedata.first, t->ar, curs, mval_fl, data->warp_end); + curs = t->scene->cursor.location; + copy_v3_v3(data->warp_sta, curs); + ED_view3d_win_to_3d(t->sa->spacedata.first, t->ar, curs, mval_fl, data->warp_end); - copy_v3_v3(data->warp_nor, t->viewinv[2]); - normalize_v3(data->warp_nor); + copy_v3_v3(data->warp_nor, t->viewinv[2]); + normalize_v3(data->warp_nor); - /* tangent */ - sub_v3_v3v3(tvec, data->warp_end, data->warp_sta); - cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor); - normalize_v3(data->warp_tan); + /* tangent */ + sub_v3_v3v3(tvec, data->warp_end, data->warp_sta); + cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor); + normalize_v3(data->warp_tan); - data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta); + data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta); - t->custom.mode.data = data; - t->custom.mode.use_free = true; + t->custom.mode.data = data; + t->custom.mode.use_free = true; } static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event) { - eRedrawFlag status = TREDRAW_NOTHING; + eRedrawFlag status = TREDRAW_NOTHING; - if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { - status = TREDRAW_HARD; - } + if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { + status = TREDRAW_HARD; + } - return status; + return status; } static void Bend(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; - float pivot_global[3]; - float warp_end_radius_global[3]; - int i; - char str[UI_MAX_DRAW_STR]; - const struct BendCustomData *data = t->custom.mode.data; - const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0; + float vec[3]; + float pivot_global[3]; + float warp_end_radius_global[3]; + int i; + char str[UI_MAX_DRAW_STR]; + const struct BendCustomData *data = t->custom.mode.data; + const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0; - union { - struct { float angle, scale; }; - float vector[2]; - } values; + union { + struct { + float angle, scale; + }; + float vector[2]; + } values; - /* amount of radians for bend */ - copy_v2_v2(values.vector, t->values); + /* amount of radians for bend */ + copy_v2_v2(values.vector, t->values); #if 0 - snapGrid(t, angle_rad); + snapGrid(t, angle_rad); #else - /* hrmf, snapping radius is using 'angle' steps, need to convert to something else - * this isnt essential but nicer to give reasonable snapping values for radius */ - if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) { - const float radius_snap = 0.1f; - const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap; - values.scale *= snap_hack; - snapGridIncrement(t, values.vector); - values.scale /= snap_hack; - } + /* hrmf, snapping radius is using 'angle' steps, need to convert to something else + * this isnt essential but nicer to give reasonable snapping values for radius */ + if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) { + const float radius_snap = 0.1f; + const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap; + values.scale *= snap_hack; + snapGridIncrement(t, values.vector); + values.scale /= snap_hack; + } #endif - if (applyNumInput(&t->num, values.vector)) { - values.scale = values.scale / data->warp_init_dist; - } - - copy_v2_v2(t->values, values.vector); - - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN * 2]; - - outputNumInput(&(t->num), c, &t->scene->unit); - - BLI_snprintf(str, sizeof(str), IFACE_("Bend Angle: %s Radius: %s Alt, Clamp %s"), - &c[0], &c[NUM_STR_REP_LEN], - WM_bool_as_string(is_clamp)); - } - else { - /* default header print */ - BLI_snprintf(str, sizeof(str), IFACE_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"), - RAD2DEGF(values.angle), values.scale * data->warp_init_dist, - WM_bool_as_string(is_clamp)); - } - - values.angle *= -1.0f; - values.scale *= data->warp_init_dist; - - /* calc 'data->warp_end' from 'data->warp_end_init' */ - copy_v3_v3(warp_end_radius_global, data->warp_end); - dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale); - /* done */ - - /* calculate pivot */ - copy_v3_v3(pivot_global, data->warp_sta); - if (values.angle > 0.0f) { - madd_v3_v3fl(pivot_global, data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle)); - } - else { - madd_v3_v3fl(pivot_global, data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle)); - } - - /* TODO(campbell): xform, compensate object center. */ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - - float warp_sta_local[3]; - float warp_end_local[3]; - float warp_end_radius_local[3]; - float pivot_local[3]; - - if (tc->use_local_mat) { - sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]); - sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]); - sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]); - sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]); - } - else { - copy_v3_v3(warp_sta_local, data->warp_sta); - copy_v3_v3(warp_end_local, data->warp_end); - copy_v3_v3(warp_end_radius_local, warp_end_radius_global); - copy_v3_v3(pivot_local, pivot_global); - } - - for (i = 0; i < tc->data_len; i++, td++) { - float mat[3][3]; - float delta[3]; - float fac, fac_scaled; - - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; - - if (UNLIKELY(values.angle == 0.0f)) { - copy_v3_v3(td->loc, td->iloc); - continue; - } - - copy_v3_v3(vec, td->iloc); - mul_m3_v3(td->mtx, vec); - - fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local); - if (is_clamp) { - CLAMP(fac, 0.0f, 1.0f); - } - - if (t->options & CTX_GPENCIL_STROKES) { - /* grease pencil multiframe falloff */ - bGPDstroke *gps = (bGPDstroke *)td->extra; - if (gps != NULL) { - fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff; - } - else { - fac_scaled = fac * td->factor; - } - } - else { - fac_scaled = fac * td->factor; - } - - axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled); - interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled); - sub_v3_v3(delta, warp_sta_local); - - /* delta is subtracted, rotation adds back this offset */ - sub_v3_v3(vec, delta); - - sub_v3_v3(vec, pivot_local); - mul_m3_v3(mat, vec); - add_v3_v3(vec, pivot_local); - - mul_m3_v3(td->smtx, vec); - - /* rotation */ - if ((t->flag & T_POINTS) == 0) { - ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS); - } - - /* location */ - copy_v3_v3(td->loc, vec); - } - } - - recalcData(t); - - ED_area_status_text(t->sa, str); + if (applyNumInput(&t->num, values.vector)) { + values.scale = values.scale / data->warp_init_dist; + } + + copy_v2_v2(t->values, values.vector); + + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN * 2]; + + outputNumInput(&(t->num), c, &t->scene->unit); + + BLI_snprintf(str, + sizeof(str), + IFACE_("Bend Angle: %s Radius: %s Alt, Clamp %s"), + &c[0], + &c[NUM_STR_REP_LEN], + WM_bool_as_string(is_clamp)); + } + else { + /* default header print */ + BLI_snprintf(str, + sizeof(str), + IFACE_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"), + RAD2DEGF(values.angle), + values.scale * data->warp_init_dist, + WM_bool_as_string(is_clamp)); + } + + values.angle *= -1.0f; + values.scale *= data->warp_init_dist; + + /* calc 'data->warp_end' from 'data->warp_end_init' */ + copy_v3_v3(warp_end_radius_global, data->warp_end); + dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale); + /* done */ + + /* calculate pivot */ + copy_v3_v3(pivot_global, data->warp_sta); + if (values.angle > 0.0f) { + madd_v3_v3fl(pivot_global, + data->warp_tan, + -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle)); + } + else { + madd_v3_v3fl(pivot_global, + data->warp_tan, + +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle)); + } + + /* TODO(campbell): xform, compensate object center. */ + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + + float warp_sta_local[3]; + float warp_end_local[3]; + float warp_end_radius_local[3]; + float pivot_local[3]; + + if (tc->use_local_mat) { + sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]); + sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]); + sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]); + sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]); + } + else { + copy_v3_v3(warp_sta_local, data->warp_sta); + copy_v3_v3(warp_end_local, data->warp_end); + copy_v3_v3(warp_end_radius_local, warp_end_radius_global); + copy_v3_v3(pivot_local, pivot_global); + } + + for (i = 0; i < tc->data_len; i++, td++) { + float mat[3][3]; + float delta[3]; + float fac, fac_scaled; + + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + if (UNLIKELY(values.angle == 0.0f)) { + copy_v3_v3(td->loc, td->iloc); + continue; + } + + copy_v3_v3(vec, td->iloc); + mul_m3_v3(td->mtx, vec); + + fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local); + if (is_clamp) { + CLAMP(fac, 0.0f, 1.0f); + } + + if (t->options & CTX_GPENCIL_STROKES) { + /* grease pencil multiframe falloff */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff; + } + else { + fac_scaled = fac * td->factor; + } + } + else { + fac_scaled = fac * td->factor; + } + + axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled); + interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled); + sub_v3_v3(delta, warp_sta_local); + + /* delta is subtracted, rotation adds back this offset */ + sub_v3_v3(vec, delta); + + sub_v3_v3(vec, pivot_local); + mul_m3_v3(mat, vec); + add_v3_v3(vec, pivot_local); + + mul_m3_v3(td->smtx, vec); + + /* rotation */ + if ((t->flag & T_POINTS) == 0) { + ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS); + } + + /* location */ + copy_v3_v3(td->loc, vec); + } + } + + recalcData(t); + + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Shear) */ @@ -3443,192 +3461,195 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) static void initShear_mouseInputMode(TransInfo *t) { - float dir[3]; + float dir[3]; - if (t->custom.mode.data == NULL) { - copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]); - } - else { - cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]); - } + if (t->custom.mode.data == NULL) { + copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]); + } + else { + cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]); + } - /* Without this, half the gizmo handles move in the opposite direction. */ - if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) { - negate_v3(dir); - } + /* Without this, half the gizmo handles move in the opposite direction. */ + if ((t->orient_axis_ortho + 1) % 3 != t->orient_axis) { + negate_v3(dir); + } - mul_mat3_m4_v3(t->viewmat, dir); - if (normalize_v2(dir) == 0.0f) { - dir[0] = 1.0f; - } - setCustomPointsFromDirection(t, &t->mouse, dir); + mul_mat3_m4_v3(t->viewmat, dir); + if (normalize_v2(dir) == 0.0f) { + dir[0] = 1.0f; + } + setCustomPointsFromDirection(t, &t->mouse, dir); - initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); } static void initShear(TransInfo *t) { - t->mode = TFM_SHEAR; - t->transform = applyShear; - t->handleEvent = handleEventShear; + t->mode = TFM_SHEAR; + t->transform = applyShear; + t->handleEvent = handleEventShear; - if (t->orient_axis == t->orient_axis_ortho) { - t->orient_axis = 2; - t->orient_axis_ortho = 1; - } + if (t->orient_axis == t->orient_axis_ortho) { + t->orient_axis = 2; + t->orient_axis_ortho = 1; + } - initShear_mouseInputMode(t); + initShear_mouseInputMode(t); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */ + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; /* Don't think we have any unit here? */ - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; } static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event) { - eRedrawFlag status = TREDRAW_NOTHING; + eRedrawFlag status = TREDRAW_NOTHING; - if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { - /* Use custom.mode.data pointer to signal Shear direction */ - if (t->custom.mode.data == NULL) { - t->custom.mode.data = (void *)1; - } - else { - t->custom.mode.data = NULL; - } - initShear_mouseInputMode(t); + if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { + /* Use custom.mode.data pointer to signal Shear direction */ + if (t->custom.mode.data == NULL) { + t->custom.mode.data = (void *)1; + } + else { + t->custom.mode.data = NULL; + } + initShear_mouseInputMode(t); - status = TREDRAW_HARD; - } - else if (event->type == XKEY && event->val == KM_PRESS) { - t->custom.mode.data = NULL; - initShear_mouseInputMode(t); + status = TREDRAW_HARD; + } + else if (event->type == XKEY && event->val == KM_PRESS) { + t->custom.mode.data = NULL; + initShear_mouseInputMode(t); - status = TREDRAW_HARD; - } - else if (event->type == YKEY && event->val == KM_PRESS) { - t->custom.mode.data = (void *)1; - initShear_mouseInputMode(t); + status = TREDRAW_HARD; + } + else if (event->type == YKEY && event->val == KM_PRESS) { + t->custom.mode.data = (void *)1; + initShear_mouseInputMode(t); - status = TREDRAW_HARD; - } + status = TREDRAW_HARD; + } - return status; + return status; } - static void applyShear(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; - float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3]; - float value; - int i; - char str[UI_MAX_DRAW_STR]; - const bool is_local_center = transdata_check_local_center(t, t->around); - - value = t->values[0]; - - snapGridIncrement(t, &value); - - applyNumInput(&t->num, &value); - - t->values[0] = value; - - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; - - outputNumInput(&(t->num), c, &t->scene->unit); - - BLI_snprintf(str, sizeof(str), IFACE_("Shear: %s %s"), c, t->proptext); - } - else { - /* default header print */ - BLI_snprintf(str, sizeof(str), IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext); - } - - unit_m3(smat); - - // Custom data signals shear direction - if (t->custom.mode.data == NULL) - smat[1][0] = value; - else - smat[0][1] = value; - - copy_v3_v3(axismat_inv[0], t->orient_matrix[t->orient_axis_ortho]); - copy_v3_v3(axismat_inv[2], t->orient_matrix[t->orient_axis]); - cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]); - invert_m3_m3(axismat, axismat_inv); - - mul_m3_series(totmat, axismat_inv, smat, axismat); - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - const float *center, *co; - - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; - - if (t->flag & T_EDIT) { - mul_m3_series(tmat, td->smtx, totmat, td->mtx); - } - else { - copy_m3_m3(tmat, totmat); - } - - if (is_local_center) { - center = td->center; - co = td->loc; - } - else { - center = tc->center_local; - co = td->center; - } - - sub_v3_v3v3(vec, co, center); - - mul_m3_v3(tmat, vec); - - add_v3_v3(vec, center); - sub_v3_v3(vec, co); - - if (t->options & CTX_GPENCIL_STROKES) { - /* grease pencil multiframe falloff */ - bGPDstroke *gps = (bGPDstroke *)td->extra; - if (gps != NULL) { - mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); - } - else { - mul_v3_fl(vec, td->factor); - } - } - else { - mul_v3_fl(vec, td->factor); - } - - add_v3_v3v3(td->loc, td->iloc, vec); - } - } - - recalcData(t); - - ED_area_status_text(t->sa, str); + float vec[3]; + float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3]; + float value; + int i; + char str[UI_MAX_DRAW_STR]; + const bool is_local_center = transdata_check_local_center(t, t->around); + + value = t->values[0]; + + snapGridIncrement(t, &value); + + applyNumInput(&t->num, &value); + + t->values[0] = value; + + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + + outputNumInput(&(t->num), c, &t->scene->unit); + + BLI_snprintf(str, sizeof(str), IFACE_("Shear: %s %s"), c, t->proptext); + } + else { + /* default header print */ + BLI_snprintf(str, + sizeof(str), + IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), + value, + t->proptext); + } + + unit_m3(smat); + + // Custom data signals shear direction + if (t->custom.mode.data == NULL) + smat[1][0] = value; + else + smat[0][1] = value; + + copy_v3_v3(axismat_inv[0], t->orient_matrix[t->orient_axis_ortho]); + copy_v3_v3(axismat_inv[2], t->orient_matrix[t->orient_axis]); + cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]); + invert_m3_m3(axismat, axismat_inv); + + mul_m3_series(totmat, axismat_inv, smat, axismat); + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + const float *center, *co; + + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + if (t->flag & T_EDIT) { + mul_m3_series(tmat, td->smtx, totmat, td->mtx); + } + else { + copy_m3_m3(tmat, totmat); + } + + if (is_local_center) { + center = td->center; + co = td->loc; + } + else { + center = tc->center_local; + co = td->center; + } + + sub_v3_v3v3(vec, co, center); + + mul_m3_v3(tmat, vec); + + add_v3_v3(vec, center); + sub_v3_v3(vec, co); + + if (t->options & CTX_GPENCIL_STROKES) { + /* grease pencil multiframe falloff */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); + } + else { + mul_v3_fl(vec, td->factor); + } + } + else { + mul_v3_fl(vec, td->factor); + } + + add_v3_v3v3(td->loc, td->iloc, vec); + } + } + + recalcData(t); + + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Resize) */ @@ -3637,81 +3658,108 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) static void initResize(TransInfo *t) { - t->mode = TFM_RESIZE; - t->transform = applyResize; + t->mode = TFM_RESIZE; + t->transform = applyResize; - initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); + initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); - t->flag |= T_NULL_ONE; - t->num.val_flag[0] |= NUM_NULL_ONE; - t->num.val_flag[1] |= NUM_NULL_ONE; - t->num.val_flag[2] |= NUM_NULL_ONE; - t->num.flag |= NUM_AFFECT_ALL; - if ((t->flag & T_EDIT) == 0) { - t->flag |= T_NO_ZERO; + t->flag |= T_NULL_ONE; + t->num.val_flag[0] |= NUM_NULL_ONE; + t->num.val_flag[1] |= NUM_NULL_ONE; + t->num.val_flag[2] |= NUM_NULL_ONE; + t->num.flag |= NUM_AFFECT_ALL; + if ((t->flag & T_EDIT) == 0) { + t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO - t->num.val_flag[0] |= NUM_NO_ZERO; - t->num.val_flag[1] |= NUM_NO_ZERO; - t->num.val_flag[2] |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[1] |= NUM_NO_ZERO; + t->num.val_flag[2] |= NUM_NO_ZERO; #endif - } + } - t->idx_max = 2; - t->num.idx_max = 2; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 2; + t->num.idx_max = 2; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; - t->num.unit_type[1] = B_UNIT_NONE; - t->num.unit_type[2] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; + t->num.unit_type[2] = B_UNIT_NONE; } static void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) { - char tvec[NUM_STR_REP_LEN * 3]; - size_t ofs = 0; - if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, &t->scene->unit); - } - else { - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); - } - - if (t->con.mode & CON_APPLY) { - switch (t->num.idx_max) { - case 0: - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale: %s%s %s"), - &tvec[0], t->con.text, t->proptext); - break; - case 1: - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale: %s : %s%s %s"), - &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); - break; - case 2: - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale: %s : %s : %s%s %s"), &tvec[0], - &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); - break; - } - } - else { - if (t->flag & T_2D_EDIT) { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale X: %s Y: %s%s %s"), - &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); - } - else { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Scale X: %s Y: %s Z: %s%s %s"), - &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); - } - } - - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); - } + char tvec[NUM_STR_REP_LEN * 3]; + size_t ofs = 0; + if (hasNumInput(&t->num)) { + outputNumInput(&(t->num), tvec, &t->scene->unit); + } + else { + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); + } + + if (t->con.mode & CON_APPLY) { + switch (t->num.idx_max) { + case 0: + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_("Scale: %s%s %s"), + &tvec[0], + t->con.text, + t->proptext); + break; + case 1: + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_("Scale: %s : %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + t->con.text, + t->proptext); + break; + case 2: + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_("Scale: %s : %s : %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + t->con.text, + t->proptext); + break; + } + } + else { + if (t->flag & T_2D_EDIT) { + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_("Scale X: %s Y: %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + t->con.text, + t->proptext); + } + else { + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_("Scale X: %s Y: %s Z: %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + t->con.text, + t->proptext); + } + } + + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf( + str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } } /** @@ -3721,227 +3769,228 @@ static void headerResize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_ */ static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3]) { - float rmat[3][3]; + float rmat[3][3]; - mat3_to_rot_size(rmat, size, mat); + mat3_to_rot_size(rmat, size, mat); - /* first tried with dotproduct... but the sign flip is crucial */ - if (dot_v3v3(rmat[0], smat[0]) < 0.0f) size[0] = -size[0]; - if (dot_v3v3(rmat[1], smat[1]) < 0.0f) size[1] = -size[1]; - if (dot_v3v3(rmat[2], smat[2]) < 0.0f) size[2] = -size[2]; + /* first tried with dotproduct... but the sign flip is crucial */ + if (dot_v3v3(rmat[0], smat[0]) < 0.0f) + size[0] = -size[0]; + if (dot_v3v3(rmat[1], smat[1]) < 0.0f) + size[1] = -size[1]; + if (dot_v3v3(rmat[2], smat[2]) < 0.0f) + size[2] = -size[2]; } static void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]) { - float tmat[3][3], smat[3][3], center[3]; - float vec[3]; - - if (t->flag & T_EDIT) { - mul_m3_m3m3(smat, mat, td->mtx); - mul_m3_m3m3(tmat, td->smtx, smat); - } - else { - copy_m3_m3(tmat, mat); - } - - if (t->con.applySize) { - t->con.applySize(t, tc, td, tmat); - } - - /* local constraint shouldn't alter center */ - if (transdata_check_local_center(t, t->around)) { - copy_v3_v3(center, td->center); - } - else if (t->options & CTX_MOVIECLIP) { - if (td->flag & TD_INDIVIDUAL_SCALE) { - copy_v3_v3(center, td->center); - } - else { - copy_v3_v3(center, tc->center_local); - } - } - else { - copy_v3_v3(center, tc->center_local); - } - - /* Size checked needed since the 3D cursor only uses rotation fields. */ - if (td->ext && td->ext->size) { - float fsize[3]; - - if (t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) { - float obsizemat[3][3]; - /* Reorient the size mat to fit the oriented object. */ - mul_m3_m3m3(obsizemat, tmat, td->axismtx); - /* print_m3("obsizemat", obsizemat); */ - TransMat3ToSize(obsizemat, td->axismtx, fsize); - /* print_v3("fsize", fsize); */ - } - else { - mat3_to_size(fsize, tmat); - } - - protectedSizeBits(td->protectflag, fsize); - - if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */ - if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { - /* scale val and reset size */ - *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor); - - td->ext->size[0] = td->ext->isize[0]; - td->ext->size[1] = td->ext->isize[1]; - td->ext->size[2] = td->ext->isize[2]; - } - else { - /* Reset val if SINGLESIZE but using a constraint */ - if (td->flag & TD_SINGLESIZE) - *td->val = td->ival; - - td->ext->size[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); - td->ext->size[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); - td->ext->size[2] = td->ext->isize[2] * (1 + (fsize[2] - 1) * td->factor); - } - } - - constraintSizeLim(t, td); - } - - /* For individual element center, Editmode need to use iloc */ - if (t->flag & T_POINTS) - sub_v3_v3v3(vec, td->iloc, center); - else - sub_v3_v3v3(vec, td->center, center); - - mul_m3_v3(tmat, vec); - - add_v3_v3(vec, center); - if (t->flag & T_POINTS) - sub_v3_v3(vec, td->iloc); - else - sub_v3_v3(vec, td->center); - - /* grease pencil falloff */ - if (t->options & CTX_GPENCIL_STROKES) { - bGPDstroke *gps = (bGPDstroke *)td->extra; - mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); - - /* scale stroke thickness */ - if (td->val) { - snapGridIncrement(t, t->values); - applyNumInput(&t->num, t->values); - - float ratio = t->values[0]; - *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff; - CLAMP_MIN(*td->val, 0.001f); - } - - } - else { - mul_v3_fl(vec, td->factor); - } - - if (t->flag & (T_OBJECT | T_POSE)) { - mul_m3_v3(td->smtx, vec); - } - - protectedTransBits(td->protectflag, vec); - if (td->loc) { - add_v3_v3v3(td->loc, td->iloc, vec); - } - - constraintTransLim(t, td); + float tmat[3][3], smat[3][3], center[3]; + float vec[3]; + + if (t->flag & T_EDIT) { + mul_m3_m3m3(smat, mat, td->mtx); + mul_m3_m3m3(tmat, td->smtx, smat); + } + else { + copy_m3_m3(tmat, mat); + } + + if (t->con.applySize) { + t->con.applySize(t, tc, td, tmat); + } + + /* local constraint shouldn't alter center */ + if (transdata_check_local_center(t, t->around)) { + copy_v3_v3(center, td->center); + } + else if (t->options & CTX_MOVIECLIP) { + if (td->flag & TD_INDIVIDUAL_SCALE) { + copy_v3_v3(center, td->center); + } + else { + copy_v3_v3(center, tc->center_local); + } + } + else { + copy_v3_v3(center, tc->center_local); + } + + /* Size checked needed since the 3D cursor only uses rotation fields. */ + if (td->ext && td->ext->size) { + float fsize[3]; + + if (t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) { + float obsizemat[3][3]; + /* Reorient the size mat to fit the oriented object. */ + mul_m3_m3m3(obsizemat, tmat, td->axismtx); + /* print_m3("obsizemat", obsizemat); */ + TransMat3ToSize(obsizemat, td->axismtx, fsize); + /* print_v3("fsize", fsize); */ + } + else { + mat3_to_size(fsize, tmat); + } + + protectedSizeBits(td->protectflag, fsize); + + if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */ + if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { + /* scale val and reset size */ + *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor); + + td->ext->size[0] = td->ext->isize[0]; + td->ext->size[1] = td->ext->isize[1]; + td->ext->size[2] = td->ext->isize[2]; + } + else { + /* Reset val if SINGLESIZE but using a constraint */ + if (td->flag & TD_SINGLESIZE) + *td->val = td->ival; + + td->ext->size[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); + td->ext->size[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); + td->ext->size[2] = td->ext->isize[2] * (1 + (fsize[2] - 1) * td->factor); + } + } + + constraintSizeLim(t, td); + } + + /* For individual element center, Editmode need to use iloc */ + if (t->flag & T_POINTS) + sub_v3_v3v3(vec, td->iloc, center); + else + sub_v3_v3v3(vec, td->center, center); + + mul_m3_v3(tmat, vec); + + add_v3_v3(vec, center); + if (t->flag & T_POINTS) + sub_v3_v3(vec, td->iloc); + else + sub_v3_v3(vec, td->center); + + /* grease pencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); + + /* scale stroke thickness */ + if (td->val) { + snapGridIncrement(t, t->values); + applyNumInput(&t->num, t->values); + + float ratio = t->values[0]; + *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff; + CLAMP_MIN(*td->val, 0.001f); + } + } + else { + mul_v3_fl(vec, td->factor); + } + + if (t->flag & (T_OBJECT | T_POSE)) { + mul_m3_v3(td->smtx, vec); + } + + protectedTransBits(td->protectflag, vec); + if (td->loc) { + add_v3_v3v3(td->loc, td->iloc, vec); + } + + constraintTransLim(t, td); } static void applyResize(TransInfo *t, const int UNUSED(mval[2])) { - float mat[3][3]; - int i; - char str[UI_MAX_DRAW_STR]; - - if (t->flag & T_AUTOVALUES) { - copy_v3_v3(t->values, t->auto_values); - } - else { - float ratio = t->values[0]; - - copy_v3_fl(t->values, ratio); - - snapGridIncrement(t, t->values); - - if (applyNumInput(&t->num, t->values)) { - constraintNumInput(t, t->values); - } - - applySnapping(t, t->values); - } - - size_to_mat3(mat, t->values); - if (t->con.mode & CON_APPLY) { - t->con.applySize(t, NULL, NULL, mat); - - /* Only so we have re-usable value with redo. */ - float pvec[3] = {0.0f, 0.0f, 0.0f}; - int j = 0; - for (i = 0; i < 3; i++) { - if (!(t->con.mode & (CON_AXIS0 << i))) { - t->values[i] = 1.0f; - } - else { - pvec[j++] = t->values[i]; - } - } - headerResize(t, pvec, str); - } - else { - headerResize(t, t->values, str); - } - - copy_m3_m3(t->mat, mat); // used in gizmo - - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; - - ElementResize(t, tc, td, mat); - } - } - - /* evil hack - redo resize if cliping needed */ - if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values, 1)) { - size_to_mat3(mat, t->values); - - if (t->con.mode & CON_APPLY) { - t->con.applySize(t, NULL, NULL, mat); - } - - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) - ElementResize(t, tc, td, mat); - - /* In proportional edit it can happen that */ - /* vertices in the radius of the brush end */ - /* outside the clipping area */ - /* XXX HACK - dg */ - if (t->flag & T_PROP_EDIT_ALL) { - clipUVData(t); - } - } - } - - recalcData(t); - - ED_area_status_text(t->sa, str); + float mat[3][3]; + int i; + char str[UI_MAX_DRAW_STR]; + + if (t->flag & T_AUTOVALUES) { + copy_v3_v3(t->values, t->auto_values); + } + else { + float ratio = t->values[0]; + + copy_v3_fl(t->values, ratio); + + snapGridIncrement(t, t->values); + + if (applyNumInput(&t->num, t->values)) { + constraintNumInput(t, t->values); + } + + applySnapping(t, t->values); + } + + size_to_mat3(mat, t->values); + if (t->con.mode & CON_APPLY) { + t->con.applySize(t, NULL, NULL, mat); + + /* Only so we have re-usable value with redo. */ + float pvec[3] = {0.0f, 0.0f, 0.0f}; + int j = 0; + for (i = 0; i < 3; i++) { + if (!(t->con.mode & (CON_AXIS0 << i))) { + t->values[i] = 1.0f; + } + else { + pvec[j++] = t->values[i]; + } + } + headerResize(t, pvec, str); + } + else { + headerResize(t, t->values, str); + } + + copy_m3_m3(t->mat, mat); // used in gizmo + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + ElementResize(t, tc, td, mat); + } + } + + /* evil hack - redo resize if cliping needed */ + if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values, 1)) { + size_to_mat3(mat, t->values); + + if (t->con.mode & CON_APPLY) { + t->con.applySize(t, NULL, NULL, mat); + } + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) + ElementResize(t, tc, td, mat); + + /* In proportional edit it can happen that */ + /* vertices in the radius of the brush end */ + /* outside the clipping area */ + /* XXX HACK - dg */ + if (t->flag & T_PROP_EDIT_ALL) { + clipUVData(t); + } + } + } + + recalcData(t); + + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Skin) */ @@ -3950,101 +3999,101 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) static void initSkinResize(TransInfo *t) { - t->mode = TFM_SKIN_RESIZE; - t->transform = applySkinResize; + t->mode = TFM_SKIN_RESIZE; + t->transform = applySkinResize; - initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); + initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); - t->flag |= T_NULL_ONE; - t->num.val_flag[0] |= NUM_NULL_ONE; - t->num.val_flag[1] |= NUM_NULL_ONE; - t->num.val_flag[2] |= NUM_NULL_ONE; - t->num.flag |= NUM_AFFECT_ALL; - if ((t->flag & T_EDIT) == 0) { - t->flag |= T_NO_ZERO; + t->flag |= T_NULL_ONE; + t->num.val_flag[0] |= NUM_NULL_ONE; + t->num.val_flag[1] |= NUM_NULL_ONE; + t->num.val_flag[2] |= NUM_NULL_ONE; + t->num.flag |= NUM_AFFECT_ALL; + if ((t->flag & T_EDIT) == 0) { + t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO - t->num.val_flag[0] |= NUM_NO_ZERO; - t->num.val_flag[1] |= NUM_NO_ZERO; - t->num.val_flag[2] |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[1] |= NUM_NO_ZERO; + t->num.val_flag[2] |= NUM_NO_ZERO; #endif - } + } - t->idx_max = 2; - t->num.idx_max = 2; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 2; + t->num.idx_max = 2; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; - t->num.unit_type[1] = B_UNIT_NONE; - t->num.unit_type[2] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; + t->num.unit_type[2] = B_UNIT_NONE; } static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) { - float size[3], mat[3][3]; - int i; - char str[UI_MAX_DRAW_STR]; + float size[3], mat[3][3]; + int i; + char str[UI_MAX_DRAW_STR]; - copy_v3_fl(size, t->values[0]); + copy_v3_fl(size, t->values[0]); - snapGridIncrement(t, size); + snapGridIncrement(t, size); - if (applyNumInput(&t->num, size)) { - constraintNumInput(t, size); - } + if (applyNumInput(&t->num, size)) { + constraintNumInput(t, size); + } - applySnapping(t, size); + applySnapping(t, size); - if (t->flag & T_AUTOVALUES) { - copy_v3_v3(size, t->auto_values); - } + if (t->flag & T_AUTOVALUES) { + copy_v3_v3(size, t->auto_values); + } - copy_v3_v3(t->values, size); + copy_v3_v3(t->values, size); - size_to_mat3(mat, size); + size_to_mat3(mat, size); - headerResize(t, size, str); + headerResize(t, size, str); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float tmat[3][3], smat[3][3]; - float fsize[3]; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float tmat[3][3], smat[3][3]; + float fsize[3]; - if (td->flag & TD_NOACTION) - break; + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (t->flag & T_EDIT) { - mul_m3_m3m3(smat, mat, td->mtx); - mul_m3_m3m3(tmat, td->smtx, smat); - } - else { - copy_m3_m3(tmat, mat); - } + if (t->flag & T_EDIT) { + mul_m3_m3m3(smat, mat, td->mtx); + mul_m3_m3m3(tmat, td->smtx, smat); + } + else { + copy_m3_m3(tmat, mat); + } - if (t->con.applySize) { - t->con.applySize(t, NULL, NULL, tmat); - } + if (t->con.applySize) { + t->con.applySize(t, NULL, NULL, tmat); + } - mat3_to_size(fsize, tmat); - td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); - td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); - } - } + mat3_to_size(fsize, tmat); + td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); + td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (ToSphere) */ @@ -4053,96 +4102,97 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) static void initToSphere(TransInfo *t) { - int i; + int i; - t->mode = TFM_TOSPHERE; - t->transform = applyToSphere; + t->mode = TFM_TOSPHERE; + t->transform = applyToSphere; - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->num.val_flag[0] |= NUM_NULL_ONE | NUM_NO_NEGATIVE; - t->flag |= T_NO_CONSTRAINT; + t->num.val_flag[0] |= NUM_NULL_ONE | NUM_NO_NEGATIVE; + t->flag |= T_NO_CONSTRAINT; - // Calculate average radius - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - t->val += len_v3v3(tc->center_local, td->iloc); - } - } + // Calculate average radius + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + t->val += len_v3v3(tc->center_local, td->iloc); + } + } - t->val /= (float)t->data_len_all; + t->val /= (float)t->data_len_all; } static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; - float ratio, radius; - int i; - char str[UI_MAX_DRAW_STR]; + float vec[3]; + float ratio, radius; + int i; + char str[UI_MAX_DRAW_STR]; - ratio = t->values[0]; + ratio = t->values[0]; - snapGridIncrement(t, &ratio); + snapGridIncrement(t, &ratio); - applyNumInput(&t->num, &ratio); + applyNumInput(&t->num, &ratio); - CLAMP(ratio, 0.0f, 1.0f); + CLAMP(ratio, 0.0f, 1.0f); - t->values[0] = ratio; + t->values[0] = ratio; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %s %s"), c, t->proptext); - } - else { - /* default header print */ - BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %.4f %s"), ratio, t->proptext); - } + BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %s %s"), c, t->proptext); + } + else { + /* default header print */ + BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %.4f %s"), ratio, t->proptext); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float tratio; - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float tratio; + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - sub_v3_v3v3(vec, td->iloc, tc->center_local); + sub_v3_v3v3(vec, td->iloc, tc->center_local); - radius = normalize_v3(vec); + radius = normalize_v3(vec); - tratio = ratio * td->factor; + tratio = ratio * td->factor; - mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio); + mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio); - add_v3_v3v3(td->loc, tc->center_local, vec); - } - } + add_v3_v3v3(td->loc, tc->center_local, vec); + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Rotation) */ @@ -4151,56 +4201,66 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) static void postInputRotation(TransInfo *t, float values[3]) { - float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); - if ((t->con.mode & CON_APPLY) && t->con.applyRot) { - t->con.applyRot(t, NULL, NULL, axis_final, values); - } + float axis_final[3]; + copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + if ((t->con.mode & CON_APPLY) && t->con.applyRot) { + t->con.applyRot(t, NULL, NULL, axis_final, values); + } } static void initRotation(TransInfo *t) { - t->mode = TFM_ROTATION; - t->transform = applyRotation; + t->mode = TFM_ROTATION; + t->transform = applyRotation; - setInputPostFct(&t->mouse, postInputRotation); - initMouseInputMode(t, &t->mouse, INPUT_ANGLE); + setInputPostFct(&t->mouse, postInputRotation); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = DEG2RAD(5.0); - t->snap[2] = DEG2RAD(1.0); + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); - copy_v3_fl(t->num.val_inc, t->snap[2]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); - t->num.unit_type[0] = B_UNIT_ROTATION; + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; - if (t->flag & T_2D_EDIT) - t->flag |= T_NO_CONSTRAINT; + if (t->flag & T_2D_EDIT) + t->flag |= T_NO_CONSTRAINT; } /* Used by Transform Rotation and Transform Normal Rotation */ static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) { - size_t ofs = 0; + size_t ofs = 0; - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); - } - else { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %.2f%s %s"), - RAD2DEGF(final), t->con.text, t->proptext); - } + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_("Rot: %s %s %s"), + &c[0], + t->con.text, + t->proptext); + } + else { + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_("Rot: %.2f%s %s"), + RAD2DEGF(final), + t->con.text, + t->proptext); + } - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); - } + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf( + str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } } /** @@ -4209,309 +4269,314 @@ static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) * * Protected axis and other transform settings are taken into account. */ -static void ElementRotation_ex(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const float *center) -{ - float vec[3], totmat[3][3], smat[3][3]; - float eul[3], fmat[3][3], quat[4]; - - if (t->flag & T_POINTS) { - mul_m3_m3m3(totmat, mat, td->mtx); - mul_m3_m3m3(smat, td->smtx, totmat); - - /* apply gpencil falloff */ - if (t->options & CTX_GPENCIL_STROKES) { - bGPDstroke *gps = (bGPDstroke *)td->extra; - float sx = smat[0][0]; - float sy = smat[1][1]; - float sz = smat[2][2]; - - mul_m3_fl(smat, gps->runtime.multi_frame_falloff); - /* fix scale */ - smat[0][0] = sx; - smat[1][1] = sy; - smat[2][2] = sz; - } - - sub_v3_v3v3(vec, td->iloc, center); - mul_m3_v3(smat, vec); - - add_v3_v3v3(td->loc, vec, center); - - sub_v3_v3v3(vec, td->loc, td->iloc); - protectedTransBits(td->protectflag, vec); - add_v3_v3v3(td->loc, td->iloc, vec); - - - if (td->flag & TD_USEQUAT) { - mul_m3_series(fmat, td->smtx, mat, td->mtx); - mat3_to_quat(quat, fmat); // Actual transform - - if (td->ext->quat) { - mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); - - /* is there a reason not to have this here? -jahka */ - protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); - } - } - } - /** - * HACK WARNING - * - * This is some VERY ugly special case to deal with pose mode. - * - * The problem is that mtx and smtx include each bone orientation. - * - * That is needed to rotate each bone properly, HOWEVER, to calculate - * the translation component, we only need the actual armature object's - * matrix (and inverse). That is not all though. Once the proper translation - * has been computed, it has to be converted back into the bone's space. - */ - else if (t->flag & T_POSE) { - // Extract and invert armature object matrix - - if ((td->flag & TD_NO_LOC) == 0) { - sub_v3_v3v3(vec, td->center, center); - - mul_m3_v3(tc->mat3, vec); // To Global space - mul_m3_v3(mat, vec); // Applying rotation - mul_m3_v3(tc->imat3, vec); // To Local space - - add_v3_v3(vec, center); - /* vec now is the location where the object has to be */ - - sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location - - /* special exception, see TD_PBONE_LOCAL_MTX definition comments */ - if (td->flag & TD_PBONE_LOCAL_MTX_P) { - /* do nothing */ - } - else if (td->flag & TD_PBONE_LOCAL_MTX_C) { - mul_m3_v3(tc->mat3, vec); // To Global space - mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location) - } - else { - mul_m3_v3(tc->mat3, vec); // To Global space - mul_m3_v3(td->smtx, vec); // To Pose space - } - - protectedTransBits(td->protectflag, vec); - - add_v3_v3v3(td->loc, td->iloc, vec); - - constraintTransLim(t, td); - } - - /* rotation */ - /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same, - * and ElementRotation() might be called in Translation context (with align snapping), - * we need to be sure to actually use the *rotation* matrix here... - * So no other way than storing it in some dedicated members of td->ext! */ - if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */ - /* euler or quaternion/axis-angle? */ - if (td->ext->rotOrder == ROT_MODE_QUAT) { - mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx); - - mat3_to_quat(quat, fmat); /* Actual transform */ - - mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); - /* this function works on end result */ - protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); - - } - else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { - /* calculate effect based on quats */ - float iquat[4], tquat[4]; - - axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); - - mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx); - mat3_to_quat(quat, fmat); /* Actual transform */ - mul_qt_qtqt(tquat, quat, iquat); - - quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); - - /* this function works on end result */ - protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, - td->ext->irotAngle); - } - else { - float eulmat[3][3]; - - mul_m3_m3m3(totmat, mat, td->ext->r_mtx); - mul_m3_m3m3(smat, td->ext->r_smtx, totmat); - - /* calculate the total rotatation in eulers */ - copy_v3_v3(eul, td->ext->irot); - eulO_to_mat3(eulmat, eul, td->ext->rotOrder); - - /* mat = transform, obmat = bone rotation */ - mul_m3_m3m3(fmat, smat, eulmat); - - mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); - - /* and apply (to end result only) */ - protectedRotateBits(td->protectflag, eul, td->ext->irot); - copy_v3_v3(td->ext->rot, eul); - } - - constraintRotLim(t, td); - } - } - else { - if ((td->flag & TD_NO_LOC) == 0) { - /* translation */ - sub_v3_v3v3(vec, td->center, center); - mul_m3_v3(mat, vec); - add_v3_v3(vec, center); - /* vec now is the location where the object has to be */ - sub_v3_v3(vec, td->center); - mul_m3_v3(td->smtx, vec); - - protectedTransBits(td->protectflag, vec); - - add_v3_v3v3(td->loc, td->iloc, vec); - } - - - constraintTransLim(t, td); - - /* rotation */ - if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself - /* euler or quaternion? */ - if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { - /* can be called for texture space translate for example, then opt out */ - if (td->ext->quat) { - mul_m3_series(fmat, td->smtx, mat, td->mtx); - mat3_to_quat(quat, fmat); // Actual transform - - mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); - /* this function works on end result */ - protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); - } - } - else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { - /* calculate effect based on quats */ - float iquat[4], tquat[4]; - - axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); - - mul_m3_series(fmat, td->smtx, mat, td->mtx); - mat3_to_quat(quat, fmat); // Actual transform - mul_qt_qtqt(tquat, quat, iquat); - - quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); - - /* this function works on end result */ - protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, - td->ext->irotAngle); - } - else { - float obmat[3][3]; - - mul_m3_m3m3(totmat, mat, td->mtx); - mul_m3_m3m3(smat, td->smtx, totmat); - - /* calculate the total rotatation in eulers */ - add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */ - eulO_to_mat3(obmat, eul, td->ext->rotOrder); - /* mat = transform, obmat = object rotation */ - mul_m3_m3m3(fmat, smat, obmat); - - mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); - - /* correct back for delta rot */ - sub_v3_v3v3(eul, eul, td->ext->drot); - - /* and apply */ - protectedRotateBits(td->protectflag, eul, td->ext->irot); - copy_v3_v3(td->ext->rot, eul); - } - - constraintRotLim(t, td); - } - } -} - -static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around) +static void ElementRotation_ex( + TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const float *center) +{ + float vec[3], totmat[3][3], smat[3][3]; + float eul[3], fmat[3][3], quat[4]; + + if (t->flag & T_POINTS) { + mul_m3_m3m3(totmat, mat, td->mtx); + mul_m3_m3m3(smat, td->smtx, totmat); + + /* apply gpencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + float sx = smat[0][0]; + float sy = smat[1][1]; + float sz = smat[2][2]; + + mul_m3_fl(smat, gps->runtime.multi_frame_falloff); + /* fix scale */ + smat[0][0] = sx; + smat[1][1] = sy; + smat[2][2] = sz; + } + + sub_v3_v3v3(vec, td->iloc, center); + mul_m3_v3(smat, vec); + + add_v3_v3v3(td->loc, vec, center); + + sub_v3_v3v3(vec, td->loc, td->iloc); + protectedTransBits(td->protectflag, vec); + add_v3_v3v3(td->loc, td->iloc, vec); + + if (td->flag & TD_USEQUAT) { + mul_m3_series(fmat, td->smtx, mat, td->mtx); + mat3_to_quat(quat, fmat); // Actual transform + + if (td->ext->quat) { + mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); + + /* is there a reason not to have this here? -jahka */ + protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + } + } + } + /** + * HACK WARNING + * + * This is some VERY ugly special case to deal with pose mode. + * + * The problem is that mtx and smtx include each bone orientation. + * + * That is needed to rotate each bone properly, HOWEVER, to calculate + * the translation component, we only need the actual armature object's + * matrix (and inverse). That is not all though. Once the proper translation + * has been computed, it has to be converted back into the bone's space. + */ + else if (t->flag & T_POSE) { + // Extract and invert armature object matrix + + if ((td->flag & TD_NO_LOC) == 0) { + sub_v3_v3v3(vec, td->center, center); + + mul_m3_v3(tc->mat3, vec); // To Global space + mul_m3_v3(mat, vec); // Applying rotation + mul_m3_v3(tc->imat3, vec); // To Local space + + add_v3_v3(vec, center); + /* vec now is the location where the object has to be */ + + sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location + + /* special exception, see TD_PBONE_LOCAL_MTX definition comments */ + if (td->flag & TD_PBONE_LOCAL_MTX_P) { + /* do nothing */ + } + else if (td->flag & TD_PBONE_LOCAL_MTX_C) { + mul_m3_v3(tc->mat3, vec); // To Global space + mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location) + } + else { + mul_m3_v3(tc->mat3, vec); // To Global space + mul_m3_v3(td->smtx, vec); // To Pose space + } + + protectedTransBits(td->protectflag, vec); + + add_v3_v3v3(td->loc, td->iloc, vec); + + constraintTransLim(t, td); + } + + /* rotation */ + /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same, + * and ElementRotation() might be called in Translation context (with align snapping), + * we need to be sure to actually use the *rotation* matrix here... + * So no other way than storing it in some dedicated members of td->ext! */ + if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */ + /* euler or quaternion/axis-angle? */ + if (td->ext->rotOrder == ROT_MODE_QUAT) { + mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx); + + mat3_to_quat(quat, fmat); /* Actual transform */ + + mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); + /* this function works on end result */ + protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + } + else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { + /* calculate effect based on quats */ + float iquat[4], tquat[4]; + + axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); + + mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx); + mat3_to_quat(quat, fmat); /* Actual transform */ + mul_qt_qtqt(tquat, quat, iquat); + + quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); + + /* this function works on end result */ + protectedAxisAngleBits(td->protectflag, + td->ext->rotAxis, + td->ext->rotAngle, + td->ext->irotAxis, + td->ext->irotAngle); + } + else { + float eulmat[3][3]; + + mul_m3_m3m3(totmat, mat, td->ext->r_mtx); + mul_m3_m3m3(smat, td->ext->r_smtx, totmat); + + /* calculate the total rotatation in eulers */ + copy_v3_v3(eul, td->ext->irot); + eulO_to_mat3(eulmat, eul, td->ext->rotOrder); + + /* mat = transform, obmat = bone rotation */ + mul_m3_m3m3(fmat, smat, eulmat); + + mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); + + /* and apply (to end result only) */ + protectedRotateBits(td->protectflag, eul, td->ext->irot); + copy_v3_v3(td->ext->rot, eul); + } + + constraintRotLim(t, td); + } + } + else { + if ((td->flag & TD_NO_LOC) == 0) { + /* translation */ + sub_v3_v3v3(vec, td->center, center); + mul_m3_v3(mat, vec); + add_v3_v3(vec, center); + /* vec now is the location where the object has to be */ + sub_v3_v3(vec, td->center); + mul_m3_v3(td->smtx, vec); + + protectedTransBits(td->protectflag, vec); + + add_v3_v3v3(td->loc, td->iloc, vec); + } + + constraintTransLim(t, td); + + /* rotation */ + if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself + /* euler or quaternion? */ + if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { + /* can be called for texture space translate for example, then opt out */ + if (td->ext->quat) { + mul_m3_series(fmat, td->smtx, mat, td->mtx); + mat3_to_quat(quat, fmat); // Actual transform + + mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); + /* this function works on end result */ + protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + } + } + else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { + /* calculate effect based on quats */ + float iquat[4], tquat[4]; + + axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); + + mul_m3_series(fmat, td->smtx, mat, td->mtx); + mat3_to_quat(quat, fmat); // Actual transform + mul_qt_qtqt(tquat, quat, iquat); + + quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); + + /* this function works on end result */ + protectedAxisAngleBits(td->protectflag, + td->ext->rotAxis, + td->ext->rotAngle, + td->ext->irotAxis, + td->ext->irotAngle); + } + else { + float obmat[3][3]; + + mul_m3_m3m3(totmat, mat, td->mtx); + mul_m3_m3m3(smat, td->smtx, totmat); + + /* calculate the total rotatation in eulers */ + add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */ + eulO_to_mat3(obmat, eul, td->ext->rotOrder); + /* mat = transform, obmat = object rotation */ + mul_m3_m3m3(fmat, smat, obmat); + + mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); + + /* correct back for delta rot */ + sub_v3_v3v3(eul, eul, td->ext->drot); + + /* and apply */ + protectedRotateBits(td->protectflag, eul, td->ext->irot); + copy_v3_v3(td->ext->rot, eul); + } + + constraintRotLim(t, td); + } + } +} + +static void ElementRotation( + TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around) { - const float *center; - - /* local constraint shouldn't alter center */ - if (transdata_check_local_center(t, around)) { - center = td->center; - } - else { - center = tc->center_local; - } - - ElementRotation_ex(t, tc, td, mat, center); + const float *center; + + /* local constraint shouldn't alter center */ + if (transdata_check_local_center(t, around)) { + center = td->center; + } + else { + center = tc->center_local; + } + + ElementRotation_ex(t, tc, td, mat, center); } static void applyRotationValue(TransInfo *t, float angle, float axis[3]) { - float mat[3][3]; - int i; + float mat[3][3]; + int i; - axis_angle_normalized_to_mat3(mat, axis, angle); + axis_angle_normalized_to_mat3(mat, axis, angle); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (t->con.applyRot) { - t->con.applyRot(t, tc, td, axis, NULL); - axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); - } - else if (t->flag & T_PROP_EDIT) { - axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); - } + if (t->con.applyRot) { + t->con.applyRot(t, tc, td, axis, NULL); + axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); + } + else if (t->flag & T_PROP_EDIT) { + axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); + } - ElementRotation(t, tc, td, mat, t->around); - } - } + ElementRotation(t, tc, td, mat, t->around); + } + } } static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; + char str[UI_MAX_DRAW_STR]; - float final; + float final; - final = t->values[0]; + final = t->values[0]; - snapGridIncrement(t, &final); + snapGridIncrement(t, &final); - float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + float axis_final[3]; + copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); - if ((t->con.mode & CON_APPLY) && t->con.applyRot) { - t->con.applyRot(t, NULL, NULL, axis_final, NULL); - } + if ((t->con.mode & CON_APPLY) && t->con.applyRot) { + t->con.applyRot(t, NULL, NULL, axis_final, NULL); + } - applySnapping(t, &final); + applySnapping(t, &final); - /* Used to clamp final result in [-PI, PI[ range, no idea why, inheritance from 2.4x area, see T48998. */ - applyNumInput(&t->num, &final); + /* Used to clamp final result in [-PI, PI[ range, no idea why, inheritance from 2.4x area, see T48998. */ + applyNumInput(&t->num, &final); - t->values[0] = final; + t->values[0] = final; - headerRotation(t, str, final); + headerRotation(t, str, final); - applyRotationValue(t, final, axis_final); + applyRotationValue(t, final, axis_final); - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Rotation - Trackball) */ @@ -4520,115 +4585,127 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) static void initTrackball(TransInfo *t) { - t->mode = TFM_TRACKBALL; - t->transform = applyTrackball; + t->mode = TFM_TRACKBALL; + t->transform = applyTrackball; - initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL); + initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL); - t->idx_max = 1; - t->num.idx_max = 1; - t->snap[0] = 0.0f; - t->snap[1] = DEG2RAD(5.0); - t->snap[2] = DEG2RAD(1.0); + t->idx_max = 1; + t->num.idx_max = 1; + t->snap[0] = 0.0f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); - copy_v3_fl(t->num.val_inc, t->snap[2]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); - t->num.unit_type[0] = B_UNIT_ROTATION; - t->num.unit_type[1] = B_UNIT_ROTATION; + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; + t->num.unit_type[1] = B_UNIT_ROTATION; - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; } -static void applyTrackballValue(TransInfo *t, const float axis1[3], const float axis2[3], float angles[2]) +static void applyTrackballValue(TransInfo *t, + const float axis1[3], + const float axis2[3], + float angles[2]) { - float mat[3][3]; - float axis[3]; - float angle; - int i; + float mat[3][3]; + float axis[3]; + float angle; + int i; - mul_v3_v3fl(axis, axis1, angles[0]); - madd_v3_v3fl(axis, axis2, angles[1]); - angle = normalize_v3(axis); - axis_angle_normalized_to_mat3(mat, axis, angle); + mul_v3_v3fl(axis, axis1, angles[0]); + madd_v3_v3fl(axis, axis2, angles[1]); + angle = normalize_v3(axis); + axis_angle_normalized_to_mat3(mat, axis, angle); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (t->flag & T_PROP_EDIT) { - axis_angle_normalized_to_mat3(mat, axis, td->factor * angle); - } + if (t->flag & T_PROP_EDIT) { + axis_angle_normalized_to_mat3(mat, axis, td->factor * angle); + } - ElementRotation(t, tc, td, mat, t->around); - } - } + ElementRotation(t, tc, td, mat, t->around); + } + } } static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; - size_t ofs = 0; - float axis1[3], axis2[3]; -#if 0 /* UNUSED */ - float mat[3][3], totmat[3][3], smat[3][3]; + char str[UI_MAX_DRAW_STR]; + size_t ofs = 0; + float axis1[3], axis2[3]; +#if 0 /* UNUSED */ + float mat[3][3], totmat[3][3], smat[3][3]; #endif - float phi[2]; + float phi[2]; - copy_v3_v3(axis1, t->persinv[0]); - copy_v3_v3(axis2, t->persinv[1]); - normalize_v3(axis1); - normalize_v3(axis2); + copy_v3_v3(axis1, t->persinv[0]); + copy_v3_v3(axis2, t->persinv[1]); + normalize_v3(axis1); + normalize_v3(axis2); - copy_v2_v2(phi, t->values); + copy_v2_v2(phi, t->values); - snapGridIncrement(t, phi); + snapGridIncrement(t, phi); - applyNumInput(&t->num, phi); + applyNumInput(&t->num, phi); - copy_v2_v2(t->values, phi); + copy_v2_v2(t->values, phi); - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN * 2]; + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN * 2]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Trackball: %s %s %s"), - &c[0], &c[NUM_STR_REP_LEN], t->proptext); - } - else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Trackball: %.2f %.2f %s"), - RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext); - } + ofs += BLI_snprintf(str + ofs, + sizeof(str) - ofs, + IFACE_("Trackball: %s %s %s"), + &c[0], + &c[NUM_STR_REP_LEN], + t->proptext); + } + else { + ofs += BLI_snprintf(str + ofs, + sizeof(str) - ofs, + IFACE_("Trackball: %.2f %.2f %s"), + RAD2DEGF(phi[0]), + RAD2DEGF(phi[1]), + t->proptext); + } - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); - } + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf( + str + ofs, sizeof(str) - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } -#if 0 /* UNUSED */ - axis_angle_normalized_to_mat3(smat, axis1, phi[0]); - axis_angle_normalized_to_mat3(totmat, axis2, phi[1]); +#if 0 /* UNUSED */ + axis_angle_normalized_to_mat3(smat, axis1, phi[0]); + axis_angle_normalized_to_mat3(totmat, axis2, phi[1]); - mul_m3_m3m3(mat, smat, totmat); + mul_m3_m3m3(mat, smat, totmat); - // TRANSFORM_FIX_ME - //copy_m3_m3(t->mat, mat); // used in gizmo + // TRANSFORM_FIX_ME + //copy_m3_m3(t->mat, mat); // used in gizmo #endif - applyTrackballValue(t, axis1, axis2, phi); + applyTrackballValue(t, axis1, axis2, phi); - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Normal Rotation) */ @@ -4637,153 +4714,154 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm) { - BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); - // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); + // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; - tc->custom.mode.data = lnors_ed_arr; - tc->custom.mode.free_cb = freeCustomNormalArray; + tc->custom.mode.data = lnors_ed_arr; + tc->custom.mode.free_cb = freeCustomNormalArray; } void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data) { - BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data; + BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data; - if (t->state == TRANS_CANCEL) { - BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; + if (t->state == TRANS_CANCEL) { + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; - /* Restore custom loop normal on cancel */ - for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { - BKE_lnor_space_custom_normal_to_data( - bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->niloc, lnor_ed->clnors_data); - } - } + /* Restore custom loop normal on cancel */ + for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->niloc, lnor_ed->clnors_data); + } + } - BM_loop_normal_editdata_array_free(lnors_ed_arr); + BM_loop_normal_editdata_array_free(lnors_ed_arr); - tc->custom.mode.data = NULL; - tc->custom.mode.free_cb = NULL; + tc->custom.mode.data = NULL; + tc->custom.mode.free_cb = NULL; } static void initNormalRotation(TransInfo *t) { - t->mode = TFM_NORMAL_ROTATION; - t->transform = applyNormalRotation; + t->mode = TFM_NORMAL_ROTATION; + t->transform = applyNormalRotation; - setInputPostFct(&t->mouse, postInputRotation); - initMouseInputMode(t, &t->mouse, INPUT_ANGLE); + setInputPostFct(&t->mouse, postInputRotation); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = DEG2RAD(5.0); - t->snap[2] = DEG2RAD(1.0); + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); - copy_v3_fl(t->num.val_inc, t->snap[2]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); - t->num.unit_type[0] = B_UNIT_ROTATION; + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; - FOREACH_TRANS_DATA_CONTAINER(t, tc) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; - BKE_editmesh_lnorspace_update(em); + BKE_editmesh_lnorspace_update(em); - storeCustomLNorValue(tc, bm); - } + storeCustomLNorValue(tc, bm); + } } /* Works by getting custom normal from clnor_data, transform, then store */ static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; + char str[UI_MAX_DRAW_STR]; - float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + float axis_final[3]; + copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); - if ((t->con.mode & CON_APPLY) && t->con.applyRot) { - t->con.applyRot(t, NULL, NULL, axis_final, NULL); - } + if ((t->con.mode & CON_APPLY) && t->con.applyRot) { + t->con.applyRot(t, NULL, NULL, axis_final, NULL); + } - FOREACH_TRANS_DATA_CONTAINER(t, tc) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; - BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data; - BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data; + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; - float axis[3]; - float mat[3][3]; - float angle = t->values[0]; - copy_v3_v3(axis, axis_final); + float axis[3]; + float mat[3][3]; + float angle = t->values[0]; + copy_v3_v3(axis, axis_final); - snapGridIncrement(t, &angle); + snapGridIncrement(t, &angle); - applySnapping(t, &angle); + applySnapping(t, &angle); - applyNumInput(&t->num, &angle); + applyNumInput(&t->num, &angle); - headerRotation(t, str, angle); + headerRotation(t, str, angle); - axis_angle_normalized_to_mat3(mat, axis, angle); + axis_angle_normalized_to_mat3(mat, axis, angle); - for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { - mul_v3_m3v3(lnor_ed->nloc, mat, lnor_ed->niloc); + for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { + mul_v3_m3v3(lnor_ed->nloc, mat, lnor_ed->niloc); - BKE_lnor_space_custom_normal_to_data( - bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data); - } - } + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data); + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Translation) */ static void initSnapSpatial(TransInfo *t, float r_snap[3]) { - if (t->spacetype == SPACE_VIEW3D) { - RegionView3D *rv3d = t->ar->regiondata; - - if (rv3d) { - View3D *v3d = t->sa->spacedata.first; - r_snap[0] = 0.0f; - r_snap[1] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f; - r_snap[2] = r_snap[1] * 0.1f; - } - } - else if (t->spacetype == SPACE_IMAGE) { - r_snap[0] = 0.0f; - r_snap[1] = 0.0625f; - r_snap[2] = 0.03125f; - } - else if (t->spacetype == SPACE_CLIP) { - r_snap[0] = 0.0f; - r_snap[1] = 0.125f; - r_snap[2] = 0.0625f; - } - else if (t->spacetype == SPACE_NODE) { - r_snap[0] = 0.0f; - r_snap[1] = ED_node_grid_size(); - r_snap[2] = ED_node_grid_size(); - } - else if (t->spacetype == SPACE_GRAPH) { - r_snap[0] = 0.0f; - r_snap[1] = 1.0; - r_snap[2] = 0.1f; - } - else { - r_snap[0] = 0.0f; - r_snap[1] = r_snap[2] = 1.0f; - } + if (t->spacetype == SPACE_VIEW3D) { + RegionView3D *rv3d = t->ar->regiondata; + + if (rv3d) { + View3D *v3d = t->sa->spacedata.first; + r_snap[0] = 0.0f; + r_snap[1] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f; + r_snap[2] = r_snap[1] * 0.1f; + } + } + else if (t->spacetype == SPACE_IMAGE) { + r_snap[0] = 0.0f; + r_snap[1] = 0.0625f; + r_snap[2] = 0.03125f; + } + else if (t->spacetype == SPACE_CLIP) { + r_snap[0] = 0.0f; + r_snap[1] = 0.125f; + r_snap[2] = 0.0625f; + } + else if (t->spacetype == SPACE_NODE) { + r_snap[0] = 0.0f; + r_snap[1] = ED_node_grid_size(); + r_snap[2] = ED_node_grid_size(); + } + else if (t->spacetype == SPACE_GRAPH) { + r_snap[0] = 0.0f; + r_snap[1] = 1.0; + r_snap[2] = 0.1f; + } + else { + r_snap[0] = 0.0f; + r_snap[1] = r_snap[2] = 1.0f; + } } /** \name Transform Translation @@ -4791,304 +4869,355 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3]) static void initTranslation(TransInfo *t) { - if (t->spacetype == SPACE_ACTION) { - /* this space uses time translate */ - BKE_report(t->reports, RPT_ERROR, - "Use 'Time_Translate' transform mode instead of 'Translation' mode " - "for translating keyframes in Dope Sheet Editor"); - t->state = TRANS_CANCEL; - } - - t->mode = TFM_TRANSLATION; - t->transform = applyTranslation; - - initMouseInputMode(t, &t->mouse, INPUT_VECTOR); - - t->idx_max = (t->flag & T_2D_EDIT) ? 1 : 2; - t->num.flag = 0; - t->num.idx_max = t->idx_max; - - copy_v3_v3(t->snap, t->snap_spatial); - - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - if (t->spacetype == SPACE_VIEW3D) { - /* Handling units makes only sense in 3Dview... See T38877. */ - t->num.unit_type[0] = B_UNIT_LENGTH; - t->num.unit_type[1] = B_UNIT_LENGTH; - t->num.unit_type[2] = B_UNIT_LENGTH; - } - else { - /* SPACE_GRAPH, SPACE_ACTION, etc. could use some time units, when we have them... */ - t->num.unit_type[0] = B_UNIT_NONE; - t->num.unit_type[1] = B_UNIT_NONE; - t->num.unit_type[2] = B_UNIT_NONE; - } + if (t->spacetype == SPACE_ACTION) { + /* this space uses time translate */ + BKE_report(t->reports, + RPT_ERROR, + "Use 'Time_Translate' transform mode instead of 'Translation' mode " + "for translating keyframes in Dope Sheet Editor"); + t->state = TRANS_CANCEL; + } + + t->mode = TFM_TRANSLATION; + t->transform = applyTranslation; + + initMouseInputMode(t, &t->mouse, INPUT_VECTOR); + + t->idx_max = (t->flag & T_2D_EDIT) ? 1 : 2; + t->num.flag = 0; + t->num.idx_max = t->idx_max; + + copy_v3_v3(t->snap, t->snap_spatial); + + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + if (t->spacetype == SPACE_VIEW3D) { + /* Handling units makes only sense in 3Dview... See T38877. */ + t->num.unit_type[0] = B_UNIT_LENGTH; + t->num.unit_type[1] = B_UNIT_LENGTH; + t->num.unit_type[2] = B_UNIT_LENGTH; + } + else { + /* SPACE_GRAPH, SPACE_ACTION, etc. could use some time units, when we have them... */ + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; + t->num.unit_type[2] = B_UNIT_NONE; + } } static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) { - size_t ofs = 0; - char tvec[NUM_STR_REP_LEN * 3]; - char distvec[NUM_STR_REP_LEN]; - char autoik[NUM_STR_REP_LEN]; - float dist; - - if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, &t->scene->unit); - dist = len_v3(t->num.val); - } - else { - float dvec[3]; - - copy_v3_v3(dvec, vec); - applyAspectRatio(t, dvec); - - dist = len_v3(vec); - if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { - int i; - - for (i = 0; i < 3; i++) { - bUnit_AsString2( - &tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length, - 4, B_UNIT_LENGTH, &t->scene->unit, true); - } - } - else { - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]); - } - } - - if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { - bUnit_AsString2( - distvec, sizeof(distvec), dist * t->scene->unit.scale_length, - 4, B_UNIT_LENGTH, &t->scene->unit, false); - } - else if (dist > 1e10f || dist < -1e10f) { - /* prevent string buffer overflow */ - BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist); - } - else { - BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist); - } - - if (t->flag & T_AUTOIK) { - short chainlen = t->settings->autoik_chainlen; - - if (chainlen) - BLI_snprintf(autoik, NUM_STR_REP_LEN, IFACE_("AutoIK-Len: %d"), chainlen); - else - autoik[0] = '\0'; - } - else - autoik[0] = '\0'; - - if (t->con.mode & CON_APPLY) { - switch (t->num.idx_max) { - case 0: - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "D: %s (%s)%s %s %s", - &tvec[0], distvec, t->con.text, t->proptext, autoik); - break; - case 1: - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "D: %s D: %s (%s)%s %s %s", - &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext, autoik); - break; - case 2: - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "D: %s D: %s D: %s (%s)%s %s %s", - &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, - t->con.text, t->proptext, autoik); - break; - } - } - else { - if (t->flag & T_2D_EDIT) { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "Dx: %s Dy: %s (%s)%s %s", - &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext); - } - else { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", - &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, - t->proptext, autoik); - } - } - - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); - } - - if (t->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first; - - if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) { - const char *str_old = BLI_strdup(str); - const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? IFACE_("right") : IFACE_("left"); - char str_km[64]; - - WM_modalkeymap_items_to_string(t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, str_km, sizeof(str_km)); - - ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("Auto-offset set to %s - press %s to toggle direction | %s"), - str_dir, str_km, str_old); - - MEM_freeN((void *)str_old); - } - } + size_t ofs = 0; + char tvec[NUM_STR_REP_LEN * 3]; + char distvec[NUM_STR_REP_LEN]; + char autoik[NUM_STR_REP_LEN]; + float dist; + + if (hasNumInput(&t->num)) { + outputNumInput(&(t->num), tvec, &t->scene->unit); + dist = len_v3(t->num.val); + } + else { + float dvec[3]; + + copy_v3_v3(dvec, vec); + applyAspectRatio(t, dvec); + + dist = len_v3(vec); + if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { + int i; + + for (i = 0; i < 3; i++) { + bUnit_AsString2(&tvec[NUM_STR_REP_LEN * i], + NUM_STR_REP_LEN, + dvec[i] * t->scene->unit.scale_length, + 4, + B_UNIT_LENGTH, + &t->scene->unit, + true); + } + } + else { + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]); + } + } + + if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { + bUnit_AsString2(distvec, + sizeof(distvec), + dist * t->scene->unit.scale_length, + 4, + B_UNIT_LENGTH, + &t->scene->unit, + false); + } + else if (dist > 1e10f || dist < -1e10f) { + /* prevent string buffer overflow */ + BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist); + } + else { + BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist); + } + + if (t->flag & T_AUTOIK) { + short chainlen = t->settings->autoik_chainlen; + + if (chainlen) + BLI_snprintf(autoik, NUM_STR_REP_LEN, IFACE_("AutoIK-Len: %d"), chainlen); + else + autoik[0] = '\0'; + } + else + autoik[0] = '\0'; + + if (t->con.mode & CON_APPLY) { + switch (t->num.idx_max) { + case 0: + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + "D: %s (%s)%s %s %s", + &tvec[0], + distvec, + t->con.text, + t->proptext, + autoik); + break; + case 1: + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + "D: %s D: %s (%s)%s %s %s", + &tvec[0], + &tvec[NUM_STR_REP_LEN], + distvec, + t->con.text, + t->proptext, + autoik); + break; + case 2: + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + "D: %s D: %s D: %s (%s)%s %s %s", + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + distvec, + t->con.text, + t->proptext, + autoik); + break; + } + } + else { + if (t->flag & T_2D_EDIT) { + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + "Dx: %s Dy: %s (%s)%s %s", + &tvec[0], + &tvec[NUM_STR_REP_LEN], + distvec, + t->con.text, + t->proptext); + } + else { + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + distvec, + t->con.text, + t->proptext, + autoik); + } + } + + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf( + str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } + + if (t->spacetype == SPACE_NODE) { + SpaceNode *snode = (SpaceNode *)t->sa->spacedata.first; + + if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) { + const char *str_old = BLI_strdup(str); + const char *str_dir = (snode->insert_ofs_dir == SNODE_INSERTOFS_DIR_RIGHT) ? + IFACE_("right") : + IFACE_("left"); + char str_km[64]; + + WM_modalkeymap_items_to_string( + t->keymap, TFM_MODAL_INSERTOFS_TOGGLE_DIR, true, str_km, sizeof(str_km)); + + ofs += BLI_snprintf(str, + UI_MAX_DRAW_STR, + IFACE_("Auto-offset set to %s - press %s to toggle direction | %s"), + str_dir, + str_km, + str_old); + + MEM_freeN((void *)str_old); + } + } } static void applyTranslationValue(TransInfo *t, const float vec[3]) { - const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT); - float tvec[3]; - - /* The ideal would be "apply_snap_align_rotation" only when a snap point is found - * so, maybe inside this function is not the best place to apply this rotation. - * but you need "handle snapping rotation before doing the translation" (really?) */ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - - float pivot[3]; - if (apply_snap_align_rotation) { - copy_v3_v3(pivot, t->tsnap.snapTarget); - /* The pivot has to be in local-space (see T49494) */ - if (tc->use_local_mat) { - mul_m4_v3(tc->imat, pivot); - } - } - - TransData *td = tc->data; - for (int i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; - - float rotate_offset[3] = {0}; - bool use_rotate_offset = false; - - /* handle snapping rotation before doing the translation */ - if (apply_snap_align_rotation) { - float mat[3][3]; - - if (validSnappingNormal(t)) { - const float *original_normal; - - /* In pose mode, we want to align normals with Y axis of bones... */ - if (t->flag & T_POSE) - original_normal = td->axismtx[1]; - else - original_normal = td->axismtx[2]; - - rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal); - } - else { - unit_m3(mat); - } - - ElementRotation_ex(t, tc, td, mat, pivot); - - if (td->loc) { - use_rotate_offset = true; - sub_v3_v3v3(rotate_offset, td->loc, td->iloc); - } - } - - if (t->con.applyVec) { - float pvec[3]; - t->con.applyVec(t, tc, td, vec, tvec, pvec); - } - else { - copy_v3_v3(tvec, vec); - } - - if (use_rotate_offset) { - add_v3_v3(tvec, rotate_offset); - } - - mul_m3_v3(td->smtx, tvec); - - if (t->options & CTX_GPENCIL_STROKES) { - /* grease pencil multiframe falloff */ - bGPDstroke *gps = (bGPDstroke *)td->extra; - if (gps != NULL) { - mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff); - } - else { - mul_v3_fl(tvec, td->factor); - } - } - else { - /* proportional editing falloff */ - mul_v3_fl(tvec, td->factor); - } - - protectedTransBits(td->protectflag, tvec); - - if (td->loc) - add_v3_v3v3(td->loc, td->iloc, tvec); - - constraintTransLim(t, td); - } - } + const bool apply_snap_align_rotation = usingSnappingNormal( + t); // && (t->tsnap.status & POINT_INIT); + float tvec[3]; + + /* The ideal would be "apply_snap_align_rotation" only when a snap point is found + * so, maybe inside this function is not the best place to apply this rotation. + * but you need "handle snapping rotation before doing the translation" (really?) */ + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + + float pivot[3]; + if (apply_snap_align_rotation) { + copy_v3_v3(pivot, t->tsnap.snapTarget); + /* The pivot has to be in local-space (see T49494) */ + if (tc->use_local_mat) { + mul_m4_v3(tc->imat, pivot); + } + } + + TransData *td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + float rotate_offset[3] = {0}; + bool use_rotate_offset = false; + + /* handle snapping rotation before doing the translation */ + if (apply_snap_align_rotation) { + float mat[3][3]; + + if (validSnappingNormal(t)) { + const float *original_normal; + + /* In pose mode, we want to align normals with Y axis of bones... */ + if (t->flag & T_POSE) + original_normal = td->axismtx[1]; + else + original_normal = td->axismtx[2]; + + rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal); + } + else { + unit_m3(mat); + } + + ElementRotation_ex(t, tc, td, mat, pivot); + + if (td->loc) { + use_rotate_offset = true; + sub_v3_v3v3(rotate_offset, td->loc, td->iloc); + } + } + + if (t->con.applyVec) { + float pvec[3]; + t->con.applyVec(t, tc, td, vec, tvec, pvec); + } + else { + copy_v3_v3(tvec, vec); + } + + if (use_rotate_offset) { + add_v3_v3(tvec, rotate_offset); + } + + mul_m3_v3(td->smtx, tvec); + + if (t->options & CTX_GPENCIL_STROKES) { + /* grease pencil multiframe falloff */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff); + } + else { + mul_v3_fl(tvec, td->factor); + } + } + else { + /* proportional editing falloff */ + mul_v3_fl(tvec, td->factor); + } + + protectedTransBits(td->protectflag, tvec); + + if (td->loc) + add_v3_v3v3(td->loc, td->iloc, tvec); + + constraintTransLim(t, td); + } + } } static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; - float value_final[3]; + char str[UI_MAX_DRAW_STR]; + float value_final[3]; - if (t->flag & T_AUTOVALUES) { - copy_v3_v3(t->values, t->auto_values); - } - else { - if ((t->con.mode & CON_APPLY) == 0) { - snapGridIncrement(t, t->values); - } + if (t->flag & T_AUTOVALUES) { + copy_v3_v3(t->values, t->auto_values); + } + else { + if ((t->con.mode & CON_APPLY) == 0) { + snapGridIncrement(t, t->values); + } - if (applyNumInput(&t->num, t->values)) { - removeAspectRatio(t, t->values); - } + if (applyNumInput(&t->num, t->values)) { + removeAspectRatio(t, t->values); + } - applySnapping(t, t->values); - } + applySnapping(t, t->values); + } - if (t->con.mode & CON_APPLY) { - float pvec[3] = {0.0f, 0.0f, 0.0f}; - t->con.applyVec(t, NULL, NULL, t->values, value_final, pvec); - headerTranslation(t, pvec, str); + if (t->con.mode & CON_APPLY) { + float pvec[3] = {0.0f, 0.0f, 0.0f}; + t->con.applyVec(t, NULL, NULL, t->values, value_final, pvec); + headerTranslation(t, pvec, str); - /* only so we have re-usable value with redo, see T46741. */ - mul_v3_m3v3(t->values, t->con.imtx, value_final); - } - else { - headerTranslation(t, t->values, str); - copy_v3_v3(value_final, t->values); - } + /* only so we have re-usable value with redo, see T46741. */ + mul_v3_m3v3(t->values, t->con.imtx, value_final); + } + else { + headerTranslation(t, t->values, str); + copy_v3_v3(value_final, t->values); + } - /* don't use 't->values' now on */ + /* don't use 't->values' now on */ - applyTranslationValue(t, value_final); + applyTranslationValue(t, value_final); - /* evil hack - redo translation if clipping needed */ - if (t->flag & T_CLIP_UV && clipUVTransform(t, value_final, 0)) { - applyTranslationValue(t, value_final); + /* evil hack - redo translation if clipping needed */ + if (t->flag & T_CLIP_UV && clipUVTransform(t, value_final, 0)) { + applyTranslationValue(t, value_final); - /* In proportional edit it can happen that */ - /* vertices in the radius of the brush end */ - /* outside the clipping area */ - /* XXX HACK - dg */ - if (t->flag & T_PROP_EDIT_ALL) { - clipUVData(t); - } - } + /* In proportional edit it can happen that */ + /* vertices in the radius of the brush end */ + /* outside the clipping area */ + /* XXX HACK - dg */ + if (t->flag & T_PROP_EDIT_ALL) { + clipUVData(t); + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Shrink-Fatten) */ @@ -5097,100 +5226,101 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) static void initShrinkFatten(TransInfo *t) { - // If not in mesh edit mode, fallback to Resize - if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) { - initResize(t); - } - else { - t->mode = TFM_SHRINKFATTEN; - t->transform = applyShrinkFatten; + // If not in mesh edit mode, fallback to Resize + if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) { + initResize(t); + } + else { + t->mode = TFM_SHRINKFATTEN; + t->transform = applyShrinkFatten; - initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); + initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 1.0f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 1.0f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_LENGTH; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_LENGTH; - t->flag |= T_NO_CONSTRAINT; - } + t->flag |= T_NO_CONSTRAINT; + } } - static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - float distance; - int i; - char str[UI_MAX_DRAW_STR]; - size_t ofs = 0; - - distance = -t->values[0]; - - snapGridIncrement(t, &distance); - - applyNumInput(&t->num, &distance); - - t->values[0] = -distance; - - /* header print for NumInput */ - ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), sizeof(str) - ofs); - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", c); - } - else { - /* default header print */ - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %.4f", distance); - } - - if (t->proptext[0]) { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", t->proptext); - } - ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); - - if (t->keymap) { - wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); - if (kmi) { - ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); - } - } - BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" or Alt) Even Thickness %s"), - WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); - /* done with header string */ - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float tdistance; /* temp dist */ - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; - - /* get the final offset */ - tdistance = distance * td->factor; - if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) { - tdistance *= td->ext->isize[0]; /* shell factor */ - } - - madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); - } - } - - recalcData(t); - - ED_area_status_text(t->sa, str); + float distance; + int i; + char str[UI_MAX_DRAW_STR]; + size_t ofs = 0; + + distance = -t->values[0]; + + snapGridIncrement(t, &distance); + + applyNumInput(&t->num, &distance); + + t->values[0] = -distance; + + /* header print for NumInput */ + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), sizeof(str) - ofs); + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + outputNumInput(&(t->num), c, &t->scene->unit); + ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", c); + } + else { + /* default header print */ + ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %.4f", distance); + } + + if (t->proptext[0]) { + ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, " %s", t->proptext); + } + ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); + + if (t->keymap) { + wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); + } + } + BLI_snprintf(str + ofs, + sizeof(str) - ofs, + IFACE_(" or Alt) Even Thickness %s"), + WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); + /* done with header string */ + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float tdistance; /* temp dist */ + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + /* get the final offset */ + tdistance = distance * td->factor; + if (td->ext && (t->flag & T_ALT_TRANSFORM) != 0) { + tdistance *= td->ext->isize[0]; /* shell factor */ + } + + madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); + } + } + + recalcData(t); + + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Tilt) */ @@ -5199,77 +5329,76 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) static void initTilt(TransInfo *t) { - t->mode = TFM_TILT; - t->transform = applyTilt; + t->mode = TFM_TILT; + t->transform = applyTilt; - initMouseInputMode(t, &t->mouse, INPUT_ANGLE); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = DEG2RAD(5.0); - t->snap[2] = DEG2RAD(1.0); + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); - copy_v3_fl(t->num.val_inc, t->snap[2]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); - t->num.unit_type[0] = B_UNIT_ROTATION; + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; - t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } - static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) { - int i; - char str[UI_MAX_DRAW_STR]; + int i; + char str[UI_MAX_DRAW_STR]; - float final; + float final; - final = t->values[0]; + final = t->values[0]; - snapGridIncrement(t, &final); + snapGridIncrement(t, &final); - applyNumInput(&t->num, &final); + applyNumInput(&t->num, &final); - t->values[0] = final; + t->values[0] = final; - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %s° %s"), &c[0], t->proptext); + BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %s° %s"), &c[0], t->proptext); - /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */ - t->values[0] = final; - } - else { - BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext); - } + /* XXX For some reason, this seems needed for this op, else RNA prop is not updated... :/ */ + t->values[0] = final; + } + else { + BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival + final * td->factor; - } - } - } + if (td->val) { + *td->val = td->ival + final * td->factor; + } + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Curve Shrink/Fatten) */ @@ -5278,79 +5407,80 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) static void initCurveShrinkFatten(TransInfo *t) { - t->mode = TFM_CURVE_SHRINKFATTEN; - t->transform = applyCurveShrinkFatten; + t->mode = TFM_CURVE_SHRINKFATTEN; + t->transform = applyCurveShrinkFatten; - initMouseInputMode(t, &t->mouse, INPUT_SPRING); + initMouseInputMode(t, &t->mouse, INPUT_SPRING); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_ZERO; + t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO - t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; #endif - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; } static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - float ratio; - int i; - char str[UI_MAX_DRAW_STR]; + float ratio; + int i; + char str[UI_MAX_DRAW_STR]; - ratio = t->values[0]; + ratio = t->values[0]; - snapGridIncrement(t, &ratio); + snapGridIncrement(t, &ratio); - applyNumInput(&t->num, &ratio); + applyNumInput(&t->num, &ratio); - t->values[0] = ratio; + t->values[0] = ratio; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c); - } - else { - BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio); - } + outputNumInput(&(t->num), c, &t->scene->unit); + BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c); + } + else { + BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival * ratio; - /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) *td->val = 0.001f; - } - } - } + if (td->val) { + *td->val = td->ival * ratio; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + if (*td->val <= 0.0f) + *td->val = 0.001f; + } + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Mask Shrink/Fatten) */ @@ -5359,104 +5489,106 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) static void initMaskShrinkFatten(TransInfo *t) { - t->mode = TFM_MASK_SHRINKFATTEN; - t->transform = applyMaskShrinkFatten; + t->mode = TFM_MASK_SHRINKFATTEN; + t->transform = applyMaskShrinkFatten; - initMouseInputMode(t, &t->mouse, INPUT_SPRING); + initMouseInputMode(t, &t->mouse, INPUT_SPRING); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_ZERO; + t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO - t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; #endif - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; } static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - float ratio; - int i; - bool initial_feather = false; - char str[UI_MAX_DRAW_STR]; + float ratio; + int i; + bool initial_feather = false; + char str[UI_MAX_DRAW_STR]; - ratio = t->values[0]; + ratio = t->values[0]; - snapGridIncrement(t, &ratio); + snapGridIncrement(t, &ratio); - applyNumInput(&t->num, &ratio); + applyNumInput(&t->num, &ratio); - t->values[0] = ratio; + t->values[0] = ratio; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %s"), c); - } - else { - BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %3f"), ratio); - } + outputNumInput(&(t->num), c, &t->scene->unit); + BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %s"), c); + } + else { + BLI_snprintf(str, sizeof(str), IFACE_("Feather Shrink/Fatten: %3f"), ratio); + } - /* detect if no points have feather yet */ - if (ratio > 1.0f) { - initial_feather = true; + /* detect if no points have feather yet */ + if (ratio > 1.0f) { + initial_feather = true; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->ival >= 0.001f) - initial_feather = false; - } - } - } + if (td->ival >= 0.001f) + initial_feather = false; + } + } + } - /* apply shrink/fatten */ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (td = tc->data, i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + /* apply shrink/fatten */ + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (td = tc->data, i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - if (initial_feather) - *td->val = td->ival + (ratio - 1.0f) * 0.01f; - else - *td->val = td->ival * ratio; + if (td->val) { + if (initial_feather) + *td->val = td->ival + (ratio - 1.0f) * 0.01f; + else + *td->val = td->ival * ratio; - /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) *td->val = 0.001f; - } - } - } + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + if (*td->val <= 0.0f) + *td->val = 0.001f; + } + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (GPencil Shrink/Fatten) */ @@ -5465,73 +5597,75 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) static void initGPShrinkFatten(TransInfo *t) { - t->mode = TFM_GPENCIL_SHRINKFATTEN; - t->transform = applyGPShrinkFatten; + t->mode = TFM_GPENCIL_SHRINKFATTEN; + t->transform = applyGPShrinkFatten; - initMouseInputMode(t, &t->mouse, INPUT_SPRING); + initMouseInputMode(t, &t->mouse, INPUT_SPRING); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_ZERO; + t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO - t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; #endif - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; } static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - float ratio; - int i; - char str[UI_MAX_DRAW_STR]; + float ratio; + int i; + char str[UI_MAX_DRAW_STR]; - ratio = t->values[0]; + ratio = t->values[0]; - snapGridIncrement(t, &ratio); + snapGridIncrement(t, &ratio); - applyNumInput(&t->num, &ratio); + applyNumInput(&t->num, &ratio); - t->values[0] = ratio; + t->values[0] = ratio; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c); - } - else { - BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio); - } + outputNumInput(&(t->num), c, &t->scene->unit); + BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %s"), c); + } + else { + BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival * ratio; - /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) *td->val = 0.001f; - } - } - } + if (td->val) { + *td->val = td->ival * ratio; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + if (*td->val <= 0.0f) + *td->val = 0.001f; + } + } + } - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -5543,77 +5677,77 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) static void initGPOpacity(TransInfo *t) { - t->mode = TFM_GPENCIL_OPACITY; - t->transform = applyGPOpacity; + t->mode = TFM_GPENCIL_OPACITY; + t->transform = applyGPOpacity; - initMouseInputMode(t, &t->mouse, INPUT_SPRING); + initMouseInputMode(t, &t->mouse, INPUT_SPRING); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_ZERO; + t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO - t->num.val_flag[0] |= NUM_NO_ZERO; + t->num.val_flag[0] |= NUM_NO_ZERO; #endif - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; } static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2])) { - float ratio; - int i; - char str[UI_MAX_DRAW_STR]; + float ratio; + int i; + char str[UI_MAX_DRAW_STR]; - ratio = t->values[0]; + ratio = t->values[0]; - snapGridIncrement(t, &ratio); + snapGridIncrement(t, &ratio); - applyNumInput(&t->num, &ratio); + applyNumInput(&t->num, &ratio); - t->values[0] = ratio; + t->values[0] = ratio; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %s"), c); - } - else { - BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %3f"), ratio); - } + outputNumInput(&(t->num), c, &t->scene->unit); + BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %s"), c); + } + else { + BLI_snprintf(str, sizeof(str), IFACE_("Opacity: %3f"), ratio); + } - FOREACH_TRANS_DATA_CONTAINER(t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival * ratio; - /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - CLAMP(*td->val, 0.0f, 1.0f); - } - } - } + if (td->val) { + *td->val = td->ival * ratio; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + CLAMP(*td->val, 0.0f, 1.0f); + } + } + } - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Push/Pull) */ @@ -5622,93 +5756,93 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2])) static void initPushPull(TransInfo *t) { - t->mode = TFM_PUSHPULL; - t->transform = applyPushPull; + t->mode = TFM_PUSHPULL; + t->transform = applyPushPull; - initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); + initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 1.0f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 1.0f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_LENGTH; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_LENGTH; } - static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3], axis_global[3]; - float distance; - int i; - char str[UI_MAX_DRAW_STR]; + float vec[3], axis_global[3]; + float distance; + int i; + char str[UI_MAX_DRAW_STR]; - distance = t->values[0]; + distance = t->values[0]; - snapGridIncrement(t, &distance); + snapGridIncrement(t, &distance); - applyNumInput(&t->num, &distance); + applyNumInput(&t->num, &distance); - t->values[0] = distance; + t->values[0] = distance; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext); - } - else { - /* default header print */ - BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext); - } + BLI_snprintf(str, sizeof(str), IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext); + } + else { + /* default header print */ + BLI_snprintf( + str, sizeof(str), IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext); + } - if (t->con.applyRot && t->con.mode & CON_APPLY) { - t->con.applyRot(t, NULL, NULL, axis_global, NULL); - } + if (t->con.applyRot && t->con.mode & CON_APPLY) { + t->con.applyRot(t, NULL, NULL, axis_global, NULL); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - sub_v3_v3v3(vec, tc->center_local, td->center); - if (t->con.applyRot && t->con.mode & CON_APPLY) { - float axis[3]; - copy_v3_v3(axis, axis_global); - t->con.applyRot(t, tc, td, axis, NULL); + sub_v3_v3v3(vec, tc->center_local, td->center); + if (t->con.applyRot && t->con.mode & CON_APPLY) { + float axis[3]; + copy_v3_v3(axis, axis_global); + t->con.applyRot(t, tc, td, axis, NULL); - mul_m3_v3(td->smtx, axis); - if (isLockConstraint(t)) { - float dvec[3]; - project_v3_v3v3(dvec, vec, axis); - sub_v3_v3(vec, dvec); - } - else { - project_v3_v3v3(vec, vec, axis); - } - } - normalize_v3_length(vec, distance * td->factor); + mul_m3_v3(td->smtx, axis); + if (isLockConstraint(t)) { + float dvec[3]; + project_v3_v3v3(dvec, vec, axis); + sub_v3_v3(vec, dvec); + } + else { + project_v3_v3v3(vec, vec, axis); + } + } + normalize_v3_length(vec, distance * td->factor); - add_v3_v3v3(td->loc, td->iloc, vec); - } - } + add_v3_v3v3(td->loc, td->iloc, vec); + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Bevel Weight) */ @@ -5717,80 +5851,82 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) static void initBevelWeight(TransInfo *t) { - t->mode = TFM_BWEIGHT; - t->transform = applyBevelWeight; + t->mode = TFM_BWEIGHT; + t->transform = applyBevelWeight; - initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA); + initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) { - float weight; - int i; - char str[UI_MAX_DRAW_STR]; + float weight; + int i; + char str[UI_MAX_DRAW_STR]; - weight = t->values[0]; + weight = t->values[0]; - CLAMP_MAX(weight, 1.0f); + CLAMP_MAX(weight, 1.0f); - snapGridIncrement(t, &weight); + snapGridIncrement(t, &weight); - applyNumInput(&t->num, &weight); + applyNumInput(&t->num, &weight); - t->values[0] = weight; + t->values[0] = weight; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - if (weight >= 0.0f) - BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%s %s"), c, t->proptext); - else - BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %s %s"), c, t->proptext); - } - else { - /* default header print */ - if (weight >= 0.0f) - BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext); - else - BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext); - } + if (weight >= 0.0f) + BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%s %s"), c, t->proptext); + else + BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %s %s"), c, t->proptext); + } + else { + /* default header print */ + if (weight >= 0.0f) + BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext); + else + BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->val) { - *td->val = td->ival + weight * td->factor; - if (*td->val < 0.0f) *td->val = 0.0f; - if (*td->val > 1.0f) *td->val = 1.0f; - } - } - } + if (td->val) { + *td->val = td->ival + weight * td->factor; + if (*td->val < 0.0f) + *td->val = 0.0f; + if (*td->val > 1.0f) + *td->val = 1.0f; + } + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Crease) */ @@ -5799,83 +5935,85 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) static void initCrease(TransInfo *t) { - t->mode = TFM_CREASE; - t->transform = applyCrease; + t->mode = TFM_CREASE; + t->transform = applyCrease; - initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA); + initMouseInputMode(t, &t->mouse, INPUT_SPRING_DELTA); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) { - float crease; - int i; - char str[UI_MAX_DRAW_STR]; + float crease; + int i; + char str[UI_MAX_DRAW_STR]; - crease = t->values[0]; + crease = t->values[0]; - CLAMP_MAX(crease, 1.0f); + CLAMP_MAX(crease, 1.0f); - snapGridIncrement(t, &crease); + snapGridIncrement(t, &crease); - applyNumInput(&t->num, &crease); + applyNumInput(&t->num, &crease); - t->values[0] = crease; + t->values[0] = crease; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - if (crease >= 0.0f) - BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%s %s"), c, t->proptext); - else - BLI_snprintf(str, sizeof(str), IFACE_("Crease: %s %s"), c, t->proptext); - } - else { - /* default header print */ - if (crease >= 0.0f) - BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%.3f %s"), crease, t->proptext); - else - BLI_snprintf(str, sizeof(str), IFACE_("Crease: %.3f %s"), crease, t->proptext); - } + if (crease >= 0.0f) + BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%s %s"), c, t->proptext); + else + BLI_snprintf(str, sizeof(str), IFACE_("Crease: %s %s"), c, t->proptext); + } + else { + /* default header print */ + if (crease >= 0.0f) + BLI_snprintf(str, sizeof(str), IFACE_("Crease: +%.3f %s"), crease, t->proptext); + else + BLI_snprintf(str, sizeof(str), IFACE_("Crease: %.3f %s"), crease, t->proptext); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival + crease * td->factor; - if (*td->val < 0.0f) *td->val = 0.0f; - if (*td->val > 1.0f) *td->val = 1.0f; - } - } - } + if (td->val) { + *td->val = td->ival + crease * td->factor; + if (*td->val < 0.0f) + *td->val = 0.0f; + if (*td->val > 1.0f) + *td->val = 1.0f; + } + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (EditBone (B-bone) width scaling) */ @@ -5884,121 +6022,134 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) static void initBoneSize(TransInfo *t) { - t->mode = TFM_BONESIZE; - t->transform = applyBoneSize; + t->mode = TFM_BONESIZE; + t->transform = applyBoneSize; - initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); + initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); - t->idx_max = 2; - t->num.idx_max = 2; - t->num.val_flag[0] |= NUM_NULL_ONE; - t->num.val_flag[1] |= NUM_NULL_ONE; - t->num.val_flag[2] |= NUM_NULL_ONE; - t->num.flag |= NUM_AFFECT_ALL; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 2; + t->num.idx_max = 2; + t->num.val_flag[0] |= NUM_NULL_ONE; + t->num.val_flag[1] |= NUM_NULL_ONE; + t->num.val_flag[2] |= NUM_NULL_ONE; + t->num.flag |= NUM_AFFECT_ALL; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; - t->num.unit_type[1] = B_UNIT_NONE; - t->num.unit_type[2] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; + t->num.unit_type[2] = B_UNIT_NONE; } static void headerBoneSize(TransInfo *t, const float vec[3], char str[UI_MAX_DRAW_STR]) { - char tvec[NUM_STR_REP_LEN * 3]; - if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, &t->scene->unit); - } - else { - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); - BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); - } - - /* hmm... perhaps the y-axis values don't need to be shown? */ - if (t->con.mode & CON_APPLY) { - if (t->num.idx_max == 0) - BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext); - else - BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleB: %s : %s : %s%s %s"), - &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); - } - else { - BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"), - &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); - } + char tvec[NUM_STR_REP_LEN * 3]; + if (hasNumInput(&t->num)) { + outputNumInput(&(t->num), tvec, &t->scene->unit); + } + else { + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); + } + + /* hmm... perhaps the y-axis values don't need to be shown? */ + if (t->con.mode & CON_APPLY) { + if (t->num.idx_max == 0) + BLI_snprintf( + str, UI_MAX_DRAW_STR, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext); + else + BLI_snprintf(str, + UI_MAX_DRAW_STR, + IFACE_("ScaleB: %s : %s : %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + t->con.text, + t->proptext); + } + else { + BLI_snprintf(str, + UI_MAX_DRAW_STR, + IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"), + &tvec[0], + &tvec[NUM_STR_REP_LEN], + &tvec[NUM_STR_REP_LEN * 2], + t->con.text, + t->proptext); + } } static void ElementBoneSize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]) { - float tmat[3][3], smat[3][3], oldy; - float sizemat[3][3]; + float tmat[3][3], smat[3][3], oldy; + float sizemat[3][3]; - mul_m3_m3m3(smat, mat, td->mtx); - mul_m3_m3m3(tmat, td->smtx, smat); + mul_m3_m3m3(smat, mat, td->mtx); + mul_m3_m3m3(tmat, td->smtx, smat); - if (t->con.applySize) { - t->con.applySize(t, tc, td, tmat); - } + if (t->con.applySize) { + t->con.applySize(t, tc, td, tmat); + } - /* we've tucked the scale in loc */ - oldy = td->iloc[1]; - size_to_mat3(sizemat, td->iloc); - mul_m3_m3m3(tmat, tmat, sizemat); - mat3_to_size(td->loc, tmat); - td->loc[1] = oldy; + /* we've tucked the scale in loc */ + oldy = td->iloc[1]; + size_to_mat3(sizemat, td->iloc); + mul_m3_m3m3(tmat, tmat, sizemat); + mat3_to_size(td->loc, tmat); + td->loc[1] = oldy; } static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) { - float size[3], mat[3][3]; - float ratio = t->values[0]; - int i; - char str[UI_MAX_DRAW_STR]; + float size[3], mat[3][3]; + float ratio = t->values[0]; + int i; + char str[UI_MAX_DRAW_STR]; - copy_v3_fl(size, ratio); + copy_v3_fl(size, ratio); - snapGridIncrement(t, size); + snapGridIncrement(t, size); - if (applyNumInput(&t->num, size)) { - constraintNumInput(t, size); - } + if (applyNumInput(&t->num, size)) { + constraintNumInput(t, size); + } - copy_v3_v3(t->values, size); + copy_v3_v3(t->values, size); - size_to_mat3(mat, size); + size_to_mat3(mat, size); - if (t->con.applySize) { - t->con.applySize(t, NULL, NULL, mat); - } + if (t->con.applySize) { + t->con.applySize(t, NULL, NULL, mat); + } - copy_m3_m3(t->mat, mat); // used in gizmo + copy_m3_m3(t->mat, mat); // used in gizmo - headerBoneSize(t, size, str); + headerBoneSize(t, size, str); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - ElementBoneSize(t, tc, td, mat); - } - } + ElementBoneSize(t, tc, td, mat); + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Bone Envelope) */ @@ -6007,71 +6158,72 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) static void initBoneEnvelope(TransInfo *t) { - t->mode = TFM_BONE_ENVELOPE; - t->transform = applyBoneEnvelope; + t->mode = TFM_BONE_ENVELOPE; + t->transform = applyBoneEnvelope; - initMouseInputMode(t, &t->mouse, INPUT_SPRING); + initMouseInputMode(t, &t->mouse, INPUT_SPRING); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) { - float ratio; - int i; - char str[UI_MAX_DRAW_STR]; + float ratio; + int i; + char str[UI_MAX_DRAW_STR]; - ratio = t->values[0]; + ratio = t->values[0]; - snapGridIncrement(t, &ratio); + snapGridIncrement(t, &ratio); - applyNumInput(&t->num, &ratio); + applyNumInput(&t->num, &ratio); - t->values[0] = ratio; + t->values[0] = ratio; - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %s"), c); - } - else { - BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %3f"), ratio); - } + outputNumInput(&(t->num), c, &t->scene->unit); + BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %s"), c); + } + else { + BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %3f"), ratio); + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - /* if the old/original value was 0.0f, then just use ratio */ - if (td->ival) - *td->val = td->ival * ratio; - else - *td->val = ratio; - } - } - } + if (td->val) { + /* if the old/original value was 0.0f, then just use ratio */ + if (td->ival) + *td->val = td->ival * ratio; + else + *td->val = ratio; + } + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -6081,159 +6233,157 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) /** \name Orig-Data Store Utility Functions * \{ */ -static void slide_origdata_init_flag( - TransInfo *t, TransDataContainer *tc, SlideOrigData *sod) -{ - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; - const bool has_layer_math = CustomData_has_math(&bm->ldata); - const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); - - if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) && - /* don't do this at all for non-basis shape keys, too easy to - * accidentally break uv maps or vertex colors then */ - (bm->shapenr <= 1) && - (has_layer_math || (cd_loop_mdisp_offset != -1))) - { - sod->use_origfaces = true; - sod->cd_loop_mdisp_offset = cd_loop_mdisp_offset; - } - else { - sod->use_origfaces = false; - sod->cd_loop_mdisp_offset = -1; - } -} - -static void slide_origdata_init_data( - TransDataContainer *tc, SlideOrigData *sod) -{ - if (sod->use_origfaces) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; - - sod->origfaces = BLI_ghash_ptr_new(__func__); - sod->bm_origfaces = BM_mesh_create( - &bm_mesh_allocsize_default, - &((struct BMeshCreateParams){.use_toolflags = false,})); - /* we need to have matching customdata */ - BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL); - } -} - -static void slide_origdata_create_data_vert( - BMesh *bm, SlideOrigData *sod, - TransDataGenericSlideVert *sv) -{ - BMIter liter; - int j, l_num; - float *loop_weights; - - /* copy face data */ - // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) { - BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v); - l_num = liter.count; - loop_weights = BLI_array_alloca(loop_weights, l_num); - for (j = 0; j < l_num; j++) { - BMLoop *l = BM_iter_step(&liter); - BMLoop *l_prev, *l_next; - void **val_p; - if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) { - BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true); - *val_p = f_copy; - } - - if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) && - (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) - { - loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co); - } - else { - loop_weights[j] = 0.0f; - } - - } - - /* store cd_loop_groups */ - if (sod->layer_math_map_num && (l_num != 0)) { - sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *)); - for (j = 0; j < sod->layer_math_map_num; j++) { - const int layer_nr = sod->layer_math_map[j]; - sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create(bm, sv->v, layer_nr, loop_weights, sod->arena); - } - } - else { - sv->cd_loop_groups = NULL; - } - - BLI_ghash_insert(sod->origverts, sv->v, sv); -} - -static void slide_origdata_create_data( - TransDataContainer *tc, SlideOrigData *sod, - TransDataGenericSlideVert *sv_array, unsigned int v_stride, unsigned int v_num) -{ - if (sod->use_origfaces) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; - unsigned int i; - TransDataGenericSlideVert *sv; - - int layer_index_dst; - int j; - - layer_index_dst = 0; - - if (CustomData_has_math(&bm->ldata)) { - /* over alloc, only 'math' layers are indexed */ - sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__); - for (j = 0; j < bm->ldata.totlayer; j++) { - if (CustomData_layer_has_math(&bm->ldata, j)) { - sod->layer_math_map[layer_index_dst++] = j; - } - } - BLI_assert(layer_index_dst != 0); - } - - sod->layer_math_map_num = layer_index_dst; - - sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - - sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num); - - for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) { - slide_origdata_create_data_vert(bm, sod, sv); - } - - if (tc->mirror.axis_flag) { - TransData *td = tc->data; - TransDataGenericSlideVert *sv_mirror; - - sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__); - sod->totsv_mirror = tc->data_len; - - sv_mirror = sod->sv_mirror; - - for (i = 0; i < tc->data_len; i++, td++) { - BMVert *eve = td->extra; - /* Check the vertex has been used since both sides of the mirror may be selected & sliding. */ - if (eve && !BLI_ghash_haskey(sod->origverts, eve)) { - sv_mirror->v = eve; - copy_v3_v3(sv_mirror->co_orig_3d, eve->co); - - slide_origdata_create_data_vert(bm, sod, sv_mirror); - sv_mirror++; - } - else { - sod->totsv_mirror--; - } - } - - if (sod->totsv_mirror == 0) { - MEM_freeN(sod->sv_mirror); - sod->sv_mirror = NULL; - } - } - } +static void slide_origdata_init_flag(TransInfo *t, TransDataContainer *tc, SlideOrigData *sod) +{ + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + const bool has_layer_math = CustomData_has_math(&bm->ldata); + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + + if ((t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) && + /* don't do this at all for non-basis shape keys, too easy to + * accidentally break uv maps or vertex colors then */ + (bm->shapenr <= 1) && (has_layer_math || (cd_loop_mdisp_offset != -1))) { + sod->use_origfaces = true; + sod->cd_loop_mdisp_offset = cd_loop_mdisp_offset; + } + else { + sod->use_origfaces = false; + sod->cd_loop_mdisp_offset = -1; + } +} + +static void slide_origdata_init_data(TransDataContainer *tc, SlideOrigData *sod) +{ + if (sod->use_origfaces) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + + sod->origfaces = BLI_ghash_ptr_new(__func__); + sod->bm_origfaces = BM_mesh_create(&bm_mesh_allocsize_default, + &((struct BMeshCreateParams){ + .use_toolflags = false, + })); + /* we need to have matching customdata */ + BM_mesh_copy_init_customdata(sod->bm_origfaces, bm, NULL); + } +} + +static void slide_origdata_create_data_vert(BMesh *bm, + SlideOrigData *sod, + TransDataGenericSlideVert *sv) +{ + BMIter liter; + int j, l_num; + float *loop_weights; + + /* copy face data */ + // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) { + BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v); + l_num = liter.count; + loop_weights = BLI_array_alloca(loop_weights, l_num); + for (j = 0; j < l_num; j++) { + BMLoop *l = BM_iter_step(&liter); + BMLoop *l_prev, *l_next; + void **val_p; + if (!BLI_ghash_ensure_p(sod->origfaces, l->f, &val_p)) { + BMFace *f_copy = BM_face_copy(sod->bm_origfaces, bm, l->f, true, true); + *val_p = f_copy; + } + + if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) && + (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) { + loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co); + } + else { + loop_weights[j] = 0.0f; + } + } + + /* store cd_loop_groups */ + if (sod->layer_math_map_num && (l_num != 0)) { + sv->cd_loop_groups = BLI_memarena_alloc(sod->arena, sod->layer_math_map_num * sizeof(void *)); + for (j = 0; j < sod->layer_math_map_num; j++) { + const int layer_nr = sod->layer_math_map[j]; + sv->cd_loop_groups[j] = BM_vert_loop_groups_data_layer_create( + bm, sv->v, layer_nr, loop_weights, sod->arena); + } + } + else { + sv->cd_loop_groups = NULL; + } + + BLI_ghash_insert(sod->origverts, sv->v, sv); +} + +static void slide_origdata_create_data(TransDataContainer *tc, + SlideOrigData *sod, + TransDataGenericSlideVert *sv_array, + unsigned int v_stride, + unsigned int v_num) +{ + if (sod->use_origfaces) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + unsigned int i; + TransDataGenericSlideVert *sv; + + int layer_index_dst; + int j; + + layer_index_dst = 0; + + if (CustomData_has_math(&bm->ldata)) { + /* over alloc, only 'math' layers are indexed */ + sod->layer_math_map = MEM_mallocN(bm->ldata.totlayer * sizeof(int), __func__); + for (j = 0; j < bm->ldata.totlayer; j++) { + if (CustomData_layer_has_math(&bm->ldata, j)) { + sod->layer_math_map[layer_index_dst++] = j; + } + } + BLI_assert(layer_index_dst != 0); + } + + sod->layer_math_map_num = layer_index_dst; + + sod->arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + + sod->origverts = BLI_ghash_ptr_new_ex(__func__, v_num); + + for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) { + slide_origdata_create_data_vert(bm, sod, sv); + } + + if (tc->mirror.axis_flag) { + TransData *td = tc->data; + TransDataGenericSlideVert *sv_mirror; + + sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__); + sod->totsv_mirror = tc->data_len; + + sv_mirror = sod->sv_mirror; + + for (i = 0; i < tc->data_len; i++, td++) { + BMVert *eve = td->extra; + /* Check the vertex has been used since both sides of the mirror may be selected & sliding. */ + if (eve && !BLI_ghash_haskey(sod->origverts, eve)) { + sv_mirror->v = eve; + copy_v3_v3(sv_mirror->co_orig_3d, eve->co); + + slide_origdata_create_data_vert(bm, sod, sv_mirror); + sv_mirror++; + } + else { + sod->totsv_mirror--; + } + } + + if (sod->totsv_mirror == 0) { + MEM_freeN(sod->sv_mirror); + sod->sv_mirror = NULL; + } + } + } } /** @@ -6241,192 +6391,199 @@ static void slide_origdata_create_data( */ static const float *slide_origdata_orig_vert_co(SlideOrigData *sod, BMVert *v) { - TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v); - return sv ? sv->co_orig_3d : v->co; -} - -static void slide_origdata_interp_data_vert( - SlideOrigData *sod, BMesh *bm, bool is_final, - TransDataGenericSlideVert *sv) -{ - BMIter liter; - int j, l_num; - float *loop_weights; - const bool is_moved = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON); - const bool do_loop_weight = sod->layer_math_map_num && is_moved; - const bool do_loop_mdisps = is_final && is_moved && (sod->cd_loop_mdisp_offset != -1); - const float *v_proj_axis = sv->v->no; - /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */ - float v_proj[3][3]; - - if (do_loop_weight || do_loop_mdisps) { - project_plane_normalized_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis); - } - - // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) - BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v); - l_num = liter.count; - loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL; - for (j = 0; j < l_num; j++) { - BMFace *f_copy; /* the copy of 'f' */ - BMLoop *l = BM_iter_step(&liter); - - f_copy = BLI_ghash_lookup(sod->origfaces, l->f); - - /* only loop data, no vertex data since that contains shape keys, - * and we do not want to mess up other shape keys */ - BM_loop_interp_from_face(bm, l, f_copy, false, false); - - /* make sure face-attributes are correct (e.g. MTexPoly) */ - BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL); - - /* weight the loop */ - if (do_loop_weight) { - const float eps = 1.0e-8f; - const BMLoop *l_prev = l->prev; - const BMLoop *l_next = l->next; - const float *co_prev = slide_origdata_orig_vert_co(sod, l_prev->v); - const float *co_next = slide_origdata_orig_vert_co(sod, l_next->v); - bool co_prev_ok; - bool co_next_ok; - - - /* In the unlikely case that we're next to a zero length edge - - * walk around the to the next. - * - * Since we only need to check if the vertex is in this corner, - * its not important _which_ loop - as long as its not overlapping - * 'sv->co_orig_3d', see: T45096. */ - project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis); - while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) && - ((l_prev = l_prev->prev) != l->next))) - { - co_prev = slide_origdata_orig_vert_co(sod, l_prev->v); - project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis); - } - project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis); - while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) && - ((l_next = l_next->next) != l->prev))) - { - co_next = slide_origdata_orig_vert_co(sod, l_next->v); - project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis); - } - - if (co_prev_ok && co_next_ok) { - const float dist = dist_signed_squared_to_corner_v3v3v3(sv->v->co, UNPACK3(v_proj), v_proj_axis); - - loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps))); - if (UNLIKELY(!isfinite(loop_weights[j]))) { - loop_weights[j] = 0.0f; - } - } - else { - loop_weights[j] = 0.0f; - } - } - } - - if (sod->layer_math_map_num) { - if (do_loop_weight) { - for (j = 0; j < sod->layer_math_map_num; j++) { - BM_vert_loop_groups_data_layer_merge_weights(bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights); - } - } - else { - for (j = 0; j < sod->layer_math_map_num; j++) { - BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]); - } - } - } - - /* Special handling for multires - * - * Interpolate from every other loop (not ideal) - * However values will only be taken from loops which overlap other mdisps. - * */ - if (do_loop_mdisps) { - float (*faces_center)[3] = BLI_array_alloca(faces_center, l_num); - BMLoop *l; - - BM_ITER_ELEM_INDEX (l, &liter, sv->v, BM_LOOPS_OF_VERT, j) { - BM_face_calc_center_median(l->f, faces_center[j]); - } - - BM_ITER_ELEM_INDEX (l, &liter, sv->v, BM_LOOPS_OF_VERT, j) { - BMFace *f_copy = BLI_ghash_lookup(sod->origfaces, l->f); - float f_copy_center[3]; - BMIter liter_other; - BMLoop *l_other; - int j_other; - - BM_face_calc_center_median(f_copy, f_copy_center); - - BM_ITER_ELEM_INDEX (l_other, &liter_other, sv->v, BM_LOOPS_OF_VERT, j_other) { - BM_face_interp_multires_ex( - bm, l_other->f, f_copy, - faces_center[j_other], f_copy_center, sod->cd_loop_mdisp_offset); - } - } - } -} - -static void slide_origdata_interp_data( - Object *obedit, SlideOrigData *sod, - TransDataGenericSlideVert *sv, unsigned int v_stride, unsigned int v_num, - bool is_final) -{ - if (sod->use_origfaces) { - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMesh *bm = em->bm; - unsigned int i; - const bool has_mdisps = (sod->cd_loop_mdisp_offset != -1); - - for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) { - - if (sv->cd_loop_groups || has_mdisps) { - slide_origdata_interp_data_vert(sod, bm, is_final, sv); - } - } - - if (sod->sv_mirror) { - sv = sod->sv_mirror; - for (i = 0; i < v_num; i++, sv++) { - if (sv->cd_loop_groups || has_mdisps) { - slide_origdata_interp_data_vert(sod, bm, is_final, sv); - } - } - } - } -} - -static void slide_origdata_free_date( - SlideOrigData *sod) -{ - if (sod->use_origfaces) { - if (sod->bm_origfaces) { - BM_mesh_free(sod->bm_origfaces); - sod->bm_origfaces = NULL; - } - - if (sod->origfaces) { - BLI_ghash_free(sod->origfaces, NULL, NULL); - sod->origfaces = NULL; - } - - if (sod->origverts) { - BLI_ghash_free(sod->origverts, NULL, NULL); - sod->origverts = NULL; - } - - if (sod->arena) { - BLI_memarena_free(sod->arena); - sod->arena = NULL; - } - - MEM_SAFE_FREE(sod->layer_math_map); - - MEM_SAFE_FREE(sod->sv_mirror); - } + TransDataGenericSlideVert *sv = BLI_ghash_lookup(sod->origverts, v); + return sv ? sv->co_orig_3d : v->co; +} + +static void slide_origdata_interp_data_vert(SlideOrigData *sod, + BMesh *bm, + bool is_final, + TransDataGenericSlideVert *sv) +{ + BMIter liter; + int j, l_num; + float *loop_weights; + const bool is_moved = (len_squared_v3v3(sv->v->co, sv->co_orig_3d) > FLT_EPSILON); + const bool do_loop_weight = sod->layer_math_map_num && is_moved; + const bool do_loop_mdisps = is_final && is_moved && (sod->cd_loop_mdisp_offset != -1); + const float *v_proj_axis = sv->v->no; + /* original (l->prev, l, l->next) projections for each loop ('l' remains unchanged) */ + float v_proj[3][3]; + + if (do_loop_weight || do_loop_mdisps) { + project_plane_normalized_v3_v3v3(v_proj[1], sv->co_orig_3d, v_proj_axis); + } + + // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) + BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, sv->v); + l_num = liter.count; + loop_weights = do_loop_weight ? BLI_array_alloca(loop_weights, l_num) : NULL; + for (j = 0; j < l_num; j++) { + BMFace *f_copy; /* the copy of 'f' */ + BMLoop *l = BM_iter_step(&liter); + + f_copy = BLI_ghash_lookup(sod->origfaces, l->f); + + /* only loop data, no vertex data since that contains shape keys, + * and we do not want to mess up other shape keys */ + BM_loop_interp_from_face(bm, l, f_copy, false, false); + + /* make sure face-attributes are correct (e.g. MTexPoly) */ + BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL); + + /* weight the loop */ + if (do_loop_weight) { + const float eps = 1.0e-8f; + const BMLoop *l_prev = l->prev; + const BMLoop *l_next = l->next; + const float *co_prev = slide_origdata_orig_vert_co(sod, l_prev->v); + const float *co_next = slide_origdata_orig_vert_co(sod, l_next->v); + bool co_prev_ok; + bool co_next_ok; + + /* In the unlikely case that we're next to a zero length edge - + * walk around the to the next. + * + * Since we only need to check if the vertex is in this corner, + * its not important _which_ loop - as long as its not overlapping + * 'sv->co_orig_3d', see: T45096. */ + project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis); + while (UNLIKELY(((co_prev_ok = (len_squared_v3v3(v_proj[1], v_proj[0]) > eps)) == false) && + ((l_prev = l_prev->prev) != l->next))) { + co_prev = slide_origdata_orig_vert_co(sod, l_prev->v); + project_plane_normalized_v3_v3v3(v_proj[0], co_prev, v_proj_axis); + } + project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis); + while (UNLIKELY(((co_next_ok = (len_squared_v3v3(v_proj[1], v_proj[2]) > eps)) == false) && + ((l_next = l_next->next) != l->prev))) { + co_next = slide_origdata_orig_vert_co(sod, l_next->v); + project_plane_normalized_v3_v3v3(v_proj[2], co_next, v_proj_axis); + } + + if (co_prev_ok && co_next_ok) { + const float dist = dist_signed_squared_to_corner_v3v3v3( + sv->v->co, UNPACK3(v_proj), v_proj_axis); + + loop_weights[j] = (dist >= 0.0f) ? 1.0f : ((dist <= -eps) ? 0.0f : (1.0f + (dist / eps))); + if (UNLIKELY(!isfinite(loop_weights[j]))) { + loop_weights[j] = 0.0f; + } + } + else { + loop_weights[j] = 0.0f; + } + } + } + + if (sod->layer_math_map_num) { + if (do_loop_weight) { + for (j = 0; j < sod->layer_math_map_num; j++) { + BM_vert_loop_groups_data_layer_merge_weights( + bm, sv->cd_loop_groups[j], sod->layer_math_map[j], loop_weights); + } + } + else { + for (j = 0; j < sod->layer_math_map_num; j++) { + BM_vert_loop_groups_data_layer_merge(bm, sv->cd_loop_groups[j], sod->layer_math_map[j]); + } + } + } + + /* Special handling for multires + * + * Interpolate from every other loop (not ideal) + * However values will only be taken from loops which overlap other mdisps. + * */ + if (do_loop_mdisps) { + float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num); + BMLoop *l; + + BM_ITER_ELEM_INDEX(l, &liter, sv->v, BM_LOOPS_OF_VERT, j) + { + BM_face_calc_center_median(l->f, faces_center[j]); + } + + BM_ITER_ELEM_INDEX(l, &liter, sv->v, BM_LOOPS_OF_VERT, j) + { + BMFace *f_copy = BLI_ghash_lookup(sod->origfaces, l->f); + float f_copy_center[3]; + BMIter liter_other; + BMLoop *l_other; + int j_other; + + BM_face_calc_center_median(f_copy, f_copy_center); + + BM_ITER_ELEM_INDEX(l_other, &liter_other, sv->v, BM_LOOPS_OF_VERT, j_other) + { + BM_face_interp_multires_ex(bm, + l_other->f, + f_copy, + faces_center[j_other], + f_copy_center, + sod->cd_loop_mdisp_offset); + } + } + } +} + +static void slide_origdata_interp_data(Object *obedit, + SlideOrigData *sod, + TransDataGenericSlideVert *sv, + unsigned int v_stride, + unsigned int v_num, + bool is_final) +{ + if (sod->use_origfaces) { + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm = em->bm; + unsigned int i; + const bool has_mdisps = (sod->cd_loop_mdisp_offset != -1); + + for (i = 0; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) { + + if (sv->cd_loop_groups || has_mdisps) { + slide_origdata_interp_data_vert(sod, bm, is_final, sv); + } + } + + if (sod->sv_mirror) { + sv = sod->sv_mirror; + for (i = 0; i < v_num; i++, sv++) { + if (sv->cd_loop_groups || has_mdisps) { + slide_origdata_interp_data_vert(sod, bm, is_final, sv); + } + } + } + } +} + +static void slide_origdata_free_date(SlideOrigData *sod) +{ + if (sod->use_origfaces) { + if (sod->bm_origfaces) { + BM_mesh_free(sod->bm_origfaces); + sod->bm_origfaces = NULL; + } + + if (sod->origfaces) { + BLI_ghash_free(sod->origfaces, NULL, NULL); + sod->origfaces = NULL; + } + + if (sod->origverts) { + BLI_ghash_free(sod->origverts, NULL, NULL); + sod->origverts = NULL; + } + + if (sod->arena) { + BLI_memarena_free(sod->arena); + sod->arena = NULL; + } + + MEM_SAFE_FREE(sod->layer_math_map); + + MEM_SAFE_FREE(sod->sv_mirror); + } } /** \} */ @@ -6439,100 +6596,95 @@ static void slide_origdata_free_date( static void calcEdgeSlideCustomPoints(struct TransInfo *t) { - EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; + EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start); + setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start); - /* setCustomPoints isn't normally changing as the mouse moves, - * in this case apply mouse input immediately so we don't refresh - * with the value from the previous points */ - applyMouseInput(t, &t->mouse, t->mval, t->values); + /* setCustomPoints isn't normally changing as the mouse moves, + * in this case apply mouse input immediately so we don't refresh + * with the value from the previous points */ + applyMouseInput(t, &t->mouse, t->mval, t->values); } - static BMEdge *get_other_edge(BMVert *v, BMEdge *e) { - BMIter iter; - BMEdge *e_iter; + BMIter iter; + BMEdge *e_iter; - BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) { - return e_iter; - } - } + BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) { + return e_iter; + } + } - return NULL; + return NULL; } /* interpoaltes along a line made up of 2 segments (used for edge slide) */ -static void interp_line_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], float t) -{ - float t_mid, t_delta; - - /* could be pre-calculated */ - t_mid = line_point_factor_v3(v2, v1, v3); - - t_delta = t - t_mid; - if (t_delta < 0.0f) { - if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) { - copy_v3_v3(p, v2); - } - else { - interp_v3_v3v3(p, v1, v2, t / t_mid); - } - } - else { - t = t - t_mid; - t_mid = 1.0f - t_mid; - - if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) { - copy_v3_v3(p, v3); - } - else { - interp_v3_v3v3(p, v2, v3, t / t_mid); - } - } +static void interp_line_v3_v3v3v3( + float p[3], const float v1[3], const float v2[3], const float v3[3], float t) +{ + float t_mid, t_delta; + + /* could be pre-calculated */ + t_mid = line_point_factor_v3(v2, v1, v3); + + t_delta = t - t_mid; + if (t_delta < 0.0f) { + if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) { + copy_v3_v3(p, v2); + } + else { + interp_v3_v3v3(p, v1, v2, t / t_mid); + } + } + else { + t = t - t_mid; + t_mid = 1.0f - t_mid; + + if (UNLIKELY(fabsf(t_mid) < FLT_EPSILON)) { + copy_v3_v3(p, v3); + } + else { + interp_v3_v3v3(p, v2, v3, t / t_mid); + } + } } /** * Find the closest point on the ngon on the opposite side. * used to set the edge slide distance for ngons. */ -static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, - const float plane_no[3], - float r_co[3]) -{ - /* skip adjacent edges */ - BMLoop *l_first = l_tmp->next; - BMLoop *l_last = l_tmp->prev; - BMLoop *l_iter; - float dist = FLT_MAX; - bool found = false; - - l_iter = l_first; - do { - float tvec[3]; - if (isect_line_plane_v3(tvec, - l_iter->v->co, l_iter->next->v->co, - l_tmp->v->co, plane_no)) - { - const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co); - /* allow some overlap to avoid missing the intersection because of float precision */ - if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) { - /* likelihood of multiple intersections per ngon is quite low, - * it would have to loop back on its self, but better support it - * so check for the closest opposite edge */ - const float tdist = len_v3v3(l_tmp->v->co, tvec); - if (tdist < dist) { - copy_v3_v3(r_co, tvec); - dist = tdist; - found = true; - } - } - } - } while ((l_iter = l_iter->next) != l_last); - - return found; +static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, const float plane_no[3], float r_co[3]) +{ + /* skip adjacent edges */ + BMLoop *l_first = l_tmp->next; + BMLoop *l_last = l_tmp->prev; + BMLoop *l_iter; + float dist = FLT_MAX; + bool found = false; + + l_iter = l_first; + do { + float tvec[3]; + if (isect_line_plane_v3(tvec, l_iter->v->co, l_iter->next->v->co, l_tmp->v->co, plane_no)) { + const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co); + /* allow some overlap to avoid missing the intersection because of float precision */ + if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) { + /* likelihood of multiple intersections per ngon is quite low, + * it would have to loop back on its self, but better support it + * so check for the closest opposite edge */ + const float tdist = len_v3v3(l_tmp->v->co, tvec); + if (tdist < dist) { + copy_v3_v3(r_co, tvec); + dist = tdist; + found = true; + } + } + } + } while ((l_iter = l_iter->next) != l_last); + + return found; } /** @@ -6542,667 +6694,673 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, * \param r_slide_vec: the direction to slide, * the length of the vector defines the slide distance. */ -static BMLoop *get_next_loop(BMVert *v, BMLoop *l, - BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3]) -{ - BMLoop *l_first; - float vec_accum[3] = {0.0f, 0.0f, 0.0f}; - float vec_accum_len = 0.0f; - int i = 0; - - BLI_assert(BM_edge_share_vert(e_prev, e_next) == v); - BLI_assert(BM_vert_in_edge(l->e, v)); - - l_first = l; - do { - l = BM_loop_other_edge_loop(l, v); - - if (l->e == e_next) { - if (i) { - normalize_v3_length(vec_accum, vec_accum_len / (float)i); - } - else { - /* When there is no edge to slide along, - * we must slide along the vector defined by the face we're attach to */ - BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v); - - BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next)); - - if (l_tmp->f->len == 4) { - /* we could use code below, but in this case - * sliding diagonally across the quad works well */ - sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co); - } - else { - float tdir[3]; - BM_loop_calc_face_direction(l_tmp, tdir); - cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir); +static BMLoop *get_next_loop( + BMVert *v, BMLoop *l, BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3]) +{ + BMLoop *l_first; + float vec_accum[3] = {0.0f, 0.0f, 0.0f}; + float vec_accum_len = 0.0f; + int i = 0; + + BLI_assert(BM_edge_share_vert(e_prev, e_next) == v); + BLI_assert(BM_vert_in_edge(l->e, v)); + + l_first = l; + do { + l = BM_loop_other_edge_loop(l, v); + + if (l->e == e_next) { + if (i) { + normalize_v3_length(vec_accum, vec_accum_len / (float)i); + } + else { + /* When there is no edge to slide along, + * we must slide along the vector defined by the face we're attach to */ + BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v); + + BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next)); + + if (l_tmp->f->len == 4) { + /* we could use code below, but in this case + * sliding diagonally across the quad works well */ + sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co); + } + else { + float tdir[3]; + BM_loop_calc_face_direction(l_tmp, tdir); + cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir); #if 0 - /* rough guess, we can do better! */ - normalize_v3_length(vec_accum, (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f); + /* rough guess, we can do better! */ + normalize_v3_length(vec_accum, (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f); #else - /* be clever, check the opposite ngon edge to slide into. - * this gives best results */ - { - float tvec[3]; - float dist; - - if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) { - dist = len_v3v3(l_tmp->v->co, tvec); - } - else { - dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f; - } - - normalize_v3_length(vec_accum, dist); - } + /* be clever, check the opposite ngon edge to slide into. + * this gives best results */ + { + float tvec[3]; + float dist; + + if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) { + dist = len_v3v3(l_tmp->v->co, tvec); + } + else { + dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f; + } + + normalize_v3_length(vec_accum, dist); + } #endif - } - } + } + } - copy_v3_v3(r_slide_vec, vec_accum); - return l; - } - else { - /* accumulate the normalized edge vector, - * normalize so some edges don't skew the result */ - float tvec[3]; - sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co); - vec_accum_len += normalize_v3(tvec); - add_v3_v3(vec_accum, tvec); - i += 1; - } + copy_v3_v3(r_slide_vec, vec_accum); + return l; + } + else { + /* accumulate the normalized edge vector, + * normalize so some edges don't skew the result */ + float tvec[3]; + sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co); + vec_accum_len += normalize_v3(tvec); + add_v3_v3(vec_accum, tvec); + i += 1; + } - if (BM_loop_other_edge_loop(l, v)->e == e_next) { - if (i) { - normalize_v3_length(vec_accum, vec_accum_len / (float)i); - } + if (BM_loop_other_edge_loop(l, v)->e == e_next) { + if (i) { + normalize_v3_length(vec_accum, vec_accum_len / (float)i); + } - copy_v3_v3(r_slide_vec, vec_accum); - return BM_loop_other_edge_loop(l, v); - } + copy_v3_v3(r_slide_vec, vec_accum); + return BM_loop_other_edge_loop(l, v); + } - } while ((l != l->radial_next) && - ((l = l->radial_next) != l_first)); + } while ((l != l->radial_next) && ((l = l->radial_next) != l_first)); - if (i) { - normalize_v3_length(vec_accum, vec_accum_len / (float)i); - } + if (i) { + normalize_v3_length(vec_accum, vec_accum_len / (float)i); + } - copy_v3_v3(r_slide_vec, vec_accum); + copy_v3_v3(r_slide_vec, vec_accum); - return NULL; + return NULL; } /** * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction. */ -static void calcEdgeSlide_mval_range( - TransInfo *t, TransDataContainer *tc, EdgeSlideData *sld, const int *sv_table, const int loop_nr, - const float mval[2], const bool use_occlude_geometry, const bool use_calc_direction) -{ - TransDataEdgeSlideVert *sv_array = sld->sv; - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; - ARegion *ar = t->ar; - View3D *v3d = NULL; - RegionView3D *rv3d = NULL; - float projectMat[4][4]; - BMBVHTree *bmbvh; - - /* only for use_calc_direction */ - float (*loop_dir)[3] = NULL, *loop_maxdist = NULL; - - float mval_start[2], mval_end[2]; - float mval_dir[3], dist_best_sq; - BMIter iter; - BMEdge *e; - - if (t->spacetype == SPACE_VIEW3D) { - /* background mode support */ - v3d = t->sa ? t->sa->spacedata.first : NULL; - rv3d = t->ar ? t->ar->regiondata : NULL; - } - - if (!rv3d) { - /* ok, let's try to survive this */ - unit_m4(projectMat); - } - else { - ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); - } - - if (use_occlude_geometry) { - bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false); - } - else { - bmbvh = NULL; - } - - /* find mouse vectors, the global one, and one per loop in case we have - * multiple loops selected, in case they are oriented different */ - zero_v3(mval_dir); - dist_best_sq = -1.0f; - - if (use_calc_direction) { - loop_dir = MEM_callocN(sizeof(float[3]) * loop_nr, "sv loop_dir"); - loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist"); - copy_vn_fl(loop_maxdist, loop_nr, -1.0f); - } - - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - int i; - - /* search cross edges for visible edge to the mouse cursor, - * then use the shared vertex to calculate screen vector*/ - for (i = 0; i < 2; i++) { - BMIter iter_other; - BMEdge *e_other; - - BMVert *v = i ? e->v1 : e->v2; - BM_ITER_ELEM (e_other, &iter_other, v, BM_EDGES_OF_VERT) { - /* screen-space coords */ - float sco_a[3], sco_b[3]; - float dist_sq; - int j, l_nr; - - if (BM_elem_flag_test(e_other, BM_ELEM_SELECT)) - continue; - - /* This test is only relevant if object is not wire-drawn! See [#32068]. */ - if (use_occlude_geometry && - !BMBVH_EdgeVisible(bmbvh, e_other, t->depsgraph, ar, v3d, tc->obedit)) - { - continue; - } - - BLI_assert(sv_table[BM_elem_index_get(v)] != -1); - j = sv_table[BM_elem_index_get(v)]; - - if (sv_array[j].v_side[1]) { - ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[1]->co, sco_b, projectMat); - } - else { - add_v3_v3v3(sco_b, v->co, sv_array[j].dir_side[1]); - ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat); - } - - if (sv_array[j].v_side[0]) { - ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[0]->co, sco_a, projectMat); - } - else { - add_v3_v3v3(sco_a, v->co, sv_array[j].dir_side[0]); - ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat); - } - - /* global direction */ - dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a); - if ((dist_best_sq == -1.0f) || - /* intentionally use 2d size on 3d vector */ - (dist_sq < dist_best_sq && (len_squared_v2v2(sco_b, sco_a) > 0.1f))) - { - dist_best_sq = dist_sq; - sub_v3_v3v3(mval_dir, sco_b, sco_a); - } - - if (use_calc_direction) { - /* per loop direction */ - l_nr = sv_array[j].loop_nr; - if (loop_maxdist[l_nr] == -1.0f || dist_sq < loop_maxdist[l_nr]) { - loop_maxdist[l_nr] = dist_sq; - sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a); - } - } - } - } - } - } - - if (use_calc_direction) { - int i; - sv_array = sld->sv; - for (i = 0; i < sld->totsv; i++, sv_array++) { - /* switch a/b if loop direction is different from global direction */ - int l_nr = sv_array->loop_nr; - if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) { - swap_v3_v3(sv_array->dir_side[0], sv_array->dir_side[1]); - SWAP(BMVert *, sv_array->v_side[0], sv_array->v_side[1]); - } - } - - MEM_freeN(loop_dir); - MEM_freeN(loop_maxdist); - } - - /* possible all of the edge loops are pointing directly at the view */ - if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) { - mval_dir[0] = 0.0f; - mval_dir[1] = 100.0f; - } - - /* zero out start */ - zero_v2(mval_start); - - /* dir holds a vector along edge loop */ - copy_v2_v2(mval_end, mval_dir); - mul_v2_fl(mval_end, 0.5f); - - sld->mval_start[0] = t->mval[0] + mval_start[0]; - sld->mval_start[1] = t->mval[1] + mval_start[1]; - - sld->mval_end[0] = t->mval[0] + mval_end[0]; - sld->mval_end[1] = t->mval[1] + mval_end[1]; - - if (bmbvh) { - BKE_bmbvh_free(bmbvh); - } -} - -static void calcEdgeSlide_even( - TransInfo *t, TransDataContainer *tc, EdgeSlideData *sld, const float mval[2]) -{ - TransDataEdgeSlideVert *sv = sld->sv; - - if (sld->totsv > 0) { - ARegion *ar = t->ar; - RegionView3D *rv3d = NULL; - float projectMat[4][4]; - - int i = 0; - - float v_proj[2]; - float dist_sq = 0; - float dist_min_sq = FLT_MAX; - - if (t->spacetype == SPACE_VIEW3D) { - /* background mode support */ - rv3d = t->ar ? t->ar->regiondata : NULL; - } - - if (!rv3d) { - /* ok, let's try to survive this */ - unit_m4(projectMat); - } - else { - ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); - } - - for (i = 0; i < sld->totsv; i++, sv++) { - /* Set length */ - sv->edge_len = len_v3v3(sv->dir_side[0], sv->dir_side[1]); - - ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat); - dist_sq = len_squared_v2v2(mval, v_proj); - if (dist_sq < dist_min_sq) { - dist_min_sq = dist_sq; - sld->curr_sv_index = i; - } - } - } - else { - sld->curr_sv_index = 0; - } +static void calcEdgeSlide_mval_range(TransInfo *t, + TransDataContainer *tc, + EdgeSlideData *sld, + const int *sv_table, + const int loop_nr, + const float mval[2], + const bool use_occlude_geometry, + const bool use_calc_direction) +{ + TransDataEdgeSlideVert *sv_array = sld->sv; + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + ARegion *ar = t->ar; + View3D *v3d = NULL; + RegionView3D *rv3d = NULL; + float projectMat[4][4]; + BMBVHTree *bmbvh; + + /* only for use_calc_direction */ + float(*loop_dir)[3] = NULL, *loop_maxdist = NULL; + + float mval_start[2], mval_end[2]; + float mval_dir[3], dist_best_sq; + BMIter iter; + BMEdge *e; + + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ + v3d = t->sa ? t->sa->spacedata.first : NULL; + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); + } + + if (use_occlude_geometry) { + bmbvh = BKE_bmbvh_new_from_editmesh(em, BMBVH_RESPECT_HIDDEN, NULL, false); + } + else { + bmbvh = NULL; + } + + /* find mouse vectors, the global one, and one per loop in case we have + * multiple loops selected, in case they are oriented different */ + zero_v3(mval_dir); + dist_best_sq = -1.0f; + + if (use_calc_direction) { + loop_dir = MEM_callocN(sizeof(float[3]) * loop_nr, "sv loop_dir"); + loop_maxdist = MEM_mallocN(sizeof(float) * loop_nr, "sv loop_maxdist"); + copy_vn_fl(loop_maxdist, loop_nr, -1.0f); + } + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + int i; + + /* search cross edges for visible edge to the mouse cursor, + * then use the shared vertex to calculate screen vector*/ + for (i = 0; i < 2; i++) { + BMIter iter_other; + BMEdge *e_other; + + BMVert *v = i ? e->v1 : e->v2; + BM_ITER_ELEM (e_other, &iter_other, v, BM_EDGES_OF_VERT) { + /* screen-space coords */ + float sco_a[3], sco_b[3]; + float dist_sq; + int j, l_nr; + + if (BM_elem_flag_test(e_other, BM_ELEM_SELECT)) + continue; + + /* This test is only relevant if object is not wire-drawn! See [#32068]. */ + if (use_occlude_geometry && + !BMBVH_EdgeVisible(bmbvh, e_other, t->depsgraph, ar, v3d, tc->obedit)) { + continue; + } + + BLI_assert(sv_table[BM_elem_index_get(v)] != -1); + j = sv_table[BM_elem_index_get(v)]; + + if (sv_array[j].v_side[1]) { + ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[1]->co, sco_b, projectMat); + } + else { + add_v3_v3v3(sco_b, v->co, sv_array[j].dir_side[1]); + ED_view3d_project_float_v3_m4(ar, sco_b, sco_b, projectMat); + } + + if (sv_array[j].v_side[0]) { + ED_view3d_project_float_v3_m4(ar, sv_array[j].v_side[0]->co, sco_a, projectMat); + } + else { + add_v3_v3v3(sco_a, v->co, sv_array[j].dir_side[0]); + ED_view3d_project_float_v3_m4(ar, sco_a, sco_a, projectMat); + } + + /* global direction */ + dist_sq = dist_squared_to_line_segment_v2(mval, sco_b, sco_a); + if ((dist_best_sq == -1.0f) || + /* intentionally use 2d size on 3d vector */ + (dist_sq < dist_best_sq && (len_squared_v2v2(sco_b, sco_a) > 0.1f))) { + dist_best_sq = dist_sq; + sub_v3_v3v3(mval_dir, sco_b, sco_a); + } + + if (use_calc_direction) { + /* per loop direction */ + l_nr = sv_array[j].loop_nr; + if (loop_maxdist[l_nr] == -1.0f || dist_sq < loop_maxdist[l_nr]) { + loop_maxdist[l_nr] = dist_sq; + sub_v3_v3v3(loop_dir[l_nr], sco_b, sco_a); + } + } + } + } + } + } + + if (use_calc_direction) { + int i; + sv_array = sld->sv; + for (i = 0; i < sld->totsv; i++, sv_array++) { + /* switch a/b if loop direction is different from global direction */ + int l_nr = sv_array->loop_nr; + if (dot_v3v3(loop_dir[l_nr], mval_dir) < 0.0f) { + swap_v3_v3(sv_array->dir_side[0], sv_array->dir_side[1]); + SWAP(BMVert *, sv_array->v_side[0], sv_array->v_side[1]); + } + } + + MEM_freeN(loop_dir); + MEM_freeN(loop_maxdist); + } + + /* possible all of the edge loops are pointing directly at the view */ + if (UNLIKELY(len_squared_v2(mval_dir) < 0.1f)) { + mval_dir[0] = 0.0f; + mval_dir[1] = 100.0f; + } + + /* zero out start */ + zero_v2(mval_start); + + /* dir holds a vector along edge loop */ + copy_v2_v2(mval_end, mval_dir); + mul_v2_fl(mval_end, 0.5f); + + sld->mval_start[0] = t->mval[0] + mval_start[0]; + sld->mval_start[1] = t->mval[1] + mval_start[1]; + + sld->mval_end[0] = t->mval[0] + mval_end[0]; + sld->mval_end[1] = t->mval[1] + mval_end[1]; + + if (bmbvh) { + BKE_bmbvh_free(bmbvh); + } +} + +static void calcEdgeSlide_even(TransInfo *t, + TransDataContainer *tc, + EdgeSlideData *sld, + const float mval[2]) +{ + TransDataEdgeSlideVert *sv = sld->sv; + + if (sld->totsv > 0) { + ARegion *ar = t->ar; + RegionView3D *rv3d = NULL; + float projectMat[4][4]; + + int i = 0; + + float v_proj[2]; + float dist_sq = 0; + float dist_min_sq = FLT_MAX; + + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); + } + + for (i = 0; i < sld->totsv; i++, sv++) { + /* Set length */ + sv->edge_len = len_v3v3(sv->dir_side[0], sv->dir_side[1]); + + ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat); + dist_sq = len_squared_v2v2(mval, v_proj); + if (dist_sq < dist_min_sq) { + dist_min_sq = dist_sq; + sld->curr_sv_index = i; + } + } + } + else { + sld->curr_sv_index = 0; + } } static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *tc) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; - BMIter iter; - BMEdge *e; - BMVert *v; - TransDataEdgeSlideVert *sv_array; - int sv_tot; - int *sv_table; /* BMVert -> sv_array index */ - EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); - float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; - int numsel, i, loop_nr; - bool use_occlude_geometry = false; - View3D *v3d = NULL; - RegionView3D *rv3d = NULL; - - slide_origdata_init_flag(t, tc, &sld->orig_data); - - sld->curr_sv_index = 0; - - /*ensure valid selection*/ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BMIter iter2; - numsel = 0; - BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - /* BMESH_TODO: this is probably very evil, - * set v->e to a selected edge*/ - v->e = e; - - numsel++; - } - } - - if (numsel == 0 || numsel > 2) { - MEM_freeN(sld); - return false; /* invalid edge selection */ - } - } - } - - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { - /* note, any edge with loops can work, but we won't get predictable results, so bail out */ - if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) { - /* can edges with at least once face user */ - MEM_freeN(sld); - return false; - } - } - } - - sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__); - -#define INDEX_UNSET -1 + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + BMIter iter; + BMEdge *e; + BMVert *v; + TransDataEdgeSlideVert *sv_array; + int sv_tot; + int *sv_table; /* BMVert -> sv_array index */ + EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; + int numsel, i, loop_nr; + bool use_occlude_geometry = false; + View3D *v3d = NULL; + RegionView3D *rv3d = NULL; + + slide_origdata_init_flag(t, tc, &sld->orig_data); + + sld->curr_sv_index = 0; + + /*ensure valid selection*/ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BMIter iter2; + numsel = 0; + BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + /* BMESH_TODO: this is probably very evil, + * set v->e to a selected edge*/ + v->e = e; + + numsel++; + } + } + + if (numsel == 0 || numsel > 2) { + MEM_freeN(sld); + return false; /* invalid edge selection */ + } + } + } + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + /* note, any edge with loops can work, but we won't get predictable results, so bail out */ + if (!BM_edge_is_manifold(e) && !BM_edge_is_boundary(e)) { + /* can edges with at least once face user */ + MEM_freeN(sld); + return false; + } + } + } + + sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__); + +#define INDEX_UNSET -1 #define INDEX_INVALID -2 - { - int j = 0; - BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - BM_elem_flag_enable(v, BM_ELEM_TAG); - sv_table[i] = INDEX_UNSET; - j += 1; - } - else { - BM_elem_flag_disable(v, BM_ELEM_TAG); - sv_table[i] = INDEX_INVALID; - } - BM_elem_index_set(v, i); /* set_inline */ - } - bm->elem_index_dirty &= ~BM_VERT; - - if (!j) { - MEM_freeN(sld); - MEM_freeN(sv_table); - return false; - } - sv_tot = j; - } - - sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array"); - loop_nr = 0; - - STACK_DECLARE(sv_array); - STACK_INIT(sv_array, sv_tot); - - while (1) { - float vec_a[3], vec_b[3]; - BMLoop *l_a, *l_b; - BMLoop *l_a_prev, *l_b_prev; - BMVert *v_first; - /* If this succeeds call get_next_loop() - * which calculates the direction to slide based on clever checks. - * - * otherwise we simply use 'e_dir' as an edge-rail. - * (which is better when the attached edge is a boundary, see: T40422) - */ + { + int j = 0; + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + sv_table[i] = INDEX_UNSET; + j += 1; + } + else { + BM_elem_flag_disable(v, BM_ELEM_TAG); + sv_table[i] = INDEX_INVALID; + } + BM_elem_index_set(v, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_VERT; + + if (!j) { + MEM_freeN(sld); + MEM_freeN(sv_table); + return false; + } + sv_tot = j; + } + + sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array"); + loop_nr = 0; + + STACK_DECLARE(sv_array); + STACK_INIT(sv_array, sv_tot); + + while (1) { + float vec_a[3], vec_b[3]; + BMLoop *l_a, *l_b; + BMLoop *l_a_prev, *l_b_prev; + BMVert *v_first; + /* If this succeeds call get_next_loop() + * which calculates the direction to slide based on clever checks. + * + * otherwise we simply use 'e_dir' as an edge-rail. + * (which is better when the attached edge is a boundary, see: T40422) + */ #define EDGESLIDE_VERT_IS_INNER(v, e_dir) \ - ((BM_edge_is_boundary(e_dir) == false) && \ - (BM_vert_edge_count_nonwire(v) == 2)) - - v = NULL; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_TAG)) - break; - - } - - if (!v) - break; - - if (!v->e) - continue; - - v_first = v; - - /*walk along the edge loop*/ - e = v->e; - - /*first, rewind*/ - do { - e = get_other_edge(v, e); - if (!e) { - e = v->e; - break; - } - - if (!BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) - break; - - v = BM_edge_other_vert(e, v); - } while (e != v_first->e); - - BM_elem_flag_disable(v, BM_ELEM_TAG); - - l_a = e->l; - l_b = e->l->radial_next; - - /* regarding e_next, use get_next_loop()'s improved interpolation where possible */ - { - BMEdge *e_next = get_other_edge(v, e); - if (e_next) { - get_next_loop(v, l_a, e, e_next, vec_a); - } - else { - BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v); - if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { - get_next_loop(v, l_a, e, l_tmp->e, vec_a); - } - else { - sub_v3_v3v3(vec_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co); - } - } - } - - /* !BM_edge_is_boundary(e); */ - if (l_b != l_a) { - BMEdge *e_next = get_other_edge(v, e); - if (e_next) { - get_next_loop(v, l_b, e, e_next, vec_b); - } - else { - BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v); - if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { - get_next_loop(v, l_b, e, l_tmp->e, vec_b); - } - else { - sub_v3_v3v3(vec_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co); - } - } - } - else { - l_b = NULL; - } - - l_a_prev = NULL; - l_b_prev = NULL; - -#define SV_FROM_VERT(v) ( \ - (sv_table[BM_elem_index_get(v)] == INDEX_UNSET) ? \ - ((void)(sv_table[BM_elem_index_get(v)] = STACK_SIZE(sv_array)), STACK_PUSH_RET_PTR(sv_array)) : \ - (&sv_array[sv_table[BM_elem_index_get(v)]])) - - /*iterate over the loop*/ - v_first = v; - do { - bool l_a_ok_prev; - bool l_b_ok_prev; - TransDataEdgeSlideVert *sv; - BMVert *v_prev; - BMEdge *e_prev; - - /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */ - BLI_assert(v != NULL); - BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID); - sv = SV_FROM_VERT(v); - sv->v = v; - copy_v3_v3(sv->v_co_orig, v->co); - sv->loop_nr = loop_nr; - - if (l_a || l_a_prev) { - BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v); - sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v); - copy_v3_v3(sv->dir_side[0], vec_a); - } - - if (l_b || l_b_prev) { - BMLoop *l_tmp = BM_loop_other_edge_loop(l_b ? l_b : l_b_prev, v); - sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v); - copy_v3_v3(sv->dir_side[1], vec_b); - } - - v_prev = v; - v = BM_edge_other_vert(e, v); - - e_prev = e; - e = get_other_edge(v, e); - - if (!e) { - BLI_assert(v != NULL); - - BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID); - sv = SV_FROM_VERT(v); - - sv->v = v; - copy_v3_v3(sv->v_co_orig, v->co); - sv->loop_nr = loop_nr; - - if (l_a) { - BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v); - sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v); - if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { - get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_side[0]); - } - else { - sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co); - } - } - - if (l_b) { - BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v); - sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v); - if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { - get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_side[1]); - } - else { - sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co); - } - } - - BM_elem_flag_disable(v, BM_ELEM_TAG); - BM_elem_flag_disable(v_prev, BM_ELEM_TAG); - - break; - } - l_a_ok_prev = (l_a != NULL); - l_b_ok_prev = (l_b != NULL); - - l_a_prev = l_a; - l_b_prev = l_b; - - if (l_a) { - l_a = get_next_loop(v, l_a, e_prev, e, vec_a); - } - else { - zero_v3(vec_a); - } - - if (l_b) { - l_b = get_next_loop(v, l_b, e_prev, e, vec_b); - } - else { - zero_v3(vec_b); - } - - - if (l_a && l_b) { - /* pass */ - } - else { - if (l_a || l_b) { - /* find the opposite loop if it was missing previously */ - if (l_a == NULL && l_b && (l_b->radial_next != l_b)) l_a = l_b->radial_next; - else if (l_b == NULL && l_a && (l_a->radial_next != l_a)) l_b = l_a->radial_next; - } - else if (e->l != NULL) { - /* if there are non-contiguous faces, we can still recover - * the loops of the new edges faces */ - - /* note!, the behavior in this case means edges may move in opposite directions, - * this could be made to work more usefully. */ - - if (l_a_ok_prev) { - l_a = e->l; - l_b = (l_a->radial_next != l_a) ? l_a->radial_next : NULL; - } - else if (l_b_ok_prev) { - l_b = e->l; - l_a = (l_b->radial_next != l_b) ? l_b->radial_next : NULL; - } - } - - if (!l_a_ok_prev && l_a) { - get_next_loop(v, l_a, e, e_prev, vec_a); - } - if (!l_b_ok_prev && l_b) { - get_next_loop(v, l_b, e, e_prev, vec_b); - } - } - - BM_elem_flag_disable(v, BM_ELEM_TAG); - BM_elem_flag_disable(v_prev, BM_ELEM_TAG); - } while ((e != v_first->e) && (l_a || l_b)); + ((BM_edge_is_boundary(e_dir) == false) && (BM_vert_edge_count_nonwire(v) == 2)) + + v = NULL; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) + break; + } + + if (!v) + break; + + if (!v->e) + continue; + + v_first = v; + + /*walk along the edge loop*/ + e = v->e; + + /*first, rewind*/ + do { + e = get_other_edge(v, e); + if (!e) { + e = v->e; + break; + } + + if (!BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) + break; + + v = BM_edge_other_vert(e, v); + } while (e != v_first->e); + + BM_elem_flag_disable(v, BM_ELEM_TAG); + + l_a = e->l; + l_b = e->l->radial_next; + + /* regarding e_next, use get_next_loop()'s improved interpolation where possible */ + { + BMEdge *e_next = get_other_edge(v, e); + if (e_next) { + get_next_loop(v, l_a, e, e_next, vec_a); + } + else { + BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v); + if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { + get_next_loop(v, l_a, e, l_tmp->e, vec_a); + } + else { + sub_v3_v3v3(vec_a, BM_edge_other_vert(l_tmp->e, v)->co, v->co); + } + } + } + + /* !BM_edge_is_boundary(e); */ + if (l_b != l_a) { + BMEdge *e_next = get_other_edge(v, e); + if (e_next) { + get_next_loop(v, l_b, e, e_next, vec_b); + } + else { + BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v); + if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { + get_next_loop(v, l_b, e, l_tmp->e, vec_b); + } + else { + sub_v3_v3v3(vec_b, BM_edge_other_vert(l_tmp->e, v)->co, v->co); + } + } + } + else { + l_b = NULL; + } + + l_a_prev = NULL; + l_b_prev = NULL; + +#define SV_FROM_VERT(v) \ + ((sv_table[BM_elem_index_get(v)] == INDEX_UNSET) ? \ + ((void)(sv_table[BM_elem_index_get(v)] = STACK_SIZE(sv_array)), \ + STACK_PUSH_RET_PTR(sv_array)) : \ + (&sv_array[sv_table[BM_elem_index_get(v)]])) + + /*iterate over the loop*/ + v_first = v; + do { + bool l_a_ok_prev; + bool l_b_ok_prev; + TransDataEdgeSlideVert *sv; + BMVert *v_prev; + BMEdge *e_prev; + + /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */ + BLI_assert(v != NULL); + BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID); + sv = SV_FROM_VERT(v); + sv->v = v; + copy_v3_v3(sv->v_co_orig, v->co); + sv->loop_nr = loop_nr; + + if (l_a || l_a_prev) { + BMLoop *l_tmp = BM_loop_other_edge_loop(l_a ? l_a : l_a_prev, v); + sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v); + copy_v3_v3(sv->dir_side[0], vec_a); + } + + if (l_b || l_b_prev) { + BMLoop *l_tmp = BM_loop_other_edge_loop(l_b ? l_b : l_b_prev, v); + sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v); + copy_v3_v3(sv->dir_side[1], vec_b); + } + + v_prev = v; + v = BM_edge_other_vert(e, v); + + e_prev = e; + e = get_other_edge(v, e); + + if (!e) { + BLI_assert(v != NULL); + + BLI_assert(sv_table[BM_elem_index_get(v)] != INDEX_INVALID); + sv = SV_FROM_VERT(v); + + sv->v = v; + copy_v3_v3(sv->v_co_orig, v->co); + sv->loop_nr = loop_nr; + + if (l_a) { + BMLoop *l_tmp = BM_loop_other_edge_loop(l_a, v); + sv->v_side[0] = BM_edge_other_vert(l_tmp->e, v); + if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { + get_next_loop(v, l_a, e_prev, l_tmp->e, sv->dir_side[0]); + } + else { + sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co); + } + } + + if (l_b) { + BMLoop *l_tmp = BM_loop_other_edge_loop(l_b, v); + sv->v_side[1] = BM_edge_other_vert(l_tmp->e, v); + if (EDGESLIDE_VERT_IS_INNER(v, l_tmp->e)) { + get_next_loop(v, l_b, e_prev, l_tmp->e, sv->dir_side[1]); + } + else { + sub_v3_v3v3(sv->dir_side[1], sv->v_side[1]->co, v->co); + } + } + + BM_elem_flag_disable(v, BM_ELEM_TAG); + BM_elem_flag_disable(v_prev, BM_ELEM_TAG); + + break; + } + l_a_ok_prev = (l_a != NULL); + l_b_ok_prev = (l_b != NULL); + + l_a_prev = l_a; + l_b_prev = l_b; + + if (l_a) { + l_a = get_next_loop(v, l_a, e_prev, e, vec_a); + } + else { + zero_v3(vec_a); + } + + if (l_b) { + l_b = get_next_loop(v, l_b, e_prev, e, vec_b); + } + else { + zero_v3(vec_b); + } + + if (l_a && l_b) { + /* pass */ + } + else { + if (l_a || l_b) { + /* find the opposite loop if it was missing previously */ + if (l_a == NULL && l_b && (l_b->radial_next != l_b)) + l_a = l_b->radial_next; + else if (l_b == NULL && l_a && (l_a->radial_next != l_a)) + l_b = l_a->radial_next; + } + else if (e->l != NULL) { + /* if there are non-contiguous faces, we can still recover + * the loops of the new edges faces */ + + /* note!, the behavior in this case means edges may move in opposite directions, + * this could be made to work more usefully. */ + + if (l_a_ok_prev) { + l_a = e->l; + l_b = (l_a->radial_next != l_a) ? l_a->radial_next : NULL; + } + else if (l_b_ok_prev) { + l_b = e->l; + l_a = (l_b->radial_next != l_b) ? l_b->radial_next : NULL; + } + } + + if (!l_a_ok_prev && l_a) { + get_next_loop(v, l_a, e, e_prev, vec_a); + } + if (!l_b_ok_prev && l_b) { + get_next_loop(v, l_b, e, e_prev, vec_b); + } + } + + BM_elem_flag_disable(v, BM_ELEM_TAG); + BM_elem_flag_disable(v_prev, BM_ELEM_TAG); + } while ((e != v_first->e) && (l_a || l_b)); #undef SV_FROM_VERT #undef INDEX_UNSET #undef INDEX_INVALID - loop_nr++; + loop_nr++; #undef EDGESLIDE_VERT_IS_INNER - } + } - /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ + /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ - BLI_assert(STACK_SIZE(sv_array) == sv_tot); + BLI_assert(STACK_SIZE(sv_array) == sv_tot); - sld->sv = sv_array; - sld->totsv = sv_tot; + sld->sv = sv_array; + sld->totsv = sv_tot; - /* use for visibility checks */ - if (t->spacetype == SPACE_VIEW3D) { - v3d = t->sa ? t->sa->spacedata.first : NULL; - rv3d = t->ar ? t->ar->regiondata : NULL; - use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && !XRAY_ENABLED(v3d)); - } + /* use for visibility checks */ + if (t->spacetype == SPACE_VIEW3D) { + v3d = t->sa ? t->sa->spacedata.first : NULL; + rv3d = t->ar ? t->ar->regiondata : NULL; + use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && + !XRAY_ENABLED(v3d)); + } - calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true); + calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true); - /* create copies of faces for customdata projection */ - bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - slide_origdata_init_data(tc, &sld->orig_data); - slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); + /* create copies of faces for customdata projection */ + bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + slide_origdata_init_data(tc, &sld->orig_data); + slide_origdata_create_data( + tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); - if (rv3d) { - calcEdgeSlide_even(t, tc, sld, mval); - } + if (rv3d) { + calcEdgeSlide_even(t, tc, sld, mval); + } - sld->em = em; + sld->em = em; - tc->custom.mode.data = sld; + tc->custom.mode.data = sld; - MEM_freeN(sv_table); + MEM_freeN(sv_table); - return true; + return true; } /** @@ -7211,600 +7369,623 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *t */ static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *tc) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; - BMIter iter; - BMEdge *e; - TransDataEdgeSlideVert *sv_array; - int sv_tot; - int *sv_table; /* BMVert -> sv_array index */ - EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); - float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; - int loop_nr; - bool use_occlude_geometry = false; - View3D *v3d = NULL; - RegionView3D *rv3d = NULL; - - if (t->spacetype == SPACE_VIEW3D) { - /* background mode support */ - v3d = t->sa ? t->sa->spacedata.first : NULL; - rv3d = t->ar ? t->ar->regiondata : NULL; - } - - slide_origdata_init_flag(t, tc, &sld->orig_data); - - sld->curr_sv_index = 0; - /* ensure valid selection */ - { - int i = 0, j = 0; - BMVert *v; - - BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { - float len_sq_max = -1.0f; - BMIter iter2; - BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) { - if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) { - float len_sq = BM_edge_calc_length_squared(e); - if (len_sq > len_sq_max) { - len_sq_max = len_sq; - v->e = e; - } - } - } - - if (len_sq_max != -1.0f) { - j++; - } - } - BM_elem_index_set(v, i); /* set_inline */ - } - bm->elem_index_dirty &= ~BM_VERT; - - if (!j) { - MEM_freeN(sld); - return false; - } - - sv_tot = j; - } - - BLI_assert(sv_tot != 0); - /* over alloc */ - sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * bm->totvertsel, "sv_array"); - - /* same loop for all loops, weak but we dont connect loops in this case */ - loop_nr = 1; - - sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__); - - { - int i = 0, j = 0; - BMVert *v; - - BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { - sv_table[i] = -1; - if ((v->e != NULL) && (BM_elem_flag_test(v, BM_ELEM_SELECT))) { - if (BM_elem_flag_test(v->e, BM_ELEM_SELECT) == 0) { - TransDataEdgeSlideVert *sv; - sv = &sv_array[j]; - sv->v = v; - copy_v3_v3(sv->v_co_orig, v->co); - sv->v_side[0] = BM_edge_other_vert(v->e, v); - sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co); - sv->loop_nr = 0; - sv_table[i] = j; - j += 1; - } - } - } - } - - /* check for wire vertices, - * interpolate the directions of wire verts between non-wire verts */ - if (sv_tot != bm->totvert) { - const int sv_tot_nowire = sv_tot; - TransDataEdgeSlideVert *sv_iter = sv_array; - - for (int i = 0; i < sv_tot_nowire; i++, sv_iter++) { - BMIter eiter; - BM_ITER_ELEM (e, &eiter, sv_iter->v, BM_EDGES_OF_VERT) { - /* walk over wire */ - TransDataEdgeSlideVert *sv_end = NULL; - BMEdge *e_step = e; - BMVert *v = sv_iter->v; - int j; - - j = sv_tot; - - while (1) { - BMVert *v_other = BM_edge_other_vert(e_step, v); - int endpoint = ( - (sv_table[BM_elem_index_get(v_other)] != -1) + - (BM_vert_is_edge_pair(v_other) == false)); - - if ((BM_elem_flag_test(e_step, BM_ELEM_SELECT) && - BM_elem_flag_test(v_other, BM_ELEM_SELECT)) && - (endpoint == 0)) - { - /* scan down the list */ - TransDataEdgeSlideVert *sv; - BLI_assert(sv_table[BM_elem_index_get(v_other)] == -1); - sv_table[BM_elem_index_get(v_other)] = j; - sv = &sv_array[j]; - sv->v = v_other; - copy_v3_v3(sv->v_co_orig, v_other->co); - copy_v3_v3(sv->dir_side[0], sv_iter->dir_side[0]); - j++; - - /* advance! */ - v = v_other; - e_step = BM_DISK_EDGE_NEXT(e_step, v_other); - } - else { - if ((endpoint == 2) && (sv_tot != j)) { - BLI_assert(BM_elem_index_get(v_other) != -1); - sv_end = &sv_array[sv_table[BM_elem_index_get(v_other)]]; - } - break; - } - } - - if (sv_end) { - int sv_tot_prev = sv_tot; - const float *co_src = sv_iter->v->co; - const float *co_dst = sv_end->v->co; - const float *dir_src = sv_iter->dir_side[0]; - const float *dir_dst = sv_end->dir_side[0]; - sv_tot = j; - - while (j-- != sv_tot_prev) { - float factor; - factor = line_point_factor_v3(sv_array[j].v->co, co_src, co_dst); - interp_v3_v3v3(sv_array[j].dir_side[0], dir_src, dir_dst, factor); - } - } - } - } - } - - /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ - - sld->sv = sv_array; - sld->totsv = sv_tot; - - /* use for visibility checks */ - if (t->spacetype == SPACE_VIEW3D) { - v3d = t->sa ? t->sa->spacedata.first : NULL; - rv3d = t->ar ? t->ar->regiondata : NULL; - use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && !XRAY_ENABLED(v3d)); - } - - calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false); - - /* create copies of faces for customdata projection */ - bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - slide_origdata_init_data(tc, &sld->orig_data); - slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); - - if (rv3d) { - calcEdgeSlide_even(t, tc, sld, mval); - } - - sld->em = em; - - tc->custom.mode.data = sld; - - MEM_freeN(sv_table); - - return true; + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + BMIter iter; + BMEdge *e; + TransDataEdgeSlideVert *sv_array; + int sv_tot; + int *sv_table; /* BMVert -> sv_array index */ + EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + float mval[2] = {(float)t->mval[0], (float)t->mval[1]}; + int loop_nr; + bool use_occlude_geometry = false; + View3D *v3d = NULL; + RegionView3D *rv3d = NULL; + + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ + v3d = t->sa ? t->sa->spacedata.first : NULL; + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + slide_origdata_init_flag(t, tc, &sld->orig_data); + + sld->curr_sv_index = 0; + /* ensure valid selection */ + { + int i = 0, j = 0; + BMVert *v; + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + float len_sq_max = -1.0f; + BMIter iter2; + BM_ITER_ELEM (e, &iter2, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) { + float len_sq = BM_edge_calc_length_squared(e); + if (len_sq > len_sq_max) { + len_sq_max = len_sq; + v->e = e; + } + } + } + + if (len_sq_max != -1.0f) { + j++; + } + } + BM_elem_index_set(v, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_VERT; + + if (!j) { + MEM_freeN(sld); + return false; + } + + sv_tot = j; + } + + BLI_assert(sv_tot != 0); + /* over alloc */ + sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * bm->totvertsel, "sv_array"); + + /* same loop for all loops, weak but we dont connect loops in this case */ + loop_nr = 1; + + sv_table = MEM_mallocN(sizeof(*sv_table) * bm->totvert, __func__); + + { + int i = 0, j = 0; + BMVert *v; + + BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { + sv_table[i] = -1; + if ((v->e != NULL) && (BM_elem_flag_test(v, BM_ELEM_SELECT))) { + if (BM_elem_flag_test(v->e, BM_ELEM_SELECT) == 0) { + TransDataEdgeSlideVert *sv; + sv = &sv_array[j]; + sv->v = v; + copy_v3_v3(sv->v_co_orig, v->co); + sv->v_side[0] = BM_edge_other_vert(v->e, v); + sub_v3_v3v3(sv->dir_side[0], sv->v_side[0]->co, v->co); + sv->loop_nr = 0; + sv_table[i] = j; + j += 1; + } + } + } + } + + /* check for wire vertices, + * interpolate the directions of wire verts between non-wire verts */ + if (sv_tot != bm->totvert) { + const int sv_tot_nowire = sv_tot; + TransDataEdgeSlideVert *sv_iter = sv_array; + + for (int i = 0; i < sv_tot_nowire; i++, sv_iter++) { + BMIter eiter; + BM_ITER_ELEM (e, &eiter, sv_iter->v, BM_EDGES_OF_VERT) { + /* walk over wire */ + TransDataEdgeSlideVert *sv_end = NULL; + BMEdge *e_step = e; + BMVert *v = sv_iter->v; + int j; + + j = sv_tot; + + while (1) { + BMVert *v_other = BM_edge_other_vert(e_step, v); + int endpoint = ((sv_table[BM_elem_index_get(v_other)] != -1) + + (BM_vert_is_edge_pair(v_other) == false)); + + if ((BM_elem_flag_test(e_step, BM_ELEM_SELECT) && + BM_elem_flag_test(v_other, BM_ELEM_SELECT)) && + (endpoint == 0)) { + /* scan down the list */ + TransDataEdgeSlideVert *sv; + BLI_assert(sv_table[BM_elem_index_get(v_other)] == -1); + sv_table[BM_elem_index_get(v_other)] = j; + sv = &sv_array[j]; + sv->v = v_other; + copy_v3_v3(sv->v_co_orig, v_other->co); + copy_v3_v3(sv->dir_side[0], sv_iter->dir_side[0]); + j++; + + /* advance! */ + v = v_other; + e_step = BM_DISK_EDGE_NEXT(e_step, v_other); + } + else { + if ((endpoint == 2) && (sv_tot != j)) { + BLI_assert(BM_elem_index_get(v_other) != -1); + sv_end = &sv_array[sv_table[BM_elem_index_get(v_other)]]; + } + break; + } + } + + if (sv_end) { + int sv_tot_prev = sv_tot; + const float *co_src = sv_iter->v->co; + const float *co_dst = sv_end->v->co; + const float *dir_src = sv_iter->dir_side[0]; + const float *dir_dst = sv_end->dir_side[0]; + sv_tot = j; + + while (j-- != sv_tot_prev) { + float factor; + factor = line_point_factor_v3(sv_array[j].v->co, co_src, co_dst); + interp_v3_v3v3(sv_array[j].dir_side[0], dir_src, dir_dst, factor); + } + } + } + } + } + + /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ + + sld->sv = sv_array; + sld->totsv = sv_tot; + + /* use for visibility checks */ + if (t->spacetype == SPACE_VIEW3D) { + v3d = t->sa ? t->sa->spacedata.first : NULL; + rv3d = t->ar ? t->ar->regiondata : NULL; + use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && + !XRAY_ENABLED(v3d)); + } + + calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false); + + /* create copies of faces for customdata projection */ + bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + slide_origdata_init_data(tc, &sld->orig_data); + slide_origdata_create_data( + tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); + + if (rv3d) { + calcEdgeSlide_even(t, tc, sld, mval); + } + + sld->em = em; + + tc->custom.mode.data = sld; + + MEM_freeN(sv_table); + + return true; } void projectEdgeSlideData(TransInfo *t, bool is_final) { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - EdgeSlideData *sld = tc->custom.mode.data; - SlideOrigData *sod = &sld->orig_data; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + EdgeSlideData *sld = tc->custom.mode.data; + SlideOrigData *sod = &sld->orig_data; - if (sod->use_origfaces == false) { - return; - } + if (sod->use_origfaces == false) { + return; + } - slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final); - } + slide_origdata_interp_data(tc->obedit, + sod, + (TransDataGenericSlideVert *)sld->sv, + sizeof(*sld->sv), + sld->totsv, + is_final); + } } void freeEdgeSlideTempFaces(EdgeSlideData *sld) { - slide_origdata_free_date(&sld->orig_data); + slide_origdata_free_date(&sld->orig_data); } -void freeEdgeSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data) +void freeEdgeSlideVerts(TransInfo *UNUSED(t), + TransDataContainer *UNUSED(tc), + TransCustomData *custom_data) { - EdgeSlideData *sld = custom_data->data; + EdgeSlideData *sld = custom_data->data; - if (!sld) - return; + if (!sld) + return; - freeEdgeSlideTempFaces(sld); + freeEdgeSlideTempFaces(sld); - bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - MEM_freeN(sld->sv); - MEM_freeN(sld); + MEM_freeN(sld->sv); + MEM_freeN(sld); - custom_data->data = NULL; + custom_data->data = NULL; } -static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp) +static void initEdgeSlide_ex( + TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp) { - EdgeSlideData *sld; - bool ok = false; + EdgeSlideData *sld; + bool ok = false; - t->mode = TFM_EDGE_SLIDE; - t->transform = applyEdgeSlide; - t->handleEvent = handleEventEdgeSlide; + t->mode = TFM_EDGE_SLIDE; + t->transform = applyEdgeSlide; + t->handleEvent = handleEventEdgeSlide; - { - EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); - slp->use_even = use_even; - slp->flipped = flipped; - /* happens to be best for single-sided */ - if (use_double_side == false) { - slp->flipped = !flipped; - } - slp->perc = 0.0f; + { + EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); + slp->use_even = use_even; + slp->flipped = flipped; + /* happens to be best for single-sided */ + if (use_double_side == false) { + slp->flipped = !flipped; + } + slp->perc = 0.0f; - if (!use_clamp) { - t->flag |= T_ALT_TRANSFORM; - } + if (!use_clamp) { + t->flag |= T_ALT_TRANSFORM; + } - t->custom.mode.data = slp; - t->custom.mode.use_free = true; - } + t->custom.mode.data = slp; + t->custom.mode.use_free = true; + } - if (use_double_side) { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - ok |= createEdgeSlideVerts_double_side(t, tc); - } - } - else { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - ok |= createEdgeSlideVerts_single_side(t, tc); - } - } + if (use_double_side) { + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + ok |= createEdgeSlideVerts_double_side(t, tc); + } + } + else { + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + ok |= createEdgeSlideVerts_single_side(t, tc); + } + } - if (!ok) { - t->state = TRANS_CANCEL; - return; - } + if (!ok) { + t->state = TRANS_CANCEL; + return; + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - sld = tc->custom.mode.data; - if (!sld) { - continue; - } - tc->custom.mode.free_cb = freeEdgeSlideVerts; - } + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + sld = tc->custom.mode.data; + if (!sld) { + continue; + } + tc->custom.mode.free_cb = freeEdgeSlideVerts; + } - /* set custom point first if you want value to be initialized by init */ - calcEdgeSlideCustomPoints(t); - initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP); + /* set custom point first if you want value to be initialized by init */ + calcEdgeSlideCustomPoints(t); + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } static void initEdgeSlide(TransInfo *t) { - initEdgeSlide_ex(t, true, false, false, true); + initEdgeSlide_ex(t, true, false, false, true); } static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event) { - if (t->mode == TFM_EDGE_SLIDE) { - EdgeSlideParams *slp = t->custom.mode.data; - - if (slp) { - switch (event->type) { - case EKEY: - if (event->val == KM_PRESS) { - slp->use_even = !slp->use_even; - calcEdgeSlideCustomPoints(t); - return TREDRAW_HARD; - } - break; - case FKEY: - if (event->val == KM_PRESS) { - slp->flipped = !slp->flipped; - calcEdgeSlideCustomPoints(t); - return TREDRAW_HARD; - } - break; - case CKEY: - /* use like a modifier key */ - if (event->val == KM_PRESS) { - t->flag ^= T_ALT_TRANSFORM; - calcEdgeSlideCustomPoints(t); - return TREDRAW_HARD; - } - break; - case EVT_MODAL_MAP: + if (t->mode == TFM_EDGE_SLIDE) { + EdgeSlideParams *slp = t->custom.mode.data; + + if (slp) { + switch (event->type) { + case EKEY: + if (event->val == KM_PRESS) { + slp->use_even = !slp->use_even; + calcEdgeSlideCustomPoints(t); + return TREDRAW_HARD; + } + break; + case FKEY: + if (event->val == KM_PRESS) { + slp->flipped = !slp->flipped; + calcEdgeSlideCustomPoints(t); + return TREDRAW_HARD; + } + break; + case CKEY: + /* use like a modifier key */ + if (event->val == KM_PRESS) { + t->flag ^= T_ALT_TRANSFORM; + calcEdgeSlideCustomPoints(t); + return TREDRAW_HARD; + } + break; + case EVT_MODAL_MAP: #if 0 - switch (event->val) { - case TFM_MODAL_EDGESLIDE_DOWN: - sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; - return TREDRAW_HARD; - case TFM_MODAL_EDGESLIDE_UP: - sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; - return TREDRAW_HARD; - } + switch (event->val) { + case TFM_MODAL_EDGESLIDE_DOWN: + sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; + return TREDRAW_HARD; + case TFM_MODAL_EDGESLIDE_UP: + sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; + return TREDRAW_HARD; + } #endif - break; - case MOUSEMOVE: - calcEdgeSlideCustomPoints(t); - break; - default: - break; - } - } - } - return TREDRAW_NOTHING; + break; + case MOUSEMOVE: + calcEdgeSlideCustomPoints(t); + break; + default: + break; + } + } + } + return TREDRAW_NOTHING; } static void drawEdgeSlide(TransInfo *t) { - if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) { - const EdgeSlideParams *slp = t->custom.mode.data; - EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - - /* Even mode */ - if ((slp->use_even == true) || (is_clamp == false)) { - const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; - - GPU_depth_test(false); - - GPU_blend(true); - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - - GPU_matrix_push(); - GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - - if (slp->use_even == true) { - float co_a[3], co_b[3], co_mark[3]; - TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float fac = (slp->perc + 1.0f) / 2.0f; - const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; - const float guide_size = ctrl_size - 0.5f; - const int alpha_shade = -30; - - add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); - add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); - - GPU_line_width(line_size); - immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBeginAtMost(GPU_PRIM_LINES, 4); - if (curr_sv->v_side[0]) { - immVertex3fv(pos, curr_sv->v_side[0]->co); - immVertex3fv(pos, curr_sv->v_co_orig); - } - if (curr_sv->v_side[1]) { - immVertex3fv(pos, curr_sv->v_side[1]->co); - immVertex3fv(pos, curr_sv->v_co_orig); - } - immEnd(); - - immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); - GPU_point_size(ctrl_size); - immBegin(GPU_PRIM_POINTS, 1); - if (slp->flipped) { - if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co); - } - else { - if (curr_sv->v_side[0]) immVertex3fv(pos, curr_sv->v_side[0]->co); - } - immEnd(); - - immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); - GPU_point_size(guide_size); - immBegin(GPU_PRIM_POINTS, 1); - interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); - immVertex3fv(pos, co_mark); - immEnd(); - } - else { - if (is_clamp == false) { - const int side_index = sld->curr_side_unclamp; - TransDataEdgeSlideVert *sv; - int i; - const int alpha_shade = -160; - - GPU_line_width(line_size); - immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immBegin(GPU_PRIM_LINES, sld->totsv * 2); - - /* TODO(campbell): Loop over all verts */ - sv = sld->sv; - for (i = 0; i < sld->totsv; i++, sv++) { - float a[3], b[3]; - - if (!is_zero_v3(sv->dir_side[side_index])) { - copy_v3_v3(a, sv->dir_side[side_index]); - } - else { - copy_v3_v3(a, sv->dir_side[!side_index]); - } - - mul_v3_fl(a, 100.0f); - negate_v3_v3(b, a); - add_v3_v3(a, sv->v_co_orig); - add_v3_v3(b, sv->v_co_orig); - - immVertex3fv(pos, a); - immVertex3fv(pos, b); - } - immEnd(); - } - else { - BLI_assert(0); - } - } - - immUnbindProgram(); - - GPU_matrix_pop(); - - GPU_blend(false); - - GPU_depth_test(true); - } - } + if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) { + const EdgeSlideParams *slp = t->custom.mode.data; + EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + + /* Even mode */ + if ((slp->use_even == true) || (is_clamp == false)) { + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + + GPU_depth_test(false); + + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + + uint pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + + if (slp->use_even == true) { + float co_a[3], co_b[3], co_mark[3]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + const float fac = (slp->perc + 1.0f) / 2.0f; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float guide_size = ctrl_size - 0.5f; + const int alpha_shade = -30; + + add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); + add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBeginAtMost(GPU_PRIM_LINES, 4); + if (curr_sv->v_side[0]) { + immVertex3fv(pos, curr_sv->v_side[0]->co); + immVertex3fv(pos, curr_sv->v_co_orig); + } + if (curr_sv->v_side[1]) { + immVertex3fv(pos, curr_sv->v_side[1]->co); + immVertex3fv(pos, curr_sv->v_co_orig); + } + immEnd(); + + immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); + GPU_point_size(ctrl_size); + immBegin(GPU_PRIM_POINTS, 1); + if (slp->flipped) { + if (curr_sv->v_side[1]) + immVertex3fv(pos, curr_sv->v_side[1]->co); + } + else { + if (curr_sv->v_side[0]) + immVertex3fv(pos, curr_sv->v_side[0]->co); + } + immEnd(); + + immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); + GPU_point_size(guide_size); + immBegin(GPU_PRIM_POINTS, 1); + interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); + immVertex3fv(pos, co_mark); + immEnd(); + } + else { + if (is_clamp == false) { + const int side_index = sld->curr_side_unclamp; + TransDataEdgeSlideVert *sv; + int i; + const int alpha_shade = -160; + + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBegin(GPU_PRIM_LINES, sld->totsv * 2); + + /* TODO(campbell): Loop over all verts */ + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + + if (!is_zero_v3(sv->dir_side[side_index])) { + copy_v3_v3(a, sv->dir_side[side_index]); + } + else { + copy_v3_v3(a, sv->dir_side[!side_index]); + } + + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->v_co_orig); + add_v3_v3(b, sv->v_co_orig); + + immVertex3fv(pos, a); + immVertex3fv(pos, b); + } + immEnd(); + } + else { + BLI_assert(0); + } + } + + immUnbindProgram(); + + GPU_matrix_pop(); + + GPU_blend(false); + + GPU_depth_test(true); + } + } } static void doEdgeSlide(TransInfo *t, float perc) { - EdgeSlideParams *slp = t->custom.mode.data; - EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - - slp->perc = perc; - - if (slp->use_even == false) { - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - if (is_clamp) { - const int side_index = (perc < 0.0f); - const float perc_final = fabsf(perc); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - EdgeSlideData *sld = tc->custom.mode.data; - TransDataEdgeSlideVert *sv = sld->sv; - for (int i = 0; i < sld->totsv; i++, sv++) { - madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final); - } - sld->curr_side_unclamp = side_index; - } - } - else { - const float perc_init = fabsf(perc) * ((sld_active->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1); - const int side_index = sld_active->curr_side_unclamp; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - EdgeSlideData *sld = tc->custom.mode.data; - TransDataEdgeSlideVert *sv = sld->sv; - for (int i = 0; i < sld->totsv; i++, sv++) { - float dir_flip[3]; - float perc_final = perc_init; - if (!is_zero_v3(sv->dir_side[side_index])) { - copy_v3_v3(dir_flip, sv->dir_side[side_index]); - } - else { - copy_v3_v3(dir_flip, sv->dir_side[!side_index]); - perc_final *= -1; - } - madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final); - } - } - } - } - else { - /** - * Implementation note, even mode ignores the starting positions and uses only the - * a/b verts, this could be changed/improved so the distance is still met but the verts are moved along - * their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell - * - * \note len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1]) - * is the same as the distance between the original vert locations, same goes for the lines below. - */ - TransDataEdgeSlideVert *curr_sv = &sld_active->sv[sld_active->curr_sv_index]; - const float curr_length_perc = curr_sv->edge_len * (((slp->flipped ? perc : -perc) + 1.0f) / 2.0f); - - float co_a[3]; - float co_b[3]; - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - EdgeSlideData *sld = tc->custom.mode.data; - TransDataEdgeSlideVert *sv = sld->sv; - for (int i = 0; i < sld->totsv; i++, sv++) { - if (sv->edge_len > FLT_EPSILON) { - const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len; - - add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]); - add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]); - - if (slp->flipped) { - interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac); - } - else { - interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac); - } - } - } - } - } + EdgeSlideParams *slp = t->custom.mode.data; + EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; + + slp->perc = perc; + + if (slp->use_even == false) { + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (is_clamp) { + const int side_index = (perc < 0.0f); + const float perc_final = fabsf(perc); + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + EdgeSlideData *sld = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = sld->sv; + for (int i = 0; i < sld->totsv; i++, sv++) { + madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final); + } + sld->curr_side_unclamp = side_index; + } + } + else { + const float perc_init = fabsf(perc) * + ((sld_active->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1); + const int side_index = sld_active->curr_side_unclamp; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + EdgeSlideData *sld = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = sld->sv; + for (int i = 0; i < sld->totsv; i++, sv++) { + float dir_flip[3]; + float perc_final = perc_init; + if (!is_zero_v3(sv->dir_side[side_index])) { + copy_v3_v3(dir_flip, sv->dir_side[side_index]); + } + else { + copy_v3_v3(dir_flip, sv->dir_side[!side_index]); + perc_final *= -1; + } + madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final); + } + } + } + } + else { + /** + * Implementation note, even mode ignores the starting positions and uses only the + * a/b verts, this could be changed/improved so the distance is still met but the verts are moved along + * their original path (which may not be straight), however how it works now is OK and matches 2.4x - Campbell + * + * \note len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1]) + * is the same as the distance between the original vert locations, same goes for the lines below. + */ + TransDataEdgeSlideVert *curr_sv = &sld_active->sv[sld_active->curr_sv_index]; + const float curr_length_perc = curr_sv->edge_len * + (((slp->flipped ? perc : -perc) + 1.0f) / 2.0f); + + float co_a[3]; + float co_b[3]; + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + EdgeSlideData *sld = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = sld->sv; + for (int i = 0; i < sld->totsv; i++, sv++) { + if (sv->edge_len > FLT_EPSILON) { + const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len; + + add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]); + add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]); + + if (slp->flipped) { + interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac); + } + else { + interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac); + } + } + } + } + } } static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; - size_t ofs = 0; - float final; - EdgeSlideParams *slp = t->custom.mode.data; - bool flipped = slp->flipped; - bool use_even = slp->use_even; - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); - - final = t->values[0]; - - snapGridIncrement(t, &final); - - /* only do this so out of range values are not displayed */ - if (is_constrained) { - CLAMP(final, -1.0f, 1.0f); - } - - applyNumInput(&t->num, &final); - - t->values[0] = final; - - /* header string */ - ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Edge Slide: "), sizeof(str) - ofs); - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs); - } - else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final); - } - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even)); - if (use_even) { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); - } - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); - /* done with header string */ - - /* do stuff here */ - doEdgeSlide(t, final); - - recalcData(t); - - ED_area_status_text(t->sa, str); + char str[UI_MAX_DRAW_STR]; + size_t ofs = 0; + float final; + EdgeSlideParams *slp = t->custom.mode.data; + bool flipped = slp->flipped; + bool use_even = slp->use_even; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); + + final = t->values[0]; + + snapGridIncrement(t, &final); + + /* only do this so out of range values are not displayed */ + if (is_constrained) { + CLAMP(final, -1.0f, 1.0f); + } + + applyNumInput(&t->num, &final); + + t->values[0] = final; + + /* header string */ + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Edge Slide: "), sizeof(str) - ofs); + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + outputNumInput(&(t->num), c, &t->scene->unit); + ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs); + } + else { + ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final); + } + ofs += BLI_snprintf( + str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even)); + if (use_even) { + ofs += BLI_snprintf( + str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); + } + ofs += BLI_snprintf( + str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); + /* done with header string */ + + /* do stuff here */ + doEdgeSlide(t, final); + + recalcData(t); + + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Vert Slide) */ @@ -7813,35 +7994,35 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) static void calcVertSlideCustomPoints(struct TransInfo *t) { - VertSlideParams *slp = t->custom.mode.data; - VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; + VertSlideParams *slp = t->custom.mode.data; + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; + TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; - const float *co_orig_3d = sv->co_orig_3d; - const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr]; + const float *co_orig_3d = sv->co_orig_3d; + const float *co_curr_3d = sv->co_link_orig_3d[sv->co_link_curr]; - float co_curr_2d[2], co_orig_2d[2]; + float co_curr_2d[2], co_orig_2d[2]; - int mval_ofs[2], mval_start[2], mval_end[2]; + int mval_ofs[2], mval_start[2], mval_end[2]; - ED_view3d_project_float_v2_m4(t->ar, co_orig_3d, co_orig_2d, sld->proj_mat); - ED_view3d_project_float_v2_m4(t->ar, co_curr_3d, co_curr_2d, sld->proj_mat); + ED_view3d_project_float_v2_m4(t->ar, co_orig_3d, co_orig_2d, sld->proj_mat); + ED_view3d_project_float_v2_m4(t->ar, co_curr_3d, co_curr_2d, sld->proj_mat); - ARRAY_SET_ITEMS(mval_ofs, t->mouse.imval[0] - co_orig_2d[0], t->mouse.imval[1] - co_orig_2d[1]); - ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]); - ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]); + ARRAY_SET_ITEMS(mval_ofs, t->mouse.imval[0] - co_orig_2d[0], t->mouse.imval[1] - co_orig_2d[1]); + ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]); + ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]); - if (slp->flipped && slp->use_even) { - setCustomPoints(t, &t->mouse, mval_start, mval_end); - } - else { - setCustomPoints(t, &t->mouse, mval_end, mval_start); - } + if (slp->flipped && slp->use_even) { + setCustomPoints(t, &t->mouse, mval_start, mval_end); + } + else { + setCustomPoints(t, &t->mouse, mval_end, mval_start); + } - /* setCustomPoints isn't normally changing as the mouse moves, - * in this case apply mouse input immediately so we don't refresh - * with the value from the previous points */ - applyMouseInput(t, &t->mouse, t->mval, t->values); + /* setCustomPoints isn't normally changing as the mouse moves, + * in this case apply mouse input immediately so we don't refresh + * with the value from the previous points */ + applyMouseInput(t, &t->mouse, t->mval, t->values); } /** @@ -7849,27 +8030,27 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) */ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) { - /* Active object may have no selected vertices. */ - VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - float mval_fl[2] = {UNPACK2(mval)}; - TransDataVertSlideVert *sv; + /* Active object may have no selected vertices. */ + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; + float mval_fl[2] = {UNPACK2(mval)}; + TransDataVertSlideVert *sv; - /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */ - float dist_sq = 0.0f; - float dist_min_sq = FLT_MAX; - int i; + /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */ + float dist_sq = 0.0f; + float dist_min_sq = FLT_MAX; + int i; - for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { - float co_2d[2]; + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + float co_2d[2]; - ED_view3d_project_float_v2_m4(t->ar, sv->co_orig_3d, co_2d, sld->proj_mat); + ED_view3d_project_float_v2_m4(t->ar, sv->co_orig_3d, co_2d, sld->proj_mat); - dist_sq = len_squared_v2v2(mval_fl, co_2d); - if (dist_sq < dist_min_sq) { - dist_min_sq = dist_sq; - sld->curr_sv_index = i; - } - } + dist_sq = len_squared_v2v2(mval_fl, co_2d); + if (dist_sq < dist_min_sq) { + dist_min_sq = dist_sq; + sld->curr_sv_index = i; + } + } } /** @@ -7877,530 +8058,547 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) */ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]) { - VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - float imval_fl[2] = {UNPACK2(t->mouse.imval)}; - float mval_fl[2] = {UNPACK2(mval)}; + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; + float imval_fl[2] = {UNPACK2(t->mouse.imval)}; + float mval_fl[2] = {UNPACK2(mval)}; - float dir[3]; - TransDataVertSlideVert *sv; - int i; + float dir[3]; + TransDataVertSlideVert *sv; + int i; - /* note: we could save a matrix-multiply for each vertex - * by finding the closest edge in local-space. - * However this skews the outcome with non-uniform-scale. */ + /* note: we could save a matrix-multiply for each vertex + * by finding the closest edge in local-space. + * However this skews the outcome with non-uniform-scale. */ - /* first get the direction of the original mouse position */ - sub_v2_v2v2(dir, imval_fl, mval_fl); - ED_view3d_win_to_delta(t->ar, dir, dir, t->zfac); - normalize_v3(dir); + /* first get the direction of the original mouse position */ + sub_v2_v2v2(dir, imval_fl, mval_fl); + ED_view3d_win_to_delta(t->ar, dir, dir, t->zfac); + normalize_v3(dir); - for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { - if (sv->co_link_tot > 1) { - float dir_dot_best = -FLT_MAX; - int co_link_curr_best = -1; - int j; + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + if (sv->co_link_tot > 1) { + float dir_dot_best = -FLT_MAX; + int co_link_curr_best = -1; + int j; - for (j = 0; j < sv->co_link_tot; j++) { - float tdir[3]; - float dir_dot; + for (j = 0; j < sv->co_link_tot; j++) { + float tdir[3]; + float dir_dot; - sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]); - mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir); - project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]); + sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]); + mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir); + project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]); - normalize_v3(tdir); - dir_dot = dot_v3v3(dir, tdir); - if (dir_dot > dir_dot_best) { - dir_dot_best = dir_dot; - co_link_curr_best = j; - } - } + normalize_v3(tdir); + dir_dot = dot_v3v3(dir, tdir); + if (dir_dot > dir_dot_best) { + dir_dot_best = dir_dot; + co_link_curr_best = j; + } + } - if (co_link_curr_best != -1) { - sv->co_link_curr = co_link_curr_best; - } - } - } + if (co_link_curr_best != -1) { + sv->co_link_curr = co_link_curr_best; + } + } + } } static bool createVertSlideVerts(TransInfo *t, TransDataContainer *tc) { - BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); - BMesh *bm = em->bm; - BMIter iter; - BMIter eiter; - BMEdge *e; - BMVert *v; - TransDataVertSlideVert *sv_array; - VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); - int j; - - slide_origdata_init_flag(t, tc, &sld->orig_data); - - sld->curr_sv_index = 0; - - j = 0; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - bool ok = false; - if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) { - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - ok = true; - break; - } - } - } - - if (ok) { - BM_elem_flag_enable(v, BM_ELEM_TAG); - j += 1; - } - else { - BM_elem_flag_disable(v, BM_ELEM_TAG); - } - } - - if (!j) { - MEM_freeN(sld); - return false; - } - - sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array"); - - j = 0; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_TAG)) { - int k; - sv_array[j].v = v; - copy_v3_v3(sv_array[j].co_orig_3d, v->co); - - k = 0; - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - k++; - } - } - - sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__); - sv_array[j].co_link_tot = k; - - k = 0; - BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - BMVert *v_other = BM_edge_other_vert(e, v); - copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co); - k++; - } - } - j++; - } - } - - sld->sv = sv_array; - sld->totsv = j; - - bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - slide_origdata_init_data(tc, &sld->orig_data); - slide_origdata_create_data(tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); - - sld->em = em; - - tc->custom.mode.data = sld; - - /* most likely will be set below */ - unit_m4(sld->proj_mat); - - if (t->spacetype == SPACE_VIEW3D) { - /* view vars */ - RegionView3D *rv3d = NULL; - ARegion *ar = t->ar; - - rv3d = ar ? ar->regiondata : NULL; - if (rv3d) { - ED_view3d_ob_project_mat_get(rv3d, tc->obedit, sld->proj_mat); - } - } - - /* XXX, calc vert slide across all objects */ - if (tc == t->data_container) { - calcVertSlideMouseActiveVert(t, t->mval); - calcVertSlideMouseActiveEdges(t, t->mval); - } - - return true; + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + BMIter iter; + BMIter eiter; + BMEdge *e; + BMVert *v; + TransDataVertSlideVert *sv_array; + VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + int j; + + slide_origdata_init_flag(t, tc, &sld->orig_data); + + sld->curr_sv_index = 0; + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + bool ok = false; + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) { + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + ok = true; + break; + } + } + } + + if (ok) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + j += 1; + } + else { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + } + + if (!j) { + MEM_freeN(sld); + return false; + } + + sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array"); + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + int k; + sv_array[j].v = v; + copy_v3_v3(sv_array[j].co_orig_3d, v->co); + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + k++; + } + } + + sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, + __func__); + sv_array[j].co_link_tot = k; + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + BMVert *v_other = BM_edge_other_vert(e, v); + copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co); + k++; + } + } + j++; + } + } + + sld->sv = sv_array; + sld->totsv = j; + + bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + slide_origdata_init_data(tc, &sld->orig_data); + slide_origdata_create_data( + tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); + + sld->em = em; + + tc->custom.mode.data = sld; + + /* most likely will be set below */ + unit_m4(sld->proj_mat); + + if (t->spacetype == SPACE_VIEW3D) { + /* view vars */ + RegionView3D *rv3d = NULL; + ARegion *ar = t->ar; + + rv3d = ar ? ar->regiondata : NULL; + if (rv3d) { + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, sld->proj_mat); + } + } + + /* XXX, calc vert slide across all objects */ + if (tc == t->data_container) { + calcVertSlideMouseActiveVert(t, t->mval); + calcVertSlideMouseActiveEdges(t, t->mval); + } + + return true; } void projectVertSlideData(TransInfo *t, bool is_final) { - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - VertSlideData *sld = tc->custom.mode.data; - SlideOrigData *sod = &sld->orig_data; - if (sod->use_origfaces == true) { - slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final); - } - } + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + VertSlideData *sld = tc->custom.mode.data; + SlideOrigData *sod = &sld->orig_data; + if (sod->use_origfaces == true) { + slide_origdata_interp_data(tc->obedit, + sod, + (TransDataGenericSlideVert *)sld->sv, + sizeof(*sld->sv), + sld->totsv, + is_final); + } + } } void freeVertSlideTempFaces(VertSlideData *sld) { - slide_origdata_free_date(&sld->orig_data); + slide_origdata_free_date(&sld->orig_data); } -void freeVertSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data) +void freeVertSlideVerts(TransInfo *UNUSED(t), + TransDataContainer *UNUSED(tc), + TransCustomData *custom_data) { - VertSlideData *sld = custom_data->data; + VertSlideData *sld = custom_data->data; - if (!sld) - return; + if (!sld) + return; - freeVertSlideTempFaces(sld); + freeVertSlideTempFaces(sld); - bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); + bmesh_edit_end(sld->em->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - if (sld->totsv > 0) { - TransDataVertSlideVert *sv = sld->sv; - int i = 0; - for (i = 0; i < sld->totsv; i++, sv++) { - MEM_freeN(sv->co_link_orig_3d); - } - } + if (sld->totsv > 0) { + TransDataVertSlideVert *sv = sld->sv; + int i = 0; + for (i = 0; i < sld->totsv; i++, sv++) { + MEM_freeN(sv->co_link_orig_3d); + } + } - MEM_freeN(sld->sv); - MEM_freeN(sld); + MEM_freeN(sld->sv); + MEM_freeN(sld); - custom_data->data = NULL; + custom_data->data = NULL; } static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp) { - t->mode = TFM_VERT_SLIDE; - t->transform = applyVertSlide; - t->handleEvent = handleEventVertSlide; + t->mode = TFM_VERT_SLIDE; + t->transform = applyVertSlide; + t->handleEvent = handleEventVertSlide; - { - VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); - slp->use_even = use_even; - slp->flipped = flipped; - slp->perc = 0.0f; + { + VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); + slp->use_even = use_even; + slp->flipped = flipped; + slp->perc = 0.0f; - if (!use_clamp) { - t->flag |= T_ALT_TRANSFORM; - } + if (!use_clamp) { + t->flag |= T_ALT_TRANSFORM; + } - t->custom.mode.data = slp; - t->custom.mode.use_free = true; - } + t->custom.mode.data = slp; + t->custom.mode.use_free = true; + } - bool ok = false; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - ok |= createVertSlideVerts(t, tc); - VertSlideData *sld = tc->custom.mode.data; - if (sld) { - tc->custom.mode.free_cb = freeVertSlideVerts; - } - } + bool ok = false; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + ok |= createVertSlideVerts(t, tc); + VertSlideData *sld = tc->custom.mode.data; + if (sld) { + tc->custom.mode.free_cb = freeVertSlideVerts; + } + } - if (ok == false) { - t->state = TRANS_CANCEL; - return; - } + if (ok == false) { + t->state = TRANS_CANCEL; + return; + } - /* set custom point first if you want value to be initialized by init */ - calcVertSlideCustomPoints(t); - initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + /* set custom point first if you want value to be initialized by init */ + calcVertSlideCustomPoints(t); + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 0.1f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; - t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } static void initVertSlide(TransInfo *t) { - initVertSlide_ex(t, false, false, true); + initVertSlide_ex(t, false, false, true); } static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event) { - if (t->mode == TFM_VERT_SLIDE) { - VertSlideParams *slp = t->custom.mode.data; - - if (slp) { - switch (event->type) { - case EKEY: - if (event->val == KM_PRESS) { - slp->use_even = !slp->use_even; - if (slp->flipped) { - calcVertSlideCustomPoints(t); - } - return TREDRAW_HARD; - } - break; - case FKEY: - if (event->val == KM_PRESS) { - slp->flipped = !slp->flipped; - calcVertSlideCustomPoints(t); - return TREDRAW_HARD; - } - break; - case CKEY: - /* use like a modifier key */ - if (event->val == KM_PRESS) { - t->flag ^= T_ALT_TRANSFORM; - calcVertSlideCustomPoints(t); - return TREDRAW_HARD; - } - break; + if (t->mode == TFM_VERT_SLIDE) { + VertSlideParams *slp = t->custom.mode.data; + + if (slp) { + switch (event->type) { + case EKEY: + if (event->val == KM_PRESS) { + slp->use_even = !slp->use_even; + if (slp->flipped) { + calcVertSlideCustomPoints(t); + } + return TREDRAW_HARD; + } + break; + case FKEY: + if (event->val == KM_PRESS) { + slp->flipped = !slp->flipped; + calcVertSlideCustomPoints(t); + return TREDRAW_HARD; + } + break; + case CKEY: + /* use like a modifier key */ + if (event->val == KM_PRESS) { + t->flag ^= T_ALT_TRANSFORM; + calcVertSlideCustomPoints(t); + return TREDRAW_HARD; + } + break; #if 0 - case EVT_MODAL_MAP: - switch (event->val) { - case TFM_MODAL_EDGESLIDE_DOWN: - sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; - break; - case TFM_MODAL_EDGESLIDE_UP: - sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; - break; - } - break; + case EVT_MODAL_MAP: + switch (event->val) { + case TFM_MODAL_EDGESLIDE_DOWN: + sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; + break; + case TFM_MODAL_EDGESLIDE_UP: + sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; + break; + } + break; #endif - case MOUSEMOVE: - { - /* don't recalculate the best edge */ - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - if (is_clamp) { - calcVertSlideMouseActiveEdges(t, event->mval); - } - calcVertSlideCustomPoints(t); - break; - } - default: - break; - } - } - } - return TREDRAW_NOTHING; + case MOUSEMOVE: { + /* don't recalculate the best edge */ + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (is_clamp) { + calcVertSlideMouseActiveEdges(t, event->mval); + } + calcVertSlideCustomPoints(t); + break; + } + default: + break; + } + } + } + return TREDRAW_NOTHING; } static void drawVertSlide(TransInfo *t) { - if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) { - const VertSlideParams *slp = t->custom.mode.data; - VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - - /* Non-Prop mode */ - { - TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - TransDataVertSlideVert *sv; - const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; - const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; - const int alpha_shade = -160; - int i; - - GPU_depth_test(false); - - GPU_blend(true); - GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) { + const VertSlideParams *slp = t->custom.mode.data; + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + + /* Non-Prop mode */ + { + TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataVertSlideVert *sv; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + const int alpha_shade = -160; + int i; + + GPU_depth_test(false); - GPU_matrix_push(); - GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + GPU_blend(true); + GPU_blend_set_func_separate( + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_line_width(line_size); + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_line_width(line_size); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + const uint shdr_pos = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBegin(GPU_PRIM_LINES, sld->totsv * 2); - if (is_clamp) { - sv = sld->sv; - for (i = 0; i < sld->totsv; i++, sv++) { - immVertex3fv(shdr_pos, sv->co_orig_3d); - immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]); - } - } - else { - sv = sld->sv; - for (i = 0; i < sld->totsv; i++, sv++) { - float a[3], b[3]; - sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); - mul_v3_fl(a, 100.0f); - negate_v3_v3(b, a); - add_v3_v3(a, sv->co_orig_3d); - add_v3_v3(b, sv->co_orig_3d); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - immVertex3fv(shdr_pos, a); - immVertex3fv(shdr_pos, b); - } - } - immEnd(); + immBegin(GPU_PRIM_LINES, sld->totsv * 2); + if (is_clamp) { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + immVertex3fv(shdr_pos, sv->co_orig_3d); + immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]); + } + } + else { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->co_orig_3d); + add_v3_v3(b, sv->co_orig_3d); - GPU_point_size(ctrl_size); + immVertex3fv(shdr_pos, a); + immVertex3fv(shdr_pos, b); + } + } + immEnd(); - immBegin(GPU_PRIM_POINTS, 1); - immVertex3fv(shdr_pos, (slp->flipped && slp->use_even) ? - curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : - curr_sv->co_orig_3d); - immEnd(); + GPU_point_size(ctrl_size); - immUnbindProgram(); + immBegin(GPU_PRIM_POINTS, 1); + immVertex3fv(shdr_pos, + (slp->flipped && slp->use_even) ? + curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : + curr_sv->co_orig_3d); + immEnd(); - /* direction from active vertex! */ - if ((t->mval[0] != t->mouse.imval[0]) || - (t->mval[1] != t->mouse.imval[1])) - { - float zfac; - float mval_ofs[2]; - float co_orig_3d[3]; - float co_dest_3d[3]; + immUnbindProgram(); - mval_ofs[0] = t->mval[0] - t->mouse.imval[0]; - mval_ofs[1] = t->mval[1] - t->mouse.imval[1]; + /* direction from active vertex! */ + if ((t->mval[0] != t->mouse.imval[0]) || (t->mval[1] != t->mouse.imval[1])) { + float zfac; + float mval_ofs[2]; + float co_orig_3d[3]; + float co_dest_3d[3]; - mul_v3_m4v3(co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d); - zfac = ED_view3d_calc_zfac(t->ar->regiondata, co_orig_3d, NULL); + mval_ofs[0] = t->mval[0] - t->mouse.imval[0]; + mval_ofs[1] = t->mval[1] - t->mouse.imval[1]; - ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac); + mul_v3_m4v3( + co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d); + zfac = ED_view3d_calc_zfac(t->ar->regiondata, co_orig_3d, NULL); - invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d); + ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac); - add_v3_v3(co_dest_3d, curr_sv->co_orig_3d); + invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, + TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d); - GPU_line_width(1.0f); + add_v3_v3(co_dest_3d, curr_sv->co_orig_3d); - immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); + GPU_line_width(1.0f); - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f); - immUniform1f("dash_width", 6.0f); - immUniform1f("dash_factor", 0.5f); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - immBegin(GPU_PRIM_LINES, 2); - immVertex3fv(shdr_pos, curr_sv->co_orig_3d); - immVertex3fv(shdr_pos, co_dest_3d); - immEnd(); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GPU_PRIM_LINES, 2); + immVertex3fv(shdr_pos, curr_sv->co_orig_3d); + immVertex3fv(shdr_pos, co_dest_3d); + immEnd(); - immUnbindProgram(); - } + immUnbindProgram(); + } - GPU_matrix_pop(); + GPU_matrix_pop(); - GPU_depth_test(true); - } - } + GPU_depth_test(true); + } + } } static void doVertSlide(TransInfo *t, float perc) { - VertSlideParams *slp = t->custom.mode.data; - - slp->perc = perc; - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - VertSlideData *sld = tc->custom.mode.data; - TransDataVertSlideVert *svlist = sld->sv, *sv; - int i; - - sv = svlist; - - if (slp->use_even == false) { - for (i = 0; i < sld->totsv; i++, sv++) { - interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc); - } - } - else { - TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index]; - const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, sv_curr->co_link_orig_3d[sv_curr->co_link_curr]); - const float tperc = perc * edge_len_curr; - - for (i = 0; i < sld->totsv; i++, sv++) { - float edge_len; - float dir[3]; - - sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); - edge_len = normalize_v3(dir); - - if (edge_len > FLT_EPSILON) { - if (slp->flipped) { - madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); - } - else { - madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc); - } - } - else { - copy_v3_v3(sv->v->co, sv->co_orig_3d); - } - } - } - } + VertSlideParams *slp = t->custom.mode.data; + + slp->perc = perc; + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + VertSlideData *sld = tc->custom.mode.data; + TransDataVertSlideVert *svlist = sld->sv, *sv; + int i; + + sv = svlist; + + if (slp->use_even == false) { + for (i = 0; i < sld->totsv; i++, sv++) { + interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc); + } + } + else { + TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index]; + const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, + sv_curr->co_link_orig_3d[sv_curr->co_link_curr]); + const float tperc = perc * edge_len_curr; + + for (i = 0; i < sld->totsv; i++, sv++) { + float edge_len; + float dir[3]; + + sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + edge_len = normalize_v3(dir); + + if (edge_len > FLT_EPSILON) { + if (slp->flipped) { + madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); + } + else { + madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc); + } + } + else { + copy_v3_v3(sv->v->co, sv->co_orig_3d); + } + } + } + } } static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; - size_t ofs = 0; - float final; - VertSlideParams *slp = t->custom.mode.data; - const bool flipped = slp->flipped; - const bool use_even = slp->use_even; - const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); - - final = t->values[0]; - - snapGridIncrement(t, &final); - - /* only do this so out of range values are not displayed */ - if (is_constrained) { - CLAMP(final, 0.0f, 1.0f); - } - - applyNumInput(&t->num, &final); - - t->values[0] = final; - - /* header string */ - ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), sizeof(str) - ofs); - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); - ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs); - } - else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final); - } - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even)); - if (use_even) { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); - } - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); - /* done with header string */ - - /* do stuff here */ - doVertSlide(t, final); - - recalcData(t); - - ED_area_status_text(t->sa, str); + char str[UI_MAX_DRAW_STR]; + size_t ofs = 0; + float final; + VertSlideParams *slp = t->custom.mode.data; + const bool flipped = slp->flipped; + const bool use_even = slp->use_even; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); + + final = t->values[0]; + + snapGridIncrement(t, &final); + + /* only do this so out of range values are not displayed */ + if (is_constrained) { + CLAMP(final, 0.0f, 1.0f); + } + + applyNumInput(&t->num, &final); + + t->values[0] = final; + + /* header string */ + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), sizeof(str) - ofs); + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + outputNumInput(&(t->num), c, &t->scene->unit); + ofs += BLI_strncpy_rlen(str + ofs, &c[0], sizeof(str) - ofs); + } + else { + ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f ", final); + } + ofs += BLI_snprintf( + str + ofs, sizeof(str) - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even)); + if (use_even) { + ofs += BLI_snprintf( + str + ofs, sizeof(str) - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); + } + ofs += BLI_snprintf( + str + ofs, sizeof(str) - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); + /* done with header string */ + + /* do stuff here */ + doVertSlide(t, final); + + recalcData(t); + + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (EditBone Roll) */ @@ -8409,72 +8607,72 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) static void initBoneRoll(TransInfo *t) { - t->mode = TFM_BONE_ROLL; - t->transform = applyBoneRoll; + t->mode = TFM_BONE_ROLL; + t->transform = applyBoneRoll; - initMouseInputMode(t, &t->mouse, INPUT_ANGLE); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = DEG2RAD(5.0); - t->snap[2] = DEG2RAD(1.0); + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); - t->num.unit_type[0] = B_UNIT_ROTATION; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; - t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) { - int i; - char str[UI_MAX_DRAW_STR]; + int i; + char str[UI_MAX_DRAW_STR]; - float final; + float final; - final = t->values[0]; + final = t->values[0]; - snapGridIncrement(t, &final); + snapGridIncrement(t, &final); - applyNumInput(&t->num, &final); + applyNumInput(&t->num, &final); - t->values[0] = final; + t->values[0] = final; - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, &t->scene->unit); + outputNumInput(&(t->num), c, &t->scene->unit); - BLI_snprintf(str, sizeof(str), IFACE_("Roll: %s"), &c[0]); - } - else { - BLI_snprintf(str, sizeof(str), IFACE_("Roll: %.2f"), RAD2DEGF(final)); - } + BLI_snprintf(str, sizeof(str), IFACE_("Roll: %s"), &c[0]); + } + else { + BLI_snprintf(str, sizeof(str), IFACE_("Roll: %.2f"), RAD2DEGF(final)); + } - /* set roll values */ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + /* set roll values */ + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - *(td->val) = td->ival - final; - } - } + *(td->val) = td->ival - final; + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Bake-Time) */ @@ -8483,89 +8681,91 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) static void initBakeTime(TransInfo *t) { - t->transform = applyBakeTime; - initMouseInputMode(t, &t->mouse, INPUT_NONE); + t->transform = applyBakeTime; + initMouseInputMode(t, &t->mouse, INPUT_NONE); - t->idx_max = 0; - t->num.idx_max = 0; - t->snap[0] = 0.0f; - t->snap[1] = 1.0f; - t->snap[2] = t->snap[1] * 0.1f; + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 1.0f; + t->snap[2] = t->snap[1] * 0.1f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; /* Don't think this uses units? */ + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; /* Don't think this uses units? */ } static void applyBakeTime(TransInfo *t, const int mval[2]) { - float time; - int i; - char str[UI_MAX_DRAW_STR]; + float time; + int i; + char str[UI_MAX_DRAW_STR]; - float fac = 0.1f; + float fac = 0.1f; - /* XXX, disable precision for now, - * this isn't even accessible by the user */ + /* XXX, disable precision for now, + * this isn't even accessible by the user */ #if 0 - if (t->mouse.precision) { - /* calculate ratio for shiftkey pos, and for total, and blend these for precision */ - time = (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac; - time += 0.1f * ((float)(t->center2d[0] * fac - mval[0]) - time); - } - else + if (t->mouse.precision) { + /* calculate ratio for shiftkey pos, and for total, and blend these for precision */ + time = (float)(t->center2d[0] - t->mouse.precision_mval[0]) * fac; + time += 0.1f * ((float)(t->center2d[0] * fac - mval[0]) - time); + } + else #endif - { - time = (float)(t->center2d[0] - mval[0]) * fac; - } - - snapGridIncrement(t, &time); - - applyNumInput(&t->num, &time); - - /* header print for NumInput */ - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; - - outputNumInput(&(t->num), c, &t->scene->unit); - - if (time >= 0.0f) - BLI_snprintf(str, sizeof(str), IFACE_("Time: +%s %s"), c, t->proptext); - else - BLI_snprintf(str, sizeof(str), IFACE_("Time: %s %s"), c, t->proptext); - } - else { - /* default header print */ - if (time >= 0.0f) - BLI_snprintf(str, sizeof(str), IFACE_("Time: +%.3f %s"), time, t->proptext); - else - BLI_snprintf(str, sizeof(str), IFACE_("Time: %.3f %s"), time, t->proptext); - } - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; - - if (td->val) { - *td->val = td->ival + time * td->factor; - if (td->ext->size && *td->val < *td->ext->size) *td->val = *td->ext->size; - if (td->ext->quat && *td->val > *td->ext->quat) *td->val = *td->ext->quat; - } - } - } - - recalcData(t); - - ED_area_status_text(t->sa, str); + { + time = (float)(t->center2d[0] - mval[0]) * fac; + } + + snapGridIncrement(t, &time); + + applyNumInput(&t->num, &time); + + /* header print for NumInput */ + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + + outputNumInput(&(t->num), c, &t->scene->unit); + + if (time >= 0.0f) + BLI_snprintf(str, sizeof(str), IFACE_("Time: +%s %s"), c, t->proptext); + else + BLI_snprintf(str, sizeof(str), IFACE_("Time: %s %s"), c, t->proptext); + } + else { + /* default header print */ + if (time >= 0.0f) + BLI_snprintf(str, sizeof(str), IFACE_("Time: +%.3f %s"), time, t->proptext); + else + BLI_snprintf(str, sizeof(str), IFACE_("Time: %.3f %s"), time, t->proptext); + } + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; + + if (td->flag & TD_SKIP) + continue; + + if (td->val) { + *td->val = td->ival + time * td->factor; + if (td->ext->size && *td->val < *td->ext->size) + *td->val = *td->ext->size; + if (td->ext->quat && *td->val > *td->ext->quat) + *td->val = *td->ext->quat; + } + } + } + + recalcData(t); + + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Mirror) */ @@ -8574,85 +8774,86 @@ static void applyBakeTime(TransInfo *t, const int mval[2]) static void initMirror(TransInfo *t) { - t->transform = applyMirror; - initMouseInputMode(t, &t->mouse, INPUT_NONE); + t->transform = applyMirror; + initMouseInputMode(t, &t->mouse, INPUT_NONE); - t->flag |= T_NULL_ONE; - if ((t->flag & T_EDIT) == 0) { - t->flag |= T_NO_ZERO; - } + t->flag |= T_NULL_ONE; + if ((t->flag & T_EDIT) == 0) { + t->flag |= T_NO_ZERO; + } } static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) { - float size[3], mat[3][3]; - int i; - char str[UI_MAX_DRAW_STR]; + float size[3], mat[3][3]; + int i; + char str[UI_MAX_DRAW_STR]; - /* - * OPTIMIZATION: - * This still recalcs transformation on mouse move - * while it should only recalc on constraint change - * */ + /* + * OPTIMIZATION: + * This still recalcs transformation on mouse move + * while it should only recalc on constraint change + * */ - /* if an axis has been selected */ - if (t->con.mode & CON_APPLY) { - size[0] = size[1] = size[2] = -1; + /* if an axis has been selected */ + if (t->con.mode & CON_APPLY) { + size[0] = size[1] = size[2] = -1; - size_to_mat3(mat, size); + size_to_mat3(mat, size); - if (t->con.applySize) { - t->con.applySize(t, NULL, NULL, mat); - } + if (t->con.applySize) { + t->con.applySize(t, NULL, NULL, mat); + } - BLI_snprintf(str, sizeof(str), IFACE_("Mirror%s"), t->con.text); + BLI_snprintf(str, sizeof(str), IFACE_("Mirror%s"), t->con.text); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - ElementResize(t, tc, td, mat); - } - } + ElementResize(t, tc, td, mat); + } + } - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); - } - else { - size[0] = size[1] = size[2] = 1; + ED_area_status_text(t->sa, str); + } + else { + size[0] = size[1] = size[2] = 1; - size_to_mat3(mat, size); + size_to_mat3(mat, size); - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - ElementResize(t, tc, td, mat); - } - } + ElementResize(t, tc, td, mat); + } + } - recalcData(t); + recalcData(t); - if (t->flag & T_2D_EDIT) - ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)")); - else - ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)")); - } + if (t->flag & T_2D_EDIT) + ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)")); + else + ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)")); + } } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Align) */ @@ -8661,59 +8862,58 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) static void initAlign(TransInfo *t) { - t->flag |= T_NO_CONSTRAINT; + t->flag |= T_NO_CONSTRAINT; - t->transform = applyAlign; + t->transform = applyAlign; - initMouseInputMode(t, &t->mouse, INPUT_NONE); + initMouseInputMode(t, &t->mouse, INPUT_NONE); } static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) { - float center[3]; - int i; + float center[3]; + int i; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + /* saving original center */ + copy_v3_v3(center, tc->center_local); + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float mat[3][3], invmat[3][3]; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - /* saving original center */ - copy_v3_v3(center, tc->center_local); - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float mat[3][3], invmat[3][3]; + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_NOACTION) - break; + if (td->flag & TD_SKIP) + continue; - if (td->flag & TD_SKIP) - continue; + /* around local centers */ + if (t->flag & (T_OBJECT | T_POSE)) { + copy_v3_v3(tc->center_local, td->center); + } + else { + if (t->settings->selectmode & SCE_SELECT_FACE) { + copy_v3_v3(tc->center_local, td->center); + } + } - /* around local centers */ - if (t->flag & (T_OBJECT | T_POSE)) { - copy_v3_v3(tc->center_local, td->center); - } - else { - if (t->settings->selectmode & SCE_SELECT_FACE) { - copy_v3_v3(tc->center_local, td->center); - } - } + invert_m3_m3(invmat, td->axismtx); - invert_m3_m3(invmat, td->axismtx); + mul_m3_m3m3(mat, t->spacemtx, invmat); - mul_m3_m3m3(mat, t->spacemtx, invmat); + ElementRotation(t, tc, td, mat, t->around); + } + /* restoring original center */ + copy_v3_v3(tc->center_local, center); + } - ElementRotation(t, tc, td, mat, t->around); - } - /* restoring original center */ - copy_v3_v3(tc->center_local, center); - } + recalcData(t); - recalcData(t); - - ED_area_status_text(t->sa, IFACE_("Align")); + ED_area_status_text(t->sa, IFACE_("Align")); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Sequencer Slide) */ @@ -8722,98 +8922,101 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) static void initSeqSlide(TransInfo *t) { - t->transform = applySeqSlide; + t->transform = applySeqSlide; - initMouseInputMode(t, &t->mouse, INPUT_VECTOR); + initMouseInputMode(t, &t->mouse, INPUT_VECTOR); - t->idx_max = 1; - t->num.flag = 0; - t->num.idx_max = t->idx_max; + t->idx_max = 1; + t->num.flag = 0; + t->num.idx_max = t->idx_max; - t->snap[0] = 0.0f; - t->snap[1] = floorf(t->scene->r.frs_sec / t->scene->r.frs_sec_base); - t->snap[2] = 10.0f; + t->snap[0] = 0.0f; + t->snap[1] = floorf(t->scene->r.frs_sec / t->scene->r.frs_sec_base); + t->snap[2] = 10.0f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - /* Would be nice to have a time handling in units as well - * (supporting frames in addition to "natural" time...). */ - t->num.unit_type[0] = B_UNIT_NONE; - t->num.unit_type[1] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + /* Would be nice to have a time handling in units as well + * (supporting frames in addition to "natural" time...). */ + t->num.unit_type[0] = B_UNIT_NONE; + t->num.unit_type[1] = B_UNIT_NONE; } static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRAW_STR]) { - char tvec[NUM_STR_REP_LEN * 3]; - size_t ofs = 0; + char tvec[NUM_STR_REP_LEN * 3]; + size_t ofs = 0; - if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, &t->scene->unit); - } - else { - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]); - } + if (hasNumInput(&t->num)) { + outputNumInput(&(t->num), tvec, &t->scene->unit); + } + else { + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]); + } - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); + ofs += BLI_snprintf( + str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); - if (t->keymap) { - wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); - if (kmi) { - ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); - } - } - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" or Alt) Expand to fit %s"), - WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); + if (t->keymap) { + wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); + } + } + ofs += BLI_snprintf(str + ofs, + UI_MAX_DRAW_STR - ofs, + IFACE_(" or Alt) Expand to fit %s"), + WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); } static void applySeqSlideValue(TransInfo *t, const float val[2]) { - int i; + int i; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor); - } - } + madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor); + } + } } static void applySeqSlide(TransInfo *t, const int mval[2]) { - char str[UI_MAX_DRAW_STR]; + char str[UI_MAX_DRAW_STR]; - snapSequenceBounds(t, mval); + snapSequenceBounds(t, mval); - if (t->con.mode & CON_APPLY) { - float pvec[3] = {0.0f, 0.0f, 0.0f}; - float tvec[3]; - t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec); - copy_v3_v3(t->values, tvec); - } - else { - // snapGridIncrement(t, t->values); - applyNumInput(&t->num, t->values); - } + if (t->con.mode & CON_APPLY) { + float pvec[3] = {0.0f, 0.0f, 0.0f}; + float tvec[3]; + t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec); + copy_v3_v3(t->values, tvec); + } + else { + // snapGridIncrement(t, t->values); + applyNumInput(&t->num, t->values); + } - t->values[0] = floorf(t->values[0] + 0.5f); - t->values[1] = floorf(t->values[1] + 0.5f); + t->values[0] = floorf(t->values[0] + 0.5f); + t->values[1] = floorf(t->values[1] + 0.5f); - headerSeqSlide(t, t->values, str); - applySeqSlideValue(t, t->values); + headerSeqSlide(t, t->values, str); + applySeqSlideValue(t, t->values); - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Animation Editors - Transform Utils * @@ -8829,109 +9032,109 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) // XXX these modifier checks should be keymappable static short getAnimEdit_SnapMode(TransInfo *t) { - short autosnap = SACTSNAP_OFF; + short autosnap = SACTSNAP_OFF; - if (t->spacetype == SPACE_ACTION) { - SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; + if (t->spacetype == SPACE_ACTION) { + SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; - if (saction) - autosnap = saction->autosnap; - } - else if (t->spacetype == SPACE_GRAPH) { - SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first; + if (saction) + autosnap = saction->autosnap; + } + else if (t->spacetype == SPACE_GRAPH) { + SpaceGraph *sipo = (SpaceGraph *)t->sa->spacedata.first; - if (sipo) - autosnap = sipo->autosnap; - } - else if (t->spacetype == SPACE_NLA) { - SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first; + if (sipo) + autosnap = sipo->autosnap; + } + else if (t->spacetype == SPACE_NLA) { + SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first; - if (snla) - autosnap = snla->autosnap; - } - else { - autosnap = SACTSNAP_OFF; - } + if (snla) + autosnap = snla->autosnap; + } + else { + autosnap = SACTSNAP_OFF; + } - /* toggle autosnap on/off - * - when toggling on, prefer nearest frame over 1.0 frame increments - */ - if (t->modifiers & MOD_SNAP_INVERT) { - if (autosnap) - autosnap = SACTSNAP_OFF; - else - autosnap = SACTSNAP_FRAME; - } + /* toggle autosnap on/off + * - when toggling on, prefer nearest frame over 1.0 frame increments + */ + if (t->modifiers & MOD_SNAP_INVERT) { + if (autosnap) + autosnap = SACTSNAP_OFF; + else + autosnap = SACTSNAP_FRAME; + } - return autosnap; + return autosnap; } /* This function is used by Animation Editor specific transform functions to do * the Snap Keyframe to Nearest Frame/Marker */ -static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap) -{ - /* snap key to nearest frame or second? */ - if (ELEM(autosnap, SACTSNAP_FRAME, SACTSNAP_SECOND)) { - const Scene *scene = t->scene; - const double secf = FPS; - double val; - - /* convert frame to nla-action time (if needed) */ - if (adt) - val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP); - else - val = *(td->val); - - /* do the snapping to nearest frame/second */ - if (autosnap == SACTSNAP_FRAME) { - val = floorf(val + 0.5); - } - else if (autosnap == SACTSNAP_SECOND) { - val = (float)(floor((val / secf) + 0.5) * secf); - } - - /* convert frame out of nla-action time */ - if (adt) - *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); - else - *(td->val) = val; - } - /* snap key to nearest marker? */ - else if (autosnap == SACTSNAP_MARKER) { - float val; - - /* convert frame to nla-action time (if needed) */ - if (adt) - val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP); - else - val = *(td->val); - - /* snap to nearest marker */ - // TODO: need some more careful checks for where data comes from - val = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, val); - - /* convert frame out of nla-action time */ - if (adt) - *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); - else - *(td->val) = val; - } - - /* if the handles are to be moved too (as side-effect of keyframes moving, to keep the general effect) - * offset them by the same amount so that the general angles are maintained (i.e. won't change while - * handles are free-to-roam and keyframes are snap-locked) - */ - if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { - td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival; - } - if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { - td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival; - } +static void doAnimEdit_SnapFrame( + TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap) +{ + /* snap key to nearest frame or second? */ + if (ELEM(autosnap, SACTSNAP_FRAME, SACTSNAP_SECOND)) { + const Scene *scene = t->scene; + const double secf = FPS; + double val; + + /* convert frame to nla-action time (if needed) */ + if (adt) + val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP); + else + val = *(td->val); + + /* do the snapping to nearest frame/second */ + if (autosnap == SACTSNAP_FRAME) { + val = floorf(val + 0.5); + } + else if (autosnap == SACTSNAP_SECOND) { + val = (float)(floor((val / secf) + 0.5) * secf); + } + + /* convert frame out of nla-action time */ + if (adt) + *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); + else + *(td->val) = val; + } + /* snap key to nearest marker? */ + else if (autosnap == SACTSNAP_MARKER) { + float val; + + /* convert frame to nla-action time (if needed) */ + if (adt) + val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP); + else + val = *(td->val); + + /* snap to nearest marker */ + // TODO: need some more careful checks for where data comes from + val = (float)ED_markers_find_nearest_marker_time(&t->scene->markers, val); + + /* convert frame out of nla-action time */ + if (adt) + *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); + else + *(td->val) = val; + } + + /* if the handles are to be moved too (as side-effect of keyframes moving, to keep the general effect) + * offset them by the same amount so that the general angles are maintained (i.e. won't change while + * handles are free-to-roam and keyframes are snap-locked) + */ + if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { + td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival; + } + if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { + td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival; + } } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Animation Translation) */ @@ -8940,164 +9143,165 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, static void initTimeTranslate(TransInfo *t) { - /* this tool is only really available in the Action Editor... */ - if (!ELEM(t->spacetype, SPACE_ACTION, SPACE_SEQ)) { - t->state = TRANS_CANCEL; - } + /* this tool is only really available in the Action Editor... */ + if (!ELEM(t->spacetype, SPACE_ACTION, SPACE_SEQ)) { + t->state = TRANS_CANCEL; + } - t->mode = TFM_TIME_TRANSLATE; - t->transform = applyTimeTranslate; + t->mode = TFM_TIME_TRANSLATE; + t->transform = applyTimeTranslate; - initMouseInputMode(t, &t->mouse, INPUT_NONE); + initMouseInputMode(t, &t->mouse, INPUT_NONE); - /* num-input has max of (n-1) */ - t->idx_max = 0; - t->num.flag = 0; - t->num.idx_max = t->idx_max; + /* num-input has max of (n-1) */ + t->idx_max = 0; + t->num.flag = 0; + t->num.idx_max = t->idx_max; - /* initialize snap like for everything else */ - t->snap[0] = 0.0f; - t->snap[1] = t->snap[2] = 1.0f; + /* initialize snap like for everything else */ + t->snap[0] = 0.0f; + t->snap[1] = t->snap[2] = 1.0f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - /* No time unit supporting frames currently... */ - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + /* No time unit supporting frames currently... */ + t->num.unit_type[0] = B_UNIT_NONE; } static void headerTimeTranslate(TransInfo *t, char str[UI_MAX_DRAW_STR]) { - char tvec[NUM_STR_REP_LEN * 3]; - int ofs = 0; - - /* if numeric input is active, use results from that, otherwise apply snapping to result */ - if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, &t->scene->unit); - } - else { - const Scene *scene = t->scene; - const short autosnap = getAnimEdit_SnapMode(t); - const double secf = FPS; - float val = t->values[0]; - - /* apply snapping + frame->seconds conversions */ - if (autosnap == SACTSNAP_STEP) { - /* frame step */ - val = floorf(val + 0.5f); - } - else if (autosnap == SACTSNAP_TSTEP) { - /* second step */ - val = floorf((double)val / secf + 0.5); - } - else if (autosnap == SACTSNAP_SECOND) { - /* nearest second */ - val = (float)((double)val / secf); - } - - if (autosnap == SACTSNAP_FRAME) - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val); - else if (autosnap == SACTSNAP_SECOND) - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 sec (%.4f)", (int)val, val); - else if (autosnap == SACTSNAP_TSTEP) - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", val); - else - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); - } - - ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("DeltaX: %s"), &tvec[0]); - - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); - } + char tvec[NUM_STR_REP_LEN * 3]; + int ofs = 0; + + /* if numeric input is active, use results from that, otherwise apply snapping to result */ + if (hasNumInput(&t->num)) { + outputNumInput(&(t->num), tvec, &t->scene->unit); + } + else { + const Scene *scene = t->scene; + const short autosnap = getAnimEdit_SnapMode(t); + const double secf = FPS; + float val = t->values[0]; + + /* apply snapping + frame->seconds conversions */ + if (autosnap == SACTSNAP_STEP) { + /* frame step */ + val = floorf(val + 0.5f); + } + else if (autosnap == SACTSNAP_TSTEP) { + /* second step */ + val = floorf((double)val / secf + 0.5); + } + else if (autosnap == SACTSNAP_SECOND) { + /* nearest second */ + val = (float)((double)val / secf); + } + + if (autosnap == SACTSNAP_FRAME) + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val); + else if (autosnap == SACTSNAP_SECOND) + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 sec (%.4f)", (int)val, val); + else if (autosnap == SACTSNAP_TSTEP) + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f sec", val); + else + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); + } + + ofs += BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("DeltaX: %s"), &tvec[0]); + + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf( + str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } } static void applyTimeTranslateValue(TransInfo *t) { - Scene *scene = t->scene; - int i; - - const short autosnap = getAnimEdit_SnapMode(t); - const double secf = FPS; - - float deltax, val /* , valprev */; - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - TransData2D *td2d = tc->data_2d; - /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ - for (i = 0; i < tc->data_len; i++, td++, td2d++) { - /* it is assumed that td->extra is a pointer to the AnimData, - * whose active action is where this keyframe comes from - * (this is only valid when not in NLA) - */ - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - - /* valprev = *td->val; */ /* UNUSED */ - - /* check if any need to apply nla-mapping */ - if (adt && (t->spacetype != SPACE_SEQ)) { - deltax = t->values[0]; - - if (autosnap == SACTSNAP_TSTEP) { - deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf); - } - else if (autosnap == SACTSNAP_STEP) { - deltax = floorf(deltax + 0.5f); - } - - val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); - val += deltax * td->factor; - *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); - } - else { - deltax = val = t->values[0]; - - if (autosnap == SACTSNAP_TSTEP) { - val = (float)(floor(((double)deltax / secf) + 0.5) * secf); - } - else if (autosnap == SACTSNAP_STEP) { - val = floorf(val + 0.5f); - } - - *(td->val) = td->ival + val; - } - - /* apply nearest snapping */ - doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); - } - } + Scene *scene = t->scene; + int i; + + const short autosnap = getAnimEdit_SnapMode(t); + const double secf = FPS; + + float deltax, val /* , valprev */; + + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + TransData2D *td2d = tc->data_2d; + /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ + for (i = 0; i < tc->data_len; i++, td++, td2d++) { + /* it is assumed that td->extra is a pointer to the AnimData, + * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) + */ + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + + /* valprev = *td->val; */ /* UNUSED */ + + /* check if any need to apply nla-mapping */ + if (adt && (t->spacetype != SPACE_SEQ)) { + deltax = t->values[0]; + + if (autosnap == SACTSNAP_TSTEP) { + deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf); + } + else if (autosnap == SACTSNAP_STEP) { + deltax = floorf(deltax + 0.5f); + } + + val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); + val += deltax * td->factor; + *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); + } + else { + deltax = val = t->values[0]; + + if (autosnap == SACTSNAP_TSTEP) { + val = (float)(floor(((double)deltax / secf) + 0.5) * secf); + } + else if (autosnap == SACTSNAP_STEP) { + val = floorf(val + 0.5f); + } + + *(td->val) = td->ival + val; + } + + /* apply nearest snapping */ + doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); + } + } } static void applyTimeTranslate(TransInfo *t, const int mval[2]) { - View2D *v2d = (View2D *)t->view; - char str[UI_MAX_DRAW_STR]; + View2D *v2d = (View2D *)t->view; + char str[UI_MAX_DRAW_STR]; - /* calculate translation amount from mouse movement - in 'time-grid space' */ - if (t->flag & T_MODAL) { - float cval[2], sval[2]; - UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); - UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[0], &sval[0], &sval[1]); + /* calculate translation amount from mouse movement - in 'time-grid space' */ + if (t->flag & T_MODAL) { + float cval[2], sval[2]; + UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); + UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[0], &sval[0], &sval[1]); - /* we only need to calculate effect for time (applyTimeTranslate only needs that) */ - t->values[0] = cval[0] - sval[0]; - } + /* we only need to calculate effect for time (applyTimeTranslate only needs that) */ + t->values[0] = cval[0] - sval[0]; + } - /* handle numeric-input stuff */ - t->vec[0] = t->values[0]; - applyNumInput(&t->num, &t->vec[0]); - t->values[0] = t->vec[0]; - headerTimeTranslate(t, str); + /* handle numeric-input stuff */ + t->vec[0] = t->values[0]; + applyNumInput(&t->num, &t->vec[0]); + t->values[0] = t->vec[0]; + headerTimeTranslate(t, str); - applyTimeTranslateValue(t); + applyTimeTranslateValue(t); - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Animation Time Slide) */ @@ -9106,188 +9310,190 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2]) static void initTimeSlide(TransInfo *t) { - /* this tool is only really available in the Action Editor... */ - if (t->spacetype == SPACE_ACTION) { - SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; - - /* set flag for drawing stuff */ - saction->flag |= SACTION_MOVING; - } - else { - t->state = TRANS_CANCEL; - } - - - t->mode = TFM_TIME_SLIDE; - t->transform = applyTimeSlide; - - initMouseInputMode(t, &t->mouse, INPUT_NONE); - - { - Scene *scene = t->scene; - float *range; - t->custom.mode.data = range = MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max"); - t->custom.mode.use_free = true; - - float min = 999999999.0f, max = -999999999.0f; - int i; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - float val = *(td->val); - - /* strip/action time to global (mapped) time */ - if (adt) - val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP); - - if (min > val) min = val; - if (max < val) max = val; - } - } - - if (min == max) { - /* just use the current frame ranges */ - min = (float)PSFRA; - max = (float)PEFRA; - } - - range[0] = min; - range[1] = max; - } - - /* num-input has max of (n-1) */ - t->idx_max = 0; - t->num.flag = 0; - t->num.idx_max = t->idx_max; - - /* initialize snap like for everything else */ - t->snap[0] = 0.0f; - t->snap[1] = t->snap[2] = 1.0f; - - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - /* No time unit supporting frames currently... */ - t->num.unit_type[0] = B_UNIT_NONE; + /* this tool is only really available in the Action Editor... */ + if (t->spacetype == SPACE_ACTION) { + SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; + + /* set flag for drawing stuff */ + saction->flag |= SACTION_MOVING; + } + else { + t->state = TRANS_CANCEL; + } + + t->mode = TFM_TIME_SLIDE; + t->transform = applyTimeSlide; + + initMouseInputMode(t, &t->mouse, INPUT_NONE); + + { + Scene *scene = t->scene; + float *range; + t->custom.mode.data = range = MEM_mallocN(sizeof(float[2]), "TimeSlide Min/Max"); + t->custom.mode.use_free = true; + + float min = 999999999.0f, max = -999999999.0f; + int i; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + float val = *(td->val); + + /* strip/action time to global (mapped) time */ + if (adt) + val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP); + + if (min > val) + min = val; + if (max < val) + max = val; + } + } + + if (min == max) { + /* just use the current frame ranges */ + min = (float)PSFRA; + max = (float)PEFRA; + } + + range[0] = min; + range[1] = max; + } + + /* num-input has max of (n-1) */ + t->idx_max = 0; + t->num.flag = 0; + t->num.idx_max = t->idx_max; + + /* initialize snap like for everything else */ + t->snap[0] = 0.0f; + t->snap[1] = t->snap[2] = 1.0f; + + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + /* No time unit supporting frames currently... */ + t->num.unit_type[0] = B_UNIT_NONE; } static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW_STR]) { - char tvec[NUM_STR_REP_LEN * 3]; + char tvec[NUM_STR_REP_LEN * 3]; - if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, &t->scene->unit); - } - else { - const float *range = t->custom.mode.data; - float minx = range[0]; - float maxx = range[1]; - float cval = t->values[0]; - float val; + if (hasNumInput(&t->num)) { + outputNumInput(&(t->num), tvec, &t->scene->unit); + } + else { + const float *range = t->custom.mode.data; + float minx = range[0]; + float maxx = range[1]; + float cval = t->values[0]; + float val; - val = 2.0f * (cval - sval) / (maxx - minx); - CLAMP(val, -1.0f, 1.0f); + val = 2.0f * (cval - sval) / (maxx - minx); + CLAMP(val, -1.0f, 1.0f); - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); - } + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); + } - BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("TimeSlide: %s"), &tvec[0]); + BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("TimeSlide: %s"), &tvec[0]); } static void applyTimeSlideValue(TransInfo *t, float sval) { - int i; - const float *range = t->custom.mode.data; - float minx = range[0]; - float maxx = range[1]; - - /* set value for drawing black line */ - if (t->spacetype == SPACE_ACTION) { - SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; - float cvalf = t->values[0]; - - saction->timeslide = cvalf; - } - - /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - /* it is assumed that td->extra is a pointer to the AnimData, - * whose active action is where this keyframe comes from - * (this is only valid when not in NLA) - */ - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - float cval = t->values[0]; - - /* only apply to data if in range */ - if ((sval > minx) && (sval < maxx)) { - float cvalc = CLAMPIS(cval, minx, maxx); - float ival = td->ival; - float timefac; - - /* NLA mapping magic here works as follows: - * - "ival" goes from strip time to global time - * - calculation is performed into td->val in global time - * (since sval and min/max are all in global time) - * - "td->val" then gets put back into strip time - */ - if (adt) { - /* strip to global */ - ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP); - } - - /* left half? */ - if (ival < sval) { - timefac = (sval - ival) / (sval - minx); - *(td->val) = cvalc - timefac * (cvalc - minx); - } - else { - timefac = (ival - sval) / (maxx - sval); - *(td->val) = cvalc + timefac * (maxx - cvalc); - } - - if (adt) { - /* global to strip */ - *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP); - } - } - } - } + int i; + const float *range = t->custom.mode.data; + float minx = range[0]; + float maxx = range[1]; + + /* set value for drawing black line */ + if (t->spacetype == SPACE_ACTION) { + SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first; + float cvalf = t->values[0]; + + saction->timeslide = cvalf; + } + + /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + /* it is assumed that td->extra is a pointer to the AnimData, + * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) + */ + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + float cval = t->values[0]; + + /* only apply to data if in range */ + if ((sval > minx) && (sval < maxx)) { + float cvalc = CLAMPIS(cval, minx, maxx); + float ival = td->ival; + float timefac; + + /* NLA mapping magic here works as follows: + * - "ival" goes from strip time to global time + * - calculation is performed into td->val in global time + * (since sval and min/max are all in global time) + * - "td->val" then gets put back into strip time + */ + if (adt) { + /* strip to global */ + ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP); + } + + /* left half? */ + if (ival < sval) { + timefac = (sval - ival) / (sval - minx); + *(td->val) = cvalc - timefac * (cvalc - minx); + } + else { + timefac = (ival - sval) / (maxx - sval); + *(td->val) = cvalc + timefac * (maxx - cvalc); + } + + if (adt) { + /* global to strip */ + *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP); + } + } + } + } } static void applyTimeSlide(TransInfo *t, const int mval[2]) { - View2D *v2d = (View2D *)t->view; - float cval[2], sval[2]; - const float *range = t->custom.mode.data; - float minx = range[0]; - float maxx = range[1]; - char str[UI_MAX_DRAW_STR]; + View2D *v2d = (View2D *)t->view; + float cval[2], sval[2]; + const float *range = t->custom.mode.data; + float minx = range[0]; + float maxx = range[1]; + char str[UI_MAX_DRAW_STR]; - /* calculate mouse co-ordinates */ - UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]); - UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &sval[0], &sval[1]); + /* calculate mouse co-ordinates */ + UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]); + UI_view2d_region_to_view(v2d, t->mouse.imval[0], t->mouse.imval[1], &sval[0], &sval[1]); - /* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */ - // XXX Need to be able to repeat this - /* t->values[0] = cval[0]; */ /* UNUSED (reset again later). */ + /* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */ + // XXX Need to be able to repeat this + /* t->values[0] = cval[0]; */ /* UNUSED (reset again later). */ - /* handle numeric-input stuff */ - t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx); - applyNumInput(&t->num, &t->vec[0]); - t->values[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0]; + /* handle numeric-input stuff */ + t->vec[0] = 2.0f * (cval[0] - sval[0]) / (maxx - minx); + applyNumInput(&t->num, &t->vec[0]); + t->values[0] = (maxx - minx) * t->vec[0] / 2.0f + sval[0]; - headerTimeSlide(t, sval[0], str); - applyTimeSlideValue(t, sval[0]); + headerTimeSlide(t, sval[0], str); + applyTimeSlideValue(t, sval[0]); - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* -------------------------------------------------------------------- */ /* Transform (Animation Time Scale) */ @@ -9296,134 +9502,133 @@ static void applyTimeSlide(TransInfo *t, const int mval[2]) static void initTimeScale(TransInfo *t) { - float center[2]; + float center[2]; - /* this tool is only really available in the Action Editor - * AND NLA Editor (for strip scaling) - */ - if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) { - t->state = TRANS_CANCEL; - } + /* this tool is only really available in the Action Editor + * AND NLA Editor (for strip scaling) + */ + if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA) == 0) { + t->state = TRANS_CANCEL; + } - t->mode = TFM_TIME_SCALE; - t->transform = applyTimeScale; + t->mode = TFM_TIME_SCALE; + t->transform = applyTimeScale; - /* recalculate center2d to use CFRA and mouse Y, since that's - * what is used in time scale */ - if ((t->flag & T_OVERRIDE_CENTER) == 0) { - t->center_global[0] = t->scene->r.cfra; - projectFloatView(t, t->center_global, center); - center[1] = t->mouse.imval[1]; - } + /* recalculate center2d to use CFRA and mouse Y, since that's + * what is used in time scale */ + if ((t->flag & T_OVERRIDE_CENTER) == 0) { + t->center_global[0] = t->scene->r.cfra; + projectFloatView(t, t->center_global, center); + center[1] = t->mouse.imval[1]; + } - /* force a reinit with the center2d used here */ - initMouseInput(t, &t->mouse, center, t->mouse.imval, false); + /* force a reinit with the center2d used here */ + initMouseInput(t, &t->mouse, center, t->mouse.imval, false); - initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); + initMouseInputMode(t, &t->mouse, INPUT_SPRING_FLIP); - t->flag |= T_NULL_ONE; - t->num.val_flag[0] |= NUM_NULL_ONE; + t->flag |= T_NULL_ONE; + t->num.val_flag[0] |= NUM_NULL_ONE; - /* num-input has max of (n-1) */ - t->idx_max = 0; - t->num.flag = 0; - t->num.idx_max = t->idx_max; + /* num-input has max of (n-1) */ + t->idx_max = 0; + t->num.flag = 0; + t->num.idx_max = t->idx_max; - /* initialize snap like for everything else */ - t->snap[0] = 0.0f; - t->snap[1] = t->snap[2] = 1.0f; + /* initialize snap like for everything else */ + t->snap[0] = 0.0f; + t->snap[1] = t->snap[2] = 1.0f; - copy_v3_fl(t->num.val_inc, t->snap[1]); - t->num.unit_sys = t->scene->unit.system; - t->num.unit_type[0] = B_UNIT_NONE; + copy_v3_fl(t->num.val_inc, t->snap[1]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_type[0] = B_UNIT_NONE; } static void headerTimeScale(TransInfo *t, char str[UI_MAX_DRAW_STR]) { - char tvec[NUM_STR_REP_LEN * 3]; + char tvec[NUM_STR_REP_LEN * 3]; - if (hasNumInput(&t->num)) - outputNumInput(&(t->num), tvec, &t->scene->unit); - else - BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]); + if (hasNumInput(&t->num)) + outputNumInput(&(t->num), tvec, &t->scene->unit); + else + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]); - BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleX: %s"), &tvec[0]); + BLI_snprintf(str, UI_MAX_DRAW_STR, IFACE_("ScaleX: %s"), &tvec[0]); } static void applyTimeScaleValue(TransInfo *t) { - Scene *scene = t->scene; - int i; + Scene *scene = t->scene; + int i; - const short autosnap = getAnimEdit_SnapMode(t); - const double secf = FPS; + const short autosnap = getAnimEdit_SnapMode(t); + const double secf = FPS; - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - TransData2D *td2d = tc->data_2d; - for (i = 0; i < tc->data_len; i++, td++, td2d++) { - /* it is assumed that td->extra is a pointer to the AnimData, - * whose active action is where this keyframe comes from - * (this is only valid when not in NLA) - */ - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - float startx = CFRA; - float fac = t->values[0]; + FOREACH_TRANS_DATA_CONTAINER(t, tc) + { + TransData *td = tc->data; + TransData2D *td2d = tc->data_2d; + for (i = 0; i < tc->data_len; i++, td++, td2d++) { + /* it is assumed that td->extra is a pointer to the AnimData, + * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) + */ + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + float startx = CFRA; + float fac = t->values[0]; - if (autosnap == SACTSNAP_TSTEP) { - fac = (float)(floor((double)fac / secf + 0.5) * secf); - } - else if (autosnap == SACTSNAP_STEP) { - fac = floorf(fac + 0.5f); - } + if (autosnap == SACTSNAP_TSTEP) { + fac = (float)(floor((double)fac / secf + 0.5) * secf); + } + else if (autosnap == SACTSNAP_STEP) { + fac = floorf(fac + 0.5f); + } - /* take proportional editing into account */ - fac = ((fac - 1.0f) * td->factor) + 1; + /* take proportional editing into account */ + fac = ((fac - 1.0f) * td->factor) + 1; - /* check if any need to apply nla-mapping */ - if (adt) - startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP); + /* check if any need to apply nla-mapping */ + if (adt) + startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP); - /* now, calculate the new value */ - *(td->val) = ((td->ival - startx) * fac) + startx; + /* now, calculate the new value */ + *(td->val) = ((td->ival - startx) * fac) + startx; - /* apply nearest snapping */ - doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); - } - } + /* apply nearest snapping */ + doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); + } + } } static void applyTimeScale(TransInfo *t, const int UNUSED(mval[2])) { - char str[UI_MAX_DRAW_STR]; + char str[UI_MAX_DRAW_STR]; - /* handle numeric-input stuff */ - t->vec[0] = t->values[0]; - applyNumInput(&t->num, &t->vec[0]); - t->values[0] = t->vec[0]; - headerTimeScale(t, str); + /* handle numeric-input stuff */ + t->vec[0] = t->values[0]; + applyNumInput(&t->num, &t->vec[0]); + t->values[0] = t->vec[0]; + headerTimeScale(t, str); - applyTimeScaleValue(t); + applyTimeScaleValue(t); - recalcData(t); + recalcData(t); - ED_area_status_text(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ - /* TODO, move to: transform_query.c */ bool checkUseAxisMatrix(TransInfo *t) { - /* currently only checks for editmode */ - if (t->flag & T_EDIT) { - if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && - (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) - { - /* not all editmode supports axis-matrix */ - return true; - } - } - - return false; + /* currently only checks for editmode */ + if (t->flag & T_EDIT) { + if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && + (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) { + /* not all editmode supports axis-matrix */ + return true; + } + } + + return false; } |