Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Sun, 13 May 2018 04:56:51 +0000 (06:56 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 13 May 2018 04:56:51 +0000 (06:56 +0200)
1  2 
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_constraints.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_input.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/transform/transform_orientations.c
source/blender/editors/transform/transform_snap.c

@@@ -1867,8 -1810,8 +1867,8 @@@ static void drawHelpline(bContext *UNUS
  static void drawTransformView(const struct bContext *C, ARegion *UNUSED(ar), void *arg)
  {
        TransInfo *t = arg;
-       
 -      glLineWidth(1.0);
 +      glLineWidth(1.0f);
  
        drawConstraint(t);
        drawPropCircle(C, t);
@@@ -1889,12 -1832,11 +1889,12 @@@ static void drawAutoKeyWarning(TransInf
  
        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);
-       
        /* warning text (to clarify meaning of overlays)
         * - original color was red to match the icon, but that clashes badly with a less nasty border
         */
  #else
        BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX);
  #endif
-       
        /* autokey recording icon... */
 -      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 +      glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
-       
        xco -= U.widget_unit;
        yco -= (int)printable_size[1] / 2;
  
  }
  
  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), 
+       /* draw autokeyframing hint in the corner
+        * - only draw if enabled (advanced users may be distracted/annoyed),
         *   for objects that will be autokeyframed (no point ohterwise),
         *   AND only for the active region (as showing all is too overwhelming)
         */
@@@ -2695,13 -2619,13 +2695,13 @@@ static void constraintTransLim(TransInf
                                        /* skip... incompatable spacetype */
                                        continue;
                                }
-                               
                                /* 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);
-                               
                                /* convert spaces again */
                                if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
                                        /* just multiply by td->smtx (this should be ok) */
@@@ -3036,13 -2964,13 +3036,13 @@@ static void Bend(TransInfo *t, const in
                             RAD2DEGF(values.angle), values.scale * data->warp_init_dist,
                             WM_bool_as_string(is_clamp));
        }
-       
        values.angle *= -1.0f;
        values.scale *= data->warp_init_dist;
-       
        /* calc 'data->warp_end' from 'data->warp_end_init' */
 -      copy_v3_v3(warp_end_radius, 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 */
@@@ -3399,11 -3302,11 +3399,11 @@@ static void ElementResize(TransInfo *t
        else {
                copy_m3_m3(tmat, mat);
        }
-       
        if (t->con.applySize) {
 -              t->con.applySize(t, td, tmat);
 +              t->con.applySize(t, tc, td, tmat);
        }
-       
        /* local constraint shouldn't alter center */
        if (transdata_check_local_center(t, t->around)) {
                copy_v3_v3(center, td->center);
@@@ -3510,28 -3422,25 +3510,28 @@@ static void applyResize(TransInfo *t, c
  
                applySnapping(t, t->values);
        }
-       
        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
-       
        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 */
                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);
  }
  /** \} */
@@@ -3623,41 -3529,38 +3623,41 @@@ static void applySkinResize(TransInfo *
        if (t->flag & T_AUTOVALUES) {
                copy_v3_v3(size, t->auto_values);
        }
-       
        copy_v3_v3(t->values, size);
-       
        size_to_mat3(mat, size);
-       
        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);
  
  static void initToSphere(TransInfo *t)
  {
 -      TransData *td = t->data;
        int i;
-       
        t->mode = TFM_TOSPHERE;
        t->transform = applyToSphere;
-       
        initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
-       
        t->idx_max = 0;
        t->num.idx_max = 0;
        t->snap[0] = 0.0f;
@@@ -3712,15 -3613,16 +3712,15 @@@ static void applyToSphere(TransInfo *t
        float ratio, radius;
        int i;
        char str[UI_MAX_DRAW_STR];
 -      TransData *td = t->data;
  
        ratio = t->values[0];
-       
        snapGridIncrement(t, &ratio);
-       
        applyNumInput(&t->num, &ratio);
-       
        CLAMP(ratio, 0.0f, 1.0f);
-       
        t->values[0] = ratio;
  
        /* header print for NumInput */
                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);
  }
  /** \} */
@@@ -3867,16 -3770,18 +3867,16 @@@ static void ElementRotation_ex(TransInf
  
                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 */
-                       
                        sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location
-                       
                        /* special exception, see TD_PBONE_LOCAL_MTX definition comments */
                        if (td->flag & TD_PBONE_LOCAL_MTX_P) {
                                /* do nothing */
@@@ -4045,31 -3950,29 +4045,31 @@@ static void ElementRotation(TransInfo *
  
  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);
 +              }
        }
  }
  
@@@ -5364,10 -5245,19 +5364,10 @@@ static void applyBoneSize(TransInfo *t
        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);
