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