== Action Editor - Copy and Paste Tools ==
authorJoshua Leung <aligorith@gmail.com>
Mon, 17 Sep 2007 11:41:12 +0000 (11:41 +0000)
committerJoshua Leung <aligorith@gmail.com>
Mon, 17 Sep 2007 11:41:12 +0000 (11:41 +0000)
Now it is possible to do Copy+Paste in the Action Editor, like in the IPO Editor. There are two new buttons in the Action Editor header for this, using the familiar icons.

* To copy...
Select the keyframes you wish to copy, and the channels that they occur in (except for ShapeKey mode, where it is not possible to select channels). Click copy button.
* To paste...
Place the current frame where you want the first of the keyframes from the buffer is to be pasted. Select all channels you wish the keyframes to be pasted into. Click paste button.

Currently, keyframes are only pasted into 'compatible' curves (i.e.  LocX keyframes can only go to LocX, and so on). This may change after user feedback, if this is found to be too restrictive.

== Code Changes ==
I've made a few changes which allow this code to be nicer.
* renamed insert_vert_ipo to insert_vert_icu, as that represents its actual purpose better (and changed all occurrences I could find)
* created a new function, insert_bezt_icu, which does the actual inserting of provided BezTriple data to a given IpoCurve
* recoded insert_vert_icu to use this new function, and also the IPO-Editor keyframe pasting (i.e.  pasting in Editmode)

16 files changed:
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/action.c
source/blender/include/BIF_editaction.h
source/blender/include/BSE_editipo.h
source/blender/include/blendef.h
source/blender/python/api2_2x/Constraint.c
source/blender/python/api2_2x/Ipo.c
source/blender/python/api2_2x/Ipocurve.c
source/blender/python/api2_2x/Object.c
source/blender/src/buttons_object.c
source/blender/src/drawaction.c
source/blender/src/editaction.c
source/blender/src/editipo.c
source/blender/src/editkey.c
source/blender/src/header_action.c
source/blender/src/usiblender.c

index 04fac832cc405c6ab7cc92096daf18197756075d..dc65750f7ba4f39c84a55370f8217ad369863bac 100644 (file)
@@ -59,7 +59,7 @@ struct bPythonConstraint;
 struct bConstraintOb;
 
 char *getIpoCurveName( struct IpoCurve * icu );
-void insert_vert_ipo(struct IpoCurve *icu, float x, float y);
+void insert_vert_icu(struct IpoCurve *icu, float x, float y);
 struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e);
 void elbeemDebugOut(char *msg);
 void fluidsimSettingsFree(struct FluidsimSettings* sb);
@@ -83,7 +83,7 @@ char *getIpoCurveName( struct IpoCurve * icu )
        return 0;
 }
 
-void insert_vert_ipo(struct IpoCurve *icu, float x, float y)
+void insert_vert_icu(struct IpoCurve *icu, float x, float y)
 {
 }
 
index e10a17a3338154defe4e34b48ef4358adfe0dd39..c333ece497d928a175c3a98b3a77b40d8582fccf 100644 (file)
@@ -112,7 +112,6 @@ static void make_local_action_channels(bAction *act)
                        }
                }
        }
-                                       
 }
 
 void make_local_action(bAction *act)
@@ -165,27 +164,27 @@ void make_local_action(bAction *act)
 }
 
 