-       
        if (applyNumInput(&t->num, size)) {
                constraintNumInput(t, size);
        }
        copy_v3_v3(t->values, size);
  
        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
-       
        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);
@@@ -6818,10 -6711,10 +6818,10 @@@ void freeEdgeSlideTempFaces(EdgeSlideDa
        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;
-       
        if (!sld)
                return;
  
@@@ -503,11 -446,10 +503,11 @@@ typedef struct TransInfo 
        short           launch_event;   /* event type used to launch transform */
  
        short           current_orientation;
 -      short           twtype;                 /* backup from view3d, to restore on end */
 +      TransformOrientation *custom_orientation; /* this gets used when current_orientation is V3D_MANIP_CUSTOM */
 +      short           twflag;                 /* backup from view3d, to restore on end */
  
        short           prop_mode;
-       
        short           mirror;
  
        float           values[4];
@@@ -3308,11 -3225,9 +3308,11 @@@ static void createTransNlaData(bContex
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
        int filter;
-       
        int count = 0;
  
 +      TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
 +
        /* determine what type of data we are operating on */
        if (ANIM_animdata_get_context(C, &ac) == 0)
                return;
                ANIM_animdata_freelist(&anim_data);
                return;
        }
-       
        /* allocate memory for data */
 -      t->total = count;
 +      tc->data_len = count;
-       
 -      t->data = MEM_callocN(t->total * sizeof(TransData), "TransData(NLA Editor)");
 -      td = t->data;
 -      t->custom.type.data = tdn = MEM_callocN(t->total * sizeof(TransDataNla), "TransDataNla (NLA Editor)");
 -      t->custom.type.use_free = true;
 +      tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(NLA Editor)");
 +      td = tc->data;
 +      tc->custom.type.data = tdn = MEM_callocN(tc->data_len * sizeof(TransDataNla), "TransDataNla (NLA Editor)");
 +      tc->custom.type.use_free = true;
-       
        /* loop 2: build transdata array */
        for (ale = anim_data.first; ale; ale = ale->next) {
                /* only if a real NLA-track */
@@@ -4068,21 -3983,19 +4068,21 @@@ static void createTransActionData(bCont
                return;
        }
  
 +      TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
 +
        /* allocate memory for data */
 -      t->total = count;
 +      tc->data_len = count;
-       
 -      t->data = MEM_callocN(t->total * sizeof(TransData), "TransData(Action Editor)");
 -      t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "transdata2d");
 -      td = t->data;
 -      td2d = t->data2d;
 +      tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(Action Editor)");
 +      tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "transdata2d");
 +      td = tc->data;
 +      td2d = tc->data_2d;
-       
        if (ELEM(ac.datatype, ANIMCONT_GPENCIL, ANIMCONT_MASK)) {
 -              t->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
 -              t->custom.type.use_free = true;
 +              tc->custom.type.data = tfd = MEM_callocN(sizeof(tGPFtransdata) * count, "tGPFtransdata");
 +              tc->custom.type.use_free = true;
        }
-       
        /* loop 2: build transdata array */
        for (ale = anim_data.first; ale; ale = ale->next) {
  
@@@ -4468,21 -4381,19 +4468,21 @@@ static void createTransGraphEditData(bC
                return;
        }
  
 +      TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
 +
        /* allocate memory for data */
 -      t->total = count;
 +      tc->data_len = count;
-       
 -      t->data = MEM_callocN(t->total * sizeof(TransData), "TransData (Graph Editor)");
 +      tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData (Graph Editor)");
        /* for each 2d vert a 3d vector is allocated, so that they can be treated just as if they were 3d verts */
 -      t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransData2D (Graph Editor)");
 -      t->custom.type.data = MEM_callocN(t->total * sizeof(TransDataGraph), "TransDataGraph");
 -      t->custom.type.use_free = true;
 +      tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransData2D (Graph Editor)");
 +      tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataGraph), "TransDataGraph");
 +      tc->custom.type.use_free = true;
-       
 -      td = t->data;
 -      td2d = t->data2d;
 -      tdg = t->custom.type.data;
 +      td = tc->data;
 +      td2d = tc->data_2d;
 +      tdg = tc->custom.type.data;
-       
        /* precompute space-conversion matrices for dealing with non-uniform scaling of Graph Editor */
        unit_m3(mtx);
        unit_m3(smtx);
