diff options
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r-- | source/blender/editors/transform/SConscript | 1 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 172 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 11 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_constraints.c | 5 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 222 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 54 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_manipulator.c | 96 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_ops.c | 28 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_orientations.c | 2 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_snap.c | 80 |
10 files changed, 526 insertions, 145 deletions
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript index f3c8c13647a..4f47062e3a3 100644 --- a/source/blender/editors/transform/SConscript +++ b/source/blender/editors/transform/SConscript @@ -40,6 +40,7 @@ incs = [ '../../ikplugin', '../../makesdna', '../../makesrna', + '../../gpu', '../../windowmanager', ] diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 42cc6b14fd5..9092dbd52dd 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -86,6 +86,9 @@ #include "transform.h" +/* Disabling, since when you type you know what you are doing, and being able to set it to zero is handy. */ +// #define USE_NUM_NO_ZERO + #define MAX_INFO_LEN 256 static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg); @@ -190,9 +193,9 @@ static bool transdata_check_local_center(TransInfo *t, short around) { return ((around == V3D_LOCAL) && ( (t->flag & (T_OBJECT | T_POSE)) || - (t->obedit && ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) || + (t->obedit && ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) || (t->spacetype == SPACE_IPO) || - (t->options & (CTX_MOVIECLIP | CTX_MASK))) + (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE))) ); } @@ -263,17 +266,27 @@ static void convertViewVec2D_mask(View2D *v2d, float r_vec[3], int dx, int dy) void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) { if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) { - const float mval_f[2] = {(float)dx, (float)dy}; - ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac); + 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) { float aspx, aspy; if (t->options & CTX_MASK) { - convertViewVec2D_mask(t->view, r_vec, dx, dy); ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy); } + else if (t->options & CTX_PAINT_CURVE) { + r_vec[0] = dx; + r_vec[1] = dy; + + aspx = aspy = 1.0; + } else { convertViewVec2D(t->view, r_vec, dx, dy); ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); @@ -351,6 +364,10 @@ void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DPr 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 aspx, aspy, v[2]; @@ -452,7 +469,11 @@ void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV switch (t->spacetype) { case SPACE_VIEW3D: { - if (t->ar->regiontype == RGN_TYPE_WINDOW) { + 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! */ @@ -480,7 +501,7 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) void applyAspectRatio(TransInfo *t, float vec[2]) { - if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION)) { + if ((t->spacetype == SPACE_IMAGE) && (t->mode == TFM_TRANSLATION) && !(t->options & CTX_PAINT_CURVE)) { SpaceImage *sima = t->sa->spacedata.first; float aspx, aspy; @@ -557,17 +578,23 @@ void removeAspectRatio(TransInfo *t, float vec[2]) static void viewRedrawForce(const bContext *C, TransInfo *t) { if (t->spacetype == SPACE_VIEW3D) { - /* 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); + 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 realtime animation record - send notifiers recognised 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); - + /* for realtime animation record - send notifiers recognised 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; @@ -593,6 +620,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) 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 { // XXX how to deal with lock? SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; @@ -646,7 +677,7 @@ static void viewRedrawPost(bContext *C, TransInfo *t) allqueue(REDRAWIMAGE, 0); allqueue(REDRAWVIEW3D, 0); } - else if (ELEM3(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) { + else if (ELEM(t->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_IPO)) { allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWNLA, 0); @@ -969,7 +1000,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_TRANSLATE: /* only switch when... */ - if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { resetTransModal(t); resetTransRestrictions(t); restoreTransObjects(t); @@ -1025,7 +1056,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) case TFM_MODAL_ROTATE: /* only switch when... */ if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { - if (ELEM6(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { resetTransModal(t); resetTransRestrictions(t); @@ -1045,7 +1076,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_RESIZE: /* only switch when... */ - if (ELEM5(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + 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_MANIP_NORMAL)) { @@ -1308,7 +1339,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case GKEY: /* only switch when... */ - if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { + if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { resetTransModal(t); resetTransRestrictions(t); restoreTransObjects(t); @@ -1320,7 +1351,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case SKEY: /* only switch when... */ - if (ELEM3(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL) ) { + if (ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION, TFM_TRACKBALL)) { resetTransModal(t); resetTransRestrictions(t); restoreTransObjects(t); @@ -1333,7 +1364,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) case RKEY: /* only switch when... */ if (!(t->options & CTX_TEXTURE)) { - if (ELEM4(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION) ) { + if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_TRANSLATION)) { resetTransModal(t); resetTransRestrictions(t); @@ -1807,23 +1838,25 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - xco = rect.xmax - (int)printable_size[0] - 10; - yco = rect.ymax - (int)printable_size[1] - 10; + 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 */ UI_ThemeColorShade(TH_TEXT_HI, -50); #ifdef WITH_INTERNATIONAL - BLF_draw_default(xco, ar->winy - 17, 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, ar->winy - 17, 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... */ glEnable(GL_BLEND); - xco -= (ICON_DEFAULT_WIDTH + 2); + xco -= U.widget_unit; + yco -= (int)printable_size[1] / 2; + UI_icon_draw(xco, yco, ICON_REC); glDisable(GL_BLEND); @@ -2064,7 +2097,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve * moded are available from manipulator and doing such check could * lead to keymap conflicts for other modes (see #31584) */ - if (ELEM3(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { + if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { wmKeyMapItem *kmi; for (kmi = t->keymap->items.first; kmi; kmi = kmi->next) { @@ -2840,7 +2873,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN * 2]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bend Angle: %s Radius: %s Alt, Clamp %s"), &c[0], &c[NUM_STR_REP_LEN], @@ -3008,7 +3041,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %s %s"), c, t->proptext); } @@ -3084,9 +3117,11 @@ static void initResize(TransInfo *t) t->num.flag |= NUM_AFFECT_ALL; if (!t->obedit) { 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; +#endif } t->idx_max = 2; @@ -3107,7 +3142,7 @@ static void headerResize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]) char tvec[NUM_STR_REP_LEN * 3]; size_t ofs = 0; if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, t->scene->unit.scale_length); + outputNumInput(&(t->num), tvec, &t->scene->unit); } else { BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); @@ -3376,9 +3411,11 @@ static void initSkinResize(TransInfo *t) t->num.flag |= NUM_AFFECT_ALL; if (!t->obedit) { 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; +#endif } t->idx_max = 2; @@ -3519,7 +3556,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %s %s"), c, t->proptext); } @@ -3591,8 +3628,15 @@ static void initRotation(TransInfo *t) if (t->flag & T_2D_EDIT) t->flag |= T_NO_CONSTRAINT; - negate_v3_v3(t->axis, t->viewinv[2]); - normalize_v3(t->axis); + if (t->options & CTX_PAINT_CURVE) { + t->axis[0] = 0.0; + t->axis[1] = 0.0; + t->axis[2] = -1.0; + } + else { + negate_v3_v3(t->axis, t->viewinv[2]); + normalize_v3(t->axis); + } copy_v3_v3(t->axis_orig, t->axis); } @@ -3626,7 +3670,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short if (td->flag & TD_USEQUAT) { - mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); + mul_m3_series(fmat, td->smtx, mat, td->mtx); mat3_to_quat(quat, fmat); // Actual transform if (td->ext->quat) { @@ -3696,7 +3740,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short 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_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL); + mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx); mat3_to_quat(quat, fmat); /* Actual transform */ @@ -3711,7 +3755,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); - mul_serie_m3(fmat, td->ext->r_mtx, mat, td->ext->r_smtx, NULL, NULL, NULL, NULL, NULL); + 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); @@ -3768,7 +3812,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short 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_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); + 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); @@ -3782,7 +3826,7 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); - mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); + mul_m3_series(fmat, td->smtx, mat, td->mtx); mat3_to_quat(quat, fmat); // Actual transform mul_qt_qtqt(tquat, quat, iquat); @@ -3876,7 +3920,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); } @@ -3980,7 +4024,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN * 2]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %s %s %s"), &c[0], &c[NUM_STR_REP_LEN], t->proptext); @@ -4082,7 +4126,7 @@ static void headerTranslation(TransInfo *t, float vec[3], char str[MAX_INFO_LEN] float dist; if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, t->scene->unit.scale_length); + outputNumInput(&(t->num), tvec, &t->scene->unit); dist = len_v3(t->num.val); } else { @@ -4330,7 +4374,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), MAX_INFO_LEN - ofs); if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", c); } else { @@ -4425,7 +4469,7 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %s° %s"), &c[0], t->proptext); @@ -4479,7 +4523,9 @@ static void initCurveShrinkFatten(TransInfo *t) t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_ZERO; +#ifdef USE_NUM_NO_ZERO t->num.val_flag[0] |= NUM_NO_ZERO; +#endif t->flag |= T_NO_CONSTRAINT; } @@ -4501,7 +4547,7 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c); } else { @@ -4554,7 +4600,9 @@ static void initMaskShrinkFatten(TransInfo *t) t->num.unit_type[0] = B_UNIT_NONE; t->flag |= T_NO_ZERO; +#ifdef USE_NUM_NO_ZERO t->num.val_flag[0] |= NUM_NO_ZERO; +#endif t->flag |= T_NO_CONSTRAINT; } @@ -4577,7 +4625,7 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %s"), c); } else { @@ -4670,7 +4718,7 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext); } @@ -4763,7 +4811,7 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); if (weight >= 0.0f) BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%s %s"), c, t->proptext); @@ -4841,7 +4889,7 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); if (crease >= 0.0f) BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%s %s"), c, t->proptext); @@ -4911,7 +4959,7 @@ static void headerBoneSize(TransInfo *t, float vec[3], char str[MAX_INFO_LEN]) { char tvec[NUM_STR_REP_LEN * 3]; if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, t->scene->unit.scale_length); + outputNumInput(&(t->num), tvec, &t->scene->unit); } else { BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); @@ -5048,7 +5096,7 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %s"), c); } else { @@ -6222,7 +6270,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); if (is_proportional) { BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s"), @@ -6744,7 +6792,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs); if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs); } else { @@ -6811,7 +6859,7 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %s"), &c[0]); } @@ -6885,7 +6933,7 @@ static void applyBakeTime(TransInfo *t, const int mval[2]) if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; - outputNumInput(&(t->num), c, t->scene->unit.scale_length); + outputNumInput(&(t->num), c, &t->scene->unit); if (time >= 0.0f) BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%s %s"), c, t->proptext); @@ -7096,7 +7144,7 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN]) size_t ofs = 0; if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, t->scene->unit.scale_length); + outputNumInput(&(t->num), tvec, &t->scene->unit); } else { BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]); @@ -7322,7 +7370,7 @@ static void headerTimeTranslate(TransInfo *t, char str[MAX_INFO_LEN]) /* 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.scale_length); + outputNumInput(&(t->num), tvec, &t->scene->unit); } else { const Scene *scene = t->scene; @@ -7486,7 +7534,7 @@ static void headerTimeSlide(TransInfo *t, float sval, char str[MAX_INFO_LEN]) char tvec[NUM_STR_REP_LEN * 3]; if (hasNumInput(&t->num)) { - outputNumInput(&(t->num), tvec, t->scene->unit.scale_length); + outputNumInput(&(t->num), tvec, &t->scene->unit); } else { float minx = *((float *)(t->customData)); @@ -7634,7 +7682,7 @@ static void headerTimeScale(TransInfo *t, char str[MAX_INFO_LEN]) char tvec[NUM_STR_REP_LEN * 3]; if (hasNumInput(&t->num)) - outputNumInput(&(t->num), tvec, t->scene->unit.scale_length); + outputNumInput(&(t->num), tvec, &t->scene->unit); else BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]); @@ -7704,7 +7752,7 @@ bool checkUseAxisMatrix(TransInfo *t) { /* currently only checks for editmode */ if (t->flag & T_EDIT) { - if ((t->around == V3D_LOCAL) && (ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) { + if ((t->around == V3D_LOCAL) && (ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) { /* not all editmode supports axis-matrix */ return true; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 0bccf177128..012f9185d8b 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -130,15 +130,15 @@ typedef struct TransDataExtension { // float drotAxis[3]; /* Initial object drotAxis, TODO: not yet implemented */ float dquat[4]; /* Initial object dquat */ float dscale[3]; /* Initial object dscale */ - float *rot; /* Rotation of the data to transform (Faculative) */ + float *rot; /* Rotation of the data to transform */ float irot[3]; /* Initial rotation */ - float *quat; /* Rotation quaternion of the data to transform (Faculative) */ + float *quat; /* Rotation quaternion of the data to transform */ float iquat[4]; /* Initial rotation quaternion */ - float *rotAngle; /* Rotation angle of the data to transform (Faculative) */ + float *rotAngle; /* Rotation angle of the data to transform */ float irotAngle; /* Initial rotation angle */ - float *rotAxis; /* Rotation axis of the data to transform (Faculative) */ + float *rotAxis; /* Rotation axis of the data to transform */ float irotAxis[4]; /* Initial rotation axis */ - float *size; /* Size of the data to transform (Faculative) */ + float *size; /* Size of the data to transform */ float isize[3]; /* Initial size */ float obmat[4][4]; /* Object matrix */ float l_smtx[3][3]; /* use instead of td->smtx, It is the same but without the 'bone->bone_mat', see TD_PBONE_LOCAL_MTX_C */ @@ -532,6 +532,7 @@ void flushTransNodes(TransInfo *t); void flushTransSeq(TransInfo *t); void flushTransTracking(TransInfo *t); void flushTransMasking(TransInfo *t); +void flushTransPaintCurve(TransInfo *t); void restoreBones(TransInfo *t); /*********************** exported from transform_manipulator.c ********** */ diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 79f266df607..d8f17315c01 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -663,7 +663,7 @@ void drawConstraint(TransInfo *t) { TransCon *tc = &(t->con); - if (!ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) + if (!ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) return; if (!(tc->mode & CON_APPLY)) return; @@ -756,6 +756,9 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) /* untested - mask aspect is TODO */ ED_space_image_get_aspect(t->sa->spacedata.first, &aspx, &aspy); } + else if (t->options & CTX_PAINT_CURVE) { + aspx = aspy = 1.0; + } else { ED_space_image_get_uv_aspect(t->sa->spacedata.first, &aspx, &aspy); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 9dfd3e568e5..aa215613841 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -33,6 +33,7 @@ #include <math.h> #include "DNA_anim_types.h" +#include "DNA_brush_types.h" #include "DNA_armature_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" @@ -80,6 +81,7 @@ #include "BKE_node.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_paint.h" #include "BKE_pointcache.h" #include "BKE_report.h" #include "BKE_rigidbody.h" @@ -124,8 +126,8 @@ static void transform_around_single_fallback(TransInfo *t) { if ((t->total == 1) && - (ELEM3(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) && - (ELEM3(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) + (ELEM(t->around, V3D_CENTER, V3D_CENTROID, V3D_ACTIVE)) && + (ELEM(t->mode, TFM_RESIZE, TFM_ROTATION, TFM_TRACKBALL))) { t->around = V3D_LOCAL; } @@ -282,7 +284,7 @@ static void createTransTexspace(TransInfo *t) } id = ob->data; - if (id == NULL || !ELEM3(GS(id->name), ID_ME, ID_CU, ID_MB)) { + if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); t->total = 0; return; @@ -584,12 +586,12 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr if (constraints_list_needinv(t, &pchan->constraints)) { copy_m3_m4(tmat, pchan->constinv); invert_m3_m3(cmat, tmat); - mul_serie_m3(td->mtx, pmat, omat, cmat, NULL, NULL, NULL, NULL, NULL); - mul_serie_m3(td->ext->r_mtx, rpmat, omat, cmat, NULL, NULL, NULL, NULL, NULL); + mul_m3_series(td->mtx, cmat, omat, pmat); + mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat); } else { - mul_serie_m3(td->mtx, pmat, omat, NULL, NULL, NULL, NULL, NULL, NULL); - mul_serie_m3(td->ext->r_mtx, rpmat, omat, NULL, NULL, NULL, NULL, NULL, NULL); + mul_m3_series(td->mtx, omat, pmat); + mul_m3_series(td->ext->r_mtx, omat, rpmat); } invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx); } @@ -1279,7 +1281,7 @@ static void createTransArmatureVerts(TransInfo *t) } } - if (mirror && total_mirrored) { + if (mirror) { /* trick to terminate iteration */ bid[total_mirrored].bone = NULL; } @@ -2368,8 +2370,7 @@ static void createTransEditVerts(TransInfo *t) quat_to_mat3(qmat, quats[BM_elem_index_get(eve)]); if (defmats) - mul_serie_m3(mat, mtx, qmat, defmats[a], - NULL, NULL, NULL, NULL, NULL); + mul_m3_series(mat, defmats[a], qmat, mtx); else mul_m3_m3m3(mat, mtx, qmat); } @@ -3707,7 +3708,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, TransDataGraph * static bool graph_edit_is_translation_mode(TransInfo *t) { - return ELEM4(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE); + return ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE, TFM_TIME_DUPLICATE); } static bool graph_edit_use_local_center(TransInfo *t) @@ -4767,12 +4768,12 @@ static bool constraints_list_needinv(TransInfo *t, ListBase *list) if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) { /* (affirmative) returns for specific constraints here... */ /* constraints that require this regardless */ - if (ELEM5(con->type, - CONSTRAINT_TYPE_CHILDOF, - CONSTRAINT_TYPE_FOLLOWPATH, - CONSTRAINT_TYPE_CLAMPTO, - CONSTRAINT_TYPE_OBJECTSOLVER, - CONSTRAINT_TYPE_FOLLOWTRACK)) + if (ELEM(con->type, + CONSTRAINT_TYPE_CHILDOF, + CONSTRAINT_TYPE_FOLLOWPATH, + CONSTRAINT_TYPE_CLAMPTO, + CONSTRAINT_TYPE_OBJECTSOLVER, + CONSTRAINT_TYPE_FOLLOWTRACK)) { return true; } @@ -5848,6 +5849,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } + else if (t->options & CTX_PAINT_CURVE) { + /* pass */ + } else if ((t->scene->basact) && (ob = t->scene->basact->object) && (ob->mode & OB_MODE_PARTICLE_EDIT) && @@ -7027,6 +7031,173 @@ void flushTransMasking(TransInfo *t) } } +typedef struct TransDataPaintCurve { + PaintCurvePoint *pcp; /* initial curve point */ + char id; +} TransDataPaintCurve; + + +#define PC_IS_ANY_SEL(pc) (((pc)->bez.f1 | (pc)->bez.f2 | (pc)->bez.f3) & SELECT) + +static void PaintCurveConvertHandle(PaintCurvePoint *pcp, int id, TransData2D *td2d, TransDataPaintCurve *tdpc, TransData *td) +{ + BezTriple *bezt = &pcp->bez; + copy_v2_v2(td2d->loc, bezt->vec[id]); + td2d->loc[2] = 0.0f; + td2d->loc2d = bezt->vec[id]; + + td->flag = 0; + td->loc = td2d->loc; + copy_v3_v3(td->center, bezt->vec[1]); + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext = NULL; + td->val = NULL; + td->flag |= TD_SELECTED; + td->dist = 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + tdpc->id = id; + tdpc->pcp = pcp; +} + +static void PaintCurvePointToTransData(PaintCurvePoint *pcp, TransData *td, TransData2D *td2d, TransDataPaintCurve *tdpc) +{ + BezTriple *bezt = &pcp->bez; + + if (pcp->bez.f2 == SELECT) { + int i; + for (i = 0; i < 3; i++) { + copy_v2_v2(td2d->loc, bezt->vec[i]); + td2d->loc[2] = 0.0f; + td2d->loc2d = bezt->vec[i]; + + td->flag = 0; + td->loc = td2d->loc; + copy_v3_v3(td->center, bezt->vec[1]); + copy_v3_v3(td->iloc, td->loc); + + memset(td->axismtx, 0, sizeof(td->axismtx)); + td->axismtx[2][2] = 1.0f; + + td->ext = NULL; + td->val = NULL; + td->flag |= TD_SELECTED; + td->dist = 0.0; + + unit_m3(td->mtx); + unit_m3(td->smtx); + + tdpc->id = i; + tdpc->pcp = pcp; + + td++; + td2d++; + tdpc++; + } + } + else { + if (bezt->f3 & SELECT) { + PaintCurveConvertHandle(pcp, 2, td2d, tdpc, td); + td2d++; + tdpc++; + td++; + } + + if (bezt->f1 & SELECT) { + PaintCurveConvertHandle(pcp, 0, td2d, tdpc, td); + } + } +} + +static void createTransPaintCurveVerts(bContext *C, TransInfo *t) +{ + Paint *paint = BKE_paint_get_active_from_context(C); + PaintCurve *pc; + PaintCurvePoint *pcp; + Brush *br; + TransData *td = NULL; + TransData2D *td2d = NULL; + TransDataPaintCurve *tdpc = NULL; + int i; + int total = 0; + + t->total = 0; + + if (!paint || !paint->brush || !paint->brush->paint_curve) + return; + + br = paint->brush; + pc = br->paint_curve; + + for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) { + if (PC_IS_ANY_SEL(pcp)) { + if (pcp->bez.f2 & SELECT) { + total += 3; + continue; + } + else { + if (pcp->bez.f1 & SELECT) + total++; + if (pcp->bez.f3 & SELECT) + total++; + } + } + } + + if (!total) + return; + + t->total = total; + td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransData2D"); + td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransData"); + tdpc = t->customData = MEM_callocN(t->total * sizeof(TransDataPaintCurve), "TransDataPaintCurve"); + t->flag |= T_FREE_CUSTOMDATA; + + for (pcp = pc->points, i = 0; i < pc->tot_points; i++, pcp++) { + if (PC_IS_ANY_SEL(pcp)) { + PaintCurvePointToTransData (pcp, td, td2d, tdpc); + + if (pcp->bez.f2 & SELECT) { + td += 3; + td2d += 3; + tdpc += 3; + } + else { + if (pcp->bez.f1 & SELECT) { + td++; + td2d++; + tdpc++; + } + if (pcp->bez.f3 & SELECT) { + td++; + td2d++; + tdpc++; + } + } + } + } +} + + +void flushTransPaintCurve(TransInfo *t) +{ + int i; + TransData2D *td2d = t->data2d; + TransDataPaintCurve *tdpc = (TransDataPaintCurve *)t->customData; + + for (i = 0; i < t->total; i++, tdpc++, td2d++) { + PaintCurvePoint *pcp = tdpc->pcp; + copy_v2_v2(pcp->bez.vec[tdpc->id], td2d->loc); + } +} + + void createTransData(bContext *C, TransInfo *t) { Scene *scene = t->scene; @@ -7059,6 +7230,10 @@ void createTransData(bContext *C, TransInfo *t) sort_trans_data_dist(t); } } + else if (t->options & CTX_PAINT_CURVE) { + if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) + createTransPaintCurveVerts(C, t); + } else if (t->obedit) { createTransUVs(C, t); if (t->data && (t->flag & T_PROP_EDIT)) { @@ -7165,7 +7340,7 @@ void createTransData(bContext *C, TransInfo *t) // XXX active-layer checking isn't done as that should probably be checked through context instead createTransPose(t, ob); } - else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) { + else if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) { /* important that ob_armature can be set even when its not selected [#23412] * lines below just check is also visible */ Object *ob_armature = modifiers_isDeformedByArmature(ob); @@ -7190,12 +7365,11 @@ void createTransData(bContext *C, TransInfo *t) sort_trans_data_dist(t); } } - else if (ob && (ob->mode & (OB_MODE_ALL_PAINT))) { - /* sculpt mode and project paint have own undo stack - * transform ops redo clears sculpt/project undo stack. - * - * Could use 'OB_MODE_ALL_PAINT' since there are key conflicts, - * transform + paint isn't well supported. */ + else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { + if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) { + t->flag |= T_POINTS | T_2D_EDIT; + createTransPaintCurveVerts(C, t); + } } else { createTransObject(C, t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 15d1bb75d89..24dc6f6e74b 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -38,6 +38,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" +#include "DNA_brush_types.h" #include "DNA_lattice_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" @@ -74,6 +75,7 @@ #include "BKE_lattice.h" #include "BKE_nla.h" #include "BKE_context.h" +#include "BKE_paint.h" #include "BKE_sequencer.h" #include "BKE_editmesh.h" #include "BKE_tracking.h" @@ -98,6 +100,7 @@ #include "WM_api.h" #include "UI_resources.h" +#include "UI_view2d.h" #include "transform.h" @@ -262,7 +265,7 @@ static void animrecord_check_state(Scene *scene, ID *id, wmTimer *animtimer) ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL; /* sanity checks */ - if (ELEM3(NULL, scene, id, sad)) + if (ELEM(NULL, scene, id, sad)) return; /* check if we need a new strip if: @@ -653,6 +656,9 @@ static void recalcData_image(TransInfo *t) if (t->options & CTX_MASK) { recalcData_mask_common(t); } + else if (t->options & CTX_PAINT_CURVE) { + flushTransPaintCurve(t); + } else if (t->obedit && t->obedit->type == OB_MESH) { SpaceImage *sima = t->sa->spacedata.first; @@ -817,7 +823,7 @@ static void recalcData_objects(TransInfo *t) } } - if (!ELEM3(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) { + if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONESIZE)) { /* fix roll */ for (i = 0; i < t->total; i++, td++) { if (td->extra) { @@ -965,6 +971,9 @@ void recalcData(TransInfo *t) else if (t->options & CTX_EDGE) { recalcData_objects(t); } + else if (t->options & CTX_PAINT_CURVE) { + flushTransPaintCurve(t); + } else if (t->spacetype == SPACE_IMAGE) { recalcData_image(t); } @@ -1073,6 +1082,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve ARegion *ar = CTX_wm_region(C); ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); + Object *ob = CTX_data_active_object(C); PropertyRNA *prop; t->scene = sce; @@ -1193,11 +1203,18 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* exceptional case */ if (t->around == V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) { - if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { + if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { t->options |= CTX_NO_PET; } } + if (ob && ob->mode & OB_MODE_ALL_PAINT) { + Paint *p = BKE_paint_get_active_from_context(C); + if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) { + t->options |= CTX_PAINT_CURVE; + } + } + /* initialize UV transform from */ if (op && ((prop = RNA_struct_find_property(op->ptr, "correct_uv")))) { if (RNA_property_is_set(op->ptr, prop)) { @@ -1226,9 +1243,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve else if (sima->mode == SI_MODE_MASK) { t->options |= CTX_MASK; } - else { - /* image not in uv edit, nor in mask mode, can happen for some tools */ + else if (sima->mode == SI_MODE_PAINT) { + Paint *p = &sce->toolsettings->imapaint.paint; + if (p->brush && (p->brush->flag & BRUSH_CURVE)) { + t->options |= CTX_PAINT_CURVE; + } } + /* image not in uv edit, nor in mask mode, can happen for some tools */ } else if (t->spacetype == SPACE_NODE) { // XXX for now, get View2D from the active region @@ -1409,7 +1430,7 @@ void postTrans(bContext *C, TransInfo *t) } if (t->spacetype == SPACE_IMAGE) { - if (t->options & CTX_MASK) { + if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) { /* pass */ } else { @@ -1539,6 +1560,13 @@ void calculateCenterCursor(TransInfo *t, float r_center[3]) invert_m3_m3(imat, mat); mul_m3_v3(imat, r_center); } + else if (t->options & CTX_PAINT_CURVE) { + if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + r_center[0] = t->ar->winx / 2.0f; + r_center[1] = t->ar->winy / 2.0f; + } + r_center[2] = 0.0f; + } } void calculateCenterCursor2D(TransInfo *t, float r_center[2]) @@ -1586,6 +1614,12 @@ void calculateCenterCursor2D(TransInfo *t, float r_center[2]) r_center[0] = co[0] * aspx; r_center[1] = co[1] * aspy; } + else if (t->options & CTX_PAINT_CURVE) { + if (t->spacetype == SPACE_IMAGE) { + r_center[0] = UI_view2d_view_to_region_x(&t->ar->v2d, cursor[0]); + r_center[1] = UI_view2d_view_to_region_y(&t->ar->v2d, cursor[1]); + } + } else { r_center[0] = cursor[0] * aspx; r_center[1] = cursor[1] * aspy; @@ -1720,6 +1754,14 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) } } } + else if (t->options & CTX_PAINT_CURVE) { + Paint *p = BKE_paint_get_active(t->scene); + Brush *br = p->brush; + PaintCurve *pc = br->paint_curve; + copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]); + r_center[2] = 0.0f; + ok = true; + } else { /* object mode */ Scene *scene = t->scene; diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 36d91c1c630..6441071056f 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -72,6 +72,8 @@ /* local module include */ #include "transform.h" +#include "GPU_select.h" + /* return codes for select, and drawing flags */ #define MAN_TRANS_X (1 << 0) @@ -858,8 +860,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co /* axes */ if (flagx) { if (is_picksel) { - if (flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X); - else if (flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X); + if (flagx & MAN_SCALE_X) GPU_select_load_id(MAN_SCALE_X); + else if (flagx & MAN_TRANS_X) GPU_select_load_id(MAN_TRANS_X); } else { manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); @@ -873,8 +875,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co case 1: if (flagy) { if (is_picksel) { - if (flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y); - else if (flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y); + if (flagy & MAN_SCALE_Y) GPU_select_load_id(MAN_SCALE_Y); + else if (flagy & MAN_TRANS_Y) GPU_select_load_id(MAN_TRANS_Y); } else { manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); @@ -888,8 +890,8 @@ static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int co case 2: if (flagz) { if (is_picksel) { - if (flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z); - else if (flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z); + if (flagz & MAN_SCALE_Z) GPU_select_load_id(MAN_SCALE_Z); + else if (flagz & MAN_TRANS_Z) GPU_select_load_id(MAN_TRANS_Z); } else { manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); @@ -975,7 +977,7 @@ static void draw_manipulator_rotate( /* Screen aligned trackball rot circle */ if (drawflags & MAN_ROT_T) { - if (is_picksel) glLoadName(MAN_ROT_T); + if (is_picksel) GPU_select_load_id(MAN_ROT_T); else UI_ThemeColor(TH_TRANSFORM); drawcircball(GL_LINE_LOOP, unitmat[3], 0.2f * size, unitmat); @@ -983,7 +985,7 @@ static void draw_manipulator_rotate( /* Screen aligned view rot circle */ if (drawflags & MAN_ROT_V) { - if (is_picksel) glLoadName(MAN_ROT_V); + if (is_picksel) GPU_select_load_id(MAN_ROT_V); else UI_ThemeColor(TH_TRANSFORM); drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat); @@ -1062,7 +1064,7 @@ static void draw_manipulator_rotate( /* Z circle */ if (drawflags & MAN_ROT_Z) { preOrthoFront(ortho, matt, 2); - if (is_picksel) glLoadName(MAN_ROT_Z); + if (is_picksel) GPU_select_load_id(MAN_ROT_Z); else manipulator_setcolor(v3d, 'Z', colcode, 255); drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat); postOrtho(ortho); @@ -1070,7 +1072,7 @@ static void draw_manipulator_rotate( /* X circle */ if (drawflags & MAN_ROT_X) { preOrthoFront(ortho, matt, 0); - if (is_picksel) glLoadName(MAN_ROT_X); + if (is_picksel) GPU_select_load_id(MAN_ROT_X); else manipulator_setcolor(v3d, 'X', colcode, 255); glRotatef(90.0, 0.0, 1.0, 0.0); drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat); @@ -1080,7 +1082,7 @@ static void draw_manipulator_rotate( /* Y circle */ if (drawflags & MAN_ROT_Y) { preOrthoFront(ortho, matt, 1); - if (is_picksel) glLoadName(MAN_ROT_Y); + if (is_picksel) GPU_select_load_id(MAN_ROT_Y); else manipulator_setcolor(v3d, 'Y', colcode, 255); glRotatef(-90.0, 1.0, 0.0, 0.0); drawcircball(GL_LINE_LOOP, unitmat[3], 1.0, unitmat); @@ -1097,7 +1099,7 @@ static void draw_manipulator_rotate( /* Z circle */ if (drawflags & MAN_ROT_Z) { preOrthoFront(ortho, rv3d->twmat, 2); - if (is_picksel) glLoadName(MAN_ROT_Z); + if (is_picksel) GPU_select_load_id(MAN_ROT_Z); else manipulator_setcolor(v3d, 'Z', colcode, 255); partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48); postOrtho(ortho); @@ -1105,7 +1107,7 @@ static void draw_manipulator_rotate( /* X circle */ if (drawflags & MAN_ROT_X) { preOrthoFront(ortho, rv3d->twmat, 0); - if (is_picksel) glLoadName(MAN_ROT_X); + if (is_picksel) GPU_select_load_id(MAN_ROT_X); else manipulator_setcolor(v3d, 'X', colcode, 255); glRotatef(90.0, 0.0, 1.0, 0.0); partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48); @@ -1115,7 +1117,7 @@ static void draw_manipulator_rotate( /* Y circle */ if (drawflags & MAN_ROT_Y) { preOrthoFront(ortho, rv3d->twmat, 1); - if (is_picksel) glLoadName(MAN_ROT_Y); + if (is_picksel) GPU_select_load_id(MAN_ROT_Y); else manipulator_setcolor(v3d, 'Y', colcode, 255); glRotatef(-90.0, 1.0, 0.0, 0.0); partial_doughnut(cusize / 4.0f, 1.0f, 0, 48, 8, 48); @@ -1132,7 +1134,7 @@ static void draw_manipulator_rotate( if (drawflags & MAN_ROT_Z) { preOrthoFront(ortho, rv3d->twmat, 2); glPushMatrix(); - if (is_picksel) glLoadName(MAN_ROT_Z); + if (is_picksel) GPU_select_load_id(MAN_ROT_Z); else manipulator_setcolor(v3d, 'Z', colcode, 255); partial_doughnut(0.7f * cusize, 1.0f, 31, 33, 8, 64); @@ -1145,7 +1147,7 @@ static void draw_manipulator_rotate( if (drawflags & MAN_ROT_Y) { preOrthoFront(ortho, rv3d->twmat, 1); glPushMatrix(); - if (is_picksel) glLoadName(MAN_ROT_Y); + if (is_picksel) GPU_select_load_id(MAN_ROT_Y); else manipulator_setcolor(v3d, 'Y', colcode, 255); glRotatef(90.0, 1.0, 0.0, 0.0); @@ -1160,7 +1162,7 @@ static void draw_manipulator_rotate( if (drawflags & MAN_ROT_X) { preOrthoFront(ortho, rv3d->twmat, 0); glPushMatrix(); - if (is_picksel) glLoadName(MAN_ROT_X); + if (is_picksel) GPU_select_load_id(MAN_ROT_X); else manipulator_setcolor(v3d, 'X', colcode, 255); glRotatef(-90.0, 0.0, 1.0, 0.0); @@ -1263,7 +1265,7 @@ static void draw_manipulator_scale( int shift = 0; // XXX /* center circle, do not add to selection when shift is pressed (planar constraint) */ - if (is_picksel && shift == 0) glLoadName(MAN_SCALE_C); + if (is_picksel && shift == 0) GPU_select_load_id(MAN_SCALE_C); else manipulator_setcolor(v3d, 'C', colcode, 255); glPushMatrix(); @@ -1304,7 +1306,7 @@ static void draw_manipulator_scale( case 0: /* X cube */ if (drawflags & MAN_SCALE_X) { glTranslatef(dz, 0.0, 0.0); - if (is_picksel) glLoadName(MAN_SCALE_X); + if (is_picksel) GPU_select_load_id(MAN_SCALE_X); else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); drawsolidcube(cusize); glTranslatef(-dz, 0.0, 0.0); @@ -1313,7 +1315,7 @@ static void draw_manipulator_scale( case 1: /* Y cube */ if (drawflags & MAN_SCALE_Y) { glTranslatef(0.0, dz, 0.0); - if (is_picksel) glLoadName(MAN_SCALE_Y); + if (is_picksel) GPU_select_load_id(MAN_SCALE_Y); else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); drawsolidcube(cusize); glTranslatef(0.0, -dz, 0.0); @@ -1322,7 +1324,7 @@ static void draw_manipulator_scale( case 2: /* Z cube */ if (drawflags & MAN_SCALE_Z) { glTranslatef(0.0, 0.0, dz); - if (is_picksel) glLoadName(MAN_SCALE_Z); + if (is_picksel) GPU_select_load_id(MAN_SCALE_Z); else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); drawsolidcube(cusize); glTranslatef(0.0, 0.0, -dz); @@ -1337,7 +1339,7 @@ static void draw_manipulator_scale( if (shift) { glTranslatef(0.0, -dz, 0.0); - glLoadName(MAN_SCALE_C); + GPU_select_load_id(MAN_SCALE_C); glBegin(GL_POINTS); glVertex3f(0.0, 0.0, 0.0); glEnd(); @@ -1399,7 +1401,7 @@ static void draw_manipulator_translate( glDisable(GL_DEPTH_TEST); /* center circle, do not add to selection when shift is pressed (planar constraint) */ - if (is_picksel && shift == 0) glLoadName(MAN_TRANS_C); + if (is_picksel && shift == 0) GPU_select_load_id(MAN_TRANS_C); else manipulator_setcolor(v3d, 'C', colcode, 255); glPushMatrix(); @@ -1412,7 +1414,7 @@ static void draw_manipulator_translate( glMultMatrixf(rv3d->twmat); /* axis */ - glLoadName(-1); + GPU_select_load_id(-1); // translate drawn as last, only axis when no combo with scale, or for ghosting if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) { @@ -1435,7 +1437,7 @@ static void draw_manipulator_translate( case 0: /* Z Cone */ if (drawflags & MAN_TRANS_Z) { glTranslatef(0.0, 0.0, dz); - if (is_picksel) glLoadName(MAN_TRANS_Z); + if (is_picksel) GPU_select_load_id(MAN_TRANS_Z); else manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->tw_idot[2])); draw_cone(qobj, cylen, cywid); glTranslatef(0.0, 0.0, -dz); @@ -1444,7 +1446,7 @@ static void draw_manipulator_translate( case 1: /* X Cone */ if (drawflags & MAN_TRANS_X) { glTranslatef(dz, 0.0, 0.0); - if (is_picksel) glLoadName(MAN_TRANS_X); + if (is_picksel) GPU_select_load_id(MAN_TRANS_X); else manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->tw_idot[0])); glRotatef(90.0, 0.0, 1.0, 0.0); draw_cone(qobj, cylen, cywid); @@ -1455,7 +1457,7 @@ static void draw_manipulator_translate( case 2: /* Y Cone */ if (drawflags & MAN_TRANS_Y) { glTranslatef(0.0, dz, 0.0); - if (is_picksel) glLoadName(MAN_TRANS_Y); + if (is_picksel) GPU_select_load_id(MAN_TRANS_Y); else manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->tw_idot[1])); glRotatef(-90.0, 1.0, 0.0, 0.0); draw_cone(qobj, cylen, cywid); @@ -1503,7 +1505,7 @@ static void draw_manipulator_rotate_cyl( unit_m4(unitmat); - if (is_picksel) glLoadName(MAN_ROT_V); + if (is_picksel) GPU_select_load_id(MAN_ROT_V); UI_ThemeColor(TH_TRANSFORM); drawcircball(GL_LINE_LOOP, unitmat[3], 1.2f * size, unitmat); @@ -1556,7 +1558,7 @@ static void draw_manipulator_rotate_cyl( case 0: /* X cylinder */ if (drawflags & MAN_ROT_X) { glTranslatef(1.0, 0.0, 0.0); - if (is_picksel) glLoadName(MAN_ROT_X); + if (is_picksel) GPU_select_load_id(MAN_ROT_X); glRotatef(90.0, 0.0, 1.0, 0.0); manipulator_setcolor(v3d, 'X', colcode, 255); draw_cylinder(qobj, cylen, cywid); @@ -1567,7 +1569,7 @@ static void draw_manipulator_rotate_cyl( case 1: /* Y cylinder */ if (drawflags & MAN_ROT_Y) { glTranslatef(0.0, 1.0, 0.0); - if (is_picksel) glLoadName(MAN_ROT_Y); + if (is_picksel) GPU_select_load_id(MAN_ROT_Y); glRotatef(-90.0, 1.0, 0.0, 0.0); manipulator_setcolor(v3d, 'Y', colcode, 255); draw_cylinder(qobj, cylen, cywid); @@ -1578,7 +1580,7 @@ static void draw_manipulator_rotate_cyl( case 2: /* Z cylinder */ if (drawflags & MAN_ROT_Z) { glTranslatef(0.0, 0.0, 1.0); - if (is_picksel) glLoadName(MAN_ROT_Z); + if (is_picksel) GPU_select_load_id(MAN_ROT_Z); manipulator_setcolor(v3d, 'Z', colcode, 255); draw_cylinder(qobj, cylen, cywid); glTranslatef(0.0, 0.0, -1.0); @@ -1689,10 +1691,11 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl { View3D *v3d = sa->spacedata.first; RegionView3D *rv3d = ar->regiondata; - rctf rect; + rctf rect, selrect; GLuint buffer[64]; // max 4 items per select, so large enuf short hits; const bool is_picksel = true; + const bool do_passes = GPU_select_query_check_active(); /* XXX check a bit later on this... (ton) */ extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect); @@ -1707,13 +1710,15 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl rect.ymin = mval[1] - hotspot; rect.ymax = mval[1] + hotspot; + selrect = rect; + view3d_winmatrix_set(ar, v3d, &rect); mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); - glSelectBuffer(64, buffer); - glRenderMode(GL_SELECT); - glInitNames(); /* these two calls whatfor? It doesn't work otherwise */ - glPushName(-2); + if (do_passes) + GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0); + else + GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_ALL, 0); /* do the drawing */ if (v3d->twtype & V3D_MANIP_ROTATE) { @@ -1725,8 +1730,23 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl if (v3d->twtype & V3D_MANIP_TRANSLATE) draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); - glPopName(); - hits = glRenderMode(GL_RENDER); + hits = GPU_select_end(); + + if (do_passes) { + GPU_select_begin(buffer, 64, &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits); + + /* do the drawing */ + if (v3d->twtype & V3D_MANIP_ROTATE) { + if (G.debug_value == 3) draw_manipulator_rotate_cyl(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); + else draw_manipulator_rotate(v3d, rv3d, MAN_ROT_C & rv3d->twdrawflag, v3d->twtype, false, is_picksel); + } + if (v3d->twtype & V3D_MANIP_SCALE) + draw_manipulator_scale(v3d, rv3d, MAN_SCALE_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); + if (v3d->twtype & V3D_MANIP_TRANSLATE) + draw_manipulator_translate(v3d, rv3d, MAN_TRANS_C & rv3d->twdrawflag, v3d->twtype, MAN_RGB, false, is_picksel); + + GPU_select_end(); + } view3d_winmatrix_set(ar, v3d, NULL); mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 7bdbbf7289d..81e065ee33a 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -49,6 +50,8 @@ #include "UI_resources.h" #include "ED_screen.h" +/* for USE_LOOPSLIDE_HACK only */ +#include "ED_mesh.h" #include "transform.h" @@ -881,6 +884,27 @@ static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) Transform_Properties(ot, P_SNAP); } +static int edge_bevelweight_exec(bContext *C, wmOperator *op) +{ + Mesh *me = (Mesh *)CTX_data_edit_object(C)->data; + + /* auto-enable bevel edge weight drawing, then chain to common transform code */ + me->drawflag |= ME_DRAWBWEIGHTS; + + return transform_exec(C, op); +} + +static int edge_bevelweight_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Mesh *me = (Mesh *)CTX_data_edit_object(C)->data; + + /* auto-enable bevel edge weight drawing, then chain to common transform code */ + me->drawflag |= ME_DRAWBWEIGHTS; + + return transform_invoke(C, op, event); +} + + static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot) { /* identifiers */ @@ -890,8 +914,8 @@ static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; /* api callbacks */ - ot->invoke = transform_invoke; - ot->exec = transform_exec; + ot->invoke = edge_bevelweight_invoke; + ot->exec = edge_bevelweight_exec; ot->modal = transform_modal; ot->cancel = transform_cancel; ot->poll = ED_operator_editmesh; diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index ba90926df3b..69d135b8550 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -756,7 +756,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], if (flag) { float tvec[3]; if ((v3d->around == V3D_LOCAL) || - ELEM3(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3)) + ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3)) { BKE_nurb_bezt_calc_normal(nu, bezt, tvec); add_v3_v3(normal, tvec); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 451837fd311..abef2c9fc30 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -117,8 +117,8 @@ int BIF_snappingSupported(Object *obedit) { int status = 0; - if (obedit == NULL || ELEM5(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) /* only support object mesh, armature, curves */ - { + /* only support object mesh, armature, curves */ + if (obedit == NULL || ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) { status = 1; } @@ -337,6 +337,46 @@ void applyProject(TransInfo *t) mul_m3_v3(td->smtx, tvec); add_v3_v3(td->loc, tvec); + + if (t->tsnap.align && (t->flag & T_OBJECT)) { + /* handle alignment as well */ + const float *original_normal; + float axis[3]; + float mat[3][3]; + float angle; + float totmat[3][3], smat[3][3]; + float eul[3], fmat[3][3], quat[4]; + float obmat[3][3]; + + /* In pose mode, we want to align normals with Y axis of bones... */ + original_normal = td->axismtx[2]; + + cross_v3_v3v3(axis, original_normal, no); + angle = saacos(dot_v3v3(original_normal, no)); + + axis_angle_to_quat(quat, axis, angle); + + quat_to_mat3(mat, quat); + + 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); /* we have to 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 */ + copy_v3_v3(td->ext->rot, eul); + + /* TODO support constraints for rotation too? see ElementRotation */ + } } } @@ -505,7 +545,7 @@ static void initSnappingMode(TransInfo *t) /* Edit mode */ if (t->tsnap.applySnap != NULL && // A snapping function actually exist - (obedit != NULL && ELEM5(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs + (obedit != NULL && ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs { /* Exclude editmesh if using proportional edit */ if ((obedit->type == OB_MESH) && (t->flag & T_PROP_EDIT)) { @@ -588,7 +628,7 @@ void initSnapping(TransInfo *t, wmOperator *op) } /* use scene defaults only when transform is modal */ else if (t->flag & T_MODAL) { - if (ELEM3(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) { + if (ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE, SPACE_NODE)) { if (ts->snap_flag & SCE_SNAP) { t->modifiers |= MOD_SNAP; } @@ -658,7 +698,8 @@ static void setSnappingCallback(TransInfo *t) void addSnapPoint(TransInfo *t) { - if (t->tsnap.status & POINT_INIT) { + /* Currently only 3D viewport works for snapping points. */ + if (t->tsnap.status & POINT_INIT && t->spacetype == SPACE_VIEW3D) { TransSnapPoint *p = MEM_callocN(sizeof(TransSnapPoint), "SnapPoint"); t->tsnap.selectedPoint = p; @@ -1492,6 +1533,8 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes const float mval[2], float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth, bool do_bb) { bool retval = false; + const bool do_ray_start_correction = (snap_mode == SCE_SNAP_MODE_FACE && ar && + !((RegionView3D *)ar->regiondata)->is_persp); int totvert = dm->getNumVerts(dm); if (totvert > 0) { @@ -1518,6 +1561,28 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes return retval; } } + else if (do_ray_start_correction) { + /* We *need* a reasonably valid len_diff in this case. + * Use BHVTree to find the closest face from ray_start_local. + */ + BVHTreeFromMesh treeData; + BVHTreeNearest nearest; + len_diff = 0.0f; /* In case BVHTree would fail for some reason... */ + + treeData.em_evil = em; + bvhtree_from_mesh_faces(&treeData, dm, 0.0f, 2, 6); + if (treeData.tree != NULL) { + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + BLI_bvhtree_find_nearest(treeData.tree, ray_start_local, &nearest, + treeData.nearest_callback, &treeData); + if (nearest.index != -1) { + len_diff = sqrtf(nearest.dist_sq); + } + } + free_bvhtree_from_mesh(&treeData); + } switch (snap_mode) { case SCE_SNAP_MODE_FACE: @@ -1529,7 +1594,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes * been *inside* boundbox, leading to snap failures (see T38409). * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ - if (ar && !((RegionView3D *)ar->regiondata)->is_persp) { + if (do_ray_start_correction) { float ray_org_local[3]; copy_v3_v3(ray_org_local, ray_origin); @@ -2383,6 +2448,9 @@ static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fa if (t->options & CTX_MASK) { ED_space_image_get_aspect(t->sa->spacedata.first, asp, asp + 1); } + else if (t->options & CTX_PAINT_CURVE) { + asp[0] = asp[1] = 1.0; + } else { ED_space_image_get_uv_aspect(t->sa->spacedata.first, asp, asp + 1); } |