Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / armature / armature_edit.c
index 539d56a..9fcf6ad 100644 (file)
 #include "BKE_armature.h"
 #include "BKE_constraint.h"
 #include "BKE_context.h"
+#include "BKE_layer.h"
 #include "BKE_global.h"
 #include "BKE_report.h"
+#include "BKE_object.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
@@ -138,17 +140,16 @@ void ED_armature_transform(struct bArmature *arm, float mat[4][4], const bool do
 
 /* exported for use in editors/object/ */
 /* 0 == do center, 1 == center new, 2 == center cursor */
-void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int centermode, int around)
+void ED_armature_origin_set(Object *ob, float cursor[3], int centermode, int around)
 {
-       Object *obedit = scene->obedit; // XXX get from context
+       const bool is_editmode = BKE_object_is_in_editmode(ob);
        EditBone *ebone;
        bArmature *arm = ob->data;
        float cent[3];
 
        /* Put the armature into editmode */
-       if (ob != obedit) {
+       if (is_editmode == false) {
                ED_armature_to_edit(arm);
-               obedit = NULL; /* we cant use this so behave as if there is no obedit */
        }
 
        /* Find the centerpoint */
@@ -188,13 +189,13 @@ void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int cente
        }
 
        /* Turn the list into an armature */
-       if (obedit == NULL) {
+       if (is_editmode == false) {
                ED_armature_from_edit(arm);
                ED_armature_edit_free(arm);
        }
 
        /* Adjust object location for new centerpoint */
-       if (centermode && obedit == NULL) {
+       if (centermode && (is_editmode == false)) {
                mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */
                add_v3_v3(ob->loc, cent);
        }
@@ -317,10 +318,10 @@ static int armature_calc_roll_exec(bContext *C, wmOperator *op)
                Scene *scene = CTX_data_scene(C);
                View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
                float cursor_local[3];
-               const float   *cursor = ED_view3d_cursor3d_get(scene, v3d);
+               const View3DCursor *cursor = ED_view3d_cursor3d_get(scene, v3d);
 
                invert_m4_m4(ob->imat, ob->obmat);
-               copy_v3_v3(cursor_local, cursor);
+               copy_v3_v3(cursor_local, cursor->location);
                mul_m4_v3(ob->imat, cursor_local);
 
 
@@ -630,25 +631,39 @@ static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
 /* bone adding between selected joints */
 static int armature_fill_bones_exec(bContext *C, wmOperator *op)
 {
-       Object *obedit = CTX_data_edit_object(C);
-       bArmature *arm = (obedit) ? obedit->data : NULL;
+       Object *obedit_active = CTX_data_edit_object(C);
        Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
        ListBase points = {NULL, NULL};
        EditBone *newbone = NULL;
        int count;
+       bool mixed_object_error = false;
 
        /* sanity checks */
-       if (ELEM(NULL, obedit, arm))
+       if (ELEM(NULL, obedit_active, obedit_active->data)) {
                return OPERATOR_CANCELLED;
+       }
 
        /* loop over all bones, and only consider if visible */
-       CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
+       bArmature *arm = NULL;
+       CTX_DATA_BEGIN_WITH_ID(C, EditBone *, ebone, visible_bones, bArmature *, arm_iter)
        {
-               if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
+               bool check = false;
+               if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL)) {
                        fill_add_joint(ebone, 0, &points);
-               if (ebone->flag & BONE_TIPSEL)
+                       check = true;
+               }
+               if (ebone->flag & BONE_TIPSEL) {
                        fill_add_joint(ebone, 1, &points);
+                       check = true;
+               }
+
+               if (check) {
+                       if (arm && (arm != arm_iter)) {
+                               mixed_object_error = true;
+                       }
+                       arm = arm_iter;
+               }
        }
        CTX_DATA_END;
 
@@ -663,7 +678,25 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
                BKE_report(op->reports, RPT_ERROR, "No joints selected");
                return OPERATOR_CANCELLED;
        }
-       else if (count == 1) {
+       else if (mixed_object_error) {
+               BKE_report(op->reports, RPT_ERROR, "Bones for different objects selected");
+               BLI_freelistN(&points);
+               return OPERATOR_CANCELLED;
+       }
+
+       Object *obedit = NULL;
+       {
+               ViewLayer *view_layer = CTX_data_view_layer(C);
+               FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, OB_MODE_EDIT, ob_iter) {
+                       if (ob_iter->data == arm) {
+                               obedit = ob_iter;
+                       }
+               }
+               FOREACH_OBJECT_IN_MODE_END;
+       }
+       BLI_assert(obedit != NULL);
+
+       if (count == 1) {
                EditBonePoint *ebp;
                float curs[3];
 
@@ -672,7 +705,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
 
                /* Get points - cursor (tail) */
                invert_m4_m4(obedit->imat, obedit->obmat);
-               mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
+               mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)->location);
 
                /* Create a bone */
                newbone = add_points_bone(obedit, ebp->vec, curs);
@@ -710,7 +743,7 @@ static int armature_fill_bones_exec(bContext *C, wmOperator *op)
 
                                /* get cursor location */
                                invert_m4_m4(obedit->imat, obedit->obmat);
-                               mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
+                               mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d)->location);
 
                                /* get distances */
                                dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
@@ -1301,38 +1334,50 @@ static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p)
 /* only editmode! */
 static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
 {
-       bArmature *arm;
        EditBone *curBone, *ebone_next;
-       Object *obedit = CTX_data_edit_object(C);
-       bool changed = false;
-       arm = obedit->data;
+       bool changed_multi = false;
 
        /* cancel if nothing selected */
        if (CTX_DATA_COUNT(C, selected_bones) == 0)
                return OPERATOR_CANCELLED;
 
-       armature_select_mirrored(arm);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
+       uint objects_len = 0;
+       Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+       for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+               Object *obedit = objects[ob_index];
+               bArmature *arm = obedit->data;
+               bool changed = false;
+
+               armature_select_mirrored(arm);
+
+               BKE_pose_channels_remove(obedit, armature_delete_ebone_cb, arm);
+
+               for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
+                       ebone_next = curBone->next;
+                       if (arm->layer & curBone->layer) {
+                               if (curBone->flag & BONE_SELECTED) {
+                                       if (curBone == arm->act_edbone) arm->act_edbone = NULL;
+                                       ED_armature_ebone_remove(arm, curBone);
+                                       changed = true;
+                               }
+                       }
+               }
+
+               if (changed) {
+                       changed_multi = true;
 
-       BKE_pose_channels_remove(obedit, armature_delete_ebone_cb, arm);
+                       ED_armature_edit_sync_selection(arm->edbo);
+                       BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);
 
-       for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
-               ebone_next = curBone->next;
-               if (arm->layer & curBone->layer) {
-                       if (curBone->flag & BONE_SELECTED) {
-                               if (curBone == arm->act_edbone) arm->act_edbone = NULL;
-                               ED_armature_ebone_remove(arm, curBone);
-                               changed = true;
-                       }
+                       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
                }
        }
+       MEM_freeN(objects);
 
-       if (!changed)
+       if (!changed_multi) {
                return OPERATOR_CANCELLED;
-
-       ED_armature_edit_sync_selection(arm->edbo);
-       BKE_pose_tag_recalc(CTX_data_main(C), obedit->pose);
-
-       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
+       }
 
        return OPERATOR_FINISHED;
 }