Blender  V3.3
pose_lib.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 Blender Foundation. */
3 
8 #include <math.h>
9 #include <string.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_blenlib.h"
14 #include "BLI_dlrbTree.h"
15 #include "BLI_string_utils.h"
16 
17 #include "BLT_translation.h"
18 
19 #include "DNA_anim_types.h"
20 #include "DNA_armature_types.h"
21 #include "DNA_object_types.h"
22 #include "DNA_scene_types.h"
23 
24 #include "BKE_action.h"
25 #include "BKE_animsys.h"
26 #include "BKE_armature.h"
27 #include "BKE_fcurve.h"
28 #include "BKE_idprop.h"
29 #include "BKE_lib_id.h"
30 #include "BKE_main.h"
31 #include "BKE_object.h"
32 
33 #include "BKE_context.h"
34 #include "BKE_report.h"
35 
36 #include "DEG_depsgraph.h"
37 
38 #include "RNA_access.h"
39 #include "RNA_define.h"
40 #include "RNA_enum_types.h"
41 #include "RNA_prototypes.h"
42 
43 #include "WM_api.h"
44 #include "WM_types.h"
45 
46 #include "UI_interface.h"
47 #include "UI_resources.h"
48 
49 #include "ED_anim_api.h"
50 #include "ED_armature.h"
51 #include "ED_keyframes_edit.h"
52 #include "ED_keyframes_keylist.h"
53 #include "ED_keyframing.h"
54 #include "ED_object.h"
55 #include "ED_screen.h"
56 
57 #include "armature_intern.h"
58 
59 /* ******* XXX ********** */
60 
61 static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUSED(c))
62 {
63 }
64 
65 /* ************************************************************* */
84 /* ************************************************************* */
85 
86 /* gets the first available frame in poselib to store a pose on
87  * - frames start from 1, and a pose should occur on every frame... 0 is error!
88  */
90 {
91  TimeMarker *marker;
92  int low = 0, high = 0;
93  bool changed = false;
94 
95  /* sanity checks */
96  if (ELEM(NULL, act, act->markers.first)) {
97  return 1;
98  }
99 
100  /* As poses are not stored in chronological order, we must iterate over this list
101  * a few times until we don't make any new discoveries (mostly about the lower bound).
102  * Prevents problems with deleting then trying to add new poses T27412.
103  */
104  do {
105  changed = false;
106 
107  for (marker = act->markers.first; marker; marker = marker->next) {
108  /* only increase low if value is 1 greater than low, to find "gaps" where
109  * poses were removed from the poselib
110  */
111  if (marker->frame == (low + 1)) {
112  low++;
113  changed = true;
114  }
115 
116  /* value replaces high if it is the highest value encountered yet */
117  if (marker->frame > high) {
118  high = marker->frame;
119  changed = true;
120  }
121  }
122  } while (changed != 0);
123 
124  /* - if low is not equal to high, then low+1 is a gap
125  * - if low is equal to high, then high+1 is the next index (add at end)
126  */
127  if (low < high) {
128  return (low + 1);
129  }
130  return (high + 1);
131 }
132 
133 /* returns the active pose for a poselib */
135 {
136  if ((act) && (act->active_marker)) {
137  return BLI_findlink(&act->markers, act->active_marker - 1);
138  }
139  return NULL;
140 }
141 
142 /* Get object that Pose Lib should be found on */
143 /* XXX C can be zero */
145 {
146  ScrArea *area;
147 
148  /* sanity check */
149  if (C == NULL) {
150  return NULL;
151  }
152 
153  area = CTX_wm_area(C);
154 
155  if (area && (area->spacetype == SPACE_PROPERTIES)) {
156  return ED_object_context(C);
157  }
159 }
160 
161 /* Poll callback for operators that require existing PoseLib data (with poses) to work */
163 {
164  Object *ob = get_poselib_object(C);
165  return (ob && ob->poselib);
166 }
167 
168 /* Poll callback for operators that require existing PoseLib data (with poses)
169  * as they need to do some editing work on those poses (i.e. not on lib-linked actions)
170  */
172 {
173  Object *ob = get_poselib_object(C);
174  return (ob && ob->poselib && BKE_id_is_editable(CTX_data_main(C), &ob->poselib->id));
175 }
176 
177 /* ----------------------------------- */
178 
179 /* Initialize a new poselib (whether it is needed or not) */
180 static bAction *poselib_init_new(Main *bmain, Object *ob)
181 {
182  /* sanity checks - only for armatures */
183  if (ELEM(NULL, ob, ob->pose)) {
184  return NULL;
185  }
186 
187  /* init object's poselib action (unlink old one if there) */
188  if (ob->poselib) {
189  id_us_min(&ob->poselib->id);
190  }
191 
192  ob->poselib = BKE_action_add(bmain, "PoseLib");
193  ob->poselib->idroot = ID_OB;
194 
195  return ob->poselib;
196 }
197 
198 /* Initialize a new poselib (checks if that needs to happen) */
199 static bAction *poselib_validate(Main *bmain, Object *ob)
200 {
201  if (ELEM(NULL, ob, ob->pose)) {
202  return NULL;
203  }
204  if (ob->poselib == NULL) {
205  return poselib_init_new(bmain, ob);
206  }
207  return ob->poselib;
208 }
209 
210 /* ************************************************************* */
211 /* Pose Lib UI Operators */
212 
214 {
215  Main *bmain = CTX_data_main(C);
216  Object *ob = get_poselib_object(C);
217 
218  /* sanity checks */
219  if (ob == NULL) {
220  return OPERATOR_CANCELLED;
221  }
222 
223  /* new method here deals with the rest... */
224  poselib_init_new(bmain, ob);
225 
226  /* notifier here might evolve? */
228 
229  return OPERATOR_FINISHED;
230 }
231 
233 {
234  /* identifiers */
235  ot->name = "New Legacy Pose Library";
236  ot->idname = "POSELIB_OT_new";
237  ot->description =
238  "Deprecated, will be removed in Blender 3.3. "
239  "Add New Legacy Pose Library to active Object";
240 
241  /* callbacks */
244 
245  /* flags */
247 }
248 
249 /* ------------------------------------------------ */
250 
252 {
253  Object *ob = get_poselib_object(C);
254 
255  /* sanity checks */
256  if (ELEM(NULL, ob, ob->poselib)) {
257  return OPERATOR_CANCELLED;
258  }
259 
260  /* there should be a poselib (we just checked above!), so just lower its user count and remove */
261  id_us_min(&ob->poselib->id);
262  ob->poselib = NULL;
263 
264  /* notifier here might evolve? */
266 
267  return OPERATOR_FINISHED;
268 }
269 
271 {
272  /* identifiers */
273  ot->name = "Unlink Legacy Pose Library";
274  ot->idname = "POSELIB_OT_unlink";
275  ot->description =
276  "Deprecated, will be removed in Blender 3.3. "
277  "Remove Legacy Pose Library from active Object";
278 
279  /* callbacks */
282 
283  /* flags */
285 }
286 
287 /* ************************************************************* */
288 /* Pose Editing Operators */
289 
290 /* This tool automagically generates/validates poselib data so that it corresponds to the data
291  * in the action. This is for use in making existing actions usable as poselibs.
292  */
294 {
295  Object *ob = get_poselib_object(C);
296  bAction *act = (ob) ? ob->poselib : NULL;
297  TimeMarker *marker, *markern;
298 
299  /* validate action */
300  if (act == NULL) {
301  BKE_report(op->reports, RPT_WARNING, "No action to validate");
302  return OPERATOR_CANCELLED;
303  }
304 
305  /* determine which frames have keys */
306  struct AnimKeylist *keylist = ED_keylist_create();
307  action_to_keylist(NULL, act, keylist, 0);
308 
309  /* for each key, make sure there is a corresponding pose */
310  LISTBASE_FOREACH (const ActKeyColumn *, ak, ED_keylist_listbase(keylist)) {
311  /* check if any pose matches this */
312  /* TODO: don't go looking through the list like this every time... */
313  for (marker = act->markers.first; marker; marker = marker->next) {
314  if (IS_EQ((double)marker->frame, (double)ak->cfra)) {
315  marker->flag = -1;
316  break;
317  }
318  }
319 
320  /* add new if none found */
321  if (marker == NULL) {
322  /* add pose to poselib */
323  marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
324 
325  BLI_snprintf(marker->name, sizeof(marker->name), "F%d Pose", (int)ak->cfra);
326 
327  marker->frame = (int)ak->cfra;
328  marker->flag = -1;
329 
330  BLI_addtail(&act->markers, marker);
331  }
332  }
333 
334  /* remove all untagged poses (unused), and remove all tags */
335  for (marker = act->markers.first; marker; marker = markern) {
336  markern = marker->next;
337 
338  if (marker->flag != -1) {
339  BLI_freelinkN(&act->markers, marker);
340  }
341  else {
342  marker->flag = 0;
343  }
344  }
345 
346  /* free temp memory */
347  ED_keylist_free(keylist);
348 
349  /* send notifiers for this - using keyframe editing notifiers, since action
350  * may be being shown in anim editors as active action
351  */
353 
354  return OPERATOR_FINISHED;
355 }
356 
358 {
359  /* identifiers */
360  ot->name = "Sanitize Legacy Pose Library Action";
361  ot->idname = "POSELIB_OT_action_sanitize";
362  ot->description =
363  "Deprecated, will be removed in Blender 3.3. "
364  "Make action suitable for use as a Legacy Pose Library";
365 
366  /* callbacks */
369 
370  /* flags */
372 }
373 
374 /* ------------------------------------------ */
375 
376 /* Poll callback for adding poses to a PoseLib */
378 {
379  /* There are 2 cases we need to be careful with:
380  * 1) When this operator is invoked from a hotkey, there may be no PoseLib yet
381  * 2) If a PoseLib already exists, we can't edit the action if it is a lib-linked
382  * actions, as data will be lost when saving the file
383  */
384  if (ED_operator_posemode(C)) {
385  Object *ob = get_poselib_object(C);
386  if (ob) {
387  if ((ob->poselib == NULL) || BKE_id_is_editable(CTX_data_main(C), &ob->poselib->id)) {
388  return true;
389  }
390  }
391  }
392  return false;
393 }
394 
396 {
397  Object *ob = get_poselib_object(C);
398  bAction *act = ob->poselib; /* never NULL */
399  TimeMarker *marker;
400 
401  wmOperatorType *ot = WM_operatortype_find("POSELIB_OT_pose_add", 1);
402 
403  BLI_assert(ot != NULL);
404 
405  /* set the operator execution context correctly */
407 
408  /* add each marker to this menu */
409  for (marker = act->markers.first; marker; marker = marker->next) {
410  PointerRNA props_ptr;
412  layout, ot, marker->name, ICON_ARMATURE_DATA, NULL, WM_OP_EXEC_DEFAULT, 0, &props_ptr);
413  RNA_int_set(&props_ptr, "frame", marker->frame);
414  RNA_string_set(&props_ptr, "name", marker->name);
415  }
416 }
417 
418 static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
419 {
421  Object *ob = get_poselib_object(C);
422  bPose *pose = (ob) ? ob->pose : NULL;
423  uiPopupMenu *pup;
424  uiLayout *layout;
425 
426  /* sanity check */
427  if (ELEM(NULL, ob, pose)) {
428  return OPERATOR_CANCELLED;
429  }
430 
431  /* start building */
432  pup = UI_popup_menu_begin(C, op->type->name, ICON_NONE);
433  layout = UI_popup_menu_layout(pup);
435 
436  /* add new (adds to the first unoccupied frame) */
437  uiItemIntO(layout,
438  IFACE_("Add New"),
439  ICON_NONE,
440  "POSELIB_OT_pose_add",
441  "frame",
443 
444  /* check if we have any choices to add a new pose in any other way */
445  if ((ob->poselib) && (ob->poselib->markers.first)) {
446  /* add new (on current frame) */
447  uiItemIntO(layout,
448  IFACE_("Add New (Current Frame)"),
449  ICON_NONE,
450  "POSELIB_OT_pose_add",
451  "frame",
452  scene->r.cfra);
453 
454  /* Replace existing - sub-menu. */
455  uiItemMenuF(
456  layout, IFACE_("Replace Existing..."), 0, poselib_add_menu_invoke__replacemenu, NULL);
457  }
458 
459  UI_popup_menu_end(C, pup);
460 
461  /* this operator is only for a menu, not used further */
462  return OPERATOR_INTERFACE;
463 }
464 
466 {
467  Main *bmain = CTX_data_main(C);
468  Object *ob = get_poselib_object(C);
469  bAction *act = poselib_validate(bmain, ob);
470  bPose *pose = (ob) ? ob->pose : NULL;
471  TimeMarker *marker;
472  KeyingSet *ks;
473  int frame = RNA_int_get(op->ptr, "frame");
474  char name[64];
475 
476  /* sanity check (invoke should have checked this anyway) */
477  if (ELEM(NULL, ob, pose)) {
478  return OPERATOR_CANCELLED;
479  }
480 
481  /* get name to give to pose */
482  RNA_string_get(op->ptr, "name", name);
483 
484  /* add pose to poselib - replaces any existing pose there
485  * - for the 'replace' option, this should end up finding the appropriate marker,
486  * so no new one will be added
487  */
488  for (marker = act->markers.first; marker; marker = marker->next) {
489  if (marker->frame == frame) {
490  BLI_strncpy(marker->name, name, sizeof(marker->name));
491  break;
492  }
493  }
494  if (marker == NULL) {
495  marker = MEM_callocN(sizeof(TimeMarker), "ActionMarker");
496 
497  BLI_strncpy(marker->name, name, sizeof(marker->name));
498  marker->frame = frame;
499 
500  BLI_addtail(&act->markers, marker);
501  }
502 
503  /* validate name */
505  &act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
506 
507  /* use Keying Set to determine what to store for the pose */
508 
509  /* This includes custom props :). */
511 
512  ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
513 
514  /* store new 'active' pose number */
517 
518  /* done */
519  return OPERATOR_FINISHED;
520 }
521 
523 {
524  /* identifiers */
525  ot->name = "Legacy PoseLib Add Pose";
526  ot->idname = "POSELIB_OT_pose_add";
527  ot->description =
528  "Deprecated, will be removed in Blender 3.3. "
529  "Add the current Pose to the active Legacy Pose Library";
530 
531  /* api callbacks */
535 
536  /* flags */
538 
539  /* properties */
540  RNA_def_int(ot->srna, "frame", 1, 0, INT_MAX, "Frame", "Frame to store pose on", 0, INT_MAX);
541  RNA_def_string(ot->srna, "name", "Pose", 64, "Pose Name", "Name of newly added Pose");
542 }
543 
544 /* ----- */
545 
546 /* can be called with C == NULL */
549  PropertyRNA *UNUSED(prop),
550  bool *r_free)
551 {
552  Object *ob = get_poselib_object(C);
553  bAction *act = (ob) ? ob->poselib : NULL;
554  TimeMarker *marker;
555  EnumPropertyItem *item = NULL, item_tmp = {0};
556  int totitem = 0;
557  int i = 0;
558 
559  if (C == NULL) {
560  return DummyRNA_NULL_items;
561  }
562 
563  /* check that the action exists */
564  if (act) {
565  /* add each marker to the list */
566  for (marker = act->markers.first, i = 0; marker; marker = marker->next, i++) {
567  item_tmp.identifier = item_tmp.name = marker->name;
568  item_tmp.icon = ICON_ARMATURE_DATA;
569  item_tmp.value = i;
570  RNA_enum_item_add(&item, &totitem, &item_tmp);
571  }
572  }
573 
574  RNA_enum_item_end(&item, &totitem);
575  *r_free = true;
576 
577  return item;
578 }
579 
581 {
582  Object *ob = get_poselib_object(C);
583  bAction *act = (ob) ? ob->poselib : NULL;
584  TimeMarker *marker;
585  int marker_index;
586  FCurve *fcu;
587  PropertyRNA *prop;
588 
589  /* check if valid poselib */
590  if (act == NULL) {
591  BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
592  return OPERATOR_CANCELLED;
593  }
594 
595  prop = RNA_struct_find_property(op->ptr, "pose");
596  if (RNA_property_is_set(op->ptr, prop)) {
597  marker_index = RNA_property_enum_get(op->ptr, prop);
598  }
599  else {
600  marker_index = act->active_marker - 1;
601  }
602 
603  /* get index (and pointer) of pose to remove */
604  marker = BLI_findlink(&act->markers, marker_index);
605  if (marker == NULL) {
606  BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
607  return OPERATOR_CANCELLED;
608  }
609 
610  /* remove relevant keyframes */
611  for (fcu = act->curves.first; fcu; fcu = fcu->next) {
612  BezTriple *bezt;
613  uint i;
614 
615  if (fcu->bezt) {
616  for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
617  /* check if remove */
618  if (IS_EQF(bezt->vec[1][0], (float)marker->frame)) {
619  BKE_fcurve_delete_key(fcu, i);
621  break;
622  }
623  }
624  }
625  }
626 
627  /* remove poselib from list */
628  BLI_freelinkN(&act->markers, marker);
629 
630  /* fix active pose number */
631  act->active_marker = 0;
632 
633  /* send notifiers for this - using keyframe editing notifiers, since action
634  * may be being shown in anim editors as active action
635  */
638 
639  /* done */
640  return OPERATOR_FINISHED;
641 }
642 
644 {
645  PropertyRNA *prop;
646 
647  /* identifiers */
648  ot->name = "Legacy PoseLib Remove Pose";
649  ot->idname = "POSELIB_OT_pose_remove";
650  ot->description =
651  "Deprecated, will be removed in Blender 3.3. "
652  "Remove nth pose from the active Legacy Pose Library";
653 
654  /* api callbacks */
658 
659  /* flags */
661 
662  /* properties */
663  prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to remove");
666  ot->prop = prop;
667 }
668 
669 static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *event)
670 {
671  Object *ob = get_poselib_object(C);
672  bAction *act = (ob) ? ob->poselib : NULL;
673  TimeMarker *marker;
674 
675  /* check if valid poselib */
676  if (act == NULL) {
677  BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
678  return OPERATOR_CANCELLED;
679  }
680 
681  /* get index (and pointer) of pose to remove */
682  marker = BLI_findlink(&act->markers, act->active_marker - 1);
683  if (marker == NULL) {
684  BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
685  return OPERATOR_CANCELLED;
686  }
687 
688  /* Use the existing name of the marker as the name,
689  * and use the active marker as the one to rename. */
690  RNA_enum_set(op->ptr, "pose", act->active_marker - 1);
691  RNA_string_set(op->ptr, "name", marker->name);
692 
693  /* part to sync with other similar operators... */
694  return WM_operator_props_popup_confirm(C, op, event);
695 }
696 
698 {
700  bAction *act = (ob) ? ob->poselib : NULL;
701  TimeMarker *marker;
702  char newname[64];
703 
704  /* check if valid poselib */
705  if (act == NULL) {
706  BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
707  return OPERATOR_CANCELLED;
708  }
709 
710  /* get index (and pointer) of pose to remove */
711  marker = BLI_findlink(&act->markers, RNA_enum_get(op->ptr, "pose"));
712  if (marker == NULL) {
713  BKE_report(op->reports, RPT_ERROR, "Invalid index for pose");
714  return OPERATOR_CANCELLED;
715  }
716 
717  /* get new name */
718  RNA_string_get(op->ptr, "name", newname);
719 
720  /* copy name and validate it */
721  BLI_strncpy(marker->name, newname, sizeof(marker->name));
723  &act->markers, marker, DATA_("Pose"), '.', offsetof(TimeMarker, name), sizeof(marker->name));
724 
725  /* send notifiers for this - using keyframe editing notifiers, since action
726  * may be being shown in anim editors as active action
727  */
729 
730  /* done */
731  return OPERATOR_FINISHED;
732 }
733 
735 {
736  PropertyRNA *prop;
737 
738  /* identifiers */
739  ot->name = "Legacy PoseLib Rename Pose";
740  ot->idname = "POSELIB_OT_pose_rename";
741  ot->description =
742  "Deprecated, will be removed in Blender 3.3. "
743  "Rename specified pose from the active Legacy Pose Library";
744 
745  /* api callbacks */
749 
750  /* flags */
752 
753  /* properties */
754  /* NOTE: name not pose is the operator's "main" property,
755  * so that it will get activated in the popup for easy renaming */
757  ot->srna, "name", "RenamedPose", 64, "New Pose Name", "New name for pose");
758  prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to rename");
761 }
762 
764 {
765  Object *ob = get_poselib_object(C);
766  bAction *act = (ob) ? ob->poselib : NULL;
767  TimeMarker *marker;
768  int marker_index;
769  int dir;
770  PropertyRNA *prop;
771 
772  /* check if valid poselib */
773  if (act == NULL) {
774  BKE_report(op->reports, RPT_ERROR, "Object does not have pose lib data");
775  return OPERATOR_CANCELLED;
776  }
777 
778  prop = RNA_struct_find_property(op->ptr, "pose");
779  if (RNA_property_is_set(op->ptr, prop)) {
780  marker_index = RNA_property_enum_get(op->ptr, prop);
781  }
782  else {
783  marker_index = act->active_marker - 1;
784  }
785 
786  /* get index (and pointer) of pose to remove */
787  marker = BLI_findlink(&act->markers, marker_index);
788  if (marker == NULL) {
789  BKE_reportf(op->reports, RPT_ERROR, "Invalid pose specified %d", marker_index);
790  return OPERATOR_CANCELLED;
791  }
792 
793  dir = RNA_enum_get(op->ptr, "direction");
794 
795  /* move pose */
796  if (BLI_listbase_link_move(&act->markers, marker, dir)) {
797  act->active_marker = marker_index + dir + 1;
798 
799  /* send notifiers for this - using keyframe editing notifiers, since action
800  * may be being shown in anim editors as active action
801  */
803  }
804  else {
805  return OPERATOR_CANCELLED;
806  }
807 
808  /* done */
809  return OPERATOR_FINISHED;
810 }
811 
813 {
814  PropertyRNA *prop;
815  static const EnumPropertyItem pose_lib_pose_move[] = {
816  {-1, "UP", 0, "Up", ""},
817  {1, "DOWN", 0, "Down", ""},
818  {0, NULL, 0, NULL, NULL},
819  };
820 
821  /* identifiers */
822  ot->name = "Legacy PoseLib Move Pose";
823  ot->idname = "POSELIB_OT_pose_move";
824  ot->description =
825  "Deprecated, will be removed in Blender 3.3. "
826  "Move the pose up or down in the active Legacy Pose Library";
827 
828  /* api callbacks */
832 
833  /* flags */
835 
836  /* properties */
837  prop = RNA_def_enum(ot->srna, "pose", DummyRNA_NULL_items, 0, "Pose", "The pose to move");
840  ot->prop = prop;
841 
843  "direction",
844  pose_lib_pose_move,
845  0,
846  "Direction",
847  "Direction to move the chosen pose towards");
848 }
849 
850 /* ************************************************************* */
851 /* Pose-Lib Browsing/Previewing Operator */
852 
853 /* Simple struct for storing settings/data for use during PoseLib preview */
854 typedef struct tPoseLib_PreviewData {
859 
864 
877 
879  int totcount;
880 
882  short state;
884  short redraw;
886  short flag;
887 
891  char searchstr[64];
894  char searchold[64];
895 
899 
900 /* defines for tPoseLib_PreviewData->state values */
901 enum {
907 };
908 
909 /* defines for tPoseLib_PreviewData->redraw values */
910 enum {
914 };
915 
916 /* defines for tPoseLib_PreviewData->flag values */
917 enum {
921 };
922 
923 /* ---------------------------- */
924 
925 /* simple struct for storing backup info */
926 typedef struct tPoseLib_Backup {
928 
929  bPoseChannel *pchan; /* pose channel backups are for */
930 
931  bPoseChannel olddata; /* copy of pose channel's old data (at start) */
932  IDProperty *oldprops; /* copy (needs freeing) of pose channel's properties (at start) */
934 
935 /* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
937 {
938  bActionGroup *agrp;
940  bool selected = false;
941 
942  /* determine whether any bone is selected. */
943  LISTBASE_FOREACH (bPoseChannel *, bchan, &pld->pose->chanbase) {
944  selected = bchan->bone != NULL && bchan->bone->flag & BONE_SELECTED;
945  if (selected) {
947  break;
948  }
949  }
950  if (!selected) {
952  }
953 
954  /* for each posechannel that has an actionchannel in */
955  for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) {
956  /* try to find posechannel */
957  pchan = BKE_pose_channel_find_name(pld->pose, agrp->name);
958 
959  /* backup data if available */
960  if (pchan) {
961  tPoseLib_Backup *plb;
962 
963  /* store backup */
964  plb = MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
965 
966  plb->pchan = pchan;
967  memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
968 
969  if (pchan->prop) {
971  }
972 
973  BLI_addtail(&pld->backups, plb);
974 
975  /* mark as being affected */
976  pld->totcount++;
977  }
978  }
979 }
980 
981 /* Restores original pose */
983 {
984  tPoseLib_Backup *plb;
985 
986  for (plb = pld->backups.first; plb; plb = plb->next) {
987  /* copy most of data straight back */
988  memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
989 
990  /* just overwrite values of properties from the stored copies (there should be some) */
991  if (plb->oldprops) {
992  IDP_SyncGroupValues(plb->pchan->prop, plb->oldprops);
993  }
994 
995  /* TODO: constraints settings aren't restored yet,
996  * even though these could change (though not that likely) */
997  }
998 }
999 
1000 /* Free list of backups, including any side data it may use */
1002 {
1003  tPoseLib_Backup *plb, *plbn;
1004 
1005  for (plb = pld->backups.first; plb; plb = plbn) {
1006  plbn = plb->next;
1007 
1008  /* free custom data */
1009  if (plb->oldprops) {
1010  IDP_FreeProperty(plb->oldprops);
1011  }
1012 
1013  /* free backup element now */
1014  BLI_freelinkN(&pld->backups, plb);
1015  }
1016 }
1017 
1018 /* ---------------------------- */
1019 
1020 /* Applies the appropriate stored pose from the pose-library to the current pose
1021  * - assumes that a valid object, with a poselib has been supplied
1022  * - gets the string to print in the header
1023  * - this code is based on the code for extract_pose_from_action in blenkernel/action.c
1024  */
1026  const AnimationEvalContext *anim_eval_context)
1027 {
1028  PointerRNA *ptr = &pld->rna_ptr;
1029  bArmature *arm = pld->arm;
1030  bPose *pose = pld->pose;
1032  bAction *act = pld->act;
1033  bActionGroup *agrp;
1034 
1035  KeyframeEditData ked = {{NULL}};
1036  KeyframeEditFunc group_ok_cb;
1037  int frame = 1;
1038  const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
1039 
1040  /* get the frame */
1041  if (pld->marker) {
1042  frame = pld->marker->frame;
1043  }
1044  else {
1045  return;
1046  }
1047 
1048  /* init settings for testing groups for keyframes */
1050  ked.f1 = ((float)frame) - 0.5f;
1051  ked.f2 = ((float)frame) + 0.5f;
1053  anim_eval_context, frame);
1054 
1055  /* start applying - only those channels which have a key at this point in time! */
1056  for (agrp = act->groups.first; agrp; agrp = agrp->next) {
1057  /* check if group has any keyframes */
1059  &ked, NULL, agrp, ALE_GROUP, NULL, group_ok_cb, NULL)) {
1060  /* has keyframe on this frame, so try to get a PoseChannel with this name */
1061  pchan = BKE_pose_channel_find_name(pose, agrp->name);
1062 
1063  if (pchan) {
1064  bool ok = 0;
1065 
1066  /* check if this bone should get any animation applied */
1067  if (!any_bone_selected) {
1068  /* if no bones are selected, then any bone is ok */
1069  ok = 1;
1070  }
1071  else if (pchan->bone) {
1072  /* only ok if bone is visible and selected */
1073  if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->flag & BONE_HIDDEN_P) == 0 &&
1075  ok = 1;
1076  }
1077  }
1078 
1079  if (ok) {
1080  animsys_evaluate_action_group(ptr, act, agrp, &anim_context_at_frame);
1081  }
1082  }
1083  }
1084  }
1085 }
1086 
1087 /* Auto-keys/tags bones affected by the pose used from the poselib */
1089 {
1090  bPose *pose = pld->pose;
1092  bAction *act = pld->act;
1093  bActionGroup *agrp;
1094 
1096  ListBase dsources = {NULL, NULL};
1097  bool autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id);
1098  const bool any_bone_selected = pld->flag & PL_PREVIEW_ANY_BONE_SELECTED;
1099 
1100  /* start tagging/keying */
1101  for (agrp = act->groups.first; agrp; agrp = agrp->next) {
1102  /* Only for selected bones unless there aren't any selected, in which case all are included. */
1103  pchan = BKE_pose_channel_find_name(pose, agrp->name);
1104 
1105  if (pchan) {
1106  if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) {
1107  if (autokey) {
1108  /* Add data-source override for the PoseChannel, to be used later. */
1109  ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan);
1110  }
1111  }
1112  }
1113  }
1114 
1115  /* perform actual auto-keying now */
1116  if (autokey) {
1117  /* insert keyframes for all relevant bones in one go */
1118  ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)scene->r.cfra);
1119  BLI_freelistN(&dsources);
1120  }
1121 
1122  /* send notifiers for this */
1124 }
1125 
1126 /* Apply the relevant changes to the pose */
1128 {
1130 
1131  /* only recalc pose (and its dependencies) if pose has changed */
1132  if (pld->redraw == PL_PREVIEW_REDRAWALL) {
1133  /* Don't clear pose if first time. */
1134  if ((pld->flag & PL_PREVIEW_FIRSTTIME) == 0) {
1136  }
1137  else {
1138  pld->flag &= ~PL_PREVIEW_FIRSTTIME;
1139  }
1140 
1141  /* pose should be the right one to draw (unless we're temporarily not showing it) */
1142  if ((pld->flag & PL_PREVIEW_SHOWORIGINAL) == 0) {
1143  RNA_int_set(op->ptr, "pose_index", BLI_findindex(&pld->act->markers, pld->marker));
1145 
1146  const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(
1147  depsgraph, 0.0f /* poselib_apply_pose() determines its own evaluation time. */);
1148  poselib_apply_pose(pld, &anim_eval_context);
1149  }
1150  else {
1151  RNA_int_set(op->ptr, "pose_index", -2); /* -2 means don't apply any pose */
1152  }
1153 
1155  }
1156 
1157  /* do header print - if interactively previewing */
1158  if (pld->state == PL_PREVIEW_RUNNING) {
1159  if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
1160  ED_area_status_text(pld->area, TIP_("PoseLib Previewing Pose: [Showing Original Pose]"));
1161  ED_workspace_status_text(C, TIP_("Use Tab to start previewing poses again"));
1162  }
1163  else if (pld->searchstr[0]) {
1164  char tempstr[65];
1165  char markern[64];
1166  short index;
1167 
1168  /* get search-string */
1169  index = pld->search_cursor;
1170 
1171  if (index >= 0 && index < sizeof(tempstr) - 1) {
1172  memcpy(&tempstr[0], &pld->searchstr[0], index);
1173  tempstr[index] = '|';
1174  memcpy(&tempstr[index + 1], &pld->searchstr[index], (sizeof(tempstr) - 1) - index);
1175  }
1176  else {
1177  BLI_strncpy(tempstr, pld->searchstr, sizeof(tempstr));
1178  }
1179 
1180  /* get marker name */
1181  BLI_strncpy(markern, pld->marker ? pld->marker->name : "No Matches", sizeof(markern));
1182 
1183  BLI_snprintf(pld->headerstr,
1184  sizeof(pld->headerstr),
1185  TIP_("PoseLib Previewing Pose: Filter - [%s] | "
1186  "Current Pose - \"%s\""),
1187  tempstr,
1188  markern);
1189  ED_area_status_text(pld->area, pld->headerstr);
1190  ED_workspace_status_text(C, TIP_("Use ScrollWheel or PageUp/Down to change pose"));
1191  }
1192  else {
1193  BLI_snprintf(pld->headerstr,
1194  sizeof(pld->headerstr),
1195  TIP_("PoseLib Previewing Pose: \"%s\""),
1196  pld->marker->name);
1197  ED_area_status_text(pld->area, pld->headerstr);
1199  }
1200  }
1201 
1202  /* request drawing of view + clear redraw flag */
1204  pld->redraw = PL_PREVIEW_NOREDRAW;
1205 }
1206 
1207 /* ---------------------------- */
1208 
1209 /* This helper function is called during poselib_preview_poses to find the
1210  * pose to preview next (after a change event)
1211  */
1213 {
1214  /* stop if not going anywhere, as we assume that there is a direction to move in */
1215  if (step == 0) {
1216  return;
1217  }
1218 
1219  /* search-string dictates a special approach */
1220  if (pld->searchstr[0]) {
1221  TimeMarker *marker;
1222  LinkData *ld, *ldn, *ldc;
1223 
1224  /* free and rebuild if needed (i.e. if search-str changed) */
1225  if (!STREQ(pld->searchstr, pld->searchold)) {
1226  /* free list of temporary search matches */
1227  BLI_freelistN(&pld->searchp);
1228 
1229  /* generate a new list of search matches */
1230  for (marker = pld->act->markers.first; marker; marker = marker->next) {
1231  /* does the name partially match?
1232  * - don't worry about case, to make it easier for users to quickly input a name (or
1233  * part of one), which is the whole point of this feature
1234  */
1235  if (BLI_strcasestr(marker->name, pld->searchstr)) {
1236  /* make link-data to store reference to it */
1237  ld = MEM_callocN(sizeof(LinkData), "PoseMatch");
1238  ld->data = marker;
1239  BLI_addtail(&pld->searchp, ld);
1240  }
1241  }
1242 
1243  /* set current marker to NULL (so that we start from first) */
1244  pld->marker = NULL;
1245  }
1246 
1247  /* check if any matches */
1248  if (BLI_listbase_is_empty(&pld->searchp)) {
1249  pld->marker = NULL;
1250  return;
1251  }
1252 
1253  /* find first match */
1254  for (ldc = pld->searchp.first; ldc; ldc = ldc->next) {
1255  if (ldc->data == pld->marker) {
1256  break;
1257  }
1258  }
1259  if (ldc == NULL) {
1260  ldc = pld->searchp.first;
1261  }
1262 
1263  /* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate
1264  * until step == 0. At this point, marker should be the correct marker.
1265  */
1266  if (step > 0) {
1267  for (ld = ldc; ld && step; ld = ldn, step--) {
1268  ldn = (ld->next) ? ld->next : pld->searchp.first;
1269  }
1270  }
1271  else {
1272  for (ld = ldc; ld && step; ld = ldn, step++) {
1273  ldn = (ld->prev) ? ld->prev : pld->searchp.last;
1274  }
1275  }
1276 
1277  /* set marker */
1278  if (ld) {
1279  pld->marker = ld->data;
1280  }
1281  }
1282  else {
1283  TimeMarker *marker, *next;
1284 
1285  /* if no marker, because we just ended searching, then set that to the start of the list */
1286  if (pld->marker == NULL) {
1287  pld->marker = pld->act->markers.first;
1288  }
1289 
1290  /* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate
1291  * until step == 0. At this point, marker should be the correct marker.
1292  */
1293  if (step > 0) {
1294  for (marker = pld->marker; marker && step; marker = next, step--) {
1295  next = (marker->next) ? marker->next : pld->act->markers.first;
1296  }
1297  }
1298  else {
1299  for (marker = pld->marker; marker && step; marker = next, step++) {
1300  next = (marker->prev) ? marker->prev : pld->act->markers.last;
1301  }
1302  }
1303 
1304  /* it should be fairly impossible for marker to be NULL */
1305  if (marker) {
1306  pld->marker = marker;
1307  }
1308  }
1309 }
1310 
1311 /* specially handle events for searching */
1312 static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, ushort event_type, char ascii)
1313 {
1314  /* try doing some form of string manipulation first */
1315  switch (event_type) {
1316  case EVT_BACKSPACEKEY:
1317  if (pld->searchstr[0] && pld->search_cursor) {
1318  short len = strlen(pld->searchstr);
1319  short index = pld->search_cursor;
1320  short i;
1321 
1322  for (i = index; i <= len; i++) {
1323  pld->searchstr[i - 1] = pld->searchstr[i];
1324  }
1325 
1326  pld->search_cursor--;
1327 
1328  poselib_preview_get_next(pld, 1);
1330  return;
1331  }
1332  break;
1333 
1334  case EVT_DELKEY:
1335  if (pld->searchstr[0] && pld->searchstr[1]) {
1336  short len = strlen(pld->searchstr);
1337  short index = pld->search_cursor;
1338  int i;
1339 
1340  if (index < len) {
1341  for (i = index; i < len; i++) {
1342  pld->searchstr[i] = pld->searchstr[i + 1];
1343  }
1344 
1345  poselib_preview_get_next(pld, 1);
1347  return;
1348  }
1349  }
1350  break;
1351  }
1352 
1353  if (ascii) {
1354  /* character to add to the string */
1355  short index = pld->search_cursor;
1356  short len = (pld->searchstr[0]) ? strlen(pld->searchstr) : 0;
1357  short i;
1358 
1359  if (len) {
1360  for (i = len; i > index; i--) {
1361  pld->searchstr[i] = pld->searchstr[i - 1];
1362  }
1363  }
1364  else {
1365  pld->searchstr[1] = 0;
1366  }
1367 
1368  pld->searchstr[index] = ascii;
1369  pld->search_cursor++;
1370 
1371  poselib_preview_get_next(pld, 1);
1373  }
1374 }
1375 
1376 /* handle events for poselib_preview_poses */
1378 {
1379  tPoseLib_PreviewData *pld = op->customdata;
1381 
1382  /* only accept 'press' event, and ignore 'release', so that we don't get double actions */
1383  if (ELEM(event->val, KM_PRESS, KM_NOTHING) == 0) {
1384 #if 0
1385  printf("PoseLib: skipping event with type '%s' and val %d\n",
1386  WM_key_event_string(event->type, false),
1387  event->val);
1388 #endif
1389  return ret;
1390  }
1391 
1392  /* backup stuff that needs to occur before every operation
1393  * - make a copy of searchstr, so that we know if cache needs to be rebuilt
1394  */
1395  BLI_strncpy(pld->searchold, pld->searchstr, sizeof(pld->searchold));
1396 
1397  /* if we're currently showing the original pose, only certain events are handled */
1398  if (pld->flag & PL_PREVIEW_SHOWORIGINAL) {
1399  switch (event->type) {
1400  /* exit - cancel */
1401  case EVT_ESCKEY:
1402  case RIGHTMOUSE:
1403  pld->state = PL_PREVIEW_CANCEL;
1404  break;
1405 
1406  /* exit - confirm */
1407  case LEFTMOUSE:
1408  case EVT_RETKEY:
1409  case EVT_PADENTER:
1410  case EVT_SPACEKEY:
1411  pld->state = PL_PREVIEW_CONFIRM;
1412  break;
1413 
1414  /* view manipulation */
1415  /* we add pass through here, so that the operators responsible for these can still run,
1416  * even though we still maintain control (as RUNNING_MODAL flag is still set too)
1417  */
1418  case EVT_PAD0:
1419  case EVT_PAD1:
1420  case EVT_PAD2:
1421  case EVT_PAD3:
1422  case EVT_PAD4:
1423  case EVT_PAD5:
1424  case EVT_PAD6:
1425  case EVT_PAD7:
1426  case EVT_PAD8:
1427  case EVT_PAD9:
1428  case EVT_PADPLUSKEY:
1429  case EVT_PADMINUS:
1430  case MIDDLEMOUSE:
1431  case MOUSEMOVE:
1432  // pld->redraw = PL_PREVIEW_REDRAWHEADER;
1434  break;
1435 
1436  /* Quickly compare to original. */
1437  case EVT_TABKEY:
1438  pld->flag &= ~PL_PREVIEW_SHOWORIGINAL;
1440  break;
1441  }
1442 
1443  /* EXITS HERE... */
1444  return ret;
1445  }
1446 
1447  /* NORMAL EVENT HANDLING... */
1448  /* searching takes priority over normal activity */
1449  switch (event->type) {
1450  /* exit - cancel */
1451  case EVT_ESCKEY:
1452  case RIGHTMOUSE:
1453  pld->state = PL_PREVIEW_CANCEL;
1454  break;
1455 
1456  /* exit - confirm */
1457  case LEFTMOUSE:
1458  case EVT_RETKEY:
1459  case EVT_PADENTER:
1460  case EVT_SPACEKEY:
1461  pld->state = PL_PREVIEW_CONFIRM;
1462  break;
1463 
1464  /* Toggle between original pose and poselib pose. */
1465  case EVT_TABKEY:
1466  pld->flag |= PL_PREVIEW_SHOWORIGINAL;
1468  break;
1469 
1470  /* change to previous pose (cyclic) */
1471  case EVT_PAGEUPKEY:
1472  case WHEELUPMOUSE:
1473  poselib_preview_get_next(pld, -1);
1475  break;
1476 
1477  /* change to next pose (cyclic) */
1478  case EVT_PAGEDOWNKEY:
1479  case WHEELDOWNMOUSE:
1480  poselib_preview_get_next(pld, 1);
1482  break;
1483 
1484  /* jump 5 poses (cyclic, back) */
1485  case EVT_DOWNARROWKEY:
1486  poselib_preview_get_next(pld, -5);
1488  break;
1489 
1490  /* jump 5 poses (cyclic, forward) */
1491  case EVT_UPARROWKEY:
1492  poselib_preview_get_next(pld, 5);
1494  break;
1495 
1496  /* change to next pose or searching cursor control */
1497  case EVT_RIGHTARROWKEY:
1498  if (pld->searchstr[0]) {
1499  /* move text-cursor to the right */
1500  if (pld->search_cursor < strlen(pld->searchstr)) {
1501  pld->search_cursor++;
1502  }
1504  }
1505  else {
1506  /* change to next pose (cyclic) */
1507  poselib_preview_get_next(pld, 1);
1509  }
1510  break;
1511 
1512  /* change to next pose or searching cursor control */
1513  case EVT_LEFTARROWKEY:
1514  if (pld->searchstr[0]) {
1515  /* move text-cursor to the left */
1516  if (pld->search_cursor) {
1517  pld->search_cursor--;
1518  }
1520  }
1521  else {
1522  /* change to previous pose (cyclic) */
1523  poselib_preview_get_next(pld, -1);
1525  }
1526  break;
1527 
1528  /* change to first pose or start of searching string */
1529  case EVT_HOMEKEY:
1530  if (pld->searchstr[0]) {
1531  pld->search_cursor = 0;
1533  }
1534  else {
1535  /* change to first pose */
1536  pld->marker = pld->act->markers.first;
1537  pld->act->active_marker = 1;
1538 
1540  }
1541  break;
1542 
1543  /* change to last pose or start of searching string */
1544  case EVT_ENDKEY:
1545  if (pld->searchstr[0]) {
1546  pld->search_cursor = strlen(pld->searchstr);
1548  }
1549  else {
1550  /* change to last pose */
1551  pld->marker = pld->act->markers.last;
1553 
1555  }
1556  break;
1557 
1558  /* view manipulation */
1559  /* we add pass through here, so that the operators responsible for these can still run,
1560  * even though we still maintain control (as RUNNING_MODAL flag is still set too)
1561  */
1562  case MIDDLEMOUSE:
1563  case MOUSEMOVE:
1564  // pld->redraw = PL_PREVIEW_REDRAWHEADER;
1566  break;
1567 
1568  /* view manipulation, or searching */
1569  case EVT_PAD0:
1570  case EVT_PAD1:
1571  case EVT_PAD2:
1572  case EVT_PAD3:
1573  case EVT_PAD4:
1574  case EVT_PAD5:
1575  case EVT_PAD6:
1576  case EVT_PAD7:
1577  case EVT_PAD8:
1578  case EVT_PAD9:
1579  case EVT_PADPLUSKEY:
1580  case EVT_PADMINUS:
1581  if (pld->searchstr[0]) {
1582  /* searching... */
1584  }
1585  else {
1586  /* view manipulation (see above) */
1587  // pld->redraw = PL_PREVIEW_REDRAWHEADER;
1589  }
1590  break;
1591 
1592  /* otherwise, assume that searching might be able to handle it */
1593  default:
1595  break;
1596  }
1597 
1598  return ret;
1599 }
1600 
1601 /* ---------------------------- */
1602 
1603 /* Init PoseLib Previewing data */
1605 {
1606  tPoseLib_PreviewData *pld;
1607  Object *ob = get_poselib_object(C);
1608  int pose_index = RNA_int_get(op->ptr, "pose_index");
1609 
1610  /* set up preview state info */
1611  op->customdata = pld = MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data");
1612 
1613  /* get basic data */
1614  pld->ob = ob;
1615  pld->arm = (ob) ? (ob->data) : NULL;
1616  pld->pose = (ob) ? (ob->pose) : NULL;
1617  pld->act = (ob) ? (ob->poselib) : NULL;
1618 
1619  pld->scene = CTX_data_scene(C);
1620  pld->area = CTX_wm_area(C);
1621 
1622  /* get starting pose based on RNA-props for this operator */
1623  if (pose_index == -1) {
1624  pld->marker = poselib_get_active_pose(pld->act);
1625  }
1626  else if (pose_index == -2) {
1627  pld->flag |= PL_PREVIEW_SHOWORIGINAL;
1628  }
1629  else {
1630  pld->marker = (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
1631  }
1632 
1633  /* check if valid poselib */
1634  if (ELEM(NULL, pld->ob, pld->pose, pld->arm)) {
1635  BKE_report(op->reports, RPT_ERROR, "Pose lib is only for armatures in pose mode");
1636  pld->state = PL_PREVIEW_ERROR;
1637  return;
1638  }
1639  if (pld->act == NULL) {
1640  BKE_report(op->reports, RPT_ERROR, "Object does not have a valid pose lib");
1641  pld->state = PL_PREVIEW_ERROR;
1642  return;
1643  }
1644  if (pld->marker == NULL) {
1645  if (pld->act->markers.first) {
1646  /* just use first one then... */
1647  pld->marker = pld->act->markers.first;
1648  if (pose_index > -2) {
1649  BKE_report(op->reports, RPT_WARNING, "Pose lib had no active pose");
1650  }
1651  }
1652  else {
1653  BKE_report(op->reports, RPT_ERROR, "Pose lib has no poses to preview/apply");
1654  pld->state = PL_PREVIEW_ERROR;
1655  return;
1656  }
1657  }
1658 
1659  /* get ID pointer for applying poses */
1660  RNA_id_pointer_create(&ob->id, &pld->rna_ptr);
1661 
1662  /* make backups for restoring pose */
1664 
1665  /* set flags for running */
1666  pld->state = PL_PREVIEW_RUNNING;
1668  pld->flag |= PL_PREVIEW_FIRSTTIME;
1669 
1670  /* set depsgraph flags */
1671  /* make sure the lock is set OK, unlock can be accidentally saved? */
1672  pld->pose->flag |= POSE_LOCKED;
1673  pld->pose->flag &= ~POSE_DO_UNLOCK;
1674 
1675  /* clear strings + search */
1676  pld->headerstr[0] = pld->searchstr[0] = pld->searchold[0] = '\0';
1677  pld->search_cursor = 0;
1678 }
1679 
1680 /* After previewing poses */
1682 {
1684  Scene *scene = pld->scene;
1685  Object *ob = pld->ob;
1686  bPose *pose = pld->pose;
1687  bAction *act = pld->act;
1688  TimeMarker *marker = pld->marker;
1689 
1690  /* redraw the header so that it doesn't show any of our stuff anymore */
1691  ED_area_status_text(pld->area, NULL);
1693 
1694  /* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
1695  pose->flag |= POSE_DO_UNLOCK;
1696 
1697  /* clear pose if canceled */
1698  if (pld->state == PL_PREVIEW_CANCEL) {
1700 
1702  }
1703  else if (pld->state == PL_PREVIEW_CONFIRM) {
1704  /* tag poses as appropriate */
1705  poselib_keytag_pose(C, scene, pld);
1706 
1707  /* change active pose setting */
1708  act->active_marker = BLI_findindex(&act->markers, marker) + 1;
1709  action_set_activemarker(act, marker, NULL);
1710 
1711  /* Update event for pose and deformation children */
1713 
1714  /* updates */
1715  if (IS_AUTOKEY_MODE(scene, NORMAL)) {
1716  // remake_action_ipos(ob->action);
1717  }
1718  }
1719 
1720  /* Request final redraw of the view. */
1722 
1723  /* free memory used for backups and searching */
1725  BLI_freelistN(&pld->searchp);
1726 
1727  /* free temp data for operator */
1728  MEM_freeN(pld);
1729  op->customdata = NULL;
1730 }
1731 
1732 /* End previewing operation */
1734 {
1735  tPoseLib_PreviewData *pld = op->customdata;
1736  int exit_state = pld->state;
1737 
1738  /* finish up */
1740 
1741  if (ELEM(exit_state, PL_PREVIEW_CANCEL, PL_PREVIEW_ERROR)) {
1742  return OPERATOR_CANCELLED;
1743  }
1744  return OPERATOR_FINISHED;
1745 }
1746 
1747 /* Cancel previewing operation (called when exiting Blender) */
1749 {
1750  poselib_preview_exit(C, op);
1751 }
1752 
1753 /* main modal status check */
1754 static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *event)
1755 {
1756  tPoseLib_PreviewData *pld = op->customdata;
1757  int ret;
1758 
1759  /* 1) check state to see if we're still running */
1760  if (pld->state != PL_PREVIEW_RUNNING) {
1761  return poselib_preview_exit(C, op);
1762  }
1763 
1764  /* 2) handle events */
1765  ret = poselib_preview_handle_event(C, op, event);
1766 
1767  /* 3) apply changes and redraw, otherwise, confirming goes wrong */
1768  if (pld->redraw) {
1769  poselib_preview_apply(C, op);
1770  }
1771 
1772  return ret;
1773 }
1774 
1775 /* Modal Operator init */
1776 static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
1777 {
1778  tPoseLib_PreviewData *pld;
1779 
1780  /* check if everything is ok, and init settings for modal operator */
1782  pld = (tPoseLib_PreviewData *)op->customdata;
1783 
1784  if (pld->state == PL_PREVIEW_ERROR) {
1785  /* an error occurred, so free temp mem used */
1787  return OPERATOR_CANCELLED;
1788  }
1789 
1790  /* do initial apply to have something to look at */
1791  poselib_preview_apply(C, op);
1792 
1793  /* add temp handler if we're running as a modal operator */
1795 
1796  return OPERATOR_RUNNING_MODAL;
1797 }
1798 
1799 /* Repeat operator */
1801 {
1802  tPoseLib_PreviewData *pld;
1803 
1804  /* check if everything is ok, and init settings for modal operator */
1806  pld = (tPoseLib_PreviewData *)op->customdata;
1807 
1808  if (pld->state == PL_PREVIEW_ERROR) {
1809  /* an error occurred, so free temp mem used */
1811  return OPERATOR_CANCELLED;
1812  }
1813 
1814  /* the exec() callback is effectively a 'run-once' scenario, so set the state to that
1815  * so that everything draws correctly
1816  */
1817  pld->state = PL_PREVIEW_RUNONCE;
1818 
1819  /* apply the active pose */
1820  poselib_preview_apply(C, op);
1821 
1822  /* now, set the status to exit */
1823  pld->state = PL_PREVIEW_CONFIRM;
1824 
1825  /* cleanup */
1826  return poselib_preview_exit(C, op);
1827 }
1828 
1830 {
1831  /* identifiers */
1832  ot->name = "Legacy PoseLib Browse Poses";
1833  ot->idname = "POSELIB_OT_browse_interactive";
1834  ot->description =
1835  "Deprecated, will be removed in Blender 3.3. "
1836  "Interactively browse Legacy Pose Library poses in 3D-View";
1837 
1838  /* callbacks */
1844 
1845  /* flags */
1847 
1848  /* properties */
1849  /* TODO: make the pose_index into a proper enum instead of a cryptic int. */
1850  ot->prop = RNA_def_int(
1851  ot->srna,
1852  "pose_index",
1853  -1,
1854  -2,
1855  INT_MAX,
1856  "Pose",
1857  "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)",
1858  0,
1859  INT_MAX);
1860 
1861  /* XXX: percentage vs factor? */
1862  /* not used yet */
1863 #if 0
1865  "blend_factor",
1866  1.0f,
1867  0.0f,
1868  1.0f,
1869  "Blend Factor",
1870  "Amount that the pose is applied on top of the existing poses",
1871  0.0f,
1872  1.0f);
1873 #endif
1874 }
1875 
1877 {
1878  /* identifiers */
1879  ot->name = "Apply Legacy Pose Library Pose";
1880  ot->idname = "POSELIB_OT_apply_pose";
1881  ot->description =
1882  "Deprecated, will be removed in Blender 3.3. "
1883  "Apply specified Legacy Pose Library pose to the rig";
1884 
1885  /* callbacks */
1888 
1889  /* flags */
1891 
1892  /* properties */
1893  /* TODO: make the pose_index into a proper enum instead of a cryptic int... */
1894  ot->prop = RNA_def_int(
1895  ot->srna,
1896  "pose_index",
1897  -1,
1898  -2,
1899  INT_MAX,
1900  "Pose",
1901  "Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose)",
1902  0,
1903  INT_MAX);
1904 }
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
bool BKE_pose_is_layer_visible(const struct bArmature *arm, const struct bPoseChannel *pchan)
struct bAction * BKE_action_add(struct Main *bmain, const char name[])
Definition: action.c:332
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time)
Definition: anim_sys.c:761
void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, struct bActionGroup *agrp, const struct AnimationEvalContext *anim_eval_context)
AnimationEvalContext BKE_animsys_eval_context_construct_at(const AnimationEvalContext *anim_eval_context, float eval_time)
Definition: anim_sys.c:771
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
void BKE_fcurve_handles_recalc(struct FCurve *fcu)
Definition: fcurve.c:1303
void BKE_fcurve_delete_key(struct FCurve *fcu, int index)
Definition: fcurve.c:1661
void IDP_FreeProperty(struct IDProperty *prop)
Definition: idprop.c:1093
void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL()
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BKE_id_is_editable(const struct Main *bmain, const struct ID *id)
void id_us_min(struct ID *id)
Definition: lib_id.c:313
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.cc:2511
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE 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 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 void void bool BLI_listbase_link_move(ListBase *listbase, void *vlink, int step) ATTR_NONNULL()
Definition: listbase.c:405
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:538
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
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
unsigned int uint
Definition: BLI_sys_types.h:67
unsigned short ushort
Definition: BLI_sys_types.h:68
#define UNUSED(x)
#define IS_EQ(a, b)
#define ELEM(...)
#define IS_EQF(a, b)
#define STREQ(a, b)
#define TIP_(msgid)
#define IFACE_(msgid)
#define DATA_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ ID_OB
Definition: DNA_ID_enums.h:47
@ POSE_LOCKED
@ POSE_DO_UNLOCK
@ BONE_SELECTED
@ BONE_HIDDEN_P
Object is a sort of wrapper for general info.
@ SPACE_PROPERTIES
@ OPERATOR_CANCELLED
@ OPERATOR_INTERFACE
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ ALE_GROUP
Definition: ED_anim_api.h:259
@ BEZT_OK_FRAMERANGE
short(* KeyframeEditFunc)(KeyframeEditData *ked, struct BezTriple *bezt)
#define IS_AUTOKEY_MODE(scene, mode)
@ MODIFYKEY_MODE_INSERT
#define ANIM_KS_WHOLE_CHARACTER_ID
#define ANIM_KS_WHOLE_CHARACTER_SELECTED_ID
struct Object * ED_object_context(const struct bContext *C)
bool ED_operator_posemode(struct bContext *C)
Definition: screen_ops.c:530
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:792
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:816
Read Guarded memory(de)allocation.
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 NORMAL
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:294
#define C
Definition: RandGen.cpp:25
void uiItemIntO(uiLayout *layout, const char *name, int icon, const char *opname, const char *propname, int value)
struct uiLayout * UI_popup_menu_layout(uiPopupMenu *pup)
void uiItemFullO_ptr(uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, struct IDProperty *properties, wmOperatorCallContext context, int flag, struct PointerRNA *r_opptr)
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:91
void UI_popup_menu_end(struct bContext *C, struct uiPopupMenu *pup)
void uiItemMenuF(uiLayout *layout, const char *name, int icon, uiMenuCreateFunc func, void *arg)
void uiLayoutSetOperatorContext(uiLayout *layout, wmOperatorCallContext opcontext)
uiPopupMenu * UI_popup_menu_begin(struct bContext *C, const char *title, int icon) ATTR_NONNULL()
@ KM_NOTHING
Definition: WM_types.h:266
@ KM_PRESS
Definition: WM_types.h:267
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_ANIMATION
Definition: WM_types.h:338
#define ND_POSE
Definition: WM_types.h:407
#define NA_EDITED
Definition: WM_types.h:523
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
#define ND_KEYFRAME
Definition: WM_types.h:442
#define NC_OBJECT
Definition: WM_types.h:329
__forceinline ssef low(const avxf &a)
Definition: avxf.h:264
__forceinline ssef high(const avxf &a)
Definition: avxf.h:268
Scene scene
const Depsgraph * depsgraph
int len
Definition: draw_manager.c:108
short ANIM_animchanneldata_keyframes_loop(KeyframeEditData *ked, bDopeSheet *ads, void *data, int keytype, KeyframeEditFunc key_ok, KeyframeEditFunc key_cb, FcuEditFunc fcu_cb)
KeyframeEditFunc ANIM_editkeyframes_ok(short mode)
AnimKeylist * ED_keylist_create()
void ED_keylist_free(AnimKeylist *keylist)
void action_to_keylist(AnimData *adt, bAction *act, AnimKeylist *keylist, const int saction_flag)
const struct ListBase * ED_keylist_listbase(const AnimKeylist *keylist)
bool autokeyframe_cfra_can_key(const Scene *scene, ID *id)
Definition: keyframing.c:2850
int ANIM_apply_keyingset(bContext *C, ListBase *dsources, bAction *act, KeyingSet *ks, short mode, float cfra)
Definition: keyingsets.c:1038
KeyingSet * ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *transformKSName)
Definition: keyingsets.c:696
KeyingSet * ANIM_builtin_keyingset_get_named(KeyingSet *prevKS, const char name[])
Definition: keyingsets.c:531
void ANIM_relative_keyingset_add_source(ListBase *dsources, ID *id, StructRNA *srna, void *data)
Definition: keyingsets.c:924
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static ulong * next
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
static void area(int d1, int d2, int e1, int e2, float weights[2])
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static int poselib_preview_exec(bContext *C, wmOperator *op)
Definition: pose_lib.c:1800
static int poselib_new_exec(bContext *C, wmOperator *UNUSED(op))
Definition: pose_lib.c:213
static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_lib.c:669
static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData *pld)
Definition: pose_lib.c:1088
static int poselib_move_exec(bContext *C, wmOperator *op)
Definition: pose_lib.c:763
void POSELIB_OT_pose_rename(wmOperatorType *ot)
Definition: pose_lib.c:734
static bool poselib_add_poll(bContext *C)
Definition: pose_lib.c:377
static void action_set_activemarker(void *UNUSED(a), void *UNUSED(b), void *UNUSED(c))
Definition: pose_lib.c:61
void POSELIB_OT_pose_remove(wmOperatorType *ot)
Definition: pose_lib.c:643
void POSELIB_OT_pose_add(wmOperatorType *ot)
Definition: pose_lib.c:522
struct tPoseLib_PreviewData tPoseLib_PreviewData
static void poselib_preview_cancel(bContext *C, wmOperator *op)
Definition: pose_lib.c:1748
static Object * get_poselib_object(bContext *C)
Definition: pose_lib.c:144
static int poselib_preview_exit(bContext *C, wmOperator *op)
Definition: pose_lib.c:1733
static int poselib_sanitize_exec(bContext *C, wmOperator *op)
Definition: pose_lib.c:293
static bAction * poselib_init_new(Main *bmain, Object *ob)
Definition: pose_lib.c:180
static void poselib_preview_init_data(bContext *C, wmOperator *op)
Definition: pose_lib.c:1604
static void poselib_add_menu_invoke__replacemenu(bContext *C, uiLayout *layout, void *UNUSED(arg))
Definition: pose_lib.c:395
static int poselib_add_exec(bContext *C, wmOperator *op)
Definition: pose_lib.c:465
static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: pose_lib.c:418
void POSELIB_OT_apply_pose(wmOperatorType *ot)
Definition: pose_lib.c:1876
static bool has_poselib_pose_data_poll(bContext *C)
Definition: pose_lib.c:162
void POSELIB_OT_new(wmOperatorType *ot)
Definition: pose_lib.c:232
static void poselib_apply_pose(tPoseLib_PreviewData *pld, const AnimationEvalContext *anim_eval_context)
Definition: pose_lib.c:1025
static int poselib_rename_exec(bContext *C, wmOperator *op)
Definition: pose_lib.c:697
@ PL_PREVIEW_RUNNING
Definition: pose_lib.c:903
@ PL_PREVIEW_CONFIRM
Definition: pose_lib.c:904
@ PL_PREVIEW_CANCEL
Definition: pose_lib.c:905
@ PL_PREVIEW_RUNONCE
Definition: pose_lib.c:906
@ PL_PREVIEW_ERROR
Definition: pose_lib.c:902
void POSELIB_OT_unlink(wmOperatorType *ot)
Definition: pose_lib.c:270
static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: pose_lib.c:1776
static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, ushort event_type, char ascii)
Definition: pose_lib.c:1312
static int poselib_unlink_exec(bContext *C, wmOperator *UNUSED(op))
Definition: pose_lib.c:251
void POSELIB_OT_pose_move(wmOperatorType *ot)
Definition: pose_lib.c:812
static int poselib_get_free_index(bAction *act)
Definition: pose_lib.c:89
void POSELIB_OT_browse_interactive(wmOperatorType *ot)
Definition: pose_lib.c:1829
@ PL_PREVIEW_NOREDRAW
Definition: pose_lib.c:911
@ PL_PREVIEW_REDRAWHEADER
Definition: pose_lib.c:913
@ PL_PREVIEW_REDRAWALL
Definition: pose_lib.c:912
static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_lib.c:1754
static void poselib_preview_apply(bContext *C, wmOperator *op)
Definition: pose_lib.c:1127
void POSELIB_OT_action_sanitize(wmOperatorType *ot)
Definition: pose_lib.c:357
static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event)
Definition: pose_lib.c:1377
static const EnumPropertyItem * poselib_stored_pose_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
Definition: pose_lib.c:547
static void poselib_backup_posecopy(tPoseLib_PreviewData *pld)
Definition: pose_lib.c:936
static TimeMarker * poselib_get_active_pose(bAction *act)
Definition: pose_lib.c:134
static bool has_poselib_pose_data_for_editing_poll(bContext *C)
Definition: pose_lib.c:171
static int poselib_remove_exec(bContext *C, wmOperator *op)
Definition: pose_lib.c:580
static void poselib_backup_restore(tPoseLib_PreviewData *pld)
Definition: pose_lib.c:982
static void poselib_backup_free_data(tPoseLib_PreviewData *pld)
Definition: pose_lib.c:1001
struct tPoseLib_Backup tPoseLib_Backup
static bAction * poselib_validate(Main *bmain, Object *ob)
Definition: pose_lib.c:199
static void poselib_preview_cleanup(bContext *C, wmOperator *op)
Definition: pose_lib.c:1681
@ PL_PREVIEW_FIRSTTIME
Definition: pose_lib.c:918
@ PL_PREVIEW_SHOWORIGINAL
Definition: pose_lib.c:919
@ PL_PREVIEW_ANY_BONE_SELECTED
Definition: pose_lib.c:920
static void poselib_preview_get_next(tPoseLib_PreviewData *pld, int step)
Definition: pose_lib.c:1212
return ret
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:4921
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_string_get(PointerRNA *ptr, const char *name, char *value)
Definition: rna_access.c:5116
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3402
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_float_factor(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:4144
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, int maxlen, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3687
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3597
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:26
float vec[3][3]
const char * identifier
Definition: RNA_types.h:461
void * data
Definition: DNA_listBase.h:26
struct LinkData * next
Definition: DNA_listBase.h:25
struct LinkData * prev
Definition: DNA_listBase.h:25
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct bAction * poselib
struct bPose * pose
void * data
struct RenderData r
char name[64]
struct TimeMarker * prev
struct TimeMarker * next
struct bActionGroup * next
ListBase curves
ListBase groups
ListBase markers
IDProperty * prop
struct Bone * bone
ListBase chanbase
short flag
bPoseChannel olddata
Definition: pose_lib.c:931
IDProperty * oldprops
Definition: pose_lib.c:932
struct tPoseLib_Backup * next
Definition: pose_lib.c:927
bPoseChannel * pchan
Definition: pose_lib.c:929
struct tPoseLib_Backup * prev
Definition: pose_lib.c:927
char searchstr[64]
Definition: pose_lib.c:891
PointerRNA rna_ptr
Definition: pose_lib.c:866
char headerstr[UI_MAX_DRAW_STR]
Definition: pose_lib.c:897
TimeMarker * marker
Definition: pose_lib.c:876
char searchold[64]
Definition: pose_lib.c:894
bArmature * arm
Definition: pose_lib.c:870
short val
Definition: WM_types.h:680
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
char WM_event_utf8_to_ascii(const struct wmEvent *event)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ EVT_PAD8
@ EVT_PAD2
@ RIGHTMOUSE
@ EVT_PAD4
@ EVT_PAD0
@ EVT_PAD9
@ EVT_DELKEY
@ EVT_TABKEY
@ EVT_DOWNARROWKEY
@ EVT_PAD3
@ WHEELUPMOUSE
@ EVT_PAGEUPKEY
@ EVT_PAGEDOWNKEY
@ EVT_RIGHTARROWKEY
@ EVT_PADENTER
@ EVT_SPACEKEY
@ WHEELDOWNMOUSE
@ EVT_PAD6
@ EVT_PAD5
@ EVT_HOMEKEY
@ MOUSEMOVE
@ EVT_ENDKEY
@ EVT_PADMINUS
@ EVT_UPARROWKEY
@ LEFTMOUSE
@ EVT_LEFTARROWKEY
@ MIDDLEMOUSE
@ EVT_ESCKEY
@ EVT_BACKSPACEKEY
@ EVT_PAD1
@ EVT_PAD7
@ EVT_PADPLUSKEY
@ EVT_RETKEY
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
const char * WM_key_event_string(const short type, const bool compact)
Definition: wm_keymap.c:1046
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
int WM_operator_props_popup_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))