@@@ -4771,20 -4680,20 +4771,20 @@@ static void beztmap_to_data(TransInfo *
         * pointers have been fixed already, so that we don't override ones that are
         * already done
         */
 -      adjusted = MEM_callocN(t->total, "beztmap_adjusted_map");
 +      adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map");
-       
        /* for each beztmap item, find if it is used anywhere */
        bezm = bezms;
        for (i = 0; i < totvert; i++, bezm++) {
                /* loop through transdata, testing if we have a hit
                 * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped...
                 */
 -              td2d = t->data2d;
 -              td = t->data;
 -              for (j = 0; j < t->total; j++, td2d++, td++) {
 +              td2d = tc->data_2d;
 +              td = tc->data;
 +              for (j = 0; j < tc->data_len; j++, td2d++, td++) {
                        /* skip item if already marked */
                        if (adjusted[j] != 0) continue;
-                       
                        /* update all transdata pointers, no need to check for selections etc,
                         * since only points that are really needed were created as transdata
                         */
@@@ -5929,30 -5828,26 +5929,30 @@@ void autokeyframe_ob_cb_func(bContext *
                                do_loc = true;
                        }
                        else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
 -                              if (v3d->around == V3D_AROUND_ACTIVE) {
 -                                      if (ob != OBACT)
 +                              if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
 +                                      if (ob != OBACT(view_layer))
                                                do_loc = true;
                                }
 -                              else if (v3d->around == V3D_AROUND_CURSOR)
 +                              else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
                                        do_loc = true;
-                               
 +                              }
 -                              if ((v3d->flag & V3D_ALIGN) == 0)
 +                              if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
                                        do_rot = true;
 +                              }
                        }
                        else if (tmode == TFM_RESIZE) {
 -                              if (v3d->around == V3D_AROUND_ACTIVE) {
 -                                      if (ob != OBACT)
 +                              if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) {
 +                                      if (ob != OBACT(view_layer))
                                                do_loc = true;
                                }
 -                              else if (v3d->around == V3D_AROUND_CURSOR)
 +                              else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) {
                                        do_loc = true;
 +                              }
  
 -                              if ((v3d->flag & V3D_ALIGN) == 0)
 +                              if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) {
                                        do_scale = true;
 +                              }
                        }
  
                        /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */
@@@ -6443,11 -6328,11 +6443,11 @@@ void special_aftertrans_update(bContex
                        // fixme... some of this stuff is not good
                        if (ob) {
                                if (ob->pose || BKE_key_from_object(ob))
 -                                      DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
 +                                      DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
                                else
 -                                      DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 +                                      DEG_id_tag_update(&ob->id, OB_RECALC_OB);
                        }
-                       
                        /* 3 cases here for curve cleanups:
                         * 1) NOTRANSKEYCULL on     -> cleanup of duplicates shouldn't be done
                         * 2) canceled == 0        -> user confirmed the transform, so duplicates should be removed
  
                        /* Set autokey if necessary */
                        if (!canceled) {
 -                              autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode);
 +                              autokeyframe_ob_cb_func(C, t->scene, t->view_layer, ob, t->mode);
                        }
-                       
                        /* restore rigid body transform */
                        if (ob->rigidbody_object && canceled) {
                                float ctime = BKE_scene_frame_get(t->scene);
@@@ -6767,23 -6641,21 +6767,23 @@@ static void createTransObject(bContext 
  
        set_trans_object_base_flags(t);
  
 +      TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
 +
        /* count */
 -      t->total = CTX_DATA_COUNT(C, selected_objects);
 +      tc->data_len = CTX_DATA_COUNT(C, selected_objects);
-       
 -      if (!t->total) {
 +      if (!tc->data_len) {
                /* clear here, main transform function escapes too */
                clear_trans_object_base_flags(t);
                return;
        }
-       
        if (is_prop_edit) {
 -              t->total += count_proportional_objects(t);
 +              tc->data_len += count_proportional_objects(t);
        }
  
 -      td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransOb");
 -      tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransObExtension");
 +      td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb");
 +      tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension");
  
        CTX_DATA_BEGIN(C, Base *, base, selected_bases)
        {
                tx++;
        }
        CTX_DATA_END;
-       
        if (is_prop_edit) {
 -              View3D *v3d = t->view;
 +              ViewLayer *view_layer = t->view_layer;
                Base *base;
  
 -              for (base = scene->base.first; base; base = base->next) {
 +              for (base = view_layer->object_bases.first; base; base = base->next) {
                        Object *ob = base->object;
  
                        /* if base is not selected, not a parent of selection or not a child of selection and it is editable */
@@@ -8058,12 -7907,12 +8058,12 @@@ static void createTransGPencil(bContex
         * For now, we just do these without creating TransData2D for the 2D
         * strokes. This may cause issues in future though.
         */
 -      t->total = 0;
 +      tc->data_len = 0;
-       
        if (gpd == NULL)
                return;
-       
-       /* First Pass: Count the number of datapoints required for the strokes, 
+       /* First Pass: Count the number of datapoints required for the strokes,
         * (and additional info about the configuration - e.g. 2D/3D?)
         */
        for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
                                                // TODO: 2D vs 3D?
                                                for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
                                                        if (pt->flag & GP_SPOINT_SELECT)
 -                                                              t->total++;
 +                                                              tc->data_len++;
                                                }
                                        }
-                               }                               
+                               }
                        }
                }
        }
