2.5 Action Editor - Big WIP Commit

* Brought back backend for editing keyframes IPO/IPO-Curves. Did some refactoring work here that will still have to be verified when operators using them are added.

* Animation channel filtering code now returns the number of channels filtered (for Action Editor to set totrect of channels - TODO still!)

* View2D - made function to check if mouse is in View2D scrollers an API function

* Renamed keyframe related files. The old names were too clumsy.

* Started porting click-select operators for Action Editor. These don't work currently, as the events are being stolen by the markers. This needs to be fixed ASAP.
This commit is contained in:
2008-12-23 11:02:39 +00:00
parent 58da63cd3e
commit 87c05f7836
16 changed files with 1784 additions and 100 deletions

View File

@@ -254,4 +254,39 @@ void ANIM_nla_mapping_draw(gla2DDrawInfo *di, Object *ob, short restore)
}
}
/* Apply/Unapply NLA mapping to all keyframes in the nominated IPO block
* - restore = whether to map points back to ipo-time
* - only_keys = whether to only adjust the location of the center point of beztriples
*/
// was called actstrip_map_ipo_keys()
void ANIM_nla_mapping_apply(Object *ob, Ipo *ipo, short restore, short only_keys)
{
IpoCurve *icu;
BezTriple *bezt;
int a;
if (ipo==NULL) return;
/* loop through all ipo curves, adjusting the times of the selected keys */
for (icu= ipo->curve.first; icu; icu= icu->next) {
for (a=0, bezt=icu->bezt; a<icu->totvert; a++, bezt++) {
/* are the times being adjusted for editing, or has editing finished */
if (restore) {
if (only_keys == 0) {
bezt->vec[0][0]= get_action_frame(ob, bezt->vec[0][0]);
bezt->vec[2][0]= get_action_frame(ob, bezt->vec[2][0]);
}
bezt->vec[1][0]= get_action_frame(ob, bezt->vec[1][0]);
}
else {
if (only_keys == 0) {
bezt->vec[0][0]= get_action_frame_inv(ob, bezt->vec[0][0]);
bezt->vec[2][0]= get_action_frame_inv(ob, bezt->vec[2][0]);
}
bezt->vec[1][0]= get_action_frame_inv(ob, bezt->vec[1][0]);
}
}
}
}
/* *************************************************** */

View File

