Blender  V3.3
action.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 <math.h>
9 #include <stddef.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "MEM_guardedalloc.h"
14 
15 /* Allow using deprecated functionality for .blend file I/O. */
16 #define DNA_DEPRECATED_ALLOW
17 
18 #include "DNA_anim_types.h"
19 #include "DNA_armature_types.h"
20 #include "DNA_constraint_types.h"
21 #include "DNA_object_types.h"
22 #include "DNA_scene_types.h"
23 
24 #include "BLI_blenlib.h"
25 #include "BLI_ghash.h"
26 #include "BLI_math.h"
27 #include "BLI_session_uuid.h"
28 #include "BLI_string_utils.h"
29 #include "BLI_utildefines.h"
30 
31 #include "BLT_translation.h"
32 
33 #include "BKE_action.h"
34 #include "BKE_anim_data.h"
35 #include "BKE_anim_visualization.h"
36 #include "BKE_animsys.h"
37 #include "BKE_armature.h"
38 #include "BKE_asset.h"
39 #include "BKE_constraint.h"
40 #include "BKE_deform.h"
41 #include "BKE_fcurve.h"
42 #include "BKE_icons.h"
43 #include "BKE_idprop.h"
44 #include "BKE_idtype.h"
45 #include "BKE_lib_id.h"
46 #include "BKE_lib_query.h"
47 #include "BKE_main.h"
48 #include "BKE_object.h"
49 
50 #include "DEG_depsgraph.h"
51 #include "DEG_depsgraph_build.h"
52 
53 #include "BIK_api.h"
54 
55 #include "RNA_access.h"
56 #include "RNA_path.h"
57 #include "RNA_prototypes.h"
58 
59 #include "BLO_read_write.h"
60 
61 #include "CLG_log.h"
62 
63 static CLG_LogRef LOG = {"bke.action"};
64 
65 /* *********************** NOTE ON POSE AND ACTION **********************
66  *
67  * - Pose is the local (object level) component of armature. The current
68  * object pose is saved in files, and (will be) is presorted for dependency
69  * - Actions have fewer (or other) channels, and write data to a Pose
70  * - Currently ob->pose data is controlled in BKE_pose_where_is only. The (recalc)
71  * event system takes care of calling that
72  * - The NLA system (here too) uses Poses as interpolation format for Actions
73  * - Therefore we assume poses to be static, and duplicates of poses have channels in
74  * same order, for quick interpolation reasons
75  *
76  * ****************************** (ton) ************************************ */
77 
78 /**************************** Action Datablock ******************************/
79 
80 /*********************** Armature Datablock ***********************/
81 
92 static void action_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
93 {
94  bAction *action_dst = (bAction *)id_dst;
95  const bAction *action_src = (const bAction *)id_src;
96 
97  bActionGroup *group_dst, *group_src;
98  FCurve *fcurve_dst, *fcurve_src;
99 
100  /* Duplicate the lists of groups and markers. */
101  BLI_duplicatelist(&action_dst->groups, &action_src->groups);
102  BLI_duplicatelist(&action_dst->markers, &action_src->markers);
103 
104  /* Copy F-Curves, fixing up the links as we go. */
105  BLI_listbase_clear(&action_dst->curves);
106 
107  for (fcurve_src = action_src->curves.first; fcurve_src; fcurve_src = fcurve_src->next) {
108  /* Duplicate F-Curve. */
109 
110  /* XXX TODO: pass subdata flag?
111  * But surprisingly does not seem to be doing any ID refcounting... */
112  fcurve_dst = BKE_fcurve_copy(fcurve_src);
113 
114  BLI_addtail(&action_dst->curves, fcurve_dst);
115 
116  /* Fix group links (kindof bad list-in-list search, but this is the most reliable way). */
117  for (group_dst = action_dst->groups.first, group_src = action_src->groups.first;
118  group_dst && group_src;
119  group_dst = group_dst->next, group_src = group_src->next) {
120  if (fcurve_src->grp == group_src) {
121  fcurve_dst->grp = group_dst;
122 
123  if (group_dst->channels.first == fcurve_src) {
124  group_dst->channels.first = fcurve_dst;
125  }
126  if (group_dst->channels.last == fcurve_src) {
127  group_dst->channels.last = fcurve_dst;
128  }
129  break;
130  }
131  }
132  }
133 
134  if (flag & LIB_ID_COPY_NO_PREVIEW) {
135  action_dst->preview = NULL;
136  }
137  else {
138  BKE_previewimg_id_copy(&action_dst->id, &action_src->id);
139  }
140 }
141 
143 static void action_free_data(struct ID *id)
144 {
145  bAction *action = (bAction *)id;
146  /* No animdata here. */
147 
148  /* Free F-Curves. */
149  BKE_fcurves_free(&action->curves);
150 
151  /* Free groups. */
152  BLI_freelistN(&action->groups);
153 
154  /* Free pose-references (aka local markers). */
155  BLI_freelistN(&action->markers);
156 
157  BKE_previewimg_free(&action->preview);
158 }
159 
161 {
162  bAction *act = (bAction *)id;
163 
164  LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
166  }
167 
168  LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
170  }
171 }
172 
173 static void action_blend_write(BlendWriter *writer, ID *id, const void *id_address)
174 {
175  bAction *act = (bAction *)id;
176 
177  BLO_write_id_struct(writer, bAction, id_address, &act->id);
178  BKE_id_blend_write(writer, &act->id);
179 
180  BKE_fcurve_blend_write(writer, &act->curves);
181 
182  LISTBASE_FOREACH (bActionGroup *, grp, &act->groups) {
183  BLO_write_struct(writer, bActionGroup, grp);
184  }
185 
186  LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
187  BLO_write_struct(writer, TimeMarker, marker);
188  }
189 
190  BKE_previewimg_blend_write(writer, act->preview);
191 }
192 
193 static void action_blend_read_data(BlendDataReader *reader, ID *id)
194 {
195  bAction *act = (bAction *)id;
196 
197  BLO_read_list(reader, &act->curves);
198  BLO_read_list(reader, &act->chanbase); /* XXX deprecated - old animation system */
199  BLO_read_list(reader, &act->groups);
200  BLO_read_list(reader, &act->markers);
201 
202  /* XXX deprecated - old animation system <<< */
203  LISTBASE_FOREACH (bActionChannel *, achan, &act->chanbase) {
204  BLO_read_data_address(reader, &achan->grp);
205 
206  BLO_read_list(reader, &achan->constraintChannels);
207  }
208  /* >>> XXX deprecated - old animation system */
209 
210  BKE_fcurve_blend_read_data(reader, &act->curves);
211 
212  LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
213  BLO_read_data_address(reader, &agrp->channels.first);
214  BLO_read_data_address(reader, &agrp->channels.last);
215  }
216 
217  BLO_read_data_address(reader, &act->preview);
218  BKE_previewimg_blend_read(reader, act->preview);
219 }
220 
221 static void blend_read_lib_constraint_channels(BlendLibReader *reader, ID *id, ListBase *chanbase)
222 {
223  LISTBASE_FOREACH (bConstraintChannel *, chan, chanbase) {
224  BLO_read_id_address(reader, id->lib, &chan->ipo);
225  }
226 }
227 
228 static void action_blend_read_lib(BlendLibReader *reader, ID *id)
229 {
230  bAction *act = (bAction *)id;
231 
232  /* XXX deprecated - old animation system <<< */
233  LISTBASE_FOREACH (bActionChannel *, chan, &act->chanbase) {
234  BLO_read_id_address(reader, act->id.lib, &chan->ipo);
235  blend_read_lib_constraint_channels(reader, &act->id, &chan->constraintChannels);
236  }
237  /* >>> XXX deprecated - old animation system */
238 
239  BKE_fcurve_blend_read_lib(reader, &act->id, &act->curves);
240 
241  LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
242  if (marker->camera) {
243  BLO_read_id_address(reader, act->id.lib, &marker->camera);
244  }
245  }
246 }
247 
249 {
250  LISTBASE_FOREACH (bConstraintChannel *, chan, chanbase) {
251  BLO_expand(expander, chan->ipo);
252  }
253 }
254 
255 static void action_blend_read_expand(BlendExpander *expander, ID *id)
256 {
257  bAction *act = (bAction *)id;
258 
259  /* XXX deprecated - old animation system -------------- */
260  LISTBASE_FOREACH (bActionChannel *, chan, &act->chanbase) {
261  BLO_expand(expander, chan->ipo);
262  blend_read_expand_constraint_channels(expander, &chan->constraintChannels);
263  }
264  /* --------------------------------------------------- */
265 
266  /* F-Curves in Action */
267  BKE_fcurve_blend_read_expand(expander, &act->curves);
268 
269  LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
270  if (marker->camera) {
271  BLO_expand(expander, marker->camera);
272  }
273  }
274 }
275 
277 {
278  const bool is_single_frame = BKE_action_has_single_frame(action);
279 
280  IDPropertyTemplate idprop = {0};
281  idprop.i = is_single_frame;
282 
283  IDProperty *property = IDP_New(IDP_INT, &idprop, "is_single_frame");
284  return property;
285 }
286 
287 static void action_asset_pre_save(void *asset_ptr, struct AssetMetaData *asset_data)
288 {
289  bAction *action = (bAction *)asset_ptr;
290  BLI_assert(GS(action->id.name) == ID_AC);
291 
292  IDProperty *action_type = action_asset_type_property(action);
293  BKE_asset_metadata_idprop_ensure(asset_data, action_type);
294 }
295 
297  /* pre_save_fn */ action_asset_pre_save,
298 };
299 
301  .id_code = ID_AC,
302  .id_filter = FILTER_ID_AC,
303  .main_listbase_index = INDEX_ID_AC,
304  .struct_size = sizeof(bAction),
305  .name = "Action",
306  .name_plural = "actions",
307  .translation_context = BLT_I18NCONTEXT_ID_ACTION,
308  .flags = IDTYPE_FLAGS_NO_ANIMDATA,
309  .asset_type_info = &AssetType_AC,
310 
311  .init_data = NULL,
312  .copy_data = action_copy_data,
313  .free_data = action_free_data,
314  .make_local = NULL,
315  .foreach_id = action_foreach_id,
316  .foreach_cache = NULL,
317  .foreach_path = NULL,
318  .owner_get = NULL,
319 
320  .blend_write = action_blend_write,
321  .blend_read_data = action_blend_read_data,
322  .blend_read_lib = action_blend_read_lib,
323  .blend_read_expand = action_blend_read_expand,
324 
325  .blend_read_undo_preserve = NULL,
326 
327  .lib_override_apply_post = NULL,
328 };
329 
330 /* ***************** Library data level operations on action ************** */
331 
332 bAction *BKE_action_add(Main *bmain, const char name[])
333 {
334  bAction *act;
335 
336  act = BKE_id_new(bmain, ID_AC, name);
337 
338  return act;
339 }
340 
341 /* .................................. */
342 
343 /* *************** Action Groups *************** */
344 
346 {
347  bActionGroup *agrp = NULL;
348 
349  if (act && act->groups.first) {
350  for (agrp = act->groups.first; agrp; agrp = agrp->next) {
351  if (agrp->flag & AGRP_ACTIVE) {
352  break;
353  }
354  }
355  }
356 
357  return agrp;
358 }
359 
361 {
362  bActionGroup *grp;
363 
364  /* sanity checks */
365  if (act == NULL) {
366  return;
367  }
368 
369  /* Deactivate all others */
370  for (grp = act->groups.first; grp; grp = grp->next) {
371  if ((grp == agrp) && (select)) {
372  grp->flag |= AGRP_ACTIVE;
373  }
374  else {
375  grp->flag &= ~AGRP_ACTIVE;
376  }
377  }
378 }
379 
381 {
382  /* Only do color copying if using a custom color (i.e. not default color). */
383  if (grp->customCol) {
384  if (grp->customCol > 0) {
385  /* copy theme colors on-to group's custom color in case user tries to edit color */
386  bTheme *btheme = U.themes.first;
387  ThemeWireColor *col_set = &btheme->tarm[(grp->customCol - 1)];
388 
389  memcpy(&grp->cs, col_set, sizeof(ThemeWireColor));
390  }
391  else {
392  /* if a reference group is provided, use the custom color from there... */
393  if (ref_grp) {
394  /* assumption: reference group has a color set */
395  memcpy(&grp->cs, &ref_grp->cs, sizeof(ThemeWireColor));
396  }
397  /* otherwise, init custom color with a generic/placeholder color set if
398  * no previous theme color was used that we can just keep using
399  */
400  else if (grp->cs.solid[0] == 0) {
401  /* define for setting colors in theme below */
402  rgba_uchar_args_set(grp->cs.solid, 0xff, 0x00, 0x00, 255);
403  rgba_uchar_args_set(grp->cs.select, 0x81, 0xe6, 0x14, 255);
404  rgba_uchar_args_set(grp->cs.active, 0x18, 0xb6, 0xe0, 255);
405  }
406  }
407  }
408 }
409 
410 bActionGroup *action_groups_add_new(bAction *act, const char name[])
411 {
412  bActionGroup *agrp;
413 
414  /* sanity check: must have action and name */
415  if (ELEM(NULL, act, name)) {
416  return NULL;
417  }
418 
419  /* allocate a new one */
420  agrp = MEM_callocN(sizeof(bActionGroup), "bActionGroup");
421 
422  /* make it selected, with default name */
423  agrp->flag = AGRP_SELECTED;
424  BLI_strncpy(agrp->name, name[0] ? name : DATA_("Group"), sizeof(agrp->name));
425 
426  /* add to action, and validate */
427  BLI_addtail(&act->groups, agrp);
429  &act->groups, agrp, DATA_("Group"), '.', offsetof(bActionGroup, name), sizeof(agrp->name));
430 
431  /* return the new group */
432  return agrp;
433 }
434 
436 {
437  /* sanity checks */
438  if (ELEM(NULL, act, agrp, fcurve)) {
439  return;
440  }
441 
442  /* if no channels anywhere, just add to two lists at the same time */
443  if (BLI_listbase_is_empty(&act->curves)) {
444  fcurve->next = fcurve->prev = NULL;
445 
446  agrp->channels.first = agrp->channels.last = fcurve;
447  act->curves.first = act->curves.last = fcurve;
448  }
449 
450  /* if the group already has channels, the F-Curve can simply be added to the list
451  * (i.e. as the last channel in the group)
452  */
453  else if (agrp->channels.first) {
454  /* if the group's last F-Curve is the action's last F-Curve too,
455  * then set the F-Curve as the last for the action first so that
456  * the lists will be in sync after linking
457  */
458  if (agrp->channels.last == act->curves.last) {
459  act->curves.last = fcurve;
460  }
461 
462  /* link in the given F-Curve after the last F-Curve in the group,
463  * which means that it should be able to fit in with the rest of the
464  * list seamlessly
465  */
466  BLI_insertlinkafter(&agrp->channels, agrp->channels.last, fcurve);
467  }
468 
469  /* otherwise, need to find the nearest F-Curve in group before/after current to link with */
470  else {
471  bActionGroup *grp;
472 
473  /* firstly, link this F-Curve to the group */
474  agrp->channels.first = agrp->channels.last = fcurve;
475 
476  /* Step through the groups preceding this one,
477  * finding the F-Curve there to attach this one after. */
478  for (grp = agrp->prev; grp; grp = grp->prev) {
479  /* if this group has F-Curves, we want weave the given one in right after the last channel
480  * there, but via the Action's list not this group's list
481  * - this is so that the F-Curve is in the right place in the Action,
482  * but won't be included in the previous group.
483  */
484  if (grp->channels.last) {
485  /* once we've added, break here since we don't need to search any further... */
486  BLI_insertlinkafter(&act->curves, grp->channels.last, fcurve);
487  break;
488  }
489  }
490 
491  /* If grp is NULL, that means we fell through, and this F-Curve should be added as the new
492  * first since group is (effectively) the first group. Thus, the existing first F-Curve becomes
493  * the second in the chain, etc. */
494  if (grp == NULL) {
495  BLI_insertlinkbefore(&act->curves, act->curves.first, fcurve);
496  }
497  }
498 
499  /* set the F-Curve's new group */
500  fcurve->grp = agrp;
501 }
502 
504 {
505  /* Sanity check. */
506  if (ELEM(NULL, act, act->groups.first)) {
507  return;
508  }
509 
510  /* Clear out all group channels. Channels that are actually in use are
511  * reconstructed below; this step is necessary to clear out unused groups. */
512  LISTBASE_FOREACH (bActionGroup *, group, &act->groups) {
513  BLI_listbase_clear(&group->channels);
514  }
515 
516  /* Sort the channels into the group lists, destroying the act->curves list. */
517  ListBase ungrouped = {NULL, NULL};
518 
519  LISTBASE_FOREACH_MUTABLE (FCurve *, fcurve, &act->curves) {
520  if (fcurve->grp) {
521  BLI_assert(BLI_findindex(&act->groups, fcurve->grp) >= 0);
522 
523  BLI_addtail(&fcurve->grp->channels, fcurve);
524  }
525  else {
526  BLI_addtail(&ungrouped, fcurve);
527  }
528  }
529 
530  /* Recombine into the main list. */
531  BLI_listbase_clear(&act->curves);
532 
533  LISTBASE_FOREACH (bActionGroup *, group, &act->groups) {
534  /* Copy the list header to preserve the pointers in the group. */
535  ListBase tmp = group->channels;
536  BLI_movelisttolist(&act->curves, &tmp);
537  }
538 
539  BLI_movelisttolist(&act->curves, &ungrouped);
540 }
541 
543 {
544  /* sanity checks */
545  if (ELEM(NULL, act, fcu)) {
546  return;
547  }
548 
549  /* check if any group used this directly */
550  if (fcu->grp) {
551  bActionGroup *agrp = fcu->grp;
552 
553  if (agrp->channels.first == agrp->channels.last) {
554  if (agrp->channels.first == fcu) {
556  }
557  }
558  else if (agrp->channels.first == fcu) {
559  if ((fcu->next) && (fcu->next->grp == agrp)) {
560  agrp->channels.first = fcu->next;
561  }
562  else {
563  agrp->channels.first = NULL;
564  }
565  }
566  else if (agrp->channels.last == fcu) {
567  if ((fcu->prev) && (fcu->prev->grp == agrp)) {
568  agrp->channels.last = fcu->prev;
569  }
570  else {
571  agrp->channels.last = NULL;
572  }
573  }
574 
575  fcu->grp = NULL;
576  }
577 
578  /* now just remove from list */
579  BLI_remlink(&act->curves, fcu);
580 }
581 
583 {
584  /* sanity checks */
585  if (ELEM(NULL, act, act->groups.first, name) || (name[0] == 0)) {
586  return NULL;
587  }
588 
589  /* do string comparisons */
590  return BLI_findstring(&act->groups, name, offsetof(bActionGroup, name));
591 }
592 
594 {
595  bActionGroup *agrp;
596 
597  /* sanity checks */
598  if (ELEM(NULL, act, act->groups.first)) {
599  return;
600  }
601 
602  /* flag clearing loop */
603  for (agrp = act->groups.first; agrp; agrp = agrp->next) {
604  agrp->flag &= ~AGRP_TEMP;
605  }
606 }
607 
608 /* *************** Pose channels *************** */
609 
611 {
613 }
614 
615 bPoseChannel *BKE_pose_channel_find_name(const bPose *pose, const char *name)
616 {
617  if (ELEM(NULL, pose, name) || (name[0] == '\0')) {
618  return NULL;
619  }
620 
621  if (pose->chanhash) {
622  return BLI_ghash_lookup(pose->chanhash, (const void *)name);
623  }
624 
625  return BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name));
626 }
627 
628 bPoseChannel *BKE_pose_channel_ensure(bPose *pose, const char *name)
629 {
630  bPoseChannel *chan;
631 
632  if (pose == NULL) {
633  return NULL;
634  }
635 
636  /* See if this channel exists */
637  chan = BKE_pose_channel_find_name(pose, name);
638  if (chan) {
639  return chan;
640  }
641 
642  /* If not, create it and add it */
643  chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
644 
646 
647  BLI_strncpy(chan->name, name, sizeof(chan->name));
648 
649  copy_v3_fl(chan->custom_scale_xyz, 1.0f);
652 
653  /* init vars to prevent math errors */
654  unit_qt(chan->quat);
655  unit_axis_angle(chan->rotAxis, &chan->rotAngle);
656  chan->size[0] = chan->size[1] = chan->size[2] = 1.0f;
657 
658  copy_v3_fl(chan->scale_in, 1.0f);
659  copy_v3_fl(chan->scale_out, 1.0f);
660 
661  chan->limitmin[0] = chan->limitmin[1] = chan->limitmin[2] = -M_PI;
662  chan->limitmax[0] = chan->limitmax[1] = chan->limitmax[2] = M_PI;
663  chan->stiffness[0] = chan->stiffness[1] = chan->stiffness[2] = 0.0f;
664  chan->ikrotweight = chan->iklinweight = 0.0f;
665  unit_m4(chan->constinv);
666 
667  chan->protectflag = OB_LOCK_ROT4D; /* lock by components by default */
668 
669  BLI_addtail(&pose->chanbase, chan);
670  if (pose->chanhash) {
671  BLI_ghash_insert(pose->chanhash, chan->name, chan);
672  }
673 
674  return chan;
675 }
676 
677 #ifndef NDEBUG
679 {
680  if (pose->chanhash) {
681  bPoseChannel *pchan;
682  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
683  if (BLI_ghash_lookup(pose->chanhash, pchan->name) != pchan) {
684  return false;
685  }
686  }
687  }
688 
689  return true;
690 }
691 
692 #endif
693 
694 bool BKE_pose_is_layer_visible(const bArmature *arm, const bPoseChannel *pchan)
695 {
696  return (pchan->bone->layer & arm->layer);
697 }
698 
699 bPoseChannel *BKE_pose_channel_active(Object *ob, const bool check_arm_layer)
700 {
701  bArmature *arm = (ob) ? ob->data : NULL;
702  bPoseChannel *pchan;
703 
704  if (ELEM(NULL, ob, ob->pose, arm)) {
705  return NULL;
706  }
707 
708  /* find active */
709  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
710  if ((pchan->bone) && (pchan->bone == arm->act_bone)) {
711  if (!check_arm_layer || BKE_pose_is_layer_visible(arm, pchan)) {
712  return pchan;
713  }
714  }
715  }
716 
717  return NULL;
718 }
719 
721 {
722  return BKE_pose_channel_active(ob, true);
723 }
724 
726 {
727  bArmature *arm = (ob) ? ob->data : NULL;
728 
729  if (ELEM(NULL, ob, ob->pose, arm)) {
730  return NULL;
731  }
732 
734  if (pchan && (pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) {
735  return pchan;
736  }
737 
738  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
739  if (pchan->bone != NULL) {
740  if ((pchan->bone->flag & BONE_SELECTED) && PBONE_VISIBLE(arm, pchan->bone)) {
741  return pchan;
742  }
743  }
744  }
745  return NULL;
746 }
747 
748 bPoseChannel *BKE_pose_channel_get_mirrored(const bPose *pose, const char *name)
749 {
750  char name_flip[MAXBONENAME];
751 
752  BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
753 
754  if (!STREQ(name_flip, name)) {
755  return BKE_pose_channel_find_name(pose, name_flip);
756  }
757 
758  return NULL;
759 }
760 
762 {
763  if (pose) {
764  switch (pose->iksolver) {
765  case IKSOLVER_STANDARD:
766  return NULL;
767  case IKSOLVER_ITASC:
768  return "bItasc";
769  }
770  }
771  return NULL;
772 }
773 
775  const bPose *src,
776  const int flag,
777  const bool copy_constraints)
778 {
779  bPose *outPose;
780  bPoseChannel *pchan;
781  ListBase listb;
782 
783  if (!src) {
784  *dst = NULL;
785  return;
786  }
787 
788  outPose = MEM_callocN(sizeof(bPose), "pose");
789 
790  BLI_duplicatelist(&outPose->chanbase, &src->chanbase);
791 
792  /* Rebuild ghash here too, so that name lookups below won't be too bad...
793  * BUT this will have the penalty that the ghash will be built twice
794  * if BKE_pose_rebuild() gets called after this...
795  */
796  if (outPose->chanbase.first != outPose->chanbase.last) {
797  outPose->chanhash = NULL;
799  }
800 
801  outPose->iksolver = src->iksolver;
802  outPose->ikdata = NULL;
803  outPose->ikparam = MEM_dupallocN(src->ikparam);
804  outPose->avs = src->avs;
805 
806  for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) {
807  if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
808  id_us_plus((ID *)pchan->custom);
809  }
810 
811  if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
813  }
814 
815  /* warning, O(n2) here, if done without the hash, but these are rarely used features. */
816  if (pchan->custom_tx) {
817  pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name);
818  }
819  if (pchan->bbone_prev) {
820  pchan->bbone_prev = BKE_pose_channel_find_name(outPose, pchan->bbone_prev->name);
821  }
822  if (pchan->bbone_next) {
823  pchan->bbone_next = BKE_pose_channel_find_name(outPose, pchan->bbone_next->name);
824  }
825 
826  if (copy_constraints) {
827  /* #BKE_constraints_copy NULL's `listb` */
828  BKE_constraints_copy_ex(&listb, &pchan->constraints, flag, true);
829 
830  pchan->constraints = listb;
831 
832  /* XXX: This is needed for motionpath drawing to work.
833  * Dunno why it was setting to null before... */
834  pchan->mpath = animviz_copy_motionpath(pchan->mpath);
835  }
836 
837  if (pchan->prop) {
838  pchan->prop = IDP_CopyProperty_ex(pchan->prop, flag);
839  }
840 
841  pchan->draw_data = NULL; /* Drawing cache, no need to copy. */
842 
843  /* Runtime data, no need to copy. */
845  }
846 
847  /* for now, duplicate Bone Groups too when doing this */
848  if (copy_constraints) {
849  BLI_duplicatelist(&outPose->agroups, &src->agroups);
850  }
851 
852  *dst = outPose;
853 }
854 
855 void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constraints)
856 {
857  BKE_pose_copy_data_ex(dst, src, 0, copy_constraints);
858 }
859 
861 {
862  if (itasc) {
863  itasc->iksolver = IKSOLVER_ITASC;
864  itasc->minstep = 0.01f;
865  itasc->maxstep = 0.06f;
866  itasc->numiter = 100;
867  itasc->numstep = 4;
868  itasc->precision = 0.005f;
870  itasc->feedback = 20.0f;
871  itasc->maxvel = 50.0f;
872  itasc->solver = ITASC_SOLVER_SDLS;
873  itasc->dampmax = 0.5;
874  itasc->dampeps = 0.15;
875  }
876 }
878 {
879  bItasc *itasc;
880  switch (pose->iksolver) {
881  case IKSOLVER_ITASC:
882  itasc = MEM_callocN(sizeof(bItasc), "itasc");
883  BKE_pose_itasc_init(itasc);
884  pose->ikparam = itasc;
885  break;
886  case IKSOLVER_STANDARD:
887  default:
888  pose->ikparam = NULL;
889  break;
890  }
891 }
892 
893 /* only for real IK, not for auto-IK */
894 static bool pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
895 {
896  bConstraint *con;
897  Bone *bone;
898 
899  /* No need to check if constraint is active (has influence),
900  * since all constraints with CONSTRAINT_IK_AUTO are active */
901  for (con = pchan->constraints.first; con; con = con->next) {
902  if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
904  if ((data->rootbone == 0) || (data->rootbone > level)) {
905  if ((data->flag & CONSTRAINT_IK_AUTO) == 0) {
906  return true;
907  }
908  }
909  }
910  }
911  for (bone = pchan->bone->childbase.first; bone; bone = bone->next) {
912  pchan = BKE_pose_channel_find_name(ob->pose, bone->name);
913  if (pchan && pose_channel_in_IK_chain(ob, pchan, level + 1)) {
914  return true;
915  }
916  }
917  return false;
918 }
919 
921 {
922  return pose_channel_in_IK_chain(ob, pchan, 0);
923 }
924 
926 {
927  if (!pose->chanhash) {
928  bPoseChannel *pchan;
929 
930  pose->chanhash = BLI_ghash_str_new("make_pose_chan gh");
931  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
932  BLI_ghash_insert(pose->chanhash, pchan->name, pchan);
933  }
934  }
935 }
936 
938 {
939  if (pose->chanhash) {
940  BLI_ghash_free(pose->chanhash, NULL, NULL);
941  pose->chanhash = NULL;
942  }
943 }
944 
945 static void pose_channels_remove_internal_links(Object *ob, bPoseChannel *unlinked_pchan)
946 {
947  LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
948  if (pchan->bbone_prev == unlinked_pchan) {
949  pchan->bbone_prev = NULL;
950  }
951  if (pchan->bbone_next == unlinked_pchan) {
952  pchan->bbone_next = NULL;
953  }
954  if (pchan->custom_tx == unlinked_pchan) {
955  pchan->custom_tx = NULL;
956  }
957  }
958 }
959 
961  bool (*filter_fn)(const char *bone_name, void *user_data),
962  void *user_data)
963 {
964  /* Erase any associated pose channel, along with any references to them */
965  if (ob->pose) {
966  bPoseChannel *pchan, *pchan_next;
967  bConstraint *con;
968 
969  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan_next) {
970  pchan_next = pchan->next;
971 
972  if (filter_fn(pchan->name, user_data)) {
973  /* Bone itself is being removed */
974  BKE_pose_channel_free(pchan);
976  if (ob->pose->chanhash) {
977  BLI_ghash_remove(ob->pose->chanhash, pchan->name, NULL, NULL);
978  }
979  BLI_freelinkN(&ob->pose->chanbase, pchan);
980  }
981  else {
982  /* Maybe something the bone references is being removed instead? */
983  for (con = pchan->constraints.first; con; con = con->next) {
984  ListBase targets = {NULL, NULL};
985  bConstraintTarget *ct;
986 
987  if (BKE_constraint_targets_get(con, &targets)) {
988  for (ct = targets.first; ct; ct = ct->next) {
989  if (ct->tar == ob) {
990  if (ct->subtarget[0]) {
991  if (filter_fn(ct->subtarget, user_data)) {
992  con->flag |= CONSTRAINT_DISABLE;
993  ct->subtarget[0] = 0;
994  }
995  }
996  }
997  }
998 
999  BKE_constraint_targets_flush(con, &targets, 0);
1000  }
1001  }
1002 
1003  if (pchan->bbone_prev) {
1004  if (filter_fn(pchan->bbone_prev->name, user_data)) {
1005  pchan->bbone_prev = NULL;
1006  }
1007  }
1008  if (pchan->bbone_next) {
1009  if (filter_fn(pchan->bbone_next->name, user_data)) {
1010  pchan->bbone_next = NULL;
1011  }
1012  }
1013 
1014  if (pchan->custom_tx) {
1015  if (filter_fn(pchan->custom_tx->name, user_data)) {
1016  pchan->custom_tx = NULL;
1017  }
1018  }
1019  }
1020  }
1021  }
1022 }
1023 
1024 void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
1025 {
1026  if (pchan->custom) {
1027  if (do_id_user) {
1028  id_us_min(&pchan->custom->id);
1029  }
1030  pchan->custom = NULL;
1031  }
1032 
1033  if (pchan->mpath) {
1035  pchan->mpath = NULL;
1036  }
1037 
1038  BKE_constraints_free_ex(&pchan->constraints, do_id_user);
1039 
1040  if (pchan->prop) {
1041  IDP_FreeProperty_ex(pchan->prop, do_id_user);
1042  pchan->prop = NULL;
1043  }
1044 
1045  /* Cached data, for new draw manager rendering code. */
1046  MEM_SAFE_FREE(pchan->draw_data);
1047 
1048  /* Cached B-Bone shape and other data. */
1050 }
1051 
1053 {
1054  memset(runtime, 0, sizeof(*runtime));
1055 }
1056 
1058 {
1059  const SessionUUID uuid = runtime->session_uuid;
1060  memset(runtime, 0, sizeof(*runtime));
1061  runtime->session_uuid = uuid;
1062 }
1063 
1065 {
1067 }
1068 
1070 {
1071  runtime->bbone_segments = 0;
1072  MEM_SAFE_FREE(runtime->bbone_rest_mats);
1073  MEM_SAFE_FREE(runtime->bbone_pose_mats);
1074  MEM_SAFE_FREE(runtime->bbone_deform_mats);
1075  MEM_SAFE_FREE(runtime->bbone_dual_quats);
1076 }
1077 
1079 {
1080  BKE_pose_channel_free_ex(pchan, true);
1081 }
1082 
1083 void BKE_pose_channels_free_ex(bPose *pose, bool do_id_user)
1084 {
1085  bPoseChannel *pchan;
1086 
1087  if (pose->chanbase.first) {
1088  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
1089  BKE_pose_channel_free_ex(pchan, do_id_user);
1090  }
1091 
1092  BLI_freelistN(&pose->chanbase);
1093  }
1094 
1096 
1097  MEM_SAFE_FREE(pose->chan_array);
1098 }
1099 
1101 {
1102  BKE_pose_channels_free_ex(pose, true);
1103 }
1104 
1105 void BKE_pose_free_data_ex(bPose *pose, bool do_id_user)
1106 {
1107  /* free pose-channels */
1108  BKE_pose_channels_free_ex(pose, do_id_user);
1109 
1110  /* free pose-groups */
1111  if (pose->agroups.first) {
1112  BLI_freelistN(&pose->agroups);
1113  }
1114 
1115  /* free IK solver state */
1116  BIK_clear_data(pose);
1117 
1118  /* free IK solver param */
1119  if (pose->ikparam) {
1120  MEM_freeN(pose->ikparam);
1121  }
1122 }
1123 
1125 {
1126  BKE_pose_free_data_ex(pose, true);
1127 }
1128 
1129 void BKE_pose_free_ex(bPose *pose, bool do_id_user)
1130 {
1131  if (pose) {
1132  BKE_pose_free_data_ex(pose, do_id_user);
1133  /* free pose */
1134  MEM_freeN(pose);
1135  }
1136 }
1137 
1139 {
1140  BKE_pose_free_ex(pose, true);
1141 }
1142 
1144 {
1145  /* copy transform locks */
1146  pchan->protectflag = pchan_from->protectflag;
1147 
1148  /* copy rotation mode */
1149  pchan->rotmode = pchan_from->rotmode;
1150 
1151  /* copy bone group */
1152  pchan->agrp_index = pchan_from->agrp_index;
1153 
1154  /* IK (DOF) settings. */
1155  pchan->ikflag = pchan_from->ikflag;
1156  copy_v3_v3(pchan->limitmin, pchan_from->limitmin);
1157  copy_v3_v3(pchan->limitmax, pchan_from->limitmax);
1158  copy_v3_v3(pchan->stiffness, pchan_from->stiffness);
1159  pchan->ikstretch = pchan_from->ikstretch;
1160  pchan->ikrotweight = pchan_from->ikrotweight;
1161  pchan->iklinweight = pchan_from->iklinweight;
1162 
1163  /* bbone settings (typically not animated) */
1164  pchan->bbone_next = pchan_from->bbone_next;
1165  pchan->bbone_prev = pchan_from->bbone_prev;
1166 
1167  /* constraints */
1168  BKE_constraints_copy(&pchan->constraints, &pchan_from->constraints, true);
1169 
1170  /* id-properties */
1171  if (pchan->prop) {
1172  /* unlikely but possible it exists */
1173  IDP_FreeProperty(pchan->prop);
1174  pchan->prop = NULL;
1175  }
1176  if (pchan_from->prop) {
1177  pchan->prop = IDP_CopyProperty(pchan_from->prop);
1178  }
1179 
1180  /* custom shape */
1181  pchan->custom = pchan_from->custom;
1182  if (pchan->custom) {
1183  id_us_plus(&pchan->custom->id);
1184  }
1185  copy_v3_v3(pchan->custom_scale_xyz, pchan_from->custom_scale_xyz);
1186  copy_v3_v3(pchan->custom_translation, pchan_from->custom_translation);
1188 
1189  pchan->drawflag = pchan_from->drawflag;
1190 }
1191 
1193 {
1194  bPoseChannel *pchan, *parchan;
1195  bConstraint *con;
1196 
1197  /* clear */
1198  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
1199  pchan->constflag = 0;
1200  }
1202 
1203  /* detect */
1204  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
1205  for (con = pchan->constraints.first; con; con = con->next) {
1206  if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
1208 
1209  pchan->constflag |= PCHAN_HAS_IK;
1210 
1211  if (data->tar == NULL || (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0)) {
1212  pchan->constflag |= PCHAN_HAS_TARGET;
1213  }
1214 
1215  /* negative rootbone = recalc rootbone index. used in do_versions */
1216  if (data->rootbone < 0) {
1217  data->rootbone = 0;
1218 
1219  if (data->flag & CONSTRAINT_IK_TIP) {
1220  parchan = pchan;
1221  }
1222  else {
1223  parchan = pchan->parent;
1224  }
1225 
1226  while (parchan) {
1227  data->rootbone++;
1228  if ((parchan->bone->flag & BONE_CONNECTED) == 0) {
1229  break;
1230  }
1231  parchan = parchan->parent;
1232  }
1233  }
1234  }
1235  else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
1237 
1238  /* for drawing constraint colors when color set allows this */
1239  pchan->constflag |= PCHAN_HAS_CONST;
1240 
1241  /* if we have a valid target, make sure that this will get updated on frame-change
1242  * (needed for when there is no anim-data for this pose)
1243  */
1244  if ((data->tar) && (data->tar->type == OB_CURVES_LEGACY)) {
1246  }
1247  }
1248  else if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
1249  pchan->constflag |= PCHAN_HAS_SPLINEIK;
1250  }
1251  else {
1252  pchan->constflag |= PCHAN_HAS_CONST;
1253  }
1254  }
1255  }
1257 }
1258 
1260 {
1262 }
1263 
1264 /* ************************** Bone Groups ************************** */
1265 
1266 bActionGroup *BKE_pose_add_group(bPose *pose, const char *name)
1267 {
1268  bActionGroup *grp;
1269 
1270  if (!name) {
1271  name = DATA_("Group");
1272  }
1273 
1274  grp = MEM_callocN(sizeof(bActionGroup), "PoseGroup");
1275  BLI_strncpy(grp->name, name, sizeof(grp->name));
1276  BLI_addtail(&pose->agroups, grp);
1277  BLI_uniquename(&pose->agroups, grp, name, '.', offsetof(bActionGroup, name), sizeof(grp->name));
1278 
1279  pose->active_group = BLI_listbase_count(&pose->agroups);
1280 
1281  return grp;
1282 }
1283 
1284 void BKE_pose_remove_group(bPose *pose, bActionGroup *grp, const int index)
1285 {
1286  bPoseChannel *pchan;
1287  int idx = index;
1288 
1289  if (idx < 1) {
1290  idx = BLI_findindex(&pose->agroups, grp) + 1;
1291  }
1292 
1293  BLI_assert(idx > 0);
1294 
1295  /* adjust group references (the trouble of using indices!):
1296  * - firstly, make sure nothing references it
1297  * - also, make sure that those after this item get corrected
1298  */
1299  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
1300  if (pchan->agrp_index == idx) {
1301  pchan->agrp_index = 0;
1302  }
1303  else if (pchan->agrp_index > idx) {
1304  pchan->agrp_index--;
1305  }
1306  }
1307 
1308  /* now, remove it from the pose */
1309  BLI_freelinkN(&pose->agroups, grp);
1310  if (pose->active_group >= idx) {
1311  const bool has_groups = !BLI_listbase_is_empty(&pose->agroups);
1312  pose->active_group--;
1313  if (pose->active_group == 0 && has_groups) {
1314  pose->active_group = 1;
1315  }
1316  else if (pose->active_group < 0 || !has_groups) {
1317  pose->active_group = 0;
1318  }
1319  }
1320 }
1321 
1322 void BKE_pose_remove_group_index(bPose *pose, const int index)
1323 {
1324  bActionGroup *grp = NULL;
1325 
1326  /* get group to remove */
1327  grp = BLI_findlink(&pose->agroups, index - 1);
1328  if (grp) {
1329  BKE_pose_remove_group(pose, grp, index);
1330  }
1331 }
1332 
1333 /* ************** F-Curve Utilities for Actions ****************** */
1334 
1335 bool action_has_motion(const bAction *act)
1336 {
1337  FCurve *fcu;
1338 
1339  /* return on the first F-Curve that has some keyframes/samples defined */
1340  if (act) {
1341  for (fcu = act->curves.first; fcu; fcu = fcu->next) {
1342  if (fcu->totvert) {
1343  return true;
1344  }
1345  }
1346  }
1347 
1348  /* nothing found */
1349  return false;
1350 }
1351 
1352 bool BKE_action_has_single_frame(const struct bAction *act)
1353 {
1354  if (act == NULL || BLI_listbase_is_empty(&act->curves)) {
1355  return false;
1356  }
1357 
1358  bool found_key = false;
1359  float found_key_frame = 0.0f;
1360 
1361  LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
1362  switch (fcu->totvert) {
1363  case 0:
1364  /* No keys, so impossible to come to a conclusion on this curve alone. */
1365  continue;
1366  case 1:
1367  /* Single key, which is the complex case, so handle below. */
1368  break;
1369  default:
1370  /* Multiple keys, so there is animation. */
1371  return false;
1372  }
1373 
1374  const float this_key_frame = fcu->bezt != NULL ? fcu->bezt[0].vec[1][0] : fcu->fpt[0].vec[0];
1375  if (!found_key) {
1376  found_key = true;
1377  found_key_frame = this_key_frame;
1378  continue;
1379  }
1380 
1381  /* The graph editor rounds to 1/1000th of a frame, so it's not necessary to be really precise
1382  * with these comparisons. */
1383  if (!compare_ff(found_key_frame, this_key_frame, 0.001f)) {
1384  /* This key differs from the already-found key, so this Action represents animation. */
1385  return false;
1386  }
1387  }
1388 
1389  /* There is only a single frame if we found at least one key. */
1390  return found_key;
1391 }
1392 
1393 void calc_action_range(const bAction *act, float *start, float *end, short incl_modifiers)
1394 {
1395  FCurve *fcu;
1396  float min = 999999999.0f, max = -999999999.0f;
1397  short foundvert = 0, foundmod = 0;
1398 
1399  if (act) {
1400  for (fcu = act->curves.first; fcu; fcu = fcu->next) {
1401  /* if curve has keyframes, consider them first */
1402  if (fcu->totvert) {
1403  float nmin, nmax;
1404 
1405  /* get extents for this curve
1406  * - no "selected only", since this is often used in the backend
1407  * - no "minimum length" (we will apply this later), otherwise
1408  * single-keyframe curves will increase the overall length by
1409  * a phantom frame (T50354)
1410  */
1411  BKE_fcurve_calc_range(fcu, &nmin, &nmax, false, false);
1412 
1413  /* compare to the running tally */
1414  min = min_ff(min, nmin);
1415  max = max_ff(max, nmax);
1416 
1417  foundvert = 1;
1418  }
1419 
1420  /* if incl_modifiers is enabled, need to consider modifiers too
1421  * - only really care about the last modifier
1422  */
1423  if ((incl_modifiers) && (fcu->modifiers.last)) {
1424  FModifier *fcm = fcu->modifiers.last;
1425 
1426  /* only use the maximum sensible limits of the modifiers if they are more extreme */
1427  switch (fcm->type) {
1428  case FMODIFIER_TYPE_LIMITS: /* Limits F-Modifier */
1429  {
1430  FMod_Limits *fmd = (FMod_Limits *)fcm->data;
1431 
1432  if (fmd->flag & FCM_LIMIT_XMIN) {
1433  min = min_ff(min, fmd->rect.xmin);
1434  }
1435  if (fmd->flag & FCM_LIMIT_XMAX) {
1436  max = max_ff(max, fmd->rect.xmax);
1437  }
1438  break;
1439  }
1440  case FMODIFIER_TYPE_CYCLES: /* Cycles F-Modifier */
1441  {
1442  FMod_Cycles *fmd = (FMod_Cycles *)fcm->data;
1443 
1444  if (fmd->before_mode != FCM_EXTRAPOLATE_NONE) {
1445  min = MINAFRAMEF;
1446  }
1447  if (fmd->after_mode != FCM_EXTRAPOLATE_NONE) {
1448  max = MAXFRAMEF;
1449  }
1450  break;
1451  }
1452  /* TODO: function modifier may need some special limits */
1453 
1454  default: /* all other standard modifiers are on the infinite range... */
1455  min = MINAFRAMEF;
1456  max = MAXFRAMEF;
1457  break;
1458  }
1459 
1460  foundmod = 1;
1461  }
1462  }
1463  }
1464 
1465  if (foundvert || foundmod) {
1466  /* ensure that action is at least 1 frame long (for NLA strips to have a valid length) */
1467  if (min == max) {
1468  max += 1.0f;
1469  }
1470 
1471  *start = min;
1472  *end = max;
1473  }
1474  else {
1475  *start = 0.0f;
1476  *end = 1.0f;
1477  }
1478 }
1479 
1480 void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end)
1481 {
1482  if (act && (act->flag & ACT_FRAME_RANGE)) {
1483  *r_start = act->frame_start;
1484  *r_end = act->frame_end;
1485  }
1486  else {
1487  calc_action_range(act, r_start, r_end, false);
1488  }
1489 
1490  /* Ensure that action is at least 1 frame long (for NLA strips to have a valid length). */
1491  if (*r_start >= *r_end) {
1492  *r_end = *r_start + 1.0f;
1493  }
1494 }
1495 
1496 bool BKE_action_is_cyclic(const struct bAction *act)
1497 {
1498  return act && (act->flag & ACT_FRAME_RANGE) && (act->flag & ACT_CYCLIC);
1499 }
1500 
1502 {
1503  PointerRNA ptr;
1504  FCurve *fcu;
1505  char *basePath = NULL;
1506  short flags = 0;
1507 
1508  /* build PointerRNA from provided data to obtain the paths to use */
1509  if (pchan) {
1510  RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
1511  }
1512  else if (ob) {
1513  RNA_id_pointer_create((ID *)ob, &ptr);
1514  }
1515  else {
1516  return 0;
1517  }
1518 
1519  /* get the basic path to the properties of interest */
1520  basePath = RNA_path_from_ID_to_struct(&ptr);
1521  if (basePath == NULL) {
1522  return 0;
1523  }
1524 
1525  /* search F-Curves for the given properties
1526  * - we cannot use the groups, since they may not be grouped in that way...
1527  */
1528  for (fcu = act->curves.first; fcu; fcu = fcu->next) {
1529  const char *bPtr = NULL, *pPtr = NULL;
1530 
1531  /* If enough flags have been found,
1532  * we can stop checking unless we're also getting the curves. */
1533  if ((flags == ACT_TRANS_ALL) && (curves == NULL)) {
1534  break;
1535  }
1536 
1537  /* just in case... */
1538  if (fcu->rna_path == NULL) {
1539  continue;
1540  }
1541 
1542  /* step 1: check for matching base path */
1543  bPtr = strstr(fcu->rna_path, basePath);
1544 
1545  if (bPtr) {
1546  /* we must add len(basePath) bytes to the match so that we are at the end of the
1547  * base path so that we don't get false positives with these strings in the names
1548  */
1549  bPtr += strlen(basePath);
1550 
1551  /* step 2: check for some property with transforms
1552  * - to speed things up, only check for the ones not yet found
1553  * unless we're getting the curves too
1554  * - if we're getting the curves, the BLI_genericNodeN() creates a LinkData
1555  * node wrapping the F-Curve, which then gets added to the list
1556  * - once a match has been found, the curve cannot possibly be any other one
1557  */
1558  if ((curves) || (flags & ACT_TRANS_LOC) == 0) {
1559  pPtr = strstr(bPtr, "location");
1560  if (pPtr) {
1561  flags |= ACT_TRANS_LOC;
1562 
1563  if (curves) {
1565  }
1566  continue;
1567  }
1568  }
1569 
1570  if ((curves) || (flags & ACT_TRANS_SCALE) == 0) {
1571  pPtr = strstr(bPtr, "scale");
1572  if (pPtr) {
1573  flags |= ACT_TRANS_SCALE;
1574 
1575  if (curves) {
1577  }
1578  continue;
1579  }
1580  }
1581 
1582  if ((curves) || (flags & ACT_TRANS_ROT) == 0) {
1583  pPtr = strstr(bPtr, "rotation");
1584  if (pPtr) {
1585  flags |= ACT_TRANS_ROT;
1586 
1587  if (curves) {
1589  }
1590  continue;
1591  }
1592  }
1593 
1594  if ((curves) || (flags & ACT_TRANS_BBONE) == 0) {
1595  /* bbone shape properties */
1596  pPtr = strstr(bPtr, "bbone_");
1597  if (pPtr) {
1598  flags |= ACT_TRANS_BBONE;
1599 
1600  if (curves) {
1602  }
1603  continue;
1604  }
1605  }
1606 
1607  if ((curves) || (flags & ACT_TRANS_PROP) == 0) {
1608  /* custom properties only */
1609  pPtr = strstr(bPtr, "[\"");
1610  if (pPtr) {
1611  flags |= ACT_TRANS_PROP;
1612 
1613  if (curves) {
1615  }
1616  continue;
1617  }
1618  }
1619  }
1620  }
1621 
1622  /* free basePath */
1623  MEM_freeN(basePath);
1624 
1625  /* return flags found */
1626  return flags;
1627 }
1628 
1629 /* ************** Pose Management Tools ****************** */
1630 
1631 void BKE_pose_rest(bPose *pose, bool selected_bones_only)
1632 {
1633  bPoseChannel *pchan;
1634 
1635  if (!pose) {
1636  return;
1637  }
1638 
1639  memset(pose->stride_offset, 0, sizeof(pose->stride_offset));
1640  memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset));
1641 
1642  for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
1643  if (selected_bones_only && pchan->bone != NULL && (pchan->bone->flag & BONE_SELECTED) == 0) {
1644  continue;
1645  }
1646  zero_v3(pchan->loc);
1647  zero_v3(pchan->eul);
1648  unit_qt(pchan->quat);
1649  unit_axis_angle(pchan->rotAxis, &pchan->rotAngle);
1650  pchan->size[0] = pchan->size[1] = pchan->size[2] = 1.0f;
1651 
1652  pchan->roll1 = pchan->roll2 = 0.0f;
1653  pchan->curve_in_x = pchan->curve_in_z = 0.0f;
1654  pchan->curve_out_x = pchan->curve_out_z = 0.0f;
1655  pchan->ease1 = pchan->ease2 = 0.0f;
1656 
1657  copy_v3_fl(pchan->scale_in, 1.0f);
1658  copy_v3_fl(pchan->scale_out, 1.0f);
1659 
1660  pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
1661  }
1662 }
1663 
1664 void BKE_pose_copy_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
1665 {
1666  copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat);
1667  copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat);
1668 
1669  /* used for local constraints */
1670  copy_v3_v3(pchanto->loc, pchanfrom->loc);
1671  copy_qt_qt(pchanto->quat, pchanfrom->quat);
1672  copy_v3_v3(pchanto->eul, pchanfrom->eul);
1673  copy_v3_v3(pchanto->size, pchanfrom->size);
1674 
1675  copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head);
1676  copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail);
1677 
1678  pchanto->roll1 = pchanfrom->roll1;
1679  pchanto->roll2 = pchanfrom->roll2;
1680  pchanto->curve_in_x = pchanfrom->curve_in_x;
1681  pchanto->curve_in_z = pchanfrom->curve_in_z;
1682  pchanto->curve_out_x = pchanfrom->curve_out_x;
1683  pchanto->curve_out_z = pchanfrom->curve_out_z;
1684  pchanto->ease1 = pchanfrom->ease1;
1685  pchanto->ease2 = pchanfrom->ease2;
1686 
1687  copy_v3_v3(pchanto->scale_in, pchanfrom->scale_in);
1688  copy_v3_v3(pchanto->scale_out, pchanfrom->scale_out);
1689 
1690  pchanto->rotmode = pchanfrom->rotmode;
1691  pchanto->flag = pchanfrom->flag;
1692  pchanto->protectflag = pchanfrom->protectflag;
1693 }
1694 
1696 {
1697  bPoseChannel *pchanto, *pchanfrom;
1698 
1699  if (to == NULL || from == NULL) {
1700  CLOG_ERROR(
1701  &LOG, "Pose copy error, pose to:%p from:%p", (void *)to, (void *)from); /* debug temp */
1702  return false;
1703  }
1704 
1705  if (to == from) {
1706  CLOG_ERROR(&LOG, "source and target are the same");
1707  return false;
1708  }
1709 
1710  for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) {
1711  pchanto = BKE_pose_channel_find_name(to, pchanfrom->name);
1712  if (pchanto != NULL) {
1713  BKE_pose_copy_pchan_result(pchanto, pchanfrom);
1714  }
1715  }
1716  return true;
1717 }
1718 
1719 void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
1720 {
1721  pose->flag |= POSE_RECALC;
1722  /* Depsgraph components depends on actual pose state,
1723  * if pose was changed depsgraph is to be updated as well.
1724  */
1725  DEG_relations_tag_update(bmain);
1726 }
1727 
1729  Object *workob,
1730  bPose *pose,
1731  bAction *act,
1732  char groupname[],
1733  const AnimationEvalContext *anim_eval_context)
1734 {
1735  bActionGroup *agrp = BKE_action_group_find_name(act, groupname);
1736 
1737  /* clear workob */
1738  BKE_object_workob_clear(workob);
1739 
1740  /* init workob */
1741  copy_m4_m4(workob->obmat, ob->obmat);
1742  copy_m4_m4(workob->parentinv, ob->parentinv);
1743  copy_m4_m4(workob->constinv, ob->constinv);
1744  workob->parent = ob->parent;
1745 
1746  workob->rotmode = ob->rotmode;
1747 
1748  workob->trackflag = ob->trackflag;
1749  workob->upflag = ob->upflag;
1750 
1751  workob->partype = ob->partype;
1752  workob->par1 = ob->par1;
1753  workob->par2 = ob->par2;
1754  workob->par3 = ob->par3;
1755 
1756  workob->constraints.first = ob->constraints.first;
1757  workob->constraints.last = ob->constraints.last;
1758 
1759  /* Need to set pose too, since this is used for both types of Action Constraint. */
1760  workob->pose = pose;
1761  if (pose) {
1762  /* This function is most likely to be used with a temporary pose with a single bone in there.
1763  * For such cases it makes no sense to create hash since it'll only waste CPU ticks on memory
1764  * allocation and also will make lookup slower.
1765  */
1766  if (pose->chanbase.first != pose->chanbase.last) {
1768  }
1771  }
1772  }
1773 
1774  BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
1775 
1776  /* we don't use real object name, otherwise RNA screws with the real thing */
1777  BLI_strncpy(workob->id.name, "OB<ConstrWorkOb>", sizeof(workob->id.name));
1778 
1779  /* If we're given a group to use, it's likely to be more efficient
1780  * (though a bit more dangerous). */
1781  if (agrp) {
1782  /* specifically evaluate this group only */
1783  PointerRNA id_ptr;
1784 
1785  /* get RNA-pointer for the workob's ID */
1786  RNA_id_pointer_create(&workob->id, &id_ptr);
1787 
1788  /* execute action for this group only */
1789  animsys_evaluate_action_group(&id_ptr, act, agrp, anim_eval_context);
1790  }
1791  else {
1792  AnimData adt = {NULL};
1793 
1794  /* init animdata, and attach to workob */
1795  workob->adt = &adt;
1796 
1797  adt.action = act;
1798  BKE_animdata_action_ensure_idroot(&workob->id, act);
1799 
1800  /* execute effects of Action on to workob (or its PoseChannels) */
1801  BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false);
1802  }
1803 }
1804 
1806 {
1807  if (pose == NULL) {
1808  return;
1809  }
1810 
1811  struct GSet *used_uuids = BLI_gset_new(
1813 
1814  LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
1815  const SessionUUID *session_uuid = &pchan->runtime.session_uuid;
1816  if (!BLI_session_uuid_is_generated(session_uuid)) {
1817  printf("Pose channel %s does not have UUID generated.\n", pchan->name);
1818  continue;
1819  }
1820 
1821  if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) {
1822  printf("Pose channel %s has duplicate UUID generated.\n", pchan->name);
1823  continue;
1824  }
1825 
1826  BLI_gset_insert(used_uuids, (void *)session_uuid);
1827  }
1828 
1829  BLI_gset_free(used_uuids, NULL);
1830 }
1831 
1833 {
1834  /* Write each channel */
1835  if (pose == NULL) {
1836  return;
1837  }
1838 
1839  BLI_assert(arm != NULL);
1840 
1841  /* Write channels */
1842  LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) {
1843  /* Write ID Properties -- and copy this comment EXACTLY for easy finding
1844  * of library blocks that implement this. */
1845  if (chan->prop) {
1846  IDP_BlendWrite(writer, chan->prop);
1847  }
1848 
1849  BKE_constraint_blend_write(writer, &chan->constraints);
1850 
1851  animviz_motionpath_blend_write(writer, chan->mpath);
1852 
1853  /* Prevent crashes with autosave,
1854  * when a bone duplicated in edit-mode has not yet been assigned to its pose-channel.
1855  * Also needed with memundo, in some cases we can store a step before pose has been
1856  * properly rebuilt from previous undo step. */
1857  Bone *bone = (pose->flag & POSE_RECALC) ? BKE_armature_find_bone_name(arm, chan->name) :
1858  chan->bone;
1859  if (bone != NULL) {
1860  /* gets restored on read, for library armatures */
1861  chan->selectflag = bone->flag & BONE_SELECTED;
1862  }
1863 
1864  BLO_write_struct(writer, bPoseChannel, chan);
1865  }
1866 
1867  /* Write groups */
1868  LISTBASE_FOREACH (bActionGroup *, grp, &pose->agroups) {
1869  BLO_write_struct(writer, bActionGroup, grp);
1870  }
1871 
1872  /* write IK param */
1873  if (pose->ikparam) {
1874  const char *structname = BKE_pose_ikparam_get_name(pose);
1875  if (structname) {
1876  BLO_write_struct_by_name(writer, structname, pose->ikparam);
1877  }
1878  }
1879 
1880  /* Write this pose */
1881  BLO_write_struct(writer, bPose, pose);
1882 }
1883 
1885 {
1886  if (!pose) {
1887  return;
1888  }
1889 
1890  BLO_read_list(reader, &pose->chanbase);
1891  BLO_read_list(reader, &pose->agroups);
1892 
1893  pose->chanhash = NULL;
1894  pose->chan_array = NULL;
1895 
1896  LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
1897  BKE_pose_channel_runtime_reset(&pchan->runtime);
1899 
1900  pchan->bone = NULL;
1901  BLO_read_data_address(reader, &pchan->parent);
1902  BLO_read_data_address(reader, &pchan->child);
1903  BLO_read_data_address(reader, &pchan->custom_tx);
1904 
1905  BLO_read_data_address(reader, &pchan->bbone_prev);
1906  BLO_read_data_address(reader, &pchan->bbone_next);
1907 
1908  BKE_constraint_blend_read_data(reader, &pchan->constraints);
1909 
1910  BLO_read_data_address(reader, &pchan->prop);
1911  IDP_BlendDataRead(reader, &pchan->prop);
1912 
1913  BLO_read_data_address(reader, &pchan->mpath);
1914  if (pchan->mpath) {
1915  animviz_motionpath_blend_read_data(reader, pchan->mpath);
1916  }
1917 
1918  BLI_listbase_clear(&pchan->iktree);
1919  BLI_listbase_clear(&pchan->siktree);
1920 
1921  /* in case this value changes in future, clamp else we get undefined behavior */
1922  CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
1923 
1924  pchan->draw_data = NULL;
1925  }
1926  pose->ikdata = NULL;
1927  if (pose->ikparam != NULL) {
1928  BLO_read_data_address(reader, &pose->ikparam);
1929  }
1930 }
1931 
1933 {
1934  bArmature *arm = ob->data;
1935 
1936  if (!pose || !arm) {
1937  return;
1938  }
1939 
1940  /* Always rebuild to match library changes, except on Undo. */
1941  bool rebuild = false;
1942 
1943  if (!BLO_read_lib_is_undo(reader)) {
1944  if (ob->id.lib != arm->id.lib) {
1945  rebuild = true;
1946  }
1947  }
1948 
1949  LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
1950  BKE_constraint_blend_read_lib(reader, (ID *)ob, &pchan->constraints);
1951 
1952  pchan->bone = BKE_armature_find_bone_name(arm, pchan->name);
1953 
1954  IDP_BlendReadLib(reader, ob->id.lib, pchan->prop);
1955 
1956  BLO_read_id_address(reader, ob->id.lib, &pchan->custom);
1957  if (UNLIKELY(pchan->bone == NULL)) {
1958  rebuild = true;
1959  }
1960  else if (!ID_IS_LINKED(ob) && ID_IS_LINKED(arm)) {
1961  /* local pose selection copied to armature, bit hackish */
1962  pchan->bone->flag &= ~BONE_SELECTED;
1963  pchan->bone->flag |= pchan->selectflag;
1964  }
1965  }
1966 
1967  if (rebuild) {
1968  Main *bmain = BLO_read_lib_get_main(reader);
1971  BKE_pose_tag_recalc(bmain, pose);
1972  }
1973 }
1974 
1976 {
1977  if (!pose) {
1978  return;
1979  }
1980 
1981  LISTBASE_FOREACH (bPoseChannel *, chan, &pose->chanbase) {
1982  BKE_constraint_blend_read_expand(expander, &chan->constraints);
1983  IDP_BlendReadExpand(expander, chan->prop);
1984  BLO_expand(expander, chan->custom);
1985  }
1986 }
1987 
1989 {
1990  if (!act) {
1991  return;
1992  }
1993  while (act->curves.first) {
1994  FCurve *fcu = act->curves.first;
1995  action_groups_remove_channel(act, fcu);
1996  BKE_fcurve_free(fcu);
1997  }
1999 }
void BIK_clear_data(struct bPose *pose)
Definition: ikplugin_api.c:94
Blender kernel action and pose functionality.
@ ACT_TRANS_ALL
Definition: BKE_action.h:63
@ ACT_TRANS_PROP
Definition: BKE_action.h:59
@ ACT_TRANS_SCALE
Definition: BKE_action.h:51
@ ACT_TRANS_BBONE
Definition: BKE_action.h:54
@ ACT_TRANS_ROT
Definition: BKE_action.h:49
@ ACT_TRANS_LOC
Definition: BKE_action.h:47
bool BKE_animdata_action_ensure_idroot(const struct ID *owner, struct bAction *action)
void animviz_free_motionpath(struct bMotionPath *mpath)
struct bMotionPath * animviz_copy_motionpath(const struct bMotionPath *mpath_src)
void animviz_motionpath_blend_write(struct BlendWriter *writer, struct bMotionPath *mpath)
void animviz_motionpath_blend_read_data(struct BlendDataReader *reader, struct bMotionPath *mpath)
@ ADT_RECALC_ANIM
Definition: BKE_animsys.h:290
void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, bool flush_to_original)
void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, struct bActionGroup *agrp, const struct AnimationEvalContext *anim_eval_context)
struct Bone * BKE_armature_find_bone_name(struct bArmature *arm, const char *name)
Definition: armature.c:594
#define PBONE_VISIBLE(arm, bone)
Definition: BKE_armature.h:549
void BKE_asset_metadata_idprop_ensure(struct AssetMetaData *asset_data, struct IDProperty *prop)
Definition: asset.cc:125
void BKE_constraints_free_ex(struct ListBase *list, bool do_id_user)
Definition: constraint.c:5576
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
Definition: constraint.c:6186
void BKE_constraint_blend_write(struct BlendWriter *writer, struct ListBase *conlist)
Definition: constraint.c:6437
void BKE_constraint_blend_read_expand(struct BlendExpander *expander, struct ListBase *lb)
Definition: constraint.c:6596
void BKE_constraint_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb)
Definition: constraint.c:6489
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
Definition: constraint.c:6157
void BKE_constraints_copy(struct ListBase *dst, const struct ListBase *src, bool do_extern)
void BKE_constraint_blend_read_lib(struct BlendLibReader *reader, struct ID *id, struct ListBase *conlist)
Definition: constraint.c:6559
void BKE_constraints_copy_ex(struct ListBase *dst, const struct ListBase *src, int flag, bool do_extern)
support for deformation groups and hooks.
void BKE_fcurve_blend_write(struct BlendWriter *writer, struct ListBase *fcurves)
Definition: fcurve.c:2344
void BKE_fcurve_blend_read_data(struct BlendDataReader *reader, struct ListBase *fcurves)
Definition: fcurve.c:2383
void BKE_fcurve_free(struct FCurve *fcu)
Definition: fcurve.c:65
void BKE_fcurve_foreach_id(struct FCurve *fcu, struct LibraryForeachIDData *data)
Definition: fcurve.c:165
void BKE_fcurve_blend_read_lib(struct BlendLibReader *reader, struct ID *id, struct ListBase *fcurves)
Definition: fcurve.c:2438
struct FCurve * BKE_fcurve_copy(const struct FCurve *fcu)
void BKE_fcurve_blend_read_expand(struct BlendExpander *expander, struct ListBase *fcurves)
Definition: fcurve.c:2468
void BKE_fcurves_free(ListBase *list)
Definition: fcurve.c:86
bool BKE_fcurve_calc_range(struct FCurve *fcu, float *min, float *max, bool do_sel_only, bool do_min_length)
Definition: fcurve.c:754
void BKE_previewimg_free(struct PreviewImage **prv)
Definition: icons.cc:283
void BKE_previewimg_id_copy(struct ID *new_id, const struct ID *old_id)
void BKE_previewimg_blend_read(struct BlendDataReader *reader, struct PreviewImage *prv)
Definition: icons.cc:615
void BKE_previewimg_blend_write(struct BlendWriter *writer, const struct PreviewImage *prv)
void IDP_BlendReadExpand(struct BlendExpander *expander, struct IDProperty *prop)
Definition: idprop.c:1471
struct IDProperty * IDP_CopyProperty_ex(const struct IDProperty *prop, int flag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void IDP_BlendWrite(struct BlendWriter *writer, const struct IDProperty *prop)
struct IDProperty * IDP_New(char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: idprop.c:887
#define IDP_BlendDataRead(reader, prop)
Definition: BKE_idprop.h:321
void IDP_FreeProperty_ex(struct IDProperty *prop, bool do_id_user)
Definition: idprop.c:1087
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1093
void IDP_BlendReadLib(struct BlendLibReader *reader, struct Library *lib, struct IDProperty *prop)
Definition: idprop.c:1435
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition: BKE_idtype.h:41
@ LIB_ID_COPY_NO_PREVIEW
Definition: BKE_lib_id.h:150
@ LIB_ID_CREATE_NO_USER_REFCOUNT
Definition: BKE_lib_id.h:126
@ LIB_ID_CREATE_NO_MAIN
Definition: BKE_lib_id.h:122
void id_us_min(struct ID *id)
Definition: lib_id.c:313
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2008
void * BKE_id_new(struct Main *bmain, short type, const char *name)
Definition: lib_id.c:1159
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(_data, _id_super, _cb_flag)
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(_data, _func_call)
@ IDWALK_CB_NOP
Definition: BKE_lib_query.h:33
General operations, lookup, etc. for blender objects.
void BKE_object_workob_clear(struct Object *workob)
Definition: object.cc:1252
#define BLI_assert(a)
Definition: BLI_assert.h:46
struct GSet GSet
Definition: BLI_ghash.h:340
GHash * BLI_ghash_str_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:947
void * BLI_gset_lookup(const GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1061
void BLI_gset_insert(GSet *gs, void *key)
Definition: BLI_ghash.c:962
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:734
bool BLI_ghash_remove(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:790
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
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
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 BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:239
void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:842
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:301
void void void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1
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
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:340
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
#define M_PI
Definition: BLI_math_base.h:20
MINLINE int compare_ff(float a, float b, float max_diff)
MINLINE void rgba_uchar_args_set(unsigned char col[4], unsigned char r, unsigned char g, unsigned char b, unsigned char a)
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void unit_qt(float q[4])
Definition: math_rotation.c:27
void unit_axis_angle(float axis[3], float *angle)
Definition: math_rotation.c:19
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
bool BLI_session_uuid_ghash_compare(const void *lhs_v, const void *rhs_v)
Definition: session_uuid.c:59
SessionUUID BLI_session_uuid_generate(void)
Definition: session_uuid.c:22
uint BLI_session_uuid_ghash_hash(const void *uuid_v)
Definition: session_uuid.c:53
bool BLI_session_uuid_is_generated(const SessionUUID *uuid)
Definition: session_uuid.c:38
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
bool BLI_uniquename(struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_len)
Definition: string_utils.c:309
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
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define STREQ(a, b)
#define BLO_read_data_address(reader, ptr_p)
struct Main * BLO_read_lib_get_main(BlendLibReader *reader)
Definition: readfile.c:5313
void BLO_write_struct_by_name(BlendWriter *writer, const char *struct_name, const void *data_ptr)
Definition: writefile.c:1494
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5172
bool BLO_read_lib_is_undo(BlendLibReader *reader)
Definition: readfile.c:5308
#define BLO_read_id_address(reader, lib, id_ptr_p)
#define BLO_expand(expander, id)
#define BLT_I18NCONTEXT_ID_ACTION
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
void DEG_id_tag_update_ex(struct Main *bmain, struct ID *id, int flag)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
@ IDP_INT
Definition: DNA_ID.h:137
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:794
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ ID_RECALC_ANIMATION_NO_FLUSH
Definition: DNA_ID.h:879
#define FILTER_ID_AC
Definition: DNA_ID.h:899
@ INDEX_ID_AC
Definition: DNA_ID.h:984
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ ID_AC
Definition: DNA_ID_enums.h:67
@ ITASC_SOLVER_SDLS
@ IKSOLVER_STANDARD
@ IKSOLVER_ITASC
@ AGRP_TEMP
@ AGRP_ACTIVE
@ AGRP_SELECTED
struct bAction bAction
@ ACT_FRAME_RANGE
@ ACT_CYCLIC
@ ROT_MODE_MAX
@ ROT_MODE_MIN
@ ITASC_AUTO_STEP
@ ITASC_INITIAL_REITERATION
@ PCHAN_HAS_CONST
@ PCHAN_HAS_IK
@ PCHAN_HAS_TARGET
@ PCHAN_HAS_SPLINEIK
@ POSE_BBONE_SHAPE
@ POSE_ROT
@ POSE_LOC
@ POSE_SIZE
@ POSE_CONSTRAINTS_NEED_UPDATE_FLAGS
@ POSE_RECALC
@ POSE_CONSTRAINTS_TIMEDEPEND
@ FCM_EXTRAPOLATE_NONE
@ FCM_LIMIT_XMIN
@ FCM_LIMIT_XMAX
@ FMODIFIER_TYPE_CYCLES
@ FMODIFIER_TYPE_LIMITS
#define MAXBONENAME
@ BONE_SELECTED
@ BONE_CONNECTED
@ CONSTRAINT_DISABLE
@ CONSTRAINT_IK_AUTO
@ CONSTRAINT_IK_TIP
@ CONSTRAINT_TYPE_SPLINEIK
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_TYPE_FOLLOWPATH
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ OB_CURVES_LEGACY
@ OB_LOCK_ROT4D
#define MAXFRAMEF
#define MINAFRAMEF
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static void init_data(ModifierData *md)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
static AssetTypeInfo AssetType_AC
Definition: action.c:296
bAction * BKE_action_add(Main *bmain, const char name[])
Definition: action.c:332
void BKE_pose_channels_remove(Object *ob, bool(*filter_fn)(const char *bone_name, void *user_data), void *user_data)
Definition: action.c:960
void BKE_pose_channels_free(bPose *pose)
Definition: action.c:1100
void BKE_pose_check_uuids_unique_and_report(const bPose *pose)
Definition: action.c:1805
static void action_blend_read_expand(BlendExpander *expander, ID *id)
Definition: action.c:255
bool BKE_pose_channels_is_valid(const bPose *pose)
Definition: action.c:678
bPoseChannel * BKE_pose_channel_active_or_first_selected(struct Object *ob)
Definition: action.c:725
void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime)
Definition: action.c:1052
void BKE_pose_free_data(bPose *pose)
Definition: action.c:1124
static IDProperty * action_asset_type_property(const bAction *action)
Definition: action.c:276
void BKE_pose_blend_read_expand(BlendExpander *expander, bPose *pose)
Definition: action.c:1975
bool action_has_motion(const bAction *act)
Definition: action.c:1335
void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
Definition: action.c:1719
void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_from)
Definition: action.c:1143
void BKE_pose_remove_group_index(bPose *pose, const int index)
Definition: action.c:1322
bool BKE_pose_copy_result(bPose *to, bPose *from)
Definition: action.c:1695
void BKE_pose_remove_group(bPose *pose, bActionGroup *grp, const int index)
Definition: action.c:1284
void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end)
Definition: action.c:1480
static void action_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition: action.c:173
void set_active_action_group(bAction *act, bActionGroup *agrp, short select)
Definition: action.c:360
void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime)
Definition: action.c:1064
static bool pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
Definition: action.c:894
bPoseChannel * BKE_pose_channel_ensure(bPose *pose, const char *name)
Definition: action.c:628
void BKE_pose_channel_session_uuid_generate(bPoseChannel *pchan)
Definition: action.c:610
bool BKE_pose_is_layer_visible(const bArmature *arm, const bPoseChannel *pchan)
Definition: action.c:694
bool BKE_action_has_single_frame(const struct bAction *act)
Definition: action.c:1352
void BKE_pose_tag_update_constraint_flags(bPose *pose)
Definition: action.c:1259
void action_groups_clear_tempflags(bAction *act)
Definition: action.c:593
void BKE_pose_ikparam_init(bPose *pose)
Definition: action.c:877
IDTypeInfo IDType_ID_AC
Definition: action.c:300
static void pose_channels_remove_internal_links(Object *ob, bPoseChannel *unlinked_pchan)
Definition: action.c:945
void BKE_pose_free_data_ex(bPose *pose, bool do_id_user)
Definition: action.c:1105
void BKE_pose_itasc_init(bItasc *itasc)
Definition: action.c:860
static void action_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
Definition: action.c:92
static void action_blend_read_data(BlendDataReader *reader, ID *id)
Definition: action.c:193
bPoseChannel * BKE_pose_channel_get_mirrored(const bPose *pose, const char *name)
Definition: action.c:748
void BKE_pose_copy_pchan_result(bPoseChannel *pchanto, const bPoseChannel *pchanfrom)
Definition: action.c:1664
void BKE_pose_channel_free(bPoseChannel *pchan)
Definition: action.c:1078
bActionGroup * BKE_action_group_find_name(bAction *act, const char name[])
Definition: action.c:582
void BKE_pose_channels_hash_ensure(bPose *pose)
Definition: action.c:925
const char * BKE_pose_ikparam_get_name(bPose *pose)
Definition: action.c:761
void BKE_pose_free_ex(bPose *pose, bool do_id_user)
Definition: action.c:1129
void BKE_action_groups_reconstruct(bAction *act)
Definition: action.c:503
void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
Definition: action.c:435
void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const bool copy_constraints)
Definition: action.c:774
void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose)
Definition: action.c:1932
bPoseChannel * BKE_pose_channel_active_if_layer_visible(struct Object *ob)
Definition: action.c:720
void BKE_action_fcurves_clear(bAction *act)
Definition: action.c:1988
void BKE_pose_free(bPose *pose)
Definition: action.c:1138
bActionGroup * BKE_pose_add_group(bPose *pose, const char *name)
Definition: action.c:1266
void action_groups_remove_channel(bAction *act, FCurve *fcu)
Definition: action.c:542
bool BKE_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
Definition: action.c:920
static void action_foreach_id(ID *id, LibraryForeachIDData *data)
Definition: action.c:160
static CLG_LogRef LOG
Definition: action.c:63
void BKE_pose_channel_free_bbone_cache(bPoseChannel_Runtime *runtime)
Definition: action.c:1069
bActionGroup * get_active_actiongroup(bAction *act)
Definition: action.c:345
void BKE_pose_channel_runtime_reset_on_copy(bPoseChannel_Runtime *runtime)
Definition: action.c:1057
void BKE_pose_channels_free_ex(bPose *pose, bool do_id_user)
Definition: action.c:1083
void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm)
Definition: action.c:1832
bActionGroup * action_groups_add_new(bAction *act, const char name[])
Definition: action.c:410
void BKE_pose_update_constraint_flags(bPose *pose)
Definition: action.c:1192
static void blend_read_lib_constraint_channels(BlendLibReader *reader, ID *id, ListBase *chanbase)
Definition: action.c:221
static void blend_read_expand_constraint_channels(BlendExpander *expander, ListBase *chanbase)
Definition: action.c:248
bool BKE_action_is_cyclic(const struct bAction *act)
Definition: action.c:1496
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
Definition: action.c:615
void calc_action_range(const bAction *act, float *start, float *end, short incl_modifiers)
Definition: action.c:1393
static void action_asset_pre_save(void *asset_ptr, struct AssetMetaData *asset_data)
Definition: action.c:287
bPoseChannel * BKE_pose_channel_active(Object *ob, const bool check_arm_layer)
Definition: action.c:699
void BKE_pose_blend_read_data(BlendDataReader *reader, bPose *pose)
Definition: action.c:1884
void BKE_pose_channels_hash_free(bPose *pose)
Definition: action.c:937
void action_group_colors_sync(bActionGroup *grp, const bActionGroup *ref_grp)
Definition: action.c:380
short action_get_item_transforms(bAction *act, Object *ob, bPoseChannel *pchan, ListBase *curves)
Definition: action.c:1501
void what_does_obaction(Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], const AnimationEvalContext *anim_eval_context)
Definition: action.c:1728
static void action_blend_read_lib(BlendLibReader *reader, ID *id)
Definition: action.c:228
void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
Definition: action.c:1024
static void action_free_data(struct ID *id)
Definition: action.c:143
void BKE_pose_copy_data(bPose **dst, const bPose *src, const bool copy_constraints)
Definition: action.c:855
void BKE_pose_rest(bPose *pose, bool selected_bones_only)
Definition: action.c:1631
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
unsigned int U
Definition: btGjkEpa3.h:78
StackEntry * from
void * user_data
SyclQueue void void * src
#define GS(x)
Definition: iris.c:225
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:136
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
char * RNA_path_from_ID_to_struct(const PointerRNA *ptr)
Definition: rna_path.cc:981
#define min(a, b)
Definition: sort.c:35
bAction * action
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
char name[64]
struct Bone * next
ListBase childbase
struct FCurve * next
bActionGroup * grp
char * rna_path
struct FCurve * prev
unsigned int totvert
ListBase modifiers
void * data
short id_code
Definition: BKE_idtype.h:114
Definition: DNA_ID.h:368
struct Library * lib
Definition: DNA_ID.h:372
char name[66]
Definition: DNA_ID.h:378
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
short partype
ListBase constraints
struct bPose * pose
float constinv[4][4]
float parentinv[4][4]
float obmat[4][4]
short rotmode
struct AnimData * adt
struct Object * parent
short trackflag
short upflag
void * data
char parsubstr[64]
unsigned char select[4]
unsigned char solid[4]
unsigned char active[4]
ThemeWireColor cs
struct bActionGroup * prev
struct bActionGroup * next
ListBase curves
float frame_start
float frame_end
ListBase groups
PreviewImage * preview
ListBase markers
unsigned int layer
struct bConstraintTarget * next
struct bConstraint * next
float minstep
float dampmax
float precision
float dampeps
float feedback
float maxvel
short numstep
short numiter
short solver
float maxstep
struct Mat4 * bbone_deform_mats
struct DualQuat * bbone_dual_quats
struct Mat4 * bbone_pose_mats
struct Mat4 * bbone_rest_mats
ListBase constraints
IDProperty * prop
float custom_scale_xyz[3]
float scale_out[3]
bPoseChannelDrawData * draw_data
float custom_rotation_euler[3]
struct Bone * bone
struct bPoseChannel * parent
struct bPoseChannel * custom_tx
bMotionPath * mpath
float stiffness[3]
float pose_head[3]
float chan_mat[4][4]
struct bPoseChannel * bbone_next
float pose_tail[3]
struct Object * custom
struct bPoseChannel * next
float custom_translation[3]
float constinv[4][4]
struct bPoseChannel_Runtime runtime
struct bPoseChannel * bbone_prev
float pose_mat[4][4]
ListBase chanbase
void * ikdata
void * ikparam
struct GHash * chanhash
ListBase agroups
short flag
bAnimVizSettings avs
int active_group
float stride_offset[3]
bPoseChannel ** chan_array
float cyclic_offset[3]
ThemeWireColor tarm[20]
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float max
PointerRNA * ptr
Definition: wm_files.c:3480