Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2007-09-17 15:41:12 +0400
committerJoshua Leung <aligorith@gmail.com>2007-09-17 15:41:12 +0400
commit52f551678b3c9020bad91041ad28a71d4e776140 (patch)
tree32a88e58de17d3e15af2190fc73ee11d1a9001fe
parent023a929363bb822f90528eff0ab3b38c86a4b309 (diff)
== Action Editor - Copy and Paste Tools ==
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)
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c4
-rw-r--r--source/blender/blenkernel/intern/action.c11
-rw-r--r--source/blender/include/BIF_editaction.h10
-rw-r--r--source/blender/include/BSE_editipo.h4
-rw-r--r--source/blender/include/blendef.h2
-rw-r--r--source/blender/python/api2_2x/Constraint.c4
-rw-r--r--source/blender/python/api2_2x/Ipo.c2
-rw-r--r--source/blender/python/api2_2x/Ipocurve.c4
-rw-r--r--source/blender/python/api2_2x/Object.c2
-rw-r--r--source/blender/src/buttons_object.c4
-rw-r--r--source/blender/src/drawaction.c2
-rw-r--r--source/blender/src/editaction.c169
-rw-r--r--source/blender/src/editipo.c199
-rw-r--r--source/blender/src/editkey.c4
-rw-r--r--source/blender/src/header_action.c50
-rw-r--r--source/blender/src/usiblender.c2
16 files changed, 329 insertions, 144 deletions
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index 04fac832cc4..dc65750f7ba 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -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)
{
}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index e10a17a3338..c333ece497d 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -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));
diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h
index 5e1f8bc8ad7..fe6f81b9416 100644
--- a/source/blender/include/BIF_editaction.h
+++ b/source/blender/include/BIF_editaction.h
@@ -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 */
diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h
index 6c6bac0ddce..077d89fbadd 100644
--- a/source/blender/include/BSE_editipo.h
+++ b/source/blender/include/BSE_editipo.h
@@ -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);
diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h
index 1dc98b73766..ac29f386678 100644
--- a/source/blender/include/blendef.h
+++ b/source/blender/include/blendef.h
@@ -390,6 +390,8 @@
#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
diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c
index f96cf1dfc55..1bd303a5126 100644
--- a/source/blender/python/api2_2x/Constraint.c
+++ b/source/blender/python/api2_2x/Constraint.c
@@ -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;
}
diff --git a/source/blender/python/api2_2x/Ipo.c b/source/blender/python/api2_2x/Ipo.c
index 73666b05695..e3bef1468dc 100644
--- a/source/blender/python/api2_2x/Ipo.c
+++ b/source/blender/python/api2_2x/Ipo.c
@@ -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 );
diff --git a/source/blender/python/api2_2x/Ipocurve.c b/source/blender/python/api2_2x/Ipocurve.c
index 57ddc7541eb..383826d8938 100644
--- a/source/blender/python/api2_2x/Ipocurve.c
+++ b/source/blender/python/api2_2x/Ipocurve.c
@@ -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;
}
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index b02a932aa39..730ae6c0726 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -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;
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index a998c568619..33229d1d38b 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -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;
diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c
index 5b65295d212..6f8fdc17166 100644
--- a/source/blender/src/drawaction.c
+++ b/source/blender/src/drawaction.c
@@ -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;
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
index 8886e57e199..9dcb7f68363 100644
--- a/source/blender/src/editaction.c
+++ b/source/blender/src/editaction.c
@@ -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);
}
}
}
@@ -1495,9 +1495,172 @@ void clean_action (void)
}
/* **************************************************** */
+/* 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)
diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c
index 07f076d8965..800a859c8bf 100644
--- a/source/blender/src/editipo.c
+++ b/source/blender/src/editipo.c
@@ -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 */
diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c
index c557b8df259..8dc0b3d2b9d 100644
--- a/source/blender/src/editkey.c
+++ b/source/blender/src/editkey.c
@@ -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];
diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c
index 1c34bdbaeaf..d8afe0fd1f1 100644
--- a/source/blender/src/header_action.c
+++ b/source/blender/src/header_action.c
@@ -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;
diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c
index 9ab0e296149..18df27b21cb 100644
--- a/source/blender/src/usiblender.c
+++ b/source/blender/src/usiblender.c
@@ -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();