some small optimizations
[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) {
222                                            if (POSE_LOC)
223                                                 dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
224                                            if (POSE_SIZE)
225                                                 dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
226                                            if (POSE_ROT)
227                                                 dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight);
228                                         }
229                                 }
230                                 
231                                 /* Do one more iteration for the quaternions only and normalize the quaternion if needed */
232                                 if (schan->flag & POSE_ROT)
233                                         dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight);
234                                 if (mode==POSE_BLEND)
235                                         NormalQuat (dchan->quat);
236                                 dchan->flag |= schan->flag;
237                         }
238                 }
239         }
240 }
241
242         void 
243 clear_pose_constraint_status (
244         Object *ob
245 ){
246         bPoseChannel *chan;
247
248         if (!ob)
249                 return;
250         if (!ob->pose)
251                 return;
252
253         for (chan = ob->pose->chanbase.first; chan; chan=chan->next){
254                 chan->flag &= ~PCHAN_DONE;
255         }
256 }
257
258         float 
259 calc_action_start (
260         const bAction *act
261 ){
262         const bActionChannel *chan;
263         const IpoCurve  *icu;
264         float size=999999999.0f;
265         int     i;
266         int     foundvert=0;
267         const bConstraintChannel *conchan;
268
269
270         if (!act)
271                 return 0;
272
273         for (chan=act->chanbase.first; chan; chan=chan->next){
274                 for (icu=chan->ipo->curve.first; icu; icu=icu->next)
275                         for (i=0; i<icu->totvert; i++){
276                                 size = MIN2 (size, icu->bezt[i].vec[1][0]);
277                                 foundvert=1;
278                                 
279                         }
280                         for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
281                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
282                                         for (i=0; i<icu->totvert; i++){
283                                                 size = MIN2 (size, icu->bezt[i].vec[1][0]);
284                                                 foundvert=1;
285                                         }
286                         }
287         }
288         
289         if (!foundvert)
290                 return 0;
291         else
292                 return size;
293 }
294
295         float 
296 calc_action_end (
297         const bAction *act
298 ){
299         const bActionChannel    *chan;
300         const bConstraintChannel *conchan;
301         const IpoCurve          *icu;
302         float size=0;
303         int     i;
304
305         if (!act)
306                 return 0;
307
308         for (chan=act->chanbase.first; chan; chan=chan->next){
309                 for (icu=chan->ipo->curve.first; icu; icu=icu->next)
310                         for (i=0; i<icu->totvert; i++)
311                                 size = MAX2 (size, icu->bezt[i].vec[1][0]);
312                         
313                         for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
314                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
315                                         for (i=0; i<icu->totvert; i++)
316                                                 size = MAX2 (size, icu->bezt[i].vec[1][0]);
317                         }
318         }
319         return size;
320 }
321
322         void 
323 verify_pose_channel (
324         bPose* pose, 
325         const char* name
326 ) {
327         bPoseChannel *chan;
328
329         if (!pose){
330                 return;
331         }
332
333         /*      See if this channel exists */
334         for (chan=pose->chanbase.first; chan; chan=chan->next){
335                 if (!strcmp (name, chan->name))
336                         return;
337         }
338
339         /* If not, create it and add it */
340         chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
341
342         strcpy (chan->name, name);
343         chan->loc[0] = chan->loc[1] = chan->loc[2] = 0.0F;
344         chan->quat[1] = chan->quat[2] = chan->quat[3] = 0.0F; chan->quat[0] = 1.0F;
345         chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
346
347         chan->flag |= POSE_ROT|POSE_SIZE|POSE_LOC;
348
349         BLI_addtail (&pose->chanbase, chan);
350 }
351
352         void 
353 get_pose_from_pose (
354         bPose **pose,
355         const bPose *src
356 ){
357         const bPoseChannel      *pchan;
358         bPoseChannel *newchan;
359
360         if (!src)
361                 return;
362         if (!pose)
363                 return;
364
365         /* If there is no pose, create one */
366         if (!*pose){
367                 *pose=MEM_callocN (sizeof(bPose), "pose");
368         }
369
370         /* Copy the data from the action into the pose */
371         for (pchan=src->chanbase.first; pchan; pchan=pchan->next){
372                 newchan = copy_pose_channel(pchan);
373                 verify_pose_channel(*pose, pchan->name);
374                 set_pose_channel(*pose, newchan);
375         }
376 }
377
378 static void get_constraint_influence_from_pose (bPose *dst, bPose *src)
379 {
380         bConstraint *dcon, *scon;
381
382         if (!src || !dst)
383                 return;
384
385         for (dcon = dst->chanbase.first; dcon; dcon=dcon->next){
386                 for (scon=src->chanbase.first; scon; scon=scon->next){
387                         if (!strcmp(scon->name, dcon->name))
388                                 break;
389                 }
390                 if (scon){
391                         dcon->enforce = scon->enforce;
392                 }
393         }
394 }
395
396 /* If the pose does not exist, a new one is created */
397
398         void 
399 get_pose_from_action (
400         bPose **pose,
401         bAction *act,
402         float ctime
403 ) {
404         bActionChannel *achan;
405         bPoseChannel    *pchan;
406         Ipo                             *ipo;
407         IpoCurve                *curve;
408         
409
410         if (!act)
411                 return;
412         if (!pose)
413                 return;
414
415         /* If there is no pose, create one */
416         if (!*pose){
417                 *pose=MEM_callocN (sizeof(bPose), "pose");
418         }
419
420         /* Copy the data from the action into the pose */
421         for (achan=act->chanbase.first; achan; achan=achan->next){
422                 act->achan= achan;
423
424                 ipo = achan->ipo;
425                 if (ipo){
426                         pchan=MEM_callocN (sizeof(bPoseChannel), "gpfa_poseChannel");
427                         strcpy (pchan->name, achan->name);
428
429                         act->pchan=pchan;
430                         /* Evaluates and sets the internal ipo value */
431                         calc_ipo(ipo, ctime);
432
433                         /* Set the pchan flags */
434                         for (curve = achan->ipo->curve.first; curve; curve=curve->next){
435                                 /*      Skip empty curves */
436                                 if (!curve->totvert)
437                                         continue;
438
439                                 switch (curve->adrcode){
440                                 case AC_QUAT_X:
441                                 case AC_QUAT_Y:
442                                 case AC_QUAT_Z:
443                                 case AC_QUAT_W:
444                                         pchan->flag |= POSE_ROT;
445                                         break;
446                                 case AC_LOC_X:
447                                 case AC_LOC_Y:
448                                 case AC_LOC_Z:
449                                         pchan->flag |= POSE_LOC;
450                                         break;
451                                 case AC_SIZE_X:
452                                 case AC_SIZE_Y:
453                                 case AC_SIZE_Z:
454                                         pchan->flag |= POSE_SIZE;
455                                         break;
456                                 }
457                         }
458
459                         execute_ipo((ID*)act, achan->ipo);
460                 
461                         set_pose_channel(*pose, pchan);
462                 }
463         }
464 }
465
466         void 
467 do_all_actions(
468 ){
469         Base *base;
470         bPose *apose=NULL;
471         bPose *tpose=NULL;
472         Object *ob;
473         bActionStrip *strip;
474         int     doit;
475         float striptime, frametime, length, actlength;
476         float blendfac, stripframe;
477
478         int set;
479
480         /* NEW: current scene ob ipo's */
481         base= G.scene->base.first;
482         set= 0;
483
484         while(base) {
485                 
486                 ob = base->object;
487
488                 /* Retrieve data from the NLA */
489                 if(ob->type==OB_ARMATURE){
490
491                         doit=0;
492
493                         /* Clear pose */
494                         if (apose){
495                                 clear_pose(apose);
496                                 MEM_freeN(apose);
497                         }
498                         /* Clear pose */
499                         if (tpose){
500                                 clear_pose(tpose);
501                                 MEM_freeN(tpose);
502                         }
503
504                         copy_pose(&apose, ob->pose, 1);
505                         copy_pose(&tpose, ob->pose, 1);
506                         rest_pose(apose, 1);
507  
508                         if (base->object->nlastrips.first){
509                                 rest_pose(base->object->pose, 0);
510                         }
511
512                         for (strip=base->object->nlastrips.first; strip; strip=strip->next){
513                                 doit = 0;
514                                 if (strip->act){
515                         
516                                         /* Determine if the current frame is within the strip's range */
517                                         length = strip->end-strip->start;
518                                         actlength = strip->actend-strip->actstart;
519                                         striptime = (G.scene->r.cfra-(strip->start)) / length;
520                                         stripframe = (G.scene->r.cfra-(strip->start)) ;
521
522
523                                         if (striptime>=0.0){
524                                                 
525                                                 rest_pose(tpose, 1);
526
527                                                 /* Handle path */
528                                                 if (strip->flag & ACTSTRIP_USESTRIDE){
529                                                         if (ob->parent && ob->parent->type==OB_CURVE){
530                                                                 Curve *cu = ob->parent->data;
531                                                                 float ctime, pdist;
532
533                                                                 if (cu->flag & CU_PATH){
534                                                                         /* Ensure we have a valid path */
535                                                                         if(cu->path==0 || cu->path->data==0) calc_curvepath(ob->parent);
536
537                                                                         /* Find the position on the path */
538                                                                         ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
539                                                                         
540                                                                         if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
541                                                                                 ctime /= cu->pathlen;
542                                                                                 CLAMP(ctime, 0.0, 1.0);
543                                                                         }
544                                                                         pdist = ctime*cu->path->totdist;
545                                                                         
546                                                                         if (strip->stridelen)
547                                                                                 striptime = pdist / strip->stridelen;
548                                                                         else
549                                                                                 striptime = 0;
550                                                                         
551                                                                         striptime = (float)fmod (striptime, 1.0);
552                                                                         
553                                                                         frametime = (striptime * actlength) + strip->actstart;
554                                                                         get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
555 #ifdef __NLA_BLENDCON
556                                                                         do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
557 #endif
558                                                                         doit=1;
559                                                                 }
560                                                         }
561                                                 }
562
563                                                 /* Handle repeat */
564                 
565                                                 else if (striptime < 1.0){
566                                                         /* Mod to repeat */
567                                                         striptime*=strip->repeat;
568                                                         striptime = (float)fmod (striptime, 1.0);
569                                                         
570                                                         frametime = (striptime * actlength) + strip->actstart;
571                                                         get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
572 #ifdef __NLA_BLENDCON
573                                                         do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
574 #endif
575                                                         doit=1;
576                                                 }
577                                                 /* Handle extend */
578                                                 else{
579                                                         if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
580                                                                 striptime = 1.0;
581                                                                 frametime = (striptime * actlength) + strip->actstart;
582                                                                 get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
583 #ifdef __NLA_BLENDCON
584                                                                 do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0));
585 #endif
586                                                                 doit=1;
587                                                         }
588                                                 }
589
590                                                 /* Handle blendin & blendout */
591                                                 if (doit){
592                                                         /* Handle blendin */
593
594                                                         if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){
595                                                                 blendfac = stripframe/strip->blendin;
596                                                         }
597                                                         else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){
598                                                                 blendfac = (length-stripframe)/(strip->blendout);
599                                                         }
600                                                         else
601                                                                 blendfac = 1;
602
603                                                         /* Blend this pose with the accumulated pose */
604                                                         blend_poses (apose, tpose, blendfac, strip->mode);
605 #ifdef __NLA_BLENDCON
606                                                         blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode);
607 #endif
608                                                 }
609                                         }                                       
610                                         if (apose){
611                                                 get_pose_from_pose(&ob->pose, apose);
612 #ifdef __NLA_BLENDCON
613                                                 get_constraint_influence_from_pose(ob->pose, apose);
614 #endif
615                                         }
616                                 }
617                                 
618                         }
619
620                         /* Do local action (always overrides the nla actions) */
621                         /*      At the moment, only constraint ipos on the local action have any effect */
622                         if(base->object->action) {
623                                 get_pose_from_action (&ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
624                                 do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0));
625                                 doit = 1;
626                         } 
627                         
628                         if (doit)
629                                 apply_pose_armature(get_armature(ob), ob->pose, 1);
630
631                 }
632                 base= base->next;
633                 if(base==0 && set==0 && G.scene->set) {
634                         set= 1;
635                         base= G.scene->set->base.first; 
636                 }
637                 
638         }
639
640         if (apose){
641                 clear_pose(apose);
642                 MEM_freeN(apose);
643                 apose = NULL;
644         }       
645         if (tpose){
646                 clear_pose(tpose);
647                 MEM_freeN(tpose);
648                 apose = NULL;
649         }
650
651 }
652
653 static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime)
654 {
655         bPoseChannel *pchan;
656         bActionChannel *achan;
657
658         if (!pose || !act)
659                 return;
660         
661         for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){
662                 achan=get_named_actionchannel(act, pchan->name);
663                 if (achan)
664                         do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime);
665         }
666 }
667
668         bActionChannel *
669 get_named_actionchannel (
670         bAction *act,
671         const char *name
672 ){
673         bActionChannel *chan;
674
675         if (!act)
676                 return NULL;
677
678         for (chan = act->chanbase.first; chan; chan=chan->next){
679                 if (!strcmp (chan->name, name))
680                         return chan;
681         }
682
683         return NULL;
684 }
685
686         void 
687 clear_pose (
688         bPose *pose
689 ) {
690         bPoseChannel *chan;
691         
692         if (pose->chanbase.first){
693                 for (chan = pose->chanbase.first; chan; chan=chan->next){
694                         free_constraints(&chan->constraints);
695                 }
696                 BLI_freelistN (&pose->chanbase);
697         }
698 }
699
700         void 
701 make_local_action(
702         bAction *act
703 ){
704         Object *ob;
705         bAction *actn;
706         int local=0, lib=0;
707
708         if(act->id.lib==0) return;
709         if(act->id.us==1) {
710                 act->id.lib= 0;
711                 act->id.flag= LIB_LOCAL;
712                 new_id(0, (ID *)act, 0);
713                 return;
714         }
715         
716         ob= G.main->object.first;
717         while(ob) {
718                 if(ob->action==act) {
719                         if(ob->id.lib) lib= 1;
720                         else local= 1;
721                 }
722                 ob= ob->id.next;
723         }
724         
725         if(local && lib==0) {
726                 act->id.lib= 0;
727                 act->id.flag= LIB_LOCAL;
728                 new_id(0, (ID *)act, 0);
729         }
730         else if(local && lib) {
731                 actn= copy_action(act);
732                 actn->id.us= 0;
733                 
734                 ob= G.main->object.first;
735                 while(ob) {
736                         if(ob->action==act) {
737                                 
738                                 if(ob->id.lib==0) {
739                                         ob->action = actn;
740                                         ob->activecon = NULL;
741                                         actn->id.us++;
742                                         act->id.us--;
743                                 }
744                         }
745                         ob= ob->id.next;
746                 }
747         }
748 }
749
750
751         void 
752 free_action(
753         bAction *act
754 ){
755         bActionChannel *chan;
756
757         /* Free channels */
758         for (chan=act->chanbase.first; chan; chan=chan->next){
759                 if (chan->ipo)
760                         chan->ipo->id.us--;
761                 free_constraint_channels(&chan->constraintChannels);
762         }
763
764         if (act->chanbase.first)
765                 BLI_freelistN (&act->chanbase);
766 }
767
768         bAction* 
769 copy_action (
770         const bAction *src
771 ){
772         bAction *dst = NULL;
773         bActionChannel *dchan, *schan;
774         
775         if(!src) return NULL;
776         
777         dst= copy_libblock(src);
778         duplicatelist(&(dst->chanbase), &(src->chanbase));
779
780         for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
781                 dchan->ipo = copy_ipo(dchan->ipo);
782                 copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
783         }
784         dst->id.flag |= LIB_FAKEUSER;
785         dst->id.us++;
786         return dst;
787 }
788
789         bPoseChannel *
790 copy_pose_channel (
791         const bPoseChannel* src
792 ){
793         bPoseChannel *dst;
794
795         if (!src)
796                 return NULL;
797
798         dst = MEM_callocN (sizeof(bPoseChannel), "copyPoseChannel");
799         memcpy (dst, src, sizeof(bPoseChannel));
800         dst->prev=dst->next=NULL;
801
802         return dst;
803 }
804
805         void 
806 copy_pose(
807         bPose **dst, 
808         const bPose *src, 
809         int copycon
810 ){
811         bPose *outPose;
812         const bPose * inPose;
813         bPoseChannel    *newChan;
814         const bPoseChannel *curChan;
815
816         inPose = src;
817         
818         if (!inPose){
819                 *dst=NULL;
820                 return;
821         }
822
823         outPose=MEM_callocN(sizeof(bPose), "pose");
824
825         for (curChan=inPose->chanbase.first; curChan; curChan=curChan->next){
826                 newChan=MEM_callocN(sizeof(bPoseChannel), "copyposePoseChannel");
827
828                 strcpy (newChan->name, curChan->name);
829                 newChan->flag=curChan->flag;
830
831                 memcpy (newChan->loc, curChan->loc, sizeof (curChan->loc));
832                 memcpy (newChan->size, curChan->size, sizeof (curChan->size));
833                 memcpy (newChan->quat, curChan->quat, sizeof (curChan->quat));
834                 Mat4CpyMat4 (newChan->obmat, curChan->obmat);
835
836                 BLI_addtail (&outPose->chanbase, newChan);
837                 if (copycon){
838                         copy_constraints(&newChan->constraints, &curChan->constraints);
839                 }
840         }
841         
842         *dst=outPose;
843 }
844
845 bPoseChannel *set_pose_channel (bPose *pose, bPoseChannel *chan){
846         /*      chan is no longer valid for the calling function.
847                 and should not be used by that function after calling
848                 this one
849         */
850         bPoseChannel    *curChan;
851
852         /*      Determine if an equivalent channel exists already */
853         for (curChan=pose->chanbase.first; curChan; curChan=curChan->next){
854                 if (!strcmp (curChan->name, chan->name)){
855                         if (chan->flag) {
856                            if (POSE_ROT)
857                                 memcpy (curChan->quat, chan->quat, sizeof(chan->quat)); 
858                            if (POSE_SIZE) 
859                                 memcpy (curChan->size, chan->size, sizeof(chan->size));
860                            if (POSE_LOC)
861                                 memcpy (curChan->loc, chan->loc, sizeof(chan->loc));
862                            if (PCHAN_DONE)
863                                 Mat4CpyMat4 (curChan->obmat, chan->obmat);
864                         }
865                         curChan->flag |= chan->flag;
866                         MEM_freeN (chan);
867                         return curChan;
868                 }
869         }
870
871         MEM_freeN (chan);
872         return NULL;
873         /* If an equivalent channel doesn't exist, then don't bother setting it. */
874 }
875