@@ -490,12 +490,13 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
/* ----------------------------------------- */
static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel *achan, int filter_mode, void *owner, short ownertype)
static int animdata_filter_actionchannel (ListBase *anim_data, bActionChannel *achan, int filter_mode, void *owner, short ownertype)
{
bAnimListElem *ale = NULL;
bConstraintChannel *conchan;
IpoCurve *icu;
short owned= (owner && ownertype)? 1 : 0;
int items = 0;
/* only work with this channel and its subchannels if it is visible */
if (!(filter_mode & ANIMFILTER_VISIBLE) || VISIBLE_ACHAN(achan)) {
@@ -510,19 +511,20 @@ static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
}
else {
/* for insert key... this check could be improved */
return;
//return; // FIXME...
}
/* check if expanded - if not, continue on to next animion channel */
if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ANIMFILTER_ONLYICU)==0) {
/* only exit if we don't need to include constraint channels for group-channel keyframes */
if ( !(filter_mode & ANIMFILTER_IPOKEYS) || (achan->grp == NULL) || (EXPANDED_AGRP(achan->grp)==0) )
return;
return items;
}
/* ipo channels */
@@ -534,6 +536,7 @@ static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
@@ -546,6 +549,7 @@ static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
}
@@ -562,6 +566,7 @@ static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
@@ -574,12 +579,12 @@ static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel
/* check if this conchan should only be included if it is selected */
if (!(filter_mode & ANIMFILTER_SEL) || SEL_CONCHAN(conchan)) {
if (filter_mode & ANIMFILTER_IPOKEYS) {
if (ale) BLI_addtail(anim_data, ale);
ale= make_new_animlistelem(conchan, ANIMTYPE_CONCHAN2, achan, ANIMTYPE_ACHAN);
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
else {
@@ -588,6 +593,7 @@ static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
}
@@ -597,14 +603,18 @@ static void animdata_filter_animionchannel (ListBase *anim_data, bActionChannel
}
}
}
/* return the number of items added to the list */
return items;
}
static void animdata_filter_action (ListBase *anim_data, bAction *act, int filter_mode, void *owner, short ownertype)
static int animdata_filter_action (ListBase *anim_data, bAction *act, int filter_mode, void *owner, short ownertype)
{
bAnimListElem *ale=NULL;
bActionGroup *agrp;
bActionChannel *achan, *lastchan=NULL;
short owned= (owner && ownertype) ? 1 : 0;
int items = 0;
/* loop over groups */
for (agrp= act->groups.first; agrp; agrp= agrp->next) {
@@ -616,6 +626,7 @@ static void animdata_filter_action (ListBase *anim_data, bAction *act, int filte
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
}
@@ -642,7 +653,7 @@ static void animdata_filter_action (ListBase *anim_data, bAction *act, int filte
{
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
animdata_filter_animionchannel(anim_data, achan, filter_mode, owner, ownertype);
items += animdata_filter_actionchannel(anim_data, achan, filter_mode, owner, ownertype);
}
/* remove group from filtered list if last element is group
@@ -653,6 +664,7 @@ static void animdata_filter_action (ListBase *anim_data, bAction *act, int filte
(ale->data == agrp) && (agrp->channels.first) )
{
BLI_freelinkN(anim_data, ale);
items--;
}
}
}
@@ -661,19 +673,22 @@ static void animdata_filter_action (ListBase *anim_data, bAction *act, int filte
/* loop over un-grouped animion channels (only if we're not only considering those channels in the animive group) */
if (!(filter_mode & ANIMFILTER_ACTGROUPED)) {
for (achan=(lastchan)?lastchan->next:act->chanbase.first; achan; achan=achan->next) {
animdata_filter_animionchannel(anim_data, achan, filter_mode, owner, ownertype);
for (achan=(lastchan)?(lastchan->next):(act->chanbase.first); achan; achan=achan->next) {
items += animdata_filter_actionchannel(anim_data, achan, filter_mode, owner, ownertype);
}
}
/* return the number of items added to the list */
return items;
}
static void animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype)
static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode, void *owner, short ownertype)
{
bAnimListElem *ale;
KeyBlock *kb;
IpoCurve *icu;
short owned= (owner && ownertype)? 1 : 0;
int i;
int i, items=0;
/* are we filtering for display or editing */
if (filter_mode & ANIMFILTER_FORDRAWING) {
@@ -705,6 +720,7 @@ static void animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
else {
@@ -715,6 +731,7 @@ static void animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
else {
@@ -723,21 +740,26 @@ static void animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_
if (ale) {
if (owned) ale->id= owner;
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
}
/* return the number of items added to the list */
return items;
}
#if 0
// FIXME: switch this to use the bDopeSheet...
static void animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
{
bAnimListElem *ale;
ScrArea *sa, *curarea;
bGPdata *gpd;
bGPDlayer *gpl;
int items = 0;
/* check if filtering types are appropriate */
if ( !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU|ANIMFILTER_ACTGROUPED)) )
@@ -762,7 +784,10 @@ static void animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filte
if ((filter_mode & ANIMFILTER_FORDRAWING) && (gpd->layers.first)) {
/* add to list */
ale= make_new_animlistelem(gpd, ANIMTYPE_GPDATABLOCK, sa, ANIMTYPE_SPECIALDATA);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* only add layers if they will be visible (if drawing channels) */
@@ -775,26 +800,36 @@ static void animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filte
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
/* add to list */
ale= make_new_animlistelem(gpl, ANIMTYPE_GPLAYER, gpd, ANIMTYPE_GPDATABLOCK);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
}
}
}
/* return the number of items added to the list */
return items;
}
#endif
static void animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
bAnimListElem *ale=NULL;
Object *ob= base->object;
IpoCurve *icu;
int items = 0;
/* include materials-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add materials? */
@@ -812,7 +847,10 @@ static void animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads
// hmm... do we need to store the index of this material in the array anywhere?
if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
ale= make_new_animlistelem(ma, ANIMTYPE_DSMAT, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add material's ipo-curve channels? */
@@ -828,25 +866,33 @@ static void animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads
/* make owner the material not object, so that indent is not just object level */
ale->id= (ID *)ma;
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
}
}
/* return the number of items added to the list */
return items;
}
static void animdata_filter_dopesheet_cam (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
static int animdata_filter_dopesheet_cam (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
bAnimListElem *ale=NULL;
Object *ob= base->object;
Camera *ca= (Camera *)ob->data;
IpoCurve *icu;
int items = 0;
/* include camera-expand widget? */
if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
ale= make_new_animlistelem(ca, ANIMTYPE_DSCAM, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add camera ipo-curve channels? */
@@ -861,24 +907,32 @@ static void animdata_filter_dopesheet_cam (ListBase *anim_data, bDopeSheet *ads,
if (ale) {
/* make owner the material not object, so that indent is not just object level */
ale->id= (ID *)ca;
BLI_addtail(anim_data, ale);
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
/* return the number of items added to the list */
return items;
}
static void animdata_filter_dopesheet_lamp (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
static int animdata_filter_dopesheet_lamp (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
bAnimListElem *ale=NULL;
Object *ob= base->object;
Lamp *la= (Lamp *)ob->data;
IpoCurve *icu;
int items = 0;
/* include lamp-expand widget? */
if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
ale= make_new_animlistelem(la, ANIMTYPE_DSLAM, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add lamp ipo-curve channels? */
@@ -893,24 +947,32 @@ static void animdata_filter_dopesheet_lamp (ListBase *anim_data, bDopeSheet *ads
if (ale) {
/* make owner the material not object, so that indent is not just object level */
ale->id= (ID *)la;
BLI_addtail(anim_data, ale);
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
/* return the number of items added to the list */
return items;
}
static void animdata_filter_dopesheet_curve (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
static int animdata_filter_dopesheet_curve (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
bAnimListElem *ale=NULL;
Object *ob= base->object;
Curve *cu= (Curve *)ob->data;
IpoCurve *icu;
int items = 0;
/* include curve-expand widget? */
if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
ale= make_new_animlistelem(cu, ANIMTYPE_DSCUR, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add curve ipo-curve channels? */
@@ -925,40 +987,51 @@ static void animdata_filter_dopesheet_curve (ListBase *anim_data, bDopeSheet *ad
if (ale) {
/* make owner the material not object, so that indent is not just object level */
ale->id= (ID *)cu;
BLI_addtail(anim_data, ale);
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
/* return the number of items added to the list */
return items;
}
static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
bAnimListElem *ale=NULL;
Scene *sce= (Scene *)ads->source;
Object *ob= base->object;
Key *key= ob_get_key(ob);
IpoCurve *icu;
int items = 0;
/* add this object as a channel first */
if (!(filter_mode & ANIMFILTER_ONLYICU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
/* check if filtering by selection */
if ( !(filter_mode & ANIMFILTER_SEL) || ((base->flag & SELECT) || (base == sce->basact)) ) {
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
/* if collapsed, don't go any further (unless adding keyframes only) */
if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU)) )
return;
return items;
/* IPO? */
if ((ob->ipo) && !(ads->filterflag & ADS_FILTER_NOIPOS)) {
/* include ipo-expand widget? */
if (filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_IPOKEYS)) {
ale= make_new_animlistelem(ob, ANIMTYPE_FILLIPOD, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add ipo-curve channels? */
@@ -970,7 +1043,10 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
/* only if selected (if checking for selection) */
if ( !(filter_mode & ANIMFILTER_SEL) || (SEL_ICU(icu)) ) {
ale= make_new_animlistelem(icu, ANIMTYPE_ICU, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
}
}
@@ -984,13 +1060,14 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
if (ale) {
ale->id= (ID *)ob; // err.... is this a good idea?
BLI_addtail(anim_data, ale);
items++;
}
}
/* add ipo-curve channels? */
if (EXPANDED_ACTC(ob->action) || !(filter_mode & (ANIMFILTER_CHANNELS|ANIMFILTER_FORDRAWING))) {
// need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
animdata_filter_action(anim_data, ob->action, filter_mode, ob, ANIMTYPE_OBJECT);
items += animdata_filter_action(anim_data, ob->action, filter_mode, ob, ANIMTYPE_OBJECT);
}
}
@@ -999,18 +1076,21 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
/* include shapekey-expand widget? */
if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add channels */
if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
animdata_filter_shapekey (anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT);
items += animdata_filter_shapekey (anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT);
}
}
/* Materials? */
if ((ob->totcol) && !(ads->filterflag & ADS_FILTER_NOMAT))
animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
items += animdata_filter_dopesheet_mats(anim_data, ads, base, filter_mode);
/* Object Data */
switch (ob->type) {
@@ -1018,21 +1098,21 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
{
Camera *ca= (Camera *)ob->data;
if ((ca->ipo) && !(ads->filterflag & ADS_FILTER_NOCAM))
animdata_filter_dopesheet_cam(anim_data, ads, base, filter_mode);
items += animdata_filter_dopesheet_cam(anim_data, ads, base, filter_mode);
}
break;
case OB_LAMP: /* ---------- Lamp ----------- */
{
Lamp *la= (Lamp *)ob->data;
if ((la->ipo) && !(ads->filterflag & ADS_FILTER_NOLAM))
animdata_filter_dopesheet_lamp(anim_data, ads, base, filter_mode);
items += animdata_filter_dopesheet_lamp(anim_data, ads, base, filter_mode);
}
break;
case OB_CURVE: /* ------- Curve ---------- */
{
Curve *cu= (Curve *)ob->data;
if ((cu->ipo) && !(ads->filterflag & ADS_FILTER_NOCUR))
animdata_filter_dopesheet_curve(anim_data, ads, base, filter_mode);
items += animdata_filter_dopesheet_curve(anim_data, ads, base, filter_mode);
}
break;
}
@@ -1046,7 +1126,10 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
&& !(filter_mode & ANIMFILTER_IPOKEYS) )
{
ale= make_new_animlistelem(ob, ANIMTYPE_FILLCOND, base, ANIMTYPE_OBJECT);
if (ale) BLI_addtail(anim_data, ale);
if (ale) {
BLI_addtail(anim_data, ale);
items++;
}
}
/* add constraint channels? */
@@ -1062,6 +1145,7 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
if (ale) {
ale->id= (ID *)ob;
BLI_addtail(anim_data, ale);
items++;
}
}
else {
@@ -1069,6 +1153,7 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
if (ale) {
ale->id= (ID *)ob;
BLI_addtail(anim_data, ale);
items++;
}
}
}
@@ -1076,18 +1161,22 @@ static void animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads,
}
}
}
/* return the number of items added to the list */
return items;
}
// TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted)
static void animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int filter_mode)
static int animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int filter_mode)
{
Scene *sce= (Scene *)ads->source;
Base *base;
int items = 0;
/* check that we do indeed have a scene */
if ((ads->source == NULL) || (GS(ads->source->name)!=ID_SCE)) {
printf("DopeSheet Error: Not scene! \n");
return;
return 0;
}
/* loop over all bases in the scene */
@@ -1199,21 +1288,27 @@ static void animdata_filter_dopesheet (ListBase *anim_data, bDopeSheet *ads, int
}
/* since we're still here, this object should be usable */
animdata_filter_dopesheet_ob(anim_data, ads, base, filter_mode);
items += animdata_filter_dopesheet_ob(anim_data, ads, base, filter_mode);
}
}
/* return the number of items in the list */
return items;
}
/* ----------- Public API --------------- */
/* This function filters the active data source to leave only the desired
* data types. 'Public' api call.
/* This function filters the active data source to leave only animation channels suitable for
* usage by the caller. It will return the length of the list
*
* *act_data: is a pointer to a ListBase, to which the filtered animation channels
* will be placed for use.
* filter_mode: how should the data be filtered - bitmapping accessed flags
*/
void ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, short datatype)
int ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, short datatype)
{
int items = 0;
/* only filter data if there's somewhere to put it */
if (data && anim_data) {
bAnimListElem *ale, *next;
@@ -1221,20 +1316,21 @@ void ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, sho
/* firstly filter the data */
switch (datatype) {
case ANIMCONT_ACTION:
animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
items= animdata_filter_action(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
break;
case ANIMCONT_SHAPEKEY:
animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
items= animdata_filter_shapekey(anim_data, data, filter_mode, NULL, ANIMTYPE_NONE);
break;
case ANIMCONT_GPENCIL:
//animdata_filter_gpencil(anim_data, data, filter_mode);
//items= animdata_filter_gpencil(anim_data, data, filter_mode);
break;
case ANIMCONT_DOPESHEET:
animdata_filter_dopesheet(anim_data, data, filter_mode);
items= animdata_filter_dopesheet(anim_data, data, filter_mode);
break;
case ANIMCONT_IPO:
// FIXME: this will be used for showing a single IPO-block (not too useful from animator perspective though!)
//items= 0;
break;
}
@@ -1243,17 +1339,26 @@ void ANIM_animdata_filter (ListBase *anim_data, int filter_mode, void *data, sho
for (ale= anim_data->first; ale; ale= next) {
next= ale->next;
if (ale->type == ANIMTYPE_NONE)
if (ale->type == ANIMTYPE_NONE) {
items--;
BLI_freelinkN(anim_data, ale);
}
if (filter_mode & ANIMFILTER_IPOKEYS) {
if (ale->datatype != ALE_IPO)
if (ale->datatype != ALE_IPO) {
items--;
BLI_freelinkN(anim_data, ale);
else if (ale->key_data == NULL)
}
else if (ale->key_data == NULL) {
items--;
BLI_freelinkN(anim_data, ale);
}
}
}
}
/* return the number of items in the list */
return items;
}
/* ************************************************************ */

View File

@@ -0,0 +1,785 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "DNA_curve_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "BKE_action.h"
#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_utildefines.h"
#include "ED_keyframes_edit.h"
#include "ED_markers.h"
/* This file defines an API and set of callback-operators for editing keyframe data.
*
* Two API functions are defined for actually performing the operations on the data:
* ipo_keys_bezier_loop() and icu_keys_bezier_loop()
* which take the data they operate on, a few callbacks defining what operations to perform.
*
* As operators which work on keyframes usually apply the same operation on all BezTriples in
* every channel, the code has been optimised providing a set of functions which will get the
* appropriate bezier-modify function to set. These functions (ANIM_editkeyframes_*) will need
* to be called before getting any channels.
*
* - Joshua Leung, Dec 2008
*/
/* ************************************************************************** */
/* IPO Editing Loops - Exposed API */
// FIXME: it would be useful to be able to supply custom properties to the bezt function...
// workaround for those callbacks that need this now, is to set globals...
/* This function is used to loop over BezTriples in the given IpoCurve, applying a given
* operation on them, and optionally applies an IPO-curve validate function afterwards.
*/
short icu_keys_bezier_loop(Scene *scene, IpoCurve *icu, BeztEditFunc bezt_cb, IcuEditFunc icu_cb)
{
BezTriple *bezt;
int b;
/* if function to apply to bezier curves is set, then loop through executing it on beztriples */
if (bezt_cb) {
for (b=0, bezt=icu->bezt; b < icu->totvert; b++, bezt++) {
/* Exit with return-code '1' if function returns positive
* This is useful if finding if some BezTriple satisfies a condition.
*/
if (bezt_cb(scene, bezt)) return 1;
}
}
/* if ipocurve_function has been specified then execute it */
if (icu_cb)
icu_cb(icu);
/* done */
return 0;
}
/* This function is used to loop over the IPO curves (and subsequently the keyframes in them) */
short ipo_keys_bezier_loop(Scene *scene, Ipo *ipo, BeztEditFunc bezt_cb, IcuEditFunc icu_cb)
{
IpoCurve *icu;
/* Sanity check */
if (ipo == NULL)
return 0;
/* Loop through each curve in the Ipo */
for (icu= ipo->curve.first; icu; icu=icu->next) {
if (icu_keys_bezier_loop(scene, icu, bezt_cb, icu_cb))
return 1;
}
return 0;
}
/* ******************************************* */
/* Transform */
static short snap_bezier_nearest(Scene *scene, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]+0.5));
return 0;
}
static short snap_bezier_nearestsec(Scene *scene, BezTriple *bezt)
{
float secf = FPS;
if (bezt->f2 & SELECT)
bezt->vec[1][0]= (float)(floor(bezt->vec[1][0]/secf + 0.5f) * secf);
return 0;
}
static short snap_bezier_cframe(Scene *scene, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
bezt->vec[1][0]= (float)CFRA;
return 0;
}
static short snap_bezier_nearmarker(Scene *scene, BezTriple *bezt)
{
//if (bezt->f2 & SELECT)
// bezt->vec[1][0]= (float)find_nearest_marker_time(bezt->vec[1][0]); // XXX missing function!
return 0;
}
// calchandles_ipocurve
BeztEditFunc ANIM_editkeys_snap(short type)
{
switch (type) {
case SNAP_KEYS_NEARFRAME: /* snap to nearest frame */
return snap_bezier_nearest;
case SNAP_KEYS_CURFRAME: /* snap to current frame */
return snap_bezier_cframe;
case SNAP_KEYS_NEARMARKER: /* snap to nearest marker */
return snap_bezier_nearmarker;
case SNAP_KEYS_NEARSEC: /* snap to nearest second */
return snap_bezier_nearestsec;
default: /* just in case */
return snap_bezier_nearest;
}
}
/* --------- */
static short mirror_bezier_cframe(Scene *scene, BezTriple *bezt)
{
float diff;
if (bezt->f2 & SELECT) {
diff= ((float)CFRA - bezt->vec[1][0]);
bezt->vec[1][0]= ((float)CFRA + diff);
}
return 0;
}
static short mirror_bezier_yaxis(Scene *scene, BezTriple *bezt)
{
float diff;
if (bezt->f2 & SELECT) {
diff= (0.0f - bezt->vec[1][0]);
bezt->vec[1][0]= (0.0f + diff);
}
return 0;
}
static short mirror_bezier_xaxis(Scene *scene, BezTriple *bezt)
{
float diff;
if (bezt->f2 & SELECT) {
diff= (0.0f - bezt->vec[1][1]);
bezt->vec[1][1]= (0.0f + diff);
}
return 0;
}
static short mirror_bezier_marker(Scene *scene, BezTriple *bezt)
{
static TimeMarker *marker;
static short initialised = 0;
/* In order for this mirror function to work without
* any extra arguments being added, we use the case
* of bezt==NULL to denote that we should find the
* marker to mirror over. The static pointer is safe
* to use this way, as it will be set to null after
* each cycle in which this is called.
*/
if (bezt) {
/* mirroring time */
if ((bezt->f2 & SELECT) && (marker)) {
const float diff= (marker->frame - bezt->vec[1][0]);
bezt->vec[1][0]= (marker->frame + diff);
}
}
else {
/* initialisation time */
if (initialised) {
/* reset everything for safety */
marker = NULL;
initialised = 0;
}
else {
/* try to find a marker */
for (marker= scene->markers.first; marker; marker=marker->next) {
if (marker->flag & SELECT) {
initialised = 1;
break;
}
}
if (initialised == 0)
marker = NULL;
}
}
return 0;
}
/* Note: for markers case, need to set global vars (eww...) */
// calchandles_ipocurve
BeztEditFunc ANIM_editkeyframes_mirror(short type)
{
switch (type) {
case 1: /* mirror over current frame */
return mirror_bezier_cframe;
case 2: /* mirror over frame 0 */
return mirror_bezier_yaxis;
case 3: /* mirror over value 0 */
return mirror_bezier_xaxis;
case 4: /* mirror over marker */
return mirror_bezier_marker; // XXX in past, this func was called before/after with NULL, probably will need globals instead
default: /* just in case */
return mirror_bezier_yaxis;
break;
}
}
/* This function is called to calculate the average location of the
* selected keyframes, and place the current frame at that location.
*
* It must be called like so:
* snap_cfra_ipo_keys(scene, NULL, -1); // initialise the static vars first
* for (ipo...) snap_cfra_ipo_keys(scene, ipo, 0); // sum up keyframe times
* snap_cfra_ipo_keys(scene, NULL, 1); // set current frame after taking average
*/
void snap_cfra_ipo_keys(Scene *scene, Ipo *ipo, short mode)
{
static int cfra;
static int tot;
IpoCurve *icu;
BezTriple *bezt;
int a;
if (mode == -1) {
/* initialise a new snap-operation */
cfra= 0;
tot= 0;
}
else if (mode == 1) {
/* set current frame - using average frame */
if (tot != 0)
CFRA = cfra / tot;
}
else {
/* loop through keys in ipo, summing the frame
* numbers of those that are selected
*/
if (ipo == NULL)
return;
for (icu= ipo->curve.first; icu; icu= icu->next) {
for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
if (BEZSELECTED(bezt)) {
cfra += bezt->vec[1][0];
tot++;
}
}
}
}
}
/* ******************************************* */
/* Settings */
/* Sets the selected bezier handles to type 'auto' */
static short set_bezier_auto(Scene *scene, BezTriple *bezt)
{
/* is a handle selected? If so set it to type auto */
if((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
if (bezt->f1 & SELECT) bezt->h1= 1; /* the secret code for auto */
if (bezt->f3 & SELECT) bezt->h2= 1;
/* if the handles are not of the same type, set them
* to type free
*/
if (bezt->h1 != bezt->h2) {
if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
}
}
return 0;
}
/* Sets the selected bezier handles to type 'vector' */
static short set_bezier_vector(Scene *scene, BezTriple *bezt)
{
/* is a handle selected? If so set it to type vector */
if ((bezt->f1 & SELECT) || (bezt->f3 & SELECT)) {
if (bezt->f1 & SELECT) bezt->h1= HD_VECT;
if (bezt->f3 & SELECT) bezt->h2= HD_VECT;
/* if the handles are not of the same type, set them
* to type free
*/
if (bezt->h1 != bezt->h2) {
if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
}
}
return 0;
}
#if 0 // xxx currently not used (only used by old code as a check)
static short bezier_isfree(Scene *scene, BezTriple *bezt)
{
/* queries whether the handle should be set
* to type 'free' or 'align'
*/
if ((bezt->f1 & SELECT) && (bezt->h1)) return 1;
if ((bezt->f3 & SELECT) && (bezt->h2)) return 1;
return 0;
}
static short set_bezier_align(Scene *scene, BezTriple *bezt)
{
/* Sets selected bezier handles to type 'align' */
if (bezt->f1 & SELECT) bezt->h1= HD_ALIGN;
if (bezt->f3 & SELECT) bezt->h2= HD_ALIGN;
return 0;
}
#endif // xxx currently not used (only used by old code as a check, but can't replicate that now)
static short set_bezier_free(Scene *scene, BezTriple *bezt)
{
/* Sets selected bezier handles to type 'free' */
if (bezt->f1 & SELECT) bezt->h1= HD_FREE;
if (bezt->f3 & SELECT) bezt->h2= HD_FREE;
return 0;
}
/* Set all Bezier Handles to a single type */
// calchandles_ipocurve
BeztEditFunc ANIM_editkeyframes_sethandles(short code)
{
switch (code) {
case 1: /* auto */
return set_bezier_auto;
case 2: /* vector */
return set_bezier_vector;
default: /* free or align? */
return set_bezier_free; // err.. to set align, we need 'align' to be set
}
}
#if 0
void sethandles_ipo_keys(Ipo *ipo, int code)
{
/* this function lets you set bezier handles all to
* one type for some Ipo's (e.g. with hotkeys through
* the action window).
*/
/* code==1: set autohandle */
/* code==2: set vectorhandle */
/* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
switch (code) {
case 1: /* auto */
ipo_keys_bezier_loop(ipo, set_bezier_auto, calchandles_ipocurve);
break;
case 2: /* vector */
ipo_keys_bezier_loop(ipo, set_bezier_vector, calchandles_ipocurve);
break;
default: /* free or align? */
if (ipo_keys_bezier_loop(ipo, bezier_isfree, NULL)) /* free */
ipo_keys_bezier_loop(ipo, set_bezier_free, calchandles_ipocurve);
else /* align */
ipo_keys_bezier_loop(ipo, set_bezier_align, calchandles_ipocurve);
break;
}
}
#endif
/* ------- */
void set_ipocurve_mixed(IpoCurve *icu)
{
/* Sets the type of the IPO curve to mixed, as some (selected)
* keyframes were set to other interpolation modes
*/
icu->ipo= IPO_MIXED;
/* recalculate handles, as some changes may have occurred */
calchandles_ipocurve(icu);
}
static short set_bezt_constant(Scene *scene, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
bezt->ipo= IPO_CONST;
return 0;
}
static short set_bezt_linear(Scene *scene, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
bezt->ipo= IPO_LIN;
return 0;
}
static short set_bezt_bezier(Scene *scene, BezTriple *bezt)
{
if (bezt->f2 & SELECT)
bezt->ipo= IPO_BEZ;
return 0;
}
/* Set the interpolation type of the selected BezTriples in each IPO curve to the specified one */
// set_ipocurve_mixed() !
BeztEditFunc ANIM_editkeyframes_ipo(short code)
{
switch (code) {
case 1: /* constant */
return set_bezt_constant;
case 2: /* linear */
return set_bezt_linear;
default: /* bezier */
return set_bezt_bezier;
}
}
#if 0
void setipotype_ipo(Ipo *ipo, int code)
{
/* Sets the type of the selected bezts in each ipo curve in the
* Ipo to a value based on the code
*/
switch (code) {
case 1:
ipo_keys_bezier_loop(ipo, set_bezt_constant, set_ipocurve_mixed);
break;
case 2:
ipo_keys_bezier_loop(ipo, set_bezt_linear, set_ipocurve_mixed);
break;
case 3:
ipo_keys_bezier_loop(ipo, set_bezt_bezier, set_ipocurve_mixed);
break;
}
}
#endif
// XXX will we keep this?
void setexprap_ipoloop(Ipo *ipo, int code)
{
IpoCurve *icu;
/* Loop through each curve in the Ipo */
for (icu=ipo->curve.first; icu; icu=icu->next)
icu->extrap= code;
}
/* ******************************************* */
/* Selection */
static short select_bezier_add(Scene *scene, BezTriple *bezt)
{
/* Select the bezier triple */
BEZ_SEL(bezt);
return 0;
}
static short select_bezier_subtract(Scene *scene, BezTriple *bezt)
{
/* Deselect the bezier triple */
BEZ_DESEL(bezt);
return 0;
}
static short select_bezier_invert(Scene *scene, BezTriple *bezt)
{
/* Invert the selection for the bezier triple */
bezt->f2 ^= SELECT;
if (bezt->f2 & SELECT) {
bezt->f1 |= SELECT;
bezt->f3 |= SELECT;
}
else {
bezt->f1 &= ~SELECT;
bezt->f3 &= ~SELECT;
}
return 0;
}
// NULL
BeztEditFunc ANIM_editkeyframes_select(short selectmode)
{
switch (selectmode) {
case SELECT_ADD: /* add */
return select_bezier_add;
case SELECT_SUBTRACT: /* subtract */
return select_bezier_subtract;
case SELECT_INVERT: /* invert */
return select_bezier_invert;
default: /* replace (need to clear all, then add) */
return select_bezier_add;
}
}
short is_ipo_key_selected(Ipo *ipo)
{
IpoCurve *icu;
BezTriple *bezt;
int i;
if (ipo == NULL)
return 0;
for (icu=ipo->curve.first; icu; icu=icu->next) {
for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
if (BEZSELECTED(bezt))
return 1;
}
}
return 0;
}
void set_ipo_key_selection(Ipo *ipo, short sel)
{
IpoCurve *icu;
BezTriple *bezt;
int i;
if (ipo == NULL)
return;
for (icu=ipo->curve.first; icu; icu=icu->next) {
for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
if (sel == 2) {
BEZ_INVSEL(bezt);
}
else if (sel == 1) {
BEZ_SEL(bezt);
}
else {
BEZ_DESEL(bezt);
}
}
}
}
// err... this is this still used?
int fullselect_ipo_keys(Ipo *ipo)
{
IpoCurve *icu;
int tvtot = 0;
int i;
if (!ipo)
return tvtot;
for (icu=ipo->curve.first; icu; icu=icu->next) {
for (i=0; i<icu->totvert; i++) {
if (icu->bezt[i].f2 & SELECT) {
tvtot+=3;
icu->bezt[i].f1 |= SELECT;
icu->bezt[i].f3 |= SELECT;
}
}
}
return tvtot;
}
void borderselect_icu_key(Scene *scene, IpoCurve *icu, float xmin, float xmax, BeztEditFunc select_cb)
{
/* Selects all bezier triples in the Ipocurve
* between times xmin and xmax, using the selection
* function.
*/
BezTriple *bezt;
int i;
/* loop through all of the bezier triples in
* the Ipocurve -- if the triple occurs between
* times xmin and xmax then select it using the selection
* function
*/
for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
if ((bezt->vec[1][0] > xmin) && (bezt->vec[1][0] < xmax)) {
select_cb(scene, bezt);
}
}
}
void borderselect_ipo_key(Scene *scene, Ipo *ipo, float xmin, float xmax, short selectmode)
{
/* Selects all bezier triples in each Ipocurve of the
* Ipo between times xmin and xmax, using the selection mode.
*/
IpoCurve *icu;
BeztEditFunc select_cb;
/* If the ipo is no good then return */
if (ipo == NULL)
return;
/* Set the selection function based on the
* selection mode.
*/
select_cb= ANIM_editkeyframes_select(selectmode);
if (select_cb == NULL)
return;
/* loop through all of the bezier triples in all
* of the Ipocurves -- if the triple occurs between
* times xmin and xmax then select it using the selection
* function
*/
for (icu=ipo->curve.first; icu; icu=icu->next) {
borderselect_icu_key(scene, icu, xmin, xmax, select_cb);
}
}
#if 0
void select_ipo_bezier_keys(Ipo *ipo, int selectmode)
{
/* Select all of the beziers in all
* of the Ipo curves belonging to the
* Ipo, using the selection mode.
*/
switch (selectmode) {
case SELECT_ADD:
ipo_keys_bezier_loop(ipo, select_bezier_add, NULL);
break;
case SELECT_SUBTRACT:
ipo_keys_bezier_loop(ipo, select_bezier_subtract, NULL);
break;
case SELECT_INVERT:
ipo_keys_bezier_loop(ipo, select_bezier_invert, NULL);
break;
}
}
void select_icu_bezier_keys(IpoCurve *icu, int selectmode)
{
/* Select all of the beziers in all
* of the Ipo curves belonging to the
* Ipo, using the selection mode.
*/
switch (selectmode) {
case SELECT_ADD:
icu_keys_bezier_loop(icu, select_bezier_add, NULL);
break;
case SELECT_SUBTRACT:
icu_keys_bezier_loop(icu, select_bezier_subtract, NULL);
break;
case SELECT_INVERT:
icu_keys_bezier_loop(icu, select_bezier_invert, NULL);
break;
}
}
#endif
void select_icu_key(Scene *scene, IpoCurve *icu, float selx, short selectmode)
{
/* Selects all bezier triples in the Ipocurve
* at time selx, using the selection mode.
* This is kind of sloppy the obvious similarities
* with the above function, forgive me ...
*/
BeztEditFunc select_cb;
BezTriple *bezt;
int i;
/* If the icu is no good then return */
if (icu == NULL)
return;
/* Set the selection function based on the selection mode. */
switch (selectmode) {
case SELECT_ADD:
select_cb = select_bezier_add;
break;
case SELECT_SUBTRACT:
select_cb = select_bezier_subtract;
break;
case SELECT_INVERT:
select_cb = select_bezier_invert;
break;
default:
return;
}
/* loop through all of the bezier triples in
* the Ipocurve -- if the triple occurs at
* time selx then select it using the selection
* function
*/
for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
if (bezt->vec[1][0] == selx) {
select_cb(scene, bezt);
}
}
}
void select_ipo_key(Scene *scene, Ipo *ipo, float selx, short selectmode)
{
/* Selects all bezier triples in each Ipocurve of the
* Ipo at time selx, using the selection mode.
*/
IpoCurve *icu;
BezTriple *bezt;
BeztEditFunc select_cb;
int i;
/* If the ipo is no good then return */
if (ipo == NULL)
return;
/* Set the selection function based on the
* selection mode.
*/
select_cb= ANIM_editkeyframes_select(selectmode);
if (select_cb == NULL)
return;
/* loop through all of the bezier triples in all
* of the Ipocurves -- if the triple occurs at
* time selx then select it using the selection
* function
*/
for (icu=ipo->curve.first; icu; icu=icu->next) {
for (i=0, bezt=icu->bezt; i<icu->totvert; i++, bezt++) {
if (bezt->vec[1][0] == selx) {
select_cb(scene, bezt);
}
}
}
}

