Blender  V3.3
armature_add.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_anim_types.h"
10 #include "DNA_armature_types.h"
11 #include "DNA_constraint_types.h"
12 #include "DNA_object_types.h"
13 #include "DNA_scene_types.h"
14 
15 #include "MEM_guardedalloc.h"
16 
17 #include "BLI_blenlib.h"
18 #include "BLI_ghash.h"
19 #include "BLI_math.h"
20 #include "BLI_string_utils.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_deform.h"
27 #include "BKE_fcurve.h"
28 #include "BKE_idprop.h"
29 #include "BKE_layer.h"
30 #include "BKE_lib_id.h"
31 #include "BKE_library.h"
32 #include "BKE_main.h"
33 
34 #include "RNA_access.h"
35 #include "RNA_define.h"
36 
37 #include "WM_api.h"
38 #include "WM_types.h"
39 
40 #include "ED_armature.h"
41 #include "ED_outliner.h"
42 #include "ED_screen.h"
43 #include "ED_view3d.h"
44 
45 #include "DEG_depsgraph.h"
46 
47 #include "armature_intern.h"
48 
49 /* *************** Adding stuff in editmode *************** */
50 
51 EditBone *ED_armature_ebone_add(bArmature *arm, const char *name)
52 {
53  EditBone *bone = MEM_callocN(sizeof(EditBone), "eBone");
54 
55  BLI_strncpy(bone->name, name, sizeof(bone->name));
57 
58  BLI_addtail(arm->edbo, bone);
59 
60  bone->flag |= BONE_TIPSEL;
61  bone->weight = 1.0f;
62  bone->dist = 0.25f;
63  bone->xwidth = 0.1f;
64  bone->zwidth = 0.1f;
65  bone->rad_head = 0.10f;
66  bone->rad_tail = 0.05f;
67  bone->segments = 1;
68  bone->layer = arm->layer;
69 
70  /* Bendy-Bone parameters */
71  bone->roll1 = 0.0f;
72  bone->roll2 = 0.0f;
73  bone->curve_in_x = 0.0f;
74  bone->curve_in_z = 0.0f;
75  bone->curve_out_x = 0.0f;
76  bone->curve_out_z = 0.0f;
77  bone->ease1 = 1.0f;
78  bone->ease2 = 1.0f;
79 
80  copy_v3_fl(bone->scale_in, 1.0f);
81  copy_v3_fl(bone->scale_out, 1.0f);
82 
83  return bone;
84 }
85 
86 EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool view_aligned)
87 {
88  bArmature *arm = obedit_arm->data;
89  EditBone *bone;
90 
92 
93  /* Create a bone */
94  bone = ED_armature_ebone_add(arm, "Bone");
95 
96  arm->act_edbone = bone;
97 
98  zero_v3(bone->head);
99  zero_v3(bone->tail);
100 
101  bone->tail[view_aligned ? 1 : 2] = length;
102 
103  return bone;
104 }
105 
115 {
116  bArmature *arm;
117  EditBone *ebone, *newbone, *flipbone;
118  float mat[3][3], imat[3][3];
119  int a, to_root = 0;
120  Object *obedit;
121  Scene *scene;
122 
124  obedit = CTX_data_edit_object(C);
125  arm = obedit->data;
126 
127  /* find the active or selected bone */
128  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
129  if (EBONE_VISIBLE(arm, ebone)) {
130  if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone) {
131  break;
132  }
133  }
134  }
135 
136  if (ebone == NULL) {
137  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
138  if (EBONE_VISIBLE(arm, ebone)) {
139  if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone) {
140  break;
141  }
142  }
143  }
144  if (ebone == NULL) {
145  return OPERATOR_CANCELLED;
146  }
147 
148  to_root = 1;
149  }
150 
152 
153  /* we re-use code for mirror editing... */
154  flipbone = NULL;
155  if (arm->flag & ARM_MIRROR_EDIT) {
156  flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
157  }
158 
159  for (a = 0; a < 2; a++) {
160  if (a == 1) {
161  if (flipbone == NULL) {
162  break;
163  }
164  SWAP(EditBone *, flipbone, ebone);
165  }
166 
167  newbone = ED_armature_ebone_add(arm, ebone->name);
168  arm->act_edbone = newbone;
169 
170  if (to_root) {
171  copy_v3_v3(newbone->head, ebone->head);
172  newbone->rad_head = ebone->rad_tail;
173  newbone->parent = ebone->parent;
174  }
175  else {
176  copy_v3_v3(newbone->head, ebone->tail);
177  newbone->rad_head = ebone->rad_tail;
178  newbone->parent = ebone;
179  newbone->flag |= BONE_CONNECTED;
180  }
181 
182  const View3DCursor *curs = &scene->cursor;
183  copy_v3_v3(newbone->tail, curs->location);
184  sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
185 
186  if (a == 1) {
187  newbone->tail[0] = -newbone->tail[0];
188  }
189 
190  copy_m3_m4(mat, obedit->obmat);
191  invert_m3_m3(imat, mat);
192  mul_m3_v3(imat, newbone->tail);
193 
194  newbone->length = len_v3v3(newbone->head, newbone->tail);
195  newbone->rad_tail = newbone->length * 0.05f;
196  newbone->dist = newbone->length * 0.25f;
197  }
198 
200 
204 
205  return OPERATOR_FINISHED;
206 }
207 
209 {
210  /* TODO: most of this code is copied from set3dcursor_invoke,
211  * it would be better to reuse code in set3dcursor_invoke */
212 
213  /* temporarily change 3d cursor position */
214  Scene *scene;
215  ARegion *region;
216  View3D *v3d;
217  float tvec[3], oldcurs[3], mval_f[2];
218 
220  region = CTX_wm_region(C);
221  v3d = CTX_wm_view3d(C);
222 
223  View3DCursor *cursor = &scene->cursor;
224 
225  copy_v3_v3(oldcurs, cursor->location);
226 
227  copy_v2fl_v2i(mval_f, event->mval);
228  ED_view3d_win_to_3d(v3d, region, cursor->location, mval_f, tvec);
229  copy_v3_v3(cursor->location, tvec);
230 
231  /* extrude to the where new cursor is and store the operation result */
232  int retval = armature_click_extrude_exec(C, op);
233 
234  /* restore previous 3d cursor position */
235  copy_v3_v3(cursor->location, oldcurs);
236 
237  /* Support dragging to move after extrude, see: #114282. */
238  if (retval & OPERATOR_FINISHED) {
239  retval |= OPERATOR_PASS_THROUGH;
240  }
241  return WM_operator_flag_only_pass_through_on_press(retval, event);
242 }
243 
245 {
246  /* identifiers */
247  ot->name = "Extrude to Cursor";
248  ot->idname = "ARMATURE_OT_click_extrude";
249  ot->description = "Create a new bone going from the last selected joint to the mouse position";
250 
251  /* api callbacks */
255 
256  /* flags */
258 
259  /* props */
260 }
261 
262 EditBone *add_points_bone(Object *obedit, float head[3], float tail[3])
263 {
264  EditBone *ebo;
265 
266  ebo = ED_armature_ebone_add(obedit->data, "Bone");
267 
268  copy_v3_v3(ebo->head, head);
269  copy_v3_v3(ebo->tail, tail);
270 
271  return ebo;
272 }
273 
274 static EditBone *get_named_editbone(ListBase *edbo, const char *name)
275 {
276  EditBone *eBone;
277 
278  if (name) {
279  for (eBone = edbo->first; eBone; eBone = eBone->next) {
280  if (STREQ(name, eBone->name)) {
281  return eBone;
282  }
283  }
284  }
285 
286  return NULL;
287 }
288 
290 {
291  /* clear temp */
293 }
294 
300  GHash *name_map,
301  bPoseChannel *pchan_src)
302 {
303  bPoseChannel *pchan_dst = NULL;
304  const char *name_src = pchan_src->name;
305  const char *name_dst = BLI_ghash_lookup(name_map, name_src);
306  if (name_dst) {
307  pchan_dst = BKE_pose_channel_find_name(pose, name_dst);
308  }
309 
310  if (pchan_dst == NULL) {
311  pchan_dst = pchan_src;
312  }
313 
314  return pchan_dst;
315 }
316 
317 void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
318 {
319  if (ob->pose == NULL) {
320  return;
321  }
322 
325 
326  GHash *name_map = BLI_ghash_str_new(__func__);
327 
328  LISTBASE_FOREACH (EditBone *, ebone_src, editbones) {
329  EditBone *ebone_dst = ebone_src->temp.ebone;
330  if (!ebone_dst) {
331  ebone_dst = ED_armature_ebone_get_mirrored(editbones, ebone_src);
332  }
333  if (ebone_dst) {
334  BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name);
335  }
336  }
337 
338  LISTBASE_FOREACH (EditBone *, ebone_src, editbones) {
339  EditBone *ebone_dst = ebone_src->temp.ebone;
340  if (ebone_dst) {
341  bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name);
342  if (pchan_src) {
343  bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name);
344  if (pchan_dst) {
345  if (pchan_src->custom_tx) {
346  pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx);
347  }
348  if (pchan_src->bbone_prev) {
349  pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev);
350  }
351  if (pchan_src->bbone_next) {
352  pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next);
353  }
354  }
355  }
356  }
357  }
358 
359  BLI_ghash_free(name_map, NULL, NULL);
360 }
361 
362 static void updateDuplicateSubtarget(EditBone *dup_bone,
363  ListBase *editbones,
364  Object *ob,
365  bool lookup_mirror_subtarget)
366 {
367  /* If an edit bone has been duplicated, lets update its constraints if the
368  * subtarget they point to has also been duplicated.
369  */
370  EditBone *oldtarget, *newtarget;
371  bPoseChannel *pchan;
372  bConstraint *curcon;
373  ListBase *conlist;
374 
375  if ((pchan = BKE_pose_channel_ensure(ob->pose, dup_bone->name))) {
376  if ((conlist = &pchan->constraints)) {
377  for (curcon = conlist->first; curcon; curcon = curcon->next) {
378  /* does this constraint have a subtarget in
379  * this armature?
380  */
381  ListBase targets = {NULL, NULL};
382  bConstraintTarget *ct;
383 
384  if (BKE_constraint_targets_get(curcon, &targets)) {
385  for (ct = targets.first; ct; ct = ct->next) {
386  if ((ct->tar == ob) && (ct->subtarget[0])) {
387  oldtarget = get_named_editbone(editbones, ct->subtarget);
388  if (oldtarget) {
389  /* was the subtarget bone duplicated too? If
390  * so, update the constraint to point at the
391  * duplicate of the old subtarget.
392  */
393  if (oldtarget->temp.ebone) {
394  newtarget = oldtarget->temp.ebone;
395  BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
396  }
397  else if (lookup_mirror_subtarget) {
398  /* The subtarget was not selected for duplication, try to see if a mirror bone of
399  * the current target exists */
400  char name_flip[MAXBONENAME];
401 
402  BLI_string_flip_side_name(name_flip, oldtarget->name, false, sizeof(name_flip));
403  newtarget = get_named_editbone(editbones, name_flip);
404  if (newtarget) {
405  BLI_strncpy(ct->subtarget, newtarget->name, sizeof(ct->subtarget));
406  }
407  }
408  }
409  }
410  }
411 
412  BKE_constraint_targets_flush(curcon, &targets, 0);
413  }
414  }
415  }
416  }
417 }
418 
420  EditBone *dup_bone, EditBone *orig_bone, Object *ob, bPoseChannel *pchan, bConstraint *curcon)
421 {
422  bActionConstraint *act_con = (bActionConstraint *)curcon->data;
423  bAction *act = (bAction *)act_con->act;
424 
425  float mat[4][4];
426 
427  bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan};
429 
430  unit_m4(mat);
431  bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, act_con->subtarget);
433  ob, target_pchan, &cob, mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false);
434 
435  float max_axis_val = 0;
436  int max_axis = 0;
437  /* Which axis represents X now. IE, which axis defines the mirror plane. */
438  for (int i = 0; i < 3; i++) {
439  float cur_val = fabsf(mat[0][i]);
440  if (cur_val > max_axis_val) {
441  max_axis = i;
442  max_axis_val = cur_val;
443  }
444  }
445 
446  /* data->type is mapped as follows for backwards compatibility:
447  * 00,01,02 - rotation (it used to be like this)
448  * 10,11,12 - scaling
449  * 20,21,22 - location
450  */
451  /* Mirror the target range */
452  if (act_con->type < 10 && act_con->type != max_axis) {
453  /* Y or Z rotation */
454  act_con->min = -act_con->min;
455  act_con->max = -act_con->max;
456  }
457  else if (act_con->type == max_axis + 10) {
458  /* X scaling */
459  }
460  else if (act_con->type == max_axis + 20) {
461  /* X location */
462  float imat[4][4];
463 
464  invert_m4_m4(imat, mat);
465 
466  float min_vec[3], max_vec[3];
467 
468  zero_v3(min_vec);
469  zero_v3(max_vec);
470 
471  min_vec[0] = act_con->min;
472  max_vec[0] = act_con->max;
473 
474  /* convert values into local object space */
475  mul_m4_v3(mat, min_vec);
476  mul_m4_v3(mat, max_vec);
477 
478  min_vec[0] *= -1;
479  max_vec[0] *= -1;
480 
481  /* convert back to the settings space */
482  mul_m4_v3(imat, min_vec);
483  mul_m4_v3(imat, max_vec);
484 
485  act_con->min = min_vec[0];
486  act_con->max = max_vec[0];
487  }
488 
489  /* See if there is any channels that uses this bone */
490  ListBase ani_curves;
491  BLI_listbase_clear(&ani_curves);
492  if ((act != NULL) &&
493  BKE_fcurves_filter(&ani_curves, &act->curves, "pose.bones[", orig_bone->name)) {
494  /* Create a copy and mirror the animation */
495  for (LinkData *ld = ani_curves.first; ld; ld = ld->next) {
496  FCurve *old_curve = ld->data;
497  FCurve *new_curve = BKE_fcurve_copy(old_curve);
498  bActionGroup *agrp;
499 
500  char *old_path = new_curve->rna_path;
501 
502  new_curve->rna_path = BLI_str_replaceN(old_path, orig_bone->name, dup_bone->name);
503  MEM_freeN(old_path);
504 
505  /* Flip the animation */
506  int i;
507  BezTriple *bezt;
508  for (i = 0, bezt = new_curve->bezt; i < new_curve->totvert; i++, bezt++) {
509  const size_t slength = strlen(new_curve->rna_path);
510  bool flip = false;
511  if (BLI_strn_endswith(new_curve->rna_path, "location", slength) &&
512  new_curve->array_index == 0) {
513  flip = true;
514  }
515  else if (BLI_strn_endswith(new_curve->rna_path, "rotation_quaternion", slength) &&
516  ELEM(new_curve->array_index, 2, 3)) {
517  flip = true;
518  }
519  else if (BLI_strn_endswith(new_curve->rna_path, "rotation_euler", slength) &&
520  ELEM(new_curve->array_index, 1, 2)) {
521  flip = true;
522  }
523  else if (BLI_strn_endswith(new_curve->rna_path, "rotation_axis_angle", slength) &&
524  ELEM(new_curve->array_index, 2, 3)) {
525  flip = true;
526  }
527 
528  if (flip) {
529  bezt->vec[0][1] *= -1;
530  bezt->vec[1][1] *= -1;
531  bezt->vec[2][1] *= -1;
532  }
533  }
534 
535  /* Make sure that a action group name for the new bone exists */
536  agrp = BKE_action_group_find_name(act, dup_bone->name);
537 
538  if (agrp == NULL) {
539  agrp = action_groups_add_new(act, dup_bone->name);
540  }
541  BLI_assert(agrp != NULL);
542  action_groups_add_channel(act, agrp, new_curve);
543  }
544  }
545  BLI_freelistN(&ani_curves);
546 
547  /* Make deps graph aware of our changes */
549 }
550 
552 {
553  /* IK constraint */
555  ik->poleangle = -M_PI - ik->poleangle;
556  /* Wrap the angle to the +/-180.0f range (default soft limit of the input boxes). */
558 }
559 
561  bPoseChannel *pchan,
562  bConstraint *curcon)
563 {
564  /* This code assumes that bRotLimitConstraint and bLocLimitConstraint have the same fields in
565  * the same memory locations. */
566  bRotLimitConstraint *limit = (bRotLimitConstraint *)curcon->data;
567  float local_mat[4][4], imat[4][4];
568 
569  float min_vec[3], max_vec[3];
570 
571  min_vec[0] = limit->xmin;
572  min_vec[1] = limit->ymin;
573  min_vec[2] = limit->zmin;
574 
575  max_vec[0] = limit->xmax;
576  max_vec[1] = limit->ymax;
577  max_vec[2] = limit->zmax;
578 
579  unit_m4(local_mat);
580 
581  bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan};
583 
585  ob, pchan, &cob, local_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false);
586 
587  if (curcon->type == CONSTRAINT_TYPE_ROTLIMIT) {
588  /* Zero out any location translation */
589  local_mat[3][0] = local_mat[3][1] = local_mat[3][2] = 0;
590  }
591 
592  invert_m4_m4(imat, local_mat);
593  /* convert values into local object space */
594  mul_m4_v3(local_mat, min_vec);
595  mul_m4_v3(local_mat, max_vec);
596 
597  if (curcon->type == CONSTRAINT_TYPE_ROTLIMIT) {
598  float min_copy[3];
599 
600  copy_v3_v3(min_copy, min_vec);
601 
602  min_vec[1] = max_vec[1] * -1;
603  min_vec[2] = max_vec[2] * -1;
604 
605  max_vec[1] = min_copy[1] * -1;
606  max_vec[2] = min_copy[2] * -1;
607  }
608  else {
609  float min_x_copy = min_vec[0];
610 
611  min_vec[0] = max_vec[0] * -1;
612  max_vec[0] = min_x_copy * -1;
613  }
614 
615  /* convert back to the settings space */
616  mul_m4_v3(imat, min_vec);
617  mul_m4_v3(imat, max_vec);
618 
619  limit->xmin = min_vec[0];
620  limit->ymin = min_vec[1];
621  limit->zmin = min_vec[2];
622 
623  limit->xmax = max_vec[0];
624  limit->ymax = max_vec[1];
625  limit->zmax = max_vec[2];
626 }
627 
629  bPoseChannel *pchan,
630  bConstraint *curcon)
631 {
632  bTransformConstraint *trans = (bTransformConstraint *)curcon->data;
633 
634  float target_mat[4][4], own_mat[4][4], imat[4][4];
635 
636  bConstraintOb cob = {.depsgraph = NULL, .scene = NULL, .ob = ob, .pchan = pchan};
638 
639  unit_m4(own_mat);
641  ob, pchan, &cob, own_mat, curcon->ownspace, CONSTRAINT_SPACE_LOCAL, false);
642 
643  /* ###Source map mirroring### */
644  float old_min, old_max;
645 
646  /* Source location */
647  invert_m4_m4(imat, own_mat);
648 
649  /* convert values into local object space */
650  mul_m4_v3(own_mat, trans->from_min);
651  mul_m4_v3(own_mat, trans->from_max);
652 
653  old_min = trans->from_min[0];
654  old_max = trans->from_max[0];
655 
656  trans->from_min[0] = -old_max;
657  trans->from_max[0] = -old_min;
658 
659  /* convert back to the settings space */
660  mul_m4_v3(imat, trans->from_min);
661  mul_m4_v3(imat, trans->from_max);
662 
663  /* Source rotation */
664 
665  /* Zero out any location translation */
666  own_mat[3][0] = own_mat[3][1] = own_mat[3][2] = 0;
667 
668  invert_m4_m4(imat, own_mat);
669 
670  /* convert values into local object space */
671  mul_m4_v3(own_mat, trans->from_min_rot);
672  mul_m4_v3(own_mat, trans->from_max_rot);
673 
674  old_min = trans->from_min_rot[1];
675  old_max = trans->from_max_rot[1];
676 
677  trans->from_min_rot[1] = old_max * -1;
678  trans->from_max_rot[1] = old_min * -1;
679 
680  old_min = trans->from_min_rot[2];
681  old_max = trans->from_max_rot[2];
682 
683  trans->from_min_rot[2] = old_max * -1;
684  trans->from_max_rot[2] = old_min * -1;
685 
686  /* convert back to the settings space */
687  mul_m4_v3(imat, trans->from_min_rot);
688  mul_m4_v3(imat, trans->from_max_rot);
689 
690  /* Source scale does not require any mirroring */
691 
692  /* ###Destination map mirroring### */
693  float temp_vec[3];
694  float imat_rot[4][4];
695 
696  bPoseChannel *target_pchan = BKE_pose_channel_find_name(ob->pose, trans->subtarget);
697  unit_m4(target_mat);
699  ob, target_pchan, &cob, target_mat, curcon->tarspace, CONSTRAINT_SPACE_LOCAL, false);
700 
701  invert_m4_m4(imat, target_mat);
702  /* convert values into local object space */
703  mul_m4_v3(target_mat, trans->to_min);
704  mul_m4_v3(target_mat, trans->to_max);
705  mul_m4_v3(target_mat, trans->to_min_scale);
706  mul_m4_v3(target_mat, trans->to_max_scale);
707 
708  /* Zero out any location translation */
709  target_mat[3][0] = target_mat[3][1] = target_mat[3][2] = 0;
710  invert_m4_m4(imat_rot, target_mat);
711 
712  mul_m4_v3(target_mat, trans->to_min_rot);
713  mul_m4_v3(target_mat, trans->to_max_rot);
714 
715  /* TODO(sebpa): This does not support euler order, but doing so will make this way more complex.
716  * For now we have decided to not support all corner cases and advanced setups. */
717 
718  /* Helper variables to denote the axis in trans->map */
719  const char X = 0;
720  const char Y = 1;
721  const char Z = 2;
722 
723  switch (trans->to) {
724  case TRANS_SCALE:
725  copy_v3_v3(temp_vec, trans->to_max_scale);
726 
727  for (int i = 0; i < 3; i++) {
728  if ((trans->from == TRANS_LOCATION && trans->map[i] == X) ||
729  (trans->from == TRANS_ROTATION && trans->map[i] != X)) {
730  /* X Loc to X/Y/Z Scale: Min/Max Flipped */
731  /* Y Rot to X/Y/Z Scale: Min/Max Flipped */
732  /* Z Rot to X/Y/Z Scale: Min/Max Flipped */
733  trans->to_max_scale[i] = trans->to_min_scale[i];
734  trans->to_min_scale[i] = temp_vec[i];
735  }
736  }
737  break;
738  case TRANS_LOCATION:
739  /* Invert the X location */
740  trans->to_min[0] *= -1;
741  trans->to_max[0] *= -1;
742 
743  copy_v3_v3(temp_vec, trans->to_max);
744 
745  for (int i = 0; i < 3; i++) {
746  if ((trans->from == TRANS_LOCATION && trans->map[i] == X) ||
747  (trans->from == TRANS_ROTATION && trans->map[i] != X)) {
748  /* X Loc to X/Y/Z Loc: Min/Max Flipped (and Inverted)
749  * Y Rot to X/Y/Z Loc: Min/Max Flipped
750  * Z Rot to X/Y/Z Loc: Min/Max Flipped */
751  trans->to_max[i] = trans->to_min[i];
752  trans->to_min[i] = temp_vec[i];
753  }
754  }
755  break;
756  case TRANS_ROTATION:
757  /* Invert the Z rotation */
758  trans->to_min_rot[2] *= -1;
759  trans->to_max_rot[2] *= -1;
760 
761  if ((trans->from == TRANS_LOCATION && trans->map[1] != X) ||
762  (trans->from == TRANS_ROTATION && trans->map[1] != Y) || trans->from == TRANS_SCALE) {
763  /* Invert the Y rotation */
764  trans->to_min_rot[1] *= -1;
765  trans->to_max_rot[1] *= -1;
766  }
767 
768  copy_v3_v3(temp_vec, trans->to_max_rot);
769 
770  for (int i = 0; i < 3; i++) {
771  if ((trans->from == TRANS_LOCATION && trans->map[i] == X && i != 1) ||
772  (trans->from == TRANS_ROTATION && trans->map[i] == Y && i != 1) ||
773  (trans->from == TRANS_ROTATION && trans->map[i] == Z)) {
774  /* X Loc to X/Z Rot: Flipped
775  * Y Rot to X/Z Rot: Flipped
776  * Z Rot to X/Y/Z rot: Flipped */
777  trans->to_max_rot[i] = trans->to_min_rot[i];
778  trans->to_min_rot[i] = temp_vec[i];
779  }
780  }
781 
782  if (trans->from == TRANS_ROTATION && trans->map[1] == Y) {
783  /* Y Rot to Y Rot: Flip and invert */
784  trans->to_max_rot[1] = -trans->to_min_rot[1];
785  trans->to_min_rot[1] = -temp_vec[1];
786  }
787 
788  break;
789  }
790  /* convert back to the settings space */
791  mul_m4_v3(imat, trans->to_min);
792  mul_m4_v3(imat, trans->to_max);
793  mul_m4_v3(imat_rot, trans->to_min_rot);
794  mul_m4_v3(imat_rot, trans->to_max_rot);
795  mul_m4_v3(imat, trans->to_min_scale);
796  mul_m4_v3(imat, trans->to_max_scale);
797 }
798 
799 static void updateDuplicateConstraintSettings(EditBone *dup_bone, EditBone *orig_bone, Object *ob)
800 {
801  /* If an edit bone has been duplicated, lets update its constraints if the
802  * subtarget they point to has also been duplicated.
803  */
804  bPoseChannel *pchan;
805  bConstraint *curcon;
806  ListBase *conlist;
807 
808  if ((pchan = BKE_pose_channel_ensure(ob->pose, dup_bone->name)) == NULL ||
809  (conlist = &pchan->constraints) == NULL) {
810  return;
811  }
812 
813  for (curcon = conlist->first; curcon; curcon = curcon->next) {
814  switch (curcon->type) {
816  updateDuplicateActionConstraintSettings(dup_bone, orig_bone, ob, pchan, curcon);
817  break;
820  break;
823  updateDuplicateLocRotConstraintSettings(ob, pchan, curcon);
824  break;
827  break;
828  }
829  }
830 }
831 
833 {
834  if (ob->pose == NULL) {
835  return;
836  }
837  bPoseChannel *pchan;
838  pchan = BKE_pose_channel_ensure(ob->pose, dup_bone->name);
839 
840  if (pchan->custom != NULL) {
841  Main *bmain = CTX_data_main(C);
842  char name_flip[MAX_ID_NAME - 2];
843 
844  /* Invert the X location */
845  pchan->custom_translation[0] *= -1;
846  /* Invert the Y rotation */
847  pchan->custom_rotation_euler[1] *= -1;
848  /* Invert the Z rotation */
849  pchan->custom_rotation_euler[2] *= -1;
850 
851  /* Skip the first two chars in the object name as those are used to store object type */
852  BLI_string_flip_side_name(name_flip, pchan->custom->id.name + 2, false, sizeof(name_flip));
853  Object *shape_ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name_flip);
854 
855  /* If name_flip doesn't exist, BKE_libblock_find_name() returns pchan->custom (best match) */
856  shape_ob = shape_ob == pchan->custom ? NULL : shape_ob;
857 
858  if (shape_ob != NULL) {
859  /* A flipped shape object exists, use it! */
860  pchan->custom = shape_ob;
861  }
862  else {
863  /* Flip shape */
864  pchan->custom_scale_xyz[0] *= -1;
865  }
866  }
867 }
868 
869 static void copy_pchan(EditBone *src_bone, EditBone *dst_bone, Object *src_ob, Object *dst_ob)
870 {
871  /* copy the ID property */
872  if (src_bone->prop) {
873  dst_bone->prop = IDP_CopyProperty(src_bone->prop);
874  }
875 
876  /* Lets duplicate the list of constraints that the
877  * current bone has.
878  */
879  if (src_ob->pose) {
880  bPoseChannel *chanold, *channew;
881 
882  chanold = BKE_pose_channel_ensure(src_ob->pose, src_bone->name);
883  if (chanold) {
884  /* WARNING: this creates a new posechannel, but there will not be an attached bone
885  * yet as the new bones created here are still 'EditBones' not 'Bones'.
886  */
887  channew = BKE_pose_channel_ensure(dst_ob->pose, dst_bone->name);
888 
889  if (channew) {
890  BKE_pose_channel_copy_data(channew, chanold);
891  }
892  }
893  }
894 }
895 
897  EditBone *cur_bone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
898 {
899  EditBone *e_bone = MEM_mallocN(sizeof(EditBone), "addup_editbone");
900 
901  /* Copy data from old bone to new bone */
902  memcpy(e_bone, cur_bone, sizeof(EditBone));
903 
904  cur_bone->temp.ebone = e_bone;
905  e_bone->temp.ebone = cur_bone;
906 
907  if (name != NULL) {
908  BLI_strncpy(e_bone->name, name, sizeof(e_bone->name));
909  }
910 
911  ED_armature_ebone_unique_name(editbones, e_bone->name, NULL);
912  BLI_addtail(editbones, e_bone);
913 
914  copy_pchan(cur_bone, e_bone, src_ob, dst_ob);
915 
916  return e_bone;
917 }
918 
919 EditBone *duplicateEditBone(EditBone *cur_bone, const char *name, ListBase *editbones, Object *ob)
920 {
921  return duplicateEditBoneObjects(cur_bone, name, editbones, ob, ob);
922 }
923 
925 {
926  ViewLayer *view_layer = CTX_data_view_layer(C);
927  const bool do_flip_names = RNA_boolean_get(op->ptr, "do_flip_names");
928 
929  /* cancel if nothing selected */
930  if (CTX_DATA_COUNT(C, selected_bones) == 0) {
931  return OPERATOR_CANCELLED;
932  }
933 
934  uint objects_len = 0;
936  view_layer, CTX_wm_view3d(C), &objects_len);
937  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
938  EditBone *ebone_iter;
939  /* The beginning of the duplicated bones in the edbo list */
940  EditBone *ebone_first_dupe = NULL;
941 
942  Object *ob = objects[ob_index];
943  bArmature *arm = ob->data;
944 
945  ED_armature_edit_sync_selection(arm->edbo); /* XXX why is this needed? */
946 
948 
949  /* Select mirrored bones */
950  if (arm->flag & ARM_MIRROR_EDIT) {
951  for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
952  if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
953  EditBone *ebone;
954 
955  ebone = ED_armature_ebone_get_mirrored(arm->edbo, ebone_iter);
956  if (ebone) {
957  ebone->flag |= BONE_SELECTED;
958  }
959  }
960  }
961  }
962 
963  /* Find the selected bones and duplicate them as needed */
964  for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
965  ebone_iter = ebone_iter->next) {
966  if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
967  EditBone *ebone;
968  char new_bone_name_buff[MAXBONENAME];
969  char *new_bone_name = ebone_iter->name;
970 
971  if (do_flip_names) {
973  new_bone_name_buff, ebone_iter->name, false, sizeof(new_bone_name_buff));
974 
975  /* Only use flipped name if not yet in use. Otherwise we'd get again inconsistent
976  * namings (different numbers), better keep default behavior in this case. */
977  if (ED_armature_ebone_find_name(arm->edbo, new_bone_name_buff) == NULL) {
978  new_bone_name = new_bone_name_buff;
979  }
980  }
981 
982  ebone = duplicateEditBone(ebone_iter, new_bone_name, arm->edbo, ob);
983 
984  if (!ebone_first_dupe) {
985  ebone_first_dupe = ebone;
986  }
987  }
988  }
989 
990  /* Run though the list and fix the pointers */
991  for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
992  ebone_iter = ebone_iter->next) {
993  if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
994  EditBone *ebone = ebone_iter->temp.ebone;
995 
996  if (!ebone_iter->parent) {
997  /* If this bone has no parent,
998  * Set the duplicate->parent to NULL
999  */
1000  ebone->parent = NULL;
1001  }
1002  else if (ebone_iter->parent->temp.ebone) {
1003  /* If this bone has a parent that was duplicated,
1004  * Set the duplicate->parent to the cur_bone->parent->temp
1005  */
1006  ebone->parent = ebone_iter->parent->temp.ebone;
1007  }
1008  else {
1009  /* If this bone has a parent that IS not selected,
1010  * Set the duplicate->parent to the cur_bone->parent
1011  */
1012  ebone->parent = (EditBone *)ebone_iter->parent;
1013  ebone->flag &= ~BONE_CONNECTED;
1014  }
1015 
1016  /* Update custom handle links. */
1017  if (ebone_iter->bbone_prev && ebone_iter->bbone_prev->temp.ebone) {
1018  ebone->bbone_prev = ebone_iter->bbone_prev->temp.ebone;
1019  }
1020  if (ebone_iter->bbone_next && ebone_iter->bbone_next->temp.ebone) {
1021  ebone->bbone_next = ebone_iter->bbone_next->temp.ebone;
1022  }
1023 
1024  /* Lets try to fix any constraint subtargets that might
1025  * have been duplicated
1026  */
1027  updateDuplicateSubtarget(ebone, arm->edbo, ob, false);
1028  }
1029  }
1030 
1031  /* correct the active bone */
1032  if (arm->act_edbone && arm->act_edbone->temp.ebone) {
1033  arm->act_edbone = arm->act_edbone->temp.ebone;
1034  }
1035 
1036  /* Deselect the old bones and select the new ones */
1037  for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
1038  ebone_iter = ebone_iter->next) {
1039  if (EBONE_VISIBLE(arm, ebone_iter)) {
1040  ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1041  }
1042  }
1043 
1044  postEditBoneDuplicate(arm->edbo, ob);
1045 
1047 
1050  }
1051  MEM_freeN(objects);
1052 
1054 
1055  return OPERATOR_FINISHED;
1056 }
1057 
1059 {
1060  /* identifiers */
1061  ot->name = "Duplicate Selected Bone(s)";
1062  ot->idname = "ARMATURE_OT_duplicate";
1063  ot->description = "Make copies of the selected bones within the same armature";
1064 
1065  /* api callbacks */
1068 
1069  /* flags */
1071 
1073  ot->srna,
1074  "do_flip_names",
1075  false,
1076  "Flip Names",
1077  "Try to flip names of the bones, if possible, instead of adding a number extension");
1078 }
1079 
1080 /* Get the duplicated or existing mirrored copy of the bone. */
1082 {
1083  if (bone == NULL) {
1084  return NULL;
1085  }
1086  if (bone->temp.ebone != NULL) {
1087  return bone->temp.ebone;
1088  }
1089 
1090  EditBone *mirror = ED_armature_ebone_get_mirrored(arm->edbo, bone);
1091  return (mirror != NULL) ? mirror : bone;
1092 }
1093 
1099 {
1100  ViewLayer *view_layer = CTX_data_view_layer(C);
1101  const int direction = RNA_enum_get(op->ptr, "direction");
1102  const int axis = 0;
1103 
1104  /* cancel if nothing selected */
1105  if (CTX_DATA_COUNT(C, selected_bones) == 0) {
1106  return OPERATOR_CANCELLED;
1107  }
1108 
1109  uint objects_len = 0;
1111  view_layer, CTX_wm_view3d(C), &objects_len);
1112  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1113  Object *obedit = objects[ob_index];
1114  bArmature *arm = obedit->data;
1115 
1116  EditBone *ebone_iter;
1117  /* The beginning of the duplicated mirrored bones in the edbo list */
1118  EditBone *ebone_first_dupe = NULL;
1119 
1120  ED_armature_edit_sync_selection(arm->edbo); /* XXX why is this needed? */
1121 
1122  preEditBoneDuplicate(arm->edbo);
1123 
1124  /* Select mirrored bones */
1125  for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1126  if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
1127  char name_flip[MAXBONENAME];
1128 
1129  BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
1130 
1131  if (STREQ(name_flip, ebone_iter->name)) {
1132  /* if the name matches, we don't have the potential to be mirrored, just skip */
1133  ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1134  }
1135  else {
1136  EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip);
1137 
1138  if (ebone) {
1139  if ((ebone->flag & BONE_SELECTED) == 0) {
1140  /* simple case, we're selected, the other bone isn't! */
1141  ebone_iter->temp.ebone = ebone;
1142  }
1143  else {
1144  /* complicated - choose which direction to copy */
1145  float axis_delta;
1146 
1147  axis_delta = ebone->head[axis] - ebone_iter->head[axis];
1148  if (axis_delta == 0.0f) {
1149  axis_delta = ebone->tail[axis] - ebone_iter->tail[axis];
1150  }
1151 
1152  if (axis_delta == 0.0f) {
1153  /* Both mirrored bones exist and point to each other and overlap exactly.
1154  *
1155  * in this case there's no well defined solution, so de-select both and skip.
1156  */
1157  ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1158  ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1159  }
1160  else {
1161  EditBone *ebone_src, *ebone_dst;
1162  if (((axis_delta < 0.0f) ? -1 : 1) == direction) {
1163  ebone_src = ebone;
1164  ebone_dst = ebone_iter;
1165  }
1166  else {
1167  ebone_src = ebone_iter;
1168  ebone_dst = ebone;
1169  }
1170 
1171  ebone_src->temp.ebone = ebone_dst;
1172  ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1173  }
1174  }
1175  }
1176  }
1177  }
1178  }
1179 
1180  /* Find the selected bones and duplicate them as needed, with mirrored name. */
1181  for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
1182  ebone_iter = ebone_iter->next) {
1183  if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) {
1184  if (ebone_iter->temp.ebone != NULL) {
1185  /* This will be set if the mirror bone already exists (no need to make a new one)
1186  * but we do need to make sure that the 'pchan' settings (constraints etc)
1187  * is synchronized. */
1188  bPoseChannel *pchan;
1189  /* Make sure we clean up the old data before overwriting it */
1190  pchan = BKE_pose_channel_ensure(obedit->pose, ebone_iter->temp.ebone->name);
1191  BKE_pose_channel_free(pchan);
1192  /* Sync pchan data */
1193  copy_pchan(ebone_iter, ebone_iter->temp.ebone, obedit, obedit);
1194  /* Sync scale mode */
1195  ebone_iter->temp.ebone->inherit_scale_mode = ebone_iter->inherit_scale_mode;
1196  continue;
1197  }
1198  char name_flip[MAXBONENAME];
1199 
1200  BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip));
1201 
1202  /* bones must have a side-suffix */
1203  if (!STREQ(name_flip, ebone_iter->name)) {
1204  EditBone *ebone;
1205 
1206  ebone = duplicateEditBone(ebone_iter, name_flip, arm->edbo, obedit);
1207 
1208  if (!ebone_first_dupe) {
1209  ebone_first_dupe = ebone;
1210  }
1211  }
1212  }
1213  }
1214 
1215  /* Run through the list and fix the pointers. */
1216  for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
1217  ebone_iter = ebone_iter->next) {
1218  if (ebone_iter->temp.ebone) {
1219  /* copy all flags except for ... */
1220  const int flag_copy = ((int)~0) & ~(BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
1221 
1222  EditBone *ebone = ebone_iter->temp.ebone;
1223 
1224  /* Copy flags in case bone is pre-existing data. */
1225  ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy);
1226 
1227  if (ebone_iter->parent == NULL) {
1228  /* If this bone has no parent,
1229  * Set the duplicate->parent to NULL
1230  */
1231  ebone->parent = NULL;
1232  ebone->flag &= ~BONE_CONNECTED;
1233  }
1234  else {
1235  /* the parent may have been duplicated, if not lookup the mirror parent */
1236  EditBone *ebone_parent = get_symmetrized_bone(arm, ebone_iter->parent);
1237 
1238  if (ebone_parent == ebone_iter->parent) {
1239  /* If the mirror lookup failed, (but the current bone has a parent)
1240  * then we can assume the parent has no L/R but is a center bone.
1241  * So just use the same parent for both.
1242  */
1243 
1244  if (ebone->head[axis] != 0.0f) {
1245  /* The mirrored bone doesn't start on the mirror axis, so assume that this one should
1246  * not be connected to the old parent */
1247  ebone->flag &= ~BONE_CONNECTED;
1248  }
1249  }
1250 
1251  ebone->parent = ebone_parent;
1252  }
1253 
1254  /* Update custom handle links. */
1255  ebone->bbone_prev = get_symmetrized_bone(arm, ebone_iter->bbone_prev);
1256  ebone->bbone_next = get_symmetrized_bone(arm, ebone_iter->bbone_next);
1257 
1258  /* Sync bbone handle types */
1259  ebone->bbone_prev_type = ebone_iter->bbone_prev_type;
1260  ebone->bbone_next_type = ebone_iter->bbone_next_type;
1261 
1262  ebone->bbone_flag = ebone_iter->bbone_flag;
1263  ebone->bbone_prev_flag = ebone_iter->bbone_prev_flag;
1264  ebone->bbone_next_flag = ebone_iter->bbone_next_flag;
1265 
1266  /* Lets try to fix any constraint subtargets that might
1267  * have been duplicated
1268  */
1269  updateDuplicateSubtarget(ebone, arm->edbo, obedit, true);
1270  /* Try to update constraint options so that they are mirrored as well
1271  * (need to supply bone_iter as well in case we are working with existing bones) */
1272  updateDuplicateConstraintSettings(ebone, ebone_iter, obedit);
1273  /* Mirror bone shapes if possible */
1274  updateDuplicateCustomBoneShapes(C, ebone, obedit);
1275  }
1276  }
1277 
1279 
1280  /* Selected bones now have their 'temp' pointer set,
1281  * so we don't need this anymore */
1282 
1283  /* Deselect the old bones and select the new ones */
1284  for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
1285  ebone_iter = ebone_iter->next) {
1286  if (EBONE_VISIBLE(arm, ebone_iter)) {
1287  ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1288  }
1289  }
1290 
1291  /* New bones will be selected, but some of the bones may already exist */
1292  for (ebone_iter = arm->edbo->first; ebone_iter && ebone_iter != ebone_first_dupe;
1293  ebone_iter = ebone_iter->next) {
1294  EditBone *ebone = ebone_iter->temp.ebone;
1295  if (ebone && EBONE_SELECTABLE(arm, ebone)) {
1296  ED_armature_ebone_select_set(ebone, true);
1297  }
1298  }
1299 
1300  /* correct the active bone */
1301  if (arm->act_edbone && arm->act_edbone->temp.ebone) {
1302  arm->act_edbone = arm->act_edbone->temp.ebone;
1303  }
1304 
1305  postEditBoneDuplicate(arm->edbo, obedit);
1306 
1308 
1311  }
1312  MEM_freeN(objects);
1313 
1314  return OPERATOR_FINISHED;
1315 }
1316 
1318 {
1319  /* NOTE: following conventions from #MESH_OT_symmetrize */
1320 
1321  /* subset of 'rna_enum_symmetrize_direction_items' */
1322  static const EnumPropertyItem arm_symmetrize_direction_items[] = {
1323  {-1, "NEGATIVE_X", 0, "-X to +X", ""},
1324  {+1, "POSITIVE_X", 0, "+X to -X", ""},
1325  {0, NULL, 0, NULL, NULL},
1326  };
1327 
1328  /* identifiers */
1329  ot->name = "Symmetrize";
1330  ot->idname = "ARMATURE_OT_symmetrize";
1331  ot->description = "Enforce symmetry, make copies of the selection or use existing";
1332 
1333  /* api callbacks */
1336 
1337  /* flags */
1339 
1340  ot->prop = RNA_def_enum(ot->srna,
1341  "direction",
1342  arm_symmetrize_direction_items,
1343  -1,
1344  "Direction",
1345  "Which sides to copy from and to (when both are selected)");
1346 }
1347 
1348 /* ------------------------------------------ */
1349 
1350 /* previously extrude_armature */
1351 /* context; editmode armature */
1352 /* if forked && mirror-edit: makes two bones with flipped names */
1354 {
1355  ViewLayer *view_layer = CTX_data_view_layer(C);
1356  const bool forked = RNA_boolean_get(op->ptr, "forked");
1357  bool changed_multi = false;
1358 
1359  uint objects_len = 0;
1361  view_layer, CTX_wm_view3d(C), &objects_len);
1362  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1363  Object *ob = objects[ob_index];
1364  bArmature *arm = ob->data;
1365  bool forked_iter = forked;
1366 
1367  EditBone *newbone = NULL, *ebone, *flipbone, *first = NULL;
1368  int a, totbone = 0, do_extrude;
1369 
1370  /* since we allow root extrude too, we have to make sure selection is OK */
1371  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1372  if (EBONE_VISIBLE(arm, ebone)) {
1373  if (ebone->flag & BONE_ROOTSEL) {
1374  if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
1375  if (ebone->parent->flag & BONE_TIPSEL) {
1376  ebone->flag &= ~BONE_ROOTSEL;
1377  }
1378  }
1379  }
1380  }
1381  }
1382 
1383  /* Duplicate the necessary bones */
1384  for (ebone = arm->edbo->first; ((ebone) && (ebone != first)); ebone = ebone->next) {
1385  if (EBONE_VISIBLE(arm, ebone)) {
1386  /* we extrude per definition the tip */
1387  do_extrude = false;
1388  if (ebone->flag & (BONE_TIPSEL | BONE_SELECTED)) {
1389  do_extrude = true;
1390  }
1391  else if (ebone->flag & BONE_ROOTSEL) {
1392  /* but, a bone with parent deselected we do the root... */
1393  if (ebone->parent && (ebone->parent->flag & BONE_TIPSEL)) {
1394  /* pass */
1395  }
1396  else {
1397  do_extrude = 2;
1398  }
1399  }
1400 
1401  if (do_extrude) {
1402  /* we re-use code for mirror editing... */
1403  flipbone = NULL;
1404  if (arm->flag & ARM_MIRROR_EDIT) {
1405  flipbone = ED_armature_ebone_get_mirrored(arm->edbo, ebone);
1406  if (flipbone) {
1407  forked_iter = 0; /* we extrude 2 different bones */
1408  if (flipbone->flag & (BONE_TIPSEL | BONE_ROOTSEL | BONE_SELECTED)) {
1409  /* don't want this bone to be selected... */
1410  flipbone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
1411  }
1412  }
1413  if ((flipbone == NULL) && (forked_iter)) {
1414  flipbone = ebone;
1415  }
1416  }
1417 
1418  for (a = 0; a < 2; a++) {
1419  if (a == 1) {
1420  if (flipbone == NULL) {
1421  break;
1422  }
1423  SWAP(EditBone *, flipbone, ebone);
1424  }
1425 
1426  totbone++;
1427  newbone = MEM_callocN(sizeof(EditBone), "extrudebone");
1428 
1429  if (do_extrude == true) {
1430  copy_v3_v3(newbone->head, ebone->tail);
1431  copy_v3_v3(newbone->tail, newbone->head);
1432  newbone->parent = ebone;
1433 
1434  /* copies it, in case mirrored bone */
1435  newbone->flag = ebone->flag & (BONE_TIPSEL | BONE_RELATIVE_PARENTING);
1436 
1437  if (newbone->parent) {
1438  newbone->flag |= BONE_CONNECTED;
1439  }
1440  }
1441  else {
1442  copy_v3_v3(newbone->head, ebone->head);
1443  copy_v3_v3(newbone->tail, ebone->head);
1444  newbone->parent = ebone->parent;
1445 
1446  newbone->flag = BONE_TIPSEL;
1447 
1448  if (newbone->parent && (ebone->flag & BONE_CONNECTED)) {
1449  newbone->flag |= BONE_CONNECTED;
1450  }
1451  }
1452 
1453  newbone->weight = ebone->weight;
1454  newbone->dist = ebone->dist;
1455  newbone->xwidth = ebone->xwidth;
1456  newbone->zwidth = ebone->zwidth;
1457  newbone->rad_head = ebone->rad_tail; /* don't copy entire bone. */
1458  newbone->rad_tail = ebone->rad_tail;
1459  newbone->segments = 1;
1460  newbone->layer = ebone->layer;
1461 
1462  /* Bendy-Bone parameters */
1463  newbone->roll1 = ebone->roll1;
1464  newbone->roll2 = ebone->roll2;
1465  newbone->curve_in_x = ebone->curve_in_x;
1466  newbone->curve_in_z = ebone->curve_in_z;
1467  newbone->curve_out_x = ebone->curve_out_x;
1468  newbone->curve_out_z = ebone->curve_out_z;
1469  newbone->ease1 = ebone->ease1;
1470  newbone->ease2 = ebone->ease2;
1471 
1472  copy_v3_v3(newbone->scale_in, ebone->scale_in);
1473  copy_v3_v3(newbone->scale_out, ebone->scale_out);
1474 
1475  BLI_strncpy(newbone->name, ebone->name, sizeof(newbone->name));
1476 
1477  if (flipbone && forked_iter) { /* only set if mirror edit */
1478  if (strlen(newbone->name) < (MAXBONENAME - 2)) {
1479  if (a == 0) {
1480  strcat(newbone->name, "_L");
1481  }
1482  else {
1483  strcat(newbone->name, "_R");
1484  }
1485  }
1486  }
1487  ED_armature_ebone_unique_name(arm->edbo, newbone->name, NULL);
1488 
1489  /* Add the new bone to the list */
1490  BLI_addtail(arm->edbo, newbone);
1491  if (!first) {
1492  first = newbone;
1493  }
1494 
1495  /* restore ebone if we were flipping */
1496  if (a == 1 && flipbone) {
1497  SWAP(EditBone *, flipbone, ebone);
1498  }
1499  }
1500  }
1501 
1502  /* Deselect the old bone */
1503  ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
1504  }
1505  }
1506  /* if only one bone, make this one active */
1507  if (totbone == 1 && first) {
1508  arm->act_edbone = first;
1509  }
1510  else {
1511  arm->act_edbone = newbone;
1512  }
1513 
1514  if (totbone == 0) {
1515  continue;
1516  }
1517 
1518  changed_multi = true;
1519 
1520  /* Transform the endpoints */
1522 
1525  }
1526  MEM_freeN(objects);
1527 
1528  if (!changed_multi) {
1529  return OPERATOR_CANCELLED;
1530  }
1531 
1533 
1534  return OPERATOR_FINISHED;
1535 }
1536 
1538 {
1539  /* identifiers */
1540  ot->name = "Extrude";
1541  ot->idname = "ARMATURE_OT_extrude";
1542  ot->description = "Create new bones from the selected joints";
1543 
1544  /* api callbacks */
1547 
1548  /* flags */
1550 
1551  /* props */
1552  RNA_def_boolean(ot->srna, "forked", 0, "Forked", "");
1553 }
1554 
1555 /* ********************** Bone Add *************************************/
1556 
1557 /* Op makes a new bone and returns it with its tip selected. */
1558 
1560 {
1562  Object *obedit = CTX_data_edit_object(C);
1563  EditBone *bone;
1564  float obmat[3][3], curs[3], viewmat[3][3], totmat[3][3], imat[3][3];
1565  char name[MAXBONENAME];
1566 
1567  RNA_string_get(op->ptr, "name", name);
1568 
1569  copy_v3_v3(curs, CTX_data_scene(C)->cursor.location);
1570 
1571  /* Get inverse point for head and orientation for tail */
1572  invert_m4_m4(obedit->imat, obedit->obmat);
1573  mul_m4_v3(obedit->imat, curs);
1574 
1575  if (rv3d && (U.flag & USER_ADD_VIEWALIGNED)) {
1576  copy_m3_m4(obmat, rv3d->viewmat);
1577  }
1578  else {
1579  unit_m3(obmat);
1580  }
1581 
1582  copy_m3_m4(viewmat, obedit->obmat);
1583  mul_m3_m3m3(totmat, obmat, viewmat);
1584  invert_m3_m3(imat, totmat);
1585 
1587 
1588  /* Create a bone. */
1589  bone = ED_armature_ebone_add(obedit->data, name);
1590 
1591  copy_v3_v3(bone->head, curs);
1592 
1593  if (rv3d && (U.flag & USER_ADD_VIEWALIGNED)) {
1594  add_v3_v3v3(bone->tail, bone->head, imat[1]); /* bone with unit length 1 */
1595  }
1596  else {
1597  add_v3_v3v3(bone->tail, bone->head, imat[2]); /* bone with unit length 1, pointing up Z */
1598  }
1599 
1601 
1602  /* NOTE: notifier might evolve. */
1606 
1607  return OPERATOR_FINISHED;
1608 }
1609 
1611 {
1612  /* identifiers */
1613  ot->name = "Add Bone";
1614  ot->idname = "ARMATURE_OT_bone_primitive_add";
1615  ot->description = "Add a new bone located at the 3D cursor";
1616 
1617  /* api callbacks */
1620 
1621  /* flags */
1623 
1624  RNA_def_string(ot->srna, "name", "Bone", MAXBONENAME, "Name", "Name of the newly created bone");
1625 }
1626 
1627 /* ********************** Subdivide *******************************/
1628 
1629 /* Subdivide Operators:
1630  * This group of operators all use the same 'exec' callback, but they are called
1631  * through several different operators - a combined menu (which just calls the exec in the
1632  * appropriate ways), and two separate ones.
1633  */
1634 
1636 {
1637  Object *obedit = CTX_data_edit_object(C);
1638  EditBone *newbone, *tbone;
1639  int cuts, i;
1640 
1641  /* there may not be a number_cuts property defined (for 'simple' subdivide) */
1642  cuts = RNA_int_get(op->ptr, "number_cuts");
1643 
1644  /* loop over all editable bones */
1645  /* XXX the old code did this in reverse order though! */
1646  CTX_DATA_BEGIN_WITH_ID (C, EditBone *, ebone, selected_editable_bones, bArmature *, arm) {
1647  for (i = cuts + 1; i > 1; i--) {
1648  /* compute cut ratio first */
1649  float cutratio = 1.0f / (float)i;
1650  float cutratioI = 1.0f - cutratio;
1651 
1652  float val1[3];
1653  float val2[3];
1654  float val3[3];
1655 
1656  newbone = MEM_mallocN(sizeof(EditBone), "ebone subdiv");
1657  *newbone = *ebone;
1658  BLI_addtail(arm->edbo, newbone);
1659 
1660  /* calculate location of newbone->head */
1661  copy_v3_v3(val1, ebone->head);
1662  copy_v3_v3(val2, ebone->tail);
1663  copy_v3_v3(val3, newbone->head);
1664 
1665  val3[0] = val1[0] * cutratio + val2[0] * cutratioI;
1666  val3[1] = val1[1] * cutratio + val2[1] * cutratioI;
1667  val3[2] = val1[2] * cutratio + val2[2] * cutratioI;
1668 
1669  copy_v3_v3(newbone->head, val3);
1670  copy_v3_v3(newbone->tail, ebone->tail);
1671  copy_v3_v3(ebone->tail, newbone->head);
1672 
1673  newbone->rad_head = ((ebone->rad_head * cutratio) + (ebone->rad_tail * cutratioI));
1674  ebone->rad_tail = newbone->rad_head;
1675 
1676  newbone->flag |= BONE_CONNECTED;
1677 
1678  newbone->prop = NULL;
1679 
1680  ED_armature_ebone_unique_name(arm->edbo, newbone->name, NULL);
1681 
1682  /* correct parent bones */
1683  for (tbone = arm->edbo->first; tbone; tbone = tbone->next) {
1684  if (tbone->parent == ebone) {
1685  tbone->parent = newbone;
1686  }
1687  }
1688  newbone->parent = ebone;
1689  }
1690  }
1691  CTX_DATA_END;
1692 
1693  /* NOTE: notifier might evolve. */
1697 
1698  return OPERATOR_FINISHED;
1699 }
1700 
1702 {
1703  PropertyRNA *prop;
1704 
1705  /* identifiers */
1706  ot->name = "Subdivide";
1707  ot->idname = "ARMATURE_OT_subdivide";
1708  ot->description = "Break selected bones into chains of smaller bones";
1709 
1710  /* api callbacks */
1713 
1714  /* flags */
1716 
1717  /* Properties */
1718  prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of Cuts", "", 1, 10);
1719  /* Avoid re-using last var because it can cause
1720  * _very_ high poly meshes and annoy users (or worse crash) */
1722 }
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bActionGroup * action_groups_add_new(struct bAction *act, const char name[])
Definition: action.c:410
void BKE_pose_channels_hash_free(struct bPose *pose)
Definition: action.c:937
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from)
void BKE_pose_channel_free(struct bPoseChannel *pchan)
Definition: action.c:1078
struct bActionGroup * BKE_action_group_find_name(struct bAction *act, const char name[])
Definition: action.c:582
struct bPoseChannel * BKE_pose_channel_ensure(struct bPose *pose, const char *name)
Definition: action.c:628
void BKE_pose_channels_hash_ensure(struct bPose *pose)
Definition: action.c:925
void action_groups_add_channel(struct bAction *act, struct bActionGroup *agrp, struct FCurve *fcurve)
Definition: action.c:435
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
Definition: constraint.c:6186
void BKE_constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, struct bConstraintOb *cob, float mat[4][4], short from, short to, bool keep_scale)
Definition: constraint.c:245
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
Definition: constraint.c:6157
void BKE_constraint_custom_object_space_init(struct bConstraintOb *cob, struct bConstraint *con)
Definition: constraint.c:6331
#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
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
#define CTX_DATA_COUNT(C, member)
Definition: BKE_context.h:290
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
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
support for deformation groups and hooks.
int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName)
Definition: fcurve.c:297
struct FCurve * BKE_fcurve_copy(const struct FCurve *fcu)
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:542
struct ID * BKE_libblock_find_name(struct Main *bmain, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: lib_id.c:1297
#define BLI_assert(a)
Definition: BLI_assert.h:46
GHash * BLI_ghash_str_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:734
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:710
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:863
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
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
#define M_PI
Definition: BLI_math_base.h:20
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
float angle_wrap_rad(float angle)
MINLINE void copy_v2fl_v2i(float r[2], const int a[2])
MINLINE float len_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 copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
bool BLI_strn_endswith(const char *__restrict str, const char *__restrict end, size_t length) ATTR_NONNULL()
Definition: string.c:871
char * BLI_str_replaceN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:448
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_string_flip_side_name(char *r_name, const char *from_name, bool strip_number, size_t name_len)
Definition: string_utils.c:112
unsigned int uint
Definition: BLI_sys_types.h:67
#define SWAP(type, a, b)
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_SELECT
Definition: DNA_ID.h:818
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition: DNA_ID.h:879
#define MAX_ID_NAME
Definition: DNA_ID.h:337
@ ID_OB
Definition: DNA_ID_enums.h:47
#define MAXBONENAME
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_TIPSEL
@ BONE_CONNECTED
@ BONE_RELATIVE_PARENTING
@ ARM_MIRROR_EDIT
@ CONSTRAINT_TYPE_TRANSFORM
@ CONSTRAINT_TYPE_ROTLIMIT
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_LOCLIMIT
@ CONSTRAINT_TYPE_ACTION
@ CONSTRAINT_SPACE_LOCAL
@ TRANS_SCALE
@ TRANS_ROTATION
@ TRANS_LOCATION
Object is a sort of wrapper for general info.
@ USER_ADD_VIEWALIGNED
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
#define EBONE_VISIBLE(arm, ebone)
Definition: ED_armature.h:47
#define EBONE_SELECTABLE(arm, ebone)
Definition: ED_armature.h:52
void ED_outliner_select_sync_from_edit_bone_tag(struct bContext *C)
bool ED_operator_editarmature(struct bContext *C)
Definition: screen_ops.c:466
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
#define Z
Definition: GeomUtils.cpp:201
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its X
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its Y
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
@ OPTYPE_DEPENDS_ON_CURSOR
Definition: WM_types.h:184
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_BONE_SELECT
Definition: WM_types.h:409
#define NC_OBJECT
Definition: WM_types.h:329
static void updateDuplicateKinematicConstraintSettings(bConstraint *curcon)
Definition: armature_add.c:551
void ARMATURE_OT_subdivide(wmOperatorType *ot)
static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
Definition: armature_add.c:924
void postEditBoneDuplicate(struct ListBase *editbones, Object *ob)
Definition: armature_add.c:317
static int armature_extrude_exec(bContext *C, wmOperator *op)
static void updateDuplicateSubtarget(EditBone *dup_bone, ListBase *editbones, Object *ob, bool lookup_mirror_subtarget)
Definition: armature_add.c:362
static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
Definition: armature_add.c:114
static EditBone * get_symmetrized_bone(bArmature *arm, EditBone *bone)
static void updateDuplicateTransformConstraintSettings(Object *ob, bPoseChannel *pchan, bConstraint *curcon)
Definition: armature_add.c:628
void ARMATURE_OT_click_extrude(wmOperatorType *ot)
Definition: armature_add.c:244
static void updateDuplicateConstraintSettings(EditBone *dup_bone, EditBone *orig_bone, Object *ob)
Definition: armature_add.c:799
static void updateDuplicateActionConstraintSettings(EditBone *dup_bone, EditBone *orig_bone, Object *ob, bPoseChannel *pchan, bConstraint *curcon)
Definition: armature_add.c:419
EditBone * ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool view_aligned)
Definition: armature_add.c:86
void ARMATURE_OT_duplicate(wmOperatorType *ot)
void ARMATURE_OT_symmetrize(wmOperatorType *ot)
void ARMATURE_OT_extrude(wmOperatorType *ot)
static int armature_symmetrize_exec(bContext *C, wmOperator *op)
static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: armature_add.c:208
static int armature_subdivide_exec(bContext *C, wmOperator *op)
EditBone * add_points_bone(Object *obedit, float head[3], float tail[3])
Definition: armature_add.c:262
EditBone * ED_armature_ebone_add(bArmature *arm, const char *name)
Definition: armature_add.c:51
void ARMATURE_OT_bone_primitive_add(wmOperatorType *ot)
static bPoseChannel * pchan_duplicate_map(const bPose *pose, GHash *name_map, bPoseChannel *pchan_src)
Definition: armature_add.c:299
static void updateDuplicateLocRotConstraintSettings(Object *ob, bPoseChannel *pchan, bConstraint *curcon)
Definition: armature_add.c:560
static int armature_bone_primitive_add_exec(bContext *C, wmOperator *op)
EditBone * duplicateEditBone(EditBone *cur_bone, const char *name, ListBase *editbones, Object *ob)
Definition: armature_add.c:919
void preEditBoneDuplicate(ListBase *editbones)
Definition: armature_add.c:289
EditBone * duplicateEditBoneObjects(EditBone *cur_bone, const char *name, ListBase *editbones, Object *src_ob, Object *dst_ob)
Definition: armature_add.c:896
static EditBone * get_named_editbone(ListBase *edbo, const char *name)
Definition: armature_add.c:274
static void updateDuplicateCustomBoneShapes(bContext *C, EditBone *dup_bone, Object *ob)
Definition: armature_add.c:832
static void copy_pchan(EditBone *src_bone, EditBone *dst_bone, Object *src_ob, Object *dst_ob)
Definition: armature_add.c:869
void ED_armature_ebone_unique_name(ListBase *ebones, char *name, EditBone *bone)
bool ED_armature_edit_deselect_all(Object *obedit)
void ED_armature_edit_transform_mirror_update(Object *obedit)
void ED_armature_ebone_listbase_temp_clear(ListBase *lb)
void ED_armature_edit_refresh_layer_used(bArmature *arm)
void ED_armature_edit_sync_selection(ListBase *edbo)
void ED_armature_ebone_select_set(EditBone *ebone, bool select)
void ED_armature_edit_validate_active(struct bArmature *arm)
EditBone * ED_armature_ebone_find_name(const ListBase *edbo, const char *name)
EditBone * ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
unsigned int U
Definition: btGjkEpa3.h:78
Scene scene
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
T length(const vec_base< T, Size > &a)
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
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_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3687
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3597
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
float vec[3][3]
float curve_out_z
Definition: BKE_armature.h:74
float scale_in[3]
Definition: BKE_armature.h:76
char name[64]
Definition: BKE_armature.h:43
short bbone_prev_flag
Definition: BKE_armature.h:86
float ease2
Definition: BKE_armature.h:75
float weight
Definition: BKE_armature.h:65
float roll1
Definition: BKE_armature.h:72
int bbone_flag
Definition: BKE_armature.h:85
struct EditBone * next
Definition: BKE_armature.h:33
short segments
Definition: BKE_armature.h:71
float tail[3]
Definition: BKE_armature.h:54
char bbone_prev_type
Definition: BKE_armature.h:82
float roll2
Definition: BKE_armature.h:72
struct EditBone * ebone
Definition: BKE_armature.h:105
float curve_in_x
Definition: BKE_armature.h:73
float zwidth
Definition: BKE_armature.h:67
short bbone_next_flag
Definition: BKE_armature.h:87
struct EditBone * bbone_next
Definition: BKE_armature.h:90
float curve_in_z
Definition: BKE_armature.h:73
float length
Definition: BKE_armature.h:67
float xwidth
Definition: BKE_armature.h:67
float dist
Definition: BKE_armature.h:65
char bbone_next_type
Definition: BKE_armature.h:83
struct EditBone * parent
Definition: BKE_armature.h:41
float rad_tail
Definition: BKE_armature.h:68
union EditBone::@3 temp
struct IDProperty * prop
Definition: BKE_armature.h:35
float ease1
Definition: BKE_armature.h:75
float rad_head
Definition: BKE_armature.h:68
float scale_out[3]
Definition: BKE_armature.h:76
char inherit_scale_mode
Definition: BKE_armature.h:62
float curve_out_x
Definition: BKE_armature.h:74
struct EditBone * bbone_prev
Definition: BKE_armature.h:89
float head[3]
Definition: BKE_armature.h:53
char * rna_path
BezTriple * bezt
int array_index
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct bPose * pose
float imat[4][4]
float obmat[4][4]
void * data
float viewmat[4][4]
View3DCursor cursor
struct bAction * act
struct EditBone * act_edbone
unsigned int layer
ListBase * edbo
struct Depsgraph * depsgraph
struct bConstraintTarget * next
struct bConstraint * next
ListBase constraints
float custom_scale_xyz[3]
float custom_rotation_euler[3]
struct bPoseChannel * custom_tx
struct bPoseChannel * bbone_next
struct Object * custom
float custom_translation[3]
struct bPoseChannel * bbone_prev
int mval[2]
Definition: WM_types.h:684
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 PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_operator_flag_only_pass_through_on_press(int retval, const struct wmEvent *event)