-void free_action(bAction *act)
+void free_action (bAction *act)
 {
        bActionChannel *chan;
        
        /* Free channels */
-       for (chan=act->chanbase.first; chan; chan=chan->next){
+       for (chan=act->chanbase.first; chan; chan=chan->next) {
                if (chan->ipo)
                        chan->ipo->id.us--;
                free_constraint_channels(&chan->constraintChannels);
        }
        
        if (act->chanbase.first)
-               BLI_freelistN (&act->chanbase);
+               BLI_freelistN(&act->chanbase);
 }
 
-bAction* copy_action(bAction *src)
+bAction *copy_action (bAction *src)
 {
        bAction *dst = NULL;
        bActionChannel *dchan, *schan;
        
-       if(!src) return NULL;
+       if (!src) return NULL;
        
        dst= copy_libblock(src);
        duplicatelist(&(dst->chanbase), &(src->chanbase));
index 5e1f8bc8ad7a28171b9b9b76fc5cd4ee7e682d3b..fe6f81b94168205b789ce537ef9f94e8014ce0df 100644 (file)
@@ -79,7 +79,6 @@ enum {
        SET_IPO_BEZIER,
 };
 
-
 /* constants for setting ipo-extrapolation type */
 enum {
        
@@ -92,6 +91,7 @@ enum {
        SET_EXTEND_CYCLICEXTRAPOLATION
 };
 
+
 struct bAction;
 struct bActionChannel;
 struct bPoseChannel;
@@ -116,6 +116,11 @@ void column_select_action_keys(int mode);
 void selectall_action_keys(short mval[], short mode, short selectmode);
 void markers_selectkeys_between(void);
 
+/* Action Data Copying */
+void free_actcopybuf(void);
+void copy_actdata(void);
+void paste_actdata(void);
+
 /* channel/strip operations */
 void up_sel_action(void);
 void down_sel_action(void);
@@ -132,11 +137,12 @@ void deselect_action_keys(short test, short sel);
 void deselect_action_channels(short test);
 void deselect_actionchannels(struct bAction *act, short test);
 int select_channel(struct bAction *act, struct bActionChannel *achan, int selectmode);
-void select_actionchannel_by_name (struct bAction *act, char *name, int select);
+void select_actionchannel_by_name(struct bAction *act, char *name, int select);
 
 /* ShapeKey stuff */
 struct Key *get_action_mesh_key(void);
 int get_nearest_key_num(struct Key *key, short *mval, float *x);
+
 void *get_nearest_act_channel(short mval[], short *ret_type);
 
 /* Action */
index 6c6bac0ddcecb7951068417504c0ac9e60379db2..077d89fbaddadecd33c210cbb1dbdfcb5135c90d 100644 (file)
@@ -91,8 +91,10 @@ struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, int);
 struct Ipo *verify_ipo(struct ID *, short, char *, char *);
 int texchannel_to_adrcode(int channel);
 
-void insert_vert_ipo(struct IpoCurve *icu, float x, float y);
+int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt);
+void insert_vert_icu(struct IpoCurve *icu, float x, float y);
 void add_vert_ipo(void);
+
 void add_duplicate_editipo(void);
 void remove_doubles_ipo(void);
 void clean_ipo(void);
index 1dc98b737663babe48a83b4f8eff1358a4e0f3f8..ac29f3866787e695b85b9ca9f5be68c958e485dd 100644 (file)
 #define B_ACTMAIN              707
 #define        B_ACTPIN                708
 #define B_ACTBAKE              709
+#define B_ACTCOPYKEYS          710
+#define B_ACTPASTEKEYS         711
 
 /* TIME: 751 - 800 */
 #define B_TL_REW               751
index f96cf1dfc55d4cd52689f09484676cae11e48061..1bd303a512666e67d7888d65556832c59c5b98d5 100644 (file)
@@ -431,9 +431,9 @@ static PyObject *Constraint_insertKey( BPy_Constraint * self, PyObject * value )
                                "cannot get a curve from this IPO, may be using libdata" );
        
        if( ob->action )
-               insert_vert_ipo( icu, get_action_frame(ob, cfra), con->enforce);
+               insert_vert_icu( icu, get_action_frame(ob, cfra), con->enforce);
        else
-               insert_vert_ipo( icu, cfra, con->enforce);
+               insert_vert_icu( icu, cfra, con->enforce);
 
        Py_RETURN_NONE;
 }
index 73666b056951d25560df92dcc4dd629c6f476d61..e3bef1468dc999209b887a9798e9e5bdc6ef9d9a 100644 (file)
@@ -1483,7 +1483,7 @@ static int Ipo_setIpoCurveByName( BPy_Ipo * self, PyObject * key,
                icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
                set_icu_vars( icu );
                BLI_addtail( &(ipo->curve), icu);
-               insert_vert_ipo( icu, time, curval );
+               insert_vert_icu( icu, time, curval );
 
                allspace( REMAKEIPO, 0 );
                EXPP_allqueue( REDRAWIPO, 0 );
index 57ddc7541eb611a6437d953ec431f7e508a33765..383826d8938d846700a3ec824d9df3caed20176b 100644 (file)
@@ -531,7 +531,7 @@ static PyObject *IpoCurve_append( C_IpoCurve * self, PyObject * value )
                Py_DECREF( xobj );
                y = (float)PyFloat_AsDouble( yobj );
                Py_DECREF( yobj );
-               insert_vert_ipo( icu, x, y);
+               insert_vert_icu( icu, x, y);
        }
 
        Py_RETURN_NONE;
@@ -745,7 +745,7 @@ static int IpoCurve_setCurval( C_IpoCurve * self, PyObject * key,
 
        /* insert a key at the specified time */
 
-       insert_vert_ipo( self->ipocurve, time, curval );
+       insert_vert_icu( self->ipocurve, time, curval );
        allspace(REMAKEIPO, 0);
        return 0;
 }
