New: Hotkey/menu access in 3D window to add constraints. Works in PoseMode
[blender.git] / source / blender / src / poseobject.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Ton Roosendaal, Blender Foundation '05, full recode.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * support for animation modes - Reevan McKay
27  */
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_arithb.h"
35 #include "BLI_blenlib.h"
36
37 #include "DNA_action_types.h"
38 #include "DNA_armature_types.h"
39 #include "DNA_constraint_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_meshdata_types.h"
42 #include "DNA_modifier_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_view3d_types.h"
47
48 #include "BKE_action.h"
49 #include "BKE_armature.h"
50 #include "BKE_constraint.h"
51 #include "BKE_deform.h"
52 #include "BKE_depsgraph.h"
53 #include "BKE_DerivedMesh.h"
54 #include "BKE_displist.h"
55 #include "BKE_global.h"
56 #include "BKE_modifier.h"
57 #include "BKE_object.h"
58 #include "BKE_utildefines.h"
59
60 #include "BIF_editarmature.h"
61 #include "BIF_editaction.h"
62 #include "BIF_editconstraint.h"
63 #include "BIF_editdeform.h"
64 #include "BIF_gl.h"
65 #include "BIF_graphics.h"
66 #include "BIF_interface.h"
67 #include "BIF_poseobject.h"
68 #include "BIF_meshtools.h"
69 #include "BIF_space.h"
70 #include "BIF_toolbox.h"
71 #include "BIF_screen.h"
72
73 #include "BDR_editobject.h"
74
75 #include "BSE_edit.h"
76 #include "BSE_editipo.h"
77 #include "BSE_trans_types.h"
78
79 #include "mydevice.h"
80 #include "blendef.h"
81
82 void enter_posemode(void)
83 {
84         Base *base;
85         Object *ob;
86         bArmature *arm;
87         
88         if(G.scene->id.lib) return;
89         base= BASACT;
90         if(base==NULL) return;
91         
92         ob= base->object;
93         
94         if (ob->id.lib){
95                 error ("Can't pose libdata");
96                 return;
97         }
98
99         switch (ob->type){
100         case OB_ARMATURE:
101                 arm= get_armature(ob);
102                 if( arm==NULL ) return;
103                 
104                 ob->flag |= OB_POSEMODE;
105                 base->flag= ob->flag;
106                 
107                 allqueue(REDRAWHEADERS, 0);     
108                 allqueue(REDRAWBUTSALL, 0);     
109                 allqueue(REDRAWOOPS, 0);
110                 allqueue(REDRAWVIEW3D, 0);
111                 break;
112         default:
113                 return;
114         }
115
116         if (G.obedit) exit_editmode(1);
117         G.f &= ~(G_VERTEXPAINT | G_FACESELECT | G_TEXTUREPAINT | G_WEIGHTPAINT);
118 }
119
120 void set_pose_keys (Object *ob)
121 {
122         bPoseChannel *chan;
123
124         if (ob->pose){
125                 for (chan=ob->pose->chanbase.first; chan; chan=chan->next){
126                         Bone *bone= chan->bone;
127                         if(bone && (bone->flag & BONE_SELECTED)) {
128                                 chan->flag |= POSE_KEY;         
129                         }
130                         else {
131                                 chan->flag &= ~POSE_KEY;
132                         }
133                 }
134         }
135 }
136
137
138 void exit_posemode(void)
139 {
140         Object *ob= OBACT;
141         Base *base= BASACT;
142
143         if(ob==NULL) return;
144         
145         ob->flag &= ~OB_POSEMODE;
146         base->flag= ob->flag;
147         
148         countall();
149         allqueue(REDRAWVIEW3D, 0);
150         allqueue(REDRAWOOPS, 0);
151         allqueue(REDRAWHEADERS, 0);     
152         allqueue(REDRAWBUTSALL, 0);     
153
154         scrarea_queue_headredraw(curarea);
155 }
156
157 /* called by buttons to find a bone to display/edit values for */
158 bPoseChannel *get_active_posechannel (Object *ob)
159 {
160         bPoseChannel *pchan;
161         
162         /* find active */
163         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
164                 if(pchan->bone && (pchan->bone->flag & BONE_ACTIVE))
165                         return pchan;
166         }
167         
168         return NULL;
169 }
170
171 int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
172 {
173         bConstraint *con;
174         Bone *bone;
175         
176         for(con= pchan->constraints.first; con; con= con->next) {
177                 if(con->type==CONSTRAINT_TYPE_KINEMATIC) return 1;
178         }
179         for(bone= pchan->bone->childbase.first; bone; bone= bone->next) {
180                 pchan= get_pose_channel(ob->pose, bone->name);
181                 if(pchan && pose_channel_in_IK_chain(ob, pchan))
182                         return 1;
183         }
184         return 0;
185 }
186
187 /* ********************************************** */
188
189 /* for the object with pose/action: create path curves for selected bones */
190 void pose_calculate_path(Object *ob)
191 {
192         bPoseChannel *pchan;
193         Base *base;
194         float *fp;
195         int cfra;
196         
197         if(ob==NULL || ob->pose==NULL)
198                 return;
199         
200         if(EFRA<=SFRA) return;
201         
202         DAG_object_update_flags(G.scene, ob, screen_view3d_layers());
203         
204         /* malloc the path blocks */
205         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
206                 if(pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
207                         pchan->pathlen= EFRA-SFRA;
208                         if(pchan->path)
209                                 MEM_freeN(pchan->path);
210                         pchan->path= MEM_callocN(3*pchan->pathlen*sizeof(float), "pchan path");
211                 }
212         }
213         
214         cfra= CFRA;
215         for(CFRA=SFRA; CFRA<EFRA; CFRA++) {
216                 
217                 /* do all updates */
218                 for(base= FIRSTBASE; base; base= base->next) {
219                         if(base->object->recalc) {
220                                 int temp= base->object->recalc;
221                                 object_handle_update(base->object);
222                                 base->object->recalc= temp;
223                         }
224                 }
225                 
226                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
227                         if(pchan->bone && (pchan->bone->flag & BONE_SELECTED)) {
228                                 if(pchan->path) {
229                                         fp= pchan->path+3*(CFRA-SFRA);
230                                         VECCOPY(fp, pchan->pose_tail);
231                                         Mat4MulVecfl(ob->obmat, fp);
232                                 }
233                         }
234                 }
235         }
236         
237         CFRA= cfra;
238         allqueue(REDRAWVIEW3D, 0);      /* recalc tags are still there */
239 }
240
241
242 /* for the object with pose/action: clear all path curves */
243 void pose_clear_paths(Object *ob)
244 {
245         bPoseChannel *pchan;
246         
247         if(ob==NULL || ob->pose==NULL)
248                 return;
249         
250         /* free the path blocks */
251         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
252                 if(pchan->path) {
253                         MEM_freeN(pchan->path);
254                         pchan->path= NULL;
255                 }
256         }
257         
258         allqueue(REDRAWVIEW3D, 0);
259 }
260
261
262
263 void pose_select_constraint_target(void)
264 {
265         Object *ob= OBACT;
266         bPoseChannel *pchan;
267         bConstraint *con;
268         
269         /* paranoia checks */
270         if(!ob && !ob->pose) return;
271         if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
272         
273         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
274                 if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
275                         
276                         for(con= pchan->constraints.first; con; con= con->next) {
277                                 char *subtarget;
278                                 Object *target= get_constraint_target(con, &subtarget);
279                                 
280                                 if(ob==target) {
281                                         if(subtarget) {
282                                                 bPoseChannel *pchanc= get_pose_channel(ob->pose, subtarget);
283                                                 pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
284                                         }
285                                 }
286                         }
287                 }
288         }
289         
290         allqueue (REDRAWVIEW3D, 0);
291         allqueue (REDRAWBUTSOBJECT, 0);
292         allqueue (REDRAWOOPS, 0);
293         
294         BIF_undo_push("Select constraint target");
295
296 }
297
298 /* context: active channel */
299 void pose_special_editmenu(void)
300 {
301         Object *ob= OBACT;
302         short nr;
303         
304         /* paranoia checks */
305         if(!ob && !ob->pose) return;
306         if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
307         
308         nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear All Paths%x4");
309         if(nr==1) {
310                 pose_select_constraint_target();
311         }
312         else if(nr==2) {
313                 pose_flip_names();
314         }
315         else if(nr==3) {
316                 pose_calculate_path(ob);
317         }
318         else if(nr==4) {
319                 pose_clear_paths(ob);
320         }
321 }
322
323 void pose_add_IK(void)
324 {
325         Object *ob= OBACT;
326         
327         /* paranoia checks */
328         if(!ob && !ob->pose) return;
329         if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
330         
331         add_constraint(1);      /* 1 means only IK */
332 }
333
334 /* context: all selected channels */
335 void pose_clear_IK(void)
336 {
337         Object *ob= OBACT;
338         bPoseChannel *pchan;
339         bConstraint *con;
340         bConstraint *next;
341         
342         /* paranoia checks */
343         if(!ob && !ob->pose) return;
344         if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
345         
346         if(okee("Remove IK constraint(s)")==0) return;
347
348         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
349                 if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
350                         
351                         for(con= pchan->constraints.first; con; con= next) {
352                                 next= con->next;
353                                 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
354                                         BLI_remlink(&pchan->constraints, con);
355                                         free_constraint_data(con);
356                                         MEM_freeN(con);
357                                 }
358                         }
359                         pchan->constflag &= ~PCHAN_HAS_IK;
360                 }
361         }
362         
363         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
364         
365         allqueue (REDRAWVIEW3D, 0);
366         allqueue (REDRAWBUTSOBJECT, 0);
367         allqueue (REDRAWOOPS, 0);
368         
369         BIF_undo_push("Remove IK constraint(s)");
370 }
371
372 void pose_clear_constraints(void)
373 {
374         Object *ob= OBACT;
375         bPoseChannel *pchan;
376         
377         /* paranoia checks */
378         if(!ob && !ob->pose) return;
379         if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
380         
381         if(okee("Remove Constraints")==0) return;
382         
383         /* find active */
384         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
385                 if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
386                         free_constraints(&pchan->constraints);
387                         pchan->constflag= 0;
388                 }
389         }
390         
391         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
392         
393         allqueue (REDRAWVIEW3D, 0);
394         allqueue (REDRAWBUTSOBJECT, 0);
395         allqueue (REDRAWOOPS, 0);
396         
397         BIF_undo_push("Remove Constraint(s)");
398         
399 }
400
401
402 void pose_copy_menu(void)
403 {
404         Object *ob= OBACT;
405         bPoseChannel *pchan, *pchanact;
406         short nr;
407         
408         /* paranoia checks */
409         if(!ob && !ob->pose) return;
410         if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
411         
412         /* find active */
413         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
414                 if(pchan->bone->flag & BONE_ACTIVE) break;
415         }
416         
417         if(pchan==NULL) return;
418         pchanact= pchan;
419         
420         nr= pupmenu("Copy Pose Attributes %t|Location%x1|Rotation%x2|Size%x3|Constraints");
421         
422         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
423                 if(pchan->bone->flag & BONE_SELECTED) {
424                         if(pchan!=pchanact) {
425                                 if(nr==1) {
426                                         VECCOPY(pchan->loc, pchanact->loc);
427                                 }
428                                 else if(nr==2) {
429                                         QUATCOPY(pchan->quat, pchanact->quat);
430                                 }
431                                 else if(nr==3) {
432                                         VECCOPY(pchan->size, pchanact->size);
433                                 }
434                                 else if(nr==4) {
435                                         free_constraints(&pchan->constraints);
436                                         copy_constraints(&pchan->constraints, &pchanact->constraints);
437                                         pchan->constflag = pchanact->constflag;
438                                 }
439                         }
440                 }
441         }
442         
443         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
444         
445         allqueue (REDRAWVIEW3D, 0);
446         allqueue (REDRAWBUTSOBJECT, 0);
447         allqueue (REDRAWOOPS, 0);
448         
449         BIF_undo_push("Copy Pose Attributes");
450         
451 }
452
453 /* ******************** copy/paste pose ********************** */
454
455 static bPose    *g_posebuf=NULL;
456
457 void free_posebuf(void) 
458 {
459         if (g_posebuf) {
460                 // was copied without constraints
461                 BLI_freelistN (&g_posebuf->chanbase);
462                 MEM_freeN (g_posebuf);
463         }
464         g_posebuf=NULL;
465 }
466
467 void copy_posebuf (void)
468 {
469         Object *ob= OBACT;
470
471         if (!ob || !ob->pose){
472                 error ("No Pose");
473                 return;
474         }
475
476         free_posebuf();
477         
478         set_pose_keys(ob);  // sets chan->flag to POSE_KEY if bone selected
479         copy_pose(&g_posebuf, ob->pose, 0);
480
481 }
482
483 void paste_posebuf (int flip)
484 {
485         Object *ob= OBACT;
486         bPoseChannel *chan, *pchan;
487         float eul[4];
488         char name[32];
489         
490         if (!ob || !ob->pose)
491                 return;
492
493         if (!g_posebuf){
494                 error ("Copy buffer is empty");
495                 return;
496         }
497         
498         /* Safely merge all of the channels in this pose into
499         any existing pose */
500         for (chan=g_posebuf->chanbase.first; chan; chan=chan->next){
501                 if (chan->flag & POSE_KEY) {
502                         BLI_strncpy(name, chan->name, sizeof(name));
503                         if (flip)
504                                 bone_flip_name (name, 0);               // 0 = don't strip off number extensions
505                                 
506                         /* only copy when channel exists, poses are not meant to add random channels to anymore */
507                         pchan= get_pose_channel(ob->pose, name);
508                         
509                         if(pchan) {
510                                 /* only loc rot size */
511                                 /* only copies transform info for the pose */
512                                 VECCOPY(pchan->loc, chan->loc);
513                                 VECCOPY(pchan->size, chan->size);
514                                 QUATCOPY(pchan->quat, chan->quat);
515                                 pchan->flag= chan->flag;
516                                 
517                                 if (flip){
518                                         pchan->loc[0]*= -1;
519
520                                         QuatToEul(pchan->quat, eul);
521                                         eul[1]*= -1;
522                                         eul[2]*= -1;
523                                         EulToQuat(eul, pchan->quat);
524                                 }
525
526                                 if (G.flags & G_RECORDKEYS){
527                                         ID *id= &ob->id;
528                                         /* Set keys on pose */
529                                         if (chan->flag & POSE_ROT){
530                                                 insertkey(id, ID_PO, chan->name, NULL, AC_QUAT_X);
531                                                 insertkey(id, ID_PO, chan->name, NULL, AC_QUAT_Y);
532                                                 insertkey(id, ID_PO, chan->name, NULL, AC_QUAT_Z);
533                                                 insertkey(id, ID_PO, chan->name, NULL, AC_QUAT_W);
534                                         }
535                                         if (chan->flag & POSE_SIZE){
536                                                 insertkey(id, ID_PO, chan->name, NULL, AC_SIZE_X);
537                                                 insertkey(id, ID_PO, chan->name, NULL, AC_SIZE_Y);
538                                                 insertkey(id, ID_PO, chan->name, NULL, AC_SIZE_Z);
539                                         }
540                                         if (chan->flag & POSE_LOC){
541                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X);
542                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y);
543                                                 insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z);
544                                         }
545                                 }
546                         }
547                 }
548         }
549
550         /* Update event for pose and deformation children */
551         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
552         
553         if (G.flags & G_RECORDKEYS) {
554                 remake_action_ipos(ob->action);
555                 allqueue (REDRAWIPO, 0);
556                 allqueue (REDRAWVIEW3D, 0);
557                 allqueue (REDRAWACTION, 0);             
558                 allqueue(REDRAWNLA, 0);
559         }
560         else {
561                 /* need to trick depgraph, action is not allowed to execute on pose */
562                 where_is_pose(ob);
563                 ob->recalc= 0;
564         }
565
566         BIF_undo_push("Paste Action Pose");
567 }
568
569 /* ********************************************** */
570
571 struct vgroup_map {
572         float head[3], tail[3];
573         Bone *bone;
574         bDeformGroup *dg, *dgflip;
575         Object *meshobj;
576 };
577
578 static void pose_adds_vgroups__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
579 {
580         struct vgroup_map *map= userData;
581         float vec[3], fac;
582         
583         VECCOPY(vec, co);
584         Mat4MulVecfl(map->meshobj->obmat, vec);
585                 
586         /* get the distance-factor from the vertex to bone */
587         fac= distfactor_to_bone (vec, map->head, map->tail, map->bone->rad_head, map->bone->rad_tail, map->bone->dist);
588         
589         /* add to vgroup. this call also makes me->dverts */
590         if(fac!=0.0f) 
591                 add_vert_to_defgroup (map->meshobj, map->dg, index, fac, WEIGHT_REPLACE);
592         else
593                 remove_vert_defgroup (map->meshobj, map->dg, index);
594         
595         if(map->dgflip) {
596                 int j= mesh_get_x_mirror_vert(map->meshobj, index);
597                 if(j>=0) {
598                         if(fac!=0.0f) 
599                                 add_vert_to_defgroup (map->meshobj, map->dgflip, j, fac, WEIGHT_REPLACE);
600                         else
601                                 remove_vert_defgroup (map->meshobj, map->dgflip, j);
602                 }
603         }
604 }
605
606 /* context weightpaint and deformer in posemode */
607 void pose_adds_vgroups(Object *meshobj)
608 {
609         extern VPaint Gwp;         /* from vpaint */
610         struct vgroup_map map;
611         DerivedMesh *dm;
612         Object *poseobj= modifiers_isDeformedByArmature(meshobj);
613         bPoseChannel *pchan;
614         Bone *bone;
615         bDeformGroup *dg, *curdef;
616         int DMneedsFree;
617         
618         if(poseobj==NULL || (poseobj->flag & OB_POSEMODE)==0) return;
619         
620         dm = mesh_get_derived_final(meshobj, &DMneedsFree);
621         
622         map.meshobj= meshobj;
623         
624         for(pchan= poseobj->pose->chanbase.first; pchan; pchan= pchan->next) {
625                 bone= pchan->bone;
626                 if(bone->flag & (BONE_SELECTED)) {
627                         
628                         /* check if mesh has vgroups */
629                         dg= get_named_vertexgroup(meshobj, bone->name);
630                         if(dg==NULL)
631                                 dg= add_defgroup_name(meshobj, bone->name);
632                         
633                         /* flipped bone */
634                         if(Gwp.flag & VP_MIRROR_X) {
635                                 char name[32];
636                                 
637                                 BLI_strncpy(name, dg->name, 32);
638                                 bone_flip_name(name, 0);                // 0 = don't strip off number extensions
639                                 
640                                 for (curdef = meshobj->defbase.first; curdef; curdef=curdef->next)
641                                         if (!strcmp(curdef->name, name))
642                                                 break;
643                                 map.dgflip= curdef;
644                         }
645                         else map.dgflip= NULL;
646                         
647                         /* get the root of the bone in global coords */
648                         VECCOPY(map.head, bone->arm_head);
649                         Mat4MulVecfl(poseobj->obmat, map.head);
650                         
651             /* get the tip of the bone in global coords */
652                         VECCOPY(map.tail, bone->arm_tail);
653             Mat4MulVecfl(poseobj->obmat, map.tail);
654                         
655                         /* use the optimal vertices instead of mverts */
656                         map.dg= dg;
657                         map.bone= bone;
658                         if(dm->foreachMappedVert) 
659                                 dm->foreachMappedVert(dm, pose_adds_vgroups__mapFunc, (void*) &map);
660                         else {
661                                 Mesh *me= meshobj->data;
662                                 int i;
663                                 for(i=0; i<me->totvert; i++) 
664                                         pose_adds_vgroups__mapFunc(&map, i, (me->mvert+i)->co, NULL, NULL);
665                         }
666                         
667                 }
668         }
669         
670         if (DMneedsFree) dm->release(dm);
671
672         allqueue(REDRAWVIEW3D, 0);
673         allqueue(REDRAWBUTSEDIT, 0);
674         
675         DAG_object_flush_update(G.scene, meshobj, OB_RECALC_DATA);      // and all its relations
676
677 }
678
679 /* ********************************************** */
680
681 /* context active object */
682 void pose_flip_names(void)
683 {
684         Object *ob= OBACT;
685         bPoseChannel *pchan;
686         char newname[32];
687         
688         /* paranoia checks */
689         if(!ob && !ob->pose) return;
690         if(ob==G.obedit || (ob->flag & OB_POSEMODE)==0) return;
691         
692         for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
693                 if(pchan->bone->flag & (BONE_ACTIVE|BONE_SELECTED)) {
694                         BLI_strncpy(newname, pchan->name, sizeof(newname));
695                         bone_flip_name(newname, 1);     // 1 = do strip off number extensions
696                         armature_bone_rename(ob->data, pchan->name, newname);
697                 }
698         }
699         
700         allqueue(REDRAWVIEW3D, 0);
701         allqueue(REDRAWBUTSEDIT, 0);
702         allqueue(REDRAWBUTSOBJECT, 0);
703         allqueue (REDRAWACTION, 0);
704         allqueue(REDRAWOOPS, 0);
705         BIF_undo_push("Flip names");
706         
707 }
708
709 /* context active object, or weightpainted object with armature in posemode */
710 void pose_activate_flipped_bone(void)
711 {
712         Object *ob= OBACT;
713         
714         if(ob==NULL) return;
715
716         if(G.f & G_WEIGHTPAINT) {
717                 ob= modifiers_isDeformedByArmature(ob);
718         }
719         if(ob && (ob->flag & OB_POSEMODE)) {
720                 bPoseChannel *pchan, *pchanf;
721                 
722                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
723                         if(pchan->bone->flag & BONE_ACTIVE) {
724                                 break;
725                         }
726                 }
727                 if(pchan) {
728                         char name[32];
729                         
730                         BLI_strncpy(name, pchan->name, 32);
731                         bone_flip_name(name, 1);        // 0 = do not strip off number extensions
732                         
733                         pchanf= get_pose_channel(ob->pose, name);
734                         if(pchanf && pchanf!=pchan) {
735                                 pchan->bone->flag &= ~(BONE_SELECTED|BONE_ACTIVE);
736                                 pchanf->bone->flag |= (BONE_SELECTED|BONE_ACTIVE);
737                         
738                                 /* in weightpaint we select the associated vertex group too */
739                                 if(G.f & G_WEIGHTPAINT) {
740                                         vertexgroup_select_by_name(OBACT, name);
741                                         DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
742                                 }
743                                 
744                                 select_actionchannel_by_name(ob->action, name, 1);
745                                 
746                                 allqueue(REDRAWVIEW3D, 0);
747                                 allqueue(REDRAWACTION, 0);
748                                 allqueue(REDRAWIPO, 0);         /* To force action/constraint ipo update */
749                                 allqueue(REDRAWBUTSEDIT, 0);
750                                 allqueue(REDRAWBUTSOBJECT, 0);
751                                 allqueue(REDRAWOOPS, 0);
752                         }                       
753                 }
754         }
755 }
756