== Action Editor - Copy/Paste ==

Now the Copy/Paste functionality stores more info about where keyframes came from. This allows users to copy full poses in the Action Editor and paste them in another action. 

Peach request/bugfix for William.
This commit is contained in:
Joshua Leung
2007-12-19 22:37:38 +00:00
parent b8ca87a0ba
commit 361d23224c

View File

@@ -1144,10 +1144,9 @@ 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.
/* - The copy/paste buffer currently stores a set of Action Channels, with temporary
* IPO-blocks, and also temporary IpoCurves which only contain the selected keyframes.
* - Only pastes between compatable data is possible (i.e. same achan->name, ipo-curve type, etc.)
*/
/* globals for copy/paste data (like for other copy/paste buffers) */
@@ -1156,16 +1155,34 @@ ListBase actcopybuf = {NULL, NULL};
/* This function frees any MEM_calloc'ed copy/paste buffer data */
void free_actcopybuf ()
{
IpoCurve *icu;
bActionChannel *achan, *anext;
bConstraintChannel *conchan, *cnext;
while( (icu= actcopybuf.first) ) {
BLI_remlink(&actcopybuf, icu);
free_ipo_curve(icu);
for (achan= actcopybuf.first; achan; achan= next) {
next= achan->next;
if (achan->ipo) {
free_ipo(achan->ipo);
MEM_freeN(achan->ipo);
}
for (conchan=achan->constraintChannels.first; conchan; conchan=cnext) {
cnext= conchan->next;
if (conchan->ipo) {
free_ipo(conchan->ipo);
MEM_freeN(conchan->ipo);
}
BLI_freelistN(&achan->constraintChannels, conchan);
}
BLI_freelinkN(&actcopybuf, achan);
}
}
/* This function adds data to the copy/paste buffer, freeing existing data first
* Only the active action channel gets its selected keyframes copied.
* Only the selected action channels gets their selected keyframes copied.
*/
void copy_actdata ()
{
@@ -1183,40 +1200,61 @@ void copy_actdata ()
if (data == NULL) return;
/* filter data */
filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_ONLYICU);
filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_IPOKEYS);
actdata_filter(&act_data, filter, data, datatype);
/* each of these entries should be an ipo curve */
/* assume that each of these is an ipo-block */
for (ale= act_data.first; ale; ale= ale->next) {
IpoCurve *icu= ale->key_data;
IpoCurve *icn;
bActionChannel *achan;
Ipo *ipo= ale->key_data;
Ipo *ipn;
IpoCurve *icu, *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;
}
/* coerce an action-channel out of owner */
if (ale->ownertype == ACTTYPE_ACHAN) {
bActionChannel *achanO= ale->owner;
achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
strcpy(achan->name, achanO->name);
}
/* 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);
else if (ale->ownertype == ACTTYPE_SHAPEKEY) {
achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
strcpy(achan->name, "#ACP_ShapeKey");
}
else
continue;
BLI_addtail(&actcopybuf, achan);
/* 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);
/* add constraint channel if needed, then add new ipo-block */
if (ale->type == ACTTYPE_CONCHAN) {
bConstraintChannel *conchanO= ale->data;
bConstraintChannel *conchan;
conchan= MEM_callocN(sizeof(bConstraintChannel), "ActCopyPasteConchan");
strcpy(conchan->name, conchanO->name);
BLI_addtail(&achan->constraintChannels, conchan);
conchan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
}
else {
achan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
}
ipn->blocktype = ipo->blocktype;
/* now loop through curves, and only copy selected keyframes */
for (icu= ipo->curve.first; icu; icu= icu->next) {
/* allocate a new curve */
icn= MEM_callocN(sizeof(IpoCurve), "ActCopyPasteIcu");
icn->blocktype = icu->blocktype;
icn->adrcode = icu->adrcode;
BLI_addtail(&ipn->curve, 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);
}
}
}
@@ -1247,48 +1285,88 @@ void paste_actdata ()
if (data == NULL) return;
/* filter data */
filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU);
filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
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;
Ipo *ipo_src=NULL, *ipo_dst=ale->key_data;
bActionChannel *achan;
IpoCurve *ico, *icu;
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;
/* find matching ipo-block */
for (achan= actcopybuf.first; achan; achan= achan->next) {
/* try to match data */
if (ale->ownertype == ACTTYPE_ACHAN) {
bActionChannel *achant= ale->owner;
/* check if we have a corresponding action channel */
if (strcmp(achan->name, achant->name)==0) {
/* check if this is a constraint channel */
if (ale->type == ACTTYPE_CONCHAN) {
bConstraintChannel *conchant= ale->data;
bConstraintChannel *conchan;
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
if (strcmp(conchan->name, conchant->name)==0) {
ipo_src= conchan->ipo;
break;
}
}
if (ipo_src) break;
}
else {
ipo_src= achan->ipo;
break;
}
}
}
else if (ale->ownertype == ACTTYPE_SHAPEKEY) {
/* check if this action channel is "#ACP_ShapeKey" */
if (strcmp(achan->name, "#ACP_ShapeKey")==0) {
ipo_src= achan->ipo;
break;
}
}
}
/* loop over curves, pasting keyframes */
for (icu= ipo_dst->curve.first; icu; icu= icu->next) {
for (ico= ipo_src->curve.first; ico; ico= ico->next) {
/* only paste if compatable blocktype + adrcode */
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;
}
/* temporarily apply offset to src beztriple while copying */
bezt->vec[0][0] += offset;
bezt->vec[1][0] += offset;
bezt->vec[2][0] += offset;
/* recalculate channel's handles? */
calchandles_ipocurve(icu);
/* 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;
/* done for this channel */
break;
}
/* recalculate channel's handles? */
calchandles_ipocurve(icu);
/* done for this channel */
break;
}
}
}