index b02a932aa39d79cbcdb45616ee4bcf869ad588a4..730ae6c0726839629be653b918927e3d7d7b9c67 100644 (file)
@@ -2517,7 +2517,7 @@ static PyObject *Object_setConstraintInfluenceForBone( BPy_Object * self,
                return EXPP_ReturnPyObjError( PyExc_RuntimeError,
                                "cannot get a curve from this IPO, may be using libdata" );             
        
-       insert_vert_ipo(icu, (float)CFRA, influence);
+       insert_vert_icu(icu, (float)CFRA, influence);
        self->object->recalc |= OB_RECALC_OB;  
 
        Py_RETURN_NONE;
index a998c5686190166378e3460b96ffcb1af028e26c..33229d1d38b8c7d4d0f2bc5b1fb8c321b03dd0cb 100644 (file)
@@ -263,9 +263,9 @@ static void add_influence_key_to_constraint_func (void *ob_v, void *con_v)
        }
        
        if(ob->action)
-               insert_vert_ipo(icu, get_action_frame(ob, (float)CFRA), con->enforce);
+               insert_vert_icu(icu, get_action_frame(ob, (float)CFRA), con->enforce);
        else
-               insert_vert_ipo(icu, CFRA, con->enforce);
+               insert_vert_icu(icu, CFRA, con->enforce);
        
        /* make sure ipowin shows it */
        ob->ipowin= ID_CO;
index 5b65295d2129632680869f0c9bdcca05ecbb10fd..6f8fdc17166fcfe12d5f1245572930b50a968a39 100644 (file)
@@ -198,7 +198,7 @@ static void icu_slider_func(void *voidicu, void *voidignore)
         * otherwise modify it's value
         */
        if (!bezt) {
-               insert_vert_ipo(icu, cfra, icu->curval);
+               insert_vert_icu(icu, cfra, icu->curval);
        }
        else {
                bezt->vec[1][1] = icu->curval;
index 8886e57e1991a5c055ae5dd196f895aad18079ff..9dcb7f683638aac92fb8f8093986c5e45d5baed9 100644 (file)
@@ -1335,7 +1335,7 @@ void insertkey_action(void)
                                if (ob)
                                        insertkey((ID *)ob, icu->blocktype, achan->name, NULL, icu->adrcode);
                                else
-                                       insert_vert_ipo(icu, cfra, icu->curval);
+                                       insert_vert_icu(icu, cfra, icu->curval);
                        }
                }
                
@@ -1352,7 +1352,7 @@ void insertkey_action(void)
                
                if (key->ipo) {
                        for (icu= key->ipo->curve.first; icu; icu=icu->next) {
-                               insert_vert_ipo(icu, cfra, icu->curval);
+                               insert_vert_icu(icu, cfra, icu->curval);
                        }
                }
        }
@@ -1494,10 +1494,173 @@ void clean_action (void)
        allqueue(REDRAWNLA, 0);
 }
 
