Blender  V2.93
armature_edit.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * Armature EditMode tools - transforms, chain based editing, and other settings
19  */
20 
25 #include "DNA_armature_types.h"
26 #include "DNA_constraint_types.h"
27 #include "DNA_object_types.h"
28 #include "DNA_scene_types.h"
29 
30 #include "MEM_guardedalloc.h"
31 
32 #include "BLT_translation.h"
33 
34 #include "BLI_blenlib.h"
35 #include "BLI_ghash.h"
36 #include "BLI_math.h"
37 
38 #include "BKE_action.h"
39 #include "BKE_armature.h"
40 #include "BKE_constraint.h"
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_layer.h"
44 #include "BKE_main.h"
45 #include "BKE_object.h"
46 #include "BKE_report.h"
47 
48 #include "RNA_access.h"
49 #include "RNA_define.h"
50 
51 #include "WM_api.h"
52 #include "WM_types.h"
53 
54 #include "ED_armature.h"
55 #include "ED_outliner.h"
56 #include "ED_screen.h"
57 #include "ED_view3d.h"
58 
59 #include "DEG_depsgraph.h"
60 
61 #include "armature_intern.h"
62 
63 /* -------------------------------------------------------------------- */
67 /* NOTE: these functions are exported to the Object module to be called from the tools there */
68 
72 void ED_armature_edit_transform(bArmature *arm, const float mat[4][4], const bool do_props)
73 {
74  EditBone *ebone;
75  float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
76  float mat3[3][3];
77 
78  copy_m3_m4(mat3, mat);
79  normalize_m3(mat3);
80  /* Do the rotations */
81  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
82  float tmat[3][3];
83 
84  /* find the current bone's roll matrix */
85  ED_armature_ebone_to_mat3(ebone, tmat);
86 
87  /* transform the roll matrix */
88  mul_m3_m3m3(tmat, mat3, tmat);
89 
90  /* transform the bone */
91  mul_m4_v3(mat, ebone->head);
92  mul_m4_v3(mat, ebone->tail);
93 
94  /* apply the transformed roll back */
95  mat3_to_vec_roll(tmat, NULL, &ebone->roll);
96 
97  if (do_props) {
98  ebone->rad_head *= scale;
99  ebone->rad_tail *= scale;
100  ebone->dist *= scale;
101 
102  /* we could be smarter and scale by the matrix along the x & z axis */
103  ebone->xwidth *= scale;
104  ebone->zwidth *= scale;
105  }
106  }
107 }
108 
109 void ED_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props)
110 {
111  if (arm->edbo) {
112  ED_armature_edit_transform(arm, mat, do_props);
113  }
114  else {
115  BKE_armature_transform(arm, mat, do_props);
116  }
117 }
118 
119 /* exported for use in editors/object/ */
120 /* 0 == do center, 1 == center new, 2 == center cursor */
122  Main *bmain, Object *ob, const float cursor[3], int centermode, int around)
123 {
124  const bool is_editmode = BKE_object_is_in_editmode(ob);
125  EditBone *ebone;
126  bArmature *arm = ob->data;
127  float cent[3];
128 
129  /* Put the armature into edit-mode. */
130  if (is_editmode == false) {
131  ED_armature_to_edit(arm);
132  }
133 
134  /* Find the center-point. */
135  if (centermode == 2) {
136  copy_v3_v3(cent, cursor);
137  invert_m4_m4(ob->imat, ob->obmat);
138  mul_m4_v3(ob->imat, cent);
139  }
140  else {
141  if (around == V3D_AROUND_CENTER_BOUNDS) {
142  float min[3], max[3];
143  INIT_MINMAX(min, max);
144  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
145  minmax_v3v3_v3(min, max, ebone->head);
146  minmax_v3v3_v3(min, max, ebone->tail);
147  }
148  mid_v3_v3v3(cent, min, max);
149  }
150  else { /* #V3D_AROUND_CENTER_MEDIAN. */
151  int total = 0;
152  zero_v3(cent);
153  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
154  total += 2;
155  add_v3_v3(cent, ebone->head);
156  add_v3_v3(cent, ebone->tail);
157  }
158  if (total) {
159  mul_v3_fl(cent, 1.0f / (float)total);
160  }
161  }
162  }
163 
164  /* Do the adjustments */
165  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
166  sub_v3_v3(ebone->head, cent);
167  sub_v3_v3(ebone->tail, cent);
168  }
169 
170  /* Turn the list into an armature */
171  if (is_editmode == false) {
172  ED_armature_from_edit(bmain, arm);
174  }
175 
176  /* Adjust object location for new center-point. */
177  if (centermode && (is_editmode == false)) {
178  mul_mat3_m4_v3(ob->obmat, cent); /* omit translation part */
179  add_v3_v3(ob->loc, cent);
180  }
181 }
182 
185 /* -------------------------------------------------------------------- */
189 /* adjust bone roll to align Z axis with vector
190  * vec is in local space and is normalized
191  */
193  const float align_axis[3],
194  const bool axis_only)
195 {
196  float mat[3][3], nor[3];
197  float vec[3], align_axis_proj[3], roll = 0.0f;
198 
199  BLI_ASSERT_UNIT_V3(align_axis);
200 
201  sub_v3_v3v3(nor, bone->tail, bone->head);
202 
203  /* If tail == head or the bone is aligned with the axis... */
204  if (normalize_v3(nor) <= FLT_EPSILON ||
205  (fabsf(dot_v3v3(align_axis, nor)) >= (1.0f - FLT_EPSILON))) {
206  return roll;
207  }
208 
209  vec_roll_to_mat3_normalized(nor, 0.0f, mat);
210 
211  /* project the new_up_axis along the normal */
212  project_v3_v3v3_normalized(vec, align_axis, nor);
213  sub_v3_v3v3(align_axis_proj, align_axis, vec);
214 
215  if (axis_only) {
216  if (angle_v3v3(align_axis_proj, mat[2]) > (float)(M_PI_2)) {
217  negate_v3(align_axis_proj);
218  }
219  }
220 
221  roll = angle_v3v3(align_axis_proj, mat[2]);
222 
223  cross_v3_v3v3(vec, mat[2], align_axis_proj);
224 
225  if (dot_v3v3(vec, nor) < 0.0f) {
226  return -roll;
227  }
228  return roll;
229 }
230 
231 /* note, ranges arithmetic is used below */
232 typedef enum eCalcRollTypes {
233  /* pos */
237 
240 
241  /* neg */
245 
248 
249  /* no sign */
254 
256  {0, "", 0, N_("Positive"), ""},
257  {CALC_ROLL_TAN_POS_X, "POS_X", 0, "Local +X Tangent", ""},
258  {CALC_ROLL_TAN_POS_Z, "POS_Z", 0, "Local +Z Tangent", ""},
259 
260  {CALC_ROLL_POS_X, "GLOBAL_POS_X", 0, "Global +X Axis", ""},
261  {CALC_ROLL_POS_Y, "GLOBAL_POS_Y", 0, "Global +Y Axis", ""},
262  {CALC_ROLL_POS_Z, "GLOBAL_POS_Z", 0, "Global +Z Axis", ""},
263 
264  {0, "", 0, N_("Negative"), ""},
265 
266  {CALC_ROLL_TAN_NEG_X, "NEG_X", 0, "Local -X Tangent", ""},
267  {CALC_ROLL_TAN_NEG_Z, "NEG_Z", 0, "Local -Z Tangent", ""},
268 
269  {CALC_ROLL_NEG_X, "GLOBAL_NEG_X", 0, "Global -X Axis", ""},
270  {CALC_ROLL_NEG_Y, "GLOBAL_NEG_Y", 0, "Global -Y Axis", ""},
271  {CALC_ROLL_NEG_Z, "GLOBAL_NEG_Z", 0, "Global -Z Axis", ""},
272 
273  {0, "", 0, N_("Other"), ""},
274  {CALC_ROLL_ACTIVE, "ACTIVE", 0, "Active Bone", ""},
275  {CALC_ROLL_VIEW, "VIEW", 0, "View Axis", ""},
276  {CALC_ROLL_CURSOR, "CURSOR", 0, "Cursor", ""},
277  {0, NULL, 0, NULL, NULL},
278 };
279 
281 {
282  ViewLayer *view_layer = CTX_data_view_layer(C);
283  Object *ob_active = CTX_data_edit_object(C);
284  int ret = OPERATOR_FINISHED;
285 
286  eCalcRollTypes type = RNA_enum_get(op->ptr, "type");
287  const bool axis_only = RNA_boolean_get(op->ptr, "axis_only");
288  /* axis_flip when matching the active bone never makes sense */
289  bool axis_flip = ((type >= CALC_ROLL_ACTIVE) ? RNA_boolean_get(op->ptr, "axis_flip") :
290  (type >= CALC_ROLL_TAN_NEG_X) ? true : false);
291 
292  uint objects_len = 0;
294  view_layer, CTX_wm_view3d(C), &objects_len);
295  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
296  Object *ob = objects[ob_index];
297  bArmature *arm = ob->data;
298  bool changed = false;
299 
300  float imat[3][3];
301  EditBone *ebone;
302 
303  if ((type >= CALC_ROLL_NEG_X) && (type <= CALC_ROLL_TAN_NEG_Z)) {
305  axis_flip = true;
306  }
307 
308  copy_m3_m4(imat, ob->obmat);
309  invert_m3(imat);
310 
311  if (type == CALC_ROLL_CURSOR) { /* Cursor */
313  float cursor_local[3];
314  const View3DCursor *cursor = &scene->cursor;
315 
316  invert_m4_m4(ob->imat, ob->obmat);
317  copy_v3_v3(cursor_local, cursor->location);
318  mul_m4_v3(ob->imat, cursor_local);
319 
320  /* cursor */
321  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
322  if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
323  float cursor_rel[3];
324  sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
325  if (axis_flip) {
326  negate_v3(cursor_rel);
327  }
328  if (normalize_v3(cursor_rel) != 0.0f) {
329  ebone->roll = ED_armature_ebone_roll_to_vector(ebone, cursor_rel, axis_only);
330  changed = true;
331  }
332  }
333  }
334  }
336  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
337  if (ebone->parent) {
338  bool is_edit = (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone));
339  bool is_edit_parent = (EBONE_VISIBLE(arm, ebone->parent) &&
340  EBONE_EDITABLE(ebone->parent));
341 
342  if (is_edit || is_edit_parent) {
343  EditBone *ebone_other = ebone->parent;
344  float dir_a[3];
345  float dir_b[3];
346  float vec[3];
347  bool is_vec_zero;
348 
349  sub_v3_v3v3(dir_a, ebone->tail, ebone->head);
350  normalize_v3(dir_a);
351 
352  /* find the first bone in the chain with a different direction */
353  do {
354  sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
355  normalize_v3(dir_b);
356 
357  if (type == CALC_ROLL_TAN_POS_Z) {
358  cross_v3_v3v3(vec, dir_a, dir_b);
359  }
360  else {
361  add_v3_v3v3(vec, dir_a, dir_b);
362  }
363  } while ((is_vec_zero = (normalize_v3(vec) < 0.00001f)) &&
364  (ebone_other = ebone_other->parent));
365 
366  if (!is_vec_zero) {
367  if (axis_flip) {
368  negate_v3(vec);
369  }
370 
371  if (is_edit) {
372  ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
373  changed = true;
374  }
375 
376  /* parentless bones use cross product with child */
377  if (is_edit_parent) {
378  if (ebone->parent->parent == NULL) {
380  ebone->parent, vec, axis_only);
381  changed = true;
382  }
383  }
384  }
385  }
386  }
387  }
388  }
389  else {
390  float vec[3] = {0.0f, 0.0f, 0.0f};
391  if (type == CALC_ROLL_VIEW) { /* View */
393  if (rv3d == NULL) {
394  BKE_report(op->reports, RPT_ERROR, "No region view3d available");
396  goto cleanup;
397  }
398 
399  copy_v3_v3(vec, rv3d->viewinv[2]);
400  mul_m3_v3(imat, vec);
401  }
402  else if (type == CALC_ROLL_ACTIVE) {
403  float mat[3][3];
404  bArmature *arm_active = ob_active->data;
405  ebone = (EditBone *)arm_active->act_edbone;
406  if (ebone == NULL) {
407  BKE_report(op->reports, RPT_ERROR, "No active bone set");
409  goto cleanup;
410  }
411 
412  ED_armature_ebone_to_mat3(ebone, mat);
413  copy_v3_v3(vec, mat[2]);
414  }
415  else { /* Axis */
416  BLI_assert(type <= 5);
417  if (type < 3) {
418  vec[type] = 1.0f;
419  }
420  else {
421  vec[type - 2] = -1.0f;
422  }
423  mul_m3_v3(imat, vec);
424  normalize_v3(vec);
425  }
426 
427  if (axis_flip) {
428  negate_v3(vec);
429  }
430 
431  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
432  if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
433  /* roll func is a callback which assumes that all is well */
434  ebone->roll = ED_armature_ebone_roll_to_vector(ebone, vec, axis_only);
435  changed = true;
436  }
437  }
438  }
439 
440  if (arm->flag & ARM_MIRROR_EDIT) {
441  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
442  if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
443  EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
444  if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
445  ebone->roll = -ebone_mirr->roll;
446  }
447  }
448  }
449  }
450 
451  if (changed) {
452  /* note, notifier might evolve */
455  }
456  }
457 
458 cleanup:
459  MEM_freeN(objects);
460  return ret;
461 }
462 
464 {
465  /* identifiers */
466  ot->name = "Recalculate Roll";
467  ot->idname = "ARMATURE_OT_calculate_roll";
468  ot->description = "Automatically fix alignment of select bones' axes";
469 
470  /* api callbacks */
474 
475  /* flags */
477 
478  /* properties */
480  RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis");
482  "axis_only",
483  0,
484  "Shortest Rotation",
485  "Ignore the axis direction, use the shortest rotation to align");
486 }
487 
489 {
490  ViewLayer *view_layer = CTX_data_view_layer(C);
491  const float roll = RNA_float_get(op->ptr, "roll");
492 
493  uint objects_len = 0;
495  view_layer, CTX_wm_view3d(C), &objects_len);
496  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
497  Object *ob = objects[ob_index];
498  bArmature *arm = ob->data;
499  bool changed = false;
500 
501  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
502  if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
503  /* Roll func is a callback which assumes that all is well. */
504  ebone->roll = roll;
505  changed = true;
506  }
507  }
508 
509  if (arm->flag & ARM_MIRROR_EDIT) {
510  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
511  if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
512  EditBone *ebone_mirr = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
513  if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
514  ebone->roll = -ebone_mirr->roll;
515  changed = true;
516  }
517  }
518  }
519  }
520 
521  if (changed) {
522  /* Note, notifier might evolve. */
525  }
526  }
527  MEM_freeN(objects);
528 
529  return OPERATOR_FINISHED;
530 }
531 
533 {
534  /* identifiers */
535  ot->name = "Clear Roll";
536  ot->idname = "ARMATURE_OT_roll_clear";
537  ot->description = "Clear roll for selected bones";
538 
539  /* api callbacks */
542 
543  /* flags */
545 
547  "roll",
548  0,
549  NULL,
550  DEG2RADF(-360.0f),
551  DEG2RADF(360.0f),
552  "Roll",
553  "",
554  DEG2RADF(-360.0f),
555  DEG2RADF(360.0f));
556 }
557 
560 /* -------------------------------------------------------------------- */
564 /* temporary data-structure for merge/fill bones */
565 typedef struct EditBonePoint {
567 
568  EditBone *head_owner; /* EditBone which uses this point as a 'head' point */
569  EditBone *tail_owner; /* EditBone which uses this point as a 'tail' point */
570 
571  float vec[3]; /* the actual location of the point in local/EditMode space */
573 
574 /* find chain-tips (i.e. bones without children) */
575 static void chains_find_tips(ListBase *edbo, ListBase *list)
576 {
577  EditBone *curBone, *ebo;
578  LinkData *ld;
579 
580  /* note: this is potentially very slow ... there's got to be a better way */
581  for (curBone = edbo->first; curBone; curBone = curBone->next) {
582  short stop = 0;
583 
584  /* is this bone contained within any existing chain? (skip if so) */
585  for (ld = list->first; ld; ld = ld->next) {
586  for (ebo = ld->data; ebo; ebo = ebo->parent) {
587  if (ebo == curBone) {
588  stop = 1;
589  break;
590  }
591  }
592 
593  if (stop) {
594  break;
595  }
596  }
597  /* skip current bone if it is part of an existing chain */
598  if (stop) {
599  continue;
600  }
601 
602  /* is any existing chain part of the chain formed by this bone? */
603  stop = 0;
604  for (ebo = curBone->parent; ebo; ebo = ebo->parent) {
605  for (ld = list->first; ld; ld = ld->next) {
606  if (ld->data == ebo) {
607  ld->data = curBone;
608  stop = 1;
609  break;
610  }
611  }
612 
613  if (stop) {
614  break;
615  }
616  }
617  /* current bone has already been added to a chain? */
618  if (stop) {
619  continue;
620  }
621 
622  /* add current bone to a new chain */
623  ld = MEM_callocN(sizeof(LinkData), "BoneChain");
624  ld->data = curBone;
625  BLI_addtail(list, ld);
626  }
627 }
628 
631 /* -------------------------------------------------------------------- */
635 static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
636 {
637  EditBonePoint *ebp;
638  float vec[3];
639  short found = 0;
640 
641  if (eb_tail) {
642  copy_v3_v3(vec, ebo->tail);
643  }
644  else {
645  copy_v3_v3(vec, ebo->head);
646  }
647 
648  for (ebp = points->first; ebp; ebp = ebp->next) {
649  if (equals_v3v3(ebp->vec, vec)) {
650  if (eb_tail) {
651  if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
652  /* so this bone's tail owner is this bone */
653  ebp->tail_owner = ebo;
654  found = 1;
655  break;
656  }
657  }
658  else {
659  if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
660  /* so this bone's head owner is this bone */
661  ebp->head_owner = ebo;
662  found = 1;
663  break;
664  }
665  }
666  }
667  }
668 
669  /* allocate a new point if no existing point was related */
670  if (found == 0) {
671  ebp = MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
672 
673  if (eb_tail) {
674  copy_v3_v3(ebp->vec, ebo->tail);
675  ebp->tail_owner = ebo;
676  }
677  else {
678  copy_v3_v3(ebp->vec, ebo->head);
679  ebp->head_owner = ebo;
680  }
681 
682  BLI_addtail(points, ebp);
683  }
684 }
685 
686 /* bone adding between selected joints */
688 {
690  View3D *v3d = CTX_wm_view3d(C);
691  ListBase points = {NULL, NULL};
692  EditBone *newbone = NULL;
693  int count;
694  bool mixed_object_error = false;
695 
696  /* loop over all bones, and only consider if visible */
697  bArmature *arm = NULL;
698  CTX_DATA_BEGIN_WITH_ID (C, EditBone *, ebone, visible_bones, bArmature *, arm_iter) {
699  bool check = false;
700  if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL)) {
701  fill_add_joint(ebone, 0, &points);
702  check = true;
703  }
704  if (ebone->flag & BONE_TIPSEL) {
705  fill_add_joint(ebone, 1, &points);
706  check = true;
707  }
708 
709  if (check) {
710  if (arm && (arm != arm_iter)) {
711  mixed_object_error = true;
712  }
713  arm = arm_iter;
714  }
715  }
716  CTX_DATA_END;
717 
718  /* the number of joints determines how we fill:
719  * 1) between joint and cursor (joint=head, cursor=tail)
720  * 2) between the two joints (order is dependent on active-bone/hierarchy)
721  * 3+) error (a smarter method involving finding chains needs to be worked out
722  */
723  count = BLI_listbase_count(&points);
724 
725  if (count == 0) {
726  BKE_report(op->reports, RPT_ERROR, "No joints selected");
727  return OPERATOR_CANCELLED;
728  }
729 
730  if (mixed_object_error) {
731  BKE_report(op->reports, RPT_ERROR, "Bones for different objects selected");
732  BLI_freelistN(&points);
733  return OPERATOR_CANCELLED;
734  }
735 
736  Object *obedit = NULL;
737  {
738  ViewLayer *view_layer = CTX_data_view_layer(C);
739  FOREACH_OBJECT_IN_EDIT_MODE_BEGIN (view_layer, v3d, ob_iter) {
740  if (ob_iter->data == arm) {
741  obedit = ob_iter;
742  }
743  }
745  }
746  BLI_assert(obedit != NULL);
747 
748  if (count == 1) {
749  EditBonePoint *ebp;
750  float curs[3];
751 
752  /* Get Points - selected joint */
753  ebp = points.first;
754 
755  /* Get points - cursor (tail) */
756  invert_m4_m4(obedit->imat, obedit->obmat);
757  mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
758 
759  /* Create a bone */
760  newbone = add_points_bone(obedit, ebp->vec, curs);
761  }
762  else if (count == 2) {
763  EditBonePoint *ebp_a, *ebp_b;
764  float head[3], tail[3];
765  short headtail = 0;
766 
767  /* check that the points don't belong to the same bone */
768  ebp_a = (EditBonePoint *)points.first;
769  ebp_b = ebp_a->next;
770 
771  if (((ebp_a->head_owner == ebp_b->tail_owner) && (ebp_a->head_owner != NULL)) ||
772  ((ebp_a->tail_owner == ebp_b->head_owner) && (ebp_a->tail_owner != NULL))) {
773  BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
774  BLI_freelistN(&points);
775  return OPERATOR_CANCELLED;
776  }
777 
778  /* find which one should be the 'head' */
779  if ((ebp_a->head_owner && ebp_b->head_owner) || (ebp_a->tail_owner && ebp_b->tail_owner)) {
780  /* use active, nice predictable */
781  if (arm->act_edbone && ELEM(arm->act_edbone, ebp_a->head_owner, ebp_a->tail_owner)) {
782  headtail = 1;
783  }
784  else if (arm->act_edbone && ELEM(arm->act_edbone, ebp_b->head_owner, ebp_b->tail_owner)) {
785  headtail = 2;
786  }
787  else {
788  /* rule: whichever one is closer to 3d-cursor */
789  float curs[3];
790  float dist_sq_a, dist_sq_b;
791 
792  /* get cursor location */
793  invert_m4_m4(obedit->imat, obedit->obmat);
794  mul_v3_m4v3(curs, obedit->imat, scene->cursor.location);
795 
796  /* get distances */
797  dist_sq_a = len_squared_v3v3(ebp_a->vec, curs);
798  dist_sq_b = len_squared_v3v3(ebp_b->vec, curs);
799 
800  /* compare distances - closer one therefore acts as direction for bone to go */
801  headtail = (dist_sq_a < dist_sq_b) ? 2 : 1;
802  }
803  }
804  else if (ebp_a->head_owner) {
805  headtail = 1;
806  }
807  else if (ebp_b->head_owner) {
808  headtail = 2;
809  }
810 
811  /* assign head/tail combinations */
812  if (headtail == 2) {
813  copy_v3_v3(head, ebp_a->vec);
814  copy_v3_v3(tail, ebp_b->vec);
815  }
816  else if (headtail == 1) {
817  copy_v3_v3(head, ebp_b->vec);
818  copy_v3_v3(tail, ebp_a->vec);
819  }
820 
821  /* add new bone and parent it to the appropriate end */
822  if (headtail) {
823  newbone = add_points_bone(obedit, head, tail);
824 
825  /* do parenting (will need to set connected flag too) */
826  if (headtail == 2) {
827  /* ebp tail or head - tail gets priority */
828  if (ebp_a->tail_owner) {
829  newbone->parent = ebp_a->tail_owner;
830  }
831  else {
832  newbone->parent = ebp_a->head_owner;
833  }
834  }
835  else {
836  /* ebp_b tail or head - tail gets priority */
837  if (ebp_b->tail_owner) {
838  newbone->parent = ebp_b->tail_owner;
839  }
840  else {
841  newbone->parent = ebp_b->head_owner;
842  }
843  }
844 
845  /* don't set for bone connecting two head points of bones */
846  if (ebp_a->tail_owner || ebp_b->tail_owner) {
847  newbone->flag |= BONE_CONNECTED;
848  }
849  }
850  }
851  else {
852  BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
853  BLI_freelistN(&points);
854  return OPERATOR_CANCELLED;
855  }
856 
857  if (newbone) {
859  arm->act_edbone = newbone;
860  newbone->flag |= BONE_TIPSEL;
861  }
862 
863  /* updates */
867 
868  /* free points */
869  BLI_freelistN(&points);
870 
871  return OPERATOR_FINISHED;
872 }
873 
875 {
876  /* identifiers */
877  ot->name = "Fill Between Joints";
878  ot->idname = "ARMATURE_OT_fill";
879  ot->description = "Add bone between selected joint(s) and/or 3D cursor";
880 
881  /* callbacks */
884 
885  /* flags */
887 }
888 
891 /* -------------------------------------------------------------------- */
899 /* helper to clear BONE_TRANSFORM flags */
901 {
902  EditBone *ebone;
903 
904  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
905  ebone->flag &= ~BONE_TRANSFORM;
906  }
907 }
908 
910 {
911  ViewLayer *view_layer = CTX_data_view_layer(C);
912  uint objects_len = 0;
914  view_layer, CTX_wm_view3d(C), &objects_len);
915 
916  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
917  Object *ob = objects[ob_index];
918  bArmature *arm = ob->data;
919 
920  ListBase chains = {NULL, NULL};
921  LinkData *chain;
922 
923  /* get chains of bones (ends on chains) */
924  chains_find_tips(arm->edbo, &chains);
925  if (BLI_listbase_is_empty(&chains)) {
926  continue;
927  }
928 
929  /* ensure that mirror bones will also be operated on */
931 
932  /* Clear BONE_TRANSFORM flags
933  * - Used to prevent duplicate/canceling operations from occurring T34123.
934  * - #BONE_DONE cannot be used here as that's already used for mirroring.
935  */
937 
938  /* loop over chains, only considering selected and visible bones */
939  for (chain = chains.first; chain; chain = chain->next) {
940  EditBone *ebo, *child = NULL, *parent = NULL;
941 
942  /* loop over bones in chain */
943  for (ebo = chain->data; ebo; ebo = parent) {
944  /* parent is this bone's original parent
945  * - we store this, as the next bone that is checked is this one
946  * but the value of ebo->parent may change here...
947  */
948  parent = ebo->parent;
949 
950  /* skip bone if already handled, see T34123. */
951  if ((ebo->flag & BONE_TRANSFORM) == 0) {
952  /* only if selected and editable */
953  if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {
954  /* swap head and tail coordinates */
955  swap_v3_v3(ebo->head, ebo->tail);
956 
957  /* do parent swapping:
958  * - use 'child' as new parent
959  * - connected flag is only set if points are coincidental
960  */
961  ebo->parent = child;
962  if ((child) && equals_v3v3(ebo->head, child->tail)) {
963  ebo->flag |= BONE_CONNECTED;
964  }
965  else {
966  ebo->flag &= ~BONE_CONNECTED;
967  }
968 
969  /* get next bones
970  * - child will become the new parent of next bone
971  */
972  child = ebo;
973  }
974  else {
975  /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it
976  * as it will be facing in opposite direction
977  */
978  if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
979  ebo->parent = NULL;
980  ebo->flag &= ~BONE_CONNECTED;
981  }
982 
983  /* get next bones
984  * - child will become new parent of next bone (not swapping occurred,
985  * so set to NULL to prevent infinite-loop)
986  */
987  child = NULL;
988  }
989 
990  /* tag as done (to prevent double-swaps) */
991  ebo->flag |= BONE_TRANSFORM;
992  }
993  }
994  }
995 
996  /* free chains */
997  BLI_freelistN(&chains);
998 
999  /* clear temp flags */
1001  armature_tag_unselect(arm);
1002 
1003  /* note, notifier might evolve */
1006  }
1007  MEM_freeN(objects);
1008 
1009  return OPERATOR_FINISHED;
1010 }
1011 
1013 {
1014  /* identifiers */
1015  ot->name = "Switch Direction";
1016  ot->idname = "ARMATURE_OT_switch_direction";
1017  ot->description = "Change the direction that a chain of bones points in (head and tail swap)";
1018 
1019  /* api callbacks */
1022 
1023  /* flags */
1025 }
1026 
1029 /* -------------------------------------------------------------------- */
1033 /* helper to fix a ebone position if its parent has moved due to alignment*/
1034 static void fix_connected_bone(EditBone *ebone)
1035 {
1036  float diff[3];
1037 
1038  if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) ||
1039  equals_v3v3(ebone->parent->tail, ebone->head)) {
1040  return;
1041  }
1042 
1043  /* if the parent has moved we translate child's head and tail accordingly */
1044  sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
1045  add_v3_v3(ebone->head, diff);
1046  add_v3_v3(ebone->tail, diff);
1047 }
1048 
1049 /* helper to recursively find chains of connected bones starting at ebone and fix their position */
1051 {
1052  EditBone *selbone;
1053 
1054  for (selbone = edbo->first; selbone; selbone = selbone->next) {
1055  if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
1056  fix_connected_bone(selbone);
1057  fix_editbone_connected_children(edbo, selbone);
1058  }
1059  }
1060 }
1061 
1062 static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
1063 {
1064  float selboneaxis[3], actboneaxis[3], length;
1065 
1066  sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
1067  normalize_v3(actboneaxis);
1068 
1069  sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
1070  length = len_v3(selboneaxis);
1071 
1072  mul_v3_fl(actboneaxis, length);
1073  add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
1074  selbone->roll = actbone->roll;
1075 
1076  /* if the bone being aligned has connected descendants they must be moved
1077  * according to their parent new position, otherwise they would be left
1078  * in an inconsistent state: connected but away from the parent*/
1079  fix_editbone_connected_children(edbo, selbone);
1080 }
1081 
1083 {
1084  Object *ob = CTX_data_edit_object(C);
1085  bArmature *arm = (bArmature *)ob->data;
1086  EditBone *actbone = CTX_data_active_bone(C);
1087  EditBone *actmirb = NULL;
1088  int num_selected_bones;
1089 
1090  /* there must be an active bone */
1091  if (actbone == NULL) {
1092  BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
1093  return OPERATOR_CANCELLED;
1094  }
1095 
1096  if (arm->flag & ARM_MIRROR_EDIT) {
1097  /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
1098  * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone
1099  * (i.e. selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
1100  * This is useful for arm-chains, for example parenting lower arm to upper arm
1101  * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
1102  * then just use actbone. Useful when doing upper arm to spine.
1103  */
1104  actmirb = ED_armature_ebone_get_mirrored(arm->edbo, actbone);
1105  if (actmirb == NULL) {
1106  actmirb = actbone;
1107  }
1108  }
1109 
1110  /* if there is only 1 selected bone, we assume that that is the active bone,
1111  * since a user will need to have clicked on a bone (thus selecting it) to make it active
1112  */
1113  num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones);
1114  if (num_selected_bones <= 1) {
1115  /* When only the active bone is selected, and it has a parent,
1116  * align it to the parent, as that is the only possible outcome.
1117  */
1118  if (actbone->parent) {
1119  bone_align_to_bone(arm->edbo, actbone, actbone->parent);
1120 
1121  if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent)) {
1122  bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
1123  }
1124 
1125  BKE_reportf(op->reports, RPT_INFO, "Aligned bone '%s' to parent", actbone->name);
1126  }
1127  }
1128  else {
1129  /* Align 'selected' bones to the active one
1130  * - the context iterator contains both selected bones and their mirrored copies,
1131  * so we assume that unselected bones are mirrored copies of some selected bone
1132  * - since the active one (and/or its mirror) will also be selected, we also need
1133  * to check that we are not trying to operate on them, since such an operation
1134  * would cause errors
1135  */
1136 
1137  /* align selected bones to the active one */
1138  CTX_DATA_BEGIN (C, EditBone *, ebone, selected_editable_bones) {
1139  if (ELEM(ebone, actbone, actmirb) == 0) {
1140  if (ebone->flag & BONE_SELECTED) {
1141  bone_align_to_bone(arm->edbo, ebone, actbone);
1142  }
1143  else {
1144  bone_align_to_bone(arm->edbo, ebone, actmirb);
1145  }
1146  }
1147  }
1148  CTX_DATA_END;
1149 
1150  BKE_reportf(
1151  op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name);
1152  }
1153 
1154  /* note, notifier might evolve */
1157 
1158  return OPERATOR_FINISHED;
1159 }
1160 
1162 {
1163  /* identifiers */
1164  ot->name = "Align Bones";
1165  ot->idname = "ARMATURE_OT_align";
1166  ot->description = "Align selected bones to the active bone (or to their parent)";
1167 
1168  /* api callbacks */
1171 
1172  /* flags */
1174 }
1175 
1178 /* -------------------------------------------------------------------- */
1183 {
1184  ViewLayer *view_layer = CTX_data_view_layer(C);
1185 
1186  uint objects_len = 0;
1188  view_layer, CTX_wm_view3d(C), &objects_len);
1189  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1190  Object *ob = objects[ob_index];
1191  bArmature *arm = ob->data;
1192 
1193  LISTBASE_FOREACH (EditBone *, bone, arm->edbo) {
1194  if (bone->parent && (bone->flag & BONE_SELECTED) != (bone->parent->flag & BONE_SELECTED)) {
1195  bone->parent = NULL;
1196  bone->flag &= ~BONE_CONNECTED;
1197  }
1198  }
1199  LISTBASE_FOREACH (EditBone *, bone, arm->edbo) {
1200  ED_armature_ebone_select_set(bone, (bone->flag & BONE_SELECTED) != 0);
1201  }
1202 
1205  }
1206 
1207  MEM_freeN(objects);
1208  return OPERATOR_FINISHED;
1209 }
1210 
1212 {
1213  /* identifiers */
1214  ot->name = "Split";
1215  ot->idname = "ARMATURE_OT_split";
1216  ot->description = "Split off selected bones from connected unselected bones";
1217 
1218  /* api callbacks */
1221 
1222  /* flags */
1224 }
1225 
1228 /* -------------------------------------------------------------------- */
1232 static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p)
1233 {
1234  bArmature *arm = arm_p;
1235  EditBone *ebone;
1236 
1237  ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
1238  return (ebone && (ebone->flag & BONE_SELECTED) && (arm->layer & ebone->layer));
1239 }
1240 
1241 /* previously delete_armature */
1242 /* only editmode! */
1244 {
1245  EditBone *curBone, *ebone_next;
1246  bool changed_multi = false;
1247 
1248  /* cancel if nothing selected */
1249  if (CTX_DATA_COUNT(C, selected_bones) == 0) {
1250  return OPERATOR_CANCELLED;
1251  }
1252 
1253  ViewLayer *view_layer = CTX_data_view_layer(C);
1254  uint objects_len = 0;
1256  view_layer, CTX_wm_view3d(C), &objects_len);
1257  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1258  Object *obedit = objects[ob_index];
1259  bArmature *arm = obedit->data;
1260  bool changed = false;
1261 
1263 
1265 
1266  for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
1267  ebone_next = curBone->next;
1268  if (arm->layer & curBone->layer) {
1269  if (curBone->flag & BONE_SELECTED) {
1270  if (curBone == arm->act_edbone) {
1271  arm->act_edbone = NULL;
1272  }
1273  ED_armature_ebone_remove(arm, curBone);
1274  changed = true;
1275  }
1276  }
1277  }
1278 
1279  if (changed) {
1280  changed_multi = true;
1281 
1288  }
1289  }
1290  MEM_freeN(objects);
1291 
1292  if (!changed_multi) {
1293  return OPERATOR_CANCELLED;
1294  }
1295 
1296  return OPERATOR_FINISHED;
1297 }
1298 
1300 {
1301  /* identifiers */
1302  ot->name = "Delete Selected Bone(s)";
1303  ot->idname = "ARMATURE_OT_delete";
1304  ot->description = "Remove selected bones from the armature";
1305 
1306  /* api callbacks */
1310 
1311  /* flags */
1313 }
1314 
1315 static bool armature_dissolve_ebone_cb(const char *bone_name, void *arm_p)
1316 {
1317  bArmature *arm = arm_p;
1318  EditBone *ebone;
1319 
1320  ebone = ED_armature_ebone_find_name(arm->edbo, bone_name);
1321  return (ebone && (ebone->flag & BONE_DONE));
1322 }
1323 
1325 {
1326  ViewLayer *view_layer = CTX_data_view_layer(C);
1327  EditBone *ebone, *ebone_next;
1328  bool changed_multi = false;
1329 
1330  uint objects_len = 0;
1332  view_layer, CTX_wm_view3d(C), &objects_len);
1333  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1334  Object *obedit = objects[ob_index];
1335  bArmature *arm = obedit->data;
1336  bool changed = false;
1337 
1338  /* store for mirror */
1339  GHash *ebone_flag_orig = NULL;
1340  int ebone_num = 0;
1341 
1342  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1343  ebone->temp.p = NULL;
1344  ebone->flag &= ~BONE_DONE;
1345  ebone_num++;
1346  }
1347 
1348  if (arm->flag & ARM_MIRROR_EDIT) {
1349  GHashIterator gh_iter;
1350 
1351  ebone_flag_orig = BLI_ghash_ptr_new_ex(__func__, ebone_num);
1352  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1353  union {
1354  int flag;
1355  void *p;
1356  } val = {0};
1357  val.flag = ebone->flag;
1358  BLI_ghash_insert(ebone_flag_orig, ebone, val.p);
1359  }
1360 
1362 
1363  GHASH_ITER (gh_iter, ebone_flag_orig) {
1364  union {
1365  int flag;
1366  void *p;
1367  } *val_p = (void *)BLI_ghashIterator_getValue_p(&gh_iter);
1368  ebone = BLI_ghashIterator_getKey(&gh_iter);
1369  val_p->flag = ebone->flag & ~val_p->flag;
1370  }
1371  }
1372 
1373  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1374  if (ebone->parent && ebone->flag & BONE_CONNECTED) {
1375  if (ebone->parent->temp.ebone == ebone->parent) {
1376  /* ignore */
1377  }
1378  else if (ebone->parent->temp.ebone) {
1379  /* set ignored */
1380  ebone->parent->temp.ebone = ebone->parent;
1381  }
1382  else {
1383  /* set child */
1384  ebone->parent->temp.ebone = ebone;
1385  }
1386  }
1387  }
1388 
1389  /* cleanup multiple used bones */
1390  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1391  if (ebone->temp.ebone == ebone) {
1392  ebone->temp.ebone = NULL;
1393  }
1394  }
1395 
1396  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1397  /* break connections for unseen bones */
1398  if (((arm->layer & ebone->layer) &&
1400  ebone->temp.ebone = NULL;
1401  }
1402 
1403  if (((arm->layer & ebone->layer) &&
1405  if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
1406  ebone->parent->temp.ebone = NULL;
1407  }
1408  }
1409  }
1410 
1411  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1412 
1413  if (ebone->parent && (ebone->parent->temp.ebone == ebone)) {
1414  ebone->flag |= BONE_DONE;
1415  }
1416  }
1417 
1419 
1420  for (ebone = arm->edbo->first; ebone; ebone = ebone_next) {
1421  ebone_next = ebone->next;
1422 
1423  if (ebone->flag & BONE_DONE) {
1424  copy_v3_v3(ebone->parent->tail, ebone->tail);
1425  ebone->parent->rad_tail = ebone->rad_tail;
1427 
1428  ED_armature_ebone_remove_ex(arm, ebone, false);
1429  changed = true;
1430  }
1431  }
1432 
1433  if (changed) {
1434  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1435  if (ebone->parent && ebone->parent->temp.ebone && (ebone->flag & BONE_CONNECTED)) {
1436  ebone->rad_head = ebone->parent->rad_tail;
1437  }
1438  }
1439 
1440  if (arm->flag & ARM_MIRROR_EDIT) {
1441  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1442  union {
1443  int flag;
1444  void *p;
1445  } *val_p = (void *)BLI_ghash_lookup_p(ebone_flag_orig, ebone);
1446  if (val_p && val_p->flag) {
1447  ebone->flag &= ~val_p->flag;
1448  }
1449  }
1450  }
1451  }
1452 
1453  if (arm->flag & ARM_MIRROR_EDIT) {
1454  BLI_ghash_free(ebone_flag_orig, NULL, NULL);
1455  }
1456 
1457  if (changed) {
1458  changed_multi = true;
1464  }
1465  }
1466  MEM_freeN(objects);
1467 
1468  if (!changed_multi) {
1469  return OPERATOR_CANCELLED;
1470  }
1471 
1472  return OPERATOR_FINISHED;
1473 }
1474 
1476 {
1477  /* identifiers */
1478  ot->name = "Dissolve Selected Bone(s)";
1479  ot->idname = "ARMATURE_OT_dissolve";
1480  ot->description = "Dissolve selected bones from the armature";
1481 
1482  /* api callbacks */
1485 
1486  /* flags */
1488 }
1489 
1492 /* -------------------------------------------------------------------- */
1497 {
1498  ViewLayer *view_layer = CTX_data_view_layer(C);
1499  const int invert = RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
1500 
1501  /* cancel if nothing selected */
1502  if (CTX_DATA_COUNT(C, selected_bones) == 0) {
1503  return OPERATOR_CANCELLED;
1504  }
1505 
1506  uint objects_len = 0;
1508  view_layer, CTX_wm_view3d(C), &objects_len);
1509  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1510  Object *obedit = objects[ob_index];
1511  bArmature *arm = obedit->data;
1512  bool changed = false;
1513 
1514  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1515  if (EBONE_VISIBLE(arm, ebone)) {
1516  if ((ebone->flag & BONE_SELECTED) != invert) {
1517  ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
1518  ebone->flag |= BONE_HIDDEN_A;
1519  changed = true;
1520  }
1521  }
1522  }
1523 
1524  if (!changed) {
1525  continue;
1526  }
1529 
1532  }
1533  MEM_freeN(objects);
1534  return OPERATOR_FINISHED;
1535 }
1536 
1538 {
1539  /* identifiers */
1540  ot->name = "Hide Selected";
1541  ot->idname = "ARMATURE_OT_hide";
1542  ot->description = "Tag selected bones to not be visible in Edit Mode";
1543 
1544  /* api callbacks */
1547 
1548  /* flags */
1550 
1551  /* props */
1552  RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
1553 }
1554 
1557 /* -------------------------------------------------------------------- */
1562 {
1563  ViewLayer *view_layer = CTX_data_view_layer(C);
1564  const bool select = RNA_boolean_get(op->ptr, "select");
1565  uint objects_len = 0;
1567  view_layer, CTX_wm_view3d(C), &objects_len);
1568  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1569  Object *obedit = objects[ob_index];
1570  bArmature *arm = obedit->data;
1571  bool changed = false;
1572 
1573  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1574  if (arm->layer & ebone->layer) {
1575  if (ebone->flag & BONE_HIDDEN_A) {
1576  if (!(ebone->flag & BONE_UNSELECTABLE)) {
1578  }
1579  ebone->flag &= ~BONE_HIDDEN_A;
1580  changed = true;
1581  }
1582  }
1583  }
1584 
1585  if (changed) {
1588 
1591  }
1592  }
1593  MEM_freeN(objects);
1594  return OPERATOR_FINISHED;
1595 }
1596 
1598 {
1599  /* identifiers */
1600  ot->name = "Reveal Hidden";
1601  ot->idname = "ARMATURE_OT_reveal";
1602  ot->description = "Reveal all bones hidden in Edit Mode";
1603 
1604  /* api callbacks */
1607 
1608  /* flags */
1610 
1611  RNA_def_boolean(ot->srna, "select", true, "Select", "");
1612 }
1613 
Blender kernel action and pose functionality.
void BKE_pose_channels_remove(struct Object *ob, bool(*filter_fn)(const char *bone_name, void *user_data), void *user_data)
Definition: action.c:986
void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose)
Definition: action.c:1726
void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props)
Definition: armature.c:567
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll)
Definition: armature.c:2059
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3])
Definition: armature.c:2155
#define CTX_DATA_BEGIN_WITH_ID(C, Type, instance, member, Type_id, instance_id)
Definition: BKE_context.h:266
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct EditBone * CTX_data_active_bone(const bContext *C)
Definition: context.c:1321
#define CTX_DATA_COUNT(C, member)
Definition: BKE_context.h:272
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:769
#define CTX_DATA_END
Definition: BKE_context.h:260
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:426
#define FOREACH_OBJECT_IN_MODE_END
Definition: BKE_layer.h:284
#define FOREACH_OBJECT_IN_EDIT_MODE_BEGIN(_view_layer, _v3d, _instance)
Definition: BKE_layer.h:288
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const struct Object *ob)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE void * BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:146
BLI_INLINE void ** BLI_ghashIterator_getValue_p(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:154
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:169
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void ** BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:830
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
GHash * BLI_ghash_ptr_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define M_PI_2
Definition: BLI_math_base.h:41
#define BLI_ASSERT_UNIT_V3(v)
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:105
void mul_mat3_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:794
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void normalize_m3(float R[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1919
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
float mat4_to_scale(const float M[4][4])
Definition: math_matrix.c:2196
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
bool invert_m3(float R[3][3])
Definition: math_matrix.c:1152
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:391
#define DEG2RADF(_deg)
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:443
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:1020
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_v3_v3v3_normalized(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:717
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
MINLINE void swap_v3_v3(float a[3], float b[3])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:83
#define INIT_MINMAX(min, max)
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define N_(msgid)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_TRANSFORM
@ BONE_UNSELECTABLE
@ BONE_DONE
@ BONE_HIDDEN_A
@ BONE_TIPSEL
@ BONE_CONNECTED
@ ARM_MIRROR_EDIT
Object is a sort of wrapper for general info.
@ V3D_AROUND_CENTER_BOUNDS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define EBONE_VISIBLE(arm, ebone)
Definition: ED_armature.h:56
#define EBONE_EDITABLE(ebone)
Definition: ED_armature.h:64
void ED_outliner_select_sync_from_edit_bone_tag(struct bContext *C)
Definition: outliner_sync.c:62
bool ED_operator_editarmature(struct bContext *C)
Definition: screen_ops.c:437
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_POSE
Definition: WM_types.h:359
#define ND_BONE_SELECT
Definition: WM_types.h:361
#define NC_OBJECT
Definition: WM_types.h:280
EditBone * add_points_bone(Object *obedit, float head[3], float tail[3])
Definition: armature_add.c:279
void ARMATURE_OT_hide(wmOperatorType *ot)
void ARMATURE_OT_delete(wmOperatorType *ot)
static void armature_clear_swap_done_flags(bArmature *arm)
static int armature_roll_clear_exec(bContext *C, wmOperator *op)
static bool armature_delete_ebone_cb(const char *bone_name, void *arm_p)
static int armature_dissolve_selected_exec(bContext *C, wmOperator *UNUSED(op))
static void fix_editbone_connected_children(ListBase *edbo, EditBone *ebone)
static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
void ARMATURE_OT_roll_clear(wmOperatorType *ot)
void ARMATURE_OT_fill(wmOperatorType *ot)
static void fix_connected_bone(EditBone *ebone)
static int armature_align_bones_exec(bContext *C, wmOperator *op)
static void chains_find_tips(ListBase *edbo, ListBase *list)
static int armature_split_exec(bContext *C, wmOperator *UNUSED(op))
static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
float ED_armature_ebone_roll_to_vector(const EditBone *bone, const float align_axis[3], const bool axis_only)
static int armature_reveal_exec(bContext *C, wmOperator *op)
static int armature_hide_exec(bContext *C, wmOperator *op)
void ARMATURE_OT_align(wmOperatorType *ot)
static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
static const EnumPropertyItem prop_calc_roll_types[]
void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
static int armature_calc_roll_exec(bContext *C, wmOperator *op)
void ED_armature_origin_set(Main *bmain, Object *ob, const float cursor[3], int centermode, int around)
void ED_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props)
void ARMATURE_OT_switch_direction(wmOperatorType *ot)
void ED_armature_edit_transform(bArmature *arm, const float mat[4][4], const bool do_props)
Definition: armature_edit.c:72
void ARMATURE_OT_dissolve(wmOperatorType *ot)
void ARMATURE_OT_reveal(wmOperatorType *ot)
static bool armature_dissolve_ebone_cb(const char *bone_name, void *arm_p)
static int armature_fill_bones_exec(bContext *C, wmOperator *op)
struct EditBonePoint EditBonePoint
eCalcRollTypes
@ CALC_ROLL_POS_Z
@ CALC_ROLL_VIEW
@ CALC_ROLL_NEG_Y
@ CALC_ROLL_TAN_NEG_Z
@ CALC_ROLL_CURSOR
@ CALC_ROLL_POS_Y
@ CALC_ROLL_NEG_Z
@ CALC_ROLL_TAN_NEG_X
@ CALC_ROLL_TAN_POS_X
@ CALC_ROLL_POS_X
@ CALC_ROLL_TAN_POS_Z
@ CALC_ROLL_ACTIVE
@ CALC_ROLL_NEG_X
void ARMATURE_OT_split(wmOperatorType *ot)
void armature_tag_unselect(struct bArmature *arm)
void armature_select_mirrored(struct bArmature *arm)
void armature_select_mirrored_ex(struct bArmature *arm, const int flag)
void armature_tag_select_mirrored(struct bArmature *arm)
bool ED_armature_edit_deselect_all(Object *obedit)
void ED_armature_edit_refresh_layer_used(bArmature *arm)
void ED_armature_ebone_remove_ex(bArmature *arm, EditBone *exBone, bool clear_connected)
void ED_armature_edit_sync_selection(ListBase *edbo)
int ED_armature_ebone_selectflag_get(const EditBone *ebone)
void ED_armature_ebone_select_set(EditBone *ebone, bool select)
void ED_armature_edit_validate_active(struct bArmature *arm)
void ED_armature_ebone_to_mat3(EditBone *ebone, float r_mat[3][3])
void ED_armature_edit_free(struct bArmature *arm)
void ED_armature_from_edit(Main *bmain, bArmature *arm)
void ED_armature_ebone_remove(bArmature *arm, EditBone *exBone)
EditBone * ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
void ED_armature_to_edit(bArmature *arm)
EditBone * ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
Scene scene
uint nor
int count
#define fabsf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
return ret
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
PropertyRNA * RNA_def_float_rotation(StructOrFunctionRNA *cont_, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:4005
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
#define min(a, b)
Definition: sort.c:51
EditBone * tail_owner
EditBone * head_owner
struct EditBonePoint * next
struct EditBonePoint * prev
struct EditBone * next
Definition: BKE_armature.h:49
float tail[3]
Definition: BKE_armature.h:66
float roll
Definition: BKE_armature.h:62
struct EditBone * ebone
Definition: BKE_armature.h:112
float zwidth
Definition: BKE_armature.h:77
float xwidth
Definition: BKE_armature.h:77
float dist
Definition: BKE_armature.h:75
struct EditBone * parent
Definition: BKE_armature.h:55
void * p
Definition: BKE_armature.h:114
float rad_tail
Definition: BKE_armature.h:78
union EditBone::@2 temp
float rad_head
Definition: BKE_armature.h:78
float head[3]
Definition: BKE_armature.h:65
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
struct bPose * pose
float loc[3]
float imat[4][4]
float obmat[4][4]
void * data
float viewinv[4][4]
View3DCursor cursor
struct EditBone * act_edbone
unsigned int layer
ListBase * edbo
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition: svm_invert.h:19
float max
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982