diff options
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r-- | source/blender/editors/transform/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/transform/SConscript | 4 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 170 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 13 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_constraints.c | 14 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 17 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 27 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_manipulator.c | 12 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_ops.c | 26 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_orientations.c | 62 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_snap.c | 215 |
11 files changed, 341 insertions, 220 deletions
diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 0bc38f81dd7..42aa6a0a3a3 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../../blenfont ../../blenkernel ../../blenlib + ../../blentranslation ../../bmesh ../../gpu ../../ikplugin diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript index 1a2e9ab074a..0f34ce546de 100644 --- a/source/blender/editors/transform/SConscript +++ b/source/blender/editors/transform/SConscript @@ -37,6 +37,7 @@ incs = [ '../../blenfont', '../../blenkernel', '../../blenlib', + '../../blentranslation', '../../bmesh', '../../gpu', '../../ikplugin', @@ -45,7 +46,8 @@ incs = [ '../../windowmanager', ] -defs = env['BF_GL_DEFINITIONS'] +defs = [] +defs += env['BF_GL_DEFINITIONS'] if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a889faba9a4..d6ce32f9974 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -86,7 +86,7 @@ #include "RNA_access.h" #include "BLF_api.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "transform.h" @@ -168,11 +168,12 @@ 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); +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]); +static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp); static void initVertSlide(TransInfo *t); static eRedrawFlag handleEventVertSlide(TransInfo *t, const struct wmEvent *event); static void applyVertSlide(TransInfo *t, const int mval[2]); @@ -1037,6 +1038,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } /* vert slide can fail on unconnected vertices (rare but possible) */ if (t->state == TRANS_CANCEL) { + t->mode = TFM_TRANSLATION; t->state = TRANS_STARTING; restoreTransObjects(t); resetTransRestrictions(t); @@ -1063,15 +1065,14 @@ int transformEvent(TransInfo *t, const wmEvent *event) /* 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) { - restoreTransObjects(t); initTrackball(t); } else { - restoreTransObjects(t); initRotation(t); } initSnapping(t, NULL); // need to reinit after mode change @@ -1363,15 +1364,14 @@ int transformEvent(TransInfo *t, const wmEvent *event) /* 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) { - restoreTransObjects(t); initTrackball(t); } else { - restoreTransObjects(t); initRotation(t); } initSnapping(t, NULL); // need to reinit after mode change @@ -1721,7 +1721,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) glVertex2fv(cent); glEnd(); - glTranslatef(mval[0], mval[1], 0); + glTranslate2iv(mval); glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1); setlinestyle(0); @@ -1733,7 +1733,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) case HLP_HARROW: UI_ThemeColor(TH_VIEW_OVERLAY); - glTranslatef(mval[0], mval[1], 0); + glTranslate2iv(mval); glLineWidth(3.0); drawArrow(RIGHT, 5, 10, 5); @@ -1743,7 +1743,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) case HLP_VARROW: UI_ThemeColor(TH_VIEW_OVERLAY); - glTranslatef(mval[0], mval[1], 0); + glTranslate2iv(mval); glLineWidth(3.0); drawArrow(UP, 5, 10, 5); @@ -1794,7 +1794,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) unsigned char col[3], col2[3]; UI_GetThemeColor3ubv(TH_GRID, col); - glTranslatef(mval[0], mval[1], 0); + glTranslate2iv(mval); glLineWidth(3.0); @@ -2077,47 +2077,41 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->launch_event = LEFTMOUSE; } + unit_m3(t->spacemtx); + initTransInfo(C, t, op, event); + initTransformOrientation(C, t); if (t->spacetype == SPACE_VIEW3D) { - initTransformOrientation(C, t); - 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), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_IMAGE) { - unit_m3(t->spacemtx); 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), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_CLIP) { - unit_m3(t->spacemtx); 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), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_NODE) { - unit_m3(t->spacemtx); /*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), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_IPO) { - unit_m3(t->spacemtx); 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), helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_ACTION) { - unit_m3(t->spacemtx); 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), helpline_poll, drawHelpline, t); } - else - unit_m3(t->spacemtx); createTransData(C, t); // make TransData structs from selection @@ -2234,14 +2228,20 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->mode = TFM_BONE_ENVELOPE_DIST; break; case TFM_EDGE_SLIDE: + case TFM_VERT_SLIDE: { - const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true); - initEdgeSlide_ex(t, use_double_side); + 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_VERT_SLIDE: - initVertSlide(t); - break; case TFM_BONE_ROLL: initBoneRoll(t); break; @@ -3092,6 +3092,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) float value; int i; char str[MAX_INFO_LEN]; + const bool is_local_center = transdata_check_local_center(t, t->around); copy_m3_m4(persmat, t->viewmat); invert_m3_m3(persinv, persmat); @@ -3127,8 +3128,10 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) mul_m3_m3m3(tmat, smat, persmat); mul_m3_m3m3(totmat, persinv, tmat); - + for (i = 0; i < t->total; i++, td++) { + const float *center, *co; + if (td->flag & TD_NOACTION) break; @@ -3143,12 +3146,22 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) else { copy_m3_m3(tmat, totmat); } - sub_v3_v3v3(vec, td->center, t->center); + + if (is_local_center) { + center = td->center; + co = td->loc; + } + else { + center = t->center; + co = td->center; + } + + sub_v3_v3v3(vec, co, center); mul_m3_v3(tmat, vec); - add_v3_v3(vec, t->center); - sub_v3_v3(vec, td->center); + add_v3_v3(vec, center); + sub_v3_v3(vec, co); mul_v3_fl(vec, td->factor); @@ -5967,7 +5980,7 @@ static void calcEdgeSlide_mval_range( } } -static void calcEdgeSlide_non_proportional( +static void calcEdgeSlide_even( TransInfo *t, EdgeSlideData *sld, const float mval[2]) { TransDataEdgeSlideVert *sv = sld->sv; @@ -6013,7 +6026,7 @@ static void calcEdgeSlide_non_proportional( } } -static bool createEdgeSlideVerts_double_side(TransInfo *t) +static bool createEdgeSlideVerts_double_side(TransInfo *t, bool use_even, bool flipped, bool use_clamp) { BMEditMesh *em = BKE_editmesh_from_object(t->obedit); BMesh *bm = em->bm; @@ -6032,9 +6045,11 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t) slide_origdata_init_flag(t, &sld->orig_data); - sld->is_proportional = true; + sld->use_even = use_even; sld->curr_sv_index = 0; - sld->flipped_vtx = false; + sld->flipped = flipped; + if (!use_clamp) + t->flag |= T_ALT_TRANSFORM; /*ensure valid selection*/ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -6340,7 +6355,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t) slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); if (rv3d) { - calcEdgeSlide_non_proportional(t, sld, mval); + calcEdgeSlide_even(t, sld, mval); } sld->em = em; @@ -6358,7 +6373,7 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t) * A simple version of #createEdgeSlideVerts_double_side * Which assumes the longest unselected. */ -static bool createEdgeSlideVerts_single_side(TransInfo *t) +static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool flipped, bool use_clamp) { BMEditMesh *em = BKE_editmesh_from_object(t->obedit); BMesh *bm = em->bm; @@ -6383,10 +6398,12 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t) slide_origdata_init_flag(t, &sld->orig_data); - sld->is_proportional = true; + sld->use_even = use_even; sld->curr_sv_index = 0; - /* heppans to be best for single-sided */ - sld->flipped_vtx = true; + /* happens to be best for single-sided */ + sld->flipped = !flipped; + if (!use_clamp) + t->flag |= T_ALT_TRANSFORM; /* ensure valid selection */ j = 0; @@ -6532,7 +6549,7 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t) slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); if (rv3d) { - calcEdgeSlide_non_proportional(t, sld, mval); + calcEdgeSlide_even(t, sld, mval); } sld->em = em; @@ -6580,7 +6597,7 @@ void freeEdgeSlideVerts(TransInfo *t) t->customData = NULL; } -static void initEdgeSlide_ex(TransInfo *t, bool use_double_side) +static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp) { EdgeSlideData *sld; bool ok; @@ -6590,10 +6607,10 @@ static void initEdgeSlide_ex(TransInfo *t, bool use_double_side) t->handleEvent = handleEventEdgeSlide; if (use_double_side) { - ok = createEdgeSlideVerts_double_side(t); + ok = createEdgeSlideVerts_double_side(t, use_even, flipped, use_clamp); } else { - ok = createEdgeSlideVerts_single_side(t); + ok = createEdgeSlideVerts_single_side(t, use_even, flipped, use_clamp); } if (!ok) { @@ -6627,7 +6644,7 @@ static void initEdgeSlide_ex(TransInfo *t, bool use_double_side) static void initEdgeSlide(TransInfo *t) { - initEdgeSlide_ex(t, true); + initEdgeSlide_ex(t, true, false, false, true); } static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event) @@ -6639,16 +6656,14 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven switch (event->type) { case EKEY: if (event->val == KM_PRESS) { - sld->is_proportional = !sld->is_proportional; + sld->use_even = !sld->use_even; calcEdgeSlideCustomPoints(t); return TREDRAW_HARD; } break; case FKEY: if (event->val == KM_PRESS) { - if (sld->is_proportional == false) { - sld->flipped_vtx = !sld->flipped_vtx; - } + sld->flipped = !sld->flipped; calcEdgeSlideCustomPoints(t); return TREDRAW_HARD; } @@ -6688,8 +6703,8 @@ static void drawEdgeSlide(TransInfo *t) EdgeSlideData *sld = t->customData; const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); - /* Non-Prop mode */ - if ((sld->is_proportional == false) || (is_clamp == false)) { + /* Even mode */ + if ((sld->use_even == true) || (is_clamp == false)) { View3D *v3d = t->view; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; @@ -6704,7 +6719,7 @@ static void drawEdgeSlide(TransInfo *t) glMultMatrixf(t->obedit->obmat); - if (sld->is_proportional == false) { + if (sld->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 = (sld->perc + 1.0f) / 2.0f; @@ -6731,7 +6746,7 @@ static void drawEdgeSlide(TransInfo *t) UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); glPointSize(ctrl_size); bglBegin(GL_POINTS); - if (sld->flipped_vtx) { + if (sld->flipped) { if (curr_sv->v_side[1]) bglVertex3fv(curr_sv->v_side[1]->co); } else { @@ -6807,7 +6822,7 @@ static void doEdgeSlide(TransInfo *t, float perc) sld->perc = perc; sv = svlist; - if (sld->is_proportional == true) { + if (sld->use_even == false) { const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); if (is_clamp) { const int side_index = (perc < 0.0f); @@ -6837,7 +6852,7 @@ static void doEdgeSlide(TransInfo *t, float perc) } else { /** - * Implementation note, non proportional mode ignores the starting positions and uses only the + * 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 * @@ -6845,7 +6860,7 @@ static void doEdgeSlide(TransInfo *t, float perc) * is the same as the distance between the original vert locations, same goes for the lines below. */ TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float curr_length_perc = curr_sv->edge_len * (((sld->flipped_vtx ? perc : -perc) + 1.0f) / 2.0f); + const float curr_length_perc = curr_sv->edge_len * (((sld->flipped ? perc : -perc) + 1.0f) / 2.0f); float co_a[3]; float co_b[3]; @@ -6857,7 +6872,7 @@ static void doEdgeSlide(TransInfo *t, float perc) 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 (sld->flipped_vtx) { + if (sld->flipped) { interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac); } else { @@ -6874,8 +6889,8 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) size_t ofs = 0; float final; EdgeSlideData *sld = t->customData; - bool flipped = sld->flipped_vtx; - bool is_proportional = sld->is_proportional; + bool flipped = sld->flipped; + bool use_even = sld->use_even; const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); @@ -6902,8 +6917,8 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) else { ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final); } - ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional)); - if (!is_proportional) { + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even)); + if (use_even) { ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); } ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); @@ -6944,7 +6959,7 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) 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 (sld->flipped_vtx && sld->is_proportional == false) { + if (sld->flipped && sld->use_even) { setCustomPoints(t, &t->mouse, mval_start, mval_end); } else { @@ -7035,7 +7050,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] } } -static bool createVertSlideVerts(TransInfo *t) +static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool use_clamp) { BMEditMesh *em = BKE_editmesh_from_object(t->obedit); BMesh *bm = em->bm; @@ -7049,9 +7064,11 @@ static bool createVertSlideVerts(TransInfo *t) slide_origdata_init_flag(t, &sld->orig_data); - sld->is_proportional = true; + sld->use_even = use_even; sld->curr_sv_index = 0; - sld->flipped_vtx = false; + sld->flipped = flipped; + if (!use_clamp) + t->flag |= T_ALT_TRANSFORM; j = 0; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -7185,7 +7202,7 @@ void freeVertSlideVerts(TransInfo *t) t->customData = NULL; } -static void initVertSlide(TransInfo *t) +static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp) { VertSlideData *sld; @@ -7193,7 +7210,7 @@ static void initVertSlide(TransInfo *t) t->transform = applyVertSlide; t->handleEvent = handleEventVertSlide; - if (!createVertSlideVerts(t)) { + if (!createVertSlideVerts(t, use_even, flipped, use_clamp)) { t->state = TRANS_CANCEL; return; } @@ -7222,6 +7239,11 @@ static void initVertSlide(TransInfo *t) t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } +static void initVertSlide(TransInfo *t) +{ + initVertSlide_ex(t, false, false, true); +} + static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event) { if (t->mode == TFM_VERT_SLIDE) { @@ -7231,8 +7253,8 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven switch (event->type) { case EKEY: if (event->val == KM_PRESS) { - sld->is_proportional = !sld->is_proportional; - if (sld->flipped_vtx) { + sld->use_even = !sld->use_even; + if (sld->flipped) { calcVertSlideCustomPoints(t); } return TREDRAW_HARD; @@ -7240,7 +7262,7 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven break; case FKEY: if (event->val == KM_PRESS) { - sld->flipped_vtx = !sld->flipped_vtx; + sld->flipped = !sld->flipped; calcVertSlideCustomPoints(t); return TREDRAW_HARD; } @@ -7339,7 +7361,7 @@ static void drawVertSlide(TransInfo *t) glPointSize(ctrl_size); bglBegin(GL_POINTS); - bglVertex3fv((sld->flipped_vtx && sld->is_proportional == false) ? + bglVertex3fv((sld->flipped && sld->use_even) ? curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : curr_sv->co_orig_3d); bglEnd(); @@ -7397,7 +7419,7 @@ static void doVertSlide(TransInfo *t, float perc) sld->perc = perc; sv = svlist; - if (sld->is_proportional == true) { + if (sld->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); } @@ -7415,7 +7437,7 @@ static void doVertSlide(TransInfo *t, float perc) edge_len = normalize_v3(dir); if (edge_len > FLT_EPSILON) { - if (sld->flipped_vtx) { + if (sld->flipped) { madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); } else { @@ -7435,8 +7457,8 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) size_t ofs = 0; float final; VertSlideData *sld = t->customData; - const bool flipped = sld->flipped_vtx; - const bool is_proportional = sld->is_proportional; + const bool flipped = sld->flipped; + const bool use_even = sld->use_even; const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); @@ -7463,8 +7485,8 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) else { ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final); } - ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(!is_proportional)); - if (!is_proportional) { + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), WM_bool_as_string(use_even)); + if (use_even) { ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), WM_bool_as_string(flipped)); } ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), WM_bool_as_string(is_clamp)); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index cdd260b3edb..e77ebfc4532 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -252,8 +252,8 @@ typedef struct EdgeSlideData { float perc; - bool is_proportional; - bool flipped_vtx; + bool use_even; + bool flipped; int curr_sv_index; @@ -284,8 +284,8 @@ typedef struct VertSlideData { float perc; - bool is_proportional; - bool flipped_vtx; + bool use_even; + bool flipped; int curr_sv_index; @@ -727,7 +727,7 @@ bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const floa struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], const char *name, const bool overwrite); -bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64]); +bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r_name[64], int index); #define ORIENTATION_NONE 0 #define ORIENTATION_NORMAL 1 @@ -735,7 +735,8 @@ bool applyTransformOrientation(const struct bContext *C, float mat[3][3], char r #define ORIENTATION_EDGE 3 #define ORIENTATION_FACE 4 -int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], const bool activeOnly); +int getTransformOrientation_ex(const struct bContext *C, float normal[3], float plane[3], const short around); +int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3]); void freeEdgeSlideTempFaces(EdgeSlideData *sld); void freeEdgeSlideVerts(TransInfo *t); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index b546ff9449c..895c8a81044 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -53,7 +53,7 @@ #include "ED_image.h" #include "ED_view3d.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "UI_resources.h" @@ -855,21 +855,15 @@ void getConstraintMatrix(TransInfo *t) unit_m3(t->con.pmtx); if (!(t->con.mode & CON_AXIS0)) { - t->con.pmtx[0][0] = - t->con.pmtx[0][1] = - t->con.pmtx[0][2] = 0.0f; + zero_v3(t->con.pmtx[0]); } if (!(t->con.mode & CON_AXIS1)) { - t->con.pmtx[1][0] = - t->con.pmtx[1][1] = - t->con.pmtx[1][2] = 0.0f; + zero_v3(t->con.pmtx[1]); } if (!(t->con.mode & CON_AXIS2)) { - t->con.pmtx[2][0] = - t->con.pmtx[2][1] = - t->con.pmtx[2][2] = 0.0f; + zero_v3(t->con.pmtx[2]); } mul_m3_m3m3(mat, t->con.pmtx, t->con.imtx); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 687cf2f69e4..5e13afdc152 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1252,7 +1252,18 @@ static void createTransArmatureVerts(TransInfo *t) else { if (ebo->flag & BONE_TIPSEL) { copy_v3_v3(td->iloc, ebo->tail); - copy_v3_v3(td->center, (t->around == V3D_LOCAL) ? ebo->head : td->iloc); + + /* Don't allow single selected tips to have a modified center, + * causes problem with snapping (see T45974). + * However, in rotation mode, we want to keep that 'rotate bone around root with + * only its tip selected' behavior (see T46325). */ + if ((t->around == V3D_LOCAL) && ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) { + copy_v3_v3(td->center, ebo->head); + } + else { + copy_v3_v3(td->center, td->iloc); + } + td->loc = ebo->tail; td->flag = TD_SELECTED; if (ebo->flag & BONE_EDITMODE_LOCKED) @@ -1655,7 +1666,7 @@ static void createTransCurveVerts(TransInfo *t) /* TODO - in the case of tilt and radius we can also avoid allocating the initTransDataCurveHandles * but for now just don't change handle types */ - if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT) == 0) { + if (ELEM(t->mode, TFM_CURVE_SHRINKFATTEN, TFM_TILT, TFM_DUMMY) == 0) { /* sets the handles based on their selection, do this after the data is copied to the TransData */ BKE_nurb_handles_test(nu, !hide_handles); } @@ -5548,7 +5559,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) { /* only insert into active keyingset - * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden spe + * NOTE: we assume here that the active Keying Set does not need to have its iterator overridden */ ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index d57d4fb3ca8..dc541c6da42 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -57,7 +57,7 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "RNA_access.h" @@ -1207,18 +1207,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->around = V3D_CURSOR; } - if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) && - RNA_property_is_set(op->ptr, prop))) - { - t->current_orientation = RNA_property_enum_get(op->ptr, prop); - - if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) { - t->current_orientation = V3D_MANIP_GLOBAL; - } - } - else { - t->current_orientation = v3d->twmode; - } + t->current_orientation = v3d->twmode; /* exceptional case */ if (t->around == V3D_LOCAL) { @@ -1305,6 +1294,16 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } t->around = V3D_CENTER; } + + if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) && + RNA_property_is_set(op->ptr, prop))) + { + t->current_orientation = RNA_property_enum_get(op->ptr, prop); + + if (t->current_orientation >= V3D_MANIP_CUSTOM + BIF_countTransformOrientation(C)) { + t->current_orientation = V3D_MANIP_GLOBAL; + } + } if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && RNA_property_is_set(op->ptr, prop))) @@ -1832,7 +1831,7 @@ void calculateCenter(TransInfo *t) /* zfac is only used convertViewVec only in cases operator was invoked in RGN_TYPE_WINDOW * and never used in other cases. * - * We need special case here as well, since ED_view3d_calc_zfac will crahs when called + * We need special case here as well, since ED_view3d_calc_zfac will crash when called * for a region different from RGN_TYPE_WINDOW. */ if (t->ar->regiontype == RGN_TYPE_WINDOW) { diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index acc6108f264..f13bc6b6b55 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -568,7 +568,7 @@ static int calc_manipulator_stats(const bContext *C) { if (obedit || ob->mode & OB_MODE_POSE) { float mat[3][3]; - ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE)); + ED_getTransformOrientationMatrix(C, mat, v3d->around); copy_m4_m3(rv3d->twmat, mat); break; } @@ -583,7 +583,7 @@ static int calc_manipulator_stats(const bContext *C) * and users who select many bones will understand whats going on and what local means * when they start transforming */ float mat[3][3]; - ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE)); + ED_getTransformOrientationMatrix(C, mat, v3d->around); copy_m4_m3(rv3d->twmat, mat); break; } @@ -602,7 +602,7 @@ static int calc_manipulator_stats(const bContext *C) default: /* V3D_MANIP_CUSTOM */ { float mat[3][3]; - if (applyTransformOrientation(C, mat, NULL)) { + if (applyTransformOrientation(C, mat, NULL, v3d->twmode - V3D_MANIP_CUSTOM)) { copy_m4_m3(rv3d->twmat, mat); } break; @@ -643,7 +643,7 @@ static void test_manipulator_axis(const bContext *C) static float screen_aligned(RegionView3D *rv3d, float mat[4][4]) { - glTranslatef(mat[3][0], mat[3][1], mat[3][2]); + glTranslate3fv(mat[3]); /* sets view screen aligned */ glRotatef(-360.0f * saacos(rv3d->viewquat[0]) / (float)M_PI, rv3d->viewquat[1], rv3d->viewquat[2], rv3d->viewquat[3]); @@ -923,7 +923,7 @@ static void draw_manipulator_rotate( /* prepare for screen aligned draw */ size = len_v3(rv3d->twmat[0]); glPushMatrix(); - glTranslatef(rv3d->twmat[3][0], rv3d->twmat[3][1], rv3d->twmat[3][2]); + glTranslate3fv(rv3d->twmat[3]); if (arcs) { /* clipplane makes nice handles, calc here because of multmatrix but with translate! */ @@ -1362,7 +1362,7 @@ static void draw_manipulator_translate( manipulator_axis_order(rv3d, axis_order); - // XXX if (moving) glTranslatef(t->vec[0], t->vec[1], t->vec[2]); + // XXX if (moving) glTranslate3fv(t->vec); glDisable(GL_DEPTH_TEST); /* center circle, do not add to selection when shift is pressed (planar constraint) */ diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 013e47886eb..45afeeb7da9 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -33,7 +33,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "BKE_context.h" #include "BKE_global.h" @@ -527,7 +527,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) RNA_def_enum(ot->srna, "proportional", proportional_editing_items, 0, "Proportional Editing", ""); prop = RNA_def_enum(ot->srna, "proportional_edit_falloff", proportional_falloff_items, 0, "Proportional Editing Falloff", "Falloff type for proportional editing mode"); - RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_CURVE); /* Abusing id_curve :/ */ RNA_def_float(ot->srna, "proportional_size", 1, 0.00001f, FLT_MAX, "Proportional Size", "", 0.001, 100); } @@ -643,8 +643,6 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot) static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) { - PropertyRNA *prop; - /* identifiers */ ot->name = "Trackball"; ot->description = "Trackball style rotation of selected items"; @@ -659,16 +657,13 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) ot->poll = ED_operator_screenactive; /* Maybe we could use float_vector_xyz here too? */ - prop = RNA_def_float_vector(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); - RNA_def_property_subtype(prop, PROP_ANGLE); + RNA_def_float_rotation(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP | P_GPENCIL_EDIT); } static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) { - PropertyRNA *prop; - /* identifiers */ ot->name = "Rotate"; ot->description = "Rotate selected items"; @@ -682,8 +677,7 @@ static void TRANSFORM_OT_rotate(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; - prop = RNA_def_float(ot->srna, "value", 0.0f, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); - RNA_def_property_subtype(prop, PROP_ANGLE); + RNA_def_float_rotation(ot->srna, "value", 0, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -M_PI * 2, M_PI * 2); Transform_Properties(ot, P_AXIS | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_GEO_SNAP | P_GPENCIL_EDIT); } @@ -857,6 +851,12 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) prop = RNA_def_boolean(ot->srna, "single_side", false, "Single Side", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + RNA_def_boolean(ot->srna, "use_even", false, "Even", + "Make the edge loop match the shape of the adjacent edge loop"); + RNA_def_boolean(ot->srna, "flipped", false, "Flipped", + "When Even mode is active, flips between the two adjacent edge loops"); + RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", + "Clamp within the edge extents"); Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV); } @@ -877,6 +877,12 @@ static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) ot->poll = ED_operator_editmesh_region_view3d; RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); + RNA_def_boolean(ot->srna, "use_even", false, "Even", + "Make the edge loop match the shape of the adjacent edge loop"); + RNA_def_boolean(ot->srna, "flipped", false, "Flipped", + "When Even mode is active, flips between the two adjacent edge loops"); + RNA_def_boolean(ot->srna, "use_clamp", true, "Clamp", + "Clamp within the edge extents"); Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV); } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 7fea8e163fd..a1bb6f4e0f3 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -36,6 +36,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "BLI_math.h" @@ -52,7 +53,7 @@ #include "BKE_main.h" #include "BKE_screen.h" -#include "BLF_translation.h" +#include "BLT_translation.h" #include "ED_armature.h" @@ -85,7 +86,7 @@ static bool uniqueOrientationNameCheck(void *arg, const char *name) static void uniqueOrientationName(ListBase *lb, char *name) { - BLI_uniquename_cb(uniqueOrientationNameCheck, lb, CTX_DATA_(BLF_I18NCONTEXT_ID_SCENE, "Space"), '.', name, + BLI_uniquename_cb(uniqueOrientationNameCheck, lb, CTX_DATA_(BLT_I18NCONTEXT_ID_SCENE, "Space"), '.', name, sizeof(((TransformOrientation *)NULL)->name)); } @@ -144,7 +145,7 @@ static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, float mat[3][3]; float normal[3], plane[3]; - getTransformOrientation(C, normal, plane, 0); + getTransformOrientation(C, normal, plane); if (createSpaceNormalTangent(mat, normal, plane) == 0) { BKE_reports_prepend(reports, "Cannot use zero-length bone"); @@ -164,7 +165,7 @@ static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports, float mat[3][3]; float normal[3], plane[3]; - getTransformOrientation(C, normal, plane, 0); + getTransformOrientation(C, normal, plane); if (createSpaceNormalTangent(mat, normal, plane) == 0) { BKE_reports_prepend(reports, "Cannot use zero-length curve"); @@ -186,7 +187,7 @@ static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, float normal[3], plane[3]; int type; - type = getTransformOrientation(C, normal, plane, 0); + type = getTransformOrientation(C, normal, plane); switch (type) { case ORIENTATION_VERT: @@ -390,15 +391,12 @@ int BIF_countTransformOrientation(const bContext *C) return BLI_listbase_count(transform_spaces); } -bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name) +bool applyTransformOrientation(const bContext *C, float mat[3][3], char *r_name, int index) { - View3D *v3d = CTX_wm_view3d(C); - int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); - ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces; - TransformOrientation *ts = BLI_findlink(transform_spaces, selected_index); + TransformOrientation *ts = BLI_findlink(transform_spaces, index); - BLI_assert(selected_index >= 0); + BLI_assert(index >= 0); if (ts) { if (r_name) { @@ -442,7 +440,6 @@ static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it) void initTransformOrientation(bContext *C, TransInfo *t) { - View3D *v3d = CTX_wm_view3d(C); Object *ob = CTX_data_active_object(C); Object *obedit = CTX_data_active_object(C); @@ -462,7 +459,7 @@ void initTransformOrientation(bContext *C, TransInfo *t) case V3D_MANIP_NORMAL: if (obedit || (ob && ob->mode & OB_MODE_POSE)) { BLI_strncpy(t->spacename, IFACE_("normal"), sizeof(t->spacename)); - ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE)); + ED_getTransformOrientationMatrix(C, t->spacemtx, t->around); break; } /* fall-through */ /* we define 'normal' as 'local' in Object mode */ @@ -480,7 +477,9 @@ void initTransformOrientation(bContext *C, TransInfo *t) break; case V3D_MANIP_VIEW: - if (t->ar->regiontype == RGN_TYPE_WINDOW) { + if ((t->spacetype == SPACE_VIEW3D) && + (t->ar->regiontype == RGN_TYPE_WINDOW)) + { RegionView3D *rv3d = t->ar->regiondata; float mat[3][3]; @@ -494,7 +493,7 @@ void initTransformOrientation(bContext *C, TransInfo *t) } break; default: /* V3D_MANIP_CUSTOM */ - if (applyTransformOrientation(C, t->spacemtx, t->spacename)) { + if (applyTransformOrientation(C, t->spacemtx, t->spacename, t->current_orientation - V3D_MANIP_CUSTOM)) { /* pass */ } else { @@ -585,14 +584,14 @@ static unsigned int bm_mesh_faces_select_get_n(BMesh *bm, BMVert **elems, const } #endif -int getTransformOrientation(const bContext *C, float normal[3], float plane[3], const bool activeOnly) +int getTransformOrientation_ex(const bContext *C, float normal[3], float plane[3], const short around) { Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); Object *obedit = CTX_data_edit_object(C); Base *base; Object *ob = OBACT; int result = ORIENTATION_NONE; + const bool activeOnly = (around == V3D_ACTIVE); zero_v3(normal); zero_v3(plane); @@ -718,7 +717,6 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], /* should never fail */ if (LIKELY(v_pair[0] && v_pair[1])) { bool v_pair_swap = false; - float tvec[3]; /** * Logic explained: * @@ -749,11 +747,6 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], sub_v3_v3v3(plane, v_pair[0]->co, v_pair[1]->co); /* flip the plane normal so we point outwards */ negate_v3(plane); - - /* align normal to edge direction (so normal is perpendicular to the plane). - * 'ORIENTATION_EDGE' will do the other way around */ - project_v3_v3v3(tvec, normal, plane); - sub_v3_v3(normal, tvec); } result = ORIENTATION_EDGE; @@ -861,7 +854,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], /* exception */ if (flag) { float tvec[3]; - if ((v3d->around == V3D_LOCAL) || + if ((around == V3D_LOCAL) || ELEM(flag, SEL_F2, SEL_F1 | SEL_F3, SEL_F1 | SEL_F2 | SEL_F3)) { BKE_nurb_bezt_calc_normal(nu, bezt, tvec); @@ -962,8 +955,16 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], /* Vectors from edges don't need the special transpose inverse multiplication */ if (result == ORIENTATION_EDGE) { + float tvec[3]; + mul_mat3_m4_v3(ob->obmat, normal); mul_mat3_m4_v3(ob->obmat, plane); + + /* align normal to edge direction (so normal is perpendicular to the plane). + * 'ORIENTATION_EDGE' will do the other way around. + * This has to be done **after** applying obmat, see T45775! */ + project_v3_v3v3(tvec, normal, plane); + sub_v3_v3(normal, tvec); } else { mul_m3_v3(mat, normal); @@ -1015,6 +1016,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } else { /* we need the one selected object, if its not active */ + View3D *v3d = CTX_wm_view3d(C); ob = OBACT; if (ob && (ob->flag & SELECT)) { /* pass */ @@ -1040,14 +1042,22 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], return result; } -void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const bool activeOnly) +int getTransformOrientation(const bContext *C, float normal[3], float plane[3]) +{ + /* dummy value, not V3D_ACTIVE and not V3D_LOCAL */ + short around = V3D_CENTER; + + return getTransformOrientation_ex(C, normal, plane, around); +} + +void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const short around) { float normal[3] = {0.0, 0.0, 0.0}; float plane[3] = {0.0, 0.0, 0.0}; int type; - type = getTransformOrientation(C, normal, plane, activeOnly); + type = getTransformOrientation_ex(C, normal, plane, around); switch (type) { case ORIENTATION_NORMAL: diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 3b488fde2b3..0e954d40c18 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -85,6 +85,8 @@ #define TRANSFORM_DIST_MAX_PX 1000.0f #define TRANSFORM_SNAP_MAX_PX 100.0f +#define TRANSFORM_DIST_INVALID NAN_FLT + /* use half of flt-max so we can scale up without an exception */ /********************* PROTOTYPES ***********************/ @@ -220,7 +222,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) h = (((float)hi) / IMG_SIZE_FALLBACK) * G.sima->zoom * yuser_asp; cpack(0xFFFFFF); - glTranslatef(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], 0.0f); + glTranslate2fv(t->tsnap.snapPoint); //glRectf(0, 0, 1, 1); @@ -810,14 +812,18 @@ static void ApplySnapRotation(TransInfo *t, float *value) static void ApplySnapResize(TransInfo *t, float vec[3]) { + float dist; + if (t->tsnap.target == SCE_SNAP_TARGET_CLOSEST) { - vec[0] = vec[1] = vec[2] = t->tsnap.dist; + dist = t->tsnap.dist; } else { float point[3]; getSnapPoint(t, point); - vec[0] = vec[1] = vec[2] = ResizeBetween(t, t->tsnap.snapTarget, point); + dist = ResizeBetween(t, t->tsnap.snapTarget, point); } + + copy_v3_fl(vec, dist); } /********************** DISTANCE **************************/ @@ -884,6 +890,8 @@ static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) sub_v3_v3v3(d1, p1, t->center_global); sub_v3_v3v3(d2, p2, t->center_global); + project_v3_v3v3(d1, d1, d2); + if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { mul_m3_v3(t->con.pmtx, d1); mul_m3_v3(t->con.pmtx, d2); @@ -891,7 +899,10 @@ static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) len_d1 = len_v3(d1); - return len_d1 != 0.0f ? len_v3(d2) / len_d1 : 1; + /* Use 'invalid' dist when `center == p1` (after projecting), + * in this case scale will _never_ move the point in relation to the center, + * so it makes no sense to take it into account when scaling. see: T46503 */ + return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID; } /********************** CALC **************************/ @@ -975,7 +986,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) break; } - new_dist = len_v3v3(last_p, vec); + new_dist = len_squared_v3v3(last_p, vec); if (new_dist < max_dist) { copy_v3_v3(p, vec); @@ -996,6 +1007,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) BLI_freelistN(&depth_peels); } else { + zero_v3(no); /* objects won't set this */ found = snapObjectsTransform(t, mval, &dist_px, loc, no, t->tsnap.modeSelect); } @@ -1170,8 +1182,10 @@ static void TargetSnapClosest(TransInfo *t) mul_m4_v3(td->ext->obmat, loc); dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); - - if (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)) { + + if ((dist != TRANSFORM_DIST_INVALID) && + (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist))) + { copy_v3_v3(t->tsnap.snapTarget, loc); closest = td; t->tsnap.dist = dist; @@ -1186,8 +1200,10 @@ static void TargetSnapClosest(TransInfo *t) copy_v3_v3(loc, td->center); dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); - - if (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)) { + + if ((dist != TRANSFORM_DIST_INVALID) && + (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist))) + { copy_v3_v3(t->tsnap.snapTarget, loc); closest = td; t->tsnap.dist = dist; @@ -1210,7 +1226,9 @@ static void TargetSnapClosest(TransInfo *t) dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); - if (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist)) { + if ((dist != TRANSFORM_DIST_INVALID) && + (closest == NULL || fabsf(dist) < fabsf(t->tsnap.dist))) + { copy_v3_v3(t->tsnap.snapTarget, loc); closest = td; t->tsnap.dist = dist; @@ -1520,8 +1538,17 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes if (do_bb) { BoundBox *bb = BKE_object_boundbox_get(ob); - if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) { - return retval; + + if (bb) { + BoundBox bb_temp; + + /* We cannot aford a bbox with some null dimension, which may happen in some cases... + * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ + bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); + + if (!BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, &len_diff)) { + return retval; + } } } else if (do_ray_start_correction) { @@ -1533,6 +1560,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes len_diff = 0.0f; /* In case BVHTree would fail for some reason... */ treeData.em_evil = em; + treeData.em_evil_all = false; bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 2, 6); if (treeData.tree != NULL) { nearest.index = -1; @@ -1575,6 +1603,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes } treeData.em_evil = em; + treeData.em_evil_all = false; bvhtree_from_mesh_looptri(&treeData, dm, 0.0f, 4, 6); hit.index = -1; @@ -1847,8 +1876,16 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f do_bb = false; } else { + /* in this case we want the mesh from the editmesh, avoids stale data. see: T45978. + * still set the 'em' to NULL, since we only want the 'dm'. */ + em = BKE_editmesh_from_object(ob); + if (em) { + editbmesh_get_derived_cage_and_final(scene, ob, em, CD_MASK_BAREMESH, &dm); + } + else { + dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + } em = NULL; - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); } retval = snapDerivedMesh(snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, ray_origin, mval, r_loc, r_no, r_dist_px, r_depth, do_bb); @@ -1968,8 +2005,20 @@ static bool snapObjects(Scene *scene, short snap_mode, Base *base_act, View3D *v bool snapObjectsTransform(TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) { float ray_dist = TRANSFORM_DIST_MAX_RAY; - return snapObjects(t->scene, t->scene->toolsettings->snap_mode, t->scene->basact, t->view, t->ar, t->obedit, - mval, r_dist_px, r_loc, r_no, &ray_dist, mode); + Object *obedit = NULL; + Base *base_act = NULL; + + if (t->flag & T_EDIT) { + obedit = t->obedit; + } + + if ((t->options & CTX_GPENCIL_STROKES) == 0) { + base_act = t->scene->basact; + } + + return snapObjects( + t->scene, t->scene->toolsettings->snap_mode, base_act, t->view, t->ar, obedit, + mval, r_dist_px, r_loc, r_no, &ray_dist, mode); } bool snapObjectsContext(bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) @@ -2056,21 +2105,62 @@ static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float n peel->flag = 0; } -static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]), - ListBase *depth_peels) +struct PeelRayCast_Data { + BVHTreeFromMesh bvhdata; + + /* internal vars for adding peel */ + Object *ob; + const float (*obmat)[4]; + const float (*timat)[3]; + + const float *ray_start; /* globalspace */ + + const MLoopTri *looptri; + const float (*polynors)[3]; /* optional, can be NULL */ + + /* output list */ + ListBase *depth_peels; +}; + +static void peelRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + struct PeelRayCast_Data *data = userdata; + + data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit); + + if (hit->index != -1) { + /* get all values in worldspace */ + float location[3], normal[3]; + float depth; + + /* worldspace location */ + mul_v3_m4v3(location, (float (*)[4])data->obmat, hit->co); + depth = len_v3v3(location, data->ray_start); + + /* worldspace normal */ + copy_v3_v3(normal, data->polynors ? data->polynors[data->looptri[hit->index].poly] : hit->no); + mul_m3_v3((float (*)[3])data->timat, normal); + normalize_v3(normal); + + addDepthPeel(data->depth_peels, depth, location, normal, data->ob); + } +} + +static bool peelDerivedMesh( + Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]), + ListBase *depth_peels) { bool retval = false; int totvert = dm->getNumVerts(dm); if (totvert > 0) { const MLoopTri *looptri = dm->getLoopTriArray(dm); - const MLoop *mloop = dm->getLoopArray(dm); - int looptri_num = dm->getNumLoopTri(dm); + const int looptri_num = dm->getNumLoopTri(dm); float imat[4][4]; float timat[3][3]; /* transpose inverse matrix for normals */ float ray_start_local[3], ray_normal_local[3]; - int test = 1; + bool test = true; invert_m4_m4(imat, obmat); @@ -2083,56 +2173,41 @@ static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], * test against boundbox first * */ if (looptri_num > 16) { - struct BoundBox *bb = BKE_object_boundbox_get(ob); - test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL); - } - - if (test == 1) { - const MLoopTri *lt; - MVert *verts = dm->getVertArray(dm); - float (*polynors)[3] = dm->getPolyDataArray(dm, CD_NORMAL); - int i; - - for (i = 0, lt = looptri; i < looptri_num; i++, lt++) { - const unsigned int vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v}; - float lambda; - int result; - - - result = isect_ray_tri_threshold_v3( - ray_start_local, ray_normal_local, - verts[vtri[0]].co, verts[vtri[1]].co, verts[vtri[2]].co, - &lambda, NULL, 0.001); - - if (result) { - float location[3], normal[3]; - float intersect[3]; - float new_depth; - - copy_v3_v3(intersect, ray_normal_local); - mul_v3_fl(intersect, lambda); - add_v3_v3(intersect, ray_start_local); - - copy_v3_v3(location, intersect); + BoundBox *bb = BKE_object_boundbox_get(ob); - if (polynors) { - copy_v3_v3(normal, polynors[lt->poly]); - } - else { - normal_tri_v3(normal, verts[vtri[0]].co, verts[vtri[1]].co, verts[vtri[2]].co); - } + if (bb) { + BoundBox bb_temp; - mul_m4_v3(obmat, location); - - new_depth = len_v3v3(location, ray_start); - - mul_m3_v3(timat, normal); - normalize_v3(normal); + /* We cannot aford a bbox with some null dimension, which may happen in some cases... + * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */ + bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f); - addDepthPeel(depth_peels, new_depth, location, normal, ob); - } + test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL); } } + + if (test == true) { + struct PeelRayCast_Data data; + + data.bvhdata.em_evil = em; + data.bvhdata.em_evil_all = false; + bvhtree_from_mesh_looptri(&data.bvhdata, dm, 0.0f, 4, 6); + + if (data.bvhdata.tree != NULL) { + data.ob = ob; + data.obmat = (const float (*)[4])obmat; + data.timat = (const float (*)[3])timat; + data.ray_start = ray_start; + data.looptri = looptri; + data.polynors = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */ + data.depth_peels = depth_peels; + + BLI_bvhtree_ray_cast_all(data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f, + peelRayCast_cb, &data); + } + + free_bvhtree_from_mesh(&data.bvhdata); + } } return retval; @@ -2168,13 +2243,13 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, if (dob != obedit) { dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH); - val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, depth_peels); + val = peelDerivedMesh(dob, dm, NULL, dob->obmat, ray_start, ray_normal, mval, depth_peels); } else { em = BKE_editmesh_from_object(dob); dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH); - val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, depth_peels); + val = peelDerivedMesh(dob, dm, em, dob->obmat, ray_start, ray_normal, mval, depth_peels); } retval = retval || val; @@ -2192,14 +2267,14 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, if (ob != obedit && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT))) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); - val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); + val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, depth_peels); dm->release(dm); } else if (ob == obedit && mode != SNAP_NOT_OBEDIT) { BMEditMesh *em = BKE_editmesh_from_object(ob); DerivedMesh *dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH); - val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, depth_peels); + val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, depth_peels); dm->release(dm); } |