Blender  V3.3
transform_convert.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 
8 #include "DNA_anim_types.h"
9 #include "DNA_constraint_types.h"
10 #include "DNA_mesh_types.h"
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "BLI_kdtree.h"
15 #include "BLI_linklist_stack.h"
16 #include "BLI_listbase.h"
17 #include "BLI_math.h"
18 
19 #include "BKE_action.h"
20 #include "BKE_anim_data.h"
21 #include "BKE_context.h"
22 #include "BKE_fcurve.h"
23 #include "BKE_global.h"
24 #include "BKE_image.h"
25 #include "BKE_layer.h"
26 #include "BKE_lib_id.h"
27 #include "BKE_main.h"
28 #include "BKE_modifier.h"
29 #include "BKE_nla.h"
30 #include "BKE_scene.h"
31 
32 #include "ED_keyframes_edit.h"
33 #include "ED_keyframing.h"
34 #include "ED_particle.h"
35 #include "ED_screen.h"
36 #include "ED_screen_types.h"
37 
38 #include "UI_view2d.h"
39 
40 #include "WM_types.h"
41 
42 #include "DEG_depsgraph_build.h"
43 
44 #include "transform.h"
45 #include "transform_snap.h"
46 
47 /* Own include. */
48 #include "transform_convert.h"
49 
51 {
52  return ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL);
53 }
54 
56 {
57  if (data_len_all != 1) {
58  return;
59  }
61  return;
62  }
64  return;
65  }
66  if (t->flag & T_OVERRIDE_CENTER) {
67  return;
68  }
69 
70  t->around = V3D_AROUND_LOCAL_ORIGINS;
71 }
72 
74 {
75  transform_around_single_fallback_ex(t, t->data_len_all);
76 }
77 
78 /* -------------------------------------------------------------------- */
82 static int trans_data_compare_dist(const void *a, const void *b)
83 {
84  const TransData *td_a = (const TransData *)a;
85  const TransData *td_b = (const TransData *)b;
86 
87  if (td_a->dist < td_b->dist) {
88  return -1;
89  }
90  if (td_a->dist > td_b->dist) {
91  return 1;
92  }
93  return 0;
94 }
95 
96 static int trans_data_compare_rdist(const void *a, const void *b)
97 {
98  const TransData *td_a = (const TransData *)a;
99  const TransData *td_b = (const TransData *)b;
100 
101  if (td_a->rdist < td_b->rdist) {
102  return -1;
103  }
104  if (td_a->rdist > td_b->rdist) {
105  return 1;
106  }
107  return 0;
108 }
109 
111 {
112  TransData *start = tc->data;
113  int i;
114 
115  for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) {
116  start++;
117  }
118 
119  if (i < tc->data_len) {
120  if (t->flag & T_PROP_CONNECTED) {
121  qsort(start, (size_t)tc->data_len - i, sizeof(TransData), trans_data_compare_dist);
122  }
123  else {
124  qsort(start, (size_t)tc->data_len - i, sizeof(TransData), trans_data_compare_rdist);
125  }
126  }
127 }
129 {
132  }
133 }
134 
139 {
140  TransData *sel, *unsel;
141  TransData temp;
142  unsel = tc->data;
143  sel = &tc->data[tc->data_len - 1];
144  while (sel > unsel) {
145  while (unsel->flag & TD_SELECTED) {
146  unsel++;
147  if (unsel == sel) {
148  return;
149  }
150  }
151  while (!(sel->flag & TD_SELECTED)) {
152  sel--;
153  if (unsel == sel) {
154  return;
155  }
156  }
157  temp = *unsel;
158  *unsel = *sel;
159  *sel = temp;
160  sel--;
161  unsel++;
162  }
163 }
165 {
168  }
169 }
170 
174 static void set_prop_dist(TransInfo *t, const bool with_dist)
175 {
176  int a;
177 
178  float _proj_vec[3];
179  const float *proj_vec = NULL;
180 
181  /* support for face-islands */
182  const bool use_island = transdata_check_local_islands(t, t->around);
183 
184  if (t->flag & T_PROP_PROJECTED) {
185  if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) {
186  RegionView3D *rv3d = t->region->regiondata;
187  normalize_v3_v3(_proj_vec, rv3d->viewinv[2]);
188  proj_vec = _proj_vec;
189  }
190  }
191 
192  /* Count number of selected. */
193  int td_table_len = 0;
195  TransData *td = tc->data;
196  for (a = 0; a < tc->data_len; a++, td++) {
197  if (td->flag & TD_SELECTED) {
198  td_table_len++;
199  }
200  else {
201  /* By definition transform-data has selected items in beginning. */
202  break;
203  }
204  }
205  }
206 
207  /* Pointers to selected's #TransData.
208  * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */
209  TransData **td_table = MEM_mallocN(sizeof(*td_table) * td_table_len, __func__);
210 
211  /* Create and fill KD-tree of selected's positions - in global or proj_vec space. */
212  KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len);
213 
214  int td_table_index = 0;
216  TransData *td = tc->data;
217  for (a = 0; a < tc->data_len; a++, td++) {
218  if (td->flag & TD_SELECTED) {
219  /* Initialize, it was mallocced. */
220  float vec[3];
221  td->rdist = 0.0f;
222 
223  if (use_island) {
224  if (tc->use_local_mat) {
225  mul_v3_m4v3(vec, tc->mat, td->iloc);
226  }
227  else {
228  mul_v3_m3v3(vec, td->mtx, td->iloc);
229  }
230  }
231  else {
232  if (tc->use_local_mat) {
233  mul_v3_m4v3(vec, tc->mat, td->center);
234  }
235  else {
236  mul_v3_m3v3(vec, td->mtx, td->center);
237  }
238  }
239 
240  if (proj_vec) {
241  float vec_p[3];
242  project_v3_v3v3(vec_p, vec, proj_vec);
243  sub_v3_v3(vec, vec_p);
244  }
245 
246  BLI_kdtree_3d_insert(td_tree, td_table_index, vec);
247  td_table[td_table_index++] = td;
248  }
249  else {
250  /* By definition transform-data has selected items in beginning. */
251  break;
252  }
253  }
254  }
255  BLI_assert(td_table_index == td_table_len);
256 
257  BLI_kdtree_3d_balance(td_tree);
258 
259  /* For each non-selected vertex, find distance to the nearest selected vertex. */
261  TransData *td = tc->data;
262  for (a = 0; a < tc->data_len; a++, td++) {
263  if ((td->flag & TD_SELECTED) == 0) {
264  float vec[3];
265 
266  if (use_island) {
267  if (tc->use_local_mat) {
268  mul_v3_m4v3(vec, tc->mat, td->iloc);
269  }
270  else {
271  mul_v3_m3v3(vec, td->mtx, td->iloc);
272  }
273  }
274  else {
275  if (tc->use_local_mat) {
276  mul_v3_m4v3(vec, tc->mat, td->center);
277  }
278  else {
279  mul_v3_m3v3(vec, td->mtx, td->center);
280  }
281  }
282 
283  if (proj_vec) {
284  float vec_p[3];
285  project_v3_v3v3(vec_p, vec, proj_vec);
286  sub_v3_v3(vec, vec_p);
287  }
288 
289  KDTreeNearest_3d nearest;
290  const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest);
291 
292  td->rdist = -1.0f;
293  if (td_index != -1) {
294  td->rdist = nearest.dist;
295  if (use_island) {
296  copy_v3_v3(td->center, td_table[td_index]->center);
297  copy_m3_m3(td->axismtx, td_table[td_index]->axismtx);
298  }
299  }
300 
301  if (with_dist) {
302  td->dist = td->rdist;
303  }
304  }
305  }
306  }
307 
308  BLI_kdtree_3d_free(td_tree);
309  MEM_freeN(td_table);
310 }
311 
314 /* -------------------------------------------------------------------- */
318 /* adjust pose-channel's auto-ik chainlen */
319 static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
320 {
321  bConstraint *con;
322  bool changed = false;
323 
324  /* don't bother to search if no valid constraints */
325  if ((pchan->constflag & (PCHAN_HAS_IK | PCHAN_HAS_TARGET)) == 0) {
326  return changed;
327  }
328 
329  /* check if pchan has ik-constraint */
330  for (con = pchan->constraints.first; con; con = con->next) {
331  if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) {
332  continue;
333  }
334  if (con->type == CONSTRAINT_TYPE_KINEMATIC && (con->enforce != 0.0f)) {
336 
337  /* only accept if a temporary one (for auto-ik) */
338  if (data->flag & CONSTRAINT_IK_TEMP) {
339  /* chainlen is new chainlen, but is limited by maximum chainlen */
340  const int old_rootbone = data->rootbone;
341  if ((chainlen == 0) || (chainlen > data->max_rootbone)) {
342  data->rootbone = data->max_rootbone;
343  }
344  else {
345  data->rootbone = chainlen;
346  }
347  changed |= (data->rootbone != old_rootbone);
348  }
349  }
350  }
351 
352  return changed;
353 }
354 
356 {
357  Main *bmain = CTX_data_main(t->context);
358 
359  short *chainlen = &t->settings->autoik_chainlen;
360  bPoseChannel *pchan;
361 
362  /* mode determines what change to apply to chainlen */
363  if (mode == 1) {
364  /* mode=1 is from WHEELMOUSEDOWN... increases len */
365  (*chainlen)++;
366  }
367  else if (mode == -1) {
368  /* mode==-1 is from WHEELMOUSEUP... decreases len */
369  if (*chainlen > 0) {
370  (*chainlen)--;
371  }
372  else {
373  /* IK length did not change, skip updates. */
374  return;
375  }
376  }
377 
378  /* apply to all pose-channels */
379  bool changed = false;
380 
382 
383  /* sanity checks (don't assume t->poseobj is set, or that it is an armature) */
384  if (ELEM(NULL, tc->poseobj, tc->poseobj->pose)) {
385  continue;
386  }
387 
388  for (pchan = tc->poseobj->pose->chanbase.first; pchan; pchan = pchan->next) {
389  changed |= pchan_autoik_adjust(pchan, *chainlen);
390  }
391  }
392 
393  if (changed) {
394  /* TODO(sergey): Consider doing partial update only. */
396  }
397 }
398 
401 /* -------------------------------------------------------------------- */
405 void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic)
406 {
407  TransData *td;
410  for (td = head; td <= tail; td++) {
411  if (td->flag & TD_SELECTED) {
412  td->dist = 0.0f;
414  }
415  else {
416  td->dist = FLT_MAX;
417  }
418  }
419 
420  while ((td = BLI_LINKSTACK_POP(queue))) {
421  float dist;
422  float vec[3];
423 
424  TransData *next_td = NULL;
425 
426  if (td + 1 <= tail) {
427  next_td = td + 1;
428  }
429  else if (cyclic) {
430  next_td = head;
431  }
432 
433  if (next_td != NULL && !(next_td->flag & TD_NOTCONNECTED)) {
434  sub_v3_v3v3(vec, next_td->center, td->center);
435  mul_m3_v3(head->mtx, vec);
436  dist = len_v3(vec) + td->dist;
437 
438  if (dist < next_td->dist) {
439  next_td->dist = dist;
440  BLI_LINKSTACK_PUSH(queue, next_td);
441  }
442  }
443 
444  next_td = NULL;
445 
446  if (td - 1 >= head) {
447  next_td = td - 1;
448  }
449  else if (cyclic) {
450  next_td = tail;
451  }
452 
453  if (next_td != NULL && !(next_td->flag & TD_NOTCONNECTED)) {
454  sub_v3_v3v3(vec, next_td->center, td->center);
455  mul_m3_v3(head->mtx, vec);
456  dist = len_v3(vec) + td->dist;
457 
458  if (dist < next_td->dist) {
459  next_td->dist = dist;
460  BLI_LINKSTACK_PUSH(queue, next_td);
461  }
462  }
463  }
465 }
466 
468 {
470  td->flag |= TD_BEZTRIPLE;
471  hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data");
472  hdata->ih1 = bezt->h1;
473  hdata->h1 = &bezt->h1;
474  hdata->ih2 = bezt->h2; /* in case the second is not selected */
475  hdata->h2 = &bezt->h2;
476  return hdata;
477 }
478 
481 /* -------------------------------------------------------------------- */
486 {
488  TransData *td = tc->data;
489  for (int a = 0; a < tc->data_len; a++, td++) {
490  if ((td->flag & TD_SKIP) || (!td->loc)) {
491  continue;
492  }
493 
494  td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]);
495  td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]);
496  }
497  }
498 }
499 
502 /* -------------------------------------------------------------------- */
507 {
508  char r_dir;
509  float center[2];
510  if (t->flag & T_MODAL) {
512  (View2D *)t->view, t->mouse.imval[0], t->mouse.imval[1], &center[0], &center[1]);
513  r_dir = (center[0] > cframe) ? 'R' : 'L';
514  {
515  /* XXX: This saves the direction in the "mirror" property to be used for redo! */
516  if (r_dir == 'R') {
517  t->flag |= T_NO_MIRROR;
518  }
519  }
520  }
521  else {
522  r_dir = (t->flag & T_NO_MIRROR) ? 'R' : 'L';
523  }
524 
525  return r_dir;
526 }
527 
528 bool FrameOnMouseSide(char side, float frame, float cframe)
529 {
530  /* both sides, so it doesn't matter */
531  if (side == 'B') {
532  return true;
533  }
534 
535  /* only on the named side */
536  if (side == 'R') {
537  return (frame >= cframe);
538  }
539  return (frame <= cframe);
540 }
541 
544 /* -------------------------------------------------------------------- */
548 /* Time + Average value */
549 typedef struct tRetainedKeyframe {
551  float frame; /* frame to cluster around */
552  float val; /* average value */
553 
554  size_t tot_count; /* number of keyframes that have been averaged */
555  size_t del_count; /* number of keyframes of this sort that have been deleted so far */
557 
558 void posttrans_fcurve_clean(FCurve *fcu, const int sel_flag, const bool use_handle)
559 {
560  /* NOTE: We assume that all keys are sorted */
561  ListBase retained_keys = {NULL, NULL};
562  const bool can_average_points = ((fcu->flag & (FCURVE_INT_VALUES | FCURVE_DISCRETE_VALUES)) ==
563  0);
564 
565  /* sanity checks */
566  if ((fcu->totvert == 0) || (fcu->bezt == NULL)) {
567  return;
568  }
569 
570  /* 1) Identify selected keyframes, and average the values on those
571  * in case there are collisions due to multiple keys getting scaled
572  * to all end up on the same frame
573  */
574  for (int i = 0; i < fcu->totvert; i++) {
575  BezTriple *bezt = &fcu->bezt[i];
576 
577  if (BEZT_ISSEL_ANY(bezt)) {
578  bool found = false;
579 
580  /* If there's another selected frame here, merge it */
581  for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
582  if (IS_EQT(rk->frame, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
583  rk->val += bezt->vec[1][1];
584  rk->tot_count++;
585 
586  found = true;
587  break;
588  }
589  if (rk->frame < bezt->vec[1][0]) {
590  /* Terminate early if have passed the supposed insertion point? */
591  break;
592  }
593  }
594 
595  /* If nothing found yet, create a new one */
596  if (found == false) {
597  tRetainedKeyframe *rk = MEM_callocN(sizeof(tRetainedKeyframe), "tRetainedKeyframe");
598 
599  rk->frame = bezt->vec[1][0];
600  rk->val = bezt->vec[1][1];
601  rk->tot_count = 1;
602 
603  BLI_addtail(&retained_keys, rk);
604  }
605  }
606  }
607 
608  if (BLI_listbase_is_empty(&retained_keys)) {
609  /* This may happen if none of the points were selected... */
610  if (G.debug & G_DEBUG) {
611  printf("%s: nothing to do for FCurve %p (rna_path = '%s')\n", __func__, fcu, fcu->rna_path);
612  }
613  return;
614  }
615 
616  /* Compute the average values for each retained keyframe */
617  LISTBASE_FOREACH (tRetainedKeyframe *, rk, &retained_keys) {
618  rk->val = rk->val / (float)rk->tot_count;
619  }
620 
621  /* 2) Delete all keyframes duplicating the "retained keys" found above
622  * - Most of these will be unselected keyframes
623  * - Some will be selected keyframes though. For those, we only keep the last one
624  * (or else everything is gone), and replace its value with the averaged value.
625  */
626  for (int i = fcu->totvert - 1; i >= 0; i--) {
627  BezTriple *bezt = &fcu->bezt[i];
628 
629  /* Is this keyframe a candidate for deletion? */
630  /* TODO: Replace loop with an O(1) lookup instead */
631  for (tRetainedKeyframe *rk = retained_keys.last; rk; rk = rk->prev) {
632  if (IS_EQT(bezt->vec[1][0], rk->frame, BEZT_BINARYSEARCH_THRESH)) {
633  /* Selected keys are treated with greater care than unselected ones... */
634  if (BEZT_ISSEL_ANY(bezt)) {
635  /* - If this is the last selected key left (based on rk->del_count) ==> UPDATE IT
636  * (or else we wouldn't have any keyframe left here)
637  * - Otherwise, there are still other selected keyframes on this frame
638  * to be merged down still ==> DELETE IT
639  */
640  if (rk->del_count == rk->tot_count - 1) {
641  /* Update keyframe... */
642  if (can_average_points) {
643  /* TODO: update handles too? */
644  bezt->vec[1][1] = rk->val;
645  }
646  }
647  else {
648  /* Delete Keyframe */
649  BKE_fcurve_delete_key(fcu, i);
650  }
651 
652  /* Update count of how many we've deleted
653  * - It should only matter that we're doing this for all but the last one
654  */
655  rk->del_count++;
656  }
657  else {
658  /* Always delete - Unselected keys don't matter */
659  BKE_fcurve_delete_key(fcu, i);
660  }
661 
662  /* Stop the RK search... we've found our match now */
663  break;
664  }
665  }
666  }
667 
668  /* 3) Recalculate handles */
669  testhandles_fcurve(fcu, sel_flag, use_handle);
670 
671  /* cleanup */
672  BLI_freelistN(&retained_keys);
673 }
674 
677 /* -------------------------------------------------------------------- */
682 {
683  bConstraint *con;
684 
685  /* loop through constraints, checking if there's one of the mentioned
686  * constraints needing special crazy-space corrections
687  */
688  if (list) {
689  for (con = list->first; con; con = con->next) {
690  /* only consider constraint if it is enabled, and has influence on result */
691  if ((con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) == 0 && (con->enforce != 0.0f)) {
692  /* (affirmative) returns for specific constraints here... */
693  /* constraints that require this regardless. */
694  if (ELEM(con->type,
700  return true;
701  }
702 
703  /* constraints that require this only under special conditions */
704  if (con->type == CONSTRAINT_TYPE_CHILDOF) {
705  /* ChildOf constraint only works when using all location components, see T42256. */
707 
708  if ((data->flag & CHILDOF_LOCX) && (data->flag & CHILDOF_LOCY) &&
709  (data->flag & CHILDOF_LOCZ)) {
710  return true;
711  }
712  }
713  else if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
714  /* CopyRot constraint only does this when rotating, and offset is on */
716 
718  ELEM(t->mode, TFM_ROTATION)) {
719  return true;
720  }
721  }
722  else if (con->type == CONSTRAINT_TYPE_TRANSLIKE) {
723  /* Copy Transforms constraint only does this in the Before mode. */
725 
727  ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) {
728  return true;
729  }
730  if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) {
731  return true;
732  }
733  }
734  else if (con->type == CONSTRAINT_TYPE_ACTION) {
735  /* The Action constraint only does this in the Before mode. */
737 
739  ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) {
740  return true;
741  }
742  if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) {
743  return true;
744  }
745  }
746  else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
747  /* Transform constraint needs it for rotation at least (r.57309),
748  * but doing so when translating may also mess things up, see: T36203. */
750 
751  if (data->to == TRANS_ROTATION) {
752  if (t->mode == TFM_ROTATION && data->mix_mode_rot == TRANS_MIXROT_BEFORE) {
753  return true;
754  }
755  }
756  }
757  }
758  }
759  }
760 
761  /* no appropriate candidates found */
762  return false;
763 }
764 
767 /* -------------------------------------------------------------------- */
772 {
773  /* NOTE: Sequencer freeing has its own function now because of a conflict
774  * with transform's order of freeing (campbell).
775  * Order changed, the sequencer stuff should go back in here. */
776 
777  /* early out when nothing happened */
778  if (t->data_len_all == 0 || t->mode == TFM_DUMMY) {
779  return;
780  }
781 
782  if (!t->data_type || !t->data_type->special_aftertrans_update) {
783  return;
784  }
785 
786  BLI_assert(CTX_data_main(t->context) == CTX_data_main(C));
787  t->data_type->special_aftertrans_update(C, t);
788 }
789 
791 {
792  if (t->options & CTX_CURSOR) {
793  return G_TRANSFORM_CURSOR;
794  }
795  if (t->spacetype == SPACE_SEQ) {
796  return G_TRANSFORM_SEQ;
797  }
798  if (t->spacetype == SPACE_GRAPH) {
799  return G_TRANSFORM_FCURVES;
800  }
801  if ((t->flag & T_EDIT) || (t->options & CTX_POSE_BONE)) {
802  return G_TRANSFORM_EDIT;
803  }
804  if (t->options & (CTX_OBJECT | CTX_TEXTURE_SPACE)) {
805  return G_TRANSFORM_OBJ;
806  }
807 
808  return 0;
809 }
810 
813 /* -------------------------------------------------------------------- */
818 {
819  BLI_assert(ELEM(t->data_len_all, 0, -1));
820  t->data_len_all = 0;
821  int data_container_len_orig = t->data_container_len;
822  for (TransDataContainer *th_end = t->data_container - 1,
823  *tc = &t->data_container[t->data_container_len - 1];
824  tc != th_end;
825  tc--) {
826  if (tc->data_len == 0) {
827  uint index = tc - t->data_container;
828  if (index + 1 != t->data_container_len) {
830  t->data_container[index],
831  t->data_container[t->data_container_len - 1]);
832  }
833  t->data_container_len -= 1;
834  }
835  else {
836  t->data_len_all += tc->data_len;
837  }
838  }
839  if (data_container_len_orig != t->data_container_len) {
840  t->data_container = MEM_reallocN(t->data_container,
841  sizeof(*t->data_container) * t->data_container_len);
842  }
843  return t->data_len_all;
844 }
845 
847 {
848  /* NOTE: PET is not usable in pose mode yet T32444. */
849  if (!ELEM(t->data_type,
865  /* Disable PET */
866  t->options |= CTX_NO_PET;
867  t->flag &= ~T_PROP_EDIT_ALL;
868  return;
869  }
870 
871  if (t->data_len_all && (t->flag & T_PROP_EDIT)) {
872  if (t->data_type == &TransConvertType_Object) {
873  /* Selected objects are already first, no need to presort. */
874  }
875  else {
877  }
878 
880  /* Distance has already been set. */
881  }
882  else if (ELEM(t->data_type,
886  if (t->flag & T_PROP_CONNECTED) {
887  /* Already calculated by transform_convert_mesh_connectivity_distance. */
888  }
889  else {
890  set_prop_dist(t, false);
891  }
892  }
893  else if (t->data_type == &TransConvertType_MeshUV && t->flag & T_PROP_CONNECTED) {
894  /* Already calculated by uv_set_connectivity_distance. */
895  }
896  else if (t->data_type == &TransConvertType_Curve) {
897  BLI_assert(t->obedit_type == OB_CURVES_LEGACY);
898  set_prop_dist(t, false);
899  }
900  else {
901  set_prop_dist(t, true);
902  }
903 
905  }
906  else if (ELEM(t->obedit_type, OB_CURVES_LEGACY)) {
907  /* Needed because bezier handles can be partially selected
908  * and are still added into transform data. */
910  }
911 }
912 
913 /* For multi object editing. */
915  Object *obact,
916  Object **objects,
917  uint objects_len)
918 {
919  if (!ELEM(t->data_type,
931  /* Does not support Multi object editing. */
932  return;
933  }
934 
935  const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT;
936  const short object_type = obact ? obact->type : -1;
937 
938  if ((object_mode & OB_MODE_EDIT) || (t->data_type == &TransConvertType_GPencil) ||
939  ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) {
940  if (t->data_container) {
941  MEM_freeN(t->data_container);
942  }
943 
944  bool free_objects = false;
945  if (objects == NULL) {
947  t->view_layer,
948  (t->spacetype == SPACE_VIEW3D) ? t->view : NULL,
949  &objects_len,
950  {
951  .object_mode = object_mode,
952  /* Pose transform operates on `ob->pose` so don't skip duplicate object-data. */
953  .no_dup_data = (object_mode & OB_MODE_POSE) == 0,
954  });
955  free_objects = true;
956  }
957 
958  t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__);
959  t->data_container_len = objects_len;
960 
961  for (int i = 0; i < objects_len; i++) {
962  TransDataContainer *tc = &t->data_container[i];
963  if (!(t->flag & T_NO_MIRROR) && (objects[i]->type == OB_MESH)) {
964  tc->use_mirror_axis_x = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_X) != 0;
965  tc->use_mirror_axis_y = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Y) != 0;
966  tc->use_mirror_axis_z = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Z) != 0;
967  }
968 
969  if (object_mode & OB_MODE_EDIT) {
970  tc->obedit = objects[i];
971  /* Check needed for UV's */
972  if ((t->flag & T_2D_EDIT) == 0) {
973  tc->use_local_mat = true;
974  }
975  }
976  else if (object_mode & OB_MODE_POSE) {
977  tc->poseobj = objects[i];
978  tc->use_local_mat = true;
979  }
980  else if (t->data_type == &TransConvertType_GPencil) {
981  tc->use_local_mat = true;
982  }
983 
984  if (tc->use_local_mat) {
985  BLI_assert((t->flag & T_2D_EDIT) == 0);
986  copy_m4_m4(tc->mat, objects[i]->obmat);
987  copy_m3_m4(tc->mat3, tc->mat);
988  /* for non-invertible scale matrices, invert_m4_m4_fallback()
989  * can still provide a valid pivot */
990  invert_m4_m4_fallback(tc->imat, tc->mat);
991  invert_m3_m3(tc->imat3, tc->mat3);
992  normalize_m3_m3(tc->mat3_unit, tc->mat3);
993  }
994  /* Otherwise leave as zero. */
995  }
996 
997  if (free_objects) {
998  MEM_freeN(objects);
999  }
1000  }
1001 }
1002 
1003 static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj_armature)
1004 {
1005  ViewLayer *view_layer = t->view_layer;
1006  Object *ob = OBACT(view_layer);
1007 
1008  /* if tests must match recalcData for correct updates */
1009  if (t->options & CTX_CURSOR) {
1010  if (t->spacetype == SPACE_IMAGE) {
1012  }
1013 
1014  if (t->spacetype == SPACE_SEQ) {
1016  }
1017 
1018  return &TransConvertType_Cursor3D;
1019  }
1020  if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && ob &&
1021  (ob->mode == OB_MODE_SCULPT) && ob->sculpt) {
1022  return &TransConvertType_Sculpt;
1023  }
1024  if (t->options & CTX_TEXTURE_SPACE) {
1026  }
1027  if (t->options & CTX_EDGE_DATA) {
1028  return &TransConvertType_MeshEdge;
1029  }
1030  if (t->options & CTX_GPENCIL_STROKES) {
1031  return &TransConvertType_GPencil;
1032  }
1033  if (t->spacetype == SPACE_IMAGE) {
1034  if (t->options & CTX_MASK) {
1035  return &TransConvertType_Mask;
1036  }
1037  if (t->options & CTX_PAINT_CURVE) {
1038  if (!ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
1040  }
1041  }
1042  else if (t->obedit_type == OB_MESH) {
1043  return &TransConvertType_MeshUV;
1044  }
1045  return NULL;
1046  }
1047  if (t->spacetype == SPACE_ACTION) {
1048  return &TransConvertType_Action;
1049  }
1050  if (t->spacetype == SPACE_NLA) {
1051  return &TransConvertType_NLA;
1052  }
1053  if (t->spacetype == SPACE_SEQ) {
1054  if (t->options & CTX_SEQUENCER_IMAGE) {
1056  }
1058  }
1059  if (t->spacetype == SPACE_GRAPH) {
1060  return &TransConvertType_Graph;
1061  }
1062  if (t->spacetype == SPACE_NODE) {
1063  return &TransConvertType_Node;
1064  }
1065  if (t->spacetype == SPACE_CLIP) {
1066  if (t->options & CTX_MOVIECLIP) {
1067  return &TransConvertType_Tracking;
1068  }
1069  if (t->options & CTX_MASK) {
1070  return &TransConvertType_Mask;
1071  }
1072  return NULL;
1073  }
1074  if (t->obedit_type != -1) {
1075  if (t->obedit_type == OB_MESH) {
1076  if (t->mode == TFM_SKIN_RESIZE) {
1077  return &TransConvertType_MeshSkin;
1078  }
1079  if (ELEM(t->mode, TFM_BWEIGHT, TFM_VERT_CREASE)) {
1081  }
1082  return &TransConvertType_Mesh;
1083  }
1084  if (ELEM(t->obedit_type, OB_CURVES_LEGACY, OB_SURF)) {
1085  return &TransConvertType_Curve;
1086  }
1087  if (t->obedit_type == OB_LATTICE) {
1088  return &TransConvertType_Lattice;
1089  }
1090  if (t->obedit_type == OB_MBALL) {
1091  return &TransConvertType_MBall;
1092  }
1093  if (t->obedit_type == OB_ARMATURE) {
1095  }
1096  return NULL;
1097  }
1098  if (ob && (ob->mode & OB_MODE_POSE)) {
1099  return &TransConvertType_Pose;
1100  }
1101  if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) {
1103  if (ob_armature) {
1104  *r_obj_armature = ob_armature;
1105  return &TransConvertType_Pose;
1106  }
1107  return NULL;
1108  }
1109  if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) &&
1110  PE_start_edit(PE_get_current(t->depsgraph, t->scene, ob))) {
1111  return &TransConvertType_Particle;
1112  }
1113  if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
1114  if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
1116  }
1117  return NULL;
1118  }
1119  if ((ob) && (ELEM(ob->mode,
1124  /* In grease pencil all transformations must be canceled if not Object or Edit. */
1125  return NULL;
1126  }
1127  return &TransConvertType_Object;
1128 }
1129 
1131 {
1132  t->data_len_all = -1;
1133 
1134  Object *ob_armature = NULL;
1135  t->data_type = convert_type_get(t, &ob_armature);
1136  if (t->data_type == NULL) {
1137  printf("edit type not implemented!\n");
1138  BLI_assert(t->data_len_all == -1);
1139  t->data_len_all = 0;
1140  return;
1141  }
1142 
1143  t->flag |= t->data_type->flags;
1144 
1145  if (ob_armature) {
1146  init_TransDataContainers(t, ob_armature, &ob_armature, 1);
1147  }
1148  else {
1149  ViewLayer *view_layer = t->view_layer;
1150  Object *ob = OBACT(view_layer);
1151  init_TransDataContainers(t, ob, NULL, 0);
1152  }
1153 
1154  if (t->data_type == &TransConvertType_Object) {
1155  t->options |= CTX_OBJECT;
1156 
1157  /* Needed for correct Object.obmat after duplication, see: T62135. */
1158  BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
1159 
1160  if ((t->settings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) {
1161  t->options |= CTX_OBMODE_XFORM_OBDATA;
1162  }
1163  if ((t->settings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) {
1164  t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN;
1165  }
1167  /* Check if we're transforming the camera from the camera */
1168  if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
1169  View3D *v3d = t->view;
1170  RegionView3D *rv3d = t->region->regiondata;
1171  if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
1172  /* we could have a flag to easily check an object is being transformed */
1173  if (v3d->camera->id.tag & LIB_TAG_DOIT) {
1174  t->options |= CTX_CAMERA;
1175  }
1176  }
1177  else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) {
1178  t->options |= CTX_CAMERA;
1179  }
1180  }
1181  }
1182  else {
1183  if (t->data_type == &TransConvertType_Pose) {
1184  t->options |= CTX_POSE_BONE;
1185  }
1186  else if (t->data_type == &TransConvertType_Sequencer) {
1187  /* Sequencer has no use for floating point transform. */
1188  t->num.flag |= NUM_NO_FRACTION;
1189  }
1190  else if (t->data_type == &TransConvertType_SequencerImage) {
1191  t->obedit_type = -1;
1192  }
1193  t->data_type->createTransData(C, t);
1194  }
1195 
1197 
1199 }
1200 
1203 /* -------------------------------------------------------------------- */
1208 {
1209  Object *ob = tc->obedit;
1210  ModifierData *md = ob->modifiers.first;
1211  float tolerance[3] = {0.0f, 0.0f, 0.0f};
1212  int axis = 0;
1213 
1214  for (; md; md = md->next) {
1215  if ((md->type == eModifierType_Mirror) && (md->mode & eModifierMode_Realtime)) {
1217 
1218  if (mmd->flag & MOD_MIR_CLIPPING) {
1219  axis = 0;
1220  if (mmd->flag & MOD_MIR_AXIS_X) {
1221  axis |= 1;
1222  tolerance[0] = mmd->tolerance;
1223  }
1224  if (mmd->flag & MOD_MIR_AXIS_Y) {
1225  axis |= 2;
1226  tolerance[1] = mmd->tolerance;
1227  }
1228  if (mmd->flag & MOD_MIR_AXIS_Z) {
1229  axis |= 4;
1230  tolerance[2] = mmd->tolerance;
1231  }
1232  if (axis) {
1233  float mtx[4][4], imtx[4][4];
1234  int i;
1235 
1236  if (mmd->mirror_ob) {
1237  float obinv[4][4];
1238 
1239  invert_m4_m4(obinv, mmd->mirror_ob->obmat);
1240  mul_m4_m4m4(mtx, obinv, ob->obmat);
1241  invert_m4_m4(imtx, mtx);
1242  }
1243 
1244  TransData *td = tc->data;
1245  for (i = 0; i < tc->data_len; i++, td++) {
1246  int clip;
1247  float loc[3], iloc[3];
1248 
1249  if (td->loc == NULL) {
1250  break;
1251  }
1252 
1253  if (td->flag & TD_SKIP) {
1254  continue;
1255  }
1256 
1257  copy_v3_v3(loc, td->loc);
1258  copy_v3_v3(iloc, td->iloc);
1259 
1260  if (mmd->mirror_ob) {
1261  mul_m4_v3(mtx, loc);
1262  mul_m4_v3(mtx, iloc);
1263  }
1264 
1265  clip = 0;
1266  if (axis & 1) {
1267  if (fabsf(iloc[0]) <= tolerance[0] || loc[0] * iloc[0] < 0.0f) {
1268  loc[0] = 0.0f;
1269  clip = 1;
1270  }
1271  }
1272 
1273  if (axis & 2) {
1274  if (fabsf(iloc[1]) <= tolerance[1] || loc[1] * iloc[1] < 0.0f) {
1275  loc[1] = 0.0f;
1276  clip = 1;
1277  }
1278  }
1279  if (axis & 4) {
1280  if (fabsf(iloc[2]) <= tolerance[2] || loc[2] * iloc[2] < 0.0f) {
1281  loc[2] = 0.0f;
1282  clip = 1;
1283  }
1284  }
1285  if (clip) {
1286  if (mmd->mirror_ob) {
1287  mul_m4_v3(imtx, loc);
1288  }
1289  copy_v3_v3(td->loc, loc);
1290  }
1291  }
1292  }
1293  }
1294  }
1295  }
1296 }
1297 
1299 {
1300  Scene *scene = t->scene;
1301  wmTimer *animtimer = t->animtimer;
1302  ScreenAnimData *sad = (animtimer) ? animtimer->customdata : NULL;
1303 
1304  /* sanity checks */
1305  if (ELEM(NULL, scene, id, sad)) {
1306  return;
1307  }
1308 
1309  /* check if we need a new strip if:
1310  * - if animtimer is running
1311  * - we're not only keying for available channels
1312  * - the option to add new actions for each round is not enabled
1313  */
1314  if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL) == 0 &&
1316  /* if playback has just looped around,
1317  * we need to add a new NLA track+strip to allow a clean pass to occur */
1318  if ((sad) && (sad->flag & ANIMPLAY_FLAG_JUMPED)) {
1319  AnimData *adt = BKE_animdata_from_id(id);
1320  const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
1321 
1322  /* perform push-down manually with some differences
1323  * NOTE: BKE_nla_action_pushdown() sync warning...
1324  */
1325  if ((adt->action) && !(adt->flag & ADT_NLA_EDIT_ON)) {
1326  float astart, aend;
1327 
1328  /* only push down if action is more than 1-2 frames long */
1329  calc_action_range(adt->action, &astart, &aend, 1);
1330  if (aend > astart + 2.0f) {
1332 
1333  /* clear reference to action now that we've pushed it onto the stack */
1334  id_us_min(&adt->action->id);
1335  adt->action = NULL;
1336 
1337  /* adjust blending + extend so that they will behave correctly */
1341 
1342  /* copy current "action blending" settings from adt to the strip,
1343  * as it was keyframed with these settings, so omitting them will
1344  * change the effect [T54766]
1345  */
1346  if (is_first == false) {
1347  strip->blendmode = adt->act_blendmode;
1348  strip->influence = adt->act_influence;
1349 
1350  if (adt->act_influence < 1.0f) {
1351  /* enable "user-controlled" influence (which will insert a default keyframe)
1352  * so that the influence doesn't get lost on the new update
1353  *
1354  * NOTE: An alternative way would have been to instead hack the influence
1355  * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
1356  * is disabled but auto-blending isn't being used. However, that approach
1357  * is a bit hacky/hard to discover, and may cause backwards compatibility issues,
1358  * so it's better to just do it this way.
1359  */
1362  }
1363  }
1364 
1365  /* also, adjust the AnimData's action extend mode to be on
1366  * 'nothing' so that previous result still play
1367  */
1369  }
1370  }
1371  }
1372  }
1373 }
1374 
1375 void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float y_fac)
1376 {
1377  float delta_x = td->loc[0] - td->iloc[0];
1378  float delta_y = (td->loc[1] - td->iloc[1]) * y_fac;
1379 
1380  /* If the handles are to be moved too
1381  * (as side-effect of keyframes moving, to keep the general effect)
1382  * offset them by the same amount so that the general angles are maintained
1383  * (i.e. won't change while handles are free-to-roam and keyframes are snap-locked).
1384  */
1385  if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) {
1386  td2d->h1[0] = td2d->ih1[0] + delta_x;
1387  td2d->h1[1] = td2d->ih1[1] + delta_y;
1388  }
1389  if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) {
1390  td2d->h2[0] = td2d->ih2[0] + delta_x;
1391  td2d->h2[1] = td2d->ih2[1] + delta_y;
1392  }
1393 }
1394 
1396 {
1397  if (!t->data_type || !t->data_type->recalcData) {
1398  return;
1399  }
1400  t->data_type->recalcData(t);
1401 }
1402 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers)
struct AnimData * BKE_animdata_from_id(const struct ID *id)
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
void testhandles_fcurve(struct FCurve *fcu, eBezTriple_Flag sel_flag, bool use_handle)
Definition: fcurve.c:1308
#define BEZT_BINARYSEARCH_THRESH
Definition: BKE_fcurve.h:222
void BKE_fcurve_delete_key(struct FCurve *fcu, int index)
Definition: fcurve.c:1661
@ G_DEBUG
Definition: BKE_global.h:174
@ G_TRANSFORM_OBJ
Definition: BKE_global.h:247
@ G_TRANSFORM_CURSOR
Definition: BKE_global.h:257
@ G_TRANSFORM_SEQ
Definition: BKE_global.h:249
@ G_TRANSFORM_EDIT
Definition: BKE_global.h:248
@ G_TRANSFORM_FCURVES
Definition: BKE_global.h:250
#define BKE_view_layer_array_from_objects_in_mode(view_layer, v3d, r_len,...)
Definition: BKE_layer.h:523
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip)
Definition: nla.c:1523
struct NlaStrip * BKE_nlastack_add_strip(struct AnimData *adt, struct bAction *act, bool is_liboverride)
Definition: nla.c:445
void BKE_scene_graph_evaluated_ensure(struct Depsgraph *depsgraph, struct Main *bmain)
Definition: scene.cc:2653
#define BLI_assert(a)
Definition: BLI_assert.h:46
A KD-tree for nearest neighbor search.
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
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4_m4_fallback(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1215
void normalize_m3_m3(float R[3][3], const float M[3][3]) ATTR_NONNULL()
Definition: math_matrix.c:1927
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:71
void copy_m3_m4(float m1[3][3], const float m2[4][4])
Definition: math_matrix.c:87
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 copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
MINLINE void sub_v3_v3(float r[3], const float a[3])
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])
void project_v3_v3v3(float out[3], const float p[3], const float v_proj[3])
Definition: math_vector.c:600
MINLINE float normalize_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 SWAP(type, a, b)
#define ELEM(...)
#define IS_EQT(a, b, c)
void DEG_relations_tag_update(struct Main *bmain)
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ PCHAN_HAS_IK
@ PCHAN_HAS_TARGET
@ NLASTRIP_FLAG_ACTIVE
@ NLASTRIP_FLAG_USR_INFLUENCE
@ NLASTRIP_FLAG_AUTO_BLENDS
@ NLASTRIP_FLAG_SELECT
@ ADT_NLA_EDIT_ON
@ NLASTRIP_EXTEND_NOTHING
@ FCURVE_INT_VALUES
@ FCURVE_DISCRETE_VALUES
@ CONSTRAINT_OFF
@ CONSTRAINT_DISABLE
@ CONSTRAINT_IK_TEMP
@ ROTLIKE_MIX_OFFSET
@ ROTLIKE_MIX_BEFORE
@ CONSTRAINT_TYPE_CHILDOF
@ CONSTRAINT_TYPE_TRANSFORM
@ CONSTRAINT_TYPE_FOLLOWTRACK
@ CONSTRAINT_TYPE_OBJECTSOLVER
@ CONSTRAINT_TYPE_ARMATURE
@ CONSTRAINT_TYPE_ROTLIKE
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_TRANSLIKE
@ CONSTRAINT_TYPE_CLAMPTO
@ CONSTRAINT_TYPE_ACTION
@ CONSTRAINT_TYPE_FOLLOWPATH
@ ACTCON_MIX_BEFORE
@ ACTCON_MIX_BEFORE_SPLIT
@ ACTCON_MIX_BEFORE_FULL
@ TRANSLIKE_MIX_BEFORE
@ TRANSLIKE_MIX_BEFORE_SPLIT
@ TRANSLIKE_MIX_BEFORE_FULL
@ CHILDOF_LOCZ
@ CHILDOF_LOCX
@ CHILDOF_LOCY
@ TRANS_ROTATION
@ TRANS_MIXROT_BEFORE
#define BEZT_ISSEL_ANY(bezt)
@ ME_SYMMETRY_X
@ ME_SYMMETRY_Y
@ ME_SYMMETRY_Z
@ eModifierMode_Realtime
@ eModifierType_Mirror
@ MOD_MIR_AXIS_Z
@ MOD_MIR_CLIPPING
@ MOD_MIR_AXIS_X
@ MOD_MIR_AXIS_Y
#define OB_MODE_ALL_PAINT
#define OB_MODE_ALL_WEIGHT_PAINT
eObjectMode
@ OB_MODE_VERTEX_GPENCIL
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_GPENCIL
@ OB_MODE_SCULPT
@ OB_MODE_SCULPT_GPENCIL
@ OB_MODE_POSE
@ OB_MODE_OBJECT
@ OB_MODE_PAINT_GPENCIL
@ OB_LATTICE
@ OB_MBALL
@ OB_SURF
@ OB_ARMATURE
@ OB_MESH
@ OB_CURVES_LEGACY
@ SCE_XFORM_SKIP_CHILDREN
@ SCE_XFORM_DATA_ORIGIN
#define OBACT(_view_layer)
@ RGN_TYPE_WINDOW
@ SPACE_CLIP
@ SPACE_ACTION
@ SPACE_NODE
@ SPACE_NLA
@ SPACE_SEQ
@ SPACE_IMAGE
@ SPACE_GRAPH
@ SPACE_VIEW3D
@ ANIMRECORD_FLAG_WITHNLA
@ V3D_AROUND_ACTIVE
@ V3D_AROUND_CENTER_BOUNDS
@ V3D_AROUND_CENTER_MEDIAN
@ V3D_AROUND_LOCAL_ORIGINS
#define RV3D_CAMOB
#define IS_AUTOKEY_FLAG(scene, flag)
@ NUM_NO_FRACTION
Definition: ED_numinput.h:58
int PE_start_edit(struct PTCacheEdit *edit)
struct PTCacheEdit * PE_get_current(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
@ ANIMPLAY_FLAG_JUMPED
@ TFM_RESIZE
Definition: ED_transform.h:32
@ TFM_SKIN_RESIZE
Definition: ED_transform.h:33
@ TFM_SHEAR
Definition: ED_transform.h:35
@ TFM_SHRINKFATTEN
Definition: ED_transform.h:37
@ TFM_VERT_CREASE
Definition: ED_transform.h:42
@ TFM_ROTATION
Definition: ED_transform.h:31
@ TFM_BWEIGHT
Definition: ED_transform.h:57
@ TFM_TRANSLATION
Definition: ED_transform.h:30
@ TFM_DUMMY
Definition: ED_transform.h:29
@ TFM_TRACKBALL
Definition: ED_transform.h:39
NSNotificationCenter * center
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
#define C
Definition: RandGen.cpp:25
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
Scene scene
SyclQueue * queue
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 G(x, y, z)
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
struct Object * transform_object_deform_pose_armature_get(const TransInfo *t, struct Object *ob)
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
bAction * action
short act_blendmode
float act_influence
short act_extendmode
ListBase nla_tracks
uint8_t h1
float vec[3][3]
uint8_t h2
char * rna_path
BezTriple * bezt
short flag
unsigned int totvert
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct Object * mirror_ob
struct ModifierData * next
short blendmode
float influence
short extendmode
ListBase modifiers
float obmat[4][4]
struct SculptSession * sculpt
float viewinv[4][4]
struct ToolSettings * toolsettings
void(* createTransData)(bContext *C, TransInfo *t)
float ih2[2]
float ih1[2]
TransDataCurveHandleFlags * hdata
float axismtx[3][3]
float mtx[3][3]
struct Object * camera
struct Object * ob_center
struct bConstraint * next
ListBase constraints
struct bPoseChannel * next
struct tRetainedKeyframe * prev
struct tRetainedKeyframe * next
void * customdata
Definition: WM_types.h:869
bool transdata_check_local_islands(TransInfo *t, short around)
Definition: transform.c:64
void calc_distanceCurveVerts(TransData *head, TransData *tail, bool cyclic)
void transform_convert_flush_handle2D(TransData *td, TransData2D *td2d, const float y_fac)
void transform_autoik_update(TransInfo *t, short mode)
void special_aftertrans_update(bContext *C, TransInfo *t)
void transform_convert_clip_mirror_modifier_apply(TransDataContainer *tc)
void recalcData(TransInfo *t)
void sort_trans_data_dist(TransInfo *t)
bool FrameOnMouseSide(char side, float frame, float cframe)
void transform_around_single_fallback(TransInfo *t)
static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc)
static bool pchan_autoik_adjust(bPoseChannel *pchan, short chainlen)
void clipUVData(TransInfo *t)
static void init_proportional_edit(TransInfo *t)
static int countAndCleanTransDataContainer(TransInfo *t)
void animrecord_check_state(TransInfo *t, struct ID *id)
struct tRetainedKeyframe tRetainedKeyframe
void transform_around_single_fallback_ex(TransInfo *t, int data_len_all)
static void init_TransDataContainers(TransInfo *t, Object *obact, Object **objects, uint objects_len)
static void sort_trans_data_selected_first(TransInfo *t)
void createTransData(bContext *C, TransInfo *t)
static TransConvertTypeInfo * convert_type_get(const TransInfo *t, Object **r_obj_armature)
bool transform_mode_use_local_origins(const TransInfo *t)
int special_transform_moving(TransInfo *t)
bool constraints_list_needinv(TransInfo *t, ListBase *list)
void posttrans_fcurve_clean(FCurve *fcu, const int sel_flag, const bool use_handle)
static void sort_trans_data_selected_first_container(TransDataContainer *tc)
TransDataCurveHandleFlags * initTransDataCurveHandles(TransData *td, struct BezTriple *bezt)
static int trans_data_compare_rdist(const void *a, const void *b)
static void set_prop_dist(TransInfo *t, const bool with_dist)
char transform_convert_frame_side_dir_get(TransInfo *t, float cframe)
static int trans_data_compare_dist(const void *a, const void *b)
conversion and adaptation of different datablocks to a common struct.
TransConvertTypeInfo TransConvertType_Action
TransConvertTypeInfo TransConvertType_CursorImage
TransConvertTypeInfo TransConvertType_GPencil
TransConvertTypeInfo TransConvertType_MeshSkin
TransConvertTypeInfo TransConvertType_MeshVertCData
TransConvertTypeInfo TransConvertType_Cursor3D
TransConvertTypeInfo TransConvertType_Mask
TransConvertTypeInfo TransConvertType_NLA
TransConvertTypeInfo TransConvertType_Particle
TransConvertTypeInfo TransConvertType_PaintCurve
TransConvertTypeInfo TransConvertType_Sequencer
TransConvertTypeInfo TransConvertType_MeshUV
TransConvertTypeInfo TransConvertType_CursorSequencer
TransConvertTypeInfo TransConvertType_MeshEdge
TransConvertTypeInfo TransConvertType_Sculpt
TransConvertTypeInfo TransConvertType_ObjectTexSpace
TransConvertTypeInfo TransConvertType_Tracking
TransConvertTypeInfo TransConvertType_MBall
TransConvertTypeInfo TransConvertType_Graph
TransConvertTypeInfo TransConvertType_Curve
TransConvertTypeInfo TransConvertType_Node
TransConvertTypeInfo TransConvertType_Lattice
TransConvertTypeInfo TransConvertType_EditArmature
TransConvertTypeInfo TransConvertType_SequencerImage
TransConvertTypeInfo TransConvertType_Mesh
TransConvertTypeInfo TransConvertType_Pose
TransConvertTypeInfo TransConvertType_Object
@ TD_BEZTRIPLE
@ TD_NOTCONNECTED
@ TD_MOVEHANDLE1
@ TD_SELECTED
@ TD_SKIP
@ TD_MOVEHANDLE2