Fix transform gizmo showing with active element pivot point and no selection.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Wed, 12 Dec 2018 13:20:10 +0000 (14:20 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Wed, 12 Dec 2018 14:02:30 +0000 (15:02 +0100)
It should be possible to use this when the active element is unselected, but
there still needs to be something else selected. Otherwise it is not possible
to deselect all as a way to get the gizmo out of the way.

source/blender/editors/transform/transform_gizmo_3d.c

index 91c13a6ca901dab248289c4e64ecc860ea5bb418..b1d2fd329bbd0ff629fc3ee95a740dafca26c7b9 100644 (file)
@@ -454,6 +454,17 @@ static void gizmo_get_axis_constraint(const int axis_idx, bool r_axis[3])
 
 /* **************** Preparation Stuff **************** */
 
+static void reset_tw_center(struct TransformBounds *tbounds)
+{
+       INIT_MINMAX(tbounds->min, tbounds->max);
+       zero_v3(tbounds->center);
+
+       for (int i = 0; i < 3; i++) {
+               tbounds->axis_min[i] = +FLT_MAX;
+               tbounds->axis_max[i] = -FLT_MAX;
+       }
+}
+
 /* transform widget center calc helper for below */
 static void calc_tw_center(struct TransformBounds *tbounds, const float co[3])
 {
@@ -757,8 +768,7 @@ int ED_transform_calc_gizmo_stats(
        }
 
        /* transform widget centroid/center */
-       INIT_MINMAX(tbounds->min, tbounds->max);
-       zero_v3(tbounds->center);
+       reset_tw_center(tbounds);
 
        copy_m3_m4(tbounds->axis, rv3d->twmat);
        if (params->use_local_axis && (ob && ob->mode & OB_MODE_EDIT)) {
@@ -770,11 +780,6 @@ int ED_transform_calc_gizmo_stats(
                normalize_m3(tbounds->axis);
        }
 
-       for (int i = 0; i < 3; i++) {
-               tbounds->axis_min[i] = +FLT_MAX;
-               tbounds->axis_max[i] = -FLT_MAX;
-       }
-
        if (is_gp_edit) {
                float diff_mat[4][4];
                for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
@@ -832,219 +837,240 @@ int ED_transform_calc_gizmo_stats(
 
                ob = obedit;
                if (obedit->type == OB_MESH) {
-                       BMEditMesh *em = BKE_editmesh_from_object(obedit);
-                       BMEditSelection ese;
-                       float vec[3] = {0, 0, 0};
-
-                       /* USE LAST SELECT WITH ACTIVE */
-                       if ((pivot_point == V3D_AROUND_ACTIVE) && BM_select_history_active_get(em->bm, &ese)) {
-                               BM_editselection_center(&ese, vec);
-                               calc_tw_center(tbounds, vec);
-                               totsel = 1;
-                       }
-                       else {
-                               FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
-                                       BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
-                                       BMesh *bm = em_iter->bm;
+                       FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
+                               BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
+                               BMesh *bm = em_iter->bm;
 
-                                       if (bm->totvertsel == 0) {
-                                               continue;
-                                       }
+                               if (bm->totvertsel == 0) {
+                                       continue;
+                               }
 
-                                       BMVert *eve;
-                                       BMIter iter;
+                               BMVert *eve;
+                               BMIter iter;
 
-                                       float mat_local[4][4];
-                                       if (use_mat_local) {
-                                               mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
-                                       }
+                               float mat_local[4][4];
+                               if (use_mat_local) {
+                                       mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+                               }
 
-                                       BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
-                                               if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
-                                                       if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
-                                                               calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
-                                                               totsel++;
-                                                       }
+                               BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+                                       if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+                                               if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+                                                       calc_tw_center_with_matrix(tbounds, eve->co, use_mat_local, mat_local);
+                                                       totsel++;
                                                }
                                        }
-                               } FOREACH_EDIT_OBJECT_END();
+                               }
+                       } FOREACH_EDIT_OBJECT_END();
+
+                       /* Around active, only if there is a selection. The active
+                        * element itself does not have to be selected. */
+                       if ((pivot_point == V3D_AROUND_ACTIVE) && totsel) {
+                               BMEditMesh *em = BKE_editmesh_from_object(obedit);
+                               BMEditSelection ese;
+
+                               if (BM_select_history_active_get(em->bm, &ese)) {
+                                       float vec[3] = {0, 0, 0};
+                                       BM_editselection_center(&ese, vec);
+                                       reset_tw_center(tbounds);
+                                       calc_tw_center(tbounds, vec);
+                                       totsel = 1;
+                               }
                        }
                } /* end editmesh */
                else if (obedit->type == OB_ARMATURE) {
-                       bArmature *arm = obedit->data;
-                       EditBone *ebo;
-
-                       if ((pivot_point == V3D_AROUND_ACTIVE) && (ebo = arm->act_edbone)) {
-                               /* doesn't check selection or visibility intentionally */
-                               if (ebo->flag & BONE_TIPSEL) {
-                                       calc_tw_center(tbounds, ebo->tail);
-                                       totsel++;
+                       FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
+                               bArmature *arm = ob_iter->data;
+
+                               float mat_local[4][4];
+                               if (use_mat_local) {
+                                       mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
                                }
-                               if ((ebo->flag & BONE_ROOTSEL) ||
-                                   ((ebo->flag & BONE_TIPSEL) == false))  /* ensure we get at least one point */
-                               {
-                                       calc_tw_center(tbounds, ebo->head);
-                                       totsel++;
+                               for (EditBone *ebo = arm->edbo->first; ebo; ebo = ebo->next) {
+                                       if (EBONE_VISIBLE(arm, ebo)) {
+                                               if (ebo->flag & BONE_TIPSEL) {
+                                                       calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
+                                                       totsel++;
+                                               }
+                                               if ((ebo->flag & BONE_ROOTSEL) &&
+                                                       /* don't include same point multiple times */
+                                                       ((ebo->flag & BONE_CONNECTED) &&
+                                                        (ebo->parent != NULL) &&
+                                                        (ebo->parent->flag & BONE_TIPSEL) &&
+                                                        EBONE_VISIBLE(arm, ebo->parent)) == 0)
+                                               {
+                                                       calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
+                                                       totsel++;
+                                               }
+                                               if (ebo->flag & BONE_SELECTED) {
+                                                       protectflag_to_drawflags_ebone(rv3d, ebo);
+                                               }
+                                       }
                                }
-                               protectflag_to_drawflags_ebone(rv3d, ebo);
-                       }
-                       else {
-                               FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
-                                       arm = ob_iter->data;
+                       } FOREACH_EDIT_OBJECT_END();
+
+                       /* Around active, only if there is a selection. The active
+                        * element itself does not have to be selected. */
+                       if ((pivot_point == V3D_AROUND_ACTIVE) && totsel) {
+                               bArmature *arm = obedit->data;
+                               EditBone *ebo = arm->act_edbone;
 
-                                       float mat_local[4][4];
-                                       if (use_mat_local) {
-                                               mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+                               if (ebo) {
+                                       reset_tw_center(tbounds);
+                                       rv3d->twdrawflag = 0xFFFF;
+                                       totsel = 0;
+
+                                       if (ebo->flag & BONE_TIPSEL) {
+                                               calc_tw_center(tbounds, ebo->tail);
+                                               totsel++;
                                        }
-                                       for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
-                                               if (EBONE_VISIBLE(arm, ebo)) {
-                                                       if (ebo->flag & BONE_TIPSEL) {
-                                                               calc_tw_center_with_matrix(tbounds, ebo->tail, use_mat_local, mat_local);
-                                                               totsel++;
-                                                       }
-                                                       if ((ebo->flag & BONE_ROOTSEL) &&
-                                                           /* don't include same point multiple times */
-                                                           ((ebo->flag & BONE_CONNECTED) &&
-                                                            (ebo->parent != NULL) &&
-                                                            (ebo->parent->flag & BONE_TIPSEL) &&
-                                                            EBONE_VISIBLE(arm, ebo->parent)) == 0)
-                                                       {
-                                                               calc_tw_center_with_matrix(tbounds, ebo->head, use_mat_local, mat_local);
-                                                               totsel++;
-                                                       }
-                                                       if (ebo->flag & BONE_SELECTED) {
-                                                               protectflag_to_drawflags_ebone(rv3d, ebo);
-                                                       }
-                                               }
+                                       if ((ebo->flag & BONE_ROOTSEL) ||
+                                               ((ebo->flag & BONE_TIPSEL) == false))  /* ensure we get at least one point */
+                                       {
+                                               calc_tw_center(tbounds, ebo->head);
+                                               totsel++;
                                        }
-                               } FOREACH_EDIT_OBJECT_END();
+                                       protectflag_to_drawflags_ebone(rv3d, ebo);
+                               }
                        }
                }
                else if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
-                       Curve *cu = obedit->data;
-                       float center[3];
-
-                       if ((pivot_point == V3D_AROUND_ACTIVE) && ED_curve_active_center(cu, center)) {
-                               calc_tw_center(tbounds, center);
-                               totsel++;
-                       }
-                       else {
-                               FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
-                                       cu = ob_iter->data;
-                                       Nurb *nu;
-                                       BezTriple *bezt;
-                                       BPoint *bp;
-                                       ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-
-                                       float mat_local[4][4];
-                                       if (use_mat_local) {
-                                               mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
-                                       }
+                       FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
+                               Curve *cu = ob_iter->data;
+                               Nurb *nu;
+                               BezTriple *bezt;
+                               BPoint *bp;
+                               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+
+                               float mat_local[4][4];
+                               if (use_mat_local) {
+                                       mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+                               }
 
-                                       nu = nurbs->first;
-                                       while (nu) {
-                                               if (nu->type == CU_BEZIER) {
-                                                       bezt = nu->bezt;
-                                                       a = nu->pntsu;
-                                                       while (a--) {
-                                                               /* exceptions
-                                                                * if handles are hidden then only check the center points.
-                                                                * If the center knot is selected then only use this as the center point.
-                                                                */
-                                                               if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
-                                                                       if (bezt->f2 & SELECT) {
-                                                                               calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
-                                                                               totsel++;
-                                                                       }
-                                                               }
-                                                               else if (bezt->f2 & SELECT) {
+                               nu = nurbs->first;
+                               while (nu) {
+                                       if (nu->type == CU_BEZIER) {
+                                               bezt = nu->bezt;
+                                               a = nu->pntsu;
+                                               while (a--) {
+                                                       /* exceptions
+                                                        * if handles are hidden then only check the center points.
+                                                        * If the center knot is selected then only use this as the center point.
+                                                        */
+                                                       if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
+                                                               if (bezt->f2 & SELECT) {
                                                                        calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
                                                                        totsel++;
                                                                }
-                                                               else {
-                                                                       if (bezt->f1 & SELECT) {
-                                                                               const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
-                                                                               calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
-                                                                               totsel++;
-                                                                       }
-                                                                       if (bezt->f3 & SELECT) {
-                                                                               const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
-                                                                               calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
-                                                                               totsel++;
-                                                                       }
-                                                               }
-                                                               bezt++;
                                                        }
-                                               }
-                                               else {
-                                                       bp = nu->bp;
-                                                       a = nu->pntsu * nu->pntsv;
-                                                       while (a--) {
-                                                               if (bp->f1 & SELECT) {
-                                                                       calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
+                                                       else if (bezt->f2 & SELECT) {
+                                                               calc_tw_center_with_matrix(tbounds, bezt->vec[1], use_mat_local, mat_local);
+                                                               totsel++;
+                                                       }
+                                                       else {
+                                                               if (bezt->f1 & SELECT) {
+                                                                       const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 0];
+                                                                       calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
+                                                                       totsel++;
+                                                               }
+                                                               if (bezt->f3 & SELECT) {
+                                                                       const float *co = bezt->vec[(pivot_point == V3D_AROUND_LOCAL_ORIGINS) ? 1 : 2];
+                                                                       calc_tw_center_with_matrix(tbounds, co, use_mat_local, mat_local);
                                                                        totsel++;
                                                                }
-                                                               bp++;
                                                        }
+                                                       bezt++;
                                                }
-                                               nu = nu->next;
                                        }
-                               } FOREACH_EDIT_OBJECT_END();
+                                       else {
+                                               bp = nu->bp;
+                                               a = nu->pntsu * nu->pntsv;
+                                               while (a--) {
+                                                       if (bp->f1 & SELECT) {
+                                                               calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
+                                                               totsel++;
+                                                       }
+                                                       bp++;
+                                               }
+                                       }
+                                       nu = nu->next;
+                               }
+                       } FOREACH_EDIT_OBJECT_END();
+
+                       /* Around active, only if there is a selection. The active
+                        * element itself does not have to be selected. */
+                       if ((pivot_point == V3D_AROUND_ACTIVE) && totsel) {
+                               Curve *cu = obedit->data;
+                               float center[3];
+
+                               if (ED_curve_active_center(cu, center)) {
+                                       reset_tw_center(tbounds);
+                                       calc_tw_center(tbounds, center);
+                                       totsel = 1;
+                               }
                        }
                }
                else if (obedit->type == OB_MBALL) {
-                       MetaBall *mb = (MetaBall *)obedit->data;
-                       MetaElem *ml;
+                       FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
+                               MetaBall *mb = (MetaBall *)ob_iter->data;
 
-                       if ((pivot_point == V3D_AROUND_ACTIVE) && (ml = mb->lastelem)) {
-                               calc_tw_center(tbounds, &ml->x);
-                               totsel++;
-                       }
-                       else {
-                               FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
-                                       mb = (MetaBall *)ob_iter->data;
-
-                                       float mat_local[4][4];
-                                       if (use_mat_local) {
-                                               mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
-                                       }
+                               float mat_local[4][4];
+                               if (use_mat_local) {
+                                       mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+                               }
 
-                                       for (ml = mb->editelems->first; ml; ml = ml->next) {
-                                               if (ml->flag & SELECT) {
-                                                       calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
-                                                       totsel++;
-                                               }
+                               for (MetaElem *ml = mb->editelems->first; ml; ml = ml->next) {
+                                       if (ml->flag & SELECT) {
+                                               calc_tw_center_with_matrix(tbounds, &ml->x, use_mat_local, mat_local);
+                                               totsel++;
                                        }
-                               } FOREACH_EDIT_OBJECT_END();
+                               }
+                       } FOREACH_EDIT_OBJECT_END();
+
+                       /* Around active, only if there is a selection. The active
+                        * element itself does not have to be selected. */
+                       if ((pivot_point == V3D_AROUND_ACTIVE) && totsel) {
+                               MetaBall *mb = (MetaBall *)obedit->data;
+                               MetaElem *ml = mb->lastelem;
+
+                               if (ml) {
+                                       reset_tw_center(tbounds);
+                                       calc_tw_center(tbounds, &ml->x);
+                                       totsel = 1;
+                               }
                        }
                }
                else if (obedit->type == OB_LATTICE) {
-                       Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
-                       BPoint *bp;
-
-                       if ((pivot_point == V3D_AROUND_ACTIVE) && (bp = BKE_lattice_active_point_get(lt))) {
-                               calc_tw_center(tbounds, bp->vec);
-                               totsel++;
-                       }
-                       else {
-                               FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
-                                       lt = ((Lattice *)ob_iter->data)->editlatt->latt;
-                                       bp = lt->def;
-                                       a = lt->pntsu * lt->pntsv * lt->pntsw;
-
-                                       float mat_local[4][4];
-                                       if (use_mat_local) {
-                                               mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
-                                       }
+                       FOREACH_EDIT_OBJECT_BEGIN(ob_iter, use_mat_local) {
+                               Lattice *lt = ((Lattice *)ob_iter->data)->editlatt->latt;
+                               BPoint *bp = lt->def;
+                               a = lt->pntsu * lt->pntsv * lt->pntsw;
+
+                               float mat_local[4][4];
+                               if (use_mat_local) {
+                                       mul_m4_m4m4(mat_local, obedit->imat, ob_iter->obmat);
+                               }
 
-                                       while (a--) {
-                                               if (bp->f1 & SELECT) {
-                                                       calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
-                                                       totsel++;
-                                               }
-                                               bp++;
+                               while (a--) {
+                                       if (bp->f1 & SELECT) {
+                                               calc_tw_center_with_matrix(tbounds, bp->vec, use_mat_local, mat_local);
+                                               totsel++;
                                        }
-                               } FOREACH_EDIT_OBJECT_END();
+                                       bp++;
+                               }
+                       } FOREACH_EDIT_OBJECT_END();
+
+                       /* Around active, only if there is a selection. The active
+                        * element itself does not have to be selected. */
+                       if ((pivot_point == V3D_AROUND_ACTIVE) && totsel) {
+                               Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
+                               BPoint *bp = BKE_lattice_active_point_get(lt);
+
+                               if (bp) {
+                                       reset_tw_center(tbounds);
+                                       calc_tw_center(tbounds, bp->vec);
+                                       totsel = 1;
+                               }
                        }
                }
 
@@ -1062,22 +1088,19 @@ int ED_transform_calc_gizmo_stats(
        else if (ob && (ob->mode & OB_MODE_POSE)) {
                bPoseChannel *pchan;
                int mode = TFM_ROTATION; // mislead counting bones... bah. We don't know the gizmo mode, could be mixed
-               bool ok = false;
 
-               if ((pivot_point == V3D_AROUND_ACTIVE) && (pchan = BKE_pose_channel_active(ob))) {
-                       /* doesn't check selection or visibility intentionally */
-                       Bone *bone = pchan->bone;
-                       if (bone) {
+               totsel = count_set_pose_transflags(ob, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
+
+               if (totsel) {
+                       if ((pivot_point == V3D_AROUND_ACTIVE) &&
+                           (pchan = BKE_pose_channel_active(ob)))
+                       {
+                               /* Doesn't check selection or visibility of the active bone intentionally. */
                                calc_tw_center(tbounds, pchan->pose_head);
                                protectflag_to_drawflags_pchan(rv3d, pchan);
                                totsel = 1;
-                               ok = true;
                        }
-               }
-               else {
-                       totsel = count_set_pose_transflags(ob, mode, V3D_AROUND_CENTER_BOUNDS, NULL);
-
-                       if (totsel) {
+                       else {
                                /* use channels to get stats */
                                for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
                                        Bone *bone = pchan->bone;
@@ -1086,11 +1109,8 @@ int ED_transform_calc_gizmo_stats(
                                                protectflag_to_drawflags_pchan(rv3d, pchan);
                                        }
                                }
-                               ok = true;
                        }
-               }
 
-               if (ok) {
                        mul_v3_fl(tbounds->center, 1.0f / (float)totsel);   // centroid!
                        mul_m4_v3(ob->obmat, tbounds->center);
                        mul_m4_v3(ob->obmat, tbounds->min);