+/* **************************************************** */
+/* COPY/PASTE FOR ACTIONS */
+/* - The copy/paste buffer currently stores a set of IPO curves, with no
+ *   repeating curve-types (i.e.  no curves with the same adrcode). 
+ * - Only selected keyframes from the source curves are placed here. 
+ * - Only 'compatible' pastes are done.
+ */
+
+/* globals for copy/paste data (like for other copy/paste buffers) */
+ListBase actcopybuf = {NULL, NULL};
+
+/* This function frees any MEM_calloc'ed copy/paste buffer data */
+void free_actcopybuf ()
+{
+       IpoCurve *icu;
+       
+       while( (icu= actcopybuf.first) ) {
+               BLI_remlink(&actcopybuf, icu);
+               free_ipo_curve(icu);
+       }
+}
+
+/* This function adds data to the copy/paste buffer, freeing existing data first
+ * Only the active action channel gets its selected keyframes copied.
+ */
+void copy_actdata ()
+{
+       ListBase act_data = {NULL, NULL};
+       bActListElem *ale;
+       int filter;
+       void *data;
+       short datatype;
+       
+       /* clear buffer first */
+       free_actcopybuf();
+       
+       /* get data */
+       data= get_action_context(&datatype);
+       if (data == NULL) return;
+       
+       /* filter data */
+       filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_ONLYICU);
+       actdata_filter(&act_data, filter, data, datatype);
+       
+       /* each of these entries should be an ipo curve */
+       for (ale= act_data.first; ale; ale= ale->next) {
+               IpoCurve *icu= ale->key_data;
+               IpoCurve *icn;
+               BezTriple *bezt;
+               short nin_buffer= 1;
+               int i;
+               
+               /* check if a curve like this exists already in buffer */
+               for (icn= actcopybuf.first; icn; icn= icn->next) {
+                       if ((icn->blocktype==icu->blocktype) && (icn->adrcode==icu->adrcode)) {
+                               nin_buffer= 0;
+                               break;
+                       }
+               }
+               /* allocate memory for a new curve if a valid one wasn't found */
+               if (nin_buffer) {
+                       icn= MEM_callocN(sizeof(IpoCurve), "actcopybuf");
+                       
+                       *icn= *icu;
+                       icn->totvert= 0;
+                       icn->bezt = NULL;
+                       icn->driver = NULL;
+                       
+                       BLI_addtail(&actcopybuf, icn);
+               }
+               
+               /* find selected BezTriples to add to the buffer */
+               for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
+                       if (BEZSELECTED(bezt))
+                               insert_bezt_icu(icn, bezt);
+               }
+       }
+       
+       /* check if anything ended up in the buffer */
+       if (actcopybuf.first==NULL || actcopybuf.last==NULL)
+               error("Nothing copied to buffer");
+       
+       /* free temp memory */
+       BLI_freelistN(&act_data);
+}
+
+void paste_actdata ()
+{
+       ListBase act_data = {NULL, NULL};
+       bActListElem *ale;
+       int filter;
+       void *data;
+       short datatype;
+       
+       /* check if buffer is empty */
+       if (actcopybuf.first==NULL || actcopybuf.last==NULL) {
+               error("No data in buffer to paste");
+               return;
+       }
+       
+       /* get data */
+       data= get_action_context(&datatype);
+       if (data == NULL) return;
+       
+       /* filter data */
+       filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU);
+       actdata_filter(&act_data, filter, data, datatype);
+       
+       /* from selected channels */
+       for (ale= act_data.first; ale; ale= ale->next) {
+               IpoCurve *icu= ale->key_data;
+               IpoCurve *ico;
+               BezTriple *bezt;
+               int i;
+               float offset= 0.0f;
+               short offsetInit= 1;
+               
+               /* find matching ipo-curve */
+               for (ico= actcopybuf.first; ico; ico= ico->next) {
+                       if ((ico->blocktype==icu->blocktype) && (ico->adrcode==icu->adrcode)) {
+                               /* just start pasting, with the the first keyframe on the current frame, and so on */
+                               for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) {
+                                       /* initialise offset (if not already done) */
+                                       if (offsetInit) {
+                                               offset= CFRA - bezt->vec[1][0];
+                                               offsetInit= 0;
+                                       }
+                                       
+                                       /* temporarily apply offset to src beztriple while copying */
+                                       bezt->vec[0][0] += offset;
+                                       bezt->vec[1][0] += offset;
+                                       bezt->vec[2][0] += offset;
+                                       
+                                       /* insert the keyframe */
+                                       insert_bezt_icu(icu, bezt);
+                                       
+                                       /* un-apply offset from src beztriple after copying */
+                                       bezt->vec[0][0] -= offset;
+                                       bezt->vec[1][0] -= offset;
+                                       bezt->vec[2][0] -= offset;
+                               }
+                               
+                               /* recalculate channel's handles? */
+                               calchandles_ipocurve(icu);
+                               
+                               /* done for this channel */
+                               break;
+                       }
+               }
+       }
+       
+       /* free temp memory */
+       BLI_freelistN(&act_data);
+       
+       /* undo and redraw stuff */
+       allqueue(REDRAWVIEW3D, 0);
+       allspace(REMAKEIPO, 0);
+       allqueue(REDRAWACTION, 0);
+       allqueue(REDRAWIPO, 0);
+       allqueue(REDRAWNLA, 0);
+       BIF_undo_push("Paste Action Keyframes");
+}
+
 /* **************************************************** */
 /* VARIOUS SETTINGS */
 
-/* this function combines several features related to setting 
+/* This function combines several features related to setting 
  * various ipo extrapolation/interpolation
  */
 void action_set_ipo_flags (short mode, short event)
index 07f076d8965d5ae6d79ae6655dd0c5717dc9dad9..800a859c8bf9fd01862da58d6bd33973bf73ce93 100644 (file)
@@ -1893,55 +1893,48 @@ IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constn
        return icu;
 }
 