View File

@@ -32,6 +32,9 @@
struct ID;
struct ListBase;
struct bContext;
struct wmWindowManager;
struct ScrArea;
struct ARegion;
struct View2D;
struct gla2DDrawInfo;
struct Object;
@@ -54,6 +57,7 @@ typedef struct bAnimContext {
short spacetype; /* sa->spacetype */
short regiontype; /* active region -> type (channels or main) */
struct ScrArea *sa; /* editor */
struct ARegion *ar; /* region within editor */
struct Scene *scene; /* active scene */
struct Object *obact; /* active object */
@@ -215,7 +219,7 @@ typedef enum eAnimFilter_Flags {
/* ---------------- API -------------------- */
/* Obtain list of filtered Animation channels to operate on */
void ANIM_animdata_filter(struct ListBase *anim_data, int filter_mode, void *data, short datatype);
int ANIM_animdata_filter(struct ListBase *anim_data, int filter_mode, void *data, short datatype);
/* Obtain current anim-data context from Blender Context info */
/** Example usage (example to be removed...):
@@ -268,9 +272,12 @@ unsigned int ipo_rainbow(int cur, int tot);
/* Obtain the Object providing NLA-scaling for the given channel if applicable */
struct Object *ANIM_nla_mapping_get(bAnimContext *ac, bAnimListElem *ale);
/* set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time */
/* Set/clear temporary mapping of coordinates from 'local-action' time to 'global-nla-scaled' time */
void ANIM_nla_mapping_draw(struct gla2DDrawInfo *di, struct Object *ob, short restore);
/* Apply/Unapply NLA mapping to all keyframes in the nominated IPO block */
void ANIM_nla_mapping_apply(struct Object *ob, struct Ipo *ipo, short restore, short only_keys);
/* ------------- xxx macros ----------------------- */
#define BEZSELECTED(bezt) ((bezt->f2 & SELECT) || (bezt->f1 & SELECT) || (bezt->f3 & SELECT))

View File

@@ -0,0 +1,104 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef ED_KEYFRAMES_EDIT_H
#define ED_KEYFRAMES_EDIT_H
struct Ipo;
struct IpoCurve;
struct BezTriple;
struct Scene;
/* ************************************************ */
/* Common Macros and Defines */
/* --------- BezTriple Selection ------------- */
#define BEZSELECTED(bezt) ((bezt->f2 & SELECT) || (bezt->f1 & SELECT) || (bezt->f3 & SELECT))
#define BEZ_SEL(bezt) { (bezt)->f1 |= SELECT; (bezt)->f2 |= SELECT; (bezt)->f3 |= SELECT; }
#define BEZ_DESEL(bezt) { (bezt)->f1 &= ~SELECT; (bezt)->f2 &= ~SELECT; (bezt)->f3 &= ~SELECT; }
#define BEZ_INVSEL(bezt) { (bezt)->f1 ^= SELECT; (bezt)->f2 ^= SELECT; (bezt)->f3 ^= SELECT; }
/* --------- Tool Flags ------------ */
/* select tools */
typedef enum eEditKeyframes_Select {
SELECT_REPLACE = (1<<0),
SELECT_ADD = (1<<1),
SELECT_SUBTRACT = (1<<2),
SELECT_INVERT = (1<<4),
} eEditKeyframes_Select;
/* snapping tools */
typedef enum eEditKeyframes_Snap {
SNAP_KEYS_NEARFRAME = 1,
SNAP_KEYS_CURFRAME,
SNAP_KEYS_NEARMARKER,
SNAP_KEYS_NEARSEC,
} eEditKeyframes_Snap;
/* mirroring tools */
//typedef enum eEditKeyframes_Mirror {
//} eEditKeyframes_Mirror;
/* ************************************************ */
/* Editing API */
/* ------- Function Pointer Typedefs --------------- */
/* callback function that refreshes the IPO curve after use */
typedef void (*IcuEditFunc)(struct IpoCurve *icu);
typedef short (*BeztEditFunc)(struct Scene *scene, struct BezTriple *bezt);
/* ------------- Looping API ------------------- */
short icu_keys_bezier_loop(struct Scene *scene, struct IpoCurve *icu, BeztEditFunc bezt_cb, IcuEditFunc icu_cb);
short ipo_keys_bezier_loop(struct Scene *scene, struct Ipo *ipo, BeztEditFunc bezt_cb, IcuEditFunc icu_cb);
/* ------------ BezTriple Callback Getters --------------- */
BeztEditFunc ANIM_editkeyframes_snap(short mode);
BeztEditFunc ANIM_editkeyframes_mirror(short mode);
BeztEditFunc ANIM_editkeyframes_select(short mode);
BeztEditFunc ANIM_editkeyframes_handles(short mode);
BeztEditFunc ANIM_editkeyframes_ipo(short mode);
/* ------------ Helper Funcs -------------- */
// XXX will these be needed to set globals for some funcs?
/* ************************************************ */
void select_ipo_key(struct Scene *scene, struct Ipo *ipo, float selx, short selectmode);
void select_icu_key(struct Scene *scene, struct IpoCurve *icu, float selx, short selectmode);
/* ************************************************ */
#endif /* ED_KEYFRAMES_EDIT_H */

View File

@@ -28,6 +28,7 @@
#ifndef ED_MARKERS_H
#define ED_MARKERS_H
/* flags for drawing markers */
enum {
DRAW_MARKERS_LINES = (1<<0),
@@ -35,8 +36,9 @@ enum {
};
struct wmWindowManager;
struct bContext;
void draw_markers_time(const bContext *C, int flag);
void draw_markers_time(const struct bContext *C, int flag);
/* called in screen_ops.c:ED_operatortypes_screen() */
void ED_marker_operatortypes(void);

View File

@@ -167,8 +167,12 @@ void UI_view2d_to_region_no_clip(struct View2D *v2d, float x, float y, short *re
/* utilities */
struct View2D *UI_view2d_fromcontext(const struct bContext *C);
struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C);
void UI_view2d_getscale(struct View2D *v2d, float *x, float *y);
short UI_view2d_mouse_in_scrollers(const struct bContext *C, struct View2D *v2d, int x, int y);
/* operators */
void ui_view2d_operatortypes(void);
void UI_view2d_keymap(struct wmWindowManager *wm);

View File

@@ -1689,3 +1689,32 @@ void UI_view2d_getscale(View2D *v2d, float *x, float *y)
if (y) *y = (v2d->mask.ymax - v2d->mask.ymin) / (v2d->cur.ymax - v2d->cur.ymin);
}
/* Check if mouse is within scrollers
* - Returns appropriate code for match
* 'h' = in horizontal scroller
* 'v' = in vertical scroller
* 0 = not in scroller
*
* - x,y = mouse coordinates in screen (not region) space
*/
short UI_view2d_mouse_in_scrollers (const bContext *C, View2D *v2d, int x, int y)
{
ARegion *ar= CTX_wm_region(C);
int co[2];
/* clamp x,y to region-coordinates first */
co[0]= x - ar->winrct.xmin;
co[1]= y - ar->winrct.ymin;
/* check if within scrollbars */
if (v2d->scroll & V2D_SCROLL_HORIZONTAL) {
if (IN_2D_HORIZ_SCROLL(v2d, co)) return 'h';
}
if (v2d->scroll & V2D_SCROLL_VERTICAL) {
if (IN_2D_VERT_SCROLL(v2d, co)) return 'v';
}
/* not found */
return 0;
}

View File

@@ -53,38 +53,6 @@
#include "UI_resources.h"
#include "UI_view2d.h"
/* ********************************************************* */
/* General Polling Funcs */
/* Check if mouse is within scrollbars
* - Returns appropriate code for match
* 'h' = in horizontal scrollbar
* 'v' = in vertical scrollbar
* 0 = not in scrollbar
*
* - x,y = mouse coordinates in screen (not region) space
*/
static short mouse_in_v2d_scrollers (const bContext *C, View2D *v2d, int x, int y)
{
ARegion *ar= CTX_wm_region(C);
int co[2];
/* clamp x,y to region-coordinates first */
co[0]= x - ar->winrct.xmin;
co[1]= y - ar->winrct.ymin;
/* check if within scrollbars */
if (v2d->scroll & V2D_SCROLL_HORIZONTAL) {
if (IN_2D_HORIZ_SCROLL(v2d, co)) return 'h';
}
if (v2d->scroll & V2D_SCROLL_VERTICAL) {
if (IN_2D_VERT_SCROLL(v2d, co)) return 'v';
}
/* not found */
return 0;
}
/* ********************************************************* */
/* VIEW PANNING OPERATOR */
@@ -1106,7 +1074,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
v2d= &ar->v2d;
/* check if mouse in scrollbars, if they're enabled */
in_scroller= mouse_in_v2d_scrollers(C, v2d, event->x, event->y);
in_scroller= UI_view2d_mouse_in_scrollers(C, v2d, event->x, event->y);
/* if in a scroller, init customdata then set modal handler which will catch mousedown to start doing useful stuff */
if (in_scroller) {

View File

@@ -3,7 +3,7 @@ Import ('env')
sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../makesrna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
env.BlenderLib ( 'bf_editors_space_action', sources, Split(incs), [], libtype=['core','intern'], priority=[33, 37] )

View File

@@ -32,6 +32,8 @@ struct bContext;
struct bAnimContext;
struct SpaceAction;
struct ARegion;
struct wmWindowManager;
struct wmOperatorType;
/* internal exports only */
@@ -42,6 +44,12 @@ void draw_channel_strips(struct bAnimContext *ac, struct SpaceAction *saction, s
/* action_header.c */
void action_header_buttons(const struct bContext *C, struct ARegion *ar);
/* action_select.c */
void ED_ACT_OT_keyframes_clickselect(struct wmOperatorType *ot);
/* action_ops.c */
void action_operatortypes(void);
void action_keymap(struct wmWindowManager *wm);
#endif /* ED_ACTION_INTERN_H */

View File

@@ -0,0 +1,91 @@
/**
* $Id:
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2008 Blender Foundation.
* All rights reserved.
*
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include <math.h>
#include "MEM_guardedalloc.h"
#include "DNA_listBase.h"
#include "DNA_action_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_windowmanager_types.h"
#include "BLI_blenlib.h"
#include "BKE_context.h"
#include "BKE_utildefines.h"
#include "UI_interface.h"
#include "UI_view2d.h"
#include "action_intern.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
/* ************************** registration - operator types **********************************/
void action_operatortypes(void)
{
/* channels */
/* keyframes */
WM_operatortype_append(ED_ACT_OT_keyframes_clickselect);
}
/* ************************** registration - keymaps **********************************/
static void action_keymap_keyframes (ListBase *keymap)
{
/* click-select */
WM_keymap_add_item(keymap, "ED_ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
RNA_boolean_set(WM_keymap_add_item(keymap, "ED_ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "extend_select", 1);
RNA_boolean_set(WM_keymap_add_item(keymap, "ED_ACT_OT_keyframes_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0)->ptr, "left_right", 1);
}
/* --------------- */
void action_keymap(wmWindowManager *wm)
{
ListBase *keymap;
/* channels */
keymap= WM_keymap_listbase(wm, "Action_Channels", SPACE_ACTION, 0);
/* keyframes */
keymap= WM_keymap_listbase(wm, "Action_Keys", SPACE_ACTION, 0);
action_keymap_keyframes(keymap);
}

View File

@@ -0,0 +1,551 @@
/**
* $Id: editaction.c 17746 2008-12-08 11:19:44Z aligorith $
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <float.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "DNA_listBase.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_curve_types.h"
#include "DNA_ipo_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_constraint_types.h"
#include "DNA_key_types.h"
#include "DNA_lamp_types.h"
#include "DNA_material_types.h"
#include "DNA_userdef_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_windowmanager_types.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "BKE_action.h"
#include "BKE_depsgraph.h"
#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_material.h"
#include "BKE_object.h"
#include "BKE_context.h"
#include "BKE_utildefines.h"
#include "UI_view2d.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
#include "ED_keyframes_draw.h"
#include "ED_keyframes_edit.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "WM_api.h"
#include "WM_types.h"
/* ************************************************************************** */
/* GENERAL STUFF */
#if 0
/* this function finds the channel that mouse is floating over */
void *get_nearest_act_channel (short mval[], short *ret_type, void **owner)
{
ListBase act_data = {NULL, NULL};
bActListElem *ale;
void *data;
short datatype;
int filter;
int clickmin, clickmax;
float x,y;
/* init 'owner' return val */
*owner= NULL;
/* determine what type of data we are operating on */
data = get_action_context(&datatype);
if (data == NULL) {
*ret_type= ACTTYPE_NONE;
return NULL;
}
areamouseco_to_ipoco(G.v2d, mval, &x, &y);
clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP));
clickmax = clickmin;
if (clickmax < 0) {
*ret_type= ACTTYPE_NONE;
return NULL;
}
/* filter data */
filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
actdata_filter(&act_data, filter, data, datatype);
for (ale= act_data.first; ale; ale= ale->next) {
if (clickmax < 0)
break;
if (clickmin <= 0) {
/* found match */
*ret_type= ale->type;
data= ale->data;
/* if an 'ID' has been set, this takes presidence as owner (for dopesheet) */
if (datatype == ACTCONT_DOPESHEET) {
/* return pointer to ID as owner instead */
if (ale->id)
*owner= ale->id;
else
*owner= ale->owner;
}
else {
/* just use own owner */
*owner= ale->owner;
}
BLI_freelistN(&act_data);
return data;
}
--clickmin;
--clickmax;
}
/* cleanup */
BLI_freelistN(&act_data);
*ret_type= ACTTYPE_NONE;
return NULL;
}
#endif
/* used only by mouse_action. It is used to find the location of the nearest
* keyframe to where the mouse clicked,
*/
static void *get_nearest_action_key (bAnimContext *ac, int mval[2], float *selx, short *sel, short *ret_type, bActionChannel **par)
{
ListBase anim_data = {NULL, NULL};
ListBase anim_keys = {NULL, NULL};
bAnimListElem *ale;
ActKeyColumn *ak;
View2D *v2d= &ac->ar->v2d;
int filter;
rctf rectf;
void *data = NULL;
float xmin, xmax, x, y;
int clickmin, clickmax;
short found = 0;
/* action-channel */
*par= NULL;
UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
clickmin = (int) (((ACHANNEL_HEIGHT_HALF) - y) / (ACHANNEL_STEP)); // xxx max y-co (first) is -ACHANNEL_HEIGHT
clickmax = clickmin;
/* x-range to check is +/- 7 on either side of mouse click (size of keyframe icon) */
UI_view2d_region_to_view(v2d, mval[0]-7, mval[1], &rectf.xmin, &rectf.ymin);
UI_view2d_region_to_view(v2d, mval[0]+7, mval[1], &rectf.xmax, &rectf.ymax);
if (clickmax < 0) {
*ret_type= ANIMTYPE_NONE;
return NULL;
}
/* filter data */
filter= (ANIMFILTER_FORDRAWING | ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
for (ale= anim_data.first; ale; ale= ale->next) {
if (clickmax < 0)
break;
if (clickmin <= 0) {
/* found match - must return here... */
Object *nob= ANIM_nla_mapping_get(ac, ale);
/* apply NLA-scaling correction? */
if (nob) {
xmin= get_action_frame(nob, rectf.xmin);
xmax= get_action_frame(nob, rectf.xmax);
}
else {
xmin= rectf.xmin;
xmax= rectf.xmax;
}
/* make list of keyframes */
if (ale->key_data) {
switch (ale->datatype) {
case ALE_OB:
{
Object *ob= (Object *)ale->key_data;
ob_to_keylist(ob, &anim_keys, NULL, NULL);
}
break;
case ALE_ACT:
{
bAction *act= (bAction *)ale->key_data;
action_to_keylist(act, &anim_keys, NULL, NULL);
}
break;
case ALE_IPO:
{
Ipo *ipo= (Ipo *)ale->key_data;
ipo_to_keylist(ipo, &anim_keys, NULL, NULL);
}
break;
case ALE_ICU:
{
IpoCurve *icu= (IpoCurve *)ale->key_data;
icu_to_keylist(icu, &anim_keys, NULL, NULL);
}
break;
}
}
else if (ale->type == ANIMTYPE_GROUP) {
bActionGroup *agrp= (bActionGroup *)ale->data;
agroup_to_keylist(agrp, &anim_keys, NULL, NULL);
}
else if (ale->type == ANIMTYPE_GPDATABLOCK) {
/* cleanup */
BLI_freelistN(&anim_data);
/* this channel currently doens't have any keyframes... must ignore! */
*ret_type= ANIMTYPE_NONE;
return NULL;
}
else if (ale->type == ANIMTYPE_GPLAYER) {
bGPDlayer *gpl= (bGPDlayer *)ale->data;
gpl_to_keylist(gpl, &anim_keys, NULL, NULL);
}
/* loop through keyframes, finding one that was clicked on */
for (ak= anim_keys.first; ak; ak= ak->next) {
if (IN_RANGE(ak->cfra, xmin, xmax)) {
*selx= ak->cfra;
found= 1;
break;
}
}
/* no matching keyframe found - set to mean frame value so it doesn't actually select anything */
if (found == 0)
*selx= ((xmax+xmin) / 2);
/* figure out what to return */
if (ac->datatype == ANIMCONT_ACTION) {
*par= ale->owner; /* assume that this is an action channel */
*ret_type= ale->type;
data = ale->data;
}
else if (ac->datatype == ANIMCONT_SHAPEKEY) {
data = ale->key_data;
*ret_type= ANIMTYPE_ICU;
}
else if (ac->datatype == ANIMCONT_DOPESHEET) {
data = ale->data;
*ret_type= ale->type;
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
data = ale->data;
*ret_type= ANIMTYPE_GPLAYER;
}
/* cleanup tempolary lists */
BLI_freelistN(&anim_keys);
anim_keys.first = anim_keys.last = NULL;
BLI_freelistN(&anim_data);
return data;
}
--clickmin;
--clickmax;
}
/* cleanup */
BLI_freelistN(&anim_data);
*ret_type= ANIMTYPE_NONE;
return NULL;
}
/* ************************************************************************** */
/* CHANNEL STUFF */
/* ************************************************************************** */
/* KEYFRAMES STUFF */
/* ******************** Column Select Operator **************************** */
/* ******************** Mouse-Click Select Operator *********************** */
/* This operator works in one of four ways:
* - main area
* -> 1) without alt-key - selects keyframe that was under mouse position
* -> 2) with alt-key - only those keyframes on same side of current frame
* - 3) horizontal scroller (*) - select all keyframes in frame (err... maybe integrate this with column select only)?
* - 4) vertical scroller (*) - select all keyframes in channel
*
* (*) - these are not obviously presented in UI. We need to find a new way to showcase them.
*/
/* option 1) select keyframe directly under mouse */
static void mouse_action_keys (bAnimContext *ac, int mval[2], short selectmode)
{
Object *ob= NULL;
bDopeSheet *ads= NULL;
bAction *act= NULL;
bActionGroup *agrp= NULL;
bActionChannel *achan= NULL;
bConstraintChannel *conchan= NULL;
Ipo *ipo= NULL;
IpoCurve *icu= NULL;
bGPdata *gpd = NULL;
bGPDlayer *gpl = NULL;
void *act_channel;
short sel, act_type = 0;
float selx = 0.0f, selxa;
/* determine what type of data we are operating on */
if (ac->datatype == ANIMCONT_ACTION)
act= (bAction *)ac->data;
else if (ac->datatype == ANIMCONT_DOPESHEET)
ads= (bDopeSheet *)ac->data;
else if (ac->datatype == ANIMCONT_GPENCIL)
gpd= (bGPdata *)ac->data;
act_channel= get_nearest_action_key(ac, mval, &selx, &sel, &act_type, &achan);
if (act_channel) {
/* must have been a channel */
switch (act_type) {
case ANIMTYPE_ICU:
icu= (IpoCurve *)act_channel;
break;
case ANIMTYPE_CONCHAN:
conchan= (bConstraintChannel *)act_channel;
break;
case ANIMTYPE_ACHAN:
achan= (bActionChannel *)act_channel;
break;
case ANIMTYPE_GROUP:
agrp= (bActionGroup *)act_channel;
break;
case ANIMTYPE_DSMAT:
ipo= ((Material *)act_channel)->ipo;
break;
case ANIMTYPE_DSLAM:
ipo= ((Lamp *)act_channel)->ipo;
break;
case ANIMTYPE_DSCAM:
ipo= ((Camera *)act_channel)->ipo;
break;
case ANIMTYPE_DSCUR:
ipo= ((Curve *)act_channel)->ipo;
break;
case ANIMTYPE_DSSKEY:
ipo= ((Key *)act_channel)->ipo;
break;
case ANIMTYPE_FILLACTD:
act= (bAction *)act_channel;
break;
case ANIMTYPE_FILLIPOD:
ipo= ((Object *)act_channel)->ipo;
break;
case ANIMTYPE_OBJECT:
ob= ((Base *)act_channel)->object;
break;
case ANIMTYPE_GPLAYER:
gpl= (bGPDlayer *)act_channel;
break;
default:
return;
}
if (selectmode == SELECT_REPLACE) {
selectmode = SELECT_ADD;
//deselect_action_keys(0, 0); // XXX fixme
if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
//deselect_action_channels(0);
/* Highlight either an Action-Channel or Action-Group */
if (achan) {
achan->flag |= ACHAN_SELECTED;
//hilight_channel(act, achan, 1);
//select_poseelement_by_name(achan->name, 2); /* 2 is activate */
}
else if (agrp) {
agrp->flag |= AGRP_SELECTED;
//set_active_actiongroup(act, agrp, 1);
}
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
//deselect_action_channels(0);
/* Highlight gpencil layer */
gpl->flag |= GP_LAYER_SELECT;
//gpencil_layer_setactive(gpd, gpl);
}
}
if (icu)
select_icu_key(ac->scene, icu, selx, selectmode);
else if (ipo)
select_ipo_key(ac->scene, ipo, selx, selectmode);
else if (conchan)
select_ipo_key(ac->scene, conchan->ipo, selx, selectmode);
else if (achan)
select_ipo_key(ac->scene, achan->ipo, selx, selectmode);
else if (agrp) {
for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
select_ipo_key(ac->scene, achan->ipo, selx, selectmode);
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
select_ipo_key(ac->scene, conchan->ipo, selx, selectmode);
}
}
else if (act) {
for (achan= act->chanbase.first; achan; achan= achan->next) {
select_ipo_key(ac->scene, achan->ipo, selx, selectmode);
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
select_ipo_key(ac->scene, conchan->ipo, selx, selectmode);
}
}
else if (ob) {
if (ob->ipo)
select_ipo_key(ac->scene, ob->ipo, selx, selectmode);
if (ob->action) {
selxa= get_action_frame(ob, selx);
for (achan= ob->action->chanbase.first; achan; achan= achan->next) {
select_ipo_key(ac->scene, achan->ipo, selxa, selectmode);
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
select_ipo_key(ac->scene, conchan->ipo, selxa, selectmode);
}
}
for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next)
select_ipo_key(ac->scene, conchan->ipo, selx, selectmode);
}
//else if (gpl)
// select_gpencil_frame(gpl, (int)selx, selectmode);
}
}
/* ------------------- */
static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event)
{
bAnimContext ac;
ARegion *ar;
short in_scroller, selectmode;
int mval[2];
puts("Action click select invoke");
/* get editor data */
if ((ANIM_animdata_get_context(C, &ac) == 0) || (ac.data == NULL))
return OPERATOR_CANCELLED;
/* get useful pointers from animation context data */
ar= ac.ar;
/* get mouse coordinates (in region coordinates) */
mval[0]= (event->x - ar->winrct.xmin);
mval[1]= (event->y - ar->winrct.ymin);
/* check where in view mouse is */
in_scroller = UI_view2d_mouse_in_scrollers(C, &ar->v2d, event->x, event->y);
/* select mode is either replace (deselect all, then add) or add/extend */
if (RNA_boolean_get(op->ptr, "extend_select"))
selectmode= SELECT_ADD;
else
selectmode= SELECT_REPLACE;
/* check which scroller mouse is in, and figure out how to handle this */
if (in_scroller == 'h') {
/* horizontal - column select in current frame */
// FIXME.... todo
}
else if (in_scroller == 'v') {
/* vertical - row select in current channel */
// FIXME...
}
else if (RNA_boolean_get(op->ptr, "left_right")) {
/* select all keys on same side of current frame as mouse */
}
else {
/* select keyframe under mouse */
mouse_action_keys(&ac, mval, selectmode);
// XXX activate transform...
}
/* set notifier tha things have changed */
ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead!
return OPERATOR_FINISHED;
}
void ED_ACT_OT_keyframes_clickselect (wmOperatorType *ot)
{
/* identifiers */
ot->name= "Mouse Select Keys";
ot->idname= "ED_ACT_OT_keyframes_clickselect";
/* api callbacks */
ot->invoke= actkeys_clickselect_invoke;
//ot->poll= ED_operator_areaactive;
/* id-props */
RNA_def_property(ot->srna, "left_right", PROP_BOOLEAN, PROP_NONE); // ALTKEY
RNA_def_property(ot->srna, "extend_select", PROP_BOOLEAN, PROP_NONE); // SHIFTKEY
}
/* ************************************************************************** */

View File

@@ -159,7 +159,7 @@ static void action_main_area_init(wmWindowManager *wm, ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
/* own keymap */
keymap= WM_keymap_listbase(wm, "Action", SPACE_ACTION, 0); /* XXX weak? */
keymap= WM_keymap_listbase(wm, "Action_Keys", SPACE_ACTION, 0); /* XXX weak? */
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
@@ -214,16 +214,6 @@ static void action_main_area_draw(const bContext *C, ARegion *ar)
UI_view2d_scrollers_free(scrollers);
}
void action_operatortypes(void)
{
}
void action_keymap(struct wmWindowManager *wm)
{
}
/* add handlers, stuff you only do once or on area/region changes */
static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
{
@@ -232,7 +222,7 @@ static void action_channel_area_init(wmWindowManager *wm, ARegion *ar)
UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
/* own keymap */
keymap= WM_keymap_listbase(wm, "Action", SPACE_ACTION, 0); /* XXX weak? */
keymap= WM_keymap_listbase(wm, "Action_Channels", SPACE_ACTION, 0); /* XXX weak? */
WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
}
@@ -298,6 +288,11 @@ static void action_header_area_draw(const bContext *C, ARegion *ar)
static void action_main_area_listener(ARegion *ar, wmNotifier *wmn)
{
/* context changes */
switch(wmn->type) {
case WM_NOTE_MARKERS_CHANGED:
ED_region_tag_redraw(ar);
break;
}
}
/* only called once, from space/spacetypes.c */