diff options
Diffstat (limited to 'source/blender/editors/transform/transform.c')
-rw-r--r-- | source/blender/editors/transform/transform.c | 2797 |
1 files changed, 1690 insertions, 1107 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f0e90a05a3b..9bd8417c46e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -41,8 +41,11 @@ #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_mask_types.h" +#include "DNA_mesh_types.h" #include "DNA_movieclip_types.h" #include "DNA_scene_types.h" /* PET modes */ +#include "DNA_workspace_types.h" +#include "DNA_gpencil_types.h" #include "BLI_alloca.h" #include "BLI_utildefines.h" @@ -61,12 +64,21 @@ #include "BKE_constraint.h" #include "BKE_particle.h" #include "BKE_unit.h" +#include "BKE_scene.h" #include "BKE_mask.h" +#include "BKE_mesh.h" #include "BKE_report.h" +#include "BKE_workspace.h" + +#include "DEG_depsgraph.h" -#include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_immediate.h" +#include "GPU_immediate_util.h" +#include "GPU_matrix.h" +#include "GPU_state.h" + #include "ED_image.h" #include "ED_keyframing.h" #include "ED_screen.h" @@ -76,6 +88,7 @@ #include "ED_mesh.h" #include "ED_clip.h" #include "ED_node.h" +#include "ED_gpencil.h" #include "WM_types.h" #include "WM_api.h" @@ -86,6 +99,7 @@ #include "UI_resources.h" #include "RNA_access.h" +#include "RNA_define.h" #include "BLF_api.h" #include "BLT_translation.h" @@ -103,9 +117,10 @@ static void drawEdgeSlide(TransInfo *t); static void drawVertSlide(TransInfo *t); static void postInputRotation(TransInfo *t, float values[3]); -static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], const short around); +static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around); static void initSnapSpatial(TransInfo *t, float r_snap[3]); +static void storeCustomLNorValue(TransDataContainer *t, BMesh *bm); /* Transform Callbacks */ static void initBend(TransInfo *t); @@ -131,6 +146,9 @@ static void applyToSphere(TransInfo *t, const int mval[2]); static void initRotation(TransInfo *t); static void applyRotation(TransInfo *t, const int mval[2]); +static void initNormalRotation(TransInfo *t); +static void applyNormalRotation(TransInfo *t, const int mval[2]); + static void initShrinkFatten(TransInfo *t); static void applyShrinkFatten(TransInfo *t, const int mval[2]); @@ -204,7 +222,8 @@ static bool transdata_check_local_center(TransInfo *t, short around) { return ((around == V3D_AROUND_LOCAL_ORIGINS) && ( (t->flag & (T_OBJECT | T_POSE)) || - (t->obedit && ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) || + /* implicit: (t->flag & T_EDIT) */ + (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) || (t->spacetype == SPACE_IPO) || (t->options & (CTX_MOVIECLIP | CTX_MASK | CTX_PAINT_CURVE))) ); @@ -213,10 +232,10 @@ static bool transdata_check_local_center(TransInfo *t, short around) bool transdata_check_local_islands(TransInfo *t, short around) { return ((around == V3D_AROUND_LOCAL_ORIGINS) && ( - (t->obedit && ELEM(t->obedit->type, OB_MESH)))); + (ELEM(t->obedit_type, OB_MESH)))); } -/* ************************** SPACE DEPENDANT CODE **************************** */ +/* ************************** SPACE DEPENDENT CODE **************************** */ void setTransformViewMatrices(TransInfo *t) { @@ -238,6 +257,7 @@ void setTransformViewMatrices(TransInfo *t) } calculateCenter2D(t); + calculateCenterLocal(t, t->center_global); } void setTransformViewAspect(TransInfo *t, float r_aspect[3]) @@ -560,6 +580,10 @@ void removeAspectRatio(TransInfo *t, float vec[2]) static void viewRedrawForce(const bContext *C, TransInfo *t) { if (t->options & CTX_GPENCIL_STROKES) { + bGPdata *gpd = ED_gpencil_data_get_active(C); + if (gpd) { + DEG_id_tag_update(&gpd->id, OB_RECALC_DATA); + } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else if (t->spacetype == SPACE_VIEW3D) { @@ -612,8 +636,12 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) else { // XXX how to deal with lock? SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; - if (sima->lock) WM_event_add_notifier(C, NC_GEOM | ND_DATA, t->obedit->data); - else ED_area_tag_redraw(t->sa); + if (sima->lock) { + WM_event_add_notifier(C, NC_GEOM | ND_DATA, OBEDIT_FROM_VIEW_LAYER(t->view_layer)->data); + } + else { + ED_area_tag_redraw(t->sa); + } } } else if (t->spacetype == SPACE_CLIP) { @@ -637,7 +665,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) static void viewRedrawPost(bContext *C, TransInfo *t) { - ED_area_headerprint(t->sa, NULL); + ED_area_status_text(t->sa, NULL); if (t->spacetype == SPACE_VIEW3D) { /* if autokeying is enabled, send notifiers that keyframes were added */ @@ -798,6 +826,84 @@ enum { TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27, }; +static bool transform_modal_item_poll(const wmOperator *op, int value) +{ + const TransInfo *t = op->customdata; + switch (value) { + case TFM_MODAL_PROPSIZE: + case TFM_MODAL_PROPSIZE_UP: + case TFM_MODAL_PROPSIZE_DOWN: + { + if ((t->flag & T_PROP_EDIT) == 0) { + return false; + } + break; + } + case TFM_MODAL_ADD_SNAP: + case TFM_MODAL_REMOVE_SNAP: + { + if (t->spacetype != SPACE_VIEW3D) { + return false; + } + else if (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) { + return false; + } + else if (!validSnap(t)) { + return false; + } + break; + } + case TFM_MODAL_AXIS_X: + case TFM_MODAL_AXIS_Y: + case TFM_MODAL_AXIS_Z: + case TFM_MODAL_PLANE_X: + case TFM_MODAL_PLANE_Y: + case TFM_MODAL_PLANE_Z: + { + if (t->flag & T_NO_CONSTRAINT) { + return false; + } + if (!ELEM(value, TFM_MODAL_AXIS_X, TFM_MODAL_AXIS_Y)) { + if (t->flag & T_2D_EDIT) { + return false; + } + } + break; + } + case TFM_MODAL_CONS_OFF: + { + if ((t->con.mode & CON_APPLY) == 0) { + return false; + } + break; + } + case TFM_MODAL_EDGESLIDE_UP: + case TFM_MODAL_EDGESLIDE_DOWN: + { + if (t->mode != TFM_EDGE_SLIDE) { + return false; + } + break; + } + case TFM_MODAL_INSERTOFS_TOGGLE_DIR: + { + if (t->spacetype != SPACE_NODE) { + return false; + } + break; + } + case TFM_MODAL_AUTOIK_LEN_INC: + case TFM_MODAL_AUTOIK_LEN_DEC: + { + if ((t->flag & T_AUTOIK) == 0) { + return false; + } + break; + } + } + return true; +} + /* called in transform_ops.c, on each regeneration of keymaps */ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) { @@ -826,7 +932,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) {TFM_MODAL_EDGESLIDE_DOWN, "EDGESLIDE_PREV_NEXT", 0, "Select previous Edge Slide Edge", ""}, {TFM_MODAL_PROPSIZE, "PROPORTIONAL_SIZE", 0, "Adjust Proportional Influence", ""}, {TFM_MODAL_INSERTOFS_TOGGLE_DIR, "INSERTOFS_TOGGLE_DIR", 0, "Toggle Direction for Node Auto-offset", ""}, - {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Translate", ""}, + {TFM_MODAL_TRANSLATE, "TRANSLATE", 0, "Move", ""}, {TFM_MODAL_ROTATE, "ROTATE", 0, "Rotate", ""}, {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""}, {0, NULL, 0, NULL, NULL} @@ -834,63 +940,8 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Transform Modal Map"); - /* this function is called for each spacetype, only needs to add map once */ - if (keymap && keymap->modal_items) return NULL; - keymap = WM_modalkeymap_add(keyconf, "Transform Modal Map", modal_items); - - /* items for modal map */ - WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, TFM_MODAL_CONFIRM); - WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, TFM_MODAL_CANCEL); - WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_CANCEL); - - WM_modalkeymap_add_item(keymap, XKEY, KM_PRESS, 0, 0, TFM_MODAL_AXIS_X); - WM_modalkeymap_add_item(keymap, YKEY, KM_PRESS, 0, 0, TFM_MODAL_AXIS_Y); - WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, TFM_MODAL_AXIS_Z); - - WM_modalkeymap_add_item(keymap, XKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PLANE_X); - WM_modalkeymap_add_item(keymap, YKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PLANE_Y); - WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PLANE_Z); - - WM_modalkeymap_add_item(keymap, CKEY, KM_PRESS, 0, 0, TFM_MODAL_CONS_OFF); - - WM_modalkeymap_add_item(keymap, GKEY, KM_PRESS, 0, 0, TFM_MODAL_TRANSLATE); - WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, TFM_MODAL_ROTATE); - WM_modalkeymap_add_item(keymap, SKEY, KM_PRESS, 0, 0, TFM_MODAL_RESIZE); - - WM_modalkeymap_add_item(keymap, TABKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_SNAP_TOGGLE); - - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_SNAP_INV_ON); - WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_SNAP_INV_OFF); - - WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_PRESS, KM_ANY, 0, TFM_MODAL_SNAP_INV_ON); - WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_RELEASE, KM_ANY, 0, TFM_MODAL_SNAP_INV_OFF); - - WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, 0, 0, TFM_MODAL_ADD_SNAP); - WM_modalkeymap_add_item(keymap, AKEY, KM_PRESS, KM_ALT, 0, TFM_MODAL_REMOVE_SNAP); - - WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_UP); - WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, 0, 0, TFM_MODAL_PROPSIZE_DOWN); - WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP); - WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 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, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_PROPSIZE_UP); - WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 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); - - WM_modalkeymap_add_item(keymap, PAGEUPKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC); - WM_modalkeymap_add_item(keymap, PAGEDOWNKEY, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC); - WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_INC); - WM_modalkeymap_add_item(keymap, WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0, TFM_MODAL_AUTOIK_LEN_DEC); - - /* node editor only */ - WM_modalkeymap_add_item(keymap, TKEY, KM_PRESS, 0, 0, TFM_MODAL_INSERTOFS_TOGGLE_DIR); + keymap->poll_modal_item = transform_modal_item_poll; return keymap; } @@ -1032,7 +1083,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } else { - if (t->obedit && t->obedit->type == OB_MESH) { + if (t->obedit_type == OB_MESH) { if ((t->mode == TFM_TRANSLATION) && (t->spacetype == SPACE_VIEW3D)) { restoreTransObjects(t); resetTransModal(t); @@ -1042,11 +1093,13 @@ int transformEvent(TransInfo *t, const wmEvent *event) initEdgeSlide(t); /* if that fails, do vertex slide */ if (t->state == TRANS_CANCEL) { + resetTransModal(t); t->state = TRANS_STARTING; initVertSlide(t); } /* vert slide can fail on unconnected vertices (rare but possible) */ if (t->state == TRANS_CANCEL) { + resetTransModal(t); t->mode = TFM_TRANSLATION; t->state = TRANS_STARTING; restoreTransObjects(t); @@ -1450,6 +1503,18 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } break; + case NKEY: + if (ELEM(t->mode, TFM_ROTATION)) { + if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { + restoreTransObjects(t); + resetTransModal(t); + resetTransRestrictions(t); + initNormalRotation(t); + t->redraw = TREDRAW_HARD; + handled = true; + } + } + break; default: break; } @@ -1519,6 +1584,12 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } + if (t->redraw && + !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) + { + WM_window_status_area_tag_redraw(CTX_wm_window(t->context)); + } + if (handled || t->redraw) { return 0; } @@ -1532,6 +1603,8 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa TransInfo *t = MEM_callocN(sizeof(TransInfo), "TransInfo data"); bool success; + t->context = C; + t->state = TRANS_RUNNING; /* avoid calculating PET */ @@ -1548,7 +1621,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa t->around = centerMode; // override userdefined mode - if (t->total == 0) { + if (t->data_len_all == 0) { success = false; } else { @@ -1583,8 +1656,16 @@ typedef enum { LEFT, RIGHT } ArrowDirection; + +#define POS_INDEX 0 +/* NOTE: this --^ is a bit hackish, but simplifies GPUVertFormat usage among functions + * private to this file - merwin + */ + static void drawArrow(ArrowDirection d, short offset, short length, short size) { + immBegin(GPU_PRIM_LINES, 6); + switch (d) { case LEFT: offset = -offset; @@ -1592,14 +1673,12 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size) size = -size; ATTR_FALLTHROUGH; case RIGHT: - glBegin(GL_LINES); - glVertex2s(offset, 0); - glVertex2s(offset + length, 0); - glVertex2s(offset + length, 0); - glVertex2s(offset + length - size, -size); - glVertex2s(offset + length, 0); - glVertex2s(offset + length - size, size); - glEnd(); + immVertex2f(POS_INDEX, offset, 0); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length - size, -size); + immVertex2f(POS_INDEX, offset + length, 0); + immVertex2f(POS_INDEX, offset + length - size, size); break; case DOWN: @@ -1608,45 +1687,45 @@ static void drawArrow(ArrowDirection d, short offset, short length, short size) size = -size; ATTR_FALLTHROUGH; case UP: - glBegin(GL_LINES); - glVertex2s(0, offset); - glVertex2s(0, offset + length); - glVertex2s(0, offset + length); - glVertex2s(-size, offset + length - size); - glVertex2s(0, offset + length); - glVertex2s(size, offset + length - size); - glEnd(); + immVertex2f(POS_INDEX, 0, offset); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, -size, offset + length - size); + immVertex2f(POS_INDEX, 0, offset + length); + immVertex2f(POS_INDEX, size, offset + length - size); break; } + + immEnd(); } static void drawArrowHead(ArrowDirection d, short size) { + immBegin(GPU_PRIM_LINES, 4); + switch (d) { case LEFT: size = -size; ATTR_FALLTHROUGH; case RIGHT: - glBegin(GL_LINES); - glVertex2s(0, 0); - glVertex2s(-size, -size); - glVertex2s(0, 0); - glVertex2s(-size, size); - glEnd(); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, -size); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, size); break; case DOWN: size = -size; ATTR_FALLTHROUGH; case UP: - glBegin(GL_LINES); - glVertex2s(0, 0); - glVertex2s(-size, -size); - glVertex2s(0, 0); - glVertex2s(size, -size); - glEnd(); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, -size, -size); + immVertex2f(POS_INDEX, 0, 0); + immVertex2f(POS_INDEX, size, -size); break; } + + immEnd(); } static void drawArc(float size, float angle_start, float angle_end, int segments) @@ -1655,14 +1734,14 @@ static void drawArc(float size, float angle_start, float angle_end, int segments float angle; int a; - glBegin(GL_LINE_STRIP); + immBegin(GPU_PRIM_LINE_STRIP, segments + 1); for (angle = angle_start, a = 0; a < segments; angle += delta, a++) { - glVertex2f(cosf(angle) * size, sinf(angle) * size); + immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size); } - glVertex2f(cosf(angle_end) * size, sinf(angle_end) * size); + immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size); - glEnd(); + immEnd(); } static bool helpline_poll(bContext *C) @@ -1674,92 +1753,173 @@ static bool helpline_poll(bContext *C) return 0; } -static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) +static void drawHelpline(bContext *C, int x, int y, void *customdata) { TransInfo *t = (TransInfo *)customdata; - if (t->helpline != HLP_NONE && !(t->flag & T_USES_MANIPULATOR)) { + if (t->helpline != HLP_NONE) { float cent[2]; - int mval[2]; + float mval[3] = { + x, + y, + 0.0f, + }; + float tmval[2] = { + (float)t->mval[0], + (float)t->mval[1], + }; + + /* grease pencil only can edit one object at time because GP has + * multiframe edition that replaces multiobject edition. + * If multiobject edition is added, maybe this code will need + * an update + */ + if ((t->flag & T_POINTS) && (t->options & CTX_GPENCIL_STROKES) && + (t->around != V3D_AROUND_ACTIVE)) + { + Object *ob = CTX_data_active_object(C); + if ((ob) && (ob->type == OB_GPENCIL)) { + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + float vecrot[3]; + copy_v3_v3(vecrot, t->center_global); + mul_m4_v3(ob->obmat, vecrot); + projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO); + } + } + else { + /* normally, never must be used */ + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + } + } + else { + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + } + + /* Offset the values for the area region. */ + const float offset[2] = { + t->ar->winrct.xmin, + t->ar->winrct.ymin, + }; + + for (int i = 0; i < 2; i++) { + cent[i] += offset[i]; + tmval[i] += offset[i]; + } + + GPU_matrix_push(); + + /* Dashed lines first. */ + if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { + const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */ + BLI_assert(shdr_pos == POS_INDEX); + + GPU_line_width(1.0f); + + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - mval[0] = x; - mval[1] = y; + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniformThemeColor(TH_VIEW_OVERLAY); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); - projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + immBegin(GPU_PRIM_LINES, 2); + immVertex2fv(POS_INDEX, cent); + immVertex2f(POS_INDEX, tmval[0], tmval[1]); + immEnd(); - glPushMatrix(); + immUnbindProgram(); + } + + /* And now, solid lines. */ + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + UNUSED_VARS_NDEBUG(pos); /* silence warning */ + BLI_assert(pos == POS_INDEX); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); switch (t->helpline) { case HLP_SPRING: - UI_ThemeColor(TH_VIEW_OVERLAY); + immUniformThemeColor(TH_VIEW_OVERLAY); - setlinestyle(3); - glLineWidth(1); - glBegin(GL_LINES); - glVertex2iv(t->mval); - glVertex2fv(cent); - glEnd(); + GPU_matrix_translate_3fv(mval); + GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); - glTranslate2iv(mval); - glRotatef(-RAD2DEGF(atan2f(cent[0] - t->mval[0], cent[1] - t->mval[1])), 0, 0, 1); - - setlinestyle(0); - glLineWidth(3.0); + GPU_line_width(3.0f); drawArrow(UP, 5, 10, 5); drawArrow(DOWN, 5, 10, 5); break; case HLP_HARROW: - UI_ThemeColor(TH_VIEW_OVERLAY); - - glTranslate2iv(mval); + immUniformThemeColor(TH_VIEW_OVERLAY); + GPU_matrix_translate_3fv(mval); - glLineWidth(3.0); + GPU_line_width(3.0f); drawArrow(RIGHT, 5, 10, 5); drawArrow(LEFT, 5, 10, 5); break; case HLP_VARROW: - UI_ThemeColor(TH_VIEW_OVERLAY); + immUniformThemeColor(TH_VIEW_OVERLAY); - glTranslate2iv(mval); + GPU_matrix_translate_3fv(mval); - glLineWidth(3.0); + GPU_line_width(3.0f); drawArrow(UP, 5, 10, 5); drawArrow(DOWN, 5, 10, 5); break; + case HLP_CARROW: + { + /* Draw arrow based on direction defined by custom-points. */ + immUniformThemeColor(TH_VIEW_OVERLAY); + + GPU_matrix_translate_3fv(mval); + + GPU_line_width(3.0f); + + const int *data = t->mouse.data; + const float dx = data[2] - data[0], dy = data[3] - data[1]; + const float angle = -atan2f(dx, dy); + + GPU_matrix_push(); + + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + + drawArrow(UP, 5, 10, 5); + drawArrow(DOWN, 5, 10, 5); + + GPU_matrix_pop(); + break; + } case HLP_ANGLE: { - float dx = t->mval[0] - cent[0], dy = t->mval[1] - cent[1]; + float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1]; float angle = atan2f(dy, dx); float dist = hypotf(dx, dy); float delta_angle = min_ff(15.0f / dist, (float)M_PI / 4.0f); float spacing_angle = min_ff(5.0f / dist, (float)M_PI / 12.0f); - UI_ThemeColor(TH_VIEW_OVERLAY); - setlinestyle(3); - glLineWidth(1); - glBegin(GL_LINES); - glVertex2iv(t->mval); - glVertex2fv(cent); - glEnd(); + immUniformThemeColor(TH_VIEW_OVERLAY); - glTranslatef(cent[0] - t->mval[0] + mval[0], cent[1] - t->mval[1] + mval[1], 0); + GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0); - setlinestyle(0); - glLineWidth(3.0); + GPU_line_width(3.0f); drawArc(dist, angle - delta_angle, angle - spacing_angle, 10); drawArc(dist, angle + spacing_angle, angle + delta_angle, 10); - glPushMatrix(); + GPU_matrix_push(); - glTranslatef(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); - glRotatef(RAD2DEGF(angle - delta_angle), 0, 0, 1); + GPU_matrix_translate_3f(cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z'); drawArrowHead(DOWN, 5); - glPopMatrix(); + GPU_matrix_pop(); - glTranslatef(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); - glRotatef(RAD2DEGF(angle + delta_angle), 0, 0, 1); + GPU_matrix_translate_3f(cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z'); drawArrowHead(UP, 5); break; @@ -1769,18 +1929,18 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) unsigned char col[3], col2[3]; UI_GetThemeColor3ubv(TH_GRID, col); - glTranslate2iv(mval); + GPU_matrix_translate_3fv(mval); - glLineWidth(3.0); + GPU_line_width(3.0f); UI_make_axis_color(col, col2, 'X'); - glColor3ubv((GLubyte *)col2); + immUniformColor3ubv(col2); drawArrow(RIGHT, 5, 10, 5); drawArrow(LEFT, 5, 10, 5); UI_make_axis_color(col, col2, 'Y'); - glColor3ubv((GLubyte *)col2); + immUniformColor3ubv(col2); drawArrow(UP, 5, 10, 5); drawArrow(DOWN, 5, 10, 5); @@ -1788,7 +1948,8 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata) } } - glPopMatrix(); + immUnbindProgram(); + GPU_matrix_pop(); } } @@ -1796,7 +1957,7 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi { TransInfo *t = arg; - glLineWidth(1.0); + GPU_line_width(1.0f); drawConstraint(t); drawPropCircle(C, t); @@ -1805,6 +1966,9 @@ static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), voi /* edge slide, vert slide */ drawEdgeSlide(t); drawVertSlide(t); + + /* Rotation */ + drawDial3d(t); } /* just draw a little warning message in the top-right corner of the viewport to warn that autokeying is enabled */ @@ -1817,7 +1981,8 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) ED_region_visible_rect(ar, &rect); - BLF_width_and_height_default(printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); + const int font_id = BLF_default(); + BLF_width_and_height(font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); xco = (rect.xmax - U.widget_unit) - (int)printable_size[0]; yco = (rect.ymax - U.widget_unit); @@ -1825,7 +1990,9 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) /* 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); + unsigned char color[3]; + UI_GetThemeColorShade3ubv(TH_TEXT_HI, -50, color); + BLF_color3ubv(font_id, color); #ifdef WITH_INTERNATIONAL BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); #else @@ -1833,22 +2000,23 @@ static void drawAutoKeyWarning(TransInfo *UNUSED(t), ARegion *ar) #endif /* autokey recording icon... */ - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); xco -= U.widget_unit; yco -= (int)printable_size[1] / 2; UI_icon_draw(xco, yco, ICON_REC); - glDisable(GL_BLEND); + GPU_blend(false); } static void drawTransformPixel(const struct bContext *UNUSED(C), ARegion *ar, void *arg) { TransInfo *t = arg; Scene *scene = t->scene; - Object *ob = OBACT; + ViewLayer *view_layer = t->view_layer; + Object *ob = OBACT(view_layer); /* draw autokeyframing hint in the corner * - only draw if enabled (advanced users may be distracted/annoyed), @@ -1923,7 +2091,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) ts->proportional_fcurve = proportional; else if (t->spacetype == SPACE_ACTION) ts->proportional_action = proportional; - else if (t->obedit) + else if (t->obedit_type != -1) ts->proportional = proportional; else if (t->options & CTX_MASK) ts->proportional_mask = (proportional != PROP_EDIT_OFF); @@ -1955,9 +2123,10 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) && !RNA_property_is_set(op->ptr, prop)) { - View3D *v3d = t->view; - - v3d->twmode = t->current_orientation; + t->scene->orientation_type = t->current_orientation; + BLI_assert(((t->scene->orientation_index_custom == -1) && (t->custom_orientation == NULL)) || + (BKE_scene_transform_orientation_get_index( + t->scene, t->custom_orientation) == t->scene->orientation_index_custom)); } } } @@ -1972,19 +2141,33 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) RNA_property_float_set_array(op->ptr, prop, t->axis); } + if ((prop = RNA_struct_find_property(op->ptr, "axis_ortho"))) { + RNA_property_float_set_array(op->ptr, prop, t->axis_ortho); + } + if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) { RNA_property_boolean_set(op->ptr, prop, (t->flag & T_MIRROR) != 0); } if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { - /* constraint orientation can be global, event if user selects something else - * so use the orientation in the constraint if set - * */ - if (t->con.mode & CON_APPLY) { - RNA_enum_set(op->ptr, "constraint_orientation", t->con.orientation); + /* constraint orientation can be global, even if user selects something else + * so use the orientation in the constraint if set */ + short orientation = (t->con.mode & CON_APPLY) ? t->con.orientation : t->current_orientation; + + if (orientation == V3D_MANIP_CUSTOM) { + const int orientation_index_custom = BKE_scene_transform_orientation_get_index( + t->scene, t->custom_orientation); + + /* Maybe we need a t->con.custom_orientation? Seems like it would always match t->custom_orientation. */ + orientation = V3D_MANIP_CUSTOM + orientation_index_custom; + BLI_assert(orientation >= V3D_MANIP_CUSTOM); } - else { - RNA_enum_set(op->ptr, "constraint_orientation", t->current_orientation); + + RNA_float_set_array(op->ptr, "constraint_matrix", &t->spacemtx[0][0]); + + /* Use 'constraint_matrix' instead. */ + if (orientation != V3D_MANIP_CUSTOM_MATRIX) { + RNA_enum_set(op->ptr, "constraint_orientation", orientation); } if (t->con.mode & CON_APPLY) { @@ -2008,19 +2191,26 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) { const char *prop_id = NULL; + bool prop_state = true; if (t->mode == TFM_SHRINKFATTEN) { prop_id = "use_even_offset"; + prop_state = false; } if (prop_id && (prop = RNA_struct_find_property(op->ptr, prop_id))) { - - RNA_property_boolean_set(op->ptr, prop, (t->flag & T_ALT_TRANSFORM) != 0); + RNA_property_boolean_set(op->ptr, prop, ((t->flag & T_ALT_TRANSFORM) != 0) == prop_state); } } if ((prop = RNA_struct_find_property(op->ptr, "correct_uv"))) { RNA_property_boolean_set(op->ptr, prop, (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) != 0); } + + if (t->mode == TFM_SHEAR) { + prop = RNA_struct_find_property(op->ptr, "shear_axis"); + t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop)); + RNA_property_enum_set(op->ptr, prop, POINTER_AS_INT(t->custom.mode.data)); + } } /** @@ -2039,6 +2229,12 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->state = TRANS_STARTING; + if ((prop = RNA_struct_find_property(op->ptr, "cursor_transform")) && RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + options |= CTX_CURSOR; + } + } + if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) { if (RNA_property_boolean_get(op->ptr, prop)) { options |= CTX_TEXTURE; @@ -2059,7 +2255,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->launch_event = event ? WM_userdef_event_type_from_keymap_type(event->type) : -1; // XXX Remove this when wm_operator_call_internal doesn't use window->eventstate (which can have type = 0) - // For manipulator only, so assume LEFTMOUSE + // For gizmo only, so assume LEFTMOUSE if (t->launch_event == 0) { t->launch_event = LEFTMOUSE; } @@ -2073,36 +2269,54 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW); t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), + SPACE_TYPE_ANY, RGN_TYPE_ANY, + helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_IMAGE) { t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), + SPACE_TYPE_ANY, RGN_TYPE_ANY, + helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_CLIP) { t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), + SPACE_TYPE_ANY, RGN_TYPE_ANY, + helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_NODE) { /*t->draw_handle_apply = ED_region_draw_cb_activate(t->ar->type, drawTransformApply, t, REGION_DRAW_PRE_VIEW);*/ t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), + SPACE_TYPE_ANY, RGN_TYPE_ANY, + helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_IPO) { t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), + SPACE_TYPE_ANY, RGN_TYPE_ANY, + helpline_poll, drawHelpline, t); } else if (t->spacetype == SPACE_ACTION) { t->draw_handle_view = ED_region_draw_cb_activate(t->ar->type, drawTransformView, t, REGION_DRAW_POST_VIEW); //t->draw_handle_pixel = ED_region_draw_cb_activate(t->ar->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), helpline_poll, drawHelpline, t); + t->draw_handle_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), + SPACE_TYPE_ANY, RGN_TYPE_ANY, + helpline_poll, drawHelpline, t); } createTransData(C, t); // make TransData structs from selection - if (t->total == 0) { + if (t->data_len_all == 0) { postTrans(C, t); return 0; } @@ -2111,10 +2325,10 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* keymap for shortcut header prints */ t->keymap = WM_keymap_active(CTX_wm_manager(C), op->type->modalkeymap); - /* Stupid code to have Ctrl-Click on manipulator work ok + /* Stupid code to have Ctrl-Click on gizmo work ok * * do this only for translation/rotation/resize due to only this - * moded are available from manipulator and doing such check could + * moded are available from gizmo and doing such check could * lead to keymap conflicts for other modes (see #31584) */ if (ELEM(mode, TFM_TRANSLATION, TFM_ROTATION, TFM_RESIZE)) { @@ -2147,6 +2361,68 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve calculatePropRatio(t); calculateCenter(t); + /* Overwrite initial values if operator supplied a non-null vector. + * + * Run before init functions so 'values_modal_offset' can be applied on mouse input. + */ + BLI_assert(is_zero_v4(t->values_modal_offset)); + if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { + float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ + + if (RNA_property_array_check(prop)) { + RNA_float_get_array(op->ptr, "value", values); + } + else { + values[0] = RNA_float_get(op->ptr, "value"); + } + + copy_v4_v4(t->values, values); + + if (t->flag & T_MODAL) { + copy_v4_v4(t->values_modal_offset, values); + t->redraw = TREDRAW_HARD; + } + else { + copy_v4_v4(t->auto_values, values); + t->flag |= T_AUTOVALUES; + } + } + + /* Transformation axis from operator */ + if ((prop = RNA_struct_find_property(op->ptr, "axis")) && RNA_property_is_set(op->ptr, prop)) { + RNA_property_float_get_array(op->ptr, prop, t->axis); + normalize_v3(t->axis); + copy_v3_v3(t->axis_orig, t->axis); + } + + if ((prop = RNA_struct_find_property(op->ptr, "axis_ortho")) && RNA_property_is_set(op->ptr, prop)) { + RNA_property_float_get_array(op->ptr, prop, t->axis_ortho); + normalize_v3(t->axis_ortho); + } + + /* Constraint init from operator */ + if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) && RNA_property_is_set(op->ptr, prop)) { + bool constraint_axis[3]; + + RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); + + if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { + t->con.mode |= CON_APPLY; + + if (constraint_axis[0]) { + t->con.mode |= CON_AXIS0; + } + if (constraint_axis[1]) { + t->con.mode |= CON_AXIS1; + } + if (constraint_axis[2]) { + t->con.mode |= CON_AXIS2; + } + + setUserConstraint(t, t->current_orientation, t->con.mode, "%s"); + } + } + if (event) { /* Initialize accurate transform to settings requested by keymap. */ bool use_accurate = false; @@ -2175,6 +2451,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initToSphere(t); break; case TFM_SHEAR: + prop = RNA_struct_find_property(op->ptr, "shear_axis"); + t->custom.mode.data = POINTER_FROM_INT(RNA_property_enum_get(op->ptr, prop)); initShear(t); break; case TFM_BEND: @@ -2206,7 +2484,9 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve break; case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */ - bArmature *arm = t->poseobj->data; + /* Note: we have to pick one, use the active object. */ + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t); + bArmature *arm = tc->poseobj->data; if (arm->drawtype == ARM_ENVELOPE) { initBoneEnvelope(t); t->mode = TFM_BONE_ENVELOPE_DIST; @@ -2286,6 +2566,9 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve case TFM_SEQ_SLIDE: initSeqSlide(t); break; + case TFM_NORMAL_ROTATION: + initNormalRotation(t); + break; } if (t->state == TRANS_CANCEL) { @@ -2293,55 +2576,39 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve return 0; } - /* Transformation axis from operator */ - if ((prop = RNA_struct_find_property(op->ptr, "axis")) && RNA_property_is_set(op->ptr, prop)) { - RNA_property_float_get_array(op->ptr, prop, t->axis); - normalize_v3(t->axis); - copy_v3_v3(t->axis_orig, t->axis); - } - - /* Constraint init from operator */ - if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) && RNA_property_is_set(op->ptr, prop)) { - bool constraint_axis[3]; + if ((prop = RNA_struct_find_property(op->ptr, "preserve_clnor"))) { + if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { - RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) { + BMEditMesh *em = NULL;// BKE_editmesh_from_object(t->obedit); + bool do_skip = false; - if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { - t->con.mode |= CON_APPLY; + /* Currently only used for two of three most frequent transform ops, can include more ops. + * Note that scaling cannot be included here, non-uniform scaling will affect normals. */ + if (ELEM(t->mode, TFM_TRANSLATION, TFM_ROTATION)) { + if (em->bm->totvertsel == em->bm->totvert) { + /* No need to invalidate if whole mesh is selected. */ + do_skip = true; + } + } - if (constraint_axis[0]) { - t->con.mode |= CON_AXIS0; - } - if (constraint_axis[1]) { - t->con.mode |= CON_AXIS1; - } - if (constraint_axis[2]) { - t->con.mode |= CON_AXIS2; + if (t->flag & T_MODAL) { + RNA_property_boolean_set(op->ptr, prop, false); + } + else if (!do_skip) { + const bool preserve_clnor = RNA_property_boolean_get(op->ptr, prop); + if (preserve_clnor) { + BKE_editmesh_lnorspace_update(em); + t->flag |= T_CLNOR_REBUILD; + } + BM_lnorspace_invalidate(em->bm, true); + } + } } - - setUserConstraint(t, t->current_orientation, t->con.mode, "%s"); } } - /* overwrite initial values if operator supplied a non-null vector - * - * keep last so we can apply the constraints space. - */ - if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { - float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ - - if (RNA_property_array_check(prop)) { - RNA_float_get_array(op->ptr, "value", values); - } - else { - values[0] = RNA_float_get(op->ptr, "value"); - } - - copy_v4_v4(t->values, values); - copy_v4_v4(t->auto_values, values); - t->flag |= T_AUTOVALUES; - } - t->context = NULL; return 1; @@ -2402,6 +2669,12 @@ int transformEnd(bContext *C, TransInfo *t) restoreTransObjects(t); // calls recalcData() } else { + if (t->flag & T_CLNOR_REBUILD) { + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BM_lnorspace_rebuild(em->bm, true); + } + } exit_code = OPERATOR_FINISHED; } @@ -2604,7 +2877,7 @@ static void constraintTransLim(TransInfo *t, TransData *td) } /* get constraint targets if needed */ - BKE_constraint_targets_for_solving_get(con, &cob, &targets, ctime); + BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime); /* do constraint */ cti->evaluate_constraint(con, &cob, &targets); @@ -2811,6 +3084,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td) * \{ */ struct BendCustomData { + /* All values are in global space. */ float warp_sta[3]; float warp_end[3]; @@ -2838,8 +3112,8 @@ static void initBend(TransInfo *t) t->idx_max = 1; t->num.idx_max = 1; t->snap[0] = 0.0f; - t->snap[1] = DEG2RAD(5.0); - t->snap[2] = DEG2RAD(1.0); + t->snap[1] = SNAP_INCREMENTAL_ANGLE; + t->snap[2] = t->snap[1] * 0.2; copy_v3_fl(t->num.val_inc, t->snap[1]); t->num.unit_sys = t->scene->unit.system; @@ -2851,23 +3125,19 @@ static void initBend(TransInfo *t) //copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view)); if ((t->flag & T_OVERRIDE_CENTER) == 0) { - calculateCenterCursor(t, t->center); + calculateCenterCursor(t, t->center_global); } - calculateCenterGlobal(t, t->center, t->center_global); + calculateCenterLocal(t, t->center_global); t->val = 0.0f; data = MEM_callocN(sizeof(*data), __func__); - curs = ED_view3d_cursor3d_get(t->scene, t->view); + curs = ED_view3d_cursor3d_get(t->scene, t->view)->location; copy_v3_v3(data->warp_sta, curs); ED_view3d_win_to_3d(t->sa->spacedata.first, t->ar, curs, mval_fl, data->warp_end); copy_v3_v3(data->warp_nor, t->viewinv[2]); - if (t->flag & T_EDIT) { - sub_v3_v3(data->warp_sta, t->obedit->obmat[3]); - sub_v3_v3(data->warp_end, t->obedit->obmat[3]); - } normalize_v3(data->warp_nor); /* tangent */ @@ -2894,10 +3164,9 @@ static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event) static void Bend(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float vec[3]; - float pivot[3]; - float warp_end_radius[3]; + float pivot_global[3]; + float warp_end_radius_global[3]; int i; char str[UI_MAX_DRAW_STR]; const struct BendCustomData *data = t->custom.mode.data; @@ -2916,7 +3185,7 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) #else /* hrmf, snapping radius is using 'angle' steps, need to convert to something else * this isnt essential but nicer to give reasonable snapping values for radius */ - if (t->tsnap.mode == SCE_SNAP_MODE_INCREMENT) { + if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) { const float radius_snap = 0.1f; const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap; values.scale *= snap_hack; @@ -2952,69 +3221,92 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) values.scale *= data->warp_init_dist; /* calc 'data->warp_end' from 'data->warp_end_init' */ - copy_v3_v3(warp_end_radius, data->warp_end); - dist_ensure_v3_v3fl(warp_end_radius, data->warp_sta, values.scale); + copy_v3_v3(warp_end_radius_global, data->warp_end); + dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale); /* done */ /* calculate pivot */ - copy_v3_v3(pivot, data->warp_sta); + copy_v3_v3(pivot_global, data->warp_sta); if (values.angle > 0.0f) { - madd_v3_v3fl(pivot, data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle)); + madd_v3_v3fl(pivot_global, data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle)); } else { - madd_v3_v3fl(pivot, data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle)); + madd_v3_v3fl(pivot_global, data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle)); } - for (i = 0; i < t->total; i++, td++) { - float mat[3][3]; - float delta[3]; - float fac, fac_scaled; + /* TODO(campbell): xform, compensate object center. */ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; + float warp_sta_local[3]; + float warp_end_local[3]; + float warp_end_radius_local[3]; + float pivot_local[3]; - if (UNLIKELY(values.angle == 0.0f)) { - copy_v3_v3(td->loc, td->iloc); - continue; + if (tc->use_local_mat) { + sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]); + sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]); + sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]); + sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]); + } + else { + copy_v3_v3(warp_sta_local, data->warp_sta); + copy_v3_v3(warp_end_local, data->warp_end); + copy_v3_v3(warp_end_radius_local, warp_end_radius_global); + copy_v3_v3(pivot_local, pivot_global); } - copy_v3_v3(vec, td->iloc); - mul_m3_v3(td->mtx, vec); + for (i = 0; i < tc->data_len; i++, td++) { + float mat[3][3]; + float delta[3]; + float fac, fac_scaled; - fac = line_point_factor_v3(vec, data->warp_sta, warp_end_radius); - if (is_clamp) { - CLAMP(fac, 0.0f, 1.0f); - } + if (td->flag & TD_NOACTION) + break; - fac_scaled = fac * td->factor; - axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled); - interp_v3_v3v3(delta, data->warp_sta, warp_end_radius, fac_scaled); - sub_v3_v3(delta, data->warp_sta); + if (td->flag & TD_SKIP) + continue; - /* delta is subtracted, rotation adds back this offset */ - sub_v3_v3(vec, delta); + if (UNLIKELY(values.angle == 0.0f)) { + copy_v3_v3(td->loc, td->iloc); + continue; + } - sub_v3_v3(vec, pivot); - mul_m3_v3(mat, vec); - add_v3_v3(vec, pivot); + copy_v3_v3(vec, td->iloc); + mul_m3_v3(td->mtx, vec); - mul_m3_v3(td->smtx, vec); + fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local); + if (is_clamp) { + CLAMP(fac, 0.0f, 1.0f); + } - /* rotation */ - if ((t->flag & T_POINTS) == 0) { - ElementRotation(t, td, mat, V3D_AROUND_LOCAL_ORIGINS); - } + fac_scaled = fac * td->factor; + axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled); + interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled); + sub_v3_v3(delta, warp_sta_local); + + /* delta is subtracted, rotation adds back this offset */ + sub_v3_v3(vec, delta); - /* location */ - copy_v3_v3(td->loc, vec); + sub_v3_v3(vec, pivot_local); + mul_m3_v3(mat, vec); + add_v3_v3(vec, pivot_local); + + mul_m3_v3(td->smtx, vec); + + /* rotation */ + if ((t->flag & T_POINTS) == 0) { + ElementRotation(t, tc, td, mat, V3D_AROUND_LOCAL_ORIGINS); + } + + /* location */ + copy_v3_v3(td->loc, vec); + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -3025,13 +3317,42 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) /** \name Transform Shear * \{ */ +static void initShear_mouseInputMode(TransInfo *t) +{ + float dir[3]; + + if (t->custom.mode.data == NULL) { + copy_v3_v3(dir, t->axis_ortho); + } + else { + cross_v3_v3v3(dir, t->axis_ortho, t->axis); + } + + mul_mat3_m4_v3(t->viewmat, dir); + if (normalize_v2(dir) == 0.0f) { + dir[0] = 1.0f; + } + setCustomPointsFromDirection(t, &t->mouse, dir); + + initMouseInputMode(t, &t->mouse, INPUT_CUSTOM_RATIO); +} + static void initShear(TransInfo *t) { t->mode = TFM_SHEAR; t->transform = applyShear; t->handleEvent = handleEventShear; - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); + if (is_zero_v3(t->axis)) { + negate_v3_v3(t->axis, t->viewinv[2]); + normalize_v3(t->axis); + } + if (is_zero_v3(t->axis_ortho)) { + copy_v3_v3(t->axis_ortho, t->viewinv[0]); + normalize_v3(t->axis_ortho); + } + + initShear_mouseInputMode(t); t->idx_max = 0; t->num.idx_max = 0; @@ -3053,25 +3374,24 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event) if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) { /* Use custom.mode.data pointer to signal Shear direction */ if (t->custom.mode.data == NULL) { - initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO); t->custom.mode.data = (void *)1; } else { - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); t->custom.mode.data = NULL; } + initShear_mouseInputMode(t); status = TREDRAW_HARD; } else if (event->type == XKEY && event->val == KM_PRESS) { - initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO); t->custom.mode.data = NULL; + initShear_mouseInputMode(t); status = TREDRAW_HARD; } else if (event->type == YKEY && event->val == KM_PRESS) { - initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_RATIO); t->custom.mode.data = (void *)1; + initShear_mouseInputMode(t); status = TREDRAW_HARD; } @@ -3082,17 +3402,13 @@ static eRedrawFlag handleEventShear(TransInfo *t, const wmEvent *event) static void applyShear(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float vec[3]; - float smat[3][3], tmat[3][3], totmat[3][3], persmat[3][3], persinv[3][3]; + float smat[3][3], tmat[3][3], totmat[3][3], axismat[3][3], axismat_inv[3][3]; float value; int i; char str[UI_MAX_DRAW_STR]; const bool is_local_center = transdata_check_local_center(t, t->around); - copy_m3_m4(persmat, t->viewmat); - invert_m3_m3(persinv, persmat); - value = t->values[0]; snapGridIncrement(t, &value); @@ -3122,51 +3438,56 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) else smat[0][1] = value; - mul_m3_m3m3(tmat, smat, persmat); - mul_m3_m3m3(totmat, persinv, tmat); + copy_v3_v3(axismat_inv[0], t->axis_ortho); + copy_v3_v3(axismat_inv[2], t->axis); + cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]); + invert_m3_m3(axismat, axismat_inv); - for (i = 0; i < t->total; i++, td++) { - const float *center, *co; + mul_m3_series(totmat, axismat_inv, smat, axismat); - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + const float *center, *co; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_NOACTION) + break; - if (t->obedit) { - float mat3[3][3]; - mul_m3_m3m3(mat3, totmat, td->mtx); - mul_m3_m3m3(tmat, td->smtx, mat3); - } - else { - copy_m3_m3(tmat, totmat); - } + if (td->flag & TD_SKIP) + continue; - if (is_local_center) { - center = td->center; - co = td->loc; - } - else { - center = t->center; - co = td->center; - } + if (t->flag & T_EDIT) { + mul_m3_series(tmat, td->smtx, totmat, td->mtx); + } + else { + copy_m3_m3(tmat, totmat); + } - sub_v3_v3v3(vec, co, center); + if (is_local_center) { + center = td->center; + co = td->loc; + } + else { + center = tc->center_local; + co = td->center; + } - mul_m3_v3(tmat, vec); + sub_v3_v3v3(vec, co, center); - add_v3_v3(vec, center); - sub_v3_v3(vec, co); + mul_m3_v3(tmat, vec); - mul_v3_fl(vec, td->factor); + add_v3_v3(vec, center); + sub_v3_v3(vec, co); - add_v3_v3v3(td->loc, td->iloc, vec); + mul_v3_fl(vec, td->factor); + + add_v3_v3v3(td->loc, td->iloc, vec); + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -3189,7 +3510,7 @@ static void initResize(TransInfo *t) t->num.val_flag[1] |= NUM_NULL_ONE; t->num.val_flag[2] |= NUM_NULL_ONE; t->num.flag |= NUM_AFFECT_ALL; - if (!t->obedit) { + if ((t->flag & T_EDIT) == 0) { t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO t->num.val_flag[0] |= NUM_NO_ZERO; @@ -3273,7 +3594,7 @@ static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3]) if (dot_v3v3(rmat[2], smat[2]) < 0.0f) size[2] = -size[2]; } -static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) +static void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]) { float tmat[3][3], smat[3][3], center[3]; float vec[3]; @@ -3287,7 +3608,7 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) } if (t->con.applySize) { - t->con.applySize(t, td, tmat); + t->con.applySize(t, tc, td, tmat); } /* local constraint shouldn't alter center */ @@ -3299,14 +3620,15 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) copy_v3_v3(center, td->center); } else { - copy_v3_v3(center, t->center); + copy_v3_v3(center, tc->center_local); } } else { - copy_v3_v3(center, t->center); + copy_v3_v3(center, tc->center_local); } - if (td->ext) { + /* Size checked needed since the 3D cursor only uses rotation fields. */ + if (td->ext && td->ext->size) { float fsize[3]; if (t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) { @@ -3360,7 +3682,25 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) else sub_v3_v3(vec, td->center); - mul_v3_fl(vec, td->factor); + /* grease pencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); + + /* scale stroke thickness */ + if (td->val) { + snapGridIncrement(t, t->values); + applyNumInput(&t->num, t->values); + + float ratio = t->values[0]; + *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff; + CLAMP_MIN(*td->val, 0.001f); + } + + } + else { + mul_v3_fl(vec, td->factor); + } if (t->flag & (T_OBJECT | T_POSE)) { mul_m3_v3(td->smtx, vec); @@ -3374,9 +3714,8 @@ static void ElementResize(TransInfo *t, TransData *td, float mat[3][3]) constraintTransLim(t, td); } -static void applyResize(TransInfo *t, const int mval[2]) +static void applyResize(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td; float mat[3][3]; int i; char str[UI_MAX_DRAW_STR]; @@ -3385,15 +3724,7 @@ static void applyResize(TransInfo *t, const int mval[2]) copy_v3_v3(t->values, t->auto_values); } else { - float ratio; - - /* for manipulator, center handle, the scaling can't be done relative to center */ - if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { - ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f; - } - else { - ratio = t->values[0]; - } + float ratio = t->values[0]; copy_v3_fl(t->values, ratio); @@ -3409,21 +3740,24 @@ static void applyResize(TransInfo *t, const int mval[2]) size_to_mat3(mat, t->values); if (t->con.applySize) { - t->con.applySize(t, NULL, mat); + t->con.applySize(t, NULL, NULL, mat); } - copy_m3_m3(t->mat, mat); // used in manipulator + copy_m3_m3(t->mat, mat); // used in gizmo headerResize(t, t->values, str); - for (i = 0, td = t->data; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - ElementResize(t, td, mat); + ElementResize(t, tc, td, mat); + } } /* evil hack - redo resize if cliping needed */ @@ -3431,23 +3765,27 @@ static void applyResize(TransInfo *t, const int mval[2]) size_to_mat3(mat, t->values); if (t->con.applySize) - t->con.applySize(t, NULL, mat); + t->con.applySize(t, NULL, NULL, mat); - for (i = 0, td = t->data; i < t->total; i++, td++) - ElementResize(t, td, mat); - /* In proportional edit it can happen that */ - /* vertices in the radius of the brush end */ - /* outside the clipping area */ - /* XXX HACK - dg */ - if (t->flag & T_PROP_EDIT_ALL) { - clipUVData(t); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) + ElementResize(t, tc, td, mat); + + /* In proportional edit it can happen that */ + /* vertices in the radius of the brush end */ + /* outside the clipping area */ + /* XXX HACK - dg */ + if (t->flag & T_PROP_EDIT_ALL) { + clipUVData(t); + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -3470,7 +3808,7 @@ static void initSkinResize(TransInfo *t) t->num.val_flag[1] |= NUM_NULL_ONE; t->num.val_flag[2] |= NUM_NULL_ONE; t->num.flag |= NUM_AFFECT_ALL; - if (!t->obedit) { + if ((t->flag & T_EDIT) == 0) { t->flag |= T_NO_ZERO; #ifdef USE_NUM_NO_ZERO t->num.val_flag[0] |= NUM_NO_ZERO; @@ -3494,7 +3832,6 @@ static void initSkinResize(TransInfo *t) static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td; float size[3], mat[3][3]; int i; char str[UI_MAX_DRAW_STR]; @@ -3519,36 +3856,39 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) headerResize(t, size, str); - for (i = 0, td = t->data; i < t->total; i++, td++) { - float tmat[3][3], smat[3][3]; - float fsize[3]; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float tmat[3][3], smat[3][3]; + float fsize[3]; - if (td->flag & TD_NOACTION) - break; + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (t->flag & T_EDIT) { - mul_m3_m3m3(smat, mat, td->mtx); - mul_m3_m3m3(tmat, td->smtx, smat); - } - else { - copy_m3_m3(tmat, mat); - } + if (t->flag & T_EDIT) { + mul_m3_m3m3(smat, mat, td->mtx); + mul_m3_m3m3(tmat, td->smtx, smat); + } + else { + copy_m3_m3(tmat, mat); + } - if (t->con.applySize) { - t->con.applySize(t, NULL, tmat); - } + if (t->con.applySize) { + t->con.applySize(t, NULL, NULL, tmat); + } - mat3_to_size(fsize, tmat); - td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); - td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); + mat3_to_size(fsize, tmat); + td->val[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); + td->val[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -3561,7 +3901,6 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) static void initToSphere(TransInfo *t) { - TransData *td = t->data; int i; t->mode = TFM_TOSPHERE; @@ -3583,11 +3922,14 @@ static void initToSphere(TransInfo *t) t->flag |= T_NO_CONSTRAINT; // Calculate average radius - for (i = 0; i < t->total; i++, td++) { - t->val += len_v3v3(t->center, td->iloc); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + t->val += len_v3v3(tc->center_local, td->iloc); + } } - t->val /= (float)t->total; + t->val /= (float)t->data_len_all; } static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) @@ -3596,7 +3938,6 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) float ratio, radius; int i; char str[UI_MAX_DRAW_STR]; - TransData *td = t->data; ratio = t->values[0]; @@ -3621,30 +3962,31 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), IFACE_("To Sphere: %.4f %s"), ratio, t->proptext); } + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float tratio; + if (td->flag & TD_NOACTION) + break; - for (i = 0; i < t->total; i++, td++) { - float tratio; - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - sub_v3_v3v3(vec, td->iloc, t->center); + sub_v3_v3v3(vec, td->iloc, tc->center_local); - radius = normalize_v3(vec); + radius = normalize_v3(vec); - tratio = ratio * td->factor; + tratio = ratio * td->factor; - mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio); + mul_v3_fl(vec, radius * (1.0f - tratio) + t->val * tratio); - add_v3_v3v3(td->loc, t->center, vec); + add_v3_v3v3(td->loc, tc->center_local, vec); + } } - recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -3658,7 +4000,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) static void postInputRotation(TransInfo *t, float values[3]) { if ((t->con.mode & CON_APPLY) && t->con.applyRot) { - t->con.applyRot(t, NULL, t->axis, values); + t->con.applyRot(t, NULL, NULL, t->axis, values); } } @@ -3697,13 +4039,35 @@ static void initRotation(TransInfo *t) copy_v3_v3(t->axis_orig, t->axis); } +/* Used by Transform Rotation and Transform Normal Rotation */ +static void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) +{ + size_t ofs = 0; + + if (hasNumInput(&t->num)) { + char c[NUM_STR_REP_LEN]; + + outputNumInput(&(t->num), c, &t->scene->unit); + + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); + } + else { + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_("Rot: %.2f%s %s"), + RAD2DEGF(final), t->con.text, t->proptext); + } + + if (t->flag & T_PROP_EDIT_ALL) { + ofs += BLI_snprintf(str + ofs, UI_MAX_DRAW_STR - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); + } +} + /** * Applies values of rotation to `td->loc` and `td->ext->quat` * based on a rotation matrix (mat) and a pivot (center). * * Protected axis and other transform settings are taken into account. */ -static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], const float *center) +static void ElementRotation_ex(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const float *center) { float vec[3], totmat[3][3], smat[3][3]; float eul[3], fmat[3][3], quat[4]; @@ -3712,6 +4076,20 @@ static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], con mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); + /* apply gpencil falloff */ + if (t->options & CTX_GPENCIL_STROKES) { + bGPDstroke *gps = (bGPDstroke *)td->extra; + float sx = smat[0][0]; + float sy = smat[1][1]; + float sz = smat[2][2]; + + mul_m3_fl(smat, gps->runtime.multi_frame_falloff); + /* fix scale */ + smat[0][0] = sx; + smat[1][1] = sy; + smat[2][2] = sz; + } + sub_v3_v3v3(vec, td->iloc, center); mul_m3_v3(smat, vec); @@ -3747,18 +4125,14 @@ static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], con * has been computed, it has to be converted back into the bone's space. */ else if (t->flag & T_POSE) { - float pmtx[3][3], imtx[3][3]; - // Extract and invert armature object matrix - copy_m3_m4(pmtx, t->poseobj->obmat); - invert_m3_m3(imtx, pmtx); if ((td->flag & TD_NO_LOC) == 0) { sub_v3_v3v3(vec, td->center, center); - mul_m3_v3(pmtx, vec); // To Global space + mul_m3_v3(tc->mat3, vec); // To Global space mul_m3_v3(mat, vec); // Applying rotation - mul_m3_v3(imtx, vec); // To Local space + mul_m3_v3(tc->imat3, vec); // To Local space add_v3_v3(vec, center); /* vec now is the location where the object has to be */ @@ -3770,11 +4144,11 @@ static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], con /* do nothing */ } else if (td->flag & TD_PBONE_LOCAL_MTX_C) { - mul_m3_v3(pmtx, vec); // To Global space + mul_m3_v3(tc->mat3, vec); // To Global space mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location) } else { - mul_m3_v3(pmtx, vec); // To Global space + mul_m3_v3(tc->mat3, vec); // To Global space mul_m3_v3(td->smtx, vec); // To Pose space } @@ -3916,7 +4290,7 @@ static void ElementRotation_ex(TransInfo *t, TransData *td, float mat[3][3], con } } -static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], const short around) +static void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around) { const float *center; @@ -3925,44 +4299,45 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], const center = td->center; } else { - center = t->center; + center = tc->center_local; } - ElementRotation_ex(t, td, mat, center); + ElementRotation_ex(t, tc, td, mat, center); } static void applyRotationValue(TransInfo *t, float angle, float axis[3]) { - TransData *td = t->data; float mat[3][3]; int i; axis_angle_normalized_to_mat3(mat, axis, angle); - for (i = 0; i < t->total; i++, td++) { + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) - break; + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (t->con.applyRot) { - t->con.applyRot(t, td, axis, NULL); - axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); - } - else if (t->flag & T_PROP_EDIT) { - axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); - } + if (t->con.applyRot) { + t->con.applyRot(t, tc, td, axis, NULL); + axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); + } + else if (t->flag & T_PROP_EDIT) { + axis_angle_normalized_to_mat3(mat, axis, angle * td->factor); + } - ElementRotation(t, td, mat, t->around); + ElementRotation(t, tc, td, mat, t->around); + } } } static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) { char str[UI_MAX_DRAW_STR]; - size_t ofs = 0; float final; @@ -3971,7 +4346,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) snapGridIncrement(t, &final); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { - t->con.applyRot(t, NULL, t->axis, NULL); + t->con.applyRot(t, NULL, NULL, t->axis, NULL); } else { /* reset axis if constraint is not set */ @@ -3985,27 +4360,13 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = final; - if (hasNumInput(&t->num)) { - char c[NUM_STR_REP_LEN]; - - outputNumInput(&(t->num), c, &t->scene->unit); - - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); - } - else { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_("Rot: %.2f%s %s"), - RAD2DEGF(final), t->con.text, t->proptext); - } - - if (t->flag & T_PROP_EDIT_ALL) { - ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); - } + headerRotation(t, str, final); applyRotationValue(t, final, t->axis); recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -4040,7 +4401,6 @@ static void initTrackball(TransInfo *t) static void applyTrackballValue(TransInfo *t, const float axis1[3], const float axis2[3], float angles[2]) { - TransData *td = t->data; float mat[3][3]; float axis[3]; float angle; @@ -4051,18 +4411,21 @@ static void applyTrackballValue(TransInfo *t, const float axis1[3], const float angle = normalize_v3(axis); axis_angle_normalized_to_mat3(mat, axis, angle); - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (t->flag & T_PROP_EDIT) { - axis_angle_normalized_to_mat3(mat, axis, td->factor * angle); - } + if (t->flag & T_PROP_EDIT) { + axis_angle_normalized_to_mat3(mat, axis, td->factor * angle); + } - ElementRotation(t, td, mat, t->around); + ElementRotation(t, tc, td, mat, t->around); + } } } @@ -4113,19 +4476,140 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2])) mul_m3_m3m3(mat, smat, totmat); // TRANSFORM_FIX_ME - //copy_m3_m3(t->mat, mat); // used in manipulator + //copy_m3_m3(t->mat, mat); // used in gizmo #endif applyTrackballValue(t, axis1, axis2, phi); recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ /* -------------------------------------------------------------------- */ +/* Transform (Normal Rotation) */ + +/** \name Transform Normal Rotation +* \{ */ + +static void storeCustomLNorValue(TransDataContainer *tc, BMesh *bm) +{ + BMLoopNorEditDataArray *lnors_ed_arr = BM_loop_normal_editdata_array_init(bm); + // BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + + tc->custom.mode.data = lnors_ed_arr; + tc->custom.mode.free_cb = freeCustomNormalArray; +} + +void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data) +{ + BMLoopNorEditDataArray *lnors_ed_arr = custom_data->data; + + if (t->state == TRANS_CANCEL) { + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + + for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { /* Restore custom loop normal on cancel */ + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->niloc, lnor_ed->clnors_data); + } + } + + BM_loop_normal_editdata_array_free(lnors_ed_arr); + + tc->custom.mode.data = NULL; + tc->custom.mode.free_cb = NULL; +} + +static void initNormalRotation(TransInfo *t) +{ + t->mode = TFM_NORMAL_ROTATION; + t->transform = applyNormalRotation; + + setInputPostFct(&t->mouse, postInputRotation); + initMouseInputMode(t, &t->mouse, INPUT_ANGLE); + + t->idx_max = 0; + t->num.idx_max = 0; + t->snap[0] = 0.0f; + t->snap[1] = DEG2RAD(5.0); + t->snap[2] = DEG2RAD(1.0); + + copy_v3_fl(t->num.val_inc, t->snap[2]); + t->num.unit_sys = t->scene->unit.system; + t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS); + t->num.unit_type[0] = B_UNIT_ROTATION; + + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + + BKE_editmesh_lnorspace_update(em); + + storeCustomLNorValue(tc, bm); + } + + negate_v3_v3(t->axis, t->viewinv[2]); + normalize_v3(t->axis); + + copy_v3_v3(t->axis_orig, t->axis); +} + +/* Works by getting custom normal from clnor_data, transform, then store */ +static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2])) +{ + char str[UI_MAX_DRAW_STR]; + + if ((t->con.mode & CON_APPLY) && t->con.applyRot) { + t->con.applyRot(t, NULL, NULL, t->axis, NULL); + } + else { + /* reset axis if constraint is not set */ + copy_v3_v3(t->axis, t->axis_orig); + } + + FOREACH_TRANS_DATA_CONTAINER(t, tc) { + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); + BMesh *bm = em->bm; + + BMLoopNorEditDataArray *lnors_ed_arr = tc->custom.mode.data; + BMLoopNorEditData *lnor_ed = lnors_ed_arr->lnor_editdata; + + float axis[3]; + float mat[3][3]; + float angle = t->values[0]; + copy_v3_v3(axis, t->axis); + + snapGridIncrement(t, &angle); + + applySnapping(t, &angle); + + applyNumInput(&t->num, &angle); + + headerRotation(t, str, angle); + + axis_angle_normalized_to_mat3(mat, axis, angle); + + for (int i = 0; i < lnors_ed_arr->totloop; i++, lnor_ed++) { + mul_v3_m3v3(lnor_ed->nloc, mat, lnor_ed->niloc); + + BKE_lnor_space_custom_normal_to_data( + bm->lnor_spacearr->lspacearr[lnor_ed->loop_index], lnor_ed->nloc, lnor_ed->clnors_data); + } + } + + recalcData(t); + + ED_area_status_text(t->sa, str); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ /* Transform (Translation) */ static void initSnapSpatial(TransInfo *t, float r_snap[3]) @@ -4134,8 +4618,9 @@ static void initSnapSpatial(TransInfo *t, float r_snap[3]) RegionView3D *rv3d = t->ar->regiondata; if (rv3d) { + View3D *v3d = t->sa->spacedata.first; r_snap[0] = 0.0f; - r_snap[1] = rv3d->gridview * 1.0f; + r_snap[1] = ED_view3d_grid_view_scale(t->scene, v3d, rv3d, NULL) * 1.0f; r_snap[2] = r_snap[1] * 0.1f; } } @@ -4225,12 +4710,12 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ dist = len_v3(vec); if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { - const bool do_split = (t->scene->unit.flag & USER_UNIT_OPT_SPLIT) != 0; int i; for (i = 0; i < 3; i++) { - 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, true); + bUnit_AsString2( + &tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length, + 4, B_UNIT_LENGTH, &t->scene->unit, true); } } else { @@ -4241,9 +4726,9 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ } if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) { - const bool do_split = (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, do_split, false); + bUnit_AsString2( + distvec, sizeof(distvec), dist * t->scene->unit.scale_length, + 4, B_UNIT_LENGTH, &t->scene->unit, false); } else if (dist > 1e10f || dist < -1e10f) { /* prevent string buffer overflow */ @@ -4317,81 +4802,97 @@ static void headerTranslation(TransInfo *t, const float vec[3], char str[UI_MAX_ static void applyTranslationValue(TransInfo *t, const float vec[3]) { - TransData *td = t->data; + const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT); float tvec[3]; /* The ideal would be "apply_snap_align_rotation" only when a snap point is found * so, maybe inside this function is not the best place to apply this rotation. * but you need "handle snapping rotation before doing the translation" (really?) */ - const bool apply_snap_align_rotation = usingSnappingNormal(t);// && (t->tsnap.status & POINT_INIT); - float pivot[3]; - if (apply_snap_align_rotation) { - copy_v3_v3(pivot, t->tsnap.snapTarget); - /* The pivot has to be in local-space (see T49494) */ - if (t->flag & (T_EDIT | T_POSE)) { - Object *ob = t->obedit ? t->obedit : t->poseobj; - mul_m4_v3(ob->imat, pivot); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + + float pivot[3]; + if (apply_snap_align_rotation) { + copy_v3_v3(pivot, t->tsnap.snapTarget); + /* The pivot has to be in local-space (see T49494) */ + if (tc->use_local_mat) { + mul_m4_v3(tc->imat, pivot); + } } - } - for (int i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + TransData *td = tc->data; + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - float rotate_offset[3] = {0}; - bool use_rotate_offset = false; + float rotate_offset[3] = {0}; + bool use_rotate_offset = false; - /* handle snapping rotation before doing the translation */ - if (apply_snap_align_rotation) { - float mat[3][3]; + /* handle snapping rotation before doing the translation */ + if (apply_snap_align_rotation) { + float mat[3][3]; - if (validSnappingNormal(t)) { - const float *original_normal; + if (validSnappingNormal(t)) { + const float *original_normal; - /* In pose mode, we want to align normals with Y axis of bones... */ - if (t->flag & T_POSE) - original_normal = td->axismtx[1]; - else - original_normal = td->axismtx[2]; + /* In pose mode, we want to align normals with Y axis of bones... */ + if (t->flag & T_POSE) + original_normal = td->axismtx[1]; + else + original_normal = td->axismtx[2]; + + rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal); + } + else { + unit_m3(mat); + } - rotation_between_vecs_to_mat3(mat, original_normal, t->tsnap.snapNormal); + ElementRotation_ex(t, tc, td, mat, pivot); + + if (td->loc) { + use_rotate_offset = true; + sub_v3_v3v3(rotate_offset, td->loc, td->iloc); + } + } + + if (t->con.applyVec) { + float pvec[3]; + t->con.applyVec(t, tc, td, vec, tvec, pvec); } else { - unit_m3(mat); + copy_v3_v3(tvec, vec); } - ElementRotation_ex(t, td, mat, pivot); - - if (td->loc) { - use_rotate_offset = true; - sub_v3_v3v3(rotate_offset, td->loc, td->iloc); + if (use_rotate_offset) { + add_v3_v3(tvec, rotate_offset); } - } - if (t->con.applyVec) { - float pvec[3]; - t->con.applyVec(t, td, vec, tvec, pvec); - } - else { - copy_v3_v3(tvec, vec); - } + mul_m3_v3(td->smtx, tvec); - if (use_rotate_offset) { - add_v3_v3(tvec, rotate_offset); - } - - mul_m3_v3(td->smtx, tvec); - mul_v3_fl(tvec, td->factor); + if (t->options & CTX_GPENCIL_STROKES) { + /* grease pencil multiframe falloff */ + bGPDstroke *gps = (bGPDstroke *)td->extra; + if (gps != NULL) { + mul_v3_fl(tvec, td->factor * gps->runtime.multi_frame_falloff); + } + else { + mul_v3_fl(tvec, td->factor); + } + } + else { + /* proportional editing falloff */ + mul_v3_fl(tvec, td->factor); + } - protectedTransBits(td->protectflag, tvec); + protectedTransBits(td->protectflag, tvec); - if (td->loc) - add_v3_v3v3(td->loc, td->iloc, tvec); + if (td->loc) + add_v3_v3v3(td->loc, td->iloc, tvec); - constraintTransLim(t, td); + constraintTransLim(t, td); + } } } @@ -4417,7 +4918,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) if (t->con.mode & CON_APPLY) { float pvec[3] = {0.0f, 0.0f, 0.0f}; - t->con.applyVec(t, NULL, t->values, value_final, pvec); + t->con.applyVec(t, NULL, NULL, t->values, value_final, pvec); headerTranslation(t, pvec, str); /* only so we have re-usable value with redo, see T46741. */ @@ -4447,7 +4948,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -4461,7 +4962,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2])) static void initShrinkFatten(TransInfo *t) { // If not in mesh edit mode, fallback to Resize - if (t->obedit == NULL || t->obedit->type != OB_MESH) { + if ((t->flag & T_EDIT) == 0 || (t->obedit_type != OB_MESH)) { initResize(t); } else { @@ -4491,7 +4992,6 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) int i; char str[UI_MAX_DRAW_STR]; size_t ofs = 0; - TransData *td = t->data; distance = -t->values[0]; @@ -4525,29 +5025,32 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } } BLI_snprintf(str + ofs, sizeof(str) - ofs, IFACE_(" or Alt) Even Thickness %s"), - WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0)); + WM_bool_as_string((t->flag & T_ALT_TRANSFORM) == 0)); /* done with header string */ - for (i = 0; i < t->total; i++, td++) { - float tdistance; /* temp dist */ - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float tdistance; /* temp dist */ + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - /* get the final offset */ - tdistance = distance * td->factor; - if (td->ext && (t->flag & T_ALT_TRANSFORM)) { - tdistance *= td->ext->isize[0]; /* shell factor */ - } + /* get the final offset */ + tdistance = distance * td->factor; + if (td->ext && (t->flag & T_ALT_TRANSFORM) == 0) { + tdistance *= td->ext->isize[0]; /* shell factor */ + } - madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); + madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -4582,7 +5085,6 @@ static void initTilt(TransInfo *t) static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; int i; char str[UI_MAX_DRAW_STR]; @@ -4610,21 +5112,24 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival + final * td->factor; + if (td->val) { + *td->val = td->ival + final * td->factor; + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -4662,7 +5167,6 @@ static void initCurveShrinkFatten(TransInfo *t) static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float ratio; int i; char str[UI_MAX_DRAW_STR]; @@ -4686,24 +5190,27 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival * ratio; - /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) *td->val = 0.001f; + if (td->val) { + *td->val = td->ival * ratio; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + if (*td->val <= 0.0f) *td->val = 0.001f; + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -4741,7 +5248,6 @@ static void initMaskShrinkFatten(TransInfo *t) static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td; float ratio; int i; bool initial_feather = false; @@ -4770,41 +5276,47 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) if (ratio > 1.0f) { initial_feather = true; - for (td = t->data, i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->ival >= 0.001f) - initial_feather = false; + if (td->ival >= 0.001f) + initial_feather = false; + } } } /* apply shrink/fatten */ - for (td = t->data, i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (td = tc->data, i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - if (initial_feather) - *td->val = td->ival + (ratio - 1.0f) * 0.01f; - else - *td->val = td->ival * ratio; + if (td->val) { + if (initial_feather) + *td->val = td->ival + (ratio - 1.0f) * 0.01f; + else + *td->val = td->ival * ratio; - /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) *td->val = 0.001f; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + if (*td->val <= 0.0f) *td->val = 0.001f; + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -4842,7 +5354,6 @@ static void initGPShrinkFatten(TransInfo *t) static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float ratio; int i; char str[UI_MAX_DRAW_STR]; @@ -4866,24 +5377,25 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), IFACE_("Shrink/Fatten: %3f"), ratio); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival * ratio; - /* apply PET */ - *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); - if (*td->val <= 0.0f) *td->val = 0.001f; + if (td->val) { + *td->val = td->ival * ratio; + /* apply PET */ + *td->val = (*td->val * td->factor) + ((1.0f - td->factor) * td->ival); + if (*td->val <= 0.0f) *td->val = 0.001f; + } } } - recalcData(t); - - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -4919,7 +5431,6 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) float distance; int i; char str[UI_MAX_DRAW_STR]; - TransData *td = t->data; distance = t->values[0]; @@ -4943,40 +5454,43 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) } if (t->con.applyRot && t->con.mode & CON_APPLY) { - t->con.applyRot(t, NULL, axis_global, NULL); + t->con.applyRot(t, NULL, NULL, axis_global, NULL); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; - - if (td->flag & TD_SKIP) - continue; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - sub_v3_v3v3(vec, t->center, td->center); - if (t->con.applyRot && t->con.mode & CON_APPLY) { - float axis[3]; - copy_v3_v3(axis, axis_global); - t->con.applyRot(t, td, axis, NULL); + if (td->flag & TD_SKIP) + continue; - mul_m3_v3(td->smtx, axis); - if (isLockConstraint(t)) { - float dvec[3]; - project_v3_v3v3(dvec, vec, axis); - sub_v3_v3(vec, dvec); - } - else { - project_v3_v3v3(vec, vec, axis); + sub_v3_v3v3(vec, tc->center_local, td->center); + if (t->con.applyRot && t->con.mode & CON_APPLY) { + float axis[3]; + copy_v3_v3(axis, axis_global); + t->con.applyRot(t, tc, td, axis, NULL); + + mul_m3_v3(td->smtx, axis); + if (isLockConstraint(t)) { + float dvec[3]; + project_v3_v3v3(dvec, vec, axis); + sub_v3_v3(vec, dvec); + } + else { + project_v3_v3v3(vec, vec, axis); + } } - } - normalize_v3_length(vec, distance * td->factor); + normalize_v3_length(vec, distance * td->factor); - add_v3_v3v3(td->loc, td->iloc, vec); + add_v3_v3v3(td->loc, td->iloc, vec); + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -5009,7 +5523,6 @@ static void initBevelWeight(TransInfo *t) static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float weight; int i; char str[UI_MAX_DRAW_STR]; @@ -5043,20 +5556,23 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->val) { - *td->val = td->ival + weight * td->factor; - if (*td->val < 0.0f) *td->val = 0.0f; - if (*td->val > 1.0f) *td->val = 1.0f; + if (td->val) { + *td->val = td->ival + weight * td->factor; + if (*td->val < 0.0f) *td->val = 0.0f; + if (*td->val > 1.0f) *td->val = 1.0f; + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -5089,7 +5605,6 @@ static void initCrease(TransInfo *t) static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float crease; int i; char str[UI_MAX_DRAW_STR]; @@ -5123,23 +5638,26 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), IFACE_("Crease: %.3f %s"), crease, t->proptext); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival + crease * td->factor; - if (*td->val < 0.0f) *td->val = 0.0f; - if (*td->val > 1.0f) *td->val = 1.0f; + if (td->val) { + *td->val = td->ival + crease * td->factor; + if (*td->val < 0.0f) *td->val = 0.0f; + if (*td->val > 1.0f) *td->val = 1.0f; + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -5200,7 +5718,7 @@ static void headerBoneSize(TransInfo *t, const float vec[3], char str[UI_MAX_DRA } } -static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) +static void ElementBoneSize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]) { float tmat[3][3], smat[3][3], oldy; float sizemat[3][3]; @@ -5209,7 +5727,7 @@ static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) mul_m3_m3m3(tmat, td->smtx, smat); if (t->con.applySize) { - t->con.applySize(t, td, tmat); + t->con.applySize(t, tc, td, tmat); } /* we've tucked the scale in loc */ @@ -5220,23 +5738,13 @@ static void ElementBoneSize(TransInfo *t, TransData *td, float mat[3][3]) td->loc[1] = oldy; } -static void applyBoneSize(TransInfo *t, const int mval[2]) +static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float size[3], mat[3][3]; - float ratio; + float ratio = t->values[0]; int i; char str[UI_MAX_DRAW_STR]; - // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT - /* for manipulator, center handle, the scaling can't be done relative to center */ - if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { - ratio = 1.0f - ((t->mouse.imval[0] - mval[0]) + (t->mouse.imval[1] - mval[1])) / 100.0f; - } - else { - ratio = t->values[0]; - } - copy_v3_fl(size, ratio); snapGridIncrement(t, size); @@ -5250,26 +5758,29 @@ static void applyBoneSize(TransInfo *t, const int mval[2]) size_to_mat3(mat, size); if (t->con.applySize) { - t->con.applySize(t, NULL, mat); + t->con.applySize(t, NULL, NULL, mat); } - copy_m3_m3(t->mat, mat); // used in manipulator + copy_m3_m3(t->mat, mat); // used in gizmo headerBoneSize(t, size, str); - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - ElementBoneSize(t, td, mat); + ElementBoneSize(t, tc, td, mat); + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -5302,7 +5813,6 @@ static void initBoneEnvelope(TransInfo *t) static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float ratio; int i; char str[UI_MAX_DRAW_STR]; @@ -5326,25 +5836,28 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) BLI_snprintf(str, sizeof(str), IFACE_("Envelope: %3f"), ratio); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - /* if the old/original value was 0.0f, then just use ratio */ - if (td->ival) - *td->val = td->ival * ratio; - else - *td->val = ratio; + if (td->val) { + /* if the old/original value was 0.0f, then just use ratio */ + if (td->ival) + *td->val = td->ival * ratio; + else + *td->val = ratio; + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -5355,9 +5868,9 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) * \{ */ static void slide_origdata_init_flag( - TransInfo *t, SlideOrigData *sod) + TransInfo *t, TransDataContainer *tc, SlideOrigData *sod) { - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; const bool has_layer_math = CustomData_has_math(&bm->ldata); const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); @@ -5378,10 +5891,10 @@ static void slide_origdata_init_flag( } static void slide_origdata_init_data( - TransInfo *t, SlideOrigData *sod) + TransDataContainer *tc, SlideOrigData *sod) { if (sod->use_origfaces) { - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; sod->origfaces = BLI_ghash_ptr_new(__func__); @@ -5442,11 +5955,11 @@ static void slide_origdata_create_data_vert( } static void slide_origdata_create_data( - TransInfo *t, SlideOrigData *sod, + TransInfo *t, TransDataContainer *tc, SlideOrigData *sod, TransDataGenericSlideVert *sv_array, unsigned int v_stride, unsigned int v_num) { if (sod->use_origfaces) { - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; unsigned int i; TransDataGenericSlideVert *sv; @@ -5478,15 +5991,15 @@ static void slide_origdata_create_data( } if (t->flag & T_MIRROR) { - TransData *td = t->data; + TransData *td = tc->data; TransDataGenericSlideVert *sv_mirror; - sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * t->total, __func__); - sod->totsv_mirror = t->total; + sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__); + sod->totsv_mirror = tc->data_len; sv_mirror = sod->sv_mirror; - for (i = 0; i < t->total; i++, td++) { + for (i = 0; i < tc->data_len; i++, td++) { BMVert *eve = td->extra; if (eve) { sv_mirror->v = eve; @@ -5640,12 +6153,12 @@ static void slide_origdata_interp_data_vert( } static void slide_origdata_interp_data( - TransInfo *t, SlideOrigData *sod, + Object *obedit, SlideOrigData *sod, TransDataGenericSlideVert *sv, unsigned int v_stride, unsigned int v_num, bool is_final) { if (sod->use_origfaces) { - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(obedit); BMesh *bm = em->bm; unsigned int i; const bool has_mdisps = (sod->cd_loop_mdisp_offset != -1); @@ -5708,7 +6221,7 @@ static void slide_origdata_free_date( static void calcEdgeSlideCustomPoints(struct TransInfo *t) { - EdgeSlideData *sld = t->custom.mode.data; + EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; setCustomPoints(t, &t->mouse, sld->mval_end, sld->mval_start); @@ -5776,6 +6289,7 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, BMLoop *l_last = l_tmp->prev; BMLoop *l_iter; float dist = FLT_MAX; + bool found = false; l_iter = l_first; do { @@ -5794,12 +6308,13 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, if (tdist < dist) { copy_v3_v3(r_co, tvec); dist = tdist; + found = true; } } } } while ((l_iter = l_iter->next) != l_last); - return (dist != FLT_MAX); + return found; } /** @@ -5905,11 +6420,11 @@ static BMLoop *get_next_loop(BMVert *v, BMLoop *l, * Calculate screenspace `mval_start` / `mval_end`, optionally slide direction. */ static void calcEdgeSlide_mval_range( - TransInfo *t, EdgeSlideData *sld, const int *sv_table, const int loop_nr, + TransInfo *t, TransDataContainer *tc, EdgeSlideData *sld, const int *sv_table, const int loop_nr, const float mval[2], const bool use_occlude_geometry, const bool use_calc_direction) { TransDataEdgeSlideVert *sv_array = sld->sv; - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; ARegion *ar = t->ar; View3D *v3d = NULL; @@ -5936,7 +6451,7 @@ static void calcEdgeSlide_mval_range( unit_m4(projectMat); } else { - ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); } if (use_occlude_geometry) { @@ -5978,7 +6493,9 @@ static void calcEdgeSlide_mval_range( continue; /* This test is only relevant if object is not wire-drawn! See [#32068]. */ - if (use_occlude_geometry && !BMBVH_EdgeVisible(bmbvh, e_other, ar, v3d, t->obedit)) { + if (use_occlude_geometry && + !BMBVH_EdgeVisible(bmbvh, e_other, t->depsgraph, ar, v3d, tc->obedit)) + { continue; } @@ -6065,7 +6582,7 @@ static void calcEdgeSlide_mval_range( } static void calcEdgeSlide_even( - TransInfo *t, EdgeSlideData *sld, const float mval[2]) + TransInfo *t, TransDataContainer *tc, EdgeSlideData *sld, const float mval[2]) { TransDataEdgeSlideVert *sv = sld->sv; @@ -6090,7 +6607,7 @@ static void calcEdgeSlide_even( unit_m4(projectMat); } else { - ED_view3d_ob_project_mat_get(rv3d, t->obedit, projectMat); + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, projectMat); } for (i = 0; i < sld->totsv; i++, sv++) { @@ -6110,9 +6627,9 @@ static void calcEdgeSlide_even( } } -static bool createEdgeSlideVerts_double_side(TransInfo *t, bool use_even, bool flipped, bool use_clamp) +static bool createEdgeSlideVerts_double_side(TransInfo *t, TransDataContainer *tc) { - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; BMIter iter; BMEdge *e; @@ -6127,13 +6644,9 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, bool use_even, bool f View3D *v3d = NULL; RegionView3D *rv3d = NULL; - slide_origdata_init_flag(t, &sld->orig_data); + slide_origdata_init_flag(t, tc, &sld->orig_data); - sld->use_even = use_even; sld->curr_sv_index = 0; - sld->flipped = flipped; - if (!use_clamp) - t->flag |= T_ALT_TRANSFORM; /*ensure valid selection*/ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -6449,25 +6962,23 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, bool use_even, bool f if (t->spacetype == SPACE_VIEW3D) { v3d = t->sa ? t->sa->spacedata.first : NULL; rv3d = t->ar ? t->ar->regiondata : NULL; - use_occlude_geometry = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE); + use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->shading.type > OB_WIRE); } - calcEdgeSlide_mval_range(t, sld, sv_table, loop_nr, mval, use_occlude_geometry, true); + calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, true); /* create copies of faces for customdata projection */ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - slide_origdata_init_data(t, &sld->orig_data); - slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); + slide_origdata_init_data(tc, &sld->orig_data); + slide_origdata_create_data(t, tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); if (rv3d) { - calcEdgeSlide_even(t, sld, mval); + calcEdgeSlide_even(t, tc, sld, mval); } sld->em = em; - sld->perc = 0.0f; - - t->custom.mode.data = sld; + tc->custom.mode.data = sld; MEM_freeN(sv_table); @@ -6478,9 +6989,9 @@ static bool createEdgeSlideVerts_double_side(TransInfo *t, bool use_even, bool f * A simple version of #createEdgeSlideVerts_double_side * Which assumes the longest unselected. */ -static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool flipped, bool use_clamp) +static bool createEdgeSlideVerts_single_side(TransInfo *t, TransDataContainer *tc) { - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; BMIter iter; BMEdge *e; @@ -6500,15 +7011,9 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool f rv3d = t->ar ? t->ar->regiondata : NULL; } - slide_origdata_init_flag(t, &sld->orig_data); + slide_origdata_init_flag(t, tc, &sld->orig_data); - sld->use_even = use_even; sld->curr_sv_index = 0; - /* happens to be best for single-sided */ - sld->flipped = !flipped; - if (!use_clamp) - t->flag |= T_ALT_TRANSFORM; - /* ensure valid selection */ { int i = 0, j = 0; @@ -6652,25 +7157,23 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool f if (t->spacetype == SPACE_VIEW3D) { v3d = t->sa ? t->sa->spacedata.first : NULL; rv3d = t->ar ? t->ar->regiondata : NULL; - use_occlude_geometry = (v3d && t->obedit->dt > OB_WIRE && v3d->drawtype > OB_WIRE); + use_occlude_geometry = (v3d && TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->dt > OB_WIRE && v3d->shading.type > OB_WIRE); } - calcEdgeSlide_mval_range(t, sld, sv_table, loop_nr, mval, use_occlude_geometry, false); + calcEdgeSlide_mval_range(t, tc, sld, sv_table, loop_nr, mval, use_occlude_geometry, false); /* create copies of faces for customdata projection */ bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - slide_origdata_init_data(t, &sld->orig_data); - slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); + slide_origdata_init_data(tc, &sld->orig_data); + slide_origdata_create_data(t, tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); if (rv3d) { - calcEdgeSlide_even(t, sld, mval); + calcEdgeSlide_even(t, tc, sld, mval); } sld->em = em; - sld->perc = 0.0f; - - t->custom.mode.data = sld; + tc->custom.mode.data = sld; MEM_freeN(sv_table); @@ -6679,14 +7182,16 @@ static bool createEdgeSlideVerts_single_side(TransInfo *t, bool use_even, bool f void projectEdgeSlideData(TransInfo *t, bool is_final) { - EdgeSlideData *sld = t->custom.mode.data; - SlideOrigData *sod = &sld->orig_data; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + EdgeSlideData *sld = tc->custom.mode.data; + SlideOrigData *sod = &sld->orig_data; - if (sod->use_origfaces == false) { - return; - } + if (sod->use_origfaces == false) { + return; + } - slide_origdata_interp_data(t, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final); + slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final); + } } void freeEdgeSlideTempFaces(EdgeSlideData *sld) @@ -6694,7 +7199,7 @@ void freeEdgeSlideTempFaces(EdgeSlideData *sld) slide_origdata_free_date(&sld->orig_data); } -void freeEdgeSlideVerts(TransInfo *UNUSED(t), TransCustomData *custom_data) +void freeEdgeSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data) { EdgeSlideData *sld = custom_data->data; @@ -6714,17 +7219,39 @@ void freeEdgeSlideVerts(TransInfo *UNUSED(t), TransCustomData *custom_data) static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, bool flipped, bool use_clamp) { EdgeSlideData *sld; - bool ok; + bool ok = false; t->mode = TFM_EDGE_SLIDE; t->transform = applyEdgeSlide; t->handleEvent = handleEventEdgeSlide; + { + EdgeSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); + slp->use_even = use_even; + slp->flipped = flipped; + /* happens to be best for single-sided */ + if (use_double_side == false) { + slp->flipped = !flipped; + } + slp->perc = 0.0f; + + if (!use_clamp) { + t->flag |= T_ALT_TRANSFORM; + } + + t->custom.mode.data = slp; + t->custom.mode.use_free = true; + } + if (use_double_side) { - ok = createEdgeSlideVerts_double_side(t, use_even, flipped, use_clamp); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + ok |= createEdgeSlideVerts_double_side(t, tc); + } } else { - ok = createEdgeSlideVerts_single_side(t, use_even, flipped, use_clamp); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + ok |= createEdgeSlideVerts_single_side(t, tc); + } } if (!ok) { @@ -6732,12 +7259,13 @@ static void initEdgeSlide_ex(TransInfo *t, bool use_double_side, bool use_even, return; } - sld = t->custom.mode.data; - - if (!sld) - return; - - t->custom.mode.free_cb = freeEdgeSlideVerts; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + sld = tc->custom.mode.data; + if (!sld) { + continue; + } + tc->custom.mode.free_cb = freeEdgeSlideVerts; + } /* set custom point first if you want value to be initialized by init */ calcEdgeSlideCustomPoints(t); @@ -6764,20 +7292,20 @@ static void initEdgeSlide(TransInfo *t) static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event) { if (t->mode == TFM_EDGE_SLIDE) { - EdgeSlideData *sld = t->custom.mode.data; + EdgeSlideParams *slp = t->custom.mode.data; - if (sld) { + if (slp) { switch (event->type) { case EKEY: if (event->val == KM_PRESS) { - sld->use_even = !sld->use_even; + slp->use_even = !slp->use_even; calcEdgeSlideCustomPoints(t); return TREDRAW_HARD; } break; case FKEY: if (event->val == KM_PRESS) { - sld->flipped = !sld->flipped; + slp->flipped = !slp->flipped; calcEdgeSlideCustomPoints(t); return TREDRAW_HARD; } @@ -6791,6 +7319,7 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven } break; case EVT_MODAL_MAP: +#if 0 switch (event->val) { case TFM_MODAL_EDGESLIDE_DOWN: sld->curr_sv_index = ((sld->curr_sv_index - 1) + sld->totsv) % sld->totsv; @@ -6799,6 +7328,7 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven sld->curr_sv_index = (sld->curr_sv_index + 1) % sld->totsv; return TREDRAW_HARD; } +#endif break; case MOUSEMOVE: calcEdgeSlideCustomPoints(t); @@ -6813,30 +7343,31 @@ static eRedrawFlag handleEventEdgeSlide(struct TransInfo *t, const struct wmEven static void drawEdgeSlide(TransInfo *t) { - if ((t->mode == TFM_EDGE_SLIDE) && t->custom.mode.data) { - EdgeSlideData *sld = t->custom.mode.data; + if ((t->mode == TFM_EDGE_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) { + const EdgeSlideParams *slp = t->custom.mode.data; + EdgeSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); /* Even mode */ - if ((sld->use_even == true) || (is_clamp == false)) { - View3D *v3d = t->view; + if ((slp->use_even == true) || (is_clamp == false)) { const float line_size = UI_GetThemeValuef(TH_OUTLINE_WIDTH) + 0.5f; - if (v3d && v3d->zbuf) - glDisable(GL_DEPTH_TEST); + GPU_depth_test(false); + + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); - glPushMatrix(); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - glMultMatrixf(t->obedit->obmat); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - if (sld->use_even == true) { + if (slp->use_even == true) { float co_a[3], co_b[3], co_mark[3]; TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float fac = (sld->perc + 1.0f) / 2.0f; + const float fac = (slp->perc + 1.0f) / 2.0f; const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; const float guide_size = ctrl_size - 0.5f; const int alpha_shade = -30; @@ -6844,40 +7375,36 @@ static void drawEdgeSlide(TransInfo *t) add_v3_v3v3(co_a, curr_sv->v_co_orig, curr_sv->dir_side[0]); add_v3_v3v3(co_b, curr_sv->v_co_orig, curr_sv->dir_side[1]); - glLineWidth(line_size); - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - glBegin(GL_LINES); + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBeginAtMost(GPU_PRIM_LINES, 4); if (curr_sv->v_side[0]) { - glVertex3fv(curr_sv->v_side[0]->co); - glVertex3fv(curr_sv->v_co_orig); + immVertex3fv(pos, curr_sv->v_side[0]->co); + immVertex3fv(pos, curr_sv->v_co_orig); } if (curr_sv->v_side[1]) { - glVertex3fv(curr_sv->v_side[1]->co); - glVertex3fv(curr_sv->v_co_orig); + immVertex3fv(pos, curr_sv->v_side[1]->co); + immVertex3fv(pos, curr_sv->v_co_orig); } - glEnd(); + immEnd(); - UI_ThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); - glPointSize(ctrl_size); - glBegin(GL_POINTS); - if (sld->flipped) { - if (curr_sv->v_side[1]) glVertex3fv(curr_sv->v_side[1]->co); + immUniformThemeColorShadeAlpha(TH_SELECT, -30, alpha_shade); + GPU_point_size(ctrl_size); + immBegin(GPU_PRIM_POINTS, 1); + if (slp->flipped) { + if (curr_sv->v_side[1]) immVertex3fv(pos, curr_sv->v_side[1]->co); } else { - if (curr_sv->v_side[0]) glVertex3fv(curr_sv->v_side[0]->co); + if (curr_sv->v_side[0]) immVertex3fv(pos, curr_sv->v_side[0]->co); } - glEnd(); + immEnd(); - UI_ThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); - glPointSize(guide_size); - glBegin(GL_POINTS); -#if 0 - interp_v3_v3v3(co_mark, co_b, co_a, fac); - glVertex3fv(co_mark); -#endif + immUniformThemeColorShadeAlpha(TH_SELECT, 255, alpha_shade); + GPU_point_size(guide_size); + immBegin(GPU_PRIM_POINTS, 1); interp_line_v3_v3v3v3(co_mark, co_b, curr_sv->v_co_orig, co_a, fac); - glVertex3fv(co_mark); - glEnd(); + immVertex3fv(pos, co_mark); + immEnd(); } else { if (is_clamp == false) { @@ -6886,10 +7413,11 @@ static void drawEdgeSlide(TransInfo *t) int i; const int alpha_shade = -160; - glLineWidth(line_size); - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - glBegin(GL_LINES); + GPU_line_width(line_size); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + immBegin(GPU_PRIM_LINES, sld->totsv * 2); + /* TODO(campbell): Loop over all verts */ sv = sld->sv; for (i = 0; i < sld->totsv; i++, sv++) { float a[3], b[3]; @@ -6906,61 +7434,66 @@ static void drawEdgeSlide(TransInfo *t) add_v3_v3(a, sv->v_co_orig); add_v3_v3(b, sv->v_co_orig); - glVertex3fv(a); - glVertex3fv(b); + immVertex3fv(pos, a); + immVertex3fv(pos, b); } - glEnd(); + immEnd(); } else { BLI_assert(0); } } - glPopMatrix(); - glPopAttrib(); + immUnbindProgram(); + + GPU_matrix_pop(); - glDisable(GL_BLEND); + GPU_blend(false); - if (v3d && v3d->zbuf) - glEnable(GL_DEPTH_TEST); + GPU_depth_test(true); } } } static void doEdgeSlide(TransInfo *t, float perc) { - EdgeSlideData *sld = t->custom.mode.data; - TransDataEdgeSlideVert *svlist = sld->sv, *sv; - int i; + EdgeSlideParams *slp = t->custom.mode.data; + EdgeSlideData *sld_active = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; - sld->perc = perc; - sv = svlist; + slp->perc = perc; - if (sld->use_even == false) { + if (slp->use_even == false) { const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); if (is_clamp) { const int side_index = (perc < 0.0f); const float perc_final = fabsf(perc); - for (i = 0; i < sld->totsv; i++, sv++) { - madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + EdgeSlideData *sld = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = sld->sv; + for (int i = 0; i < sld->totsv; i++, sv++) { + madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, sv->dir_side[side_index], perc_final); + } + sld->curr_side_unclamp = side_index; } - - sld->curr_side_unclamp = side_index; } else { - const int side_index = sld->curr_side_unclamp; - const float perc_init = fabsf(perc) * ((sld->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1); - for (i = 0; i < sld->totsv; i++, sv++) { - float dir_flip[3]; - float perc_final = perc_init; - if (!is_zero_v3(sv->dir_side[side_index])) { - copy_v3_v3(dir_flip, sv->dir_side[side_index]); - } - else { - copy_v3_v3(dir_flip, sv->dir_side[!side_index]); - perc_final *= -1; + const float perc_init = fabsf(perc) * ((sld_active->curr_side_unclamp == (perc < 0.0f)) ? 1 : -1); + const int side_index = sld_active->curr_side_unclamp; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + EdgeSlideData *sld = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = sld->sv; + for (int i = 0; i < sld->totsv; i++, sv++) { + float dir_flip[3]; + float perc_final = perc_init; + if (!is_zero_v3(sv->dir_side[side_index])) { + copy_v3_v3(dir_flip, sv->dir_side[side_index]); + } + else { + copy_v3_v3(dir_flip, sv->dir_side[!side_index]); + perc_final *= -1; + } + madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final); } - madd_v3_v3v3fl(sv->v->co, sv->v_co_orig, dir_flip, perc_final); } } } @@ -6973,24 +7506,28 @@ static void doEdgeSlide(TransInfo *t, float perc) * \note len_v3v3(curr_sv->dir_side[0], curr_sv->dir_side[1]) * is the same as the distance between the original vert locations, same goes for the lines below. */ - TransDataEdgeSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; - const float curr_length_perc = curr_sv->edge_len * (((sld->flipped ? perc : -perc) + 1.0f) / 2.0f); + TransDataEdgeSlideVert *curr_sv = &sld_active->sv[sld_active->curr_sv_index]; + const float curr_length_perc = curr_sv->edge_len * (((slp->flipped ? perc : -perc) + 1.0f) / 2.0f); float co_a[3]; float co_b[3]; - for (i = 0; i < sld->totsv; i++, sv++) { - if (sv->edge_len > FLT_EPSILON) { - const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + EdgeSlideData *sld = tc->custom.mode.data; + TransDataEdgeSlideVert *sv = sld->sv; + for (int i = 0; i < sld->totsv; i++, sv++) { + if (sv->edge_len > FLT_EPSILON) { + const float fac = min_ff(sv->edge_len, curr_length_perc) / sv->edge_len; - add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]); - add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]); + add_v3_v3v3(co_a, sv->v_co_orig, sv->dir_side[0]); + add_v3_v3v3(co_b, sv->v_co_orig, sv->dir_side[1]); - if (sld->flipped) { - interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac); - } - else { - interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac); + if (slp->flipped) { + interp_line_v3_v3v3v3(sv->v->co, co_b, sv->v_co_orig, co_a, fac); + } + else { + interp_line_v3_v3v3v3(sv->v->co, co_a, sv->v_co_orig, co_b, fac); + } } } } @@ -7002,9 +7539,9 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) char str[UI_MAX_DRAW_STR]; size_t ofs = 0; float final; - EdgeSlideData *sld = t->custom.mode.data; - bool flipped = sld->flipped; - bool use_even = sld->use_even; + EdgeSlideParams *slp = t->custom.mode.data; + bool flipped = slp->flipped; + bool use_even = slp->use_even; const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); @@ -7043,7 +7580,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -7056,7 +7593,8 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2])) static void calcVertSlideCustomPoints(struct TransInfo *t) { - VertSlideData *sld = t->custom.mode.data; + VertSlideParams *slp = t->custom.mode.data; + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; TransDataVertSlideVert *sv = &sld->sv[sld->curr_sv_index]; const float *co_orig_3d = sv->co_orig_3d; @@ -7073,7 +7611,7 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) ARRAY_SET_ITEMS(mval_start, co_orig_2d[0] + mval_ofs[0], co_orig_2d[1] + mval_ofs[1]); ARRAY_SET_ITEMS(mval_end, co_curr_2d[0] + mval_ofs[0], co_curr_2d[1] + mval_ofs[1]); - if (sld->flipped && sld->use_even) { + if (slp->flipped && slp->use_even) { setCustomPoints(t, &t->mouse, mval_start, mval_end); } else { @@ -7091,7 +7629,8 @@ static void calcVertSlideCustomPoints(struct TransInfo *t) */ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) { - VertSlideData *sld = t->custom.mode.data; + /* Active object may have no selected vertices. */ + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; float mval_fl[2] = {UNPACK2(mval)}; TransDataVertSlideVert *sv; @@ -7118,7 +7657,7 @@ static void calcVertSlideMouseActiveVert(struct TransInfo *t, const int mval[2]) */ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2]) { - VertSlideData *sld = t->custom.mode.data; + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; float imval_fl[2] = {UNPACK2(t->mouse.imval)}; float mval_fl[2] = {UNPACK2(mval)}; @@ -7146,7 +7685,7 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] float dir_dot; sub_v3_v3v3(tdir, sv->co_orig_3d, sv->co_link_orig_3d[j]); - mul_mat3_m4_v3(t->obedit->obmat, tdir); + mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, tdir); project_plane_v3_v3v3(tdir, tdir, t->viewinv[2]); normalize_v3(tdir); @@ -7164,9 +7703,9 @@ static void calcVertSlideMouseActiveEdges(struct TransInfo *t, const int mval[2] } } -static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool use_clamp) +static bool createVertSlideVerts(TransInfo *t, TransDataContainer *tc) { - BMEditMesh *em = BKE_editmesh_from_object(t->obedit); + BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); BMesh *bm = em->bm; BMIter iter; BMIter eiter; @@ -7176,13 +7715,9 @@ static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool VertSlideData *sld = MEM_callocN(sizeof(*sld), "sld"); int j; - slide_origdata_init_flag(t, &sld->orig_data); + slide_origdata_init_flag(t, tc, &sld->orig_data); - sld->use_even = use_even; sld->curr_sv_index = 0; - sld->flipped = flipped; - if (!use_clamp) - t->flag |= T_ALT_TRANSFORM; j = 0; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -7245,14 +7780,12 @@ static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool sld->totsv = j; bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES); - slide_origdata_init_data(t, &sld->orig_data); - slide_origdata_create_data(t, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); + slide_origdata_init_data(tc, &sld->orig_data); + slide_origdata_create_data(t, tc, &sld->orig_data, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv); sld->em = em; - sld->perc = 0.0f; - - t->custom.mode.data = sld; + tc->custom.mode.data = sld; /* most likely will be set below */ unit_m4(sld->proj_mat); @@ -7264,9 +7797,12 @@ static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool rv3d = ar ? ar->regiondata : NULL; if (rv3d) { - ED_view3d_ob_project_mat_get(rv3d, t->obedit, sld->proj_mat); + ED_view3d_ob_project_mat_get(rv3d, tc->obedit, sld->proj_mat); } + } + /* XXX, calc vert slide across all objects */ + if (tc == t->data_container) { calcVertSlideMouseActiveVert(t, t->mval); calcVertSlideMouseActiveEdges(t, t->mval); } @@ -7276,14 +7812,13 @@ static bool createVertSlideVerts(TransInfo *t, bool use_even, bool flipped, bool void projectVertSlideData(TransInfo *t, bool is_final) { - VertSlideData *sld = t->custom.mode.data; - SlideOrigData *sod = &sld->orig_data; - - if (sod->use_origfaces == false) { - return; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + VertSlideData *sld = tc->custom.mode.data; + SlideOrigData *sod = &sld->orig_data; + if (sod->use_origfaces == true) { + slide_origdata_interp_data(tc->obedit, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final); + } } - - slide_origdata_interp_data(t, sod, (TransDataGenericSlideVert *)sld->sv, sizeof(*sld->sv), sld->totsv, is_final); } void freeVertSlideTempFaces(VertSlideData *sld) @@ -7291,7 +7826,7 @@ void freeVertSlideTempFaces(VertSlideData *sld) slide_origdata_free_date(&sld->orig_data); } -void freeVertSlideVerts(TransInfo *UNUSED(t), TransCustomData *custom_data) +void freeVertSlideVerts(TransInfo *UNUSED(t), TransDataContainer *UNUSED(tc), TransCustomData *custom_data) { VertSlideData *sld = custom_data->data; @@ -7318,23 +7853,38 @@ void freeVertSlideVerts(TransInfo *UNUSED(t), TransCustomData *custom_data) static void initVertSlide_ex(TransInfo *t, bool use_even, bool flipped, bool use_clamp) { - VertSlideData *sld; t->mode = TFM_VERT_SLIDE; t->transform = applyVertSlide; t->handleEvent = handleEventVertSlide; - if (!createVertSlideVerts(t, use_even, flipped, use_clamp)) { - t->state = TRANS_CANCEL; - return; + { + VertSlideParams *slp = MEM_callocN(sizeof(*slp), __func__); + slp->use_even = use_even; + slp->flipped = flipped; + slp->perc = 0.0f; + + if (!use_clamp) { + t->flag |= T_ALT_TRANSFORM; + } + + t->custom.mode.data = slp; + t->custom.mode.use_free = true; } - sld = t->custom.mode.data; + bool ok = false; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + ok |= createVertSlideVerts(t, tc); + VertSlideData *sld = tc->custom.mode.data; + if (sld) { + tc->custom.mode.free_cb = freeVertSlideVerts; + } + } - if (!sld) + if (ok == false) { + t->state = TRANS_CANCEL; return; - - t->custom.mode.free_cb = freeVertSlideVerts; + } /* set custom point first if you want value to be initialized by init */ calcVertSlideCustomPoints(t); @@ -7361,14 +7911,14 @@ static void initVertSlide(TransInfo *t) static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event) { if (t->mode == TFM_VERT_SLIDE) { - VertSlideData *sld = t->custom.mode.data; + VertSlideParams *slp = t->custom.mode.data; - if (sld) { + if (slp) { switch (event->type) { case EKEY: if (event->val == KM_PRESS) { - sld->use_even = !sld->use_even; - if (sld->flipped) { + slp->use_even = !slp->use_even; + if (slp->flipped) { calcVertSlideCustomPoints(t); } return TREDRAW_HARD; @@ -7376,7 +7926,7 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven break; case FKEY: if (event->val == KM_PRESS) { - sld->flipped = !sld->flipped; + slp->flipped = !slp->flipped; calcVertSlideCustomPoints(t); return TREDRAW_HARD; } @@ -7421,13 +7971,13 @@ static eRedrawFlag handleEventVertSlide(struct TransInfo *t, const struct wmEven static void drawVertSlide(TransInfo *t) { - if ((t->mode == TFM_VERT_SLIDE) && t->custom.mode.data) { - VertSlideData *sld = t->custom.mode.data; + if ((t->mode == TFM_VERT_SLIDE) && TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data) { + const VertSlideParams *slp = t->custom.mode.data; + VertSlideData *sld = TRANS_DATA_CONTAINER_FIRST_OK(t)->custom.mode.data; const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); /* Non-Prop mode */ { - View3D *v3d = t->view; TransDataVertSlideVert *curr_sv = &sld->sv[sld->curr_sv_index]; TransDataVertSlideVert *sv; const float ctrl_size = UI_GetThemeValuef(TH_FACEDOT_SIZE) + 1.5f; @@ -7435,25 +7985,27 @@ static void drawVertSlide(TransInfo *t) const int alpha_shade = -160; int i; - if (v3d && v3d->zbuf) - glDisable(GL_DEPTH_TEST); + GPU_depth_test(false); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GPU_blend(true); + GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - glPushAttrib(GL_CURRENT_BIT | GL_LINE_BIT | GL_POINT_BIT); - glPushMatrix(); + GPU_matrix_push(); + GPU_matrix_mul(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); - glMultMatrixf(t->obedit->obmat); + GPU_line_width(line_size); - glLineWidth(line_size); - UI_ThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); - glBegin(GL_LINES); + const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformThemeColorShadeAlpha(TH_EDGE_SELECT, 80, alpha_shade); + + immBegin(GPU_PRIM_LINES, sld->totsv * 2); 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]); + immVertex3fv(shdr_pos, sv->co_orig_3d); + immVertex3fv(shdr_pos, sv->co_link_orig_3d[sv->co_link_curr]); } } else { @@ -7466,21 +8018,21 @@ static void drawVertSlide(TransInfo *t) add_v3_v3(a, sv->co_orig_3d); add_v3_v3(b, sv->co_orig_3d); - glVertex3fv(a); - glVertex3fv(b); + immVertex3fv(shdr_pos, a); + immVertex3fv(shdr_pos, b); } } - glEnd(); + immEnd(); - glPointSize(ctrl_size); + GPU_point_size(ctrl_size); - glBegin(GL_POINTS); - glVertex3fv((sld->flipped && sld->use_even) ? + immBegin(GPU_PRIM_POINTS, 1); + immVertex3fv(shdr_pos, (slp->flipped && slp->use_even) ? curr_sv->co_link_orig_3d[curr_sv->co_link_curr] : curr_sv->co_orig_3d); - glEnd(); + immEnd(); - glDisable(GL_BLEND); + immUnbindProgram(); /* direction from active vertex! */ if ((t->mval[0] != t->mouse.imval[0]) || @@ -7494,73 +8046,86 @@ static void drawVertSlide(TransInfo *t) mval_ofs[0] = t->mval[0] - t->mouse.imval[0]; mval_ofs[1] = t->mval[1] - t->mouse.imval[1]; - mul_v3_m4v3(co_orig_3d, t->obedit->obmat, curr_sv->co_orig_3d); + mul_v3_m4v3(co_orig_3d, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat, curr_sv->co_orig_3d); zfac = ED_view3d_calc_zfac(t->ar->regiondata, co_orig_3d, NULL); ED_view3d_win_to_delta(t->ar, mval_ofs, co_dest_3d, zfac); - invert_m4_m4(t->obedit->imat, t->obedit->obmat); - mul_mat3_m4_v3(t->obedit->imat, co_dest_3d); + invert_m4_m4(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->obmat); + mul_mat3_m4_v3(TRANS_DATA_CONTAINER_FIRST_OK(t)->obedit->imat, co_dest_3d); add_v3_v3(co_dest_3d, curr_sv->co_orig_3d); - glLineWidth(1); - setlinestyle(1); + GPU_line_width(1.0f); + + immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR); - cpack(0xffffff); - glBegin(GL_LINES); - glVertex3fv(curr_sv->co_orig_3d); - glVertex3fv(co_dest_3d); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); - glEnd(); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniformColor4f(1.0f, 1.0f, 1.0f, 1.0f); + immUniform1f("dash_width", 6.0f); + immUniform1f("dash_factor", 0.5f); + + immBegin(GPU_PRIM_LINES, 2); + immVertex3fv(shdr_pos, curr_sv->co_orig_3d); + immVertex3fv(shdr_pos, co_dest_3d); + immEnd(); + + immUnbindProgram(); } - glPopMatrix(); - glPopAttrib(); + GPU_matrix_pop(); - if (v3d && v3d->zbuf) - glEnable(GL_DEPTH_TEST); + GPU_depth_test(true); } } } static void doVertSlide(TransInfo *t, float perc) { - VertSlideData *sld = t->custom.mode.data; - TransDataVertSlideVert *svlist = sld->sv, *sv; - int i; + VertSlideParams *slp = t->custom.mode.data; - sld->perc = perc; - sv = svlist; + slp->perc = perc; - if (sld->use_even == false) { - for (i = 0; i < sld->totsv; i++, sv++) { - interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc); + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + VertSlideData *sld = tc->custom.mode.data; + TransDataVertSlideVert *svlist = sld->sv, *sv; + int i; + + sv = svlist; + + if (slp->use_even == false) { + for (i = 0; i < sld->totsv; i++, sv++) { + interp_v3_v3v3(sv->v->co, sv->co_orig_3d, sv->co_link_orig_3d[sv->co_link_curr], perc); + } } - } - else { - TransDataVertSlideVert *sv_curr = &sld->sv[sld->curr_sv_index]; - const float edge_len_curr = len_v3v3(sv_curr->co_orig_3d, sv_curr->co_link_orig_3d[sv_curr->co_link_curr]); - const float tperc = perc * edge_len_curr; + 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]; + 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); + 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) { - madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); + if (edge_len > FLT_EPSILON) { + if (slp->flipped) { + madd_v3_v3v3fl(sv->v->co, sv->co_link_orig_3d[sv->co_link_curr], dir, -tperc); + } + else { + madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc); + } } else { - madd_v3_v3v3fl(sv->v->co, sv->co_orig_3d, dir, tperc); + copy_v3_v3(sv->v->co, sv->co_orig_3d); } } - else { - copy_v3_v3(sv->v->co, sv->co_orig_3d); - } } } } @@ -7570,9 +8135,9 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) char str[UI_MAX_DRAW_STR]; size_t ofs = 0; float final; - VertSlideData *sld = t->custom.mode.data; - const bool flipped = sld->flipped; - const bool use_even = sld->use_even; + VertSlideParams *slp = t->custom.mode.data; + const bool flipped = slp->flipped; + const bool use_even = slp->use_even; const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); @@ -7611,7 +8176,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -7645,7 +8210,6 @@ static void initBoneRoll(TransInfo *t) static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; int i; char str[UI_MAX_DRAW_STR]; @@ -7671,19 +8235,22 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) } /* set roll values */ - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - *(td->val) = td->ival - final; + *(td->val) = td->ival - final; + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -7712,7 +8279,6 @@ static void initBakeTime(TransInfo *t) static void applyBakeTime(TransInfo *t, const int mval[2]) { - TransData *td = t->data; float time; int i; char str[UI_MAX_DRAW_STR]; @@ -7756,23 +8322,26 @@ static void applyBakeTime(TransInfo *t, const int mval[2]) BLI_snprintf(str, sizeof(str), IFACE_("Time: %.3f %s"), time, t->proptext); } - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - if (td->val) { - *td->val = td->ival + time * td->factor; - if (td->ext->size && *td->val < *td->ext->size) *td->val = *td->ext->size; - if (td->ext->quat && *td->val > *td->ext->quat) *td->val = *td->ext->quat; + if (td->val) { + *td->val = td->ival + time * td->factor; + if (td->ext->size && *td->val < *td->ext->size) *td->val = *td->ext->size; + if (td->ext->quat && *td->val > *td->ext->quat) *td->val = *td->ext->quat; + } } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -7789,14 +8358,13 @@ static void initMirror(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_NONE); t->flag |= T_NULL_ONE; - if (!t->obedit) { + if ((t->flag & T_EDIT) == 0) { t->flag |= T_NO_ZERO; } } static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td; float size[3], mat[3][3]; int i; char str[UI_MAX_DRAW_STR]; @@ -7814,46 +8382,52 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) size_to_mat3(mat, size); if (t->con.applySize) { - t->con.applySize(t, NULL, mat); + t->con.applySize(t, NULL, NULL, mat); } BLI_snprintf(str, sizeof(str), IFACE_("Mirror%s"), t->con.text); - for (i = 0, td = t->data; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - ElementResize(t, td, mat); + ElementResize(t, tc, td, mat); + } } recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } else { size[0] = size[1] = size[2] = 1; size_to_mat3(mat, size); - for (i = 0, td = t->data; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - ElementResize(t, td, mat); + ElementResize(t, tc, td, mat); + } } recalcData(t); if (t->flag & T_2D_EDIT) - ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y)")); + ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y)")); else - ED_area_headerprint(t->sa, IFACE_("Select a mirror axis (X, Y, Z)")); + ED_area_status_text(t->sa, IFACE_("Select a mirror axis (X, Y, Z)")); } } /** \} */ @@ -7876,45 +8450,46 @@ static void initAlign(TransInfo *t) static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) { - TransData *td = t->data; float center[3]; int i; - /* saving original center */ - copy_v3_v3(center, t->center); - for (i = 0; i < t->total; i++, td++) { - float mat[3][3], invmat[3][3]; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + /* saving original center */ + copy_v3_v3(center, tc->center_local); + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float mat[3][3], invmat[3][3]; - if (td->flag & TD_NOACTION) - break; + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - /* around local centers */ - if (t->flag & (T_OBJECT | T_POSE)) { - copy_v3_v3(t->center, td->center); - } - else { - if (t->settings->selectmode & SCE_SELECT_FACE) { - copy_v3_v3(t->center, td->center); + /* around local centers */ + if (t->flag & (T_OBJECT | T_POSE)) { + copy_v3_v3(tc->center_local, td->center); + } + else { + if (t->settings->selectmode & SCE_SELECT_FACE) { + copy_v3_v3(tc->center_local, td->center); + } } - } - invert_m3_m3(invmat, td->axismtx); + invert_m3_m3(invmat, td->axismtx); - mul_m3_m3m3(mat, t->spacemtx, invmat); + mul_m3_m3m3(mat, t->spacemtx, invmat); - ElementRotation(t, td, mat, t->around); + ElementRotation(t, tc, td, mat, t->around); + } + /* restoring original center */ + copy_v3_v3(tc->center_local, center); } - /* restoring original center */ - copy_v3_v3(t->center, center); - recalcData(t); - ED_area_headerprint(t->sa, IFACE_("Align")); + ED_area_status_text(t->sa, IFACE_("Align")); } /** \} */ @@ -7972,17 +8547,19 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA static void applySeqSlideValue(TransInfo *t, const float val[2]) { - TransData *td = t->data; int i; - for (i = 0; i < t->total; i++, td++) { - if (td->flag & TD_NOACTION) - break; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_NOACTION) + break; - if (td->flag & TD_SKIP) - continue; + if (td->flag & TD_SKIP) + continue; - madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor); + madd_v2_v2v2fl(td->loc, td->iloc, val, td->factor); + } } } @@ -7995,7 +8572,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) if (t->con.mode & CON_APPLY) { float pvec[3] = {0.0f, 0.0f, 0.0f}; float tvec[3]; - t->con.applyVec(t, NULL, t->values, tvec, pvec); + t->con.applyVec(t, NULL, NULL, t->values, tvec, pvec); copy_v3_v3(t->values, tvec); } else { @@ -8011,7 +8588,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -8215,8 +8792,6 @@ static void headerTimeTranslate(TransInfo *t, char str[UI_MAX_DRAW_STR]) static void applyTimeTranslateValue(TransInfo *t) { - TransData *td = t->data; - TransData2D *td2d = t->data2d; Scene *scene = t->scene; int i; @@ -8225,46 +8800,50 @@ static void applyTimeTranslateValue(TransInfo *t) float deltax, val /* , valprev */; - /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ - for (i = 0; i < t->total; i++, td++, td2d++) { - /* it is assumed that td->extra is a pointer to the AnimData, - * whose active action is where this keyframe comes from - * (this is only valid when not in NLA) - */ - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + TransData2D *td2d = tc->data_2d; + /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ + for (i = 0; i < tc->data_len; i++, td++, td2d++) { + /* it is assumed that td->extra is a pointer to the AnimData, + * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) + */ + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - /* valprev = *td->val; */ /* UNUSED */ + /* valprev = *td->val; */ /* UNUSED */ - /* check if any need to apply nla-mapping */ - if (adt && (t->spacetype != SPACE_SEQ)) { - deltax = t->values[0]; + /* check if any need to apply nla-mapping */ + if (adt && (t->spacetype != SPACE_SEQ)) { + deltax = t->values[0]; - if (autosnap == SACTSNAP_TSTEP) { - deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf); - } - else if (autosnap == SACTSNAP_STEP) { - deltax = floorf(deltax + 0.5f); + if (autosnap == SACTSNAP_TSTEP) { + deltax = (float)(floor(((double)deltax / secf) + 0.5) * secf); + } + else if (autosnap == SACTSNAP_STEP) { + deltax = floorf(deltax + 0.5f); + } + + val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); + val += deltax * td->factor; + *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); } + else { + deltax = val = t->values[0]; - val = BKE_nla_tweakedit_remap(adt, td->ival, NLATIME_CONVERT_MAP); - val += deltax * td->factor; - *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); - } - else { - deltax = val = t->values[0]; + if (autosnap == SACTSNAP_TSTEP) { + val = (float)(floor(((double)deltax / secf) + 0.5) * secf); + } + else if (autosnap == SACTSNAP_STEP) { + val = floorf(val + 0.5f); + } - if (autosnap == SACTSNAP_TSTEP) { - val = (float)(floor(((double)deltax / secf) + 0.5) * secf); - } - else if (autosnap == SACTSNAP_STEP) { - val = floorf(val + 0.5f); + *(td->val) = td->ival + val; } - *(td->val) = td->ival + val; + /* apply nearest snapping */ + doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); } - - /* apply nearest snapping */ - doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); } } @@ -8293,7 +8872,7 @@ static void applyTimeTranslate(TransInfo *t, const int mval[2]) recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -8331,18 +8910,19 @@ static void initTimeSlide(TransInfo *t) float min = 999999999.0f, max = -999999999.0f; int i; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + float val = *(td->val); - TransData *td = t->data; - for (i = 0; i < t->total; i++, td++) { - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - float val = *(td->val); - - /* strip/action time to global (mapped) time */ - if (adt) - val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP); + /* strip/action time to global (mapped) time */ + if (adt) + val = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_MAP); - if (min > val) min = val; - if (max < val) max = val; + if (min > val) min = val; + if (max < val) max = val; + } } if (min == max) { @@ -8395,7 +8975,6 @@ static void headerTimeSlide(TransInfo *t, const float sval, char str[UI_MAX_DRAW static void applyTimeSlideValue(TransInfo *t, float sval) { - TransData *td = t->data; int i; const float *range = t->custom.mode.data; float minx = range[0]; @@ -8410,44 +8989,47 @@ static void applyTimeSlideValue(TransInfo *t, float sval) } /* it doesn't matter whether we apply to t->data or t->data2d, but t->data2d is more convenient */ - for (i = 0; i < t->total; i++, td++) { - /* it is assumed that td->extra is a pointer to the AnimData, - * whose active action is where this keyframe comes from - * (this is only valid when not in NLA) - */ - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - float cval = t->values[0]; - - /* only apply to data if in range */ - if ((sval > minx) && (sval < maxx)) { - float cvalc = CLAMPIS(cval, minx, maxx); - float ival = td->ival; - float timefac; - - /* NLA mapping magic here works as follows: - * - "ival" goes from strip time to global time - * - calculation is performed into td->val in global time - * (since sval and min/max are all in global time) - * - "td->val" then gets put back into strip time + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + /* it is assumed that td->extra is a pointer to the AnimData, + * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) */ - if (adt) { - /* strip to global */ - ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP); - } + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + float cval = t->values[0]; + + /* only apply to data if in range */ + if ((sval > minx) && (sval < maxx)) { + float cvalc = CLAMPIS(cval, minx, maxx); + float ival = td->ival; + float timefac; + + /* NLA mapping magic here works as follows: + * - "ival" goes from strip time to global time + * - calculation is performed into td->val in global time + * (since sval and min/max are all in global time) + * - "td->val" then gets put back into strip time + */ + if (adt) { + /* strip to global */ + ival = BKE_nla_tweakedit_remap(adt, ival, NLATIME_CONVERT_MAP); + } - /* left half? */ - if (ival < sval) { - timefac = (sval - ival) / (sval - minx); - *(td->val) = cvalc - timefac * (cvalc - minx); - } - else { - timefac = (ival - sval) / (maxx - sval); - *(td->val) = cvalc + timefac * (maxx - cvalc); - } + /* left half? */ + if (ival < sval) { + timefac = (sval - ival) / (sval - minx); + *(td->val) = cvalc - timefac * (cvalc - minx); + } + else { + timefac = (ival - sval) / (maxx - sval); + *(td->val) = cvalc + timefac * (maxx - cvalc); + } - if (adt) { - /* global to strip */ - *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP); + if (adt) { + /* global to strip */ + *(td->val) = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_UNMAP); + } } } } @@ -8480,7 +9062,7 @@ static void applyTimeSlide(TransInfo *t, const int mval[2]) recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -8508,8 +9090,8 @@ static void initTimeScale(TransInfo *t) /* recalculate center2d to use CFRA and mouse Y, since that's * what is used in time scale */ if ((t->flag & T_OVERRIDE_CENTER) == 0) { - t->center[0] = t->scene->r.cfra; - projectFloatView(t, t->center, center); + t->center_global[0] = t->scene->r.cfra; + projectFloatView(t, t->center_global, center); center[1] = t->mouse.imval[1]; } @@ -8550,39 +9132,40 @@ static void headerTimeScale(TransInfo *t, char str[UI_MAX_DRAW_STR]) static void applyTimeScaleValue(TransInfo *t) { Scene *scene = t->scene; - TransData *td = t->data; - TransData2D *td2d = t->data2d; int i; const short autosnap = getAnimEdit_SnapMode(t); const double secf = FPS; + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + TransData2D *td2d = tc->data_2d; + for (i = 0; i < tc->data_len; i++, td++, td2d++) { + /* it is assumed that td->extra is a pointer to the AnimData, + * whose active action is where this keyframe comes from + * (this is only valid when not in NLA) + */ + AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; + float startx = CFRA; + float fac = t->values[0]; - for (i = 0; i < t->total; i++, td++, td2d++) { - /* it is assumed that td->extra is a pointer to the AnimData, - * whose active action is where this keyframe comes from - * (this is only valid when not in NLA) - */ - AnimData *adt = (t->spacetype != SPACE_NLA) ? td->extra : NULL; - float startx = CFRA; - float fac = t->values[0]; - - if (autosnap == SACTSNAP_TSTEP) { - fac = (float)(floor((double)fac / secf + 0.5) * secf); - } - else if (autosnap == SACTSNAP_STEP) { - fac = floorf(fac + 0.5f); - } + if (autosnap == SACTSNAP_TSTEP) { + fac = (float)(floor((double)fac / secf + 0.5) * secf); + } + else if (autosnap == SACTSNAP_STEP) { + fac = floorf(fac + 0.5f); + } - /* check if any need to apply nla-mapping */ - if (adt) - startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP); + /* check if any need to apply nla-mapping */ + if (adt) + startx = BKE_nla_tweakedit_remap(adt, startx, NLATIME_CONVERT_UNMAP); - /* now, calculate the new value */ - *(td->val) = ((td->ival - startx) * fac) + startx; + /* now, calculate the new value */ + *(td->val) = ((td->ival - startx) * fac) + startx; - /* apply nearest snapping */ - doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); + /* apply nearest snapping */ + doAnimEdit_SnapFrame(t, td, td2d, adt, autosnap); + } } } @@ -8600,7 +9183,7 @@ static void applyTimeScale(TransInfo *t, const int UNUSED(mval[2])) recalcData(t); - ED_area_headerprint(t->sa, str); + ED_area_status_text(t->sa, str); } /** \} */ @@ -8611,7 +9194,7 @@ bool checkUseAxisMatrix(TransInfo *t) /* currently only checks for editmode */ if (t->flag & T_EDIT) { if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && - (ELEM(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) + (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) { /* not all editmode supports axis-matrix */ return true; |