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:
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************** */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/* ************************************************************ */
|
||||
|
||||
785
source/blender/editors/animation/keyframes_edit.c
Normal file
785
source/blender/editors/animation/keyframes_edit.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
104
source/blender/editors/include/ED_keyframes_edit.h
Normal file
104
source/blender/editors/include/ED_keyframes_edit.h
Normal 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 */
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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] )
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
91
source/blender/editors/space_action/action_ops.c
Normal file
91
source/blender/editors/space_action/action_ops.c
Normal 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);
|
||||
}
|
||||
|
||||
551
source/blender/editors/space_action/action_select.c
Normal file
551
source/blender/editors/space_action/action_select.c
Normal 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
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user