diff options
author | Joshua Leung <aligorith@gmail.com> | 2007-12-20 01:37:38 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2007-12-20 01:37:38 +0300 |
commit | 361d23224c356aa46769a0b8102752d757231df8 (patch) | |
tree | 6c63cbe5384e5c7e0cd5000c5d8ae8b1d487b27a /source/blender/src | |
parent | b8ca87a0baefe10317fae87528f3eb2f0bf372c2 (diff) |
== 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.
Diffstat (limited to 'source/blender/src')
-rw-r--r-- | source/blender/src/editaction.c | 202 |
1 files changed, 140 insertions, 62 deletions
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index dc13e5d3019..c9e2df8d9eb 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -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); + } + else if (ale->ownertype == ACTTYPE_SHAPEKEY) { + achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan"); + strcpy(achan->name, "#ACP_ShapeKey"); } - /* allocate memory for a new curve if a valid one wasn't found */ - if (nin_buffer) { - icn= MEM_callocN(sizeof(IpoCurve), "actcopybuf"); + else + continue; + BLI_addtail(&actcopybuf, achan); + + /* add constraint channel if needed, then add new ipo-block */ + if (ale->type == ACTTYPE_CONCHAN) { + bConstraintChannel *conchanO= ale->data; + bConstraintChannel *conchan; - *icn= *icu; - icn->totvert= 0; - icn->bezt = NULL; - icn->driver = NULL; + conchan= MEM_callocN(sizeof(bConstraintChannel), "ActCopyPasteConchan"); + strcpy(conchan->name, conchanO->name); + BLI_addtail(&achan->constraintChannels, conchan); - BLI_addtail(&actcopybuf, icn); + conchan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo"); } - - /* 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); + 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; - - /* insert the keyframe */ - insert_bezt_icu(icu, bezt); + /* recalculate channel's handles? */ + calchandles_ipocurve(icu); - /* 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; } } } |