-void insert_vert_ipo(IpoCurve *icu, float x, float y)
+/* This function adds a given BezTriple to an IPO-Curve. It will allocate 
+ * memory for the array if needed, and will insert the BezTriple into a
+ * suitable place in chronological order.
+ * 
+ * NOTE: any recalculate of the IPO-Curve that needs to be done will need to 
+ *             be done by the caller.
+ */
+int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt)
 {
-       BezTriple *bezt, beztr, *newbezt;
-       int a = 0, h1, h2;
+       BezTriple *newb, *beztd;
+       int i= 0;
        
-       memset(&beztr, 0, sizeof(BezTriple));
-       beztr.vec[0][0]= x; // set all three points, for nicer start position
-       beztr.vec[0][1]= y;
-       beztr.vec[1][0]= x;
-       beztr.vec[1][1]= y;
-       beztr.vec[2][0]= x;
-       beztr.vec[2][1]= y;
-       beztr.hide= IPO_BEZ;
-       beztr.f1= beztr.f2= beztr.f3= SELECT;
-       beztr.h1= beztr.h2= HD_AUTO;
-               
-       bezt= icu->bezt;
-               
-       if(bezt==NULL) {
-               icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple");
-               *(icu->bezt)= beztr;
+       if (icu->bezt == NULL) {
+               icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
+               *(icu->bezt)= *bezt;
                icu->totvert= 1;
        }
        else {
-               /* all vertices deselect */
-               for(a=0; a<icu->totvert; a++, bezt++) {
-                       bezt->f1= bezt->f2= bezt->f3= 0;
-               }
-       
-               bezt= icu->bezt;
-               for(a=0; a<=icu->totvert; a++, bezt++) {
-                       
+               beztd= icu->bezt;
+               for (i = 0; i <= icu->totvert; i++, beztd++) {
                        /* no double points - threshold to determine this should be good enough */
-                       if(a<icu->totvert && IS_EQT(bezt->vec[1][0], x, 0.00001)) {
-                               *(bezt)= beztr;
+                       if ((i < icu->totvert) && IS_EQT(beztd->vec[1][0], bezt->vec[1][0], 0.00001)) {
+                               *(beztd)= *bezt;
                                break;
                        }
-                       if(a==icu->totvert || bezt->vec[1][0] > x) {
-                               newbezt= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple");
+                       /* if we've reached the end of the icu array, or bezt is to be pasted before current */
+                       if (i==icu->totvert || beztd->vec[1][0] > bezt->vec[1][0]) {
+                               newb= MEM_callocN( (icu->totvert+1)*sizeof(BezTriple), "beztriple");
                                
-                               if(a>0) memcpy(newbezt, icu->bezt, a*sizeof(BezTriple));
+                               /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
+                               if (i > 0) 
+                                       memcpy(newb, icu->bezt, i*sizeof(BezTriple));
                                
-                               bezt= newbezt+a;
-                               *(bezt)= beztr;
+                               /* add beztriple to paste at index j */
+                               *(newb+i)= *bezt;
                                
-                               if(a<icu->totvert) memcpy(newbezt+a+1, icu->bezt+a, (icu->totvert-a)*sizeof(BezTriple));
+                               /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
+                               if (i < icu->totvert) 
+                                       memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple));
                                
                                MEM_freeN(icu->bezt);
-                               icu->bezt= newbezt;
+                               icu->bezt= newb;
                                
                                icu->totvert++;
                                break;
@@ -1949,17 +1942,50 @@ void insert_vert_ipo(IpoCurve *icu, float x, float y)
                }
        }
        
+       /* we need to return the index, so that some tools which do post-processing can 
+        * detect where we added the BezTriple in the array
+        */
+       return i;
+}
+
+/* This function is a wrapper for insert_bezt_icu, and should be used when
+ * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere
+ * else yet. 
+ */
+void insert_vert_icu (IpoCurve *icu, float x, float y)
+{
+       BezTriple beztr;
+       int a, h1, h2;
        
+       /* set all three points, for nicer start position */
+       memset(&beztr, 0, sizeof(BezTriple));
+       beztr.vec[0][0]= x; 
+       beztr.vec[0][1]= y;
+       beztr.vec[1][0]= x;
+       beztr.vec[1][1]= y;
+       beztr.vec[2][0]= x;
+       beztr.vec[2][1]= y;
+       beztr.hide= IPO_BEZ;
+       beztr.f1= beztr.f2= beztr.f3= SELECT;
+       beztr.h1= beztr.h2= HD_AUTO;
+       
+       /* add temp beztriple to keyframes */
+       a= insert_bezt_icu(icu, &beztr);
        calchandles_ipocurve(icu);
        
        /* set handletype */
-       if(icu->totvert>2) {
+       if (icu->totvert > 2) {
+               BezTriple *bezt;
+               
                h1= h2= HD_AUTO;
-               if(a>0) h1= (bezt-1)->h2;
-               if(a<icu->totvert-1) h2= (bezt+1)->h1;
+               bezt= (icu->bezt + a);
+               
+               if (a > 0) h1= (bezt-1)->h2;
+               if (a < icu->totvert-1) h2= (bezt+1)->h1;
+               
                bezt->h1= h1;
                bezt->h2= h2;
-
+               
                calchandles_ipocurve(icu);
        }
 }
@@ -2013,7 +2039,7 @@ void add_vert_ipo(void)
                y= (float)(1 << val);
        }
        
-       insert_vert_ipo(ei->icu, x, y);
+       insert_vert_icu(ei->icu, x, y);
 
        /* to be sure: if icu was 0, or only 1 curve visible */
        ei->flag |= IPO_SELECT;
@@ -2190,7 +2216,7 @@ static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *cons
                                        }
                                }
                                
-                               insert_vert_ipo(icu, cfra, curval);
+                               insert_vert_icu(icu, cfra, curval);
                        }
                }
        }
@@ -2412,7 +2438,7 @@ void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcod
                                        }
                                }
                                