-       
        /* Stop trying if nothing selected */
 -      if (t->total == 0) {
 +      if (tc->data_len == 0) {
                return;
        }
-       
        /* Allocate memory for data */
 -      t->data = MEM_callocN(t->total * sizeof(TransData), "TransData(GPencil)");
 -      td = t->data;
 +      tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(GPencil)");
 +      td = tc->data;
-       
        unit_m3(smtx);
        unit_m3(mtx);
-       
        /* Second Pass: Build transdata array */
        for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
                /* only editable and visible layers are considered */
@@@ -8345,11 -8159,9 +8345,11 @@@ void createTransData(bContext *C, Trans
        else if (t->options & CTX_GPENCIL_STROKES) {
                t->options |= CTX_GPENCIL_STROKES;
                t->flag |= T_POINTS;
 +
                createTransGPencil(C, t);
-               
 +              countAndCleanTransDataContainer(t);
 -              if (t->data && (t->flag & T_PROP_EDIT)) {
 +              if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
                        sort_trans_data(t); // makes selected become first in array
                        set_prop_dist(t, 1);
                        sort_trans_data_dist(t);
                        }
                }
                else if (t->options & CTX_PAINT_CURVE) {
 -                      if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN))
 +                      if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
                                createTransPaintCurveVerts(C, t);
 +                              countAndCleanTransDataContainer(t);
 +                      }
                }
 -              else if (t->obedit) {
 +              else if (t->obedit_type == OB_MESH) {
 +
 +                      initTransDataContainers_FromObjectData(t);
                        createTransUVs(C, t);
 -                      if (t->data && (t->flag & T_PROP_EDIT)) {
 +                      countAndCleanTransDataContainer(t);
-       
++
 +                      t->flag |= T_EDIT;
 +
 +                      if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
                                sort_trans_data(t); // makes selected become first in array
                                set_prop_dist(t, 1);
                                sort_trans_data_dist(t);
                 * lines below just check is also visible */
                Object *ob_armature = modifiers_isDeformedByArmature(ob);
                if (ob_armature && ob_armature->mode & OB_MODE_POSE) {
 -                      Base *base_arm = BKE_scene_base_find(t->scene, ob_armature);
 +                      Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature);
                        if (base_arm) {
 -                              View3D *v3d = t->view;
 -                              if (BASE_VISIBLE(v3d, base_arm)) {
 -                                      createTransPose(t, ob_armature);
 +                              if (BASE_VISIBLE(base_arm)) {
 +                                      Object *objects[1];
 +                                      objects[0] = ob_armature;
 +                                      uint objects_len = 1;
 +                                      createTransPose(t, objects, objects_len);
 +                                      countAndCleanTransDataContainer(t);
                                }
                        }
-                       
                }
        }
        else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
@@@ -349,9 -338,9 +349,9 @@@ static bool fcu_test_selected(FCurve *f
  /* helper for recalcData() - for Action Editor transforms */
  static void recalcData_actedit(TransInfo *t)
  {
 -      Scene *scene = t->scene;
 +      ViewLayer *view_layer = t->view_layer;
        SpaceAction *saction = (SpaceAction *)t->sa->spacedata.first;
-       
        bAnimContext ac = {NULL};
        ListBase anim_data = {NULL, NULL};
        bAnimListElem *ale;
  static void recalcData_graphedit(TransInfo *t)
  {
        SpaceIpo *sipo = (SpaceIpo *)t->sa->spacedata.first;
 -      Scene *scene;
 +      ViewLayer *view_layer = t->view_layer;
-       
        ListBase anim_data = {NULL, NULL};
        bAnimContext ac = {NULL};
        int filter;
@@@ -687,9 -672,9 +687,9 @@@ static void recalcData_image(TransInfo 
        else if (t->options & CTX_PAINT_CURVE) {
                flushTransPaintCurve(t);
        }
 -      else if (t->obedit && t->obedit->type == OB_MESH) {
 +      else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
                SpaceImage *sima = t->sa->spacedata.first;
-               
                flushTransUVs(t);
                if (sima->flag & SI_LIVE_UNWRAP)
                        ED_uvedit_live_unwrap_re_solve();
@@@ -1102,8 -1054,11 +1102,8 @@@ void drawLine(TransInfo *t, const floa
  
        if (t->spacetype == SPACE_VIEW3D) {
                View3D *v3d = t->view;
-               
 -              glPushMatrix();
 -
 -              //if (t->obedit) glLoadMatrixf(t->obedit->obmat);       // sets opengl viewing
 -
 +              gpuPushMatrix();
  
                copy_v3_v3(v3, dir);
                mul_v3_fl(v3, v3d->far);
@@@ -1238,20 -1141,21 +1238,20 @@@ void initTransInfo(bContext *C, TransIn
        t->settings = ts;
        t->reports = op ? op->reports : NULL;
  
 -      if (obedit) {
 -              copy_m3_m4(t->obedit_mat, obedit->obmat);
 -              normalize_m3(t->obedit_mat);
 -      }
 -
 -      t->data = NULL;
 -      t->ext = NULL;
 -
        t->helpline = HLP_NONE;
-       
        t->flag = 0;
  
 +      t->obedit_type = (object_mode == OB_MODE_EDIT) ? object_type : -1;
 +
 +      /* Many kinds of transform only use a single handle. */
 +      if (t->data_container == NULL) {
 +              t->data_container = MEM_callocN(sizeof(*t->data_container), __func__);
 +              t->data_container_len = 1;
 +      }
 +
        t->redraw = TREDRAW_HARD;  /* redraw first time */
-       
        if (event) {
                t->mouse.imval[0] = event->mval[0];
                t->mouse.imval[1] = event->mval[1];
                t->mouse.imval[0] = 0;
                t->mouse.imval[1] = 0;
        }
-       
        t->con.imval[0] = t->mouse.imval[0];
        t->con.imval[1] = t->mouse.imval[1];
-       
        t->mval[0] = t->mouse.imval[0];
        t->mval[1] = t->mouse.imval[1];
-       
        t->transform        = NULL;
        t->handleEvent      = NULL;
-       
 -      t->total            = 0;
 +      t->data_len_all = 0;
-       
        t->val = 0.0f;
  
        zero_v3(t->vec);
        if (t->spacetype == SPACE_VIEW3D) {
                View3D *v3d = sa->spacedata.first;
                bScreen *animscreen = ED_screen_animation_playing(CTX_wm_manager(C));
-               
                t->view = v3d;
                t->animtimer = (animscreen) ? animscreen->animtimer : NULL;
-               
                /* turn manipulator off during transform */
 -              // FIXME: but don't do this when USING the manipulator...
                if (t->flag & T_MODAL) {
 -                      t->twtype = v3d->twtype;
 -                      v3d->twtype = 0;
 +                      t->twflag = v3d->twflag;
 +                      v3d->twflag = 0;
                }
  
 -              if (v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
 -              t->around = v3d->around;
 +              if (t->scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) {
 +                      t->flag |= T_V3D_ALIGN;
 +              }
 +              t->around = t->scene->toolsettings->transform_pivot_point;
  
                /* bend always uses the cursor */
                if (t->mode == TFM_BEND) {
@@@ -1636,30 -1500,29 +1636,30 @@@ void postTrans(bContext *C, TransInfo *
        }
  
        /* postTrans can be called when nothing is selected, so data is NULL already */
 -      if (t->data) {
 -
 -              /* free data malloced per trans-data */
 -              if ((t->obedit && ELEM(t->obedit->type, OB_CURVE, OB_SURF)) ||
 -                  (t->spacetype == SPACE_IPO))
 -              {
 -                      int a;
 -                      for (a = 0, td = t->data; a < t->total; a++, td++) {
 -                              if (td->flag & TD_BEZTRIPLE) {
 -                                      MEM_freeN(td->hdata);
 +      if (t->data_len_all != 0) {
 +              FOREACH_TRANS_DATA_CONTAINER (t, tc) {
 +                      /* free data malloced per trans-data */
 +                      if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) ||
 +                          (t->spacetype == SPACE_IPO))
 +                      {
 +                              TransData *td = tc->data;
 +                              for (int a = 0; a < tc->data_len; a++, td++) {
 +                                      if (td->flag & TD_BEZTRIPLE) {
 +                                              MEM_freeN(td->hdata);
 +                                      }
                                }
                        }
-       
 +                      MEM_freeN(tc->data);
++
 +                      MEM_SAFE_FREE(tc->data_ext);
 +                      MEM_SAFE_FREE(tc->data_2d);
                }
 -              MEM_freeN(t->data);
        }
-       
 -      BLI_freelistN(&t->tsnap.points);
 +      MEM_SAFE_FREE(t->data_container);
 +      t->data_container = NULL;
  
 -      if (t->ext) MEM_freeN(t->ext);
 -      if (t->data2d) {
 -              MEM_freeN(t->data2d);
 -              t->data2d = NULL;
 -      }
 +      BLI_freelistN(&t->tsnap.points);
  
        if (t->spacetype == SPACE_IMAGE) {
                if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
                View3D *v3d = t->sa->spacedata.first;
                /* restore manipulator */
                if (t->flag & T_MODAL) {
 -                      v3d->twtype = t->twtype;
 +                      v3d->twflag = t->twflag;
                }
        }
-       
        if (t->mouse.data) {
                MEM_freeN(t->mouse.data);
        }
@@@ -1741,30 -1602,26 +1741,30 @@@ static void restoreElement(TransData *t
  
  void restoreTransObjects(TransInfo *t)
  {
 -      TransData *td;
 -      TransData2D *td2d;
 +      FOREACH_TRANS_DATA_CONTAINER (t, tc) {
  
 -      for (td = t->data; td < t->data + t->total; td++) {
 -              restoreElement(td);
 -      }
 +              TransData *td;
 +              TransData2D *td2d;
  
 -      for (td2d = t->data2d; t->data2d && td2d < t->data2d + t->total; td2d++) {
 -              if (td2d->h1) {
 -                      td2d->h1[0] = td2d->ih1[0];
 -                      td2d->h1[1] = td2d->ih1[1];
 +              for (td = tc->data; td < tc->data + tc->data_len; td++) {
 +                      restoreElement(td);
                }
 -              if (td2d->h2) {
 -                      td2d->h2[0] = td2d->ih2[0];
 -                      td2d->h2[1] = td2d->ih2[1];
 +
 +              for (td2d = tc->data_2d; tc->data_2d && td2d < tc->data_2d + tc->data_len; td2d++) {
 +                      if (td2d->h1) {
 +                              td2d->h1[0] = td2d->ih1[0];
 +                              td2d->h1[1] = td2d->ih1[1];
 +                      }
 +                      if (td2d->h2) {
 +                              td2d->h2[0] = td2d->ih2[0];
 +                              td2d->h2[1] = td2d->ih2[1];
 +                      }
                }
 -      }
  
 -      unit_m3(t->mat);
 +              unit_m3(t->mat);
 +
 +      }
-       
        recalcData(t);
  }
  
@@@ -1792,12 -1660,21 +1792,12 @@@ void calculateCenterLocal
  void calculateCenterCursor(TransInfo *t, float r_center[3])
  {
        const float *cursor;
-       
 -      cursor = ED_view3d_cursor3d_get(t->scene, t->view);
 +      cursor = ED_view3d_cursor3d_get(t->scene, t->view)->location;
        copy_v3_v3(r_center, cursor);
-       
        /* If edit or pose mode, move cursor in local space */
 -      if (t->flag & (T_EDIT | T_POSE)) {
 -              Object *ob = t->obedit ? t->obedit : t->poseobj;
 -              float mat[3][3], imat[3][3];
 -
 -              sub_v3_v3v3(r_center, r_center, ob->obmat[3]);
 -              copy_m3_m4(mat, ob->obmat);
 -              invert_m3_m3(imat, mat);
 -              mul_m3_v3(imat, r_center);
 -      }
 -      else if (t->options & CTX_PAINT_CURVE) {
 +      if (t->options & CTX_PAINT_CURVE) {
                if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
                        r_center[0] = t->ar->winx / 2.0f;
                        r_center[1] = t->ar->winy / 2.0f;
@@@ -2037,17 -1889,18 +2037,17 @@@ void calculateCenter(TransInfo *t
                                /* persinv is nasty, use viewinv instead, always right */
                                copy_v3_v3(axis, t->viewinv[2]);
                                normalize_v3(axis);
-                               
                                /* 6.0 = 6 grid units */
 -                              axis[0] = t->center[0] - 6.0f * axis[0];
 -                              axis[1] = t->center[1] - 6.0f * axis[1];
 -                              axis[2] = t->center[2] - 6.0f * axis[2];
 +                              axis[0] = t->center_global[0] - 6.0f * axis[0];
 +                              axis[1] = t->center_global[1] - 6.0f * axis[1];
 +                              axis[2] = t->center_global[2] - 6.0f * axis[2];
-                               
                                projectFloatView(t, axis, t->center2d);
-                               
                                /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
                                if (t->mode == TFM_TRANSLATION) {
 -                                      copy_v3_v3(t->center, axis);
 -                                      copy_v3_v3(t->center_global, t->center);
 +                                      copy_v3_v3(t->center_global, axis);
                                }
                        }
                }
@@@ -159,48 -157,42 +159,48 @@@ void drawSnapping(const struct bContex
                        RegionView3D *rv3d = CTX_wm_region_view3d(C);
                        float imat[4][4];
                        float size;
-                       
                        glDisable(GL_DEPTH_TEST);
-                       
                        size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
-                       
                        invert_m4_m4(imat, rv3d->viewmat);
  
 +                      unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
 +
 +                      immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
 +
                        for (p = t->tsnap.points.first; p; p = p->next) {
                                if (p == t->tsnap.selectedPoint) {
 -                                      glColor4ubv(selectedCol);
 +                                      immUniformColor4ubv(selectedCol);
                                }
                                else {
 -                                      glColor4ubv(col);
 +                                      immUniformColor4ubv(col);
                                }
-                               
 -                              drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat);
 +                              imm_drawcircball(p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat, pos);
                        }
-                       
                        if (t->tsnap.status & POINT_INIT) {
 -                              glColor4ubv(activeCol);
 +                              immUniformColor4ubv(activeCol);
-                               
 -                              drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat);
 +                              imm_drawcircball(t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat, pos);
                        }
-                       
                        /* draw normal if needed */
                        if (usingSnappingNormal(t) && validSnappingNormal(t)) {
 -                              glColor4ubv(activeCol);
 -
 -                              glBegin(GL_LINES);
 -                              glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
 -                              glVertex3f(t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
 -                                         t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
 -                                         t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
 -                              glEnd();
 +                              immUniformColor4ubv(activeCol);
-                               
++
 +                              immBegin(GWN_PRIM_LINES, 2);
 +                              immVertex3f(pos, t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
 +                              immVertex3f(pos, t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
 +                                          t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
 +                                          t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
 +                              immEnd();
                        }
  
 +                      immUnbindProgram();
 +
                        if (v3d->zbuf)
                                glEnable(GL_DEPTH_TEST);
                }
                        ARegion *ar = CTX_wm_region(C);
                        TransSnapPoint *p;
                        float size;
-                       
                        size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
-                       
                        glEnable(GL_BLEND);
-                       
 +                      unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
 +
 +                      immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 +
                        for (p = t->tsnap.points.first; p; p = p->next) {
                                if (p == t->tsnap.selectedPoint) {
 -                                      glColor4ubv(selectedCol);
 +                                      immUniformColor4ubv(selectedCol);
                                }
                                else {
 -                                      glColor4ubv(col);
 +                                      immUniformColor4ubv(col);
                                }
-                               
 -                              ED_node_draw_snap(&ar->v2d, p->co, size, 0);
 +                              ED_node_draw_snap(&ar->v2d, p->co, size, 0, pos);
                        }
-                       
                        if (t->tsnap.status & POINT_INIT) {
 -                              glColor4ubv(activeCol);
 +                              immUniformColor4ubv(activeCol);
-                               
 -                              ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder);
 +                              ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder, pos);
                        }
  
 +                      immUnbindProgram();
 +
                        glDisable(GL_BLEND);
                }
        }
@@@ -344,11 -361,14 +344,11 @@@ void applyGridAbsolute(TransInfo *t
  {
        float grid_size = 0.0f;
        GearsType grid_action;
 -      TransData *td;
 -      float (*obmat)[4] = NULL;
 -      bool use_obmat = false;
        int i;
-       
        if (!(activeSnap(t) && (ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID))))
                return;
-       
        grid_action = BIG_GEARS;
        if (t->modifiers & MOD_PRECISION)
                grid_action = SMALL_GEARS;
        /* early exit on unusable grid size */
        if (grid_size == 0.0f)
                return;
-       
 -      if (t->flag & (T_EDIT | T_POSE)) {
 -              Object *ob = t->obedit ? t->obedit : t->poseobj;
 -              obmat = ob->obmat;
 -              use_obmat = true;
 -      }
 +      FOREACH_TRANS_DATA_CONTAINER(t, tc) {
 +              TransData *td;
  
 -      for (i = 0, td = t->data; i < t->total; i++, td++) {
 -              float iloc[3], loc[3], tvec[3];
 +              for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
 +                      float iloc[3], loc[3], tvec[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_PROP_EDIT) && (td->factor == 0.0f))
 -                      continue;
 +                      if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
 +                              continue;
  
 -              copy_v3_v3(iloc, td->loc);
 -              if (use_obmat) {
 -                      mul_m4_v3(obmat, iloc);
 -              }
 -              else if (t->flag & T_OBJECT) {
 -                      BKE_object_eval_transform_all(G.main->eval_ctx, t->scene, td->ob);
 -                      copy_v3_v3(iloc, td->ob->obmat[3]);
 -              }
 +                      copy_v3_v3(iloc, td->loc);
 +                      if (tc->use_local_mat) {
 +                              mul_m4_v3(tc->mat, iloc);
 +                      }
 +                      else if (t->flag & T_OBJECT) {
 +                              BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob);
 +                              copy_v3_v3(iloc, td->ob->obmat[3]);
 +                      }
  
 -              mul_v3_v3fl(loc, iloc, 1.0f / grid_size);
 -              loc[0] = roundf(loc[0]);
 -              loc[1] = roundf(loc[1]);
 -              loc[2] = roundf(loc[2]);
 -              mul_v3_fl(loc, grid_size);
 +                      mul_v3_v3fl(loc, iloc, 1.0f / grid_size);
 +                      loc[0] = roundf(loc[0]);
 +                      loc[1] = roundf(loc[1]);
 +                      loc[2] = roundf(loc[2]);
 +                      mul_v3_fl(loc, grid_size);
  
 -              sub_v3_v3v3(tvec, loc, iloc);
 -              mul_m3_v3(td->smtx, tvec);
 -              add_v3_v3(td->loc, tvec);
 +                      sub_v3_v3v3(tvec, loc, iloc);
 +                      mul_m3_v3(td->smtx, tvec);
 +                      add_v3_v3(td->loc, tvec);
 +              }
        }
  }
  
@@@ -867,8 -888,8 +867,8 @@@ static float RotationBetween
        // Angle around a constraint axis (error prone, will need debug)
        if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
                float axis[3], tmp[3];
-               
 -              t->con.applyRot(t, NULL, axis, NULL);
 +              t->con.applyRot(t, NULL, NULL, axis, NULL);
  
                project_v3_v3v3(tmp, end, axis);
                sub_v3_v3v3(end, end, tmp);
@@@ -975,10 -996,10 +975,10 @@@ static void CalcSnapGeometry(TransInfo 
                /* same as above but for UV's */
                Image *ima = ED_space_image(t->sa->spacedata.first);
                float co[2];
-               
                UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
  
 -              if (ED_uvedit_nearest_uv(t->scene, t->obedit, ima, co, t->tsnap.snapPoint)) {
 +              if (ED_uvedit_nearest_uv(t->scene, TRANS_DATA_CONTAINER_FIRST_EVIL(t)->obedit, ima, co, t->tsnap.snapPoint)) {
                        t->tsnap.snapPoint[0] *= t->aspect[0];
                        t->tsnap.snapPoint[1] *= t->aspect[1];
  
@@@ -1076,27 -1103,19 +1076,27 @@@ static void TargetSnapMedian(TransInfo 
                t->tsnap.snapTarget[1] = 0;
                t->tsnap.snapTarget[2] = 0;
  
 -              for (td = t->data, i = 0; i < t->total && td->flag & TD_SELECTED; i++, td++) {
 -                      add_v3_v3(t->tsnap.snapTarget, td->center);
 +              FOREACH_TRANS_DATA_CONTAINER (t, tc) {
 +                      TransData *td = tc->data;
 +                      int i;
 +                      for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
 +                              /* TODO(campbell): perform the global transformation once per TransDataContainer */
 +                              if (tc->use_local_mat) {
 +                                      float v[3];
 +                                      mul_v3_m4v3(v, tc->mat, td->center);
 +                                      add_v3_v3(t->tsnap.snapTarget, v);
 +                              }
 +                              else {
 +                                      add_v3_v3(t->tsnap.snapTarget, td->center);
 +                              }
 +                      }
 +                      i_accum += i;
                }
  
 -              mul_v3_fl(t->tsnap.snapTarget, 1.0 / i);
 -
 -              if (t->flag & (T_EDIT | T_POSE)) {
 -                      Object *ob = t->obedit ? t->obedit : t->poseobj;
 -                      mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
 -              }
 +              mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum);
-               
                TargetSnapOffset(t, NULL);
-               
                t->tsnap.status |= TARGET_INIT;
        }
  }
@@@ -1106,8 -1125,8 +1106,8 @@@ static void TargetSnapClosest(TransInf
        // Only valid if a snap point has been selected
        if (t->tsnap.status & POINT_INIT) {
                float dist_closest = 0.0f;
 -              TransData *closest = NULL, *td = NULL;
 +              TransData *closest = NULL;
-               
                /* Object mode */
                if (t->flag & T_OBJECT) {
                        int i;
                                }
                        }
                }
-               
 -              else {
 -                      int i;
 -                      for (td = t->data, i = 0; i < t->total && td->flag & TD_SELECTED; i++, td++) {
 -                              float loc[3];
 -                              float dist;
 -
 -                              copy_v3_v3(loc, td->center);
 -
 -                              if (t->flag & (T_EDIT | T_POSE)) {
 -                                      Object *ob = t->obedit ? t->obedit : t->poseobj;
 -                                      mul_m4_v3(ob->obmat, loc);
 -                              }
 -
 -                              dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint);
 -
 -                              if ((dist != TRANSFORM_DIST_INVALID) &&
 -                                  (closest == NULL || fabsf(dist) < fabsf(dist_closest)))
 -                              {
 -                                      copy_v3_v3(t->tsnap.snapTarget, loc);
 -                                      closest = td;
 -                                      dist_closest = dist;
 -                              }
 -                      }
 -              }
                TargetSnapOffset(t, closest);
-               
                t->tsnap.status |= TARGET_INIT;
        }
  }