diff options
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r-- | source/blender/editors/transform/SConscript | 28 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 1487 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 112 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_constraints.c | 55 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 223 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 78 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_input.c | 44 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_manipulator.c | 442 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_ops.c | 100 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_orientations.c | 117 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_snap.c | 134 |
11 files changed, 1987 insertions, 833 deletions
diff --git a/source/blender/editors/transform/SConscript b/source/blender/editors/transform/SConscript index 9cf36a2d970..d579fd73db3 100644 --- a/source/blender/editors/transform/SConscript +++ b/source/blender/editors/transform/SConscript @@ -1,4 +1,30 @@ -#!/usr/bin/python +#!/usr/bin/env python +# +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Nathan Letwory. +# +# ***** END GPL LICENSE BLOCK ***** + Import ('env') sources = env.Glob('*.c') diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d877d506e3e..64e49abd761 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -52,12 +52,14 @@ #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ -#include "RNA_access.h" - -#include "BIF_gl.h" -#include "BIF_glutil.h" - -#include "BLF_api.h" +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_rect.h" +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_smallhash.h" #include "BKE_nla.h" #include "BKE_bmesh.h" @@ -69,6 +71,9 @@ #include "BKE_unit.h" #include "BKE_mask.h" +#include "BIF_gl.h" +#include "BIF_glutil.h" + #include "ED_image.h" #include "ED_keyframing.h" #include "ED_screen.h" @@ -79,25 +84,38 @@ #include "ED_clip.h" #include "ED_mask.h" -#include "UI_view2d.h" #include "WM_types.h" #include "WM_api.h" -#include "BLI_math.h" -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" -#include "BLI_ghash.h" -#include "BLI_linklist.h" -#include "BLI_smallhash.h" -#include "BLI_array.h" - +#include "UI_view2d.h" #include "UI_interface_icons.h" #include "UI_resources.h" +#include "RNA_access.h" + +#include "BLF_api.h" +#include "BLF_translation.h" + #include "transform.h" +#define MAX_INFO_LEN 256 + static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg); static int doEdgeSlide(TransInfo *t, float perc); +static int doVertSlide(TransInfo *t, float perc); + +static void drawEdgeSlide(const struct bContext *C, TransInfo *t); +static void drawVertSlide(const struct bContext *C, TransInfo *t); + +static bool transdata_check_local_center(TransInfo *t) +{ + return ((t->around == V3D_LOCAL) && ( + (t->flag & (T_OBJECT | T_POSE)) || + (t->obedit && t->obedit->type == OB_MESH && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) || + (t->obedit && t->obedit->type == OB_ARMATURE) || + (t->spacetype == SPACE_IPO)) + ); +} /* ************************** SPACE DEPENDANT CODE **************************** */ @@ -167,7 +185,7 @@ 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); + ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac); } else if (t->spacetype == SPACE_IMAGE) { float aspx, aspy; @@ -223,11 +241,11 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) } } -void projectIntView(TransInfo *t, const float vec[3], int adr[2]) +void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag) { if (t->spacetype == SPACE_VIEW3D) { if (t->ar->regiontype == RGN_TYPE_WINDOW) { - if (ED_view3d_project_int_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + if (ED_view3d_project_int_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { adr[0] = (int)2140000000.0f; /* this is what was done in 2.64, perhaps we can be smarter? */ adr[1] = (int)2140000000.0f; } @@ -345,14 +363,19 @@ void projectIntView(TransInfo *t, const float vec[3], int adr[2]) UI_view2d_to_region_no_clip((View2D *)t->view, vec[0], vec[1], adr, adr + 1); } } +void projectIntView(TransInfo *t, const float vec[3], int adr[2]) +{ + projectIntViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); +} -void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) +void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag) { switch (t->spacetype) { case SPACE_VIEW3D: { if (t->ar->regiontype == RGN_TYPE_WINDOW) { - if (ED_view3d_project_float_global(t->ar, vec, adr, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + /* allow points behind the view [#33643] */ + if (ED_view3d_project_float_global(t->ar, vec, adr, flag) != V3D_PROJ_RET_OK) { /* XXX, 2.64 and prior did this, weak! */ adr[0] = t->ar->winx / 2.0f; adr[1] = t->ar->winy / 2.0f; @@ -376,6 +399,10 @@ void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) zero_v2(adr); } +void projectFloatView(TransInfo *t, const float vec[3], float adr[2]) +{ + projectFloatViewEx(t, vec, adr, V3D_PROJ_TEST_NOP); +} void applyAspectRatio(TransInfo *t, float vec[2]) { @@ -461,7 +488,10 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); else WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - + + if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) + WM_event_add_notifier(C, NC_GEOM | ND_DATA, 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)) @@ -685,6 +715,9 @@ static void view_editmove(unsigned short UNUSED(event)) #define TFM_MODAL_EDGESLIDE_UP 24 #define TFM_MODAL_EDGESLIDE_DOWN 25 +/* for analog input, like trackpad */ +#define TFM_MODAL_PROPSIZE 26 + /* called in transform_ops.c, on each regeneration of keymaps */ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) { @@ -714,6 +747,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) {TFM_MODAL_AUTOIK_LEN_DEC, "AUTOIK_CHAIN_LEN_DOWN", 0, "Decrease Max AutoIK Chain Length", ""}, {TFM_MODAL_EDGESLIDE_UP, "EDGESLIDE_EDGE_NEXT", 0, "Select next Edge Slide Edge", ""}, {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""}, + {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""}, {0, NULL, 0, NULL, NULL} }; @@ -749,6 +783,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN); WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP); WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN); + WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, TFM_MODAL_PROPSIZE); WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_UP); WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_ALT, 0, TFM_MODAL_EDGESLIDE_DOWN); @@ -766,22 +801,29 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm if (!(t->flag & T_NO_CONSTRAINT)) { int constraint_axis, constraint_plane; int edit_2d = (t->flag & T_2D_EDIT); - char msg1[] = "along _"; - char msg2[] = "along %s _"; - char msg3[] = "locking %s _"; + const char *msg1 = "", *msg2 = "", *msg3 = ""; char axis; /* Initialize */ switch (key_type) { case XKEY: + msg1 = IFACE_("along X"); + msg2 = IFACE_("along %s X"); + msg3 = IFACE_("locking %s X"); axis = 'X'; constraint_axis = CON_AXIS0; break; case YKEY: + msg1 = IFACE_("along Y"); + msg2 = IFACE_("along %s Y"); + msg3 = IFACE_("locking %s Y"); axis = 'Y'; constraint_axis = CON_AXIS1; break; case ZKEY: + msg1 = IFACE_("along Z"); + msg2 = IFACE_("along %s Z"); + msg3 = IFACE_("locking %s Z"); axis = 'Z'; constraint_axis = CON_AXIS2; break; @@ -789,9 +831,6 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm /* Invalid key */ return; } - msg1[sizeof(msg1) - 2] = axis; - msg2[sizeof(msg2) - 2] = axis; - msg3[sizeof(msg3) - 2] = axis; constraint_plane = ((CON_AXIS0 | CON_AXIS1 | CON_AXIS2) & (~constraint_axis)); if (edit_2d && (key_type != ZKEY)) { @@ -827,7 +866,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm } } -int transformEvent(TransInfo *t, wmEvent *event) +int transformEvent(TransInfo *t, const wmEvent *event) { float mati[3][3] = MAT3_UNITY; char cmode = constraintModeToChar(t); @@ -866,19 +905,56 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case TFM_MODAL_TRANSLATE: /* only switch when... */ - if (ELEM3(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL) ) { + if (ELEM5(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL, TFM_EDGE_SLIDE, TFM_VERT_SLIDE)) { + if (t->mode == TFM_EDGE_SLIDE) { + freeEdgeSlideVerts(t); + } + else if (t->mode == TFM_VERT_SLIDE) { + freeVertSlideVerts(t); + } resetTransRestrictions(t); restoreTransObjects(t); initTranslation(t); initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); } - else if (t->mode == TFM_TRANSLATION) { - if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { - restoreTransObjects(t); + else if (t->mode == TFM_SEQ_SLIDE) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } + else { + if (t->obedit && t->obedit->type == OB_MESH) { + if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { + resetTransRestrictions(t); + restoreTransObjects(t); - t->flag ^= T_ALT_TRANSFORM; - t->redraw |= TREDRAW_HARD; + /* first try edge slide */ + initEdgeSlide(t); + /* if that fails, do vertex slide */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + initVertSlide(t); + } + /* vert slide can fail on unconnected vertices (rare but possible) */ + if (t->state == TRANS_CANCEL) { + t->state = TRANS_STARTING; + resetTransRestrictions(t); + restoreTransObjects(t); + initTranslation(t); + } + initSnapping(t, NULL); // need to reinit after mode change + t->redraw |= TREDRAW_HARD; + WM_event_add_mousemove(t->context); + } + } + else if (t->options & (CTX_MOVIECLIP | CTX_MASK)) { + if (t->mode == TFM_TRANSLATION) { + restoreTransObjects(t); + + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } } } break; @@ -911,6 +987,10 @@ int transformEvent(TransInfo *t, wmEvent *event) initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; } + else if (t->mode == TFM_SHRINKFATTEN) { + t->flag ^= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } else if (t->mode == TFM_RESIZE) { if (t->options & CTX_MOVIECLIP) { restoreTransObjects(t); @@ -940,10 +1020,10 @@ int transformEvent(TransInfo *t, wmEvent *event) } else { if (t->flag & T_2D_EDIT) { - setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), "along X"); + setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS0), IFACE_("along X")); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0), "along %s X"); + setUserConstraint(t, t->current_orientation, (CON_AXIS0), IFACE_("along %s X")); } } t->redraw |= TREDRAW_HARD; @@ -956,10 +1036,10 @@ int transformEvent(TransInfo *t, wmEvent *event) } else { if (t->flag & T_2D_EDIT) { - setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), "along Y"); + setUserConstraint(t, V3D_MANIP_GLOBAL, (CON_AXIS1), IFACE_("along Y")); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS1), "along %s Y"); + setUserConstraint(t, t->current_orientation, (CON_AXIS1), IFACE_("along %s Y")); } } t->redraw |= TREDRAW_HARD; @@ -971,7 +1051,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS2), "along %s Z"); + setUserConstraint(t, t->current_orientation, (CON_AXIS2), IFACE_("along %s Z")); } t->redraw |= TREDRAW_HARD; } @@ -982,7 +1062,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), "locking %s X"); + setUserConstraint(t, t->current_orientation, (CON_AXIS1 | CON_AXIS2), IFACE_("locking %s X")); } t->redraw |= TREDRAW_HARD; } @@ -993,7 +1073,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), "locking %s Y"); + setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS2), IFACE_("locking %s Y")); } t->redraw |= TREDRAW_HARD; } @@ -1004,7 +1084,7 @@ int transformEvent(TransInfo *t, wmEvent *event) stopConstraint(t); } else { - setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), "locking %s Z"); + setUserConstraint(t, t->current_orientation, (CON_AXIS0 | CON_AXIS1), IFACE_("locking %s Z")); } t->redraw |= TREDRAW_HARD; } @@ -1023,6 +1103,19 @@ int transformEvent(TransInfo *t, wmEvent *event) removeSnapPoint(t); t->redraw |= TREDRAW_HARD; break; + + case TFM_MODAL_PROPSIZE: + /* MOUSEPAN usage... */ + if (t->flag & T_PROP_EDIT) { + float fac = 1.0f + 0.005f *(event->y - event->prevy); + t->prop_size *= fac; + if (t->spacetype == SPACE_VIEW3D && t->persp != RV3D_ORTHO) + t->prop_size = min_ff(t->prop_size, ((View3D *)t->view)->far); + calculatePropRatio(t); + } + t->redraw |= TREDRAW_HARD; + break; + case TFM_MODAL_PROPSIZE_UP: if (t->flag & T_PROP_EDIT) { t->prop_size *= 1.1f; @@ -1096,7 +1189,7 @@ int transformEvent(TransInfo *t, wmEvent *event) /* exception for switching to dolly, or trackball, in camera view */ if (t->flag & T_CAMERA) { if (t->mode == TFM_TRANSLATION) - setLocalConstraint(t, (CON_AXIS2), "along local Z"); + setLocalConstraint(t, (CON_AXIS2), IFACE_("along local Z")); else if (t->mode == TFM_ROTATION) { restoreTransObjects(t); initTrackball(t); @@ -1207,7 +1300,9 @@ int transformEvent(TransInfo *t, wmEvent *event) if (t->flag & T_AUTOIK) { transform_autoik_update(t, 1); } - else view_editmove(event->type); + else { + view_editmove(event->type); + } t->redraw = 1; break; case PADMINUS: @@ -1222,7 +1317,9 @@ int transformEvent(TransInfo *t, wmEvent *event) if (t->flag & T_AUTOIK) { transform_autoik_update(t, -1); } - else view_editmove(event->type); + else { + view_editmove(event->type); + } t->redraw = 1; break; case LEFTALTKEY: @@ -1460,7 +1557,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) if (ob) mul_m4_v3(ob->obmat, vecrot); } - projectFloatView(t, vecrot, cent); // no overflow in extreme cases + projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO); glPushMatrix(); @@ -1499,7 +1596,6 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) glTranslatef(mval[0], mval[1], 0); glLineWidth(3.0); - glBegin(GL_LINES); drawArrow(UP, 5, 10, 5); drawArrow(DOWN, 5, 10, 5); glLineWidth(1.0); @@ -1579,26 +1675,36 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi drawConstraint(t); drawPropCircle(C, t); drawSnapping(C, t); - drawNonPropEdge(C, t); + + /* edge slide, vert slide */ + drawEdgeSlide(C, t); + drawVertSlide(C, t); } /* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) { - const char printable[] = "Auto Keying On"; + rcti rect; + const char *printable = IFACE_("Auto Keying On"); float printable_size[2]; int xco, yco; + ED_region_visible_rect(ar, &rect); + BLF_width_and_height_default(printable, &printable_size[0], &printable_size[1]); - xco = ar->winx - (int)printable_size[0] - 10; - yco = ar->winy - (int)printable_size[1] - 10; + xco = rect.xmax - (int)printable_size[0] - 10; + yco = rect.ymax - (int)printable_size[1] - 10; /* 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, sizeof(printable)); +#else BLF_draw_default_ascii(xco, ar->winy - 17, 0.0f, printable, sizeof(printable)); +#endif /* autokey recording icon... */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1754,7 +1860,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } /* note: caller needs to free 't' on a 0 return */ -int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int mode) +int initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode) { int options = 0; PropertyRNA *prop; @@ -1855,6 +1961,8 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int } + t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); + initSnapping(t, op); // Initialize snapping data AFTER mode flags /* EVIL! posemode code can switch translation to rotate when 1 bone is selected. will be removed (ton) */ @@ -1925,6 +2033,9 @@ int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int case TFM_EDGE_SLIDE: initEdgeSlide(t); break; + case TFM_VERT_SLIDE: + initVertSlide(t); + break; case TFM_BONE_ROLL: initBoneRoll(t); break; @@ -2056,12 +2167,6 @@ void transformApply(bContext *C, TransInfo *t) t->state = TRANS_CONFIRM; } - if (BKE_ptcache_get_continue_physics()) { - // TRANSFORM_FIX_ME - //do_screenhandlers(G.curscreen); - t->redraw |= TREDRAW_HARD; - } - t->context = NULL; } @@ -2254,8 +2359,8 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu static void constraintTransLim(TransInfo *t, TransData *td) { if (td->con) { - bConstraintTypeInfo *ctiLoc = get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT); - bConstraintTypeInfo *ctiDist = get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT); + bConstraintTypeInfo *ctiLoc = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT); + bConstraintTypeInfo *ctiDist = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT); bConstraintOb cob = {NULL}; bConstraint *con; @@ -2274,7 +2379,7 @@ static void constraintTransLim(TransInfo *t, TransData *td) ListBase targets = {NULL, NULL}; /* only consider constraint if enabled */ - if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue; if (con->enforce == 0.0f) continue; /* only use it if it's tagged for this purpose (and the right type) */ @@ -2305,7 +2410,7 @@ static void constraintTransLim(TransInfo *t, TransData *td) } /* get constraint targets if needed */ - get_constraint_targets_for_solving(con, &cob, &targets, ctime); + BKE_get_constraint_targets_for_solving(con, &cob, &targets, ctime); /* do constraint */ cti->evaluate_constraint(con, &cob, &targets); @@ -2357,7 +2462,7 @@ static void constraintob_from_transdata(bConstraintOb *cob, TransData *td) static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) { if (td->con) { - bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT); + bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_ROTLIMIT); bConstraintOb cob; bConstraint *con; int do_limit = FALSE; @@ -2365,7 +2470,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) /* Evaluate valid constraints */ for (con = td->con; con; con = con->next) { /* only consider constraint if enabled */ - if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue; if (con->enforce == 0.0f) continue; /* we're only interested in Limit-Rotation constraints */ @@ -2424,7 +2529,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) static void constraintSizeLim(TransInfo *t, TransData *td) { if (td->con && td->ext) { - bConstraintTypeInfo *cti = get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT); + bConstraintTypeInfo *cti = BKE_get_constraint_typeinfo(CONSTRAINT_TYPE_SIZELIMIT); bConstraintOb cob = {NULL}; bConstraint *con; float size_sign[3], size_abs[3]; @@ -2455,7 +2560,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td) /* Evaluate valid constraints */ for (con = td->con; con; con = con->next) { /* only consider constraint if enabled */ - if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) continue; if (con->enforce == 0.0f) continue; /* we're only interested in Limit-Scale constraints */ @@ -2555,11 +2660,12 @@ void initWarp(TransInfo *t) mid_v3_v3v3(t->center, min, max); - if (max[0] == min[0]) max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */ + if (max[0] == min[0]) + max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */ t->val = (max[0] - min[0]) / 2.0f; /* t->val is X dimension projected boundbox */ } -int handleEventWarp(TransInfo *t, wmEvent *event) +int handleEventWarp(TransInfo *t, const wmEvent *event) { int status = 0; @@ -2579,9 +2685,10 @@ int handleEventWarp(TransInfo *t, wmEvent *event) int Warp(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; - float vec[3], circumfac, dist, phi0, co, si, *curs, cursor[3], gcursor[3]; + float vec[3], circumfac, dist, phi0, co, si, cursor[3], gcursor[3]; + const float *curs; int i; - char str[50]; + char str[MAX_INFO_LEN]; curs = give_cursor(t->scene, t->view); /* @@ -2616,13 +2723,13 @@ int Warp(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Warp: %s", c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %s"), c); circumfac = DEG2RADF(circumfac); } else { /* default header print */ - sprintf(str, "Warp: %.3f", RAD2DEGF(circumfac)); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac)); } t->values[0] = circumfac; @@ -2699,7 +2806,7 @@ void initShear(TransInfo *t) t->flag |= T_NO_CONSTRAINT; } -int handleEventShear(TransInfo *t, wmEvent *event) +int handleEventShear(TransInfo *t, const wmEvent *event) { int status = 0; @@ -2716,6 +2823,18 @@ int handleEventShear(TransInfo *t, wmEvent *event) status = 1; } + else if (event->type == XKEY && event->val == KM_PRESS) { + initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_ABSOLUTE); + t->customData = NULL; + + status = 1; + } + else if (event->type == YKEY && event->val == KM_PRESS) { + initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); + t->customData = (void *)1; + + status = 1; + } return status; } @@ -2728,7 +2847,7 @@ int Shear(TransInfo *t, const int UNUSED(mval[2])) float smat[3][3], tmat[3][3], totmat[3][3], persmat[3][3], persinv[3][3]; float value; int i; - char str[50]; + char str[MAX_INFO_LEN]; copy_m3_m4(persmat, t->viewmat); invert_m3_m3(persinv, persmat); @@ -2745,11 +2864,11 @@ int Shear(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Shear: %s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %s %s"), c, t->proptext); } else { /* default header print */ - sprintf(str, "Shear: %.3f %s", value, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext); } t->values[0] = value; @@ -2825,10 +2944,11 @@ void initResize(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerResize(TransInfo *t, float vec[3], char *str) { char tvec[NUM_STR_REP_LEN * 3]; - char *spos = str; + size_t ofs = 0; if (hasNumInput(&t->num)) { outputNumInput(&(t->num), tvec); } @@ -2837,37 +2957,36 @@ static void headerResize(TransInfo *t, float vec[3], char *str) BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); } - + if (t->con.mode & CON_APPLY) { switch (t->num.idx_max) { case 0: - spos += sprintf(spos, "Scale: %s%s %s", &tvec[0], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s%s %s"), + &tvec[0], t->con.text, t->proptext); break; case 1: - spos += sprintf(spos, "Scale: %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s : %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); break; case 2: - spos += sprintf(spos, "Scale: %s : %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s : %s : %s%s %s"), &tvec[0], + &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } else { if (t->flag & T_2D_EDIT) { - spos += sprintf(spos, "Scale X: %s Y: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale X: %s Y: %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); } else { - spos += sprintf(spos, "Scale X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale X: %s Y: %s Z: %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } - + if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - - (void)spos; } /* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */ @@ -2920,12 +3039,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) } /* local constraint shouldn't alter center */ - if ((t->around == V3D_LOCAL) && - ( (t->flag & (T_OBJECT | T_POSE)) || - ((t->flag & T_EDIT) && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) || - (t->obedit && t->obedit->type == OB_ARMATURE)) - ) - { + if (transdata_check_local_center(t)) { copy_v3_v3(center, td->center); } else if (t->options & CTX_MOVIECLIP) { @@ -3007,7 +3121,7 @@ int Resize(TransInfo *t, const int mval[2]) float size[3], mat[3][3]; float ratio; int i; - char str[200]; + char str[MAX_INFO_LEN]; /* for manipulator, center handle, the scaling can't be done relative to center */ if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { @@ -3112,7 +3226,7 @@ int SkinResize(TransInfo *t, const int UNUSED(mval[2])) float size[3], mat[3][3]; float ratio; int i; - char str[200]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; size[0] = size[1] = size[2] = ratio; @@ -3206,7 +3320,7 @@ int ToSphere(TransInfo *t, const int UNUSED(mval[2])) float vec[3]; float ratio, radius; int i; - char str[64]; + char str[MAX_INFO_LEN]; TransData *td = t->data; ratio = t->values[0]; @@ -3228,11 +3342,11 @@ int ToSphere(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "To Sphere: %s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %s %s"), c, t->proptext); } else { /* default header print */ - sprintf(str, "To Sphere: %.4f %s", ratio, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %.4f %s"), ratio, t->proptext); } @@ -3302,20 +3416,16 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short { float vec[3], totmat[3][3], smat[3][3]; float eul[3], fmat[3][3], quat[4]; - float *center = t->center; + const float *center; /* local constraint shouldn't alter center */ - if (around == V3D_LOCAL) { - if ( (t->flag & (T_OBJECT | T_POSE)) || - (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE)) || - (t->obedit && t->obedit->type == OB_ARMATURE)) - { - center = td->center; - } - - if (t->options & CTX_MOVIECLIP) { - center = td->center; - } + if (transdata_check_local_center(t) || + ((around == V3D_LOCAL) && (t->options & CTX_MOVIECLIP))) + { + center = td->center; + } + else { + center = t->center; } if (t->flag & T_POINTS) { @@ -3425,7 +3535,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); /* this function works on end result */ - protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle); + protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, + td->ext->irotAngle); } else { float eulmat[3][3]; @@ -3472,12 +3583,15 @@ 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? */ if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { - mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); - mat3_to_quat(quat, fmat); // Actual transform - - mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); - /* this function works on end result */ - protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + /* 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); + mat3_to_quat(quat, fmat); // Actual transform + + mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); + /* this function works on end result */ + protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + } } else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { /* calculate effect based on quats */ @@ -3492,7 +3606,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); /* this function works on end result */ - protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle); + protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, + td->ext->irotAngle); } else { float obmat[3][3]; @@ -3551,14 +3666,15 @@ static void applyRotation(TransInfo *t, float angle, float axis[3]) int Rotation(TransInfo *t, const int UNUSED(mval[2])) { - char str[128], *spos = str; - + char str[MAX_INFO_LEN]; + size_t ofs = 0; + float final; final = t->values[0]; - + snapGrid(t, &final); - + if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, t->axis, NULL); } @@ -3566,9 +3682,9 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2])) /* reset axis if constraint is not set */ copy_v3_v3(t->axis, t->axis_orig); } - + applySnapping(t, &final); - + if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; @@ -3576,19 +3692,19 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - spos += sprintf(spos, "Rot: %s %s %s", &c[0], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); /* Clamp between -180 and 180 */ final = angle_wrap_rad(DEG2RADF(final)); } else { - spos += sprintf(spos, "Rot: %.2f%s %s", RAD2DEGF(final), t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %.2f%s %s"), + RAD2DEGF(final), t->con.text, t->proptext); } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - (void)spos; t->values[0] = final; @@ -3653,7 +3769,8 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a int Trackball(TransInfo *t, const int UNUSED(mval[2])) { - char str[128], *spos = str; + char str[MAX_INFO_LEN]; + size_t ofs = 0; float axis1[3], axis2[3]; float mat[3][3], totmat[3][3], smat[3][3]; float phi[2]; @@ -3675,19 +3792,20 @@ int Trackball(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - spos += sprintf(spos, "Trackball: %s %s %s", &c[0], &c[NUM_STR_REP_LEN], t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %s %s %s"), + &c[0], &c[NUM_STR_REP_LEN], t->proptext); phi[0] = DEG2RADF(phi[0]); phi[1] = DEG2RADF(phi[1]); } else { - spos += sprintf(spos, "Trackball: %.2f %.2f %s", RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %.2f %.2f %s"), + RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext); } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - (void)spos; vec_rot_to_mat3(smat, axis1, phi[0]); vec_rot_to_mat3(totmat, axis2, phi[1]); @@ -3751,9 +3869,10 @@ void initTranslation(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTranslation(TransInfo *t, float vec[3], char *str) { - char *spos = str; + size_t ofs = 0; char tvec[NUM_STR_REP_LEN * 3]; char distvec[NUM_STR_REP_LEN]; char autoik[NUM_STR_REP_LEN]; @@ -3774,29 +3893,30 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) int i, do_split = t->scene->unit.flag & USER_UNIT_OPT_SPLIT ? 1 : 0; for (i = 0; i < 3; i++) { - bUnit_AsString(&tvec[i * NUM_STR_REP_LEN], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length, + bUnit_AsString(&tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, 1); } } else { - sprintf(&tvec[0], "%.4f", dvec[0]); - sprintf(&tvec[NUM_STR_REP_LEN], "%.4f", dvec[1]); - sprintf(&tvec[NUM_STR_REP_LEN * 2], "%.4f", dvec[2]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]); } } if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) - bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0); + bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system, + B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0); else if (dist > 1e10f || dist < -1e10f) /* prevent string buffer overflow */ - sprintf(distvec, "%.4e", dist); + BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist); else - sprintf(distvec, "%.4f", dist); + BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist); if (t->flag & T_AUTOIK) { short chainlen = t->settings->autoik_chainlen; if (chainlen) - sprintf(autoik, "AutoIK-Len: %d", chainlen); + BLI_snprintf(autoik, NUM_STR_REP_LEN, IFACE_("AutoIK-Len: %d"), chainlen); else autoik[0] = '\0'; } @@ -3806,32 +3926,34 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) if (t->con.mode & CON_APPLY) { switch (t->num.idx_max) { case 0: - spos += sprintf(spos, "D: %s (%s)%s %s %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s (%s)%s %s %s", + &tvec[0], distvec, t->con.text, t->proptext, autoik); break; case 1: - spos += sprintf(spos, "D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s D: %s (%s)%s %s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext, autoik); break; case 2: - spos += sprintf(spos, "D: %s D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s D: %s D: %s (%s)%s %s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, + t->con.text, t->proptext, autoik); } } else { if (t->flag & T_2D_EDIT) { - spos += sprintf(spos, "Dx: %s Dy: %s (%s)%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - distvec, t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "Dx: %s Dy: %s (%s)%s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext); } else { - spos += sprintf(spos, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, + t->proptext, autoik); } } - + if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, " Proportional size: %.2f", t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - (void)spos; } static void applyTranslation(TransInfo *t, float vec[3]) @@ -3903,7 +4025,7 @@ static void applyTranslation(TransInfo *t, float vec[3]) /* uses t->vec to store actual translation in */ int Translation(TransInfo *t, const int UNUSED(mval[2])) { - char str[250]; + char str[MAX_INFO_LEN]; if (t->con.mode & CON_APPLY) { float pvec[3] = {0.0f, 0.0f, 0.0f}; @@ -3979,7 +4101,8 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { float distance; int i; - char str[64]; + char str[MAX_INFO_LEN]; + size_t ofs = 0; TransData *td = t->data; distance = -t->values[0]; @@ -3989,17 +4112,32 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) applyNumInput(&t->num, &distance); /* header print for NumInput */ + 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); - - sprintf(str, "Shrink/Fatten: %s %s", c, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", c); } else { /* default header print */ - sprintf(str, "Shrink/Fatten: %.4f %s", distance, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %.4f", distance); + } + + if (t->proptext[0]) { + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", t->proptext); } + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, ", ("); + + { + wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, str + ofs, MAX_INFO_LEN - ofs); + } + } + BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Even Thickness %s"), + (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); + /* done with header string */ + t->values[0] = -distance; @@ -4053,7 +4191,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; int i; - char str[50]; + char str[MAX_INFO_LEN]; float final; @@ -4068,7 +4206,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Tilt: %s° %s", &c[0], t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %s° %s"), &c[0], t->proptext); final = DEG2RADF(final); @@ -4076,7 +4214,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = final; } else { - sprintf(str, "Tilt: %.2f° %s", RAD2DEGF(final), t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4127,7 +4265,7 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float ratio; int i; - char str[50]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; @@ -4140,10 +4278,10 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, "Shrink/Fatten: %s", c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c); } else { - sprintf(str, "Shrink/Fatten: %3f", ratio); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %3f"), ratio); } for (i = 0; i < t->total; i++, td++) { @@ -4195,7 +4333,7 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) TransData *td; float ratio; int i, initial_feather = FALSE; - char str[50]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; @@ -4208,10 +4346,10 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, "Feather Shrink/Fatten: %s", c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %s"), c); } else { - sprintf(str, "Feather Shrink/Fatten: %3f", ratio); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %3f"), ratio); } /* detect if no points have feather yet */ @@ -4281,7 +4419,7 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2])) float vec[3], axis[3]; float distance; int i; - char str[128]; + char str[MAX_INFO_LEN]; TransData *td = t->data; distance = t->values[0]; @@ -4296,11 +4434,11 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Push/Pull: %s%s %s", c, t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext); } else { /* default header print */ - sprintf(str, "Push/Pull: %.4f%s %s", distance, t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext); } t->values[0] = distance; @@ -4376,7 +4514,7 @@ void initBevel(TransInfo *t) } } -int handleEventBevel(TransInfo *t, wmEvent *event) +int handleEventBevel(TransInfo *t, const wmEvent *event) { if (event->val == KM_PRESS) { if (!G.editBMesh) return 0; @@ -4413,11 +4551,11 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2])) { float distance, d; int i; - char str[128]; + char str[MAX_INFO_LEN]; const char *mode; TransData *td = t->data; - mode = (G.editBMesh->options & BME_BEVEL_VERT) ? "verts only" : "normal"; + mode = (G.editBMesh->options & BME_BEVEL_VERT) ? IFACE_("verts only") : IFACE_("normal"); distance = t->values[0] / 4; /* 4 just seemed a nice value to me, nothing special */ distance = fabs(distance); @@ -4432,11 +4570,11 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Bevel - Dist: %s, Mode: %s (MMB to toggle))", c, mode); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel - Dist: %s, Mode: %s (MMB to toggle))"), c, mode); } else { /* default header print */ - sprintf(str, "Bevel - Dist: %.4f, Mode: %s (MMB to toggle))", distance, mode); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel - Dist: %.4f, Mode: %s (MMB to toggle))"), distance, mode); } if (distance < 0) distance = -distance; @@ -4482,7 +4620,7 @@ int BevelWeight(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float weight; int i; - char str[50]; + char str[MAX_INFO_LEN]; weight = t->values[0]; @@ -4500,16 +4638,16 @@ int BevelWeight(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); if (weight >= 0.0f) - sprintf(str, "Bevel Weight: +%s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%s %s"), c, t->proptext); else - sprintf(str, "Bevel Weight: %s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: %s %s"), c, t->proptext); } else { /* default header print */ if (weight >= 0.0f) - sprintf(str, "Bevel Weight: +%.3f %s", weight, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext); else - sprintf(str, "Bevel Weight: %.3f %s", weight, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4555,7 +4693,7 @@ int Crease(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float crease; int i; - char str[50]; + char str[MAX_INFO_LEN]; crease = t->values[0]; @@ -4573,16 +4711,16 @@ int Crease(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); if (crease >= 0.0f) - sprintf(str, "Crease: +%s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%s %s"), c, t->proptext); else - sprintf(str, "Crease: %s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: %s %s"), c, t->proptext); } else { /* default header print */ if (crease >= 0.0f) - sprintf(str, "Crease: +%.3f %s", crease, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%.3f %s"), crease, t->proptext); else - sprintf(str, "Crease: %.3f %s", crease, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: %.3f %s"), crease, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4626,6 +4764,7 @@ void initBoneSize(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerBoneSize(TransInfo *t, float vec[3], char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -4633,22 +4772,22 @@ static void headerBoneSize(TransInfo *t, float vec[3], char *str) outputNumInput(&(t->num), tvec); } else { - sprintf(&tvec[0], "%.4f", vec[0]); - sprintf(&tvec[NUM_STR_REP_LEN], "%.4f", vec[1]); - sprintf(&tvec[NUM_STR_REP_LEN * 2], "%.4f", vec[2]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); } /* hmm... perhaps the y-axis values don't need to be shown? */ if (t->con.mode & CON_APPLY) { if (t->num.idx_max == 0) - sprintf(str, "ScaleB: %s%s %s", &tvec[0], t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext); else - sprintf(str, "ScaleB: %s : %s : %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], - t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB: %s : %s : %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } else { - sprintf(str, "ScaleB X: %s Y: %s Z: %s%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], - t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } @@ -4678,7 +4817,7 @@ int BoneSize(TransInfo *t, const int mval[2]) float size[3], mat[3][3]; float ratio; int i; - char str[60]; + char str[MAX_INFO_LEN]; // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT /* for manipulator, center handle, the scaling can't be done relative to center */ @@ -4751,7 +4890,7 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float ratio; int i; - char str[50]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; @@ -4764,10 +4903,10 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, "Envelope: %s", c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %s"), c); } else { - sprintf(str, "Envelope: %3f", ratio); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %3f"), ratio); } for (i = 0; i < t->total; i++, td++) { @@ -4797,96 +4936,200 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) static BMEdge *get_other_edge(BMVert *v, BMEdge *e) { BMIter iter; - BMEdge *e2; + BMEdge *e_iter; - BM_ITER_ELEM (e2, &iter, v, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(e2, BM_ELEM_SELECT) && e2 != e) - return e2; + BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT) && e_iter != e) { + return e_iter; + } } return NULL; } +static void len_v3_ensure(float v[3], const float length) +{ + normalize_v3(v); + mul_v3_fl(v, length); +} + +/** + * Find the closest point on the ngon on the opposite side. + * used to set the edge slide distance for ngons. + */ +static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, + const float plane_no[3], + float r_co[3]) +{ + /* skip adjacent edges */ + BMLoop *l_first = l_tmp->next; + BMLoop *l_last = l_tmp->prev; + BMLoop *l_iter; + float dist = FLT_MAX; + + l_iter = l_first; + do { + float tvec[3]; + if (isect_line_plane_v3(tvec, + l_iter->v->co, l_iter->next->v->co, + l_tmp->v->co, plane_no, false)) + { + const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co); + /* allow some overlap to avoid missing the intersection because of float precision */ + if ((fac > -FLT_EPSILON) && (fac < 1.0f + FLT_EPSILON)) { + /* likelyhood of multiple intersections per ngon is quite low, + * it would have to loop back on its self, but better support it + * so check for the closest opposite edge */ + const float tdist = len_v3v3(l_tmp->v->co, tvec); + if (tdist < dist) { + copy_v3_v3(r_co, tvec); + dist = tdist; + } + } + } + } while ((l_iter = l_iter->next) != l_last); + + return (dist != FLT_MAX); +} + +/** + * Given 2 edges and a loop, step over the loops + * and calculate a direction to slide along. + * + * \param r_slide_vec the direction to slide, + * the length of the vector defines the slide distance. + */ static BMLoop *get_next_loop(BMVert *v, BMLoop *l, - BMEdge *olde, BMEdge *nexte, float vec[3]) + BMEdge *e_prev, BMEdge *e_next, float r_slide_vec[3]) { - BMLoop *firstl; - float a[3] = {0.0f, 0.0f, 0.0f}, n[3] = {0.0f, 0.0f, 0.0f}; + BMLoop *l_first; + float vec_accum[3] = {0.0f, 0.0f, 0.0f}; + float vec_accum_len = 0.0f; int i = 0; - firstl = l; + BLI_assert(BM_edge_share_vert(e_prev, e_next) == v); + + l_first = l; do { l = BM_face_other_edge_loop(l->f, l->e, v); if (l->radial_next == l) return NULL; - if (l->e == nexte) { + if (l->e == e_next) { if (i) { - mul_v3_fl(a, 1.0f / (float)i); + len_v3_ensure(vec_accum, vec_accum_len / (float)i); } else { - float f1[3], f2[3], f3[3]; + /* When there is no edge to slide along, + * we must slide along the vector defined by the face we're attach to */ + BMLoop *l_tmp = BM_face_vert_share_loop(l_first->f, v); - sub_v3_v3v3(f1, BM_edge_other_vert(olde, v)->co, v->co); - sub_v3_v3v3(f2, BM_edge_other_vert(nexte, v)->co, v->co); + BLI_assert(ELEM(l_tmp->e, e_prev, e_next) && ELEM(l_tmp->prev->e, e_prev, e_next)); - cross_v3_v3v3(f3, f1, l->f->no); - cross_v3_v3v3(a, f2, l->f->no); - mul_v3_fl(a, -1.0f); + if (l_tmp->f->len == 4) { + /* we could use code below, but in this case + * sliding diagonally across the quad works well */ + sub_v3_v3v3(vec_accum, l_tmp->next->next->v->co, v->co); + } + else { + float tdir[3]; + BM_loop_calc_face_direction(l_tmp, tdir); + cross_v3_v3v3(vec_accum, l_tmp->f->no, tdir); +#if 0 + /* rough guess, we can do better! */ + len_v3_ensure(vec_accum, (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f); +#else + /* be clever, check the opposite ngon edge to slide into. + * this gives best results */ + { + float tvec[3]; + float dist; + + if (bm_loop_calc_opposite_co(l_tmp, tdir, tvec)) { + dist = len_v3v3(l_tmp->v->co, tvec); + } + else { + dist = (BM_edge_calc_length(e_prev) + BM_edge_calc_length(e_next)) / 2.0f; + } - mid_v3_v3v3(a, a, f3); + len_v3_ensure(vec_accum, dist); + } +#endif + } } - - copy_v3_v3(vec, a); + + copy_v3_v3(r_slide_vec, vec_accum); return l; } else { - sub_v3_v3v3(n, BM_edge_other_vert(l->e, v)->co, v->co); - add_v3_v3v3(a, a, n); + /* accumulate the normalized edge vector, + * normalize so some edges don't skew the result */ + float tvec[3]; + sub_v3_v3v3(tvec, BM_edge_other_vert(l->e, v)->co, v->co); + vec_accum_len += normalize_v3(tvec); + add_v3_v3(vec_accum, tvec); i += 1; } - if (BM_face_other_edge_loop(l->f, l->e, v)->e == nexte) { - if (i) - mul_v3_fl(a, 1.0f / (float)i); - - copy_v3_v3(vec, a); + if (BM_face_other_edge_loop(l->f, l->e, v)->e == e_next) { + if (i) { + len_v3_ensure(vec_accum, vec_accum_len / (float)i); + } + + copy_v3_v3(r_slide_vec, vec_accum); return BM_face_other_edge_loop(l->f, l->e, v); } + BLI_assert(l != l->radial_next); l = l->radial_next; - } while (l != firstl); + } while (l != l_first); - if (i) - mul_v3_fl(a, 1.0f / (float)i); + if (i) { + len_v3_ensure(vec_accum, vec_accum_len / (float)i); + } - copy_v3_v3(vec, a); + copy_v3_v3(r_slide_vec, vec_accum); return NULL; } -static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const float mval[2]) +static void calcNonProportionalEdgeSlide(TransInfo *t, EdgeSlideData *sld, const float mval[2]) { - TransDataSlideVert *sv = sld->sv; + TransDataEdgeSlideVert *sv = sld->sv; if (sld->totsv > 0) { + ARegion *ar = t->ar; + RegionView3D *rv3d = NULL; + float projectMat[4][4]; + int i = 0; - float v_proj[3]; + float v_proj[2]; float dist = 0; float min_dist = FLT_MAX; + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ + rv3d = t->ar ? t->ar->regiondata : NULL; + } + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } + else { + ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + } + for (i = 0; i < sld->totsv; i++, sv++) { /* Set length */ sv->edge_len = len_v3v3(sv->upvec, sv->downvec); - mul_v3_m4v3(v_proj, t->obedit->obmat, sv->v->co); - if (ED_view3d_project_float_global(t->ar, v_proj, v_proj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - dist = len_squared_v2v2(mval, v_proj); - if (dist < min_dist) { - min_dist = dist; - sld->curr_sv_index = i; - } + ED_view3d_project_float_v2_m4(ar, sv->v->co, v_proj, projectMat); + dist = len_squared_v2v2(mval, v_proj); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; } } } @@ -4895,17 +5138,18 @@ static void calcNonProportionalEdgeSlide(TransInfo *t, SlideData *sld, const flo } } -static int createSlideVerts(TransInfo *t) +static int createEdgeSlideVerts(TransInfo *t) { BMEditMesh *em = BMEdit_FromObject(t->obedit); BMesh *bm = em->bm; BMIter iter; BMEdge *e, *e1; - BMVert *v, *v2, *first; - TransDataSlideVert *sv_array; - BMBVHTree *btree = BMBVH_NewBVH(em, BMBVH_RESPECT_HIDDEN, NULL, NULL); + BMVert *v, *v2; + TransDataEdgeSlideVert *sv_array; + int sv_tot; + BMBVHTree *btree; SmallHash table; - SlideData *sld = MEM_callocN(sizeof(*sld), "sld"); + EdgeSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); View3D *v3d = NULL; RegionView3D *rv3d = NULL; ARegion *ar = t->ar; @@ -4915,6 +5159,7 @@ static int createSlideVerts(TransInfo *t) float vec[3], vec2[3] /*, lastvec[3], size, dis=0.0, z */ /* UNUSED */; float dir[3], maxdist, (*loop_dir)[3], *loop_maxdist; int numsel, i, j, loop_nr, l_nr; + int use_btree_disp; if (t->spacetype == SPACE_VIEW3D) { /* background mode support */ @@ -4922,6 +5167,15 @@ static int createSlideVerts(TransInfo *t) rv3d = t->ar ? t->ar->regiondata : NULL; } + use_btree_disp = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE); + + if (use_btree_disp) { + btree = BMBVH_NewBVH(em, BMBVH_RESPECT_HIDDEN, NULL, NULL); + } + else { + btree = NULL; + } + sld->is_proportional = TRUE; sld->curr_sv_index = 0; sld->flipped_vtx = FALSE; @@ -4955,7 +5209,8 @@ static int createSlideVerts(TransInfo *t) if (numsel == 0 || numsel > 2) { MEM_freeN(sld); - BMBVH_FreeBVH(btree); + if (btree) + BMBVH_FreeBVH(btree); return 0; /* invalid edge selection */ } } @@ -4965,7 +5220,8 @@ static int createSlideVerts(TransInfo *t) if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { if (!BM_edge_is_manifold(e)) { MEM_freeN(sld); - BMBVH_FreeBVH(btree); + if (btree) + BMBVH_FreeBVH(btree); return 0; /* can only handle exactly 2 faces around each edge */ } } @@ -4985,16 +5241,18 @@ static int createSlideVerts(TransInfo *t) if (!j) { MEM_freeN(sld); - BMBVH_FreeBVH(btree); + if (btree) + BMBVH_FreeBVH(btree); return 0; } - sv_array = MEM_callocN(sizeof(TransDataSlideVert) * j, "sv_array"); + sv_tot = j; + sv_array = MEM_callocN(sizeof(TransDataEdgeSlideVert) * sv_tot, "sv_array"); loop_nr = 0; - j = 0; while (1) { BMLoop *l, *l1, *l2; + BMVert *v_first; v = NULL; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -5009,7 +5267,7 @@ static int createSlideVerts(TransInfo *t) if (!v->e) continue; - first = v; + v_first = v; /*walk along the edge loop*/ e = v->e; @@ -5029,7 +5287,7 @@ static int createSlideVerts(TransInfo *t) break; v = BM_edge_other_vert(e, v); - } while (e != first->e); + } while (e != v_first->e); BM_elem_flag_disable(v, BM_ELEM_TAG); @@ -5049,10 +5307,13 @@ static int createSlideVerts(TransInfo *t) } /*iterate over the loop*/ - first = v; + v_first = v; do { - TransDataSlideVert *sv = sv_array + j; + TransDataEdgeSlideVert *sv; + /* XXX, 'sv' will initialize multiple times, this is suspicious. see [#34024] */ + BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false); + sv = sv_array + GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v)); sv->v = v; sv->origvert = *v; sv->loop_nr = loop_nr; @@ -5074,9 +5335,8 @@ static int createSlideVerts(TransInfo *t) e1 = e; e = get_other_edge(v, e); if (!e) { - //v2=v, v = BM_edge_other_vert(l1->e, v); - - sv = sv_array + j + 1; + BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false); + sv = sv_array + GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v)); sv->v = v; sv->origvert = *v; sv->loop_nr = loop_nr; @@ -5093,19 +5353,22 @@ static int createSlideVerts(TransInfo *t) BM_elem_flag_disable(v, BM_ELEM_TAG); BM_elem_flag_disable(v2, BM_ELEM_TAG); - - j += 2; + break; } l1 = get_next_loop(v, l1, e1, e, vec); l2 = l2 ? get_next_loop(v, l2, e1, e, vec2) : NULL; - j += 1; + if (UNLIKELY(l1 == NULL && l2 != NULL)) { + l1 = l2; + l2 = NULL; + swap_v3_v3(vec, vec2); + } BM_elem_flag_disable(v, BM_ELEM_TAG); BM_elem_flag_disable(v2, BM_ELEM_TAG); - } while (e != first->e && l1); + } while (e != v_first->e && l1); loop_nr++; } @@ -5113,7 +5376,7 @@ static int createSlideVerts(TransInfo *t) /* EDBM_flag_disable_all(em, BM_ELEM_SELECT); */ sld->sv = sv_array; - sld->totsv = j; + sld->totsv = sv_tot; /* find mouse vectors, the global one, and one per loop in case we have * multiple loops selected, in case they are oriented different */ @@ -5140,12 +5403,11 @@ static int createSlideVerts(TransInfo *t) continue; /* This test is only relevant if object is not wire-drawn! See [#32068]. */ - if (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE && - !BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit)) - { + if (use_btree_disp && !BMBVH_EdgeVisible(btree, e2, ar, v3d, t->obedit)) { continue; } + BLI_assert(BLI_smallhash_haskey(&table, (uintptr_t)v) != false); j = GET_INT_FROM_POINTER(BLI_smallhash_lookup(&table, (uintptr_t)v)); if (sv_array[j].down) { @@ -5216,14 +5478,14 @@ static int createSlideVerts(TransInfo *t) if (dot_v3v3(loop_dir[l_nr], dir) < 0.0f) { swap_v3_v3(sv_array->upvec, sv_array->downvec); SWAP(BMVert, sv_array->vup, sv_array->vdown); - SWAP(BMVert*, sv_array->up, sv_array->down); + SWAP(BMVert *, sv_array->up, sv_array->down); } } if (rv3d) calcNonProportionalEdgeSlide(t, sld, mval); - sld->origfaces_init = TRUE; + sld->origfaces_init = true; sld->em = em; /*zero out start*/ @@ -5244,17 +5506,22 @@ static int createSlideVerts(TransInfo *t) t->customData = sld; BLI_smallhash_release(&table); - BMBVH_FreeBVH(btree); + if (btree) { + BMBVH_FreeBVH(btree); + } MEM_freeN(loop_dir); MEM_freeN(loop_maxdist); - + + /* arrays are dirty from copying faces: EDBM_index_arrays_free */ + EDBM_update_generic(em, FALSE, TRUE); + return 1; } -void projectSVData(TransInfo *t, int final) +void projectEdgeSlideData(TransInfo *t, bool is_final) { - SlideData *sld = t->customData; - TransDataSlideVert *sv; + EdgeSlideData *sld = t->customData; + TransDataEdgeSlideVert *sv; BMEditMesh *em = sld->em; SmallHash visit; int i; @@ -5356,7 +5623,8 @@ void projectSVData(TransInfo *t, int final) f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f); } else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->down)) { - f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f); + f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, + (uintptr_t)e_sel->l->radial_next->f); } } @@ -5365,7 +5633,8 @@ void projectSVData(TransInfo *t, int final) f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f); } else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->up)) { - f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f); + f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, + (uintptr_t)e_sel->l->radial_next->f); } } @@ -5373,7 +5642,7 @@ void projectSVData(TransInfo *t, int final) } } - + if (!affected) continue; @@ -5381,7 +5650,7 @@ void projectSVData(TransInfo *t, int final) * and we do not want to mess up other shape keys */ BM_loop_interp_from_face(em->bm, l, f_copy_flip, FALSE, FALSE); - if (final) { + if (is_final) { BM_loop_interp_multires(em->bm, l, f_copy_flip); if (f_copy != f_copy_flip) { BM_loop_interp_multires(em->bm, l, f_copy); @@ -5405,7 +5674,7 @@ void projectSVData(TransInfo *t, int final) BLI_smallhash_release(&visit); } -void freeSlideTempFaces(SlideData *sld) +void freeEdgeSlideTempFaces(EdgeSlideData *sld) { if (sld->origfaces_init) { SmallHashIter hiter; @@ -5418,18 +5687,21 @@ void freeSlideTempFaces(SlideData *sld) BLI_smallhash_release(&sld->origfaces); - sld->origfaces_init = FALSE; + sld->origfaces_init = false; + + /* arrays are dirty from removing faces: EDBM_index_arrays_free */ + EDBM_update_generic(sld->em, FALSE, TRUE); } } -void freeSlideVerts(TransInfo *t) +void freeEdgeSlideVerts(TransInfo *t) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; #if 0 /*BMESH_TODO*/ if (me->drawflag & ME_DRAWEXTRA_EDGELEN) { - TransDataSlideVert *sv; + TransDataEdgeSlideVert *sv; LinkNode *look = sld->vertlist; GHash *vertgh = sld->vhash; while (look) { @@ -5446,7 +5718,7 @@ void freeSlideVerts(TransInfo *t) if (!sld) return; - freeSlideTempFaces(sld); + freeEdgeSlideTempFaces(sld); bmesh_edit_end(sld->em->bm, BMO_OP_FLAG_UNTAN_MULTIRES); @@ -5462,13 +5734,13 @@ void freeSlideVerts(TransInfo *t) void initEdgeSlide(TransInfo *t) { - SlideData *sld; + EdgeSlideData *sld; t->mode = TFM_EDGE_SLIDE; t->transform = EdgeSlide; t->handleEvent = handleEventEdgeSlide; - if (!createSlideVerts(t)) { + if (!createEdgeSlideVerts(t)) { t->state = TRANS_CANCEL; return; } @@ -5478,11 +5750,11 @@ void initEdgeSlide(TransInfo *t) if (!sld) return; - t->customFree = freeSlideVerts; + t->customFree = freeEdgeSlideVerts; /* set custom point first if you want value to be initialized by init */ setCustomPoints(t, &t->mouse, sld->end, sld->start); - initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO_FLIP); t->idx_max = 0; t->num.idx_max = 0; @@ -5495,10 +5767,10 @@ void initEdgeSlide(TransInfo *t) t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } -int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) +int handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event) { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; if (sld) { switch (event->type) { @@ -5541,17 +5813,17 @@ int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) return 0; } -void drawNonPropEdge(const struct bContext *C, TransInfo *t) +void drawEdgeSlide(const struct bContext *C, TransInfo *t) { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = (SlideData *)t->customData; + EdgeSlideData *sld = (EdgeSlideData *)t->customData; /* Non-Prop mode */ if (sld && sld->is_proportional == FALSE) { View3D *v3d = CTX_wm_view3d(C); float marker[3]; float v1[3], v2[3]; float interp_v; - TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float guide_size = ctrl_size - 0.5f; const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; @@ -5617,8 +5889,8 @@ void drawNonPropEdge(const struct bContext *C, TransInfo *t) static int doEdgeSlide(TransInfo *t, float perc) { - SlideData *sld = t->customData; - TransDataSlideVert *svlist = sld->sv, *sv; + EdgeSlideData *sld = t->customData; + TransDataEdgeSlideVert *svlist = sld->sv, *sv; int i; sld->perc = perc; @@ -5648,7 +5920,7 @@ static int doEdgeSlide(TransInfo *t, float perc) * \note len_v3v3(curr_sv->upvec, curr_sv->downvec) * is the same as the distance between the original vert locations, same goes for the lines below. */ - TransDataSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + 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); float down_co[3]; @@ -5671,18 +5943,21 @@ static int doEdgeSlide(TransInfo *t, float perc) } } - projectSVData(t, 0); + projectEdgeSlideData(t, 0); return 1; } int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[128]; + char str[MAX_INFO_LEN]; float final; - SlideData *sld = t->customData; - int flipped = sld->flipped_vtx; - int is_proportional = sld->is_proportional; + EdgeSlideData *sld = t->customData; + bool flipped = sld->flipped_vtx; + bool is_proportional = sld->is_proportional; + + const char *on_str = IFACE_("ON"); + const char *off_str = IFACE_("OFF"); final = t->values[0]; @@ -5698,12 +5973,12 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - BLI_snprintf(str, sizeof(str), "Edge Slide: %s (E)ven: %s, (F)lipped: %s", - &c[0], !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF"); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"), + &c[0], !is_proportional ? on_str : off_str, flipped ? on_str : off_str); } else { - BLI_snprintf(str, sizeof(str), "Edge Slide: %.2f (E)ven: %s, (F)lipped: %s", - final, !is_proportional ? "ON" : "OFF", flipped ? "ON" : "OFF"); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"), + final, !is_proportional ? on_str : off_str, flipped ? on_str : off_str); } CLAMP(final, -1.0f, 1.0f); @@ -5711,10 +5986,524 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = final; /*do stuff here*/ - if (t->customData) + if (t->customData) { doEdgeSlide(t, final); + } + else { + BLI_strncpy(str, IFACE_("Invalid Edge Selection"), MAX_INFO_LEN); + t->state = TRANS_CANCEL; + } + + recalcData(t); + + ED_area_headerprint(t->sa, str); + + return 1; +} + + +/* ******************** Vert Slide *************** */ +static void calcVertSlideCustomPoints(struct TransInfo *t) +{ + VertSlideData *sld = t->customData; + TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; + float *co_orig = sv->co_orig_2d; + float *co_curr = sv->co_link_orig_2d[sv->co_link_curr]; + const int start[2] = {co_orig[0], co_orig[1]}; + const int end[2] = {co_curr[0], co_curr[1]}; + + if (sld->flipped_vtx && sld->is_proportional == false) { + setCustomPoints(t, &t->mouse, start, end); + } + else { + setCustomPoints(t, &t->mouse, end, start); + } +} + +/** + * Run once when initializing vert slide to find the reference edge + */ +static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) +{ + VertSlideData *sld = t->customData; + float mval_fl[2] = {UNPACK2(mval)}; + TransDataVertSlideVert *sv; + + /* set the vertex to use as a reference for the mouse direction 'curr_sv_index' */ + float dist = 0.0f; + float min_dist = FLT_MAX; + int i; + + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + dist = len_squared_v2v2(mval_fl, sv->co_orig_2d); + if (dist < min_dist) { + min_dist = dist; + sld->curr_sv_index = i; + } + } +} +/** + * Run while moving the mouse to slide along the edge matching the mouse direction + */ +static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]) +{ + VertSlideData *sld = t->customData; + float mval_fl[2] = {UNPACK2(mval)}; + + float dir[2]; + TransDataVertSlideVert *sv; + int i; + + /* first get the direction of the original vertex */ + sub_v2_v2v2(dir, sld->sv[sld->curr_sv_index].co_orig_2d, mval_fl); + normalize_v2(dir); + + for (i = 0, sv = sld->sv; i < sld->totsv; i++, sv++) { + if (sv->co_link_tot > 1) { + float dir_dot_best = -FLT_MAX; + int co_link_curr_best = -1; + int j; + + for (j = 0; j < sv->co_link_tot; j++) { + float tdir[2]; + float dir_dot; + sub_v2_v2v2(tdir, sv->co_orig_2d, sv->co_link_orig_2d[j]); + normalize_v2(tdir); + dir_dot = dot_v2v2(dir, tdir); + if (dir_dot > dir_dot_best) { + dir_dot_best = dir_dot; + co_link_curr_best = j; + } + } + + if (co_link_curr_best != -1) { + sv->co_link_curr = co_link_curr_best; + } + } + } +} + +static int createVertSlideVerts(TransInfo *t) +{ + BMEditMesh *em = BMEdit_FromObject(t->obedit); + BMesh *bm = em->bm; + BMIter iter; + BMIter eiter; + BMEdge *e; + BMVert *v; + TransDataVertSlideVert *sv_array; + VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); +// View3D *v3d = NULL; + RegionView3D *rv3d = NULL; + ARegion *ar = t->ar; + float projectMat[4][4]; + int j; + + if (t->spacetype == SPACE_VIEW3D) { + /* background mode support */ +// v3d = t->sa ? t->sa->spacedata.first : NULL; + rv3d = ar ? ar->regiondata : NULL; + } + + sld->is_proportional = true; + sld->curr_sv_index = 0; + sld->flipped_vtx = false; + + if (!rv3d) { + /* ok, let's try to survive this */ + unit_m4(projectMat); + } else { - strcpy(str, "Invalid Edge Selection"); + ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + } + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + bool ok = false; + if (BM_elem_flag_test(v, BM_ELEM_SELECT) && v->e) { + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + ok = true; + break; + } + } + } + + if (ok) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + j += 1; + } + else { + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + } + + if (!j) { + MEM_freeN(sld); + return 0; + } + + sv_array = MEM_callocN(sizeof(TransDataVertSlideVert) * j, "sv_array"); + + j = 0; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + int k; + sv_array[j].v = v; + copy_v3_v3(sv_array[j].co_orig_3d, v->co); + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + k++; + } + } + + sv_array[j].co_link_orig_3d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_3d) * k, __func__); + sv_array[j].co_link_orig_2d = MEM_mallocN(sizeof(*sv_array[j].co_link_orig_2d) * k, __func__); + sv_array[j].co_link_tot = k; + + k = 0; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { + BMVert *v_other = BM_edge_other_vert(e, v); + copy_v3_v3(sv_array[j].co_link_orig_3d[k], v_other->co); + if (ar) { + ED_view3d_project_float_v2_m4(ar, + sv_array[j].co_link_orig_3d[k], + sv_array[j].co_link_orig_2d[k], + projectMat); + } + else { + copy_v2_v2(sv_array[j].co_link_orig_2d[k], + sv_array[j].co_link_orig_3d[k]); + } + k++; + } + } + + if (ar) { + ED_view3d_project_float_v2_m4(ar, + sv_array[j].co_orig_3d, + sv_array[j].co_orig_2d, + projectMat); + } + else { + copy_v2_v2(sv_array[j].co_orig_2d, + sv_array[j].co_orig_3d); + } + + j++; + } + } + + sld->sv = sv_array; + sld->totsv = j; + + sld->em = em; + + sld->perc = 0.0f; + + t->customData = sld; + + if (rv3d) { + calcVertSlideMouseActiveVert(t, t->mval); + calcVertSlideMouseActiveEdges(t, t->mval); + } + + return 1; +} + +void freeVertSlideVerts(TransInfo *t) +{ + VertSlideData *sld = t->customData; + + if (!sld) + return; + + + if (sld->totsv > 0) { + TransDataVertSlideVert *sv = sld->sv; + int i = 0; + for (i = 0; i < sld->totsv; i++, sv++) { + MEM_freeN(sv->co_link_orig_2d); + MEM_freeN(sv->co_link_orig_3d); + } + } + + MEM_freeN(sld->sv); + MEM_freeN(sld); + + t->customData = NULL; + + recalcData(t); +} + +void initVertSlide(TransInfo *t) +{ + VertSlideData *sld; + + t->mode = TFM_VERT_SLIDE; + t->transform = VertSlide; + t->handleEvent = handleEventVertSlide; + + if (!createVertSlideVerts(t)) { + t->state = TRANS_CANCEL; + return; + } + + sld = t->customData; + + if (!sld) + return; + + t->customFree = freeVertSlideVerts; + + /* set custom point first if you want value to be initialized by init */ + calcVertSlideCustomPoints(t); + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; + + t->num.increment = t->snap[1]; + + t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; +} + +int handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event) +{ + if (t->mode == TFM_VERT_SLIDE) { + VertSlideData *sld = t->customData; + + if (sld) { + switch (event->type) { + case EKEY: + if (event->val == KM_PRESS) { + sld->is_proportional = !sld->is_proportional; + if (sld->flipped_vtx) { + calcVertSlideCustomPoints(t); + } + return 1; + } + break; + case FKEY: + { + if (event->val == KM_PRESS) { + sld->flipped_vtx = !sld->flipped_vtx; + calcVertSlideCustomPoints(t); + return 1; + } + break; + } + case CKEY: + { + /* use like a modifier key */ + if (event->val == KM_PRESS) { + t->flag ^= T_ALT_TRANSFORM; + calcVertSlideCustomPoints(t); + return 1; + } + break; + } +#if 0 + case EVT_MODAL_MAP: + { + switch (event->val) { + case TFM_MODAL_EDGESLIDE_DOWN: + { + sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; + break; + } + case TFM_MODAL_EDGESLIDE_UP: + { + sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; + break; + } + } + } +#endif + case MOUSEMOVE: + { + /* don't recalculat the best edge */ + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + if (is_clamp) { + calcVertSlideMouseActiveEdges(t, event->mval); + } + calcVertSlideCustomPoints(t); + } + default: + break; + } + } + } + return 0; +} + +static void drawVertSlide(const struct bContext *C, TransInfo *t) +{ + if (t->mode == TFM_VERT_SLIDE) { + VertSlideData *sld = (VertSlideData *)t->customData; + /* Non-Prop mode */ + if (sld) { + View3D *v3d = CTX_wm_view3d(C); + TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; + TransDataVertSlideVert *sv; + const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; + const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; + const int alpha_shade = -30; + const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); + int i; + + if (v3d && v3d->zbuf) + glDisable(GL_DEPTH_TEST); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); + glPushMatrix(); + + glMultMatrixf(t->obedit->obmat); + + glLineWidth(line_size); + UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + glBegin(GL_LINES); + if (is_clamp) { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + glVertex3fv(sv->co_orig_3d); + glVertex3fv(sv->co_link_orig_3d[sv->co_link_curr]); + } + } + else { + sv = sld->sv; + for (i = 0; i < sld->totsv; i++, sv++) { + float a[3], b[3]; + sub_v3_v3v3(a, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + mul_v3_fl(a, 100.0f); + negate_v3_v3(b, a); + add_v3_v3(a, sv->co_orig_3d); + add_v3_v3(b, sv->co_orig_3d); + + glVertex3fv(a); + glVertex3fv(b); + } + } + bglEnd(); + + glPointSize(ctrl_size); + + bglBegin(GL_POINTS); + bglVertex3fv((sld->flipped_vtx && sld->is_proportional == FALSE) ? + curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : + curr_sv->co_orig_3d); + bglEnd(); + + glPopMatrix(); + glPopAttrib(); + + glDisable(GL_BLEND); + + if (v3d && v3d->zbuf) + glEnable(GL_DEPTH_TEST); + } + } +} + +static int doVertSlide(TransInfo *t, float perc) +{ + VertSlideData *sld = t->customData; + TransDataVertSlideVert *svlist = sld->sv, *sv; + int i; + + sld->perc = perc; + sv = svlist; + + if (sld->is_proportional == TRUE) { + for (i = 0; i < sld->totsv; i++, sv++) { + interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc); + } + } + else { + TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index]; + const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, sv_curr->co_link_orig_3d[sv_curr->co_link_curr]); + const float tperc = perc * edge_len_curr; + + for (i = 0; i < sld->totsv; i++, sv++) { + float edge_len; + float dir[3]; + + sub_v3_v3v3(dir, sv->co_link_orig_3d[sv->co_link_curr], sv->co_orig_3d); + edge_len = normalize_v3(dir); + + if (edge_len > FLT_EPSILON) { + if (sld->flipped_vtx) { + madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); + } + else { + madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc); + } + } + else { + copy_v3_v3(sv->v->co, sv->co_orig_3d); + } + } + } + + return 1; +} + +int VertSlide(TransInfo *t, const int UNUSED(mval[2])) +{ + char str[MAX_INFO_LEN]; + 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 is_clamp = !(t->flag & T_ALT_TRANSFORM); + const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); + + const char *on_str = IFACE_("ON"); + const char *off_str = IFACE_("OFF"); + + final = t->values[0]; + + snapGrid(t, &final); + + /* only do this so out of range values are not displayed */ + if (is_constrained) { + CLAMP(final, 0.0f, 1.0f); + } + + /* header string */ + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs); + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + applyNumInput(&t->num, &final); + outputNumInput(&(t->num), c); + ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs); + } + 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, "), !is_proportional ? on_str : off_str); + if (!is_proportional) { + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), flipped ? on_str : off_str); + } + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), is_clamp ? on_str : off_str); + /* done with header string */ + + /*do stuff here*/ + if (t->customData) { + doVertSlide(t, final); + } + else { + BLI_strncpy(str, IFACE_("Invalid Vert Selection"), MAX_INFO_LEN); t->state = TRANS_CANCEL; } @@ -5725,6 +6514,7 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) return 1; } + /* ******************** EditBone roll *************** */ void initBoneRoll(TransInfo *t) @@ -5749,7 +6539,7 @@ int BoneRoll(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; int i; - char str[50]; + char str[MAX_INFO_LEN]; float final; @@ -5764,12 +6554,12 @@ int BoneRoll(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Roll: %s", &c[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %s"), &c[0]); final = DEG2RADF(final); } else { - sprintf(str, "Roll: %.2f", RAD2DEGF(final)); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %.2f"), RAD2DEGF(final)); } /* set roll values */ @@ -5811,7 +6601,7 @@ int BakeTime(TransInfo *t, const int mval[2]) TransData *td = t->data; float time; int i; - char str[50]; + char str[MAX_INFO_LEN]; float fac = 0.1f; @@ -5835,16 +6625,16 @@ int BakeTime(TransInfo *t, const int mval[2]) outputNumInput(&(t->num), c); if (time >= 0.0f) - sprintf(str, "Time: +%s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%s %s"), c, t->proptext); else - sprintf(str, "Time: %s %s", c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: %s %s"), c, t->proptext); } else { /* default header print */ if (time >= 0.0f) - sprintf(str, "Time: +%.3f %s", time, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%.3f %s"), time, t->proptext); else - sprintf(str, "Time: %.3f %s", time, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: %.3f %s"), time, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -5886,7 +6676,7 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2])) TransData *td; float size[3], mat[3][3]; int i; - char str[200]; + char str[MAX_INFO_LEN]; /* * OPTIMIZATION: @@ -5904,7 +6694,7 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2])) t->con.applySize(t, NULL, mat); } - sprintf(str, "Mirror%s", t->con.text); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Mirror%s"), t->con.text); for (i = 0, td = t->data; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) @@ -5938,9 +6728,9 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); if (t->flag & T_2D_EDIT) - ED_area_headerprint(t->sa, "Select a mirror axis (X, Y)"); + ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y)")); else - ED_area_headerprint(t->sa, "Select a mirror axis (X, Y, Z)"); + ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y, Z)")); } return 1; @@ -5997,7 +6787,7 @@ int Align(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); - ED_area_headerprint(t->sa, "Align"); + ED_area_headerprint(t->sa, IFACE_("Align")); return 1; } @@ -6021,18 +6811,29 @@ void initSeqSlide(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerSeqSlide(TransInfo *t, float val[2], char *str) { char tvec[NUM_STR_REP_LEN * 3]; + size_t ofs = 0; if (hasNumInput(&t->num)) { outputNumInput(&(t->num), tvec); } else { - sprintf(&tvec[0], "%.0f, %.0f", val[0], val[1]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]); } - sprintf(str, "Sequence Slide: %s%s", &tvec[0], t->con.text); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); + + { + wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + if (kmi) { + ofs += WM_keymap_item_to_string(kmi, str + ofs, MAX_INFO_LEN - ofs); + } + } + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Expand to fit %s"), + (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); } static void applySeqSlide(TransInfo *t, float val[2]) @@ -6060,7 +6861,7 @@ static void applySeqSlide(TransInfo *t, float val[2]) int SeqSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[200]; + char str[MAX_INFO_LEN]; if (t->con.mode & CON_APPLY) { float pvec[3] = {0.0f, 0.0f, 0.0f}; @@ -6176,7 +6977,11 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, #if 0 /* 'do_time' disabled for now */ const Scene *scene = t->scene; - const short do_time = 0; //getAnimEdit_DrawTime(t); // NOTE: this works, but may be confusing behavior given the option's label, hence disabled +#if 0 /* NOTE: this works, but may be confusing behavior given the option's label, hence disabled */ + const short do_time = getAnimEdit_DrawTime(t); +#else + const short do_time = 0; +#endif const double secf = FPS; #endif double val; @@ -6264,6 +7069,7 @@ void initTimeTranslate(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTimeTranslate(TransInfo *t, char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -6292,12 +7098,12 @@ static void headerTimeTranslate(TransInfo *t, char *str) } if (autosnap == SACTSNAP_FRAME) - sprintf(&tvec[0], "%d.00 (%.4f)", (int)val, val); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val); else - sprintf(&tvec[0], "%.4f", val); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); } - sprintf(str, "DeltaX: %s", &tvec[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]); } static void applyTimeTranslate(TransInfo *t, float UNUSED(sval)) @@ -6361,7 +7167,7 @@ int TimeTranslate(TransInfo *t, const int mval[2]) { View2D *v2d = (View2D *)t->view; float cval[2], sval[2]; - char str[200]; + char str[MAX_INFO_LEN]; /* calculate translation amount from mouse movement - in 'time-grid space' */ UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); @@ -6419,6 +7225,7 @@ void initTimeSlide(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTimeSlide(TransInfo *t, float sval, char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -6435,10 +7242,10 @@ static void headerTimeSlide(TransInfo *t, float sval, char *str) val = 2.0f * (cval - sval) / (maxx - minx); CLAMP(val, -1.0f, 1.0f); - sprintf(&tvec[0], "%.4f", val); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); } - sprintf(str, "TimeSlide: %s", &tvec[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("TimeSlide: %s"), &tvec[0]); } static void applyTimeSlide(TransInfo *t, float sval) @@ -6494,7 +7301,7 @@ int TimeSlide(TransInfo *t, const int mval[2]) float cval[2], sval[2]; float minx = *((float *)(t->customData)); float maxx = *((float *)(t->customData) + 1); - char str[200]; + char str[MAX_INFO_LEN]; /* calculate mouse co-ordinates */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]); @@ -6561,6 +7368,7 @@ void initTimeScale(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTimeScale(TransInfo *t, char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -6568,9 +7376,9 @@ static void headerTimeScale(TransInfo *t, char *str) if (hasNumInput(&t->num)) outputNumInput(&(t->num), tvec); else - sprintf(&tvec[0], "%.4f", t->values[0]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]); - sprintf(str, "ScaleX: %s", &tvec[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleX: %s"), &tvec[0]); } static void applyTimeScale(TransInfo *t) @@ -6615,7 +7423,7 @@ static void applyTimeScale(TransInfo *t) int TimeScale(TransInfo *t, const int UNUSED(mval[2])) { - char str[200]; + char str[MAX_INFO_LEN]; /* handle numeric-input stuff */ t->vec[0] = t->values[0]; @@ -6639,3 +7447,12 @@ void BIF_TransformSetUndo(const char *UNUSED(str)) // TRANSFORM_FIX_ME //Trans.undostr = str; } + + +/* TODO, move to: transform_queries.c */ +bool checkUseLocalCenter_GraphEdit(TransInfo *t) +{ + return ((t->around == V3D_LOCAL) && !ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)); +} + +#undef MAX_INFO_LEN diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 08fe1e7676b..a551ef5008e 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -35,6 +35,7 @@ #include "ED_transform.h" #include "ED_numinput.h" +#include "ED_view3d.h" #include "DNA_listBase.h" @@ -52,12 +53,7 @@ struct Object; struct View3D; struct ScrArea; struct Scene; -struct bPose; struct bConstraint; -struct BezTriple; -struct wmOperatorType; -struct wmOperator; -struct wmWindowManager; struct wmKeyMap; struct wmKeyConfig; struct bContext; @@ -65,7 +61,6 @@ struct wmEvent; struct wmTimer; struct ARegion; struct ReportList; -struct SmallHash; typedef struct TransSnapPoint { struct TransSnapPoint *next, *prev; @@ -108,15 +103,15 @@ typedef struct TransCon { int imval[2]; /* initial mouse value for visual calculation */ /* the one in TransInfo is not garanty to stay the same (Rotates change it) */ int mode; /* Mode flags of the Constraint */ - void (*drawExtra)(struct TransInfo *); + void (*drawExtra)(struct TransInfo *t); /* For constraints that needs to draw differently from the other * uses this instead of the generic draw function */ - void (*applyVec)(struct TransInfo *, struct TransData *, float *, float *, float *); + void (*applyVec)(struct TransInfo *t, struct TransData *td, const float in[3], float out[3], float pvec[3]); /* Apply function pointer for linear vectorial transformation */ /* The last three parameters are pointers to the in/out/printable vectors */ - void (*applySize)(struct TransInfo *, struct TransData *, float [3][3]); + void (*applySize)(struct TransInfo *t, struct TransData *td, float smat[3][3]); /* Apply function pointer for size transformation */ - void (*applyRot)(struct TransInfo *, struct TransData *, float [3], float *); + void (*applyRot)(struct TransInfo *t, struct TransData *td, float vec[3], float *angle); /* Apply function pointer for rotation transformation */ } TransCon; @@ -143,6 +138,7 @@ typedef struct TransDataExtension { * namely when a bone is in "NoLocal" or "Hinge" mode)... */ float r_smtx[3][3]; /* Invers of previous one. */ int rotOrder; /* rotation mode, as defined in eRotationModes (DNA_action_types.h) */ + float oloc[3], orot[3], oquat[4], orotAxis[3], orotAngle; /* Original object transformation used for rigid bodies */ } TransDataExtension; typedef struct TransData2D { @@ -188,7 +184,7 @@ typedef struct TransDataNla { struct LinkNode; struct GHash; -typedef struct TransDataSlideVert { +typedef struct TransDataEdgeSlideVert { struct BMVert vup, vdown; struct BMVert origvert; @@ -201,10 +197,10 @@ typedef struct TransDataSlideVert { float upvec[3], downvec[3]; int loop_nr; -} TransDataSlideVert; +} TransDataEdgeSlideVert; -typedef struct SlideData { - TransDataSlideVert *sv; +typedef struct EdgeSlideData { + TransDataEdgeSlideVert *sv; int totsv; struct SmallHash vhash; @@ -214,15 +210,40 @@ typedef struct SlideData { struct BMEditMesh *em; /* flag that is set when origfaces is initialized */ - int origfaces_init; + bool origfaces_init; float perc; - int is_proportional; - int flipped_vtx; + bool is_proportional; + bool flipped_vtx; int curr_sv_index; -} SlideData; +} EdgeSlideData; + + +typedef struct TransDataVertSlideVert { + BMVert *v; + float co_orig_3d[3]; + float co_orig_2d[2]; + float (*co_link_orig_3d)[3]; + float (*co_link_orig_2d)[2]; + int co_link_tot; + int co_link_curr; +} TransDataVertSlideVert; + +typedef struct VertSlideData { + TransDataVertSlideVert *sv; + int totsv; + + struct BMEditMesh *em; + + float perc; + + bool is_proportional; + bool flipped_vtx; + + int curr_sv_index; +} VertSlideData; typedef struct TransData { float dist; /* Distance needed to affect element (for Proportionnal Editing) */ @@ -246,8 +267,8 @@ typedef struct TransData { } TransData; typedef struct MouseInput { - void (*apply)(struct TransInfo *, struct MouseInput *, const int [2], float [3]); - void (*post)(struct TransInfo *, float [3]); + void (*apply)(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); + void (*post)(struct TransInfo *t, float values[3]); int imval[2]; /* initial mouse position */ char precision; @@ -267,7 +288,7 @@ typedef struct TransInfo { float fac; /* factor for distance based transform */ int (*transform)(struct TransInfo *, const int *); /* transform function pointer */ - int (*handleEvent)(struct TransInfo *, struct wmEvent *); + int (*handleEvent)(struct TransInfo *, const struct wmEvent *); /* event handler function pointer RETURN 1 if redraw is needed */ int total; /* total number of transformed data */ TransData *data; /* transformed data (array) */ @@ -331,7 +352,9 @@ typedef struct TransInfo { struct Scene *scene; struct ToolSettings *settings; struct wmTimer *animtimer; + struct wmKeyMap *keymap; /* so we can do lookups for header text */ int mval[2]; /* current mouse position */ + float zfac; /* use for 3d view */ struct Object *obedit; void *draw_handle_apply; void *draw_handle_view; @@ -452,26 +475,28 @@ typedef struct TransInfo { #define POINT_INIT 4 #define MULTI_POINTS 8 -int initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, struct wmEvent *event, int mode); +int initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, const struct wmEvent *event, int mode); void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op); -int transformEvent(TransInfo *t, struct wmEvent *event); +int transformEvent(TransInfo *t, const struct wmEvent *event); void transformApply(struct bContext *C, TransInfo *t); int transformEnd(struct bContext *C, TransInfo *t); void setTransformViewMatrices(TransInfo *t); void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy); +void projectIntViewEx(TransInfo *t, const float vec[3], int adr[2], const eV3DProjTest flag); void projectIntView(TransInfo *t, const float vec[3], int adr[2]); +void projectFloatViewEx(TransInfo *t, const float vec[3], float adr[2], const eV3DProjTest flag); void projectFloatView(TransInfo *t, const float vec[3], float adr[2]); void applyAspectRatio(TransInfo *t, float *vec); void removeAspectRatio(TransInfo *t, float *vec); void initWarp(TransInfo *t); -int handleEventWarp(TransInfo *t, struct wmEvent *event); +int handleEventWarp(TransInfo *t, const struct wmEvent *event); int Warp(TransInfo *t, const int mval[2]); void initShear(TransInfo *t); -int handleEventShear(TransInfo *t, struct wmEvent *event); +int handleEventShear(TransInfo *t, const struct wmEvent *event); int Shear(TransInfo *t, const int mval[2]); void initResize(TransInfo *t); @@ -508,7 +533,7 @@ void initPushPull(TransInfo *t); int PushPull(TransInfo *t, const int mval[2]); void initBevel(TransInfo *t); -int handleEventBevel(TransInfo *t, struct wmEvent *event); +int handleEventBevel(TransInfo *t, const struct wmEvent *event); int Bevel(TransInfo *t, const int mval[2]); void initBevelWeight(TransInfo *t); @@ -527,9 +552,13 @@ void initBoneRoll(TransInfo *t); int BoneRoll(TransInfo *t, const int mval[2]); void initEdgeSlide(TransInfo *t); -int handleEventEdgeSlide(TransInfo *t, struct wmEvent *event); +int handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event); int EdgeSlide(TransInfo *t, const int mval[2]); +void initVertSlide(TransInfo *t); +int handleEventVertSlide(TransInfo *t, const struct wmEvent *event); +int VertSlide(TransInfo *t, const int mval[2]); + void initTimeTranslate(TransInfo *t); int TimeTranslate(TransInfo *t, const int mval[2]); @@ -630,7 +659,7 @@ void initSnapping(struct TransInfo *t, struct wmOperator *op); void applyProject(TransInfo *t); void applySnapping(TransInfo *t, float *vec); void resetSnapping(TransInfo *t); -int handleSnapping(TransInfo *t, struct wmEvent *event); +int handleSnapping(TransInfo *t, const struct wmEvent *event); void drawSnapping(const struct bContext *C, TransInfo *t); int usingSnappingNormal(TransInfo *t); int validSnappingNormal(TransInfo *t); @@ -653,27 +682,26 @@ typedef enum { INPUT_HORIZONTAL_ABSOLUTE, INPUT_VERTICAL_RATIO, INPUT_VERTICAL_ABSOLUTE, - INPUT_CUSTOM_RATIO + INPUT_CUSTOM_RATIO, + INPUT_CUSTOM_RATIO_FLIP } MouseInputMode; -void initMouseInput(TransInfo *t, MouseInput *mi, int center[2], int mval[2]); +void initMouseInput(TransInfo *t, MouseInput *mi, const int center[2], const int mval[2]); void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); -int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, struct wmEvent *event); +int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); -void setCustomPoints(TransInfo *t, MouseInput *mi, int start[2], int end[2]); -void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float [3])); +void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]); +void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3])); /*********************** Generics ********************************/ -int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, struct wmEvent *event); +int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event); void postTrans (struct bContext *C, TransInfo *t); void resetTransRestrictions(TransInfo *t); void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis, short options); -void drawNonPropEdge(const struct bContext *C, TransInfo *t); - /* DRAWLINE options flags */ #define DRAWLIGHT 1 @@ -715,8 +743,14 @@ void applyTransformOrientation(const struct bContext *C, float mat[3][3], char * int getTransformOrientation(const struct bContext *C, float normal[3], float plane[3], int activeOnly); -void freeSlideTempFaces(SlideData *sld); -void freeSlideVerts(TransInfo *t); -void projectSVData(TransInfo *t, int final); +void freeEdgeSlideTempFaces(EdgeSlideData *sld); +void freeEdgeSlideVerts(TransInfo *t); +void projectEdgeSlideData(TransInfo *t, bool is_final); + +void freeVertSlideVerts(TransInfo *t); + + +/* TODO. transform_queries.c */ +bool checkUseLocalCenter_GraphEdit(TransInfo *t); #endif diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 947bdf53bee..f3026205ea2 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -29,19 +29,17 @@ * \ingroup edtransform */ - #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #ifndef WIN32 -#include <unistd.h> +# include <unistd.h> #else -#include <io.h> +# include <io.h> #endif - #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -53,13 +51,15 @@ #include "BKE_context.h" -#include "ED_image.h" -#include "ED_view3d.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" +#include "ED_image.h" +#include "ED_view3d.h" + +#include "BLF_translation.h" + #include "UI_resources.h" #include "transform.h" @@ -200,13 +200,14 @@ static void viewAxisCorrectCenter(TransInfo *t, float t_con_center[3]) } } -static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3]) +static void axisProjection(TransInfo *t, const float axis[3], const float in[3], float out[3]) { float norm[3], vec[3], factor, angle; float t_con_center[3]; - if (in[0] == 0.0f && in[1] == 0.0f && in[2] == 0.0f) + if (is_zero_v3(in)) { return; + } copy_v3_v3(t_con_center, t->con.center); @@ -278,7 +279,7 @@ static void axisProjection(TransInfo *t, float axis[3], float in[3], float out[3 } } -static void planeProjection(TransInfo *t, float in[3], float out[3]) +static void planeProjection(TransInfo *t, const float in[3], float out[3]) { float vec[3], factor, norm[3]; @@ -308,7 +309,7 @@ static void planeProjection(TransInfo *t, float in[3], float out[3]) * */ -static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3]) +static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { @@ -351,7 +352,7 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, float in[3], flo * Further down, that vector is mapped to each data's space. */ -static void applyObjectConstraintVec(TransInfo *t, TransData *td, float in[3], float out[3], float pvec[3]) +static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (t->con.mode & CON_APPLY) { @@ -597,24 +598,24 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte case V3D_MANIP_GLOBAL: { float mtx[3][3] = MAT3_UNITY; - BLI_snprintf(text, sizeof(text), ftext, "global"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("global")); setConstraint(t, mtx, mode, text); } break; case V3D_MANIP_LOCAL: - BLI_snprintf(text, sizeof(text), ftext, "local"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("local")); setLocalConstraint(t, mode, text); break; case V3D_MANIP_NORMAL: - BLI_snprintf(text, sizeof(text), ftext, "normal"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("normal")); setConstraint(t, t->spacemtx, mode, text); break; case V3D_MANIP_VIEW: - BLI_snprintf(text, sizeof(text), ftext, "view"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("view")); setConstraint(t, t->spacemtx, mode, text); break; case V3D_MANIP_GIMBAL: - BLI_snprintf(text, sizeof(text), ftext, "gimbal"); + BLI_snprintf(text, sizeof(text), ftext, IFACE_("gimbal")); setConstraint(t, t->spacemtx, mode, text); break; default: /* V3D_MANIP_CUSTOM */ @@ -864,11 +865,11 @@ static void setNearestAxis2d(TransInfo *t) /* no correction needed... just use whichever one is lower */ if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1]) ) { t->con.mode |= CON_AXIS1; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along Y axis"); + BLI_strncpy(t->con.text, IFACE_(" along Y axis"), sizeof(t->con.text)); } else { t->con.mode |= CON_AXIS0; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along X axis"); + BLI_strncpy(t->con.text, IFACE_(" along X axis"), sizeof(t->con.text)); } } @@ -889,9 +890,9 @@ static void setNearestAxis3d(TransInfo *t) * and to overflow the short integers. * The formula used is a bit stupid, just a simplification of the subtraction * of two 2D points 30 pixels apart (that's the last factor in the formula) after - * projecting them with window_to_3d_delta and then get the length of that vector. + * projecting them with ED_view3d_win_to_delta and then get the length of that vector. */ - zfac = t->persmat[0][3] * t->center[0] + t->persmat[1][3] * t->center[1] + t->persmat[2][3] * t->center[2] + t->persmat[3][3]; + zfac = mul_project_m4_v3_zfac(t->persmat, t->center); zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f; for (i = 0; i < 3; i++) { @@ -919,31 +920,31 @@ static void setNearestAxis3d(TransInfo *t) if (len[0] <= len[1] && len[0] <= len[2]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS1 | CON_AXIS2); - BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s X axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s X axis"), t->spacename); } else { t->con.mode |= CON_AXIS0; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s X axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s X axis"), t->spacename); } } else if (len[1] <= len[0] && len[1] <= len[2]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS2); - BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Y axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Y axis"), t->spacename); } else { t->con.mode |= CON_AXIS1; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Y axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Y axis"), t->spacename); } } else if (len[2] <= len[1] && len[2] <= len[0]) { if (t->modifiers & MOD_CONSTRAINT_PLANE) { t->con.mode |= (CON_AXIS0 | CON_AXIS1); - BLI_snprintf(t->con.text, sizeof(t->con.text), " locking %s Z axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" locking %s Z axis"), t->spacename); } else { t->con.mode |= CON_AXIS2; - BLI_snprintf(t->con.text, sizeof(t->con.text), " along %s Z axis", t->spacename); + BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along %s Z axis"), t->spacename); } } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 884ec03cc62..cf960c953c3 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -85,6 +85,7 @@ #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_report.h" +#include "BKE_rigidbody.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_tessmesh.h" @@ -113,6 +114,7 @@ #include "WM_types.h" #include "UI_view2d.h" +#include "UI_interface.h" #include "RNA_access.h" @@ -121,35 +123,30 @@ #include "BLO_sys_types.h" // for intptr_t support + /* local function prototype - for Object/Bone Constraints */ static short constraints_list_needinv(TransInfo *t, ListBase *list); /* ************************** Functions *************************** */ -static int trans_data_compare_dist(const void *A, const void *B) +static int trans_data_compare_dist(const void *a, const void *b) { - const TransData *td_A = (const TransData*)A; - const TransData *td_B = (const TransData*)B; + const TransData *td_a = (const TransData *)a; + const TransData *td_b = (const TransData *)b; - if (td_A->dist < td_B->dist) - return -1; - else if (td_A->dist > td_B->dist) - return 1; - - return 0; + if (td_a->dist < td_b->dist) return -1; + else if (td_a->dist > td_b->dist) return 1; + else return 0; } -static int trans_data_compare_rdist(const void *A, const void *B) +static int trans_data_compare_rdist(const void *a, const void *b) { - const TransData *td_A = (const TransData*)A; - const TransData *td_B = (const TransData*)B; + const TransData *td_a = (const TransData *)a; + const TransData *td_b = (const TransData *)b; - if (td_A->rdist < td_B->rdist) - return -1; - else if (td_A->rdist > td_B->rdist) - return 1; - - return 0; + if (td_a->rdist < td_b->rdist) return -1; + else if (td_a->rdist > td_b->rdist) return 1; + else return 0; } void sort_trans_data_dist(TransInfo *t) @@ -226,7 +223,9 @@ static void set_prop_dist(TransInfo *t, short with_dist) tob->rdist = dist; } } - else break; // by definition transdata has selected items in beginning + else { + break; /* by definition transdata has selected items in beginning */ + } } if (with_dist) { tob->dist = tob->rdist; @@ -271,7 +270,7 @@ static void createTransTexspace(TransInfo *t) copy_m3_m4(td->mtx, ob->obmat); copy_m3_m4(td->axismtx, ob->obmat); normalize_m3(td->axismtx); - invert_m3_m3(td->smtx, td->mtx); + pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size, &td->ext->rot)) { ob->dtx |= OB_TEXSPACE; @@ -294,6 +293,7 @@ static void createTransEdge(TransInfo *t) float mtx[3][3], smtx[3][3]; int count = 0, countsel = 0; int propmode = t->flag & T_PROP_EDIT; + int cd_edge_float_offset; BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { @@ -315,10 +315,24 @@ static void createTransEdge(TransInfo *t) td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransCrease"); copy_m3_m4(mtx, t->obedit->obmat); - invert_m3_m3(smtx, mtx); + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); + + /* create data we need */ + if (t->mode == TFM_BWEIGHT) { + BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_BWEIGHT); + cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); + } + else { //if (t->mode == TFM_CREASE) { + BLI_assert(t->mode == TFM_CREASE); + BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_EDGE_CREASE); + cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_CREASE); + } + + BLI_assert(cd_edge_float_offset != -1); BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) && (BM_elem_flag_test(eed, BM_ELEM_SELECT) || propmode)) { + float *fl_ptr; /* need to set center for center calculations */ mid_v3_v3v3(td->center, eed->v1->co, eed->v2->co); @@ -332,17 +346,10 @@ static void createTransEdge(TransInfo *t) copy_m3_m3(td->mtx, mtx); td->ext = NULL; - if (t->mode == TFM_BWEIGHT) { - float *bweight = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_BWEIGHT); - td->val = bweight; - td->ival = bweight ? *bweight : 1.0f; - } - else { - float *crease = CustomData_bmesh_get(&em->bm->edata, eed->head.data, CD_CREASE); - BLI_assert(t->mode == TFM_CREASE); - td->val = crease; - td->ival = crease ? *crease : 0.0f; - } + + fl_ptr = BM_ELEM_CD_GET_VOID_P(eed, cd_edge_float_offset); + td->val = fl_ptr; + td->ival = *fl_ptr; td++; } @@ -552,7 +559,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx); } - invert_m3_m3(td->smtx, td->mtx); + pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); /* exceptional case: rotate the pose bone which also applies transformation * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */ @@ -604,7 +611,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr /* only object matrix correction */ copy_m3_m3(td->mtx, omat); - invert_m3_m3(td->smtx, td->mtx); + pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); } } @@ -834,7 +841,7 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan) } } - con = add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC); + con = BKE_add_pose_constraint(NULL, pchan, "TempConstraint", CONSTRAINT_TYPE_KINEMATIC); pchan->constflag |= (PCHAN_HAS_IK | PCHAN_HAS_TARGET); /* for draw, but also for detecting while pose solving */ data = con->data; if (targetless) { @@ -1053,7 +1060,7 @@ static void createTransArmatureVerts(TransInfo *t) if (!t->total) return; copy_m3_m4(mtx, t->obedit->obmat); - invert_m3_m3(smtx, mtx); + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransEditBone"); @@ -1221,7 +1228,7 @@ static void createTransMBallVerts(TransInfo *t) tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "MetaElement_TransExtension"); copy_m3_m4(mtx, t->obedit->obmat); - invert_m3_m3(smtx, mtx); + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); for (ml = mb->editelems->first; ml; ml = ml->next) { if (propmode || (ml->flag & SELECT)) { @@ -1286,7 +1293,7 @@ static void calc_distanceCurveVerts(TransData *head, TransData *tail) } } else { - td->dist = MAXFLOAT; + td->dist = FLT_MAX; td->flag |= TD_NOTCONNECTED; } } @@ -1378,7 +1385,7 @@ static void createTransCurveVerts(TransInfo *t) t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Curve EditMode)"); copy_m3_m4(mtx, t->obedit->obmat); - invert_m3_m3(smtx, mtx); + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); td = t->data; for (nu = nurbs->first; nu; nu = nu->next) { @@ -1569,7 +1576,7 @@ static void createTransLatticeVerts(TransInfo *t) t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Lattice EditMode)"); copy_m3_m4(mtx, t->obedit->obmat); - invert_m3_m3(smtx, mtx); + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); td = t->data; bp = latt->def; @@ -1852,7 +1859,7 @@ static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[3][3], } /* loop-in-a-loop I know, but we need it! (ton) */ -static void get_face_center(float cent_r[3], BMVert *eve) +static void get_face_center(float r_cent[3], BMVert *eve) { BMFace *efa; @@ -1860,20 +1867,20 @@ static void get_face_center(float cent_r[3], BMVert *eve) BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) { if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - BM_face_calc_center_mean(efa, cent_r); + BM_face_calc_center_mean(efa, r_cent); break; } } } -static void get_edge_center(float cent_r[3], BMVert *eve) +static void get_edge_center(float r_cent[3], BMVert *eve) { BMEdge *eed; BMIter iter; BM_ITER_ELEM (eed, &iter, eve, BM_EDGES_OF_VERT) { if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - mid_v3_v3v3(cent_r, eed->v1->co, eed->v2->co); + mid_v3_v3v3(r_cent, eed->v1->co, eed->v2->co); break; } } @@ -1912,8 +1919,8 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx td->val = NULL; td->extra = NULL; if (t->mode == TFM_BWEIGHT) { - td->val = bweight; - td->ival = bweight ? *(bweight) : 1.0f; + td->val = bweight; + td->ival = *bweight; } else if (t->mode == TFM_SKIN_RESIZE) { MVertSkin *vs = CustomData_bmesh_get(&em->bm->vdata, @@ -1927,7 +1934,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx } else if (t->mode == TFM_SHRINKFATTEN) { td->ext = tx; - tx->isize[0] = BM_vert_calc_shell_factor(eve); + tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, BM_ELEM_SELECT); } } @@ -1949,6 +1956,7 @@ static void createTransEditVerts(TransInfo *t) int mirror = 0; char *selstate = NULL; short selectmode = ts->selectmode; + int cd_vert_bweight_offset = -1; if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_begin(em, TRUE); @@ -2030,6 +2038,10 @@ static void createTransEditVerts(TransInfo *t) } } + if (t->mode == TFM_BWEIGHT) { + BM_mesh_cd_flag_ensure(bm, BKE_mesh_from_object(t->obedit), ME_CDFLAG_VERT_BWEIGHT); + cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); + } if (propmode) { t->total = count; @@ -2038,7 +2050,9 @@ static void createTransEditVerts(TransInfo *t) if (propmode & T_PROP_CONNECTED) dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears"); } - else t->total = countsel; + else { + t->total = countsel; + } tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)"); if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { @@ -2051,7 +2065,9 @@ static void createTransEditVerts(TransInfo *t) } copy_m3_m4(mtx, t->obedit->obmat); - invert_m3_m3(smtx, mtx); + /* we use a pseudoinverse so that when one of the axes is scaled to 0, + * matrix inversion still works and we can still moving along the other */ + pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); if (propmode & T_PROP_CONNECTED) { editmesh_set_connectivity_distance(em, mtx, dists); @@ -2094,11 +2110,10 @@ static void createTransEditVerts(TransInfo *t) } } - eve = BM_iter_new(&iter, bm, BM_VERTS_OF_MESH, NULL); - for (a = 0; eve; eve = BM_iter_step(&iter), a++) { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { if (propmode || selstate[a]) { - float *bweight = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_BWEIGHT); + float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; VertsToTransData(t, tob, tx, em, eve, bweight); if (tx) @@ -2116,7 +2131,7 @@ static void createTransEditVerts(TransInfo *t) } else { tob->flag |= TD_NOTCONNECTED; - tob->dist = MAXFLOAT; + tob->dist = FLT_MAX; } } @@ -2195,7 +2210,12 @@ void flushTransNodes(TransInfo *t) /* flush to 2d vector from internally used 3d vector */ for (a = 0, td = t->data, td2d = t->data2d; a < t->total; a++, td++, td2d++) { bNode *node = td->extra; - add_v2_v2v2(&node->locx, td2d->loc, td2d->ih1); + float vec[2]; + + /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */ + add_v2_v2v2(vec, td2d->loc, td2d->ih1); + node->locx = vec[0] / UI_DPI_FAC; + node->locy = vec[1] / UI_DPI_FAC; } /* handle intersection with noodles */ @@ -2347,7 +2367,7 @@ static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, f td->dist = 0.0; } else { - td->dist = MAXFLOAT; + td->dist = FLT_MAX; } unit_m3(td->mtx); unit_m3(td->smtx); @@ -2627,6 +2647,14 @@ static void createTransNlaData(bContext *C, TransInfo *t) /* stop if trying to build list if nothing selected */ if (count == 0) { + /* clear temp metas that may have been created but aren't needed now + * because they fell on the wrong side of CFRA + */ + for (ale = anim_data.first; ale; ale = ale->next) { + NlaTrack *nlt = (NlaTrack *)ale->data; + BKE_nlastrips_clear_metas(&nlt->strips, 0, 1); + } + /* cleanup temp list */ BLI_freelistN(&anim_data); return; @@ -2671,14 +2699,14 @@ static void createTransNlaData(bContext *C, TransInfo *t) tdn->oldTrack = tdn->nlt = nlt; tdn->strip = strip; tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt); - + yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla)); - + tdn->h1[0] = strip->start; tdn->h1[1] = yval; tdn->h2[0] = strip->end; tdn->h2[1] = yval; - + center[0] = (float)CFRA; center[1] = yval; center[2] = 0.0f; @@ -3476,7 +3504,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, AnimData *adt, B td->dist = 0.0f; } else - td->dist = MAXFLOAT; + td->dist = FLT_MAX; if (ishandle) td->flag |= TD_NOTIMESNAP; @@ -3507,7 +3535,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) int count = 0, i; float cfra; float mtx[3][3], smtx[3][3]; - const short use_handle = !(sipo->flag & SIPO_NOHANDLES); + const bool use_handle = !(sipo->flag & SIPO_NOHANDLES); + const bool use_local_center = checkUseLocalCenter_GraphEdit(t); + const short anim_map_flag = ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS; /* determine what type of data we are operating on */ if (ANIM_animdata_get_context(C, &ac) == 0) @@ -3558,7 +3588,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) { /* for 'normal' pivots - just include anything that is selected. * this works a bit differently in translation modes */ - if (sel2) count++; + if (sel2) { + count++; + } else { if (sel1) count++; if (sel3) count++; @@ -3639,7 +3671,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (fcu->bezt == NULL) continue; - ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS); + ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, anim_map_flag); /* only include BezTriples whose 'keyframe' occurs on the same side of the current frame as mouse (if applicable) */ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { @@ -3674,7 +3706,7 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) } /* only include main vert if selected */ - if (sel2 && (sipo->around != V3D_LOCAL || ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE))) { + if (sel2 && (use_local_center == false)) { /* move handles relative to center */ if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) { @@ -3710,6 +3742,13 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) /* Sets handles based on the selection */ testhandles_fcurve(fcu, use_handle); + + /* even though transform values are written back right after during transform, + * using individual center's with rotation means the center point wont + * be touched again see: [#34303] */ + if (use_local_center) { + ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, anim_map_flag | ANIM_UNITCONV_RESTORE); + } } /* cleanup temp list */ @@ -4082,7 +4121,7 @@ static void SeqTransInfo(TransInfo *t, Sequence *seq, int *recursive, int *count /* Meta's can only directly be moved between channels since they * don't have their start and length set directly (children affect that) * since this Meta is nested we don't need any of its data in fact. - * calc_sequence() will update its settings when run on the toplevel meta */ + * BKE_sequence_calc() will update its settings when run on the toplevel meta */ *flag = 0; *count = 0; *recursive = TRUE; @@ -4260,8 +4299,8 @@ static void freeSeqData(TransInfo *t) { int overlap = 0; + seq_prev = NULL; for (a = 0; a < t->total; a++, td++) { - seq_prev = NULL; seq = ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev) && (seq->depth == 0) && (seq->flag & SEQ_OVERLAP)) { overlap = 1; @@ -4527,6 +4566,27 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) short constinv; short skip_invert = 0; + if (t->mode != TFM_DUMMY && ob->rigidbody_object) { + float rot[3][3], scale[3]; + + /* save original object transform */ + copy_v3_v3(td->ext->oloc, ob->loc); + + if (ob->rotmode > 0) { + copy_v3_v3(td->ext->orot, ob->rot); + } + else if (ob->rotmode == ROT_MODE_AXISANGLE) { + td->ext->orotAngle = ob->rotAngle; + copy_v3_v3(td->ext->orotAxis, ob->rotAxis); + } + else { + copy_qt_qt(td->ext->oquat, ob->quat); + } + /* update object's loc/rot to get current rigid body transform */ + mat4_to_loc_rot_size(ob->loc, rot, scale, ob->obmat); + BKE_object_mat3_to_rot(ob, rot, FALSE); + } + /* axismtx has the real orientation */ copy_m3_m4(td->axismtx, ob->obmat); normalize_m3(td->axismtx); @@ -4689,6 +4749,7 @@ static void set_trans_object_base_flags(TransInfo *t) } /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ + DAG_scene_relations_update(G.main, t->scene); DAG_scene_flush_update(G.main, t->scene, -1, 0); /* and we store them temporal in base (only used for transform code) */ @@ -4766,6 +4827,7 @@ static int count_proportional_objects(TransInfo *t) /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ + DAG_scene_relations_update(G.main, t->scene); DAG_scene_flush_update(G.main, t->scene, -1, 0); /* and we store them temporal in base (only used for transform code) */ @@ -5080,25 +5142,25 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (canceled == 0) { /* we need to delete the temporary faces before automerging */ if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; /* handle multires re-projection, done * on transform completion since it's * really slow -joeedh */ - projectSVData(t, TRUE); + projectEdgeSlideData(t, TRUE); /* free temporary faces to avoid automerging and deleting * during cleanup - psy-fi */ - freeSlideTempFaces(sld); + freeEdgeSlideTempFaces(sld); } - EDBM_automerge(t->scene, t->obedit, 1); + EDBM_automerge(t->scene, t->obedit, TRUE); } else { if (t->mode == TFM_EDGE_SLIDE) { - SlideData *sld = t->customData; + EdgeSlideData *sld = t->customData; sld->perc = 0.0; - projectSVData(t, FALSE); + projectEdgeSlideData(t, FALSE); } } } @@ -5480,6 +5542,9 @@ void special_aftertrans_update(bContext *C, TransInfo *t) if (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) recalcObPaths = 1; } + /* restore rigid body transform */ + if (ob->rigidbody_object && canceled) + BKE_rigidbody_aftertrans_update(ob, td->ext->oloc, td->ext->orot, td->ext->oquat, td->ext->orotAxis, td->ext->orotAngle); } /* recalculate motion paths for objects (if necessary) @@ -5592,7 +5657,8 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node) /* hold original location */ float locxy[2] = {BLI_rctf_cent_x(&node->totr), BLI_rctf_cent_y(&node->totr)}; - + float nodeloc[2]; + copy_v2_v2(td2d->loc, locxy); td2d->loc[2] = 0.0f; td2d->loc2d = td2d->loc; /* current location */ @@ -5617,7 +5683,10 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node) unit_m3(td->mtx); unit_m3(td->smtx); - sub_v2_v2v2(td2d->ih1, &node->locx, locxy); + /* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */ + nodeloc[0] = UI_DPI_FAC * node->locx; + nodeloc[1] = UI_DPI_FAC * node->locy; + sub_v2_v2v2(td2d->ih1, nodeloc, locxy); td->extra = node; } @@ -5673,10 +5742,10 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t) /* * motion tracking * */ -enum { +enum transDataTracking_Mode { transDataTracking_ModeTracks = 0, - transDataTracking_ModeCurves = 1, -} transDataTracking_Mode; + transDataTracking_ModeCurves = 1 +}; typedef struct TransDataTracking { int mode, flag; @@ -6531,7 +6600,7 @@ void createTransData(bContext *C, TransInfo *t) sort_trans_data_dist(t); } } - else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) { + 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. * diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 615bb786071..2a3b0bc8726 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -56,11 +56,15 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "RNA_access.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BIK_api.h" + #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -128,6 +132,7 @@ void getViewVector(TransInfo *t, float coord[3], float vec[3]) /* ************************** GENERICS **************************** */ + static void clipMirrorModifier(TransInfo *t, Object *ob) { ModifierData *md = ob->modifiers.first; @@ -375,6 +380,8 @@ static void recalcData_graphedit(TransInfo *t) bAnimListElem *ale; int dosort = 0; + + const bool use_local_center = checkUseLocalCenter_GraphEdit(t); /* initialize relevant anim-context 'context' data from TransInfo data */ @@ -403,9 +410,10 @@ static void recalcData_graphedit(TransInfo *t) /* ignore unselected fcurves */ if (!fcu_test_selected(fcu)) continue; - - // fixme: only do this for selected verts... - ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS | ANIM_UNITCONV_RESTORE); + + ANIM_unit_mapping_apply_fcurve(ac.scene, ale->id, ale->key_data, + ANIM_UNITCONV_ONLYSEL | ANIM_UNITCONV_SELVERTS | ANIM_UNITCONV_RESTORE | + (use_local_center ? ANIM_UNITCONV_SKIPKNOTS : 0)); /* watch it: if the time is wrong: do not correct handles yet */ @@ -548,13 +556,20 @@ static void recalcData_nla(TransInfo *t) break; } - /* use RNA to write the values... */ - // TODO: do we need to write in 2 passes to make sure that no truncation goes on? + /* Use RNA to write the values to ensure that constraints on these are obeyed + * (e.g. for transition strips, the values are taken from the neighbours) + * + * NOTE: we write these twice to avoid truncation errors which can arise when + * moving the strips a large distance using numeric input [#33852] + */ RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]); RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]); + RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]); + RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]); + /* flush transforms to child strips (since this should be a meta) */ BKE_nlameta_flush_transforms(strip); @@ -796,6 +811,7 @@ static void recalcData_view3d(TransInfo *t) if (td->extra) { float vec[3], up_axis[3]; float qrot[4]; + float roll; ebo = td->extra; copy_v3_v3(up_axis, td->axismtx[2]); @@ -810,7 +826,9 @@ static void recalcData_view3d(TransInfo *t) mul_m3_v3(t->mat, up_axis); } - ebo->roll = ED_rollBoneToVector(ebo, up_axis, FALSE); + /* roll has a tendency to flip in certain orientations - [#34283], [#33974] */ + roll = ED_rollBoneToVector(ebo, up_axis, false); + ebo->roll = angle_compat_rad(roll, ebo->roll); } } } @@ -847,6 +865,8 @@ static void recalcData_view3d(TransInfo *t) /* old optimize trick... this enforces to bypass the depgraph */ if (!(arm->flag & ARM_DELAYDEFORM)) { DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */ + /* transformation of pose may affect IK tree, make sure it is rebuilt */ + BIK_clear_data(ob->pose); } else BKE_pose_where_is(t->scene, ob); @@ -992,7 +1012,7 @@ void resetTransRestrictions(TransInfo *t) } /* the *op can be NULL */ -int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) +int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event) { Scene *sce = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -1445,7 +1465,7 @@ void calculateCenter2D(TransInfo *t) void calculateCenterCursor(TransInfo *t) { - float *cursor; + const float *cursor; cursor = give_cursor(t->scene, t->view); copy_v3_v3(t->center, cursor); @@ -1529,13 +1549,6 @@ void calculateCenterMedian(TransInfo *t) total++; } } - else { - /* - * All the selected elements are at the head of the array - * which means we can stop when it finds unselected data - */ - break; - } } if (i) mul_v3_fl(partial, 1.0f / total); @@ -1555,13 +1568,6 @@ void calculateCenterBound(TransInfo *t) if (!(t->data[i].flag & TD_NOCENTER)) minmax_v3v3_v3(min, max, t->data[i].center); } - else { - /* - * All the selected elements are at the head of the array - * which means we can stop when it finds unselected data - */ - break; - } } else { copy_v3_v3(max, t->data[i].center); @@ -1663,7 +1669,7 @@ void calculateCenter(TransInfo *t) projectIntView(t, axis, t->center2d); - /* rotate only needs correct 2d center, grab needs initgrabz() value */ + /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */ if (t->mode == TFM_TRANSLATION) { copy_v3_v3(t->center, axis); copy_v3_v3(t->con.center, t->center); @@ -1673,18 +1679,16 @@ void calculateCenter(TransInfo *t) } if (t->spacetype == SPACE_VIEW3D) { - /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */ + /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */ + float vec[3]; if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; - float vec[3]; - - copy_v3_v3(vec, t->center); - mul_m4_v3(ob->obmat, vec); - initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]); + mul_v3_m4v3(vec, ob->obmat, t->center); } else { - initgrabz(t->ar->regiondata, t->center[0], t->center[1], t->center[2]); + copy_v3_v3(vec, t->center); } + t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, vec, NULL); } } @@ -1764,25 +1768,25 @@ void calculatePropRatio(TransInfo *t) } switch (t->prop_mode) { case PROP_SHARP: - strcpy(t->proptext, "(Sharp)"); + strcpy(t->proptext, IFACE_("(Sharp)")); break; case PROP_SMOOTH: - strcpy(t->proptext, "(Smooth)"); + strcpy(t->proptext, IFACE_("(Smooth)")); break; case PROP_ROOT: - strcpy(t->proptext, "(Root)"); + strcpy(t->proptext, IFACE_("(Root)")); break; case PROP_LIN: - strcpy(t->proptext, "(Linear)"); + strcpy(t->proptext, IFACE_("(Linear)")); break; case PROP_CONST: - strcpy(t->proptext, "(Constant)"); + strcpy(t->proptext, IFACE_("(Constant)")); break; case PROP_SPHERE: - strcpy(t->proptext, "(Sphere)"); + strcpy(t->proptext, IFACE_("(Sphere)")); break; case PROP_RANDOM: - strcpy(t->proptext, "(Random)"); + strcpy(t->proptext, IFACE_("(Random)")); break; default: t->proptext[0] = '\0'; diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 7e05fdae364..4943a3a2fe7 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -164,7 +164,7 @@ static void InputVerticalAbsolute(TransInfo *t, MouseInput *mi, const int mval[2 output[0] = dot_v3v3(t->viewinv[1], vec) * 2.0f; } -void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, int start[2], int end[2]) +void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, const int start[2], const int end[2]) { int *data; @@ -180,7 +180,7 @@ void setCustomPoints(TransInfo *UNUSED(t), MouseInput *mi, int start[2], int end data[3] = end[1]; } -static void InputCustomRatio(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3]) +static void InputCustomRatioFlip(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3]) { double length; double distance; @@ -213,6 +213,12 @@ static void InputCustomRatio(TransInfo *UNUSED(t), MouseInput *mi, const int mva } } +static void InputCustomRatio(TransInfo *t, MouseInput *mi, const int mval[2], float output[3]) +{ + InputCustomRatioFlip(t, mi, mval, output); + output[0] = -output[0]; +} + static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], float output[3]) { double dx2 = mval[0] - mi->center[0]; @@ -232,7 +238,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], double deler = (((dx1 * dx1 + dy1 * dy1) + (dx2 * dx2 + dy2 * dy2) - (dx3 * dx3 + dy3 * dy3)) / (2.0 * ((A * B) ? (A * B) : 1.0))); - /* ((A*B)?(A*B):1.0) this takes care of potential divide by zero errors */ + /* ((A * B) ? (A * B) : 1.0) this takes care of potential divide by zero errors */ float dphi; @@ -275,7 +281,7 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2], output[0] = *angle; } -void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, int center[2], int mval[2]) +void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const int center[2], const int mval[2]) { mi->factor = 0; mi->precision = 0; @@ -301,15 +307,8 @@ static void calcSpringFactor(MouseInput *mi) void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) { - /* may have been allocated previously */ - /* TODO, holding R-key can cause mem leak, but this causes [#28903] - * disable for now. */ -#if 0 - if (mi->data) { - MEM_freeN(mi->data); - mi->data = NULL; - } -#endif + /* incase we allocate a new value */ + void *mi_data_prev = mi->data; switch (mode) { case INPUT_VECTOR: @@ -358,17 +357,27 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode) mi->apply = InputCustomRatio; t->helpline = HLP_NONE; break; + case INPUT_CUSTOM_RATIO_FLIP: + mi->apply = InputCustomRatioFlip; + t->helpline = HLP_NONE; + break; case INPUT_NONE: default: mi->apply = NULL; break; } + /* if we've allocated new data, free the old data + * less hassle then checking before every alloc above */ + if (mi_data_prev && (mi_data_prev != mi->data)) { + MEM_freeN(mi_data_prev); + } + /* bootstrap mouse input with initial values */ applyMouseInput(t, mi, mi->imval, t->values); } -void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *, float[3])) +void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float values[3])) { mi->post = post; } @@ -384,7 +393,7 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp } } -int handleMouseInput(TransInfo *t, MouseInput *mi, wmEvent *event) +int handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event) { int redraw = TREDRAW_NOTHING; @@ -397,12 +406,13 @@ int handleMouseInput(TransInfo *t, MouseInput *mi, wmEvent *event) * store the mouse position where the normal movement ended */ copy_v2_v2_int(mi->precision_mval, event->mval); mi->precision = 1; + redraw = TREDRAW_HARD; } - else { + else if (event->val == KM_RELEASE) { t->modifiers &= ~MOD_PRECISION; mi->precision = 0; + redraw = TREDRAW_HARD; } - redraw = TREDRAW_HARD; break; } diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 757fdfa2445..bea1f9da057 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -148,10 +148,8 @@ static void stats_pose(Scene *scene, RegionView3D *rv3d, bPoseChannel *pchan) Bone *bone = pchan->bone; if (bone) { - if (bone->flag & BONE_TRANSFORM) { - calc_tw_center(scene, pchan->pose_head); - protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag); - } + calc_tw_center(scene, pchan->pose_head); + protectflag_to_drawflags(pchan->protectflag, &rv3d->twdrawflag); } } @@ -361,18 +359,35 @@ int calc_manipulator_stats(const bContext *C) else if (obedit->type == OB_ARMATURE) { bArmature *arm = obedit->data; EditBone *ebo; - for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { - if (EBONE_VISIBLE(arm, ebo)) { - if (ebo->flag & BONE_TIPSEL) { - calc_tw_center(scene, ebo->tail); - totsel++; - } - if (ebo->flag & BONE_ROOTSEL) { - calc_tw_center(scene, ebo->head); - totsel++; - } - if (ebo->flag & BONE_SELECTED) { - stats_editbone(rv3d, ebo); + + if ((v3d->around == V3D_ACTIVE) && (ebo = arm->act_edbone)) { + /* doesn't check selection or visibility intentionally */ + if (ebo->flag & BONE_TIPSEL) { + calc_tw_center(scene, ebo->tail); + totsel++; + } + if ((ebo->flag & BONE_ROOTSEL) || + ((ebo->flag & BONE_TIPSEL) == FALSE)) /* ensure we get at least one point */ + { + calc_tw_center(scene, ebo->head); + totsel++; + } + stats_editbone(rv3d, ebo); + } + else { + for (ebo = arm->edbo->first; ebo; ebo = ebo->next) { + if (EBONE_VISIBLE(arm, ebo)) { + if (ebo->flag & BONE_TIPSEL) { + calc_tw_center(scene, ebo->tail); + totsel++; + } + if (ebo->flag & BONE_ROOTSEL) { + calc_tw_center(scene, ebo->head); + totsel++; + } + if (ebo->flag & BONE_SELECTED) { + stats_editbone(rv3d, ebo); + } } } } @@ -480,17 +495,35 @@ int calc_manipulator_stats(const bContext *C) else if (ob && (ob->mode & OB_MODE_POSE)) { bPoseChannel *pchan; int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the manipulator mode, could be mixed + int ok = FALSE; if ((ob->lay & v3d->lay) == 0) return 0; - totsel = count_set_pose_transflags(&mode, 0, ob); - - if (totsel) { - /* use channels to get stats */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if ((v3d->around == V3D_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) { + /* doesn't check selection or visibility intentionally */ + Bone *bone = pchan->bone; + if (bone) { stats_pose(scene, rv3d, pchan); + totsel = 1; + ok = TRUE; + } + } + else { + totsel = count_set_pose_transflags(&mode, 0, ob); + + if (totsel) { + /* use channels to get stats */ + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + Bone *bone = pchan->bone; + if (bone && (bone->flag & BONE_TRANSFORM)) { + stats_pose(scene, rv3d, pchan); + } + } + ok = TRUE; } + } + if (ok) { mul_v3_fl(scene->twcent, 1.0f / (float)totsel); // centroid! mul_m4_v3(ob->obmat, scene->twcent); mul_m4_v3(ob->obmat, scene->twmin); @@ -552,8 +585,9 @@ int calc_manipulator_stats(const bContext *C) switch (v3d->twmode) { case V3D_MANIP_GLOBAL: + { break; /* nothing to do */ - + } case V3D_MANIP_GIMBAL: { float mat[3][3]; @@ -562,28 +596,43 @@ int calc_manipulator_stats(const bContext *C) break; } /* if not gimbal, fall through to normal */ + /* pass through */ } case V3D_MANIP_NORMAL: + { if (obedit || ob->mode & OB_MODE_POSE) { float mat[3][3]; ED_getTransformOrientationMatrix(C, mat, (v3d->around == V3D_ACTIVE)); copy_m4_m3(rv3d->twmat, mat); break; } - /* no break we define 'normal' as 'local' in Object mode */ + /* no break we define 'normal' as 'local' in Object mode */ + /* pass through */ + } case V3D_MANIP_LOCAL: + { + if (ob->mode & OB_MODE_POSE) { + /* each bone moves on its own local axis, but to avoid confusion, + * use the active pones axis for display [#33575], this works as expected on a single bone + * 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)); + copy_m4_m3(rv3d->twmat, mat); + break; + } copy_m4_m4(rv3d->twmat, ob->obmat); normalize_m4(rv3d->twmat); break; - + } case V3D_MANIP_VIEW: { float mat[3][3]; copy_m3_m4(mat, rv3d->viewinv); normalize_m3(mat); copy_m4_m3(rv3d->twmat, mat); + break; } - break; default: /* V3D_MANIP_CUSTOM */ { float mat[3][3]; @@ -685,8 +734,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i float cos_phi, sin_phi, dist; phi += side_delta; - cos_phi = (float)cos(phi); - sin_phi = (float)sin(phi); + cos_phi = cosf(phi); + sin_phi = sinf(phi); dist = radhole + radring * cos_phi; glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); @@ -700,8 +749,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i float cos_phi, sin_phi, dist; phi += side_delta; - cos_phi = (float)cos(phi); - sin_phi = (float)sin(phi); + cos_phi = cosf(phi); + sin_phi = sinf(phi); dist = radhole + radring * cos_phi; glVertex3f(cos_theta1 * dist, -sin_theta1 * dist, radring * sin_phi); @@ -792,37 +841,89 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c glColor4ubv(col); } -/* viewmatrix should have been set OK, also no shademode! */ -static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode, int flagx, int flagy, int flagz) +static void axis_sort_v3(const float axis_values[3], int r_axis_order[3]) { + float v[3]; + copy_v3_v3(v, axis_values); - /* axes */ - if (flagx) { - manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0])); - if (flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X); - else if (flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X); - glBegin(GL_LINES); - glVertex3f(0.2f, 0.0f, 0.0f); - glVertex3f(1.0f, 0.0f, 0.0f); - glEnd(); +#define SWAP_AXIS(a, b) { \ + SWAP(float, v[a], v[b]); \ + SWAP(int, r_axis_order[a], r_axis_order[b]); \ +} (void)0 + + if (v[0] < v[1]) { + if (v[2] < v[0]) { SWAP_AXIS(0, 2); } } - if (flagy) { - if (flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y); - else if (flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y); - manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1])); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.2f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); - glEnd(); + else { + if (v[1] < v[2]) { SWAP_AXIS(0, 1); } + else { SWAP_AXIS(0, 2); } + } + if (v[2] < v[1]) { SWAP_AXIS(1, 2); } + +#undef SWAP_AXIS +} +static void manipulator_axis_order(RegionView3D *rv3d, int r_axis_order[3]) +{ + float axis_values[3]; + float vec[3]; + + ED_view3d_global_to_vector(rv3d, rv3d->twmat[3], vec); + + axis_values[0] = -dot_v3v3(rv3d->twmat[0], vec); + axis_values[1] = -dot_v3v3(rv3d->twmat[1], vec); + axis_values[2] = -dot_v3v3(rv3d->twmat[2], vec); + + axis_sort_v3(axis_values, r_axis_order); +} + +/* viewmatrix should have been set OK, also no shademode! */ +static void draw_manipulator_axes_single(View3D *v3d, RegionView3D *rv3d, int colcode, + int flagx, int flagy, int flagz, int axis) +{ + switch (axis) { + case 0: + /* axes */ + if (flagx) { + manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0])); + if (flagx & MAN_SCALE_X) glLoadName(MAN_SCALE_X); + else if (flagx & MAN_TRANS_X) glLoadName(MAN_TRANS_X); + glBegin(GL_LINES); + glVertex3f(0.2f, 0.0f, 0.0f); + glVertex3f(1.0f, 0.0f, 0.0f); + glEnd(); + } + break; + case 1: + if (flagy) { + if (flagy & MAN_SCALE_Y) glLoadName(MAN_SCALE_Y); + else if (flagy & MAN_TRANS_Y) glLoadName(MAN_TRANS_Y); + manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1])); + glBegin(GL_LINES); + glVertex3f(0.0f, 0.2f, 0.0f); + glVertex3f(0.0f, 1.0f, 0.0f); + glEnd(); + } + break; + case 2: + if (flagz) { + if (flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z); + else if (flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z); + manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2])); + glBegin(GL_LINES); + glVertex3f(0.0f, 0.0f, 0.2f); + glVertex3f(0.0f, 0.0f, 1.0f); + glEnd(); + } + break; } - if (flagz) { - if (flagz & MAN_SCALE_Z) glLoadName(MAN_SCALE_Z); - else if (flagz & MAN_TRANS_Z) glLoadName(MAN_TRANS_Z); - manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2])); - glBegin(GL_LINES); - glVertex3f(0.0f, 0.0f, 0.2f); - glVertex3f(0.0f, 0.0f, 1.0f); - glEnd(); +} +static void draw_manipulator_axes(View3D *v3d, RegionView3D *rv3d, int colcode, + int flagx, int flagy, int flagz, + const int axis_order[3]) +{ + int i; + for (i = 0; i < 3; i++) { + draw_manipulator_axes_single(v3d, rv3d, colcode, flagx, flagy, flagz, axis_order[i]); } } @@ -1165,10 +1266,14 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving, { float cywid = 0.25f * 0.01f * (float)U.tw_handlesize; float cusize = cywid * 0.75f, dz; + int axis_order[3] = {2, 0, 1}; + int i; /* when called while moving in mixed mode, do not draw when... */ if ((drawflags & MAN_SCALE_C) == 0) return; + manipulator_axis_order(rv3d, axis_order); + glDisable(GL_DEPTH_TEST); /* not in combo mode */ @@ -1188,7 +1293,9 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving, dz = 1.0; } - else dz = 1.0f - 4.0f * cusize; + else { + dz = 1.0f - 4.0f * cusize; + } if (moving) { float matt[4][4]; @@ -1206,28 +1313,41 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving, /* axis */ /* in combo mode, this is always drawn as first type */ - draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z); - - /* Z cube */ - glTranslatef(0.0, 0.0, dz); - if (drawflags & MAN_SCALE_Z) { - if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z); - manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2])); - drawsolidcube(cusize); - } - /* X cube */ - glTranslatef(dz, 0.0, -dz); - if (drawflags & MAN_SCALE_X) { - if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_X); - manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0])); - drawsolidcube(cusize); - } - /* Y cube */ - glTranslatef(-dz, dz, 0.0); - if (drawflags & MAN_SCALE_Y) { - if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y); - manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1])); - drawsolidcube(cusize); + draw_manipulator_axes(v3d, rv3d, colcode, + drawflags & MAN_SCALE_X, drawflags & MAN_SCALE_Y, drawflags & MAN_SCALE_Z, + axis_order); + + + for (i = 0; i < 3; i++) { + switch (axis_order[i]) { + case 0: /* X cube */ + if (drawflags & MAN_SCALE_X) { + glTranslatef(dz, 0.0, 0.0); + if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_X); + manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0])); + drawsolidcube(cusize); + glTranslatef(-dz, 0.0, 0.0); + } + break; + case 1: /* Y cube */ + if (drawflags & MAN_SCALE_Y) { + glTranslatef(0.0, dz, 0.0); + if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Y); + manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1])); + drawsolidcube(cusize); + glTranslatef(0.0, -dz, 0.0); + } + break; + case 2: /* Z cube */ + if (drawflags & MAN_SCALE_Z) { + glTranslatef(0.0, 0.0, dz); + if (G.f & G_PICKSEL) glLoadName(MAN_SCALE_Z); + manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2])); + drawsolidcube(cusize); + glTranslatef(0.0, 0.0, -dz); + } + break; + } } /* if shiftkey, center point as last, for selectbuffer order */ @@ -1284,16 +1404,17 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUS float cywid = 0.25f * cylen, dz, size; float unitmat[4][4]; int shift = 0; // XXX + int axis_order[3] = {0, 1, 2}; + int i; /* when called while moving in mixed mode, do not draw when... */ if ((drawflags & MAN_TRANS_C) == 0) return; + manipulator_axis_order(rv3d, axis_order); + // XXX if (moving) glTranslatef(t->vec[0], t->vec[1], t->vec[2]); glDisable(GL_DEPTH_TEST); - qobj = gluNewQuadric(); - gluQuadricDrawStyle(qobj, GLU_FILL); - /* center circle, do not add to selection when shift is pressed (planar constraint) */ if ((G.f & G_PICKSEL) && shift == 0) glLoadName(MAN_TRANS_C); @@ -1311,8 +1432,11 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUS glLoadName(-1); // translate drawn as last, only axis when no combo with scale, or for ghosting - if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) - draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z); + if ((combo & V3D_MANIP_SCALE) == 0 || colcode == MAN_GHOST) { + draw_manipulator_axes(v3d, rv3d, colcode, + drawflags & MAN_TRANS_X, drawflags & MAN_TRANS_Y, drawflags & MAN_TRANS_Z, + axis_order); + } /* offset in combo mode, for rotate a bit more */ @@ -1320,29 +1444,43 @@ static void draw_manipulator_translate(View3D *v3d, RegionView3D *rv3d, int UNUS else if (combo & (V3D_MANIP_SCALE)) dz = 1.0f + 0.5f * cylen; else dz = 1.0f; - /* Z Cone */ - glTranslatef(0.0, 0.0, dz); - if (drawflags & MAN_TRANS_Z) { - if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z); - manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2])); - draw_cone(qobj, cylen, cywid); - } - /* X Cone */ - glTranslatef(dz, 0.0, -dz); - if (drawflags & MAN_TRANS_X) { - if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_X); - glRotatef(90.0, 0.0, 1.0, 0.0); - manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0])); - draw_cone(qobj, cylen, cywid); - glRotatef(-90.0, 0.0, 1.0, 0.0); - } - /* Y Cone */ - glTranslatef(-dz, dz, 0.0); - if (drawflags & MAN_TRANS_Y) { - if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y); - glRotatef(-90.0, 1.0, 0.0, 0.0); - manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1])); - draw_cone(qobj, cylen, cywid); + qobj = gluNewQuadric(); + gluQuadricDrawStyle(qobj, GLU_FILL); + + for (i = 0; i < 3; i++) { + switch (axis_order[i]) { + case 0: /* Z Cone */ + if (drawflags & MAN_TRANS_Z) { + glTranslatef(0.0, 0.0, dz); + if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Z); + manipulator_setcolor(v3d, 'Z', colcode, axisBlendAngle(rv3d->twangle[2])); + draw_cone(qobj, cylen, cywid); + glTranslatef(0.0, 0.0, -dz); + } + break; + case 1: /* X Cone */ + if (drawflags & MAN_TRANS_X) { + glTranslatef(dz, 0.0, 0.0); + if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_X); + glRotatef(90.0, 0.0, 1.0, 0.0); + manipulator_setcolor(v3d, 'X', colcode, axisBlendAngle(rv3d->twangle[0])); + draw_cone(qobj, cylen, cywid); + glRotatef(-90.0, 0.0, 1.0, 0.0); + glTranslatef(-dz, 0.0, 0.0); + } + break; + case 2: /* Y Cone */ + if (drawflags & MAN_TRANS_Y) { + glTranslatef(0.0, dz, 0.0); + if (G.f & G_PICKSEL) glLoadName(MAN_TRANS_Y); + glRotatef(-90.0, 1.0, 0.0, 0.0); + manipulator_setcolor(v3d, 'Y', colcode, axisBlendAngle(rv3d->twangle[1])); + draw_cone(qobj, cylen, cywid); + glRotatef(90.0, 1.0, 0.0, 0.0); + glTranslatef(0.0, -dz, 0.0); + } + break; + } } gluDeleteQuadric(qobj); @@ -1358,10 +1496,13 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov float size; float cylen = 0.01f * (float)U.tw_handlesize; float cywid = 0.25f * cylen; - + int axis_order[3] = {2, 0, 1}; + int i; /* when called while moving in mixed mode, do not draw when... */ if ((drawflags & MAN_ROT_C) == 0) return; + manipulator_axis_order(rv3d, axis_order); + /* prepare for screen aligned draw */ glPushMatrix(); size = screen_aligned(rv3d, rv3d->twmat); @@ -1412,36 +1553,50 @@ static void draw_manipulator_rotate_cyl(View3D *v3d, RegionView3D *rv3d, int mov if ((G.f & G_PICKSEL) == 0) { // only draw axis when combo didn't draw scale axes - if ((combo & V3D_MANIP_SCALE) == 0) - draw_manipulator_axes(v3d, rv3d, colcode, drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z); + if ((combo & V3D_MANIP_SCALE) == 0) { + draw_manipulator_axes(v3d, rv3d, colcode, + drawflags & MAN_ROT_X, drawflags & MAN_ROT_Y, drawflags & MAN_ROT_Z, + axis_order); + } /* only has to be set when not in picking */ gluQuadricDrawStyle(qobj, GLU_FILL); } - /* Z cyl */ - glTranslatef(0.0, 0.0, 1.0); - if (drawflags & MAN_ROT_Z) { - if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Z); - manipulator_setcolor(v3d, 'Z', colcode, 255); - draw_cylinder(qobj, cylen, cywid); - } - /* X cyl */ - glTranslatef(1.0, 0.0, -1.0); - if (drawflags & MAN_ROT_X) { - if (G.f & G_PICKSEL) glLoadName(MAN_ROT_X); - glRotatef(90.0, 0.0, 1.0, 0.0); - manipulator_setcolor(v3d, 'X', colcode, 255); - draw_cylinder(qobj, cylen, cywid); - glRotatef(-90.0, 0.0, 1.0, 0.0); - } - /* Y cylinder */ - glTranslatef(-1.0, 1.0, 0.0); - if (drawflags & MAN_ROT_Y) { - if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Y); - glRotatef(-90.0, 1.0, 0.0, 0.0); - manipulator_setcolor(v3d, 'Y', colcode, 255); - draw_cylinder(qobj, cylen, cywid); + for (i = 0; i < 3; i++) { + switch (axis_order[i]) { + case 0: /* X cylinder */ + if (drawflags & MAN_ROT_X) { + glTranslatef(1.0, 0.0, 0.0); + if (G.f & G_PICKSEL) glLoadName(MAN_ROT_X); + glRotatef(90.0, 0.0, 1.0, 0.0); + manipulator_setcolor(v3d, 'X', colcode, 255); + draw_cylinder(qobj, cylen, cywid); + glRotatef(-90.0, 0.0, 1.0, 0.0); + glTranslatef(-1.0, 0.0, 0.0); + } + break; + case 1: /* Y cylinder */ + if (drawflags & MAN_ROT_Y) { + glTranslatef(0.0, 1.0, 0.0); + if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Y); + glRotatef(-90.0, 1.0, 0.0, 0.0); + manipulator_setcolor(v3d, 'Y', colcode, 255); + draw_cylinder(qobj, cylen, cywid); + glRotatef(90.0, 1.0, 0.0, 0.0); + glTranslatef(0.0, -1.0, 0.0); + } + break; + case 2: /* Z cylinder */ + if (drawflags & MAN_ROT_Z) { + glTranslatef(0.0, 0.0, 1.0); + if (G.f & G_PICKSEL) glLoadName(MAN_ROT_Z); + manipulator_setcolor(v3d, 'Z', colcode, 255); + draw_cylinder(qobj, cylen, cywid); + glTranslatef(0.0, 0.0, -1.0); + } + break; + } } /* restore */ @@ -1586,8 +1741,12 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl dep = buffer[4 * a + 1]; val = buffer[4 * a + 3]; - if (val == MAN_TRANS_C) return MAN_TRANS_C; - else if (val == MAN_SCALE_C) return MAN_SCALE_C; + if (val == MAN_TRANS_C) { + return MAN_TRANS_C; + } + else if (val == MAN_SCALE_C) { + return MAN_SCALE_C; + } else { if (val & MAN_ROT_C) { if (minvalrot == 0 || dep < mindeprot) { @@ -1614,7 +1773,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl /* return 0; nothing happened */ -int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op) +int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; @@ -1702,8 +1861,15 @@ int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op) //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_resize", 0), event, op->ptr, NULL, FALSE); } else if (drawflags == MAN_ROT_T) { /* trackball need special case, init is different */ - WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, op->ptr); - //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, op->ptr, NULL, FALSE); + /* Do not pass op->ptr!!! trackball has no "constraint" properties! + * See [#34621], it's a miracle it did not cause more problems!!! */ + /* However, we need to copy the "release_confirm" property... */ + PointerRNA props_ptr; + WM_operator_properties_create(&props_ptr, "TRANSFORM_OT_trackball"); + RNA_boolean_set(&props_ptr, "release_confirm", RNA_boolean_get(op->ptr, "release_confirm")); + + WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, &props_ptr); + //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, NULL, NULL, FALSE); } else if (drawflags & MAN_ROT_C) { switch (drawflags) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 916cf540589..60b0c655691 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -24,24 +24,25 @@ * \ingroup edtransform */ - #include "MEM_guardedalloc.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_global.h" #include "BKE_armature.h" #include "BKE_report.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + #include "WM_api.h" #include "WM_types.h" @@ -73,6 +74,7 @@ static char OP_TILT[] = "TRANSFORM_OT_tilt"; static char OP_TRACKBALL[] = "TRANSFORM_OT_trackball"; static char OP_MIRROR[] = "TRANSFORM_OT_mirror"; static char OP_EDGE_SLIDE[] = "TRANSFORM_OT_edge_slide"; +static char OP_VERT_SLIDE[] = "TRANSFORM_OT_vert_slide"; static char OP_EDGE_CREASE[] = "TRANSFORM_OT_edge_crease"; static char OP_EDGE_BWEIGHT[] = "TRANSFORM_OT_edge_bevelweight"; static char OP_SEQ_SLIDE[] = "TRANSFORM_OT_seq_slide"; @@ -90,6 +92,7 @@ static void TRANSFORM_OT_tilt(struct wmOperatorType *ot); static void TRANSFORM_OT_trackball(struct wmOperatorType *ot); static void TRANSFORM_OT_mirror(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot); +static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot); static void TRANSFORM_OT_edge_bevelweight(struct wmOperatorType *ot); static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot); @@ -109,6 +112,7 @@ static TransformModeItem transform_modes[] = {OP_TRACKBALL, TFM_TRACKBALL, TRANSFORM_OT_trackball}, {OP_MIRROR, TFM_MIRROR, TRANSFORM_OT_mirror}, {OP_EDGE_SLIDE, TFM_EDGE_SLIDE, TRANSFORM_OT_edge_slide}, + {OP_VERT_SLIDE, TFM_VERT_SLIDE, TRANSFORM_OT_vert_slide}, {OP_EDGE_CREASE, TFM_CREASE, TRANSFORM_OT_edge_crease}, {OP_EDGE_BWEIGHT, TFM_BWEIGHT, TRANSFORM_OT_edge_bevelweight}, {OP_SEQ_SLIDE, TFM_SEQ_SLIDE, TRANSFORM_OT_seq_slide}, @@ -150,38 +154,6 @@ EnumPropertyItem transform_mode_types[] = {0, NULL, 0, NULL, NULL} }; -static int snap_type_exec(bContext *C, wmOperator *op) -{ - ToolSettings *ts = CTX_data_tool_settings(C); - - ts->snap_mode = RNA_enum_get(op->ptr, "type"); - - WM_event_add_notifier(C, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ - - return OPERATOR_FINISHED; -} - -static void TRANSFORM_OT_snap_type(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Snap Type"; - ot->description = "Set the snap element type"; - ot->idname = "TRANSFORM_OT_snap_type"; - - /* api callbacks */ - ot->invoke = WM_menu_invoke; - ot->exec = snap_type_exec; - - ot->poll = ED_operator_areaactive; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* props */ - ot->prop = RNA_def_enum(ot->srna, "type", snap_element_items, 0, "Type", "Set the snap element type"); - -} - static int select_orientation_exec(bContext *C, wmOperator *op) { int orientation = RNA_enum_get(op->ptr, "orientation"); @@ -193,12 +165,12 @@ static int select_orientation_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; - pup = uiPupMenuBegin(C, "Orientation", ICON_NONE); + pup = uiPupMenuBegin(C, IFACE_("Orientation"), ICON_NONE); layout = uiPupMenuLayout(pup); uiItemsEnumO(layout, "TRANSFORM_OT_select_orientation", "orientation"); uiPupMenuEnd(C, pup); @@ -240,7 +212,7 @@ static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int delete_orientation_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return delete_orientation_exec(C, op); } @@ -296,7 +268,7 @@ static int create_orientation_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int create_orientation_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int create_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return create_orientation_exec(C, op); } @@ -328,7 +300,7 @@ static void transformops_exit(bContext *C, wmOperator *op) G.moving = 0; } -static int transformops_data(bContext *C, wmOperator *op, wmEvent *event) +static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event) { int retval = 1; if (op->customdata == NULL) { @@ -362,7 +334,7 @@ static int transformops_data(bContext *C, wmOperator *op, wmEvent *event) return retval; /* return 0 on error */ } -static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) +static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) { int exit_code; @@ -429,7 +401,7 @@ static int transform_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int transform_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!transformops_data(C, op, event)) { G.moving = 0; @@ -458,7 +430,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) /* Make this not hidden when there's a nice axis selection widget */ RNA_def_property_flag(prop, PROP_HIDDEN); RNA_def_property_ui_text(prop, "Axis", "The axis around which the transformation occurs"); - } if (flags & P_CONSTRAINT) { @@ -466,8 +437,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) prop = RNA_def_property(ot->srna, "constraint_orientation", PROP_ENUM, PROP_NONE); RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation"); RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf); - - } if (flags & P_MIRROR) { @@ -585,6 +554,8 @@ 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"; @@ -598,7 +569,9 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; - RNA_def_float_vector(ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); + /* 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); Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP); } @@ -793,6 +766,26 @@ static void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) Transform_Properties(ot, P_MIRROR | P_SNAP | P_CORRECT_UV); } +static void TRANSFORM_OT_vert_slide(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Vertex Slide"; + ot->description = "Slide a vertex along a mesh"; + ot->idname = OP_VERT_SLIDE; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + /* api callbacks */ + ot->invoke = transform_invoke; + ot->exec = transform_exec; + ot->modal = transform_modal; + ot->cancel = transform_cancel; + ot->poll = ED_operator_editmesh; + + RNA_def_float_factor(ot->srna, "value", 0, -10.0f, 10.0f, "Factor", "", -1.0f, 1.0f); + + Transform_Properties(ot, P_MIRROR | P_SNAP); +} + static void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) { /* identifiers */ @@ -848,7 +841,7 @@ static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_sequencer_active; - RNA_def_float_vector(ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); + RNA_def_float_vector_xyz(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); Transform_Properties(ot, P_SNAP); } @@ -891,8 +884,6 @@ void transform_operatortypes(void) WM_operatortype_append(TRANSFORM_OT_select_orientation); WM_operatortype_append(TRANSFORM_OT_create_orientation); WM_operatortype_append(TRANSFORM_OT_delete_orientation); - - WM_operatortype_append(TRANSFORM_OT_snap_type); } void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spaceid) @@ -939,7 +930,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap"); - WM_keymap_add_item(keymap, "TRANSFORM_OT_snap_type", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_element"); + kmi = WM_keymap_add_item(keymap, OP_TRANSLATION, TKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "texture_space", TRUE); @@ -1032,6 +1025,9 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_snap"); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", TABKEY, KM_PRESS, KM_SHIFT | KM_CTRL, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.snap_uv_element"); break; case SPACE_CLIP: WM_keymap_add_item(keymap, OP_TRANSLATION, GKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index d758a15f50c..b12c0906fa0 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -43,6 +43,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BKE_action.h" #include "BKE_armature.h" #include "BKE_curve.h" #include "BKE_context.h" @@ -88,7 +89,7 @@ static TransformOrientation *findOrientationName(ListBase *lb, const char *name) return NULL; } -static int uniqueOrientationNameCheck(void *arg, const char *name) +static bool uniqueOrientationNameCheck(void *arg, const char *name) { return findOrientationName((ListBase *)arg, name) != NULL; } @@ -408,14 +409,16 @@ const char *BIF_menustringTransformOrientation(const bContext *C, const char *ti int i = V3D_MANIP_CUSTOM; char *str_menu, *p; const int elem_size = MAX_NAME + 4; + size_t str_menu_size; title = IFACE_(title); - str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + elem_size * BIF_countTransformOrientation(C), "UserTransSpace from matrix"); + str_menu_size = strlen(menu) + strlen(title) + 1 + (elem_size * BIF_countTransformOrientation(C)); + str_menu = MEM_callocN(str_menu_size, "UserTransSpace from matrix"); + p = str_menu; - - p += sprintf(str_menu, "%s", title); - p += sprintf(p, "%s", menu); + p += BLI_strncpy_rlen(p, title, str_menu_size); + p += BLI_strncpy_rlen(p, menu, str_menu_size - (p - str_menu)); for (ts = transform_spaces->first; ts; ts = ts->next) { p += sprintf(p, "|%s %%x%d", ts->name, i++); @@ -437,7 +440,7 @@ int BIF_countTransformOrientation(const bContext *C) return count; } -void applyTransformOrientation(const bContext *C, float mat[3][3], char *name) +void applyTransformOrientation(const bContext *C, float mat[3][3], char name[MAX_NAME]) { TransformOrientation *ts; View3D *v3d = CTX_wm_view3d(C); @@ -448,8 +451,9 @@ void applyTransformOrientation(const bContext *C, float mat[3][3], char *name) for (i = 0, ts = CTX_data_scene(C)->transform_spaces.first; ts; ts = ts->next, i++) { if (selected_index == i) { - if (name) - strcpy(name, ts->name); + if (name) { + BLI_strncpy(name, ts->name, MAX_NAME); + } copy_m3_m3(mat, ts->mat); break; @@ -491,25 +495,25 @@ void initTransformOrientation(bContext *C, TransInfo *t) switch (t->current_orientation) { case V3D_MANIP_GLOBAL: unit_m3(t->spacemtx); - strcpy(t->spacename, "global"); + strcpy(t->spacename, IFACE_("global")); break; case V3D_MANIP_GIMBAL: unit_m3(t->spacemtx); if (gimbal_axis(ob, t->spacemtx)) { - strcpy(t->spacename, "gimbal"); + strcpy(t->spacename, IFACE_("gimbal")); break; } /* no gimbal fallthrough to normal */ case V3D_MANIP_NORMAL: if (obedit || (ob && ob->mode & OB_MODE_POSE)) { - strcpy(t->spacename, "normal"); + strcpy(t->spacename, IFACE_("normal")); ED_getTransformOrientationMatrix(C, t->spacemtx, (v3d->around == V3D_ACTIVE)); break; } /* no break we define 'normal' as 'local' in Object mode */ case V3D_MANIP_LOCAL: - strcpy(t->spacename, "local"); + strcpy(t->spacename, IFACE_("local")); if (ob) { copy_m3_m4(t->spacemtx, ob->obmat); @@ -526,7 +530,7 @@ void initTransformOrientation(bContext *C, TransInfo *t) RegionView3D *rv3d = t->ar->regiondata; float mat[3][3]; - strcpy(t->spacename, "view"); + strcpy(t->spacename, IFACE_("view")); copy_m3_m4(mat, rv3d->viewinv); normalize_m3(mat); copy_m3_m3(t->spacemtx, mat); @@ -737,7 +741,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], } } - if (normal[0] != 0 || normal[1] != 0 || normal[2] != 0) { + if (!is_zero_v3(normal)) { result = ORIENTATION_NORMAL; } } @@ -760,29 +764,45 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], else if (obedit->type == OB_ARMATURE) { bArmature *arm = obedit->data; EditBone *ebone; + int ok = FALSE; - for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { - if (arm->layer & ebone->layer) { - if (ebone->flag & BONE_SELECTED) { - float tmat[3][3]; - float vec[3]; - sub_v3_v3v3(vec, ebone->tail, ebone->head); - normalize_v3(vec); - add_v3_v3(normal, vec); - - vec_roll_to_mat3(vec, ebone->roll, tmat); - add_v3_v3(plane, tmat[2]); + /* grr. but better then duplicate code */ +#define EBONE_CALC_NORMAL_PLANE { \ + float tmat[3][3]; \ + float vec[3]; \ + sub_v3_v3v3(vec, ebone->tail, ebone->head); \ + normalize_v3(vec); \ + add_v3_v3(normal, vec); \ + \ + vec_roll_to_mat3(vec, ebone->roll, tmat); \ + add_v3_v3(plane, tmat[2]); \ + } (void)0 + + + if (activeOnly && (ebone = arm->act_edbone)) { + EBONE_CALC_NORMAL_PLANE; + ok = TRUE; + } + else { + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (arm->layer & ebone->layer) { + if (ebone->flag & BONE_SELECTED) { + EBONE_CALC_NORMAL_PLANE; + ok = TRUE; + } } } } - normalize_v3(normal); - normalize_v3(plane); + if (ok) { + normalize_v3(normal); + normalize_v3(plane); - if (plane[0] != 0 || plane[1] != 0 || plane[2] != 0) { - result = ORIENTATION_EDGE; + if (!is_zero_v3(plane)) { + result = ORIENTATION_EDGE; + } } - +#undef EBONE_CALC_NORMAL_PLANE } /* Vectors from edges don't need the special transpose inverse multiplication */ @@ -798,19 +818,32 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], else if (ob && (ob->mode & OB_MODE_POSE)) { bArmature *arm = ob->data; bPoseChannel *pchan; - int totsel; - - totsel = count_bone_select(arm, &arm->bonebase, 1); - if (totsel) { - float imat[3][3], mat[3][3]; - - /* use channels to get stats */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { - add_v3_v3(normal, pchan->pose_mat[2]); - add_v3_v3(plane, pchan->pose_mat[1]); + float imat[3][3], mat[3][3]; + int ok = FALSE; + + if (activeOnly && (pchan = BKE_pose_channel_active(ob))) { + add_v3_v3(normal, pchan->pose_mat[2]); + add_v3_v3(plane, pchan->pose_mat[1]); + ok = TRUE; + } + else { + int totsel; + + totsel = count_bone_select(arm, &arm->bonebase, 1); + if (totsel) { + /* use channels to get stats */ + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { + add_v3_v3(normal, pchan->pose_mat[2]); + add_v3_v3(plane, pchan->pose_mat[1]); + } } + ok = TRUE; } + } + + /* use for both active & all */ + if (ok) { negate_v3(plane); /* we need the transpose of the inverse for a normal... */ @@ -851,7 +884,7 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], return result; } -void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], int activeOnly) +void ED_getTransformOrientationMatrix(const bContext *C, float orientation_mat[3][3], const bool activeOnly) { float normal[3] = {0.0, 0.0, 0.0}; float plane[3] = {0.0, 0.0, 0.0}; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 9de9c96f2ec..c92cd77449e 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -47,8 +47,6 @@ #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" -#include "RNA_access.h" - #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -62,6 +60,10 @@ #include "BKE_tessmesh.h" #include "BKE_mesh.h" +#include "RNA_access.h" + +#include "WM_types.h" + #include "ED_armature.h" #include "ED_image.h" #include "ED_mesh.h" @@ -69,8 +71,6 @@ #include "ED_uvedit.h" #include "ED_view3d.h" -#include "WM_types.h" - #include "UI_resources.h" #include "UI_view2d.h" @@ -103,7 +103,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]); /****************** IMPLEMENTATIONS *********************/ -static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode); +static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode); static NodeBorder snapNodeBorder(int snap_node_mode); #if 0 @@ -260,7 +260,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) } } -int handleSnapping(TransInfo *t, wmEvent *event) +int handleSnapping(TransInfo *t, const wmEvent *event) { int status = 0; @@ -303,6 +303,9 @@ void applyProject(TransInfo *t) if (td->flag & TD_SKIP) continue; + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) + continue; copy_v3_v3(iloc, td->loc); if (t->flag & (T_EDIT | T_POSE)) { @@ -804,7 +807,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]) /********************** CALC **************************/ -static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo * t, float *UNUSED(vec)) +static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo *t, float *UNUSED(vec)) { snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS); } @@ -815,7 +818,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) float loc[3]; float no[3]; float mval[2]; - int found = 0; + bool found = false; int dist = SNAP_MIN_DISTANCE; // Use a user defined value here mval[0] = t->mval[0]; @@ -898,7 +901,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) no[0] = 0.0; no[1] = 0.0; no[2] = 1.0; - found = 1; + found = true; } BLI_freelistN(&depth_peels); @@ -907,7 +910,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect); } - if (found == 1) { + if (found == true) { float tangent[3]; sub_v3_v3v3(tangent, loc, t->tsnap.snapPoint); @@ -1141,13 +1144,13 @@ static void TargetSnapClosest(TransInfo *t) } } -static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3], - const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3], + const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; int result; - int retval = 0; + bool retval = false; copy_v3_v3(ray_end, ray_normal_local); mul_v3_fl(ray_end, 2000); @@ -1203,7 +1206,7 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh float n1[3], n2[3]; *r_depth = new_depth; - retval = 1; + retval = true; sub_v3_v3v3(edge_loc, v1co, v2co); sub_v3_v3v3(vec, intersect, v2co); @@ -1228,11 +1231,11 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh return retval; } -static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3], - const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3], + const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { - int retval = 0; + bool retval = false; float dvec[3]; sub_v3_v3v3(dvec, vco, ray_start_local); @@ -1259,7 +1262,7 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4] if (new_dist <= *r_dist && new_depth < *r_depth) { *r_depth = new_depth; - retval = 1; + retval = true; copy_v3_v3(r_loc, location); @@ -1276,13 +1279,13 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4] return retval; } -static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth) +static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float mval[2], + float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth) { float imat[4][4]; float ray_start_local[3], ray_normal_local[3]; - int retval = 0; + bool retval = false; invert_m4_m4(imat, obmat); @@ -1339,11 +1342,11 @@ static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm return retval; } -static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { - int retval = 0; + bool retval = false; int totvert = dm->getNumVerts(dm); int totface = dm->getNumTessFaces(dm); @@ -1417,7 +1420,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh if (em != NULL) { index_array = dm->getVertDataArray(dm, CD_ORIGINDEX); - EDBM_index_arrays_init(em, 1, 0, 0); + EDBM_index_arrays_ensure(em, BM_VERT); } for (i = 0; i < totvert; i++) { @@ -1452,9 +1455,6 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh } } - if (em != NULL) { - EDBM_index_arrays_free(em); - } break; } case SCE_SNAP_MODE_EDGE: @@ -1468,7 +1468,7 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh if (em != NULL) { index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX); - EDBM_index_arrays_init(em, 0, 1, 0); + EDBM_index_arrays_ensure(em, BM_EDGE); } for (i = 0; i < totedge; i++) { @@ -1505,9 +1505,6 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh } } - if (em != NULL) { - EDBM_index_arrays_free(em); - } break; } } @@ -1517,12 +1514,12 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh return retval; } -static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { ToolSettings *ts = scene->toolsettings; - int retval = 0; + bool retval = false; if (ob->type == OB_MESH) { BMEditMesh *em; @@ -1549,12 +1546,12 @@ static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, flo return retval; } -static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2], - int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2], + int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) { Base *base; - float depth = FLT_MAX; - int retval = 0; + float depth = (FLT_MAX / 2.0f); /* use half of flt-max so we can scale up without an exception */ + bool retval = false; float ray_start[3], ray_normal[3]; ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); @@ -1605,12 +1602,12 @@ static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, c return retval; } -int snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +bool snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) { return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, r_dist, r_loc, r_no, mode); } -int snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +bool snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; @@ -1670,11 +1667,11 @@ static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float n peel->flag = 0; } -static int 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) +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) { - int retval = 0; + bool retval = false; int totvert = dm->getNumVerts(dm); int totface = dm->getNumTessFaces(dm); @@ -1779,10 +1776,11 @@ static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], return retval; } -static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase *depth_peels, const float mval[2], SnapMode mode) +static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, + ListBase *depth_peels, const float mval[2], SnapMode mode) { Base *base; - int retval = 0; + bool retval = false; float ray_start[3], ray_normal[3]; ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); @@ -1801,7 +1799,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L if (dob->type == OB_MESH) { BMEditMesh *em; DerivedMesh *dm = NULL; - int val; + bool val; if (dob != obedit) { dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH); @@ -1825,7 +1823,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L } if (ob->type == OB_MESH) { - int val = 0; + bool val = false; 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); @@ -1853,12 +1851,12 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L return retval; } -int peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2], SnapMode mode) +bool peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2], SnapMode mode) { return peelObjects(t->scene, t->view, t->ar, t->obedit, depth_peels, mval, mode); } -int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], SnapMode mode) +bool peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], SnapMode mode) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; @@ -1868,7 +1866,7 @@ int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], /******************** NODES ***********************************/ -static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode) +static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode) { /* node is use for snapping only if a) snap mode matches and b) node is inside the view */ return ((mode == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) || @@ -1890,12 +1888,12 @@ static NodeBorder snapNodeBorder(int snap_node_mode) return 0; } -static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2], - float r_loc[2], int *r_dist, char *r_node_border) +static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2], + float r_loc[2], int *r_dist, char *r_node_border) { View2D *v2d = &ar->v2d; NodeBorder border = snapNodeBorder(ts->snap_node_mode); - int retval = 0; + bool retval = false; rcti totr; int new_dist; @@ -1908,7 +1906,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_LEFT; - retval = 1; + retval = true; } } @@ -1918,7 +1916,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_RIGHT; - retval = 1; + retval = true; } } @@ -1928,7 +1926,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_BOTTOM; - retval = 1; + retval = true; } } @@ -1938,19 +1936,19 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_TOP; - retval = 1; + retval = true; } } return retval; } -static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2], +static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) { bNodeTree *ntree = snode->edittree; bNode *node; - int retval = 0; + bool retval = false; *r_node_border = 0; @@ -1962,12 +1960,12 @@ static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int return retval; } -int snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +bool snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) { return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist, r_loc, r_node_border, mode); } -int snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +bool snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) { Scene *scene = CTX_data_scene(C); return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist, r_loc, r_node_border, mode); |