-                               insert_vert_ipo(icu, cfra, curval);
+                               insert_vert_icu(icu, cfra, curval);
                        }
                }
        }
@@ -2459,7 +2485,7 @@ void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, in
                        
                        /* insert new keyframe at current frame */
                        if (insert_mode) 
-                               insert_vert_ipo(icu, cfra, curval);
+                               insert_vert_icu(icu, cfra, curval);
                        
                        /* delete keyframe immediately before/after newly added */
                        switch (insert_mode) {
@@ -2506,7 +2532,7 @@ void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int a
                        }
                        
                        /* insert new keyframe at current frame */
-                       insert_vert_ipo(icu, cfra, floatkey);
+                       insert_vert_icu(icu, cfra, floatkey);
                }
        }
 }
@@ -2537,16 +2563,16 @@ void insertkey_editipo(void)
                ei->icu->totvert= 0;
                ei->icu->bezt= NULL;
                
-               insert_vert_ipo(ei->icu, 0.0f, 0.0f);
+               insert_vert_icu(ei->icu, 0.0f, 0.0f);
                
                if(ELEM3(driver->adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) {
                        if(ei->disptype==IPO_DISPDEGR)
-                               insert_vert_ipo(ei->icu, 18.0f, 18.0f);
+                               insert_vert_icu(ei->icu, 18.0f, 18.0f);
                        else
-                               insert_vert_ipo(ei->icu, 18.0f, 1.0f);
+                               insert_vert_icu(ei->icu, 18.0f, 1.0f);
                }
                else
-                       insert_vert_ipo(ei->icu, 1.0f, 1.0f);
+                       insert_vert_icu(ei->icu, 1.0f, 1.0f);
                
                ei->flag |= IPO_SELECT|IPO_VISIBLE;
                ei->icu->flag= ei->flag;
@@ -2623,7 +2649,7 @@ void insertkey_editipo(void)
                                                }
                                                fp= insertvals;
                                                for(a=0; a<tot; a++, fp+=2) {
-                                                       insert_vert_ipo(ei->icu, fp[0], fp[1]);
+                                                       insert_vert_icu(ei->icu, fp[0], fp[1]);
                                                }
                                                
                                                MEM_freeN(insertvals);
@@ -3413,7 +3439,7 @@ void clean_ipo_curve(IpoCurve *icu)
        
        /* now insert first keyframe, as it should be ok */
        bezt = old_bezts;
-       insert_vert_ipo(icu, bezt->vec[1][0], bezt->vec[1][1]);
+       insert_vert_icu(icu, bezt->vec[1][0], bezt->vec[1][1]);
        
        /* Loop through BezTriples, comparing them. Skip any that do 
         * not fit the criteria for "ok" points.
@@ -3450,7 +3476,7 @@ void clean_ipo_curve(IpoCurve *icu)
                                if (cur[1] > next[1]) {
                                        if (IS_EQT(cur[1], prev[1], thresh) == 0) {
                                                /* add new keyframe */
-                                               insert_vert_ipo(icu, cur[0], cur[1]);
+                                               insert_vert_icu(icu, cur[0], cur[1]);
                                        }
                                }
                        }
@@ -3458,7 +3484,7 @@ void clean_ipo_curve(IpoCurve *icu)
                                /* only add if values are a considerable distance apart */
                                if (IS_EQT(cur[1], prev[1], thresh) == 0) {
                                        /* add new keyframe */
-                                       insert_vert_ipo(icu, cur[0], cur[1]);
+                                       insert_vert_icu(icu, cur[0], cur[1]);
                                }
                        }
                }
@@ -3468,18 +3494,18 @@ void clean_ipo_curve(IpoCurve *icu)
                                /* does current have same value as previous and next? */
                                if (IS_EQT(cur[1], prev[1], thresh) == 0) {
                                        /* add new keyframe*/
-                                       insert_vert_ipo(icu, cur[0], cur[1]);
+                                       insert_vert_icu(icu, cur[0], cur[1]);
                                }
                                else if (IS_EQT(cur[1], next[1], thresh) == 0) {
                                        /* add new keyframe */
-                                       insert_vert_ipo(icu, cur[0], cur[1]);
+                                       insert_vert_icu(icu, cur[0], cur[1]);
                                }
                        }
                        else {  
                                /* add if value doesn't equal that of previous */
                                if (IS_EQT(cur[1], prev[1], thresh) == 0) {
                                        /* add new keyframe */
-                                       insert_vert_ipo(icu, cur[0], cur[1]);
+                                       insert_vert_icu(icu, cur[0], cur[1]);
                                }
                        }
                }
@@ -4123,10 +4149,10 @@ void paste_editipo(void)
                        
                        /* if in editmode, paste keyframes */ 
                        if (ei->flag & IPO_EDIT) {
-                               BezTriple *src, *dst, *newb;
+                               BezTriple *bezt;
                                float offset= 0.0f;
                                short offsetInit= 0;
-                               int i, j;
+                               int i;
                                
                                /* make sure an ipo-curve exists (it may not, as this is an editipo) */
                                ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, ei->adrcode);
