9f5de3f34fa2397819e8243065f42d6015c3306c
[blender.git] / source / blender / blenkernel / intern / action.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34 #include <math.h>
35 #include <stdlib.h>     /* for NULL */
36
37 #include "MEM_guardedalloc.h"
38 #include "BLI_arithb.h"
39 #include "BLI_blenlib.h"
40
41 #include "BKE_action.h"
42 #include "BKE_global.h"
43 #include "BKE_main.h"
44 #include "BKE_utildefines.h"
45
46 #include "DNA_object_types.h"
47 #include "DNA_ipo_types.h"
48 #include "DNA_curve_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_action_types.h"
51 #include "DNA_nla_types.h"
52
53 #include "BKE_blender.h"
54 #include "BKE_ipo.h"
55 #include "BKE_object.h"
56 #include "BKE_library.h"
57 #include "BKE_anim.h"
58 #include "BKE_armature.h"
59
60 #include "nla.h"
61
62 #include "BKE_constraint.h"
63 #include "DNA_constraint_types.h"
64
65 /* Local function prototypes */
66 static 
67         void 
68 do_pose_constraint_channels(
69         bPose *pose,
70         bAction *act,
71         float ctime
72 );
73
74 static 
75         void 
76 get_constraint_influence_from_pose (
77         bPose *dst,
78         bPose *src
79 );
80
81 static 
82         void 
83 blend_constraints(
84         ListBase *dst, 
85         const ListBase *src, 
86         float srcweight, 
87         short mode
88 );
89
90 static 
91         void 
92 rest_pose (
93         bPose *pose,
94         int clearflag
95 );
96
97 /* Implementation */
98
99         bPoseChannel *
100 get_pose_channel (
101         const bPose *pose, 
102         const char *name
103 ){
104         bPoseChannel *chan;
105
106         for (chan=pose->chanbase.first; chan; chan=chan->next){
107                 if (!strcmp (chan->name, name))
108                         return chan;
109         }
110
111         return NULL;
112 }
113
114 static 
115         void 
116 rest_pose (
117         bPose *pose,
118         int clearflag
119 ){
120         bPoseChannel *chan;
121         int i;
122
123         if (!pose)
124                 return;
125
126         for (chan=pose->chanbase.first; chan; chan=chan->next){
127                 for (i=0; i<3; i++){
128                         chan->loc[i]=0.0;
129                         chan->quat[i+1]=0.0;
130                         chan->size[i]=1.0;
131                 }
132                 chan->quat[0]=1.0;
133                 if (clearflag)
134                         chan->flag =0;
135         }
136 }
137
138 static 
139         void 
140 blend_constraints(
141         ListBase *dst, 
142         const ListBase *src, 
143         float srcweight, 
144         short mode
145 ){
146         bConstraint *dcon;
147         const bConstraint *scon;
148         float dstweight;
149
150         switch (mode){
151         case POSE_BLEND:
152                 dstweight = 1.0F - srcweight;
153                 break;
154         case POSE_ADD:
155                 dstweight = 1.0F;
156                 break;
157         }
158
159         /* Blend constraints */
160         for (dcon=dst->first; dcon; dcon=dcon->next){
161                 for (scon = src->first; scon; scon=scon->next){
162                         if (!strcmp(scon->name, dcon->name))
163                                 break;
164                 }
165                 
166                 if (scon){
167                         dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight);
168                         if (mode == POSE_BLEND)
169                                 dcon->enforce/=2.0;
170                         
171                         if (dcon->enforce>1.0)
172                                 dcon->enforce=1.0;
173                         if (dcon->enforce<0.0)
174                                 dcon->enforce=0.0;
175
176                 }
177         }
178 }
179
180         void 
181 blend_poses (
182         bPose *dst, 
183         const bPose *src, 
184         float srcweight, 
185         short mode
186 ){
187         bPoseChannel *dchan;
188         const bPoseChannel *schan;
189         float   dquat[4], squat[4], mat[3][3];
190         float dstweight;
191         int i;
192         
193         switch (mode){
194         case POSE_BLEND:
195                 dstweight = 1.0F - srcweight;
196                 break;
197         case POSE_ADD:
198                 dstweight = 1.0F;
199                 break;
200         default :
201                 dstweight = 1.0F;
202         }
203         
204         for (dchan = dst->chanbase.first; dchan; dchan=dchan->next){
205                 schan = get_pose_channel(src, dchan->name);
206                 if (schan){
207                         if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)){
208                                 
209                                 /* Convert both quats to matrices and then back again. 
210                                  * This prevents interpolation problems
211                                  * This sucks because it is slow and stupid
212                                  */
213                                 
214                                 QuatToMat3(dchan->quat, mat);
215                                 Mat3ToQuat(mat, dquat);
216                                 QuatToMat3(schan->quat, mat);
217                                 Mat3ToQuat(mat, squat);
218                                 
219                                 /* Do the transformation blend */
220                                 for (i=0; i<3; i++){
221                                         if (schan->flag & POSE_LOC)
222                                                 dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
223                                         if (schan->flag & POSE_SIZE)
224                                                 dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
225                                         if (schan->flag & POSE_ROT)
226                                                 dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
227                                 }
228                                 
229                                 /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
230                                 if (schan->flag & POSE_ROT)
231                                         dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
232                                 if (mode==POSE_BLEND)
233                                         NormalQuat (dchan->quat);
234                                 dchan->flag |= schan->flag;
235                         }
236                 }
237         }
238 }
239
240         void 
241 clear_pose_constraint_status (
242         Object *ob
243 ){
244         bPoseChannel *chan;
245
246         if (!ob)
247                 return;
248         if (!ob->pose)
249                 return;
250
251         for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
252                 chan->flag &= ~PCHAN_DONE;
253         }
254 }
255
256         float 
257 calc_action_start (
258         const bAction *act
259 ){
260         const bActionChannel *chan;
261         const IpoCurve  *icu;
262         float size=999999999.0f;
263         int     i;
264         int     foundvert=0;
265         const bConstraintChannel *conchan;
266
267
268         if (!act)
269                 return 0;
270
271         for (chan=act->chanbase.first; chan; chan=chan->next){
272                 for (icu=chan->ipo->curve.first; icu; icu=icu->next)
273                         for (i=0; i<icu->totvert; i++){
274                                 size = MIN2 (size, icu->bezt[i].vec[1][0]);
275                                 foundvert=1;
276                                 
277                         }
278                         for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
279                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
280                                         for (i=0; i<icu->totvert; i++){
281                                                 size = MIN2 (size, icu->bezt[i].vec[1][0]);
282                                                 foundvert=1;
283                                         }
284                         }
285         }
286         
287         if (!foundvert)
288                 return 0;
289         else
290                 return size;
291 }
292
293         float 
294 calc_action_end (
295         const bAction *act
296 ){
297         const bActionChannel    *chan;
298         const bConstraintChannel *conchan;
299         const IpoCurve          *icu;
300         float size=0;
301         int     i;
302
303         if (!act)
304                 return 0;
305
306         for (chan=act->chanbase.first; chan; chan=chan->next){
307                 for (icu=chan->ipo->curve.first; icu; icu=icu->next)
308                         for (i=0; i<icu->totvert; i++)
309                                 size = MAX2 (size, icu->bezt[i].vec[1][0]);
310                         
311                         for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
312                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
313                                         for (i=0; i<icu->totvert; i++)
314                                                 size = MAX2 (size, icu->bezt[i].vec[1][0]);
315                         }
316         }
317         return size;
318 }
319
320         void 
321 verify_pose_channel (
322         bPose* pose, 
323         const char* name
324 ) {
325         bPoseChannel *chan;
326
327         if (!pose){
328                 return;
329         }
330
331         /*      See if this channel exists */
332         for (chan=pose->chanbase.first; chan; chan=chan->next){
333                 if (!strcmp (name, chan->name))
334                         return;
335         }
336
337         /* If not, create it and add it */
338         chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
339
340         strcpy (chan->name, name);
341         chan->loc[0] = chan->loc[1] = chan->loc[2] = 0.0F;
342         chan->quat[1] = chan->quat[2] = chan->quat[3] = 0.0F; chan->quat[0] = 1.0F;
343         chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
344
345         chan->flag |= POSE_ROT|POSE_SIZE|POSE_LOC;
346
347         BLI_addtail (&pose->chanbase, chan);
348 }
349
350         void 
351 get_pose_from_pose (
352         bPose **pose,
353         const bPose *src
354 ){
355         const bPoseChannel      *pchan;
356         bPoseChannel *newchan;
357
358         if (!src)
359                 return;
360         if (!pose)
361                 return;
362
363         /* If there is no pose, create one */
364         if (!*pose){
365                 *pose=MEM_callocN (sizeof(bPose), "pose");
366         }
367
368         /* Copy the data from the action into the pose */
369         for (pchan=src->chanbase.first; pchan; pchan=pchan->next){
370                 newchan = copy_pose_channel(pchan);
371                 verify_pose_channel(*pose, pchan->name);
372                 set_pose_channel(*pose, newchan);
373         }
374 }
375
376 static void get_constraint_influence_from_pose (bPose *dst, bPose *src)
377 {
378         bConstraint *dcon, *scon;
379
380         if (!src || !dst)
381                 return;
382
383         for (dcon = dst->chanbase.first; dcon; dcon=dcon->next){
384                 for (scon=src->chanbase.first; scon; scon=scon->next){
385                         if (!strcmp(scon->name, dcon->name))
386                                 break;
387                 }
388                 if (scon){
389                         dcon->enforce = scon->enforce;
390                 }
391         }
392 }
393
394 /* If the pose does not exist, a new one is created */
395
396         void 
397 get_pose_from_action (
398         bPose **pose,
399         bAction *act,
400         float ctime
401 ) {
402         bActionChannel *achan;
403         bPoseChannel    *pchan;
404         Ipo                             *ipo;
405         IpoCurve                *curve;
406         
407
408         if (!act)
409                 return;
410         if (!pose)
411                 return;
412
413         /* If there is no pose, create one */
414         if (!*pose){
415                 *pose=MEM_callocN (sizeof(bPose), "pose");
416         }
417
418         /* Copy the data from the action into the pose */
419         for (achan=act->chanbase.first; achan; achan=achan->next){
420                 act->achan= achan;
421
422                 ipo = achan->ipo;
423                 if (ipo){
424                         pchan=MEM_callocN (sizeof(bPoseChannel), "gpfa_poseChannel");
425                         strcpy (pchan->name, achan->name);
426
427                         act->pchan=pchan;
428                         /* Evaluates and sets the internal ipo value */
429                         calc_ipo(ipo, ctime);
430
431                         /* Set the pchan flags */
432                         for (curve = achan->ipo->curve.first; curve; curve=curve->next){
433                                 /*      Skip empty curves */
434                                 if (!curve->totvert)
435                                         continue;
436
437                                 switch (curve->adrcode){
438                                 case AC_QUAT_X:
439                                 case AC_QUAT_Y:
440                                 case AC_QUAT_Z:
441                                 case AC_QUAT_W:
442                                         pchan->flag |= POSE_ROT;
443                                         break;
444                                 case AC_LOC_X:
445                                 case AC_LOC_Y:
446                                 case AC_LOC_Z:
447                                         pchan->flag |= POSE_LOC;
448                                         break;
449                                 case AC_SIZE_X:
450                                 case AC_SIZE_Y:
451                                 case AC_SIZE_Z:
452                                         pchan->flag |= POSE_SIZE;
453                                         break;
454                                 }
455                         }
456
457                         execute_ipo((ID*)act, achan->ipo);
458                 
459                         set_pose_channel(*pose, pchan);
460                 }
461         }
462 }
463
464         void 
465 do_all_actions(
466 ){
467         Base *base;
468         bPose *apose=NULL;
469         bPose *tpose=NULL;
470         Object *ob;
471         bActionStrip *strip;
472         int     doit;
473         float striptime, frametime, length, actlength;
474         float blendfac, stripframe;
475
476         int set;
477
478         /* NEW: current scene ob ipo's */
479         base= G.scene->base.first;
480         set= 0;
481
482         while(base) {
483                 
484                 ob = base->object;
485
486                 /* Retrieve data from the NLA */
487                 if(ob->type==OB_ARMATURE){
488
489                         doit=0;
490
491                         /* Clear pose */
492                         if (apose){
493                                 clear_pose(apose);
494                                 MEM_freeN(apose);
495                         }
496                         /* Clear pose */
497                         if (tpose){
498                                 clear_pose(tpose);
499                                 MEM_freeN(tpose);
500                         }
501
502                         copy_pose(&apose, ob->pose, 1);
503                         copy_pose(&tpose, ob->pose, 1);
504                         rest_pose(apose, 1);
505  
506                         if (base->object->nlastrips.first){
507                                 rest_pose(base->object->pose, 0);
508                         }
509
510                         for (strip=base->object->nlastrips.first; strip; strip=strip->next){
511                                 doit = 0;
512                                 if (strip->act){
513                         
514                                         /* Determine if the current frame is within the strip's range */
515                                         length = strip->end-strip->start;
516                                         actlength = strip->actend-strip->actstart;
517                                         striptime = (G.scene->r.cfra-(strip->start)) / length;
518                                         stripframe = (G.scene->r.cfra-(strip->start)) ;
519
520
521                                         if (striptime>=0.0){
522                                                 
523                                                 rest_pose(tpose, 1);
524
525                                                 /* Handle path */
526                                                 if (strip->flag & ACTSTRIP_USESTRIDE){
527                                                         if (ob->parent && ob->parent->type==OB_CURVE){
528                                                                 Curve *cu = ob->parent->data;
529                                                                 float ctime, pdist;
530
531                                                                 if (cu->flag & CU_PATH){
532                                                                         /* Ensure we have a valid path */
533                                                                         if(cu->path==0 || cu->path->data==0) calc_curvepath(ob->parent);
534
535                                                                         /* Find the position on the path */
536                                                                         ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
537                                                                         
538                                                                         if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
539                                                                                 ctime /= cu->pathlen;
540                                                                                 CLAMP(ctime, 0.0, 1.0);
541                                                                         }
542                                                                         pdist = ctime*cu->path->totdist;
543                                                                         
544                                                                         if (strip->stridelen)
545                                                                                 striptime = pdist / strip->stridelen;
546                                                                         else
547                                                                                 striptime = 0;
548                                                                         
549                                                                         striptime = (float)fmod (striptime, 1.0);
550                                                                         
551                                                                         frametime = (striptime * actlength) + strip->actstart;
552                                                                         get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
553 #ifdef __NLA_BLENDCON
554                                                                         do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
555 #endif
556                                                                         doit=1;
557                                                                 }
558                                                         }
559                                                 }
560
561                                                 /* Handle repeat */
562                 
563                                                 else if (striptime < 1.0){
564                                                         /* Mod to repeat */
565                                                         striptime*=strip->repeat;
566                                                         striptime = (float)fmod (striptime, 1.0);
567                                                         
568                                                         frametime = (striptime * actlength) + strip->actstart;
569                                                         get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
570 #ifdef __NLA_BLENDCON
571                                                         do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
572 #endif
573                                                         doit=1;
574                                                 }
575                                                 /* Handle extend */
576                                                 else{
577                                                         if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
578                                                                 striptime = 1.0;
579                                                                 frametime = (striptime * actlength) + strip->actstart;
580                                                                 get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
581 #ifdef __NLA_BLENDCON
582                                                                 do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
583 #endif
584                                                                 doit=1;
585                                                         }
586                                                 }
587
588                                                 /* Handle blendin & blendout */
589                                                 if (doit){
590                                                         /* Handle blendin */
591
592                                                         if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){
593                                                                 blendfac = stripframe/strip->blendin;
594                                                         }
595                                                         else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){
596                                                                 blendfac = (length-stripframe)/(strip->blendout);
597                                                         }
598                                                         else
599                                                                 blendfac = 1;
600
601                                                         /* Blend this pose with the accumulated pose */
602                                                         blend_poses (apose, tpose, blendfac, strip->mode);
603 #ifdef __NLA_BLENDCON
604                                                         blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode);
605 #endif
606                                                 }
607                                         }                                       
608                                         if (apose){
609                                                 get_pose_from_pose(&ob->pose, apose);
610 #ifdef __NLA_BLENDCON
611                                                 get_constraint_influence_from_pose(ob->pose, apose);
612 #endif
613                                         }
614                                 }
615                                 
616                         }
617
618                         /* Do local action (always overrides the nla actions) */
619                         /*      At the moment, only constraint ipos on the local action have any effect */
620                         if(base->object->action) {
621                                 get_pose_from_action (&ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
622                                 do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
623                                 doit = 1;
624                         } 
625                         
626                         if (doit)
627                                 apply_pose_armature(get_armature(ob), ob->pose, 1);
628
629                 }
630                 base= base->next;
631                 if(base==0 && set==0 && G.scene->set) {
632                         set= 1;
633                         base= G.scene->set->base.first; 
634                 }
635                 
636         }
637
638         if (apose){
639                 clear_pose(apose);
640                 MEM_freeN(apose);
641                 apose = NULL;
642         }       
643         if (tpose){
644                 clear_pose(tpose);
645                 MEM_freeN(tpose);
646                 apose = NULL;
647         }
648
649 }
650
651 static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime)
652 {
653         bPoseChannel *pchan;
654         bActionChannel *achan;
655
656         if (!pose || !act)
657                 return;
658         
659         for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
660                 achan=get_named_actionchannel(act, pchan->name);
661                 if (achan)
662                         do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime);
663         }
664 }
665
666         bActionChannel *
667 get_named_actionchannel (
668         bAction *act,
669         const char *name
670 ){
671         bActionChannel *chan;
672
673         if (!act)
674                 return NULL;
675
676         for (chan = act->chanbase.first; chan; chan=chan->next){
677                 if (!strcmp (chan->name, name))
678                         return chan;
679         }
680
681         return NULL;
682 }
683
684         void 
685 clear_pose (
686         bPose *pose
687 ) {
688         bPoseChannel *chan;
689         
690         if (pose->chanbase.first){
691                 for (chan = pose->chanbase.first; chan; chan=chan->next){
692                         free_constraints(&chan->constraints);
693                 }
694                 BLI_freelistN (&pose->chanbase);
695         }
696 }
697
698         void 
699 make_local_action(
700         bAction *act
701 ){
702         Object *ob;
703         bAction *actn;
704         int local=0, lib=0;
705
706         if(act->id.lib==0) return;
707         if(act->id.us==1) {
708                 act->id.lib= 0;
709                 act->id.flag= LIB_LOCAL;
710                 new_id(0, (ID *)act, 0);
711                 return;
712         }
713         
714         ob= G.main->object.first;
715         while(ob) {
716                 if(ob->action==act) {
717                         if(ob->id.lib) lib= 1;
718                         else local= 1;
719                 }
720                 ob= ob->id.next;
721         }
722         
723         if(local && lib==0) {
724                 act->id.lib= 0;
725                 act->id.flag= LIB_LOCAL;
726                 new_id(0, (ID *)act, 0);
727         }
728         else if(local && lib) {
729                 actn= copy_action(act);
730                 actn->id.us= 0;
731                 
732                 ob= G.main->object.first;
733                 while(ob) {
734                         if(ob->action==act) {
735                                 
736                                 if(ob->id.lib==0) {
737                                         ob->action = actn;
738                                         ob->activecon = NULL;
739                                         actn->id.us++;
740                                         act->id.us--;
741                                 }
742                         }
743                         ob= ob->id.next;
744                 }
745         }
746 }
747
748
749         void 
750 free_action(
751         bAction *act
752 ){
753         bActionChannel *chan;
754
755         /* Free channels */
756         for (chan=act->chanbase.first; chan; chan=chan->next){
757                 if (chan->ipo)
758                         chan->ipo->id.us--;
759                 free_constraint_channels(&chan->constraintChannels);
760         }
761
762         if (act->chanbase.first)
763                 BLI_freelistN (&act->chanbase);
764 }
765
766         bAction* 
767 copy_action (
768         const bAction *src
769 ){
770         bAction *dst = NULL;
771         bActionChannel *dchan, *schan;
772         
773         if(!src) return NULL;
774         
775         dst= copy_libblock(src);
776         duplicatelist(&(dst->chanbase), &(src->chanbase));
777
778         for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
779                 dchan->ipo = copy_ipo(dchan->ipo);
780                 copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
781         }
782         dst->id.flag |= LIB_FAKEUSER;
783         dst->id.us++;
784         return dst;
785 }
786
787         bPoseChannel *
788 copy_pose_channel (
789         const bPoseChannel* src
790 ){
791         bPoseChannel *dst;
792
793         if (!src)
794                 return NULL;
795
796         dst = MEM_callocN (sizeof(bPoseChannel), "copyPoseChannel");
797         memcpy (dst, src, sizeof(bPoseChannel));
798         dst->prev=dst->next=NULL;
799
800         return dst;
801 }
802
803         void 
804 copy_pose(
805         bPose **dst, 
806         const bPose *src, 
807         int copycon
808 ){
809         bPose *outPose;
810         const bPose * inPose;
811         bPoseChannel    *newChan;
812         const bPoseChannel *curChan;
813
814         inPose = src;
815         
816         if (!inPose){
817                 *dst=NULL;
818                 return;
819         }
820
821         outPose=MEM_callocN(sizeof(bPose), "pose");
822
823         for (curChan=inPose->chanbase.first; curChan; curChan=curChan->next){
824                 newChan=MEM_callocN(sizeof(bPoseChannel), "copyposePoseChannel");
825
826                 strcpy (newChan->name, curChan->name);
827                 newChan->flag=curChan->flag;
828
829                 memcpy (newChan->loc, curChan->loc, sizeof (curChan->loc));
830                 memcpy (newChan->size, curChan->size, sizeof (curChan->size));
831                 memcpy (newChan->quat, curChan->quat, sizeof (curChan->quat));
832                 Mat4CpyMat4 (newChan->obmat, curChan->obmat);
833
834                 BLI_addtail (&outPose->chanbase, newChan);
835                 if (copycon){
836                         copy_constraints(&newChan->constraints, &curChan->constraints);
837                 }
838         }
839         
840         *dst=outPose;
841 }
842
843 bPoseChannel *set_pose_channel (bPose *pose, bPoseChannel *chan){
844         /*      chan is no longer valid for the calling function.
845                 and should not be used by that function after calling
846                 this one
847         */
848         bPoseChannel    *curChan;
849
850         /*      Determine if an equivalent channel exists already */
851         for (curChan=pose->chanbase.first; curChan; curChan=curChan->next){
852                 if (!strcmp (curChan->name, chan->name)){
853                         if (chan->flag & POSE_ROT)
854                                 memcpy (curChan->quat, chan->quat, sizeof(chan->quat)); 
855                         if (chan->flag & POSE_SIZE) 
856                                 memcpy (curChan->size, chan->size, sizeof(chan->size));
857                         if (chan->flag & POSE_LOC)
858                                 memcpy (curChan->loc, chan->loc, sizeof(chan->loc));
859                         if (chan->flag & PCHAN_DONE)
860                                 Mat4CpyMat4 (curChan->obmat, chan->obmat);
861
862                         curChan->flag |= chan->flag;
863                         MEM_freeN (chan);
864                         return curChan;
865                 }
866         }
867
868         MEM_freeN (chan);
869         return NULL;
870         /* If an equivalent channel doesn't exist, then don't bother setting it. */
871 }
872
873