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