@@ -4136,62 +4162,27 @@ void paste_editipo(void)
                                 * with all added keyframes being offsetted by the difference between
                                 * the first source keyframe and the current frame.
                                 */
-                               for (i=0, src=icu->bezt; i < icu->totvert; i++, src++) {
+                               for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
                                        /* skip if not selected */
-                                       if (BEZSELECTED(src) == 0) continue;
+                                       if (BEZSELECTED(bezt) == 0) continue;
                                        
                                        /* initialise offset (if not already done) */
                                        if (offsetInit==0) {
-                                               offset= CFRA - src->vec[1][0];
+                                               offset= CFRA - bezt->vec[1][0];
                                                offsetInit= 1;
                                        }
                                        /* temporarily apply offset to src beztriple while copying */
-                                       src->vec[0][0] += offset;
-                                       src->vec[1][0] += offset;
-                                       src->vec[2][0] += offset;
+                                       bezt->vec[0][0] += offset;
+                                       bezt->vec[1][0] += offset;
+                                       bezt->vec[2][0] += offset;
                                                
-                                       /* find place to insert */
-                                       if (ei->icu->bezt == NULL) {
-                                               ei->icu->bezt= MEM_callocN( sizeof(BezTriple), "beztriple");
-                                               *(ei->icu->bezt)= *src;
-                                               ei->icu->totvert= 1;
-                                       }
-                                       else {
-                                               dst= ei->icu->bezt;
-                                               for (j=0; j <= ei->icu->totvert; j++, dst++) {
-                                                       /* no double points - threshold to determine this should be good enough */
-                                                       if ((j < ei->icu->totvert) && IS_EQT(dst->vec[1][0], src->vec[1][0], 0.00001)) {
-                                                               *(dst)= *src;
-                                                               break;
-                                                       }
-                                                       /* if we've reached the end of the ei->icu array, or src is to be pasted before current */
-                                                       if (j==ei->icu->totvert || dst->vec[1][0] > src->vec[1][0]) {
-                                                               newb= MEM_callocN( (ei->icu->totvert+1)*sizeof(BezTriple), "beztriple");
-                                                               
-                                                               /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
-                                                               if (j > 0) 
-                                                                       memcpy(newb, ei->icu->bezt, j*sizeof(BezTriple));
-                                                               
-                                                               /* add beztriple to paste at index j */
-                                                               *(newb+j)= *src;
-                                                               
-                                                               /* add the beztriples that occur after the beztriple to be pasted (originally in ei->icu) */
-                                                               if (j < ei->icu->totvert) 
-                                                                       memcpy(newb+j+1, ei->icu->bezt+j, (ei->icu->totvert-j)*sizeof(BezTriple));
-                                                               
-                                                               MEM_freeN(ei->icu->bezt);
-                                                               ei->icu->bezt= newb;
-                                                               
-                                                               ei->icu->totvert++;
-                                                               break;
-                                                       }
-                                               }
-                                       }
+                                       /* insert the keyframe */
+                                       insert_bezt_icu(ei->icu, bezt);
                                        
                                        /* un-apply offset from src beztriple after copying */
-                                       src->vec[0][0] -= offset;
-                                       src->vec[1][0] -= offset;
-                                       src->vec[2][0] -= offset;
+                                       bezt->vec[0][0] -= offset;
+                                       bezt->vec[1][0] -= offset;
+                                       bezt->vec[2][0] -= offset;
                                }
                                
                                /* recalculate handles of curve that data was pasted into */
index c557b8df2599f0c2abfd3f62f31719fc2b71054a..8dc0b3d2b9d40d89bd892f1ff68b86b607a793dd 100644 (file)
@@ -184,8 +184,8 @@ static void rvk_slider_func(void *voidob, void *voidkeynum)
                /* create the bezier triple if one doesn't exist,
                 * otherwise modify it's value
                 */
-               if (!bezt) {
-                       insert_vert_ipo(icu, cfra, meshslidervals[keynum]);
+               if (bezt == NULL) {
+                       insert_vert_icu(icu, cfra, meshslidervals[keynum]);
                }
                else {
                        bezt->vec[1][1] = meshslidervals[keynum];
index 1c34bdbaeafbdf3f27a12c16e5cf8201b3a60b15..d8afe0fd1f17e262402d4dbd16c9db26c214b018 100644 (file)
@@ -229,6 +229,14 @@ void do_action_buttons(unsigned short event)
                        paste_posebuf(1);
                        allqueue(REDRAWVIEW3D, 1);
                        break;
+                       
+               /* copy/paste buttons in Action Editor header */
+               case B_ACTCOPYKEYS:
+                       copy_actdata();
+                       break;
+               case B_ACTPASTEKEYS:
+                       paste_actdata();
+                       break;
 
                case B_ACTPIN:  /* __PINFAKE */
 /*             if (G.saction->flag & SACTION_PIN) {
@@ -1102,23 +1110,23 @@ void action_buttons(void)
 {
        uiBlock *block;
        short xco, xmax;
-       char naam[256];
+       char name[256];
        Object *ob;
        ID *from;
 
-       if (!G.saction)
+       if (G.saction == NULL)
                return;
 
-       // copy from drawactionspace....
+       /* copied from drawactionspace.... */
        if (!G.saction->pin) {
                if (OBACT)
                        G.saction->action = OBACT->action;
                else
-                       G.saction->action=NULL;
+                       G.saction->action= NULL;
        }
 
-       sprintf(naam, "header %d", curarea->headwin);
-       block= uiNewBlock(&curarea->uiblocks, naam
+       sprintf(name, "header %d", curarea->headwin);
+       block= uiNewBlock(&curarea->uiblocks, name
                                          UI_EMBOSS, UI_HELV, curarea->headwin);
 
        if (area_is_active_area(curarea)) 
@@ -1156,10 +1164,10 @@ void action_buttons(void)
        uiBlockSetEmboss(block, UI_EMBOSS);
        xco+=XIC;
 
-       if((curarea->flag & HEADER_NO_PULLDOWN)==0) {
+       if ((curarea->flag & HEADER_NO_PULLDOWN)==0) {
                /* pull down menus */
                uiBlockSetEmboss(block, UI_EMBOSSP);
-       
+               
                xmax= GetButStringLength("View");
                uiDefPulldownBut(block, action_viewmenu, NULL, 
                                          "View", xco, -2, xmax-3, 24, "");
@@ -1184,8 +1192,8 @@ void action_buttons(void)
        uiBlockSetEmboss(block, UI_EMBOSS);
        
        /* NAME ETC */
-       ob=OBACT;
-       from = (ID*) ob;
+       ob= OBACT;
+       from = (ID *)ob;
 
        xco= std_libbuttons(block, xco, 0, B_ACTPIN, &G.saction->pin, 
                                                B_ACTIONBROWSE, ID_AC, 0, (ID*)G.saction->action, 
@@ -1195,7 +1203,7 @@ void action_buttons(void)
        uiClearButLock();
 
        /* draw AUTOSNAP */
-       xco+= 8;
+       xco += 8;
        
        if (G.saction->flag & SACTION_DRAWTIME) {
                uiDefButS(block, MENU, B_REDR,
@@ -1210,15 +1218,27 @@ void action_buttons(void)
                                "Auto-snapping mode for keyframes when transforming");
        }
        
-       xco+= (70 + 8);
+       xco += (70 + 8);
        
-       /* draw LOCK*/
-               
+       /* COPY PASTE */
+       uiBlockBeginAlign(block);
+       if (curarea->headertype==HEADERTOP) {
+               uiDefIconBut(block, BUT, B_ACTCOPYKEYS, ICON_COPYUP,    xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected keyframes from the selected channel(s) to the buffer");
+               uiDefIconBut(block, BUT, B_ACTPASTEKEYS, ICON_PASTEUP,  xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the keyframes from the buffer");
+       }
+       else {
+               uiDefIconBut(block, BUT, B_ACTCOPYKEYS, ICON_COPYDOWN,  xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Copies the selected keyframes from the selected channel(s) to the buffer");
+               uiDefIconBut(block, BUT, B_ACTPASTEKEYS, ICON_PASTEDOWN,        xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Pastes the keyframes from the buffer");
+       }
+       uiBlockEndAlign(block);
+       xco += (XIC + 8);
+       
+       /* draw LOCK */
        uiDefIconButS(block, ICONTOG, 1, ICON_UNLOCKED, xco, 0, XIC, YIC, 
                                  &(G.saction->lock), 0, 0, 0, 0, 
                                  "Updates other affected window spaces automatically "
                                  "to reflect changes in real time");
-
+       
        /* always as last  */
        curarea->headbutlen = xco + 2*XIC;
 
index 9ab0e296149f337e634861d094b93da608934d88..18df27b21cbff886111cd8ff15151887a79b6915 100644 (file)
@@ -94,6 +94,7 @@
 #include "BIF_interface.h"
 #include "BIF_usiblender.h"
 #include "BIF_drawtext.h"
+#include "BIF_editaction.h"
 #include "BIF_editarmature.h"
 #include "BIF_editlattice.h"
 #include "BIF_editfont.h"
@@ -942,6 +943,7 @@ void exit_usiblender(void)
        free_blender();                         /* blender.c, does entire library */
        free_matcopybuf();
        free_ipocopybuf();
+       free_actcopybuf();
        free_vertexpaint();
        free_imagepaint();