diff options
-rw-r--r-- | source/blender/include/BIF_editaction.h | 85 | ||||
-rw-r--r-- | source/blender/include/BSE_editaction_types.h | 75 | ||||
-rw-r--r-- | source/blender/include/BSE_editipo.h | 1 | ||||
-rw-r--r-- | source/blender/src/drawaction.c | 10 | ||||
-rw-r--r-- | source/blender/src/editaction.c | 4934 | ||||
-rw-r--r-- | source/blender/src/editipo_mods.c | 49 | ||||
-rw-r--r-- | source/blender/src/editnla.c | 3 | ||||
-rw-r--r-- | source/blender/src/header_action.c | 201 |
8 files changed, 2050 insertions, 3308 deletions
diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 6e180418cd8..838bbb5c34c 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -33,21 +33,11 @@ #ifndef BIF_EDITACTION_H #define BIF_EDITACTION_H -#define SET_IPO_POPUP 0 -#define SET_IPO_CONSTANT 1 -#define SET_IPO_LINEAR 2 -#define SET_IPO_BEZIER 3 - -#define SET_EXTEND_POPUP 0 -#define SET_EXTEND_CONSTANT 1 -#define SET_EXTEND_EXTRAPOLATION 2 -#define SET_EXTEND_CYCLIC 3 -#define SET_EXTEND_CYCLICEXTRAPOLATION 4 - +/* some interface related sizes*/ #define CHANNELHEIGHT 16 #define CHANNELSKIP 2 -#define NAMEWIDTH 164 -#define SLIDERWIDTH 125 +#define NAMEWIDTH 164 +#define SLIDERWIDTH 125 #define ACTWIDTH (G.saction->actwidth) /* Some types for easier type-testing */ @@ -57,6 +47,8 @@ #define ACTTYPE_ICU 3 #define ACTTYPE_FILLIPO 4 #define ACTTYPE_FILLCON 5 +#define ACTTYPE_IPO 6 +#define ACTTYPE_SHAPEKEY 7 /* Macros for easier/more consistant state testing */ #define VISIBLE_ACHAN(achan) ((achan->flag & ACHAN_HIDDEN)==0) @@ -72,6 +64,19 @@ #define EDITABLE_ICU(icu) ((icu->flag & IPO_PROTECT)==0) #define SEL_ICU(icu) (icu->flag & IPO_SELECT) +/* constants for setting ipo-interpolation type */ +#define SET_IPO_POPUP 0 +#define SET_IPO_CONSTANT 1 +#define SET_IPO_LINEAR 2 +#define SET_IPO_BEZIER 3 + +/* constants for setting ipo-extrapolation type */ +#define SET_EXTEND_POPUP 10 +#define SET_EXTEND_CONSTANT 11 +#define SET_EXTEND_EXTRAPOLATION 12 +#define SET_EXTEND_CYCLIC 13 +#define SET_EXTEND_CYCLICEXTRAPOLATION 14 + struct bAction; struct bActionChannel; struct bPoseChannel; @@ -82,21 +87,18 @@ struct Key; struct ListBase; /* Key operations */ -void delete_meshchannel_keys(struct Key *key); -void delete_actionchannel_keys(void); -void duplicate_meshchannel_keys(struct Key *key); -void duplicate_actionchannel_keys(void); -void transform_actionchannel_keys(int mode, int dummy); -void transform_meshchannel_keys(char mode, struct Key *key); -void snap_keys_to_frame(int snap_mode); -void mirror_action_keys(short mirror_mode); -void clean_shapekeys(struct Key *key); -void clean_actionchannels(struct bAction *act); +void transform_action_keys(int mode, int dummy); +void duplicate_action_keys(void); +void snap_action_keys(short mode); +void mirror_action_keys(short mode); void insertkey_action(void); +void delete_action_keys(void); +void delete_action_channels(void); +void clean_action(void); -/* Marker Operations */ -void column_select_shapekeys(struct Key *key, int mode); -void column_select_actionkeys(struct bAction *act, int mode); +/* Column/Channel Key select */ +void column_select_action_keys(int mode); +void selectall_action_keys(short mval[], short mode, short selectmode); void markers_selectkeys_between(void); /* channel/strip operations */ @@ -105,20 +107,15 @@ void down_sel_action(void); void top_sel_action(void); void bottom_sel_action(void); -/* Handles */ -void sethandles_meshchannel_keys(int code, struct Key *key); -void sethandles_actionchannel_keys(int code); - -/* Ipo type */ -void set_ipotype_actionchannels(int ipotype); -void set_extendtype_actionchannels(int extendtype); +/* IPO/Handle Types */ +void sethandles_action_keys(int code); +void action_set_ipo_flags(int mode); /* Select */ -void borderselect_mesh(struct Key *key); void borderselect_action(void); -void deselect_actionchannel_keys(struct bAction *act, int test, int sel); -void deselect_actionchannels (struct bAction *act, int test); -void deselect_meshchannel_keys (struct Key *key, int test, int sel); +void deselect_action_keys(short test, short sel); +void deselect_action_channels(short test); +void deselect_actionchannels(struct bAction *act, short test); int select_channel(struct bAction *act, struct bActionChannel *achan, int selectmode); void select_actionchannel_by_name (struct bAction *act, char *name, int select); @@ -128,19 +125,17 @@ int get_nearest_key_num(struct Key *key, short *mval, float *x); void *get_nearest_act_channel(short mval[], short *ret_type); /* Action */ -struct bActionChannel* get_hilighted_action_channel(struct bAction* action); +struct bActionChannel *get_hilighted_action_channel(struct bAction* action); struct bAction *add_empty_action(char *name); - -void winqreadactionspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt); - -/* contextual get action */ struct bAction *ob_get_action(struct Object *ob); +void actdata_filter(ListBase *act_data, int filter_mode, void *data, short datatype); +void *get_action_context(short *datatype); + void remake_action_ipos(struct bAction *act); -/* this needs review badly! (ton) */ -struct bAction *bake_action_with_client (struct bAction *act, struct Object *arm, float tolerance); -void world2bonespace(float boneSpaceMat[][4], float worldSpace[][4], float restPos[][4], float armPos[][4]); +/* event handling */ +void winqreadactionspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt); #endif diff --git a/source/blender/include/BSE_editaction_types.h b/source/blender/include/BSE_editaction_types.h new file mode 100644 index 00000000000..c4f78710d2d --- /dev/null +++ b/source/blender/include/BSE_editaction_types.h @@ -0,0 +1,75 @@ +/** + * $Id: BIF_editaction.h 10519 2007-04-13 11:15:08Z aligorith $ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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): 2007, Joshua Leung (major Action Editor recode) + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BIF_EDITACTION_TYPES_H +#define BIF_EDITACTION_TYPES_H + +/******************************************************* */ +/* FILTERED ACTION DATA - TYPES */ + +/* types of keyframe data in ActListElem */ +#define ALE_NONE 0 +#define ALE_IPO 1 +#define ALE_ICU 2 + +/* This struct defines a structure used for quick access */ +typedef struct bActListElem { + struct bActListElem *next, *prev; + + void *data; /* source data this elem represents */ + int type; /* one of the ACTTYPE_* values */ + int flag; /* copy of elem's flags for quick access */ + + void *key_data; /* motion data - ipo or ipo-curve */ + short datatype; /* type of motion data to expect */ + + void *owner; /* will either be an action channel or fake ipo-channel (for keys) */ + short ownertype; /* type of owner */ +} bActListElem; + +/******************************************************* */ +/* FILTER ACTION DATA - METHODS/TYPES */ + +/* filtering flags - under what circumstances should a channel be added */ +#define ACTFILTER_VISIBLE 0x001 /* should channels be visible */ +#define ACTFILTER_SEL 0x002 /* should channels be selected */ +#define ACTFILTER_FOREDIT 0x004 /* does editable status matter */ +#define ACTFILTER_CHANNELS 0x008 /* do we only care that it is a channel */ +#define ACTFILTER_IPOKEYS 0x010 /* only channels referencing ipo's */ +#define ACTFILTER_ONLYICU 0x020 /* only reference ipo-curves */ + +/* Action Editor - Main Data types */ +#define ACTCONT_NONE 0 +#define ACTCONT_ACTION 1 +#define ACTCONT_SHAPEKEY 2 + +#endif diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index 01f985018ed..f861a2abd7a 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -107,6 +107,7 @@ void ipo_mirror(short event); void mouse_select_ipo(void); void sethandles_ipo(int code); void select_ipo_bezier_keys(struct Ipo *ipo, int selectmode); +void select_icu_bezier_keys(struct IpoCurve *icu, int selectmode); void set_ipotype(void); void borderselect_ipo(void); void del_ipo(int need_check); diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index fd6f5f8f0b4..6576dac1d2c 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -110,14 +110,14 @@ static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key) * correctly *grumble* */ mywinset(curarea->win); - myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375); + myortho2(-0.375, curarea->winx-0.375, G.v2d->cur.ymin, G.v2d->cur.ymax); sprintf(str, "actionbuttonswin %d", curarea->win); block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS, UI_HELV, curarea->win); x = NAMEWIDTH + 1; - y = key->totkey*(CHANNELHEIGHT+CHANNELSKIP) + CHANNELHEIGHT/2 - G.v2d->cur.ymin; + y = CHANNELHEIGHT/2; /* make the little 'open the sliders' widget */ BIF_ThemeColor(TH_FACE); // this slot was open... @@ -534,7 +534,7 @@ static void draw_action_mesh_names(Key *key) KeyBlock *kb; x = 0.0; - y= key->totkey*(CHANNELHEIGHT+CHANNELSKIP); + y= 0.0; kb= key->block.first; @@ -846,7 +846,7 @@ static void draw_mesh_strips(SpaceAction *saction, Key *key) scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; di= glaBegin2DDraw(&scr_rct, &G.v2d->cur); - ybase = key->totkey*(CHANNELHEIGHT+CHANNELSKIP); + ybase = 0; for (icu = key->ipo->curve.first; icu ; icu = icu->next) { int frame1_x, channel_y; @@ -959,7 +959,7 @@ void drawactionspace(ScrArea *sa, void *spacedata) if (G.v2d->cur.ymin < -CHANNELHEIGHT) G.v2d->cur.ymin = -CHANNELHEIGHT; - maxymin = key->totkey*(CHANNELHEIGHT+CHANNELSKIP); + maxymin = -(key->totkey*(CHANNELHEIGHT+CHANNELSKIP)); if (G.v2d->cur.ymin > maxymin) G.v2d->cur.ymin = maxymin; } diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 1b0429abda2..2fc0390b7f3 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -25,7 +25,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): 2007, Joshua Leung (major rewrite of Action Editor) * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -84,6 +84,7 @@ #include "BSE_edit.h" #include "BSE_drawipo.h" #include "BSE_headerbuttons.h" +#include "BSE_editaction_types.h" #include "BSE_editipo.h" #include "BSE_time.h" #include "BSE_trans_types.h" @@ -95,65 +96,61 @@ #include "blendef.h" #include "nla.h" -/* Local Function prototypes, are forward needed */ -static void hilight_channel (bAction *act, bActionChannel *achan, short select); +/* **************************************************** */ +/* ACTION API */ -/* messy call... */ -static void select_poseelement_by_name (char *name, int select) +/* this function adds a new Action block */ +bAction *add_empty_action (char *name) { - /* Syncs selection of channels with selection of object elements in posemode */ - Object *ob= OBACT; - bPoseChannel *pchan; + bAction *act; - if (!ob || ob->type!=OB_ARMATURE) - return; + act= alloc_libblock(&G.main->action, ID_AC, name); + act->id.flag |= LIB_FAKEUSER; + act->id.us++; - if(select==2) { - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) - pchan->bone->flag &= ~(BONE_ACTIVE); - } + return act; +} + +/* generic get current action call, for action window context */ +bAction *ob_get_action (Object *ob) +{ + bActionStrip *strip; - pchan= get_pose_channel(ob->pose, name); - if(pchan) { - if(select) - pchan->bone->flag |= (BONE_SELECTED); - else - pchan->bone->flag &= ~(BONE_SELECTED); - if(select==2) - pchan->bone->flag |= (BONE_ACTIVE); + if(ob->action) + return ob->action; + + for (strip=ob->nlastrips.first; strip; strip=strip->next) { + if (strip->flag & ACTSTRIP_SELECT) + return strip->act; } + return NULL; } -/* apparently within active object context */ -/* called extern, like on bone selection */ -void select_actionchannel_by_name (bAction *act, char *name, int select) +/* used by ipo, outliner, buttons to find the active channel */ +bActionChannel *get_hilighted_action_channel (bAction *action) { bActionChannel *achan; - if (!act) - return; + if (!action) + return NULL; - for (achan = act->chanbase.first; achan; achan= achan->next) { - if (!strcmp(achan->name, name)) { - if (select) { - achan->flag |= ACHAN_SELECTED; - hilight_channel(act, achan, 1); - } - else { - achan->flag &= ~ACHAN_SELECTED; - hilight_channel(act, achan, 0); - } - return; + for (achan= action->chanbase.first; achan; achan= achan->next) { + if(VISIBLE_ACHAN(achan)) { + if (SEL_ACHAN(achan) && (achan->flag & ACHAN_HILIGHTED)) + return achan; } } + + return NULL; } -/* called on changing action ipos or keys */ -void remake_action_ipos(bAction *act) +/* ----------------------------------------- */ + +void remake_action_ipos (bAction *act) { bActionChannel *achan; bConstraintChannel *conchan; - IpoCurve *icu; + IpoCurve *icu; for (achan= act->chanbase.first; achan; achan= achan->next) { if (achan->ipo) { @@ -175,7 +172,7 @@ void remake_action_ipos(bAction *act) synchronize_action_strips(); } -static void remake_meshaction_ipos(Ipo *ipo) +static void remake_meshaction_ipos (Ipo *ipo) { /* this puts the bezier triples in proper * order and makes sure the bezier handles @@ -189,7 +186,7 @@ static void remake_meshaction_ipos(Ipo *ipo) } } -static void meshkey_do_redraw(Key *key) +static void meshkey_do_redraw (Key *key) { if(key->ipo) remake_meshaction_ipos(key->ipo); @@ -203,37 +200,351 @@ static void meshkey_do_redraw(Key *key) } -void duplicate_meshchannel_keys(Key *key) +/* **************************************************** */ +/* FILTER->EDIT STRUCTURES */ +/* + * This method involves generating a list of edit structures which enable + * tools to naively perform the actions they require without all the boiler-plate + * associated with loops within loops and checking for cases to ignore. + */ + +/* this function allocates memory for a new bActListElem struct for the + * provided action channel-data. + */ +bActListElem *make_new_actlistelem (void *data, short datatype, void *owner, short ownertype) { - duplicate_ipo_keys(key->ipo); - transform_meshchannel_keys('g', key); + bActListElem *ale= NULL; + + /* only allocate memory if there is data to convert */ + if (data) { + /* allocate and set generic data */ + ale= MEM_callocN(sizeof(bActListElem), "bActListElem"); + + ale->data= data; + ale->type= datatype; + ale->owner= owner; + ale->ownertype= ownertype; + + /* do specifics */ + switch (datatype) { + case ACTTYPE_ACHAN: + { + bActionChannel *achan= (bActionChannel *)data; + + ale->flag= achan->flag; + + if (achan->ipo) { + ale->key_data= achan->ipo; + ale->datatype= ALE_IPO; + } + else { + ale->key_data= NULL; + ale->datatype= ALE_NONE; + } + } + break; + case ACTTYPE_CONCHAN: + { + bConstraintChannel *conchan= (bConstraintChannel *)data; + + ale->flag= conchan->flag; + + if (conchan->ipo && conchan->ipo->curve.first) { + /* we assume that constraint ipo blocks only have 1 curve: + * INFLUENCE, so we pretend that a constraint channel is + * really just a Ipo-Curve channel instead. + */ + ale->key_data= conchan->ipo->curve.first; + ale->datatype= ALE_ICU; + } + else { + ale->key_data= NULL; + ale->datatype= ALE_NONE; + } + } + break; + case ACTTYPE_ICU: + { + IpoCurve *icu= (IpoCurve *)data; + + ale->flag= icu->flag; + ale->key_data= icu; + ale->datatype= ALE_ICU; + } + break; + + case ACTTYPE_FILLIPO: + case ACTTYPE_FILLCON: + { + bActionChannel *achan= (bActionChannel *)data; + + if (datatype == ACTTYPE_FILLIPO) + ale->flag= FILTER_IPO_ACHAN(achan); + else + ale->flag= FILTER_CON_ACHAN(achan); + + ale->key_data= NULL; + ale->datatype= ALE_NONE; + } + break; + case ACTTYPE_IPO: + { + ale->flag= 0; + ale->key_data= data; + ale->datatype= ALE_IPO; + } + break; + } + } + + /* return created datatype */ + return ale; } - -void duplicate_actionchannel_keys(void) + +/* ----------------------------------------- */ + +static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode) { - bAction *act; + bActListElem *ale; bActionChannel *achan; bConstraintChannel *conchan; + IpoCurve *icu; + + /* loop over action channels, performing the necessary checks */ + for (achan= act->chanbase.first; achan; achan= achan->next) { + /* only work with this channel and its subchannels if it is visible */ + if (!(filter_mode & ACTFILTER_VISIBLE) || VISIBLE_ACHAN(achan)) { + /* only work with this channel and its subchannels if it is editable */ + if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_ACHAN(achan)) { + /* check if this achan should only be included if it is selected */ + if (!(filter_mode & ACTFILTER_SEL) || SEL_ACHAN(achan)) { + /* are we only interested in the ipo-curves? */ + if ((filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(achan, ACTTYPE_ACHAN, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); + } + } + + /* check if expanded - if not, continue on to next action channel */ + if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ACTFILTER_ONLYICU)==0) + continue; + + /* ipo channels */ + if (achan->ipo) { + /* include ipo-expand widget? */ + if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(achan, ACTTYPE_FILLIPO, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); + } + + /* add ipo-curve channels? */ + if (FILTER_IPO_ACHAN(achan) || (filter_mode & ACTFILTER_ONLYICU)) { + /* loop through ipo-curve channels, adding them */ + for (icu= achan->ipo->curve.first; icu; icu=icu->next) { + ale= make_new_actlistelem(icu, ACTTYPE_ICU, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); + } + } + } + + /* constraint channels */ + if (achan->constraintChannels.first) { + /* include constraint-expand widget? */ + if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(achan, ACTTYPE_FILLCON, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); + } + + /* add constaint channels? */ + if (FILTER_CON_ACHAN(achan)) { + /* loop through constraint channels, checking and adding them */ + for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { + /* only work with this channel and its subchannels if it is editable */ + if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_CONCHAN(conchan)) { + /* check if this conchan should only be included if it is selected */ + if (!(filter_mode & ACTFILTER_SEL) || SEL_CONCHAN(conchan)) { + if ((filter_mode & ACTFILTER_ONLYICU)==0) { + ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN, achan, ACTTYPE_ACHAN); + if (ale) BLI_addtail(act_data, ale); + } + } + } + } + } + } + } + } + } +} - act=G.saction->action; - if (!act) - return; - - /* Find selected items */ - for (achan = act->chanbase.first; achan; achan= achan->next) { - if(EDITABLE_ACHAN(achan)) { - duplicate_ipo_keys(achan->ipo); +static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mode) +{ + bActListElem *ale; + IpoCurve *icu; + + /* loop over ipo curves if present */ + if (key->ipo) { + if (filter_mode & ACTFILTER_IPOKEYS) { + ale= make_new_actlistelem(key->ipo, ACTTYPE_IPO, key, ACTTYPE_SHAPEKEY); + if (ale) BLI_addtail(act_data, ale); + } + else { + for (icu= key->ipo->curve.first; icu; icu=icu->next) { + ale= make_new_actlistelem(icu, ACTTYPE_ICU, key, ACTTYPE_SHAPEKEY); + if (ale) BLI_addtail(act_data, ale); + } + } + } +} + +/* This function filters the active data source to leave only the desired + * data types. 'Public' api call. + * *act_data: is a pointer to a ListBase, to which the filtered action data + * will be placed for use. + * filter_mode: how should the data be filtered - bitmapping accessed flags + */ +void actdata_filter (ListBase *act_data, int filter_mode, void *data, short datatype) +{ + /* only filter data if there's somewhere to put it */ + if (data && act_data) { + bActListElem *ale, *next; + + /* firstly filter the data */ + switch (datatype) { + case ACTCONT_ACTION: + actdata_filter_action(act_data, data, filter_mode); + break; + case ACTCONT_SHAPEKEY: + actdata_filter_shapekey(act_data, data, filter_mode); + break; + } - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (EDITABLE_CONCHAN(conchan)) - duplicate_ipo_keys(conchan->ipo); - } + /* remove any weedy entries */ + for (ale= act_data->first; ale; ale= next) { + next= ale->next; + + if (ale->type == ACTTYPE_NONE) + BLI_freelinkN(act_data, ale); + + if (filter_mode & ACTFILTER_IPOKEYS) { + if (ale->datatype != ALE_IPO) + BLI_freelinkN(act_data, ale); + else if (ale->key_data == NULL) + BLI_freelinkN(act_data, ale); } } } +} + +/* **************************************************** */ +/* GENERAL ACTION TOOLS */ + + +/* gets the key data from the currently selected + * mesh/lattice. If a mesh is not selected, or does not have + * key data, then we return NULL (currently only + * returns key data for RVK type meshes). If there + * is an action that is pinned, return null + */ +Key *get_action_mesh_key(void) +{ + Object *ob; + Key *key; + + ob = OBACT; + if (!ob) return NULL; + + if (G.saction->pin) return NULL; + + if (ob->type==OB_MESH ) { + key = ((Mesh *)ob->data)->key; + } + else if (ob->type==OB_LATTICE ) { + key = ((Lattice *)ob->data)->key; + } + else return NULL; - transform_actionchannel_keys ('g', 0); + if (key) { + if (key->type == KEY_RELATIVE) + return key; + } + + return NULL; +} + +/* TODO: kill this! */ +int get_nearest_key_num (Key *key, short *mval, float *x) +{ + /* returns the key num that cooresponds to the + * y value of the mouse click. Does not check + * if this is a valid keynum. Also gives the Ipo + * x coordinate. + */ + int num; + float ybase, y; + + areamouseco_to_ipoco(G.v2d, mval, x, &y); + num = (int) ((CHANNELHEIGHT/2 - y) / (CHANNELHEIGHT+CHANNELSKIP)); + + return (num + 1); +} + +/* this function is used to get a pointer to an action or shapekey + * datablock, thus simplying that process. + */ +/* this function is intended for use */ +void *get_nearest_act_channel (short mval[], short *ret_type) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + void *data; + short datatype; + int filter; + + int clickmin, clickmax; + float x,y; + + /* 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_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; + + BLI_freelistN(&act_data); + + return data; + } + --clickmin; + --clickmax; + } + + /* cleanup */ + BLI_freelistN(&act_data); + + *ret_type= ACTTYPE_NONE; + return NULL; } /* helper for get_nearest_[action,mesh]channel_key */ @@ -295,11 +606,17 @@ static IpoCurve *get_nearest_icu_key (IpoCurve *curve, float *selx, short *sel, return firsticu; } -static void *get_nearest_actionchannel_key (float *selx, short *sel, short *ret_type, bActionChannel **par) +/* 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 (float *selx, short *sel, short *ret_type, bActionChannel **par) { - bAction *act= G.saction->action; - bActionChannel *achan; - bConstraintChannel *conchan; + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + void *data; + short datatype; + int filter; + IpoCurve *icu; rctf rectf; float xmin, xmax, x, y; @@ -312,7 +629,9 @@ static void *get_nearest_actionchannel_key (float *selx, short *sel, short *ret_ /* action-channel */ *par= NULL; - if (act == NULL) { + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) { *ret_type= ACTTYPE_NONE; return NULL; } @@ -327,7 +646,7 @@ static void *get_nearest_actionchannel_key (float *selx, short *sel, short *ret_ areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); /* if action is mapped in NLA, it returns a correction */ - if (G.saction->pin==0 && OBACT) { + if (G.saction->pin==0 && OBACT && datatype==ACTCONT_ACTION) { xmin= get_action_frame(OBACT, rectf.xmin); xmax= get_action_frame(OBACT, rectf.xmax); } @@ -343,799 +662,149 @@ static void *get_nearest_actionchannel_key (float *selx, short *sel, short *ret_ xrange[0]= xmin; xrange[1]= xmax; - /* try in action channels */ - for (achan = act->chanbase.first; achan; achan=achan->next) { - if(VISIBLE_ACHAN(achan)) { - if (clickmax < 0) - break; - if ((clickmin <= 0) && (achan->ipo)) { - /* found level - action channel */ - icu= get_nearest_icu_key(achan->ipo->curve.first, selx, sel, xrange); - - *ret_type= ACTTYPE_ACHAN; - return achan; - } - --clickmin; - --clickmax; - } - else - continue; - - if (EXPANDED_ACHAN(achan) == 0) - continue; - - /* try in ipo curves */ - if (achan->ipo) { - /* check header first */ - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found level - ipo-curves show/hide */ - *ret_type= ACTTYPE_NONE; - return NULL; - } - --clickmin; - --clickmax; - - /* now the ipo-curve channels if they are exposed */ - if (FILTER_IPO_ACHAN(achan)) { - for (icu= achan->ipo->curve.first; icu; icu=icu->next) { - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found level - ipo-curve channel */ - icu= get_nearest_icu_key (icu, selx, sel, xrange); - - *ret_type= ACTTYPE_ICU; - *par= achan; - return icu; - } - --clickmin; - --clickmax; - } - } - } - - /* try in constaint channels */ - if (achan->constraintChannels.first) { - /* check header first */ - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match - constraints show/hide */ - *ret_type= ACTTYPE_NONE; - return NULL; - } - --clickmin; - --clickmax; - - /* now the constraint channels if they are exposed */ - if (FILTER_CON_ACHAN(achan)) { - for (conchan= achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (clickmax < 0) - break; - if ((clickmin <= 0) && (conchan->ipo)) { - /* found match - constraint channel */ - icu= get_nearest_icu_key(conchan->ipo->curve.first, selx, sel, xrange); - - *ret_type= ACTTYPE_CONCHAN; - *par= achan; - return conchan; - } - --clickmin; - --clickmax; - } - } - } - } - - *ret_type= ACTTYPE_NONE; - return NULL; -} - -static IpoCurve *get_nearest_meshchannel_key (float *index, short *sel) -{ - /* This function tries to find the RVK key that is - * closest to the user's mouse click - */ - Key *key; - IpoCurve *icu; - IpoCurve *firsticu=NULL; - int foundsel=0; - float firstvert=-1, foundx=-1; - int i; - short mval[2]; - float ymin, ymax, ybase; - rctf rectf; - - *index=0; - - key = get_action_mesh_key(); - - /* lets get the mouse position and process it so - * we can start testing selections - */ - getmouseco_areawin (mval); - mval[0]-=7; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); - mval[0]+=14; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); - - ybase = key->totkey * (CHANNELHEIGHT + CHANNELSKIP); - ybase += CHANNELHEIGHT/2; - *sel=0; - - /* lets loop through the IpoCurves trying to find the closest bezier */ - if (!key->ipo) return NULL; - for (icu = key->ipo->curve.first; icu ; icu = icu->next) { - /* lets not deal with the "speed" Ipo */ - if (!icu->adrcode) continue; - - ymax = ybase - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1); - ymin = ymax - (CHANNELHEIGHT+CHANNELSKIP); - - /* Does this curve coorespond to the right - * strip? - */ - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { - - /* loop through the beziers in the curve */ - for (i=0; i<icu->totvert; i++) { - - /* Is this bezier in the right area? */ - if (icu->bezt[i].vec[1][0] > rectf.xmin && - icu->bezt[i].vec[1][0] <= rectf.xmax ) { - - /* if no other curves have been picked ... */ - if (!firsticu){ - /* mark this curve/bezier as the first selected */ - firsticu=icu; - firstvert=icu->bezt[i].vec[1][0]; - - /* sel = (is the bezier is already selected) ? 1 : 0; */ - *sel = icu->bezt[i].f2 & 1; - } - - /* if the bezier is selected ... */ - if (icu->bezt[i].f2 & 1){ - /* if we haven't found a selected one yet ... */ - if (!foundsel){ - /* record the found x value */ - foundsel=1; - foundx = icu->bezt[i].vec[1][0]; - } - } - - /* if the bezier is unselected and not at the x - * position of a previous found selected bezier ... - */ - else if (foundsel && icu->bezt[i].vec[1][0] != foundx){ - /* lets return this found curve/bezier */ - *index=icu->bezt[i].vec[1][0]; - *sel = 0; - return icu; - } - } - } - } - } - /* return what we've found - */ - *index=firstvert; - return firsticu; -} - -/* This function makes a list of the selected keyframes - * in the ipo curves it has been passed - */ -static void make_sel_cfra_list(Ipo *ipo, ListBase *elems) -{ - IpoCurve *icu; - BezTriple *bezt; - int a; - - for(icu= ipo->curve.first; icu; icu= icu->next) { - - bezt= icu->bezt; - if(bezt) { - a= icu->totvert; - while(a--) { - if(bezt->f2 & 1) { - add_to_cfra_elem(elems, bezt); - } - bezt++; - } - } - } -} - -/* This function selects all key frames in the same column(s) as a already selected key(s) - * this version only works for Shape Keys, Key should be not NULL - */ -void column_select_shapekeys(Key *key, int mode) -{ - if(key && key->ipo) { - IpoCurve *icu; - ListBase elems= {NULL, NULL}; - CfraElem *ce; - - /* build list of columns */ - switch (mode) { - case 1: - /* create a list of all selected keys */ - make_sel_cfra_list(key->ipo, &elems); - break; - case 2: - /* create a list of all selected markers */ - make_marker_cfra_list(&elems, 1); - break; - } - - /* loop through all of the keys and select additional keyframes - * based on the keys found to be selected above - */ - for(ce= elems.first; ce; ce= ce->next) { - for (icu = key->ipo->curve.first; icu ; icu = icu->next) { - BezTriple *bezt= icu->bezt; - if(bezt) { - int verts = icu->totvert; - while(verts--) { - if( ((int)ce->cfra) == ((int)bezt->vec[1][0]) ) { - bezt->f2 |= 1; - } - bezt++; - } - } - } - } - - BLI_freelistN(&elems); - } -} - -/* This function selects all key frames in the same column(s) as a already selected key(s) - * this version only works for on Action. *act should be not NULL - */ -void column_select_actionkeys(bAction *act, int mode) -{ - IpoCurve *icu; - BezTriple *bezt; - ListBase elems= {NULL, NULL}; - CfraElem *ce; - bActionChannel *achan; - bConstraintChannel *conchan; - - if (!act) - return; + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_CHANNELS); + actdata_filter(&act_data, filter, data, datatype); - /* build list of columns */ - switch (mode) { - case 1: - /* create a list of all selected keys */ - for (achan=act->chanbase.first; achan; achan=achan->next) { - if(VISIBLE_ACHAN(achan)) { - if (achan->ipo) - make_sel_cfra_list(achan->ipo, &elems); - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (conchan->ipo) - make_sel_cfra_list(conchan->ipo, &elems); - } - } - } - } + for (ale= act_data.first; ale; ale= ale->next) { + if (clickmax < 0) break; - case 2: - /* create a list of all selected markers */ - make_marker_cfra_list(&elems, 1); + if (clickmin <= 0) { + /* found match */ + *ret_type= ale->type; - /* apply scaled action correction if needed */ - if (G.saction->pin==0 && OBACT) { - for (ce= elems.first; ce; ce= ce->next) - ce->cfra= get_action_frame(OBACT, ce->cfra); - } - break; - } - - /* loop through all of the keys and select additional keyframes - * based on the keys found to be selected above - */ - for (achan=act->chanbase.first; achan; achan= achan->next){ - if(VISIBLE_ACHAN(achan)) { - if (achan->ipo) { - for(ce= elems.first; ce; ce= ce->next) { - for (icu = achan->ipo->curve.first; icu; icu = icu->next){ - bezt= icu->bezt; - if(bezt) { - int verts = icu->totvert; - while(verts--) { - - if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) ) { - bezt->f2 |= 1; - } - bezt++; - } - } + /* find location of keyframe (if applicable) */ + if (ale->key_data) { + switch (ale->datatype) { + case ALE_IPO: + { + Ipo *ipo= (Ipo *)ale->key_data; + icu= get_nearest_icu_key(ipo->curve.first, selx, sel, xrange); + } + break; + case ALE_ICU: + { + icu= (IpoCurve *)ale->key_data; + icu= get_nearest_icu_key(icu, selx, sel, xrange); } + break; } } - if (EXPANDED_ACHAN(achan) == 0 || (FILTER_CON_ACHAN(achan))) - continue; + /* figure out what to return */ + if (datatype == ACTCONT_ACTION) + *par= ale->owner; /* assume that this is an action channel */ + data = ale->data; - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (conchan->ipo) { - for(ce= elems.first; ce; ce= ce->next) { - for (icu = conchan->ipo->curve.first; icu; icu = icu->next){ - bezt= icu->bezt; - if(bezt) { - int verts = icu->totvert; - while(verts--) { - - if( ((int)ce->cfra) == ((int)bezt->vec[1][0]) ) { - bezt->f2 |= 1; - } - bezt++; - } - } - } - } - } - } - } - } - BLI_freelistN(&elems); -} - -/* apparently within active object context */ -static void mouse_action(int selectmode) -{ - bAction *act; - bActionChannel *achan; - bConstraintChannel *conchan= NULL; - IpoCurve *icu= NULL; - TimeMarker *marker; - void *act_channel; - short sel, act_type; - float selx; - - act=G.saction->action; - if (!act) - return; - - act_channel= get_nearest_actionchannel_key(&selx, &sel, &act_type, &achan); - marker=find_nearest_marker(1); - - if (act_channel) { - switch (act_type) { - case ACTTYPE_ICU: - icu= (IpoCurve *)act_channel; - break; - case ACTTYPE_CONCHAN: - conchan= (bConstraintChannel *)act_channel; - break; - default: - achan= (bActionChannel *)act_channel; - } - - if (selectmode == SELECT_REPLACE) { - selectmode = SELECT_ADD; - - deselect_actionchannel_keys(act, 0, 0); - deselect_actionchannels(act, 0); + BLI_freelistN(&act_data); - achan->flag |= ACHAN_SELECTED; - hilight_channel (act, achan, 1); - select_poseelement_by_name(achan->name, 2); /* 2 is activate */ - } - - if (icu) - select_icu_key(icu, selx, selectmode); - else if (conchan) - select_ipo_key(conchan->ipo, selx, selectmode); - else - select_ipo_key(achan->ipo, selx, selectmode); - - std_rmouse_transform(transform_actionchannel_keys); - - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWOOPS, 0); - allqueue(REDRAWBUTSALL, 0); - } - else if (marker) { - /* not channel, so maybe marker */ - if (selectmode == SELECT_REPLACE) { - deselect_markers(0, 0); - marker->flag |= SELECT; - } - else if (selectmode == SELECT_INVERT) { - if (marker->flag & SELECT) - marker->flag &= ~SELECT; - else - marker->flag |= SELECT; - } - else if (selectmode == SELECT_ADD) - marker->flag |= SELECT; - else if (selectmode == SELECT_SUBTRACT) - marker->flag &= ~SELECT; - - std_rmouse_transform(transform_markers); - - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); - } -} - -static void mouse_mesh_action(int selectmode, Key *key) -{ - /* Handle a right mouse click selection in an - * action window displaying RVK data - */ - - IpoCurve *icu; - TimeMarker *marker; - short sel; - float selx; - short mval[2]; - - /* going to assume that the only reason - * we got here is because it has been - * determined that we are a mesh with - * the right properties (i.e., have key - * data, etc) - */ - - marker= find_nearest_marker(1); - - /* get the click location, and the cooresponding - * ipo curve and selection time value - */ - getmouseco_areawin (mval); - icu = get_nearest_meshchannel_key(&selx, &sel); - - if (icu) { - if (selectmode == SELECT_REPLACE) { - /* if we had planned to replace the - * selection, then we will first deselect - * all of the keys, and if the clicked on - * key had been unselected, we will select - * it, otherwise, we are done. - */ - deselect_meshchannel_keys(key, 0, 0); - - if (sel == 0) - selectmode = SELECT_ADD; - else - /* the key is selected so we should - * deselect -- but everything is now deselected - * so we are done. - */ - return; - } - - /* select the key using the given mode - * and redraw as mush stuff as needed. - */ - select_icu_key(icu, selx, selectmode); - - BIF_undo_push("Select Action key"); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - - } - else if (marker) { - /* not channel, so maybe marker */ - if (selectmode == SELECT_REPLACE) { - deselect_markers(0, 0); - marker->flag |= SELECT; - } - else if (selectmode == SELECT_INVERT) { - if (marker->flag & SELECT) - marker->flag &= ~SELECT; - else - marker->flag |= SELECT; + return data; } - else if (selectmode == SELECT_ADD) - marker->flag |= SELECT; - else if (selectmode == SELECT_SUBTRACT) - marker->flag &= ~SELECT; - - std_rmouse_transform(transform_markers); - - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); + --clickmin; + --clickmax; } -} - -void borderselect_action(void) -{ - rcti rect; - rctf rectf; - bAction *act; - bActionChannel *achan; - bConstraintChannel *conchan; - IpoCurve *icu; - int val, selectmode; - int (*select_function)(BezTriple *); - short mval[2]; - float ymin, ymax; - act=G.saction->action; - - if (!act) - return; - - if ( (val = get_border(&rect, 3)) ) { - if (val == LEFTMOUSE) { - selectmode = SELECT_ADD; - select_function = select_bezier_add; - } - else { - selectmode = SELECT_SUBTRACT; - select_function = select_bezier_subtract; - } - - mval[0]= rect.xmin; - mval[1]= rect.ymin+2; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); - mval[0]= rect.xmax; - mval[1]= rect.ymax-2; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); - - /* if action is mapped in NLA, it returns a correction */ - if (G.saction->pin==0 && OBACT) { - rectf.xmin= get_action_frame(OBACT, rectf.xmin); - rectf.xmax= get_action_frame(OBACT, rectf.xmax); - } - - ymax = CHANNELHEIGHT/2; - - for (achan=act->chanbase.first; achan; achan= achan->next) { - if(VISIBLE_ACHAN(achan)) { - /* Check action channel */ - ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP); - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) - borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); - ymax=ymin; - - if (EXPANDED_ACHAN(achan)) { - /* check ipo - although the action channel has already been checked, - * selection may have started below that channel - */ - if (achan->ipo) { - /* skip the widget*/ - ymin= ymax-(CHANNELHEIGHT+CHANNELSKIP); - ymax= ymin; - - if (FILTER_IPO_ACHAN(achan)) { - /* check ipo-curve channels */ - for (icu=achan->ipo->curve.first; icu; icu=icu->next) { - ymin= ymax-(CHANNELHEIGHT+CHANNELSKIP); - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) - borderselect_icu_key(icu, rectf.xmin, rectf.xmax, select_function); - - ymax=ymin; - } - } - } - - /* Check constraints */ - if (achan->constraintChannels.first) { - /* skip the widget*/ - ymin= ymax-(CHANNELHEIGHT+CHANNELSKIP); - ymax= ymin; - - /* check constraint channels */ - if (FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - ymin= ymax-(CHANNELHEIGHT+CHANNELSKIP); - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) - borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); - - ymax=ymin; - } - } - } - } - } - } - - BIF_undo_push("Border Select Action"); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } -} - -void borderselect_mesh(Key *key) -{ - rcti rect; - int val, adrcodemax, adrcodemin; - short mval[2]; - float xmin, xmax; - int selectmode; - int (*select_function)(BezTriple *); - IpoCurve *icu; + /* cleanup */ + BLI_freelistN(&act_data); - if ( (val = get_border(&rect, 3)) ){ - /* set the selection function based on what - * mouse button had been used in the border - * select - */ - if (val == LEFTMOUSE) { - selectmode = SELECT_ADD; - select_function = select_bezier_add; - } - else { - selectmode = SELECT_SUBTRACT; - select_function = select_bezier_subtract; - } - - /* get the minimum and maximum adrcode numbers - * for the IpoCurves (this is the number that - * relates an IpoCurve to the keyblock it - * controls). - */ - mval[0]= rect.xmin; - mval[1]= rect.ymin+2; - adrcodemax = get_nearest_key_num(key, mval, &xmin); - adrcodemax = (adrcodemax >= key->totkey) ? key->totkey : adrcodemax; - - mval[0]= rect.xmax; - mval[1]= rect.ymax-2; - adrcodemin = get_nearest_key_num(key, mval, &xmax); - adrcodemin = (adrcodemin < 1) ? 1 : adrcodemin; - - /* Lets loop throug the IpoCurves and do borderselect - * on the curves with adrcodes in our selected range. - */ - if(key->ipo) { - for (icu = key->ipo->curve.first; icu ; icu = icu->next) { - /* lets not deal with the "speed" Ipo - */ - if (!icu->adrcode) continue; - if ( (icu->adrcode >= adrcodemin) && - (icu->adrcode <= adrcodemax) ) { - borderselect_icu_key(icu, xmin, xmax, select_function); - } - } - } - - /* redraw stuff */ - BIF_undo_push("Border select Action Key"); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } + *ret_type= ACTTYPE_NONE; + return NULL; } -/* ******************** action API ***************** */ - -/* generic get current action call, for action window context */ -bAction *ob_get_action(Object *ob) +void *get_action_context (short *datatype) { - bActionStrip *strip; + bAction *act; + Key *key; - if(ob->action) - return ob->action; + /* get pointers to active action/shapekey blocks */ + act = (G.saction)? G.saction->action: NULL; + key = get_action_mesh_key(); - for (strip=ob->nlastrips.first; strip; strip=strip->next){ - if (strip->flag & ACTSTRIP_SELECT) - return strip->act; + if (act) { + *datatype= ACTCONT_ACTION; + return act; } - return NULL; -} - -/* used by ipo, outliner, buttons to find the active channel */ -bActionChannel *get_hilighted_action_channel(bAction *action) -{ - bActionChannel *achan; - - if (!action) + else if (key) { + *datatype= ACTCONT_SHAPEKEY; + return key; + } + else { + *datatype= ACTCONT_NONE; return NULL; - - for (achan= action->chanbase.first; achan; achan= achan->next) { - if(VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && achan->flag & ACHAN_HILIGHTED) - return achan; - } } - - return NULL; - } -bAction *add_empty_action(char *name) -{ - bAction *act; - /* - if(blocktype==ID_OB) - str= "ObAction"; - else if(blocktype==ID_KE) - str= "ShapeAction"; - */ - act= alloc_libblock(&G.main->action, ID_AC, name); - act->id.flag |= LIB_FAKEUSER; - act->id.us++; - return act; -} +/* **************************************************** */ +/* TRANSFORM TOOLS */ -void transform_actionchannel_keys(int mode, int dummy) +/* initialise the transform data - create transverts */ +static TransVert *transform_action_init (int *tvtot, float *minx, float *maxx) { - bAction *act; + ListBase act_data = {NULL, NULL}; + bActListElem *ale; TransVert *tv; - Object *ob= OBACT; - bActionChannel *achan; - bConstraintChannel *conchan; - float deltax, startx; - float minx, maxx, cenf[2]; - float sval[2], cval[2], lastcval[2]={0,0}; - float fac=0.0f; - int loop=1; - int tvtot=0; - int invert=0, firsttime=1; - int i; - short cancel=0; - short mvals[2], mvalc[2], cent[2]; - char str[256]; - - act=G.saction->action; - if(act==NULL) return; - - /* Ensure that partial selections result in beztriple selections */ - for (achan=act->chanbase.first; achan; achan= achan->next){ - if (EDITABLE_ACHAN(achan)) { - tvtot+=fullselect_ipo_keys(achan->ipo); - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (EDITABLE_CONCHAN(conchan)) - tvtot+=fullselect_ipo_keys(conchan->ipo); - } - } - } - } + void *data; + short datatype; + int filter; + int count= 0; + float min= 0, max= 0; + int i; - /* If nothing is selected, bail out */ - if (!tvtot) - return; + /* initialise the values being passed by reference */ + *tvtot = *minx = *maxx = 0; + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return NULL; - /* Build the transvert structure */ - tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert"); + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); - tvtot=0; - for (achan=act->chanbase.first; achan; achan= achan->next){ - if(EDITABLE_ACHAN(achan)) { - tvtot = add_trans_ipo_keys(achan->ipo, tv, tvtot); - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (EDITABLE_CONCHAN(conchan)) - tvtot = add_trans_ipo_keys(conchan->ipo, tv, tvtot); - } - } - } - } + /* loop 1: fully select ipo-keys and count how many BezTriples are selected */ + for (ale= act_data.first; ale; ale= ale->next) + count += fullselect_ipo_keys(ale->key_data); + + /* stop if trying to build list if nothing selected */ + if (count == 0) return NULL; + + /* Build the transvert structure */ + tv = MEM_callocN (sizeof(TransVert) * count, "transVert"); + /* loop 2: build transvert structure */ + for (ale= act_data.first; ale; ale= ale->next) + *tvtot = add_trans_ipo_keys(ale->key_data, tv, *tvtot); + /* min max, only every other three */ - minx= maxx= tv[1].loc[0]; - for (i=1; i<tvtot; i+=3){ - if(minx>tv[i].loc[0]) minx= tv[i].loc[0]; - if(maxx<tv[i].loc[0]) maxx= tv[i].loc[0]; + min= max= tv[1].loc[0]; + for (i=1; i<count; i+=3){ + if(min>tv[i].loc[0]) min= tv[i].loc[0]; + if(max<tv[i].loc[0]) max= tv[i].loc[0]; } + *minx= min; + *maxx= max; + + /* cleanup temp list */ + BLI_freelistN(&act_data); + + /* return created transverts */ + return tv; +} + +/* main transform loop for action editor */ +static short transform_action_loop (TransVert *tv, int tvtot, char mode, short context, float minx, float maxx) +{ + Object *ob= OBACT; + float deltax, startx; + float cenf[2]; + float sval[2], cval[2], lastcval[2]={0,0}; + float fac=0.0f; + int loop=1, invert=0; + int i; + short cancel=0, firsttime=1; + short mvals[2], mvalc[2], cent[2]; + char str[256]; /* Do the event loop */ cent[0] = curarea->winx + (G.saction->v2d.hor.xmax)/2; @@ -1156,7 +825,6 @@ void transform_actionchannel_keys(int mode, int dummy) startx=sval[0]; while (loop) { - if(mode=='t' && minx==maxx) break; @@ -1251,7 +919,7 @@ void transform_actionchannel_keys(int mode, int dummy) } break; case 'g': - if (G.saction->pin==0 && OBACT) { + if (G.saction->pin==0 && OBACT && context==ACTCONT_ACTION) { deltax = get_action_frame_inv(OBACT, cval[0]); deltax -= get_action_frame_inv(OBACT, sval[0]); @@ -1292,7 +960,7 @@ void transform_actionchannel_keys(int mode, int dummy) fac*=-1; } startx= (G.scene->r.cfra); - if(G.saction->pin==0 && OBACT) + if(G.saction->pin==0 && OBACT && context==ACTCONT_ACTION) startx= get_action_frame(OBACT, startx); tv[i].loc[0]-= startx; @@ -1307,7 +975,7 @@ void transform_actionchannel_keys(int mode, int dummy) float snapval; /* convert frame to nla-action time (if needed) */ - if (G.saction->pin==0 && OBACT) + if (G.saction->pin==0 && OBACT && context==ACTCONT_ACTION) snapval= get_action_frame_inv(OBACT, tv[i].loc[0]); else snapval= tv[i].loc[0]; @@ -1316,7 +984,7 @@ void transform_actionchannel_keys(int mode, int dummy) snapval= (float)(floor(snapval+0.5)); /* convert frame out of nla-action time */ - if (G.saction->pin==0 && OBACT) + if (G.saction->pin==0 && OBACT && context==ACTCONT_ACTION) tv[i].loc[0]= get_action_frame(OBACT, snapval); else tv[i].loc[0]= snapval; @@ -1328,7 +996,7 @@ void transform_actionchannel_keys(int mode, int dummy) headerprint(str); } else if (mode=='g') { - if(G.saction->pin==0 && OBACT) { + if(G.saction->pin==0 && OBACT && context==ACTCONT_ACTION) { /* recalculate the delta based on 'visual' times */ fac = get_action_frame_inv(OBACT, cval[0]); fac -= get_action_frame_inv(OBACT, sval[0]); @@ -1347,14 +1015,25 @@ void transform_actionchannel_keys(int mode, int dummy) } if (G.saction->lock) { - if(ob) { - ob->ctime= -1234567.0f; - if(ob->pose || ob_get_key(ob)) - DAG_object_flush_update(G.scene, ob, OB_RECALC); - else - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); + if (context == ACTCONT_ACTION) { + if(ob) { + ob->ctime= -1234567.0f; + if(ob->pose || ob_get_key(ob)) + DAG_object_flush_update(G.scene, ob, OB_RECALC); + else + DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); + } + force_draw_plus(SPACE_VIEW3D, 0); + } + else if (context == ACTCONT_SHAPEKEY) { + DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA); + allqueue (REDRAWVIEW3D, 0); + allqueue (REDRAWACTION, 0); + allqueue (REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWTIME, 0); + force_draw_all(0); } - force_draw_plus(SPACE_VIEW3D, 0); } else { force_draw(0); @@ -1367,392 +1046,712 @@ void transform_actionchannel_keys(int mode, int dummy) firsttime= 0; } - /* Update the curve */ - /* Depending on the lock status, draw necessary views */ + return cancel; +} - if(ob) { - ob->ctime= -1234567.0f; +/* main call to start transforming keyframes */ +/* NOTE: someday, this should be integrated with the transform system + * instead of relying on our own methods + */ +void transform_action_keys (int mode, int dummy) +{ + Object *ob= OBACT; + TransVert *tv; + int tvtot= 0; + short cancel; + float minx, maxx; + + void *data; + short datatype; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* initialise transform */ + tv= transform_action_init(&tvtot, &minx, &maxx); + if (tv == NULL) return; + + /* do transform loop */ + cancel= transform_action_loop(tv, tvtot, mode, datatype, minx, maxx); + + /* cleanup */ + if (datatype == ACTCONT_ACTION) { + /* Update the curve */ + /* Depending on the lock status, draw necessary views */ + if(ob) { + ob->ctime= -1234567.0f; - if(ob->pose || ob_get_key(ob)) - DAG_object_flush_update(G.scene, ob, OB_RECALC); - else - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); + if(ob->pose || ob_get_key(ob)) + DAG_object_flush_update(G.scene, ob, OB_RECALC); + else + DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); + } + + remake_action_ipos((bAction *)data); + + G.saction->flag &= ~SACTION_MOVING; + + if (cancel==0) BIF_undo_push("Transform Action"); // does it have to be here? + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWTIME, 0); + } + else if (datatype == ACTCONT_SHAPEKEY) { + /* fix up the Ipocurves and redraw stuff */ + meshkey_do_redraw((Key *)data); + if (cancel==0) BIF_undo_push("Transform Action"); } - remake_action_ipos(act); + MEM_freeN(tv); +} + +/* ----------------------------------------- */ - G.saction->flag &= ~SACTION_MOVING; +/* duplicate keyframes */ +void duplicate_action_keys (void) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + void *data; + short datatype; + int filter; - if(cancel==0) BIF_undo_push("Transform Action"); - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - allqueue(REDRAWTIME, 0); - MEM_freeN (tv); + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* loop through filtered data and duplicate selected keys */ + for (ale= act_data.first; ale; ale= ale->next) { + duplicate_ipo_keys((Ipo *)ale->key_data); + } + + /* free filtered list */ + BLI_freelistN(&act_data); + + /* now, go into transform-grab mode, to move keys */ + transform_action_keys('g', 0); } -void transform_meshchannel_keys(char mode, Key *key) +/* this function is responsible for snapping keyframes to frame-times */ +void snap_action_keys(short mode) { - /* this is the function that determines what happens - * to those little blocky rvk key things you have selected - * after you press a 'g' or an 's'. I'd love to say that - * I have an intimate knowledge of all of what this function - * is doing, but instead I'm just going to pretend. - */ - TransVert *tv; - int /*sel=0,*/ i; - short mvals[2], mvalc[2], cent[2]; - float sval[2], cval[2], lastcval[2]={0,0}; - short cancel=0; - float fac=0.0F; - int loop=1; - int tvtot=0; - float deltax, startx; - float cenf[2]; - int invert=0, firsttime=1; - char str[256]; - - /* count all of the selected beziers, and - * set all 3 control handles to selected - */ - tvtot=fullselect_ipo_keys(key->ipo); - - /* If nothing is selected, bail out */ - if (!tvtot) - return; + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + char str[32]; + + /* get data */ + data= get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* determine mode */ + switch (mode) { + case 1: + strcpy(str, "Snap Keys To Nearest Frame"); + break; + case 2: + strcpy(str, "Snap Keys To Current Frame"); + break; + case 3: + strcpy(str, "Snap Keys To Nearest Marker"); + break; + default: + return; + } + + /* snap to frame */ + for (ale= act_data.first; ale; ale= ale->next) { + snap_ipo_keys(ale->key_data, mode); + } + BLI_freelistN(&act_data); + if (datatype == ACTCONT_ACTION) + remake_action_ipos(data); - /* Build the transvert structure */ - tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert"); - tvtot=0; + BIF_undo_push(str); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); +} - tvtot = add_trans_ipo_keys(key->ipo, tv, tvtot); +/* this function is responsible for snapping keyframes to frame-times */ +void mirror_action_keys(short mode) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + char str[32]; + + /* get data */ + data= get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); - /* Do the event loop */ - cent[0] = curarea->winx + (G.saction->v2d.hor.xmax)/2; - cent[1] = curarea->winy + (G.saction->v2d.hor.ymax)/2; - areamouseco_to_ipoco(G.v2d, cent, &cenf[0], &cenf[1]); + /* determine mode */ + switch (mode) { + case 1: + strcpy(str, "Mirror Keys Over Current Frame"); + break; + case 2: + strcpy(str, "Mirror Keys Over Y-Axis"); + break; + case 3: + strcpy(str, "Mirror Keys Over X-Axis"); + break; + case 4: + strcpy(str, "Mirror Keys Over Marker"); + break; + default: + return; + } + + /* mirror */ + for (ale= act_data.first; ale; ale= ale->next) { + mirror_ipo_keys(ale->key_data, mode); + } + BLI_freelistN(&act_data); + + if (datatype == ACTCONT_ACTION) + remake_action_ipos(data); + + BIF_undo_push(str); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); +} - getmouseco_areawin (mvals); - areamouseco_to_ipoco(G.v2d, mvals, &sval[0], &sval[1]); +/* **************************************************** */ +/* ADD/REMOVE KEYFRAMES */ - startx=sval[0]; - while (loop) { - /* Get the input - * If we're cancelling, reset transformations - * Else calc new transformation - * Perform the transformations - */ - while (qtest()) { - short val; - unsigned short event= extern_qread(&val); - - if (val) { - switch (event) { - case LEFTMOUSE: - case SPACEKEY: - case RETKEY: - loop=0; - break; - case XKEY: - break; - case ESCKEY: - case RIGHTMOUSE: - cancel=1; - loop=0; - break; - default: - arrows_move_cursor(event); - break; - }; - } - } - - if (cancel) { - for (i=0; i<tvtot; i++) { - tv[i].loc[0]=tv[i].oldloc[0]; - tv[i].loc[1]=tv[i].oldloc[1]; - } - } - else { - getmouseco_areawin (mvalc); - areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]); - - if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) { - PIL_sleep_ms(1); - } - else { - short autosnap= 0; +/* This function allows the user to insert keyframes on the current + * frame from the Action Editor, using the current values of the channels + * to be keyframed. + */ +void insertkey_action(void) +{ + void *data; + short datatype; + + Object *ob= OBACT; + short mode; + float cfra; + + /* get data */ + data= get_action_context(&datatype); + if (data == NULL) return; + cfra = frame_to_float(CFRA); + + if (datatype == ACTCONT_ACTION) { + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + + /* ask user what to keyframe */ + mode = pupmenu("Insert Key%t|All Channels%x1|Only Selected Channels%x2"); + if (mode == 0) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU ); + if (mode == 2) filter |= ACTFILTER_SEL; + + actdata_filter(&act_data, filter, data, datatype); + + /* loop through ipo curves retrieved */ + for (ale= act_data.first; ale; ale= ale->next) { + /* verify that this is indeed an ipo curve */ + if (ale->key_data && ale->owner) { + bActionChannel *achan= (bActionChannel *)ale->owner; + IpoCurve *icu= (IpoCurve *)ale->key_data; - /* determine mode of keyframe snapping/autosnap */ - if (mode != 't') { - switch (G.saction->autosnap) { - case SACTSNAP_OFF: - if (G.qual == LR_CTRLKEY) - autosnap= SACTSNAP_STEP; - else if (G.qual == LR_SHIFTKEY) - autosnap= SACTSNAP_FRAME; - else - autosnap= SACTSNAP_OFF; - break; - case SACTSNAP_STEP: - autosnap= (G.qual==LR_CTRLKEY)? SACTSNAP_OFF: SACTSNAP_FRAME; - break; - case SACTSNAP_FRAME: - autosnap= (G.qual==LR_SHIFTKEY)? SACTSNAP_OFF: SACTSNAP_FRAME; - break; - } - } - - for (i=0; i<tvtot; i++) { - tv[i].loc[0]=tv[i].oldloc[0]; - - switch (mode){ - case 'g': - deltax = cval[0]-sval[0]; - fac= deltax; - - if (autosnap == SACTSNAP_STEP) { - /* NOTE: this doesn't take into account NLA scaling */ - fac= 1.0f*floor(fac/1.0f + 0.5f); - } - - tv[i].loc[0]+=fac; - break; - case 's': - startx=mvals[0]-(ACTWIDTH/2+(curarea->winrct.xmax - -curarea->winrct.xmin)/2); - deltax=mvalc[0]-(ACTWIDTH/2+(curarea->winrct.xmax - -curarea->winrct.xmin)/2); - fac= fabs(deltax/startx); - - if (autosnap == SACTSNAP_FRAME) { - /* NOTE: this doesn't take into account NLA scaling */ - fac= 1.0f*floor(fac/1.0f + 0.5f); - } + if (ob) + insertkey((ID *)ob, icu->blocktype, achan->name, NULL, icu->adrcode); + else + insert_vert_ipo(icu, cfra, icu->curval); + } + } - if (invert){ - if (i % 03 == 0){ - memcpy (tv[i].loc, tv[i].oldloc, - sizeof(tv[i+2].oldloc)); - } - if (i % 03 == 2){ - memcpy (tv[i].loc, tv[i].oldloc, - sizeof(tv[i-2].oldloc)); - } - - fac*=-1; - } - startx= (G.scene->r.cfra); - - tv[i].loc[0]-= startx; - tv[i].loc[0]*=fac; - tv[i].loc[0]+= startx; + /* cleanup */ + BLI_freelistN(&act_data); + } + else if (datatype == ACTCONT_SHAPEKEY) { + Key *key= (Key *)data; + IpoCurve *icu; - break; - } - - /* auto-snap key to nearest frame? */ - if (autosnap == SACTSNAP_FRAME) { - tv[i].loc[0]= (float)(floor(tv[i].loc[0]+0.5)); - } - } - } - /* Display a message showing the magnitude of - * the grab/scale we are performing - */ - if (mode=='s') { - sprintf(str, "scaleX: %.3f", fac); - headerprint(str); - } - else if (mode=='g') { - sprintf(str, "deltaX: %.3f", fac); - headerprint(str); - } - - if (G.saction->lock) { - /* doubt any of this code ever gets - * executed, but it might in the - * future - */ - - DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB|OB_RECALC_DATA); - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWACTION, 0); - allqueue (REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWTIME, 0); - force_draw_all(0); - } - else { - addqueue (curarea->win, REDRAWALL, 0); - force_draw(0); - } - } + /* ask user if they want to insert a keyframe */ + mode = okee("Insert Keyframe?"); + if (mode == 0) return; - lastcval[0]= cval[0]; - lastcval[1]= cval[1]; - firsttime= 0; - } + if (key->ipo) { + for (icu= key->ipo->curve.first; icu; icu=icu->next) { + insert_vert_ipo(icu, cfra, icu->curval); + } + } + } - /* fix up the Ipocurves and redraw stuff */ - meshkey_do_redraw(key); - BIF_undo_push("Transform Action Keys"); - - MEM_freeN (tv); - - /* did you understand all of that? I pretty much understand - * what it does, but the specifics seem a little weird and crufty. - */ + BIF_undo_push("Insert Key"); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); } -void deselect_actionchannel_keys (bAction *act, int test, int sel) +/* delete selected keyframes */ +void delete_action_keys (void) { - bActionChannel *achan; - bConstraintChannel *conchan; + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + void *data; + short datatype; + int filter; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* loop through filtered data and delete selected keys */ + for (ale= act_data.first; ale; ale= ale->next) { + delete_ipo_keys((Ipo *)ale->key_data); + } + + /* free filtered list */ + BLI_freelistN(&act_data); + + if (datatype == ACTCONT_ACTION) + remake_action_ipos(data); + + BIF_undo_push("Delete Action Keys"); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); +} - if (!act) - return; +/* delete selected keyframes */ +void delete_action_channels (void) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale, *next; + bAction *act; + void *data; + short datatype; + int filter; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + if (datatype != ACTCONT_ACTION) return; + act= (bAction *)data; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_CHANNELS | ACTFILTER_SEL); + actdata_filter(&act_data, filter, data, datatype); + + /* remove irrelevant entries */ + for (ale= act_data.first; ale; ale= next) { + next= ale->next; + + if (ale->type != ACTTYPE_ACHAN) + BLI_freelinkN(&act_data, ale); + } + + /* clean up action channels */ + for (ale= act_data.first; ale; ale= next) { + bActionChannel *achan= (bActionChannel *)ale->data; + bConstraintChannel *conchan, *cnext; + next= ale->next; + + /* release reference to ipo users */ + if (achan->ipo) + achan->ipo->id.us--; + + for (conchan= achan->constraintChannels.first; conchan; conchan=cnext) { + cnext= conchan->next; + + if (conchan->ipo) + conchan->ipo->id.us--; + } + + /* free memory */ + BLI_freelistN(&achan->constraintChannels); + BLI_freelinkN(&act->chanbase, achan); + BLI_freelinkN(&act_data, ale); + } + + remake_action_ipos(data); + + BIF_undo_push("Delete Action Channels"); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); +} - /* Determine if this is selection or deselection */ - if (test) { - for (achan= act->chanbase.first; achan; achan= achan->next) { - if(VISIBLE_ACHAN(achan)) { - /* Test the channel ipos */ - if (is_ipo_key_selected(achan->ipo)) { - sel = 0; - break; - } +/* 'Clean' IPO curves - remove any unnecessary keyframes */ +void clean_action (void) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype, ok; + + /* don't proceed any further if nothing to work on or user refuses */ + data= get_action_context(&datatype); + ok= fbutton(&G.scene->toolsettings->clean_thresh, + 0.0000001f, 1.0, 0.001, 0.1, + "Clean Threshold"); + if (!ok) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_SEL | ACTFILTER_ONLYICU); + actdata_filter(&act_data, filter, data, datatype); + + /* loop through filtered data and clean curves */ + for (ale= act_data.first; ale; ale= ale->next) { + clean_ipo_curve((IpoCurve *)ale->key_data); + } + + /* admin and redraws */ + BLI_freelistN(&act_data); + + BIF_undo_push("Clean Action"); + allqueue(REMAKEIPO, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); +} - if ((EXPANDED_ACHAN(achan) == 0) || (FILTER_CON_ACHAN(achan)==0)) - continue; - - /* Test the constraint ipos */ - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){ - if (is_ipo_key_selected(conchan->ipo)) { - sel = 0; - break; - } - } +/* **************************************************** */ +/* VARIOUS SETTINGS */ - if (sel == 0) - break; - } +/* this function combines several features related to setting + * various ipo extrapolation/interpolation + */ +void action_set_ipo_flags (int mode) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + void *data; + short datatype; + int filter, event; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* determine which set of processing we are doing */ + switch (mode) { + case SET_EXTEND_POPUP: + { + /* present popup menu for ipo extrapolation type */ + event + = pupmenu("Channel Extending Type %t|" + "Constant %x11|" + "Extrapolation %x12|" + "Cyclic %x13|" + "Cyclic extrapolation %x14"); + if(event < 1) return; } + break; + case SET_IPO_POPUP: + { + /* present popup menu for ipo interpolation type */ + event + = pupmenu("Channel Ipo Type %t|" + "Constant %x1|" + "Linear %x2|" + "Bezier %x3"); + if(event < 1) return; + } + break; + + default: /* weird, unhandled case */ + return; } - /* Set the flags */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - if(VISIBLE_ACHAN(achan)) { - set_ipo_key_selection(achan->ipo, sel); - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) - set_ipo_key_selection(conchan->ipo, sel); + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* loop through setting flags */ + for (ale= act_data.first; ale; ale= ale->next) { + Ipo *ipo= (Ipo *)ale->key_data; + + /* depending on the mode */ + switch (mode) { + case SET_EXTEND_POPUP: /* extrapolation */ + { + switch (event) { + case SET_EXTEND_CONSTANT: + setexprap_ipoloop(ipo, IPO_HORIZ); + break; + case SET_EXTEND_EXTRAPOLATION: + setexprap_ipoloop(ipo, IPO_DIR); + break; + case SET_EXTEND_CYCLIC: + setexprap_ipoloop(ipo, IPO_CYCL); + break; + case SET_EXTEND_CYCLICEXTRAPOLATION: + setexprap_ipoloop(ipo, IPO_CYCLX); + break; + } + } + break; + case SET_IPO_POPUP: /* interpolation */ + { + setipotype_ipo(ipo, event); } + break; } } + + /* cleanup */ + BLI_freelistN(&act_data); + + if (datatype == ACTCONT_ACTION) + remake_action_ipos(data); + + BIF_undo_push("Set Ipo Type"); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); } -void deselect_meshchannel_keys (Key *key, int test, int sel) +/* this function sets the handles on keyframes + */ +void sethandles_action_keys (int code) { - /* should deselect the rvk keys */ - - /* Determine if this is selection or deselection */ - if (test) { - if (is_ipo_key_selected(key->ipo)) { - sel = 0; - } - } + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + void *data; + short datatype; + int filter; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* loop through setting flags */ + for (ale= act_data.first; ale; ale= ale->next) { + sethandles_ipo_keys((Ipo *)ale->key_data, code); + } - /* Set the flags */ - set_ipo_key_selection(key->ipo, sel); + /* cleanup */ + BLI_freelistN(&act_data); + if (datatype == ACTCONT_ACTION) + remake_action_ipos(data); + + BIF_undo_push("Set Handle Type"); + allspace(REMAKEIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWNLA, 0); } -/* apparently within active object context */ -void deselect_actionchannels (bAction *act, int test) +/* ----------------------------------------- */ + +static void clever_keyblock_names (Key *key, short *mval) { - bActionChannel *achan; - bConstraintChannel *conchan; - IpoCurve *icu; - int sel= 1; + KeyBlock *kb; + int but=0, i, keynum; + char str[64]; + float x; + + /* get the keynum cooresponding to the y value + * of the mouse pointer, return if this is + * an invalid key number (and we don't deal + * with the speed ipo). + */ - if (!act) - return; + keynum = get_nearest_key_num(key, mval, &x); + if ( (keynum < 1) || (keynum >= key->totkey) ) + return; - /* See if we should be selecting or deselecting */ - if (test) { - for (achan=act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (!sel) - break; - - if (achan->flag & ACHAN_SELECTED) { - sel= 0; - break; - } - if (sel) { - if (EXPANDED_ACHAN(achan)) { - if (FILTER_IPO_ACHAN(achan) && (achan->ipo)) { - for (icu=achan->ipo->curve.first; icu; icu=icu->next) { - if (SEL_ICU(icu)) { - sel= 0; - break; - } - } + kb= key->block.first; + for (i=0; i<keynum; ++i) kb = kb->next; - } - if (FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (SEL_CONCHAN(conchan)) { - sel= 0; - break; - } - } - } - } - } - } - } + if (kb->name[0] == '\0') { + sprintf(str, "Key %d", keynum); + } + else { + strcpy(str, kb->name); } - else - sel= 0; - - /* Now set the flags */ - for (achan=act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - select_poseelement_by_name(achan->name, sel); - if (sel) - achan->flag |= ACHAN_SELECTED; - else - achan->flag &= ~ACHAN_SELECTED; + if ( (kb->slidermin >= kb->slidermax) ) { + kb->slidermin = 0.0; + kb->slidermax = 1.0; + } - if (EXPANDED_ACHAN(achan)) { - if (FILTER_IPO_ACHAN(achan) && (achan->ipo)) { - for (icu=achan->ipo->curve.first; icu; icu=icu->next) { - if (sel) - icu->flag |= IPO_SELECT; - else - icu->flag &= ~IPO_SELECT; - } - } - if (FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (sel) - conchan->flag |= CONSTRAINT_CHANNEL_SELECT; - else - conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT; - } - } + add_numbut(but++, TEX, "KB: ", 0, 24, str, + "Does this really need a tool tip?"); + add_numbut(but++, NUM|FLO, "Slider Min:", + -10000, kb->slidermax, &kb->slidermin, 0); + add_numbut(but++, NUM|FLO, "Slider Max:", + kb->slidermin, 10000, &kb->slidermax, 0); + + if (do_clever_numbuts(str, but, REDRAW)) { + strcpy(kb->name, str); + allqueue (REDRAWACTION, 0); + allspace(REMAKEIPO, 0); + allqueue (REDRAWIPO, 0); + } +} + +static void clever_achannel_names (short *mval) +{ + void *act_channel; + bActionChannel *achan= NULL; + bConstraintChannel *conchan= NULL; + IpoCurve *icu= NULL; + + int but=0; + char str[64]; + short expand, protect, chantype; + float slidermin, slidermax; + + /* figure out what is under cursor */ + act_channel= get_nearest_act_channel(mval, &chantype); + + /* create items for clever-numbut */ + if (chantype == ACTTYPE_ACHAN) { + achan= (bActionChannel *)act_channel; + + strcpy(str, achan->name); + protect= (achan->flag & ACHAN_PROTECTED); + expand = (achan->flag & ACHAN_EXPANDED); + + add_numbut(but++, TEX, "ActChan: ", 0, 31, str, "Name of Action Channel"); + add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Channel is Expanded"); + add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); + } + else if (chantype == ACTTYPE_CONCHAN) { + conchan= (bConstraintChannel *)act_channel; + + strcpy(str, conchan->name); + protect= (conchan->flag & CONSTRAINT_CHANNEL_PROTECTED); + + add_numbut(but++, TEX, "ConChan: ", 0, 29, str, "Name of Constraint Channel"); + add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); + } + else if (chantype == ACTTYPE_ICU) { + icu= (IpoCurve *)act_channel; + + strcpy(str, getname_ipocurve(icu)); + + if (IS_EQ(icu->slide_max, icu->slide_min)) { + if (IS_EQ(icu->ymax, icu->ymin)) { + icu->slide_min= -100.0; + icu->slide_max= 100.0; + } + else { + icu->slide_min= icu->ymin; + icu->slide_max= icu->ymax; } } + slidermin= icu->slide_min; + slidermax= icu->slide_max; + + //protect= (icu->flag & IPO_PROTECT); + + add_numbut(but++, NUM|FLO, "Slider Min:", -10000, slidermax, &slidermin, 0); + add_numbut(but++, NUM|FLO, "Slider Max:", slidermin, 10000, &slidermax, 0); + //add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); + } + else { + /* nothing under-cursor */ + return; + } + + /* draw clever-numbut */ + if (do_clever_numbuts(str, but, REDRAW)) { + /* restore settings based on type */ + if (icu) { + icu->slide_min= slidermin; + icu->slide_max= slidermax; + + //if (protect) icu->flag |= IPO_PROTECT; + //else icu->flag &= ~IPO_PROTECT; + } + else if (conchan) { + strcpy(conchan->name, str); + + if (protect) conchan->flag |= CONSTRAINT_CHANNEL_PROTECTED; + else conchan->flag &= ~CONSTRAINT_CHANNEL_PROTECTED; + } + else if (achan) { + strcpy(achan->name, str); + + if (expand) achan->flag |= ACHAN_EXPANDED; + else achan->flag &= ~ACHAN_EXPANDED; + + if (protect) achan->flag |= ACHAN_PROTECTED; + else achan->flag &= ~ACHAN_PROTECTED; + } + + allqueue (REDRAWACTION, 0); + allqueue (REDRAWVIEW3D, 0); } +} +/* this gets called when nkey is pressed (no Transform Properties panel yet) */ +static void numbuts_action (void) +{ + /* now called from action window event loop, plus reacts on mouseclick */ + /* removed Hos grunts for that reason! :) (ton) */ + void *data; + short datatype; + short mval[2]; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + getmouseco_areawin(mval); + + if (mval[0] < NAMEWIDTH) { + switch (datatype) { + case ACTCONT_ACTION: + clever_achannel_names(mval); + break; + case ACTCONT_SHAPEKEY: + clever_keyblock_names(data, mval); + break; + } + } } -static void hilight_channel (bAction *act, bActionChannel *achan, short select) + +/* **************************************************** */ +/* CHANNEL SELECTION */ + +static void hilight_channel(bAction *act, bActionChannel *achan, short select) { bActionChannel *curchan; @@ -1767,6 +1766,56 @@ static void hilight_channel (bAction *act, bActionChannel *achan, short select) } } +/* messy call... */ +static void select_poseelement_by_name(char *name, int select) +{ + /* Syncs selection of channels with selection of object elements in posemode */ + Object *ob= OBACT; + bPoseChannel *pchan; + + if (!ob || ob->type!=OB_ARMATURE) + return; + + if(select==2) { + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) + pchan->bone->flag &= ~(BONE_ACTIVE); + } + + pchan= get_pose_channel(ob->pose, name); + if(pchan) { + if(select) + pchan->bone->flag |= (BONE_SELECTED); + else + pchan->bone->flag &= ~(BONE_SELECTED); + if(select==2) + pchan->bone->flag |= (BONE_ACTIVE); + } +} + +/* apparently within active object context */ +/* called extern, like on bone selection */ +void select_actionchannel_by_name (bAction *act, char *name, int select) +{ + bActionChannel *achan; + + if (!act) + return; + + for (achan = act->chanbase.first; achan; achan= achan->next) { + if (!strcmp(achan->name, name)) { + if (select) { + achan->flag |= ACHAN_SELECTED; + hilight_channel(act, achan, 1); + } + else { + achan->flag &= ~ACHAN_SELECTED; + hilight_channel(act, achan, 0); + } + return; + } + } +} + /* select_mode = SELECT_REPLACE * = SELECT_ADD * = SELECT_SUBTRACT @@ -1801,7 +1850,8 @@ int select_channel(bAction *act, bActionChannel *achan, int selectmode) static int select_constraint_channel(bAction *act, bConstraintChannel *conchan, - int selectmode) { + int selectmode) +{ /* Select the constraint channel based on the selection mode */ int flag; @@ -1841,150 +1891,535 @@ int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode) return flag; } -static void borderselect_actionchannels(bAction *act, short *mval, - short *mvalo, int selectmode) +/* ----------------------------------------- */ + +/* deselects action channels in given action */ +void deselect_actionchannels (bAction *act, short test) { - /* Select action channels, based on mouse values. - * If mvalo is NULL we assume it is a one click - * action, other wise we treat it like it is a - * border select with mval[0],mval[1] and - * mvalo[0], mvalo[1] forming the corners of - * a rectangle. - */ - bActionChannel *achan; - bConstraintChannel *conchan; - IpoCurve *icu; - float click, x,y; - int clickmin, clickmax; + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter, sel=1; + + /* filter data */ + filter= ACTFILTER_VISIBLE; + actdata_filter(&act_data, filter, act, ACTCONT_ACTION); + + /* See if we should be selecting or deselecting */ + if (test) { + for (ale= act_data.first; ale; ale= ale->next) { + if (sel == 0) + break; + + switch (ale->type) { + case ACTTYPE_ACHAN: + if (ale->flag & ACHAN_SELECTED) + sel= 0; + break; + case ACTTYPE_CONCHAN: + if (ale->flag & CONSTRAINT_CHANNEL_SELECT) + sel=0; + break; + case ACTTYPE_ICU: + if (ale->flag & IPO_SELECT) + sel=0; + break; + } + } + } + else + sel= 0; + + /* Now set the flags */ + for (ale= act_data.first; ale; ale= ale->next) { + switch (ale->type) { + case ACTTYPE_ACHAN: + { + bActionChannel *achan= (bActionChannel *)ale->data; + + if (sel) + achan->flag |= ACHAN_SELECTED; + else + achan->flag &= ~ACHAN_SELECTED; + select_poseelement_by_name(achan->name, sel); + } + break; + case ACTTYPE_CONCHAN: + { + bConstraintChannel *conchan= (bConstraintChannel *)ale->data; + + if (sel) + conchan->flag |= CONSTRAINT_CHANNEL_SELECT; + else + conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT; + } + break; + case ACTTYPE_ICU: + { + IpoCurve *icu= (IpoCurve *)ale->data; + + if (sel) + icu->flag |= IPO_SELECT; + else + icu->flag &= ~IPO_SELECT; + } + break; + } + } + + /* Cleanup */ + BLI_freelistN(&act_data); +} - if (!act) - return; - - if (selectmode == SELECT_REPLACE) { - deselect_actionchannels (act, 0); - selectmode = SELECT_ADD; +/* deselects channels in the action editor */ +void deselect_action_channels (short test) +{ + void *data; + short datatype; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* based on type */ + if (datatype == ACTCONT_ACTION) + deselect_actionchannels(data, test); + // should shapekey channels be allowed to do this? +} + +/* deselects keyframes in the action editor */ +void deselect_action_keys (short test, short sel) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* See if we should be selecting or deselecting */ + if (test) { + for (ale= act_data.first; ale; ale= ale->next) { + if (is_ipo_key_selected(ale->key_data)) { + sel= 0; + break; + } + } + } + + /* Now set the flags */ + for (ale= act_data.first; ale; ale= ale->next) { + set_ipo_key_selection(ale->key_data, sel); } + + /* Cleanup */ + BLI_freelistN(&act_data); +} - areamouseco_to_ipoco(G.v2d, mval, &x, &y); - clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP)); +/* selects all keyframes in the action editor - per channel or time + * mode = 0: all in channel; mode = 1: all in frame + */ +void selectall_action_keys (short mval[], short mode, short select_mode) +{ + void *data; + short datatype; - /* Only one click */ - if (mvalo == NULL) { - clickmax = clickmin; + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + if (select_mode == SELECT_REPLACE) { + deselect_action_keys(0, 0); + select_mode = SELECT_ADD; } - /* Two click values (i.e., border select */ - else { - areamouseco_to_ipoco(G.v2d, mvalo, &x, &y); - click = (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP)); + + /* depending on mode */ + switch (mode) { + case 0: /* all in channel*/ + { + void *act_channel; + short chantype; + + /* get channel, and act according to type */ + act_channel= get_nearest_act_channel(mval, &chantype); + switch (chantype) { + case ACTTYPE_ACHAN: + { + bActionChannel *achan= (bActionChannel *)act_channel; + select_ipo_bezier_keys(achan->ipo, select_mode); + } + break; + case ACTTYPE_CONCHAN: + { + bConstraintChannel *conchan= (bConstraintChannel *)act_channel; + select_ipo_bezier_keys(conchan->ipo, select_mode); + } + break; + case ACTTYPE_ICU: + { + IpoCurve *icu= (IpoCurve *)act_channel; + select_icu_bezier_keys(icu, select_mode); + } + break; + } + } + break; + case 1: /* all in frame */ + { + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + rcti rect; + rctf rectf; + + /* use bounding box to find kframe */ + rect.xmin = rect.xmax = mval[0]; + rect.ymin = rect.ymax = mval[1]; + + mval[0]= rect.xmin; + mval[1]= rect.ymin+2; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + rectf.xmax= rectf.xmin; + rectf.ymax= rectf.ymin; + + rectf.xmin = rectf.xmin - 0.5; + rectf.xmax = rectf.xmax + 0.5; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* Now set the flags */ + for (ale= act_data.first; ale; ale= ale->next) + borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, select_mode); + + /* Cleanup */ + BLI_freelistN(&act_data); + } + break; + } + + allqueue(REDRAWNLA, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); +} - if ( ((int) click) < clickmin) { - clickmax = clickmin; - clickmin = (int) click; +void markers_selectkeys_between (void) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + float min, max; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* get extreme markers */ + get_minmax_markers(1, &min, &max); + if (min==max) return; + min -= 0.5f; + max += 0.5f; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); + + /* select keys in-between */ + for (ale= act_data.first; ale; ale= ale->next) { + if(G.saction->pin==0 && OBACT && datatype==ACTCONT_ACTION) { + actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); + borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD); + actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); } else { - clickmax = (int) click; + borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD); } } + + /* Cleanup */ + BLI_freelistN(&act_data); +} - if (clickmax < 0) { - return; - } +/* ----------------------------------------- */ - /* clickmin and clickmax now coorespond to indices into - * the collection of channels and constraint channels. - * What we need to do is apply the selection mode on all - * channels and constraint channels between these indices. - * This is done by traversing the channels and constraint - * channels, for each item decrementing clickmin and clickmax. - * When clickmin is less than zero we start selecting stuff, - * until clickmax is less than zero or we run out of channels - * and constraint channels. - */ +/* This function makes a list of the selected keyframes + * in the ipo curves it has been passed + */ +static void make_sel_cfra_list(Ipo *ipo, ListBase *elems) +{ + IpoCurve *icu; + + if (ipo == NULL) return; + + for(icu= ipo->curve.first; icu; icu= icu->next) { + BezTriple *bezt; + int a= 0; + + for (bezt=icu->bezt; a<icu->totvert; a++, bezt++) { + if (bezt && BEZSELECTED(bezt)) + add_to_cfra_elem(elems, bezt); + } + } +} - /* try in action channels */ - for (achan = act->chanbase.first; achan; achan= achan->next){ - if(VISIBLE_ACHAN(achan)) { - if (clickmax < 0) break; +/* This function selects all key frames in the same column(s) as a already selected key(s) + * or marker(s), or all the keyframes on a particular frame (triggered by a RMB on x-scrollbar) + */ +void column_select_action_keys(int mode) +{ + ListBase elems= {NULL, NULL}; + CfraElem *ce; + IpoCurve *icu; + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* build list of columns */ + switch (mode) { + case 1: /* list of selected keys */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); + actdata_filter(&act_data, filter, data, datatype); - if (clickmin <= 0) { - /* Select the channel with the given mode. If the - * channel is freshly selected then set it to the - * active channel for the action - */ - select_channel(act, achan, selectmode); - /* messy... */ - select_poseelement_by_name(achan->name, 2); - } + for (ale= act_data.first; ale; ale= ale->next) + make_sel_cfra_list(ale->key_data, &elems); + + BLI_freelistN(&act_data); + break; + case 2: /* list of selected markers */ + make_marker_cfra_list(&elems, 1); - --clickmin; - --clickmax; + /* apply scaled action correction if needed */ + if (G.saction->pin==0 && OBACT && datatype==ACTCONT_ACTION) { + for (ce= elems.first; ce; ce= ce->next) + ce->cfra= get_action_frame(OBACT, ce->cfra); + } + break; + } + + /* loop through all of the keys and select additional keyframes + * based on the keys found to be selected above + */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_ONLYICU); + actdata_filter(&act_data, filter, data, datatype); + + for (ale= act_data.first; ale; ale= ale->next) { + for(ce= elems.first; ce; ce= ce->next) { + for (icu= ale->key_data; icu; icu= icu->next) { + BezTriple *bezt; + int verts = 0; + + for (bezt=icu->bezt; verts<icu->totvert; bezt++, verts++) { + if (bezt) { + if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) ) + bezt->f2 |= 1; + } + } + } } + } + + BLI_freelistN(&act_data); + BLI_freelistN(&elems); +} + +/* borderselect: for keyframes only */ +void borderselect_action (void) +{ + ListBase act_data = {NULL, NULL}; + bActListElem *ale; + int filter; + void *data; + short datatype; + + rcti rect; + rctf rectf; + int val, selectmode; + int (*select_function)(BezTriple *); + short mval[2]; + float ymin, ymax; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + /* draw and handle the borderselect stuff (ui) and get the select rect */ + if ( (val = get_border(&rect, 3)) ) { + if (val == LEFTMOUSE) { + selectmode = SELECT_ADD; + select_function = select_bezier_add; + } + else { + selectmode = SELECT_SUBTRACT; + select_function = select_bezier_subtract; + } + + mval[0]= rect.xmin; + mval[1]= rect.ymin+2; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + mval[0]= rect.xmax; + mval[1]= rect.ymax-2; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); - if (EXPANDED_ACHAN(achan) == 0) { - /* cannot search IPO/constaint channels */ - continue; + /* if action is mapped in NLA, it returns a correction */ + if (G.saction->pin==0 && OBACT && datatype==ACTCONT_ACTION) { + rectf.xmin= get_action_frame(OBACT, rectf.xmin); + rectf.xmax= get_action_frame(OBACT, rectf.xmax); } - if (achan->ipo) { - /* widget */ - if (clickmax < 0) break; - --clickmin; - --clickmax; - - for (icu= achan->ipo->curve.first; icu; icu=icu->next) { - if (clickmax < 0) break; - - if (clickmin <= 0) { - /* constraint channel */ - select_icu_channel(act, icu, selectmode); + ymax = CHANNELHEIGHT/2; + + /* filter data */ + filter= (ACTFILTER_VISIBLE | ACTFILTER_CHANNELS); + actdata_filter(&act_data, filter, data, datatype); + + /* loop over data, doing border select */ + for (ale= act_data.first; ale; ale= ale->next) { + ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP); + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { + if (ale->key_data) { + if (ale->datatype == ALE_IPO) + borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, selectmode); + else if (ale->datatype == ALE_ICU) + borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_function); } - - --clickmin; - --clickmax; } + ymax=ymin; } - if (achan->constraintChannels.first) { - /* widget */ - if (clickmax < 0) break; - --clickmin; - --clickmax; + /* cleanup */ + BLI_freelistN(&act_data); + + BIF_undo_push("Border Select Action"); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + } +} + +/* **************************************************** */ +/* MOUSE-HANDLING */ + +/* right-hand side - mouse click */ +static void mouse_action (int selectmode) +{ + void *data; + short datatype; + bAction *act; + bActionChannel *achan; + bConstraintChannel *conchan= NULL; + IpoCurve *icu= NULL; + TimeMarker *marker; + void *act_channel; + short sel, act_type; + float selx; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; + + act_channel= get_nearest_action_key(&selx, &sel, &act_type, &achan); + marker=find_nearest_marker(1); + + if (act_channel) { + switch (act_type) { + case ACTTYPE_ICU: + icu= (IpoCurve *)act_channel; + break; + case ACTTYPE_CONCHAN: + conchan= (bConstraintChannel *)act_channel; + break; + default: + achan= (bActionChannel *)act_channel; + } + + if (selectmode == SELECT_REPLACE) { + selectmode = SELECT_ADD; - /* try in constaint channels */ - for (conchan= achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (clickmax < 0) break; - - if (clickmin <= 0) { - /* constraint channel */ - select_constraint_channel(act, conchan, selectmode); - } + deselect_action_keys(0, 0); + + if (datatype == ACTCONT_ACTION) { + deselect_action_channels(0); - --clickmin; - --clickmax; + achan->flag |= ACHAN_SELECTED; + hilight_channel(act, achan, 1); + select_poseelement_by_name(achan->name, 2); /* 2 is activate */ } } + + if (icu) + select_icu_key(icu, selx, selectmode); + else if (conchan) + select_ipo_key(conchan->ipo, selx, selectmode); + else + select_ipo_key(achan->ipo, selx, selectmode); + + std_rmouse_transform(transform_action_keys); + + allqueue(REDRAWIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWOOPS, 0); + allqueue(REDRAWBUTSALL, 0); + } + else if (marker) { + /* not channel, so maybe marker */ + if (selectmode == SELECT_REPLACE) { + deselect_markers(0, 0); + marker->flag |= SELECT; + } + else if (selectmode == SELECT_INVERT) { + if (marker->flag & SELECT) + marker->flag &= ~SELECT; + else + marker->flag |= SELECT; + } + else if (selectmode == SELECT_ADD) + marker->flag |= SELECT; + else if (selectmode == SELECT_SUBTRACT) + marker->flag &= ~SELECT; + + std_rmouse_transform(transform_markers); + + allqueue(REDRAWTIME, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWSOUND, 0); } - - allqueue (REDRAWIPO, 0); - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWACTION, 0); - allqueue (REDRAWNLA, 0); - allqueue (REDRAWOOPS, 0); - allqueue (REDRAWBUTSALL, 0); } -/* lefthand side */ +/* lefthand side - mouse-click */ static void mouse_actionchannels (short mval[]) { bAction *act= G.saction->action; - void *act_channel; - short chan_type; + void *data, *act_channel; + short datatype, chantype; + + /* determine what type of data we are operating on */ + data = get_action_context(&datatype); + if (data == NULL) return; /* get channel to work on */ - act_channel= get_nearest_act_channel(mval, &chan_type); + act_channel= get_nearest_act_channel(mval, &chantype); /* action to take depends on what channel we've got */ - switch (chan_type) { + switch (chantype) { case ACTTYPE_ACHAN: { bActionChannel *achan= (bActionChannel *)act_channel; @@ -2084,1058 +2519,165 @@ static void mouse_actionchannels (short mval[]) allqueue (REDRAWBUTSALL, 0); } -void delete_meshchannel_keys(Key *key) -{ - delete_ipo_keys(key->ipo); - - BIF_undo_push("Delete Action Keys"); - meshkey_do_redraw(key); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} +/* **************************************************** */ +/* ACTION CHANNEL RE-ORDERING */ -void delete_actionchannel_keys(void) +void top_sel_action() { bAction *act; bActionChannel *achan; - bConstraintChannel *conchan; - + + /* Get the selected action, exit if none are selected */ act = G.saction->action; - if (!act) - return; - - for (achan = act->chanbase.first; achan; achan= achan->next) { - if (EDITABLE_ACHAN(achan)) { - /* Check action channel keys*/ - delete_ipo_keys(achan->ipo); - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - /* Delete constraint channel keys */ - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (EDITABLE_CONCHAN(conchan)) - delete_ipo_keys(conchan->ipo); - } - } - } - } - - remake_action_ipos(act); - BIF_undo_push("Delete Action Keys"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); - -} - -static void delete_actionchannels (void) -{ - bAction *act; - bActionChannel *achan, *next; - bConstraintChannel *conchan=NULL, *nextconchan; - int freechan; - - act=G.saction->action; - - if (!act) - return; - - for (achan=act->chanbase.first; achan; achan=achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan)) - break; - - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){ - if (SEL_CONCHAN(conchan)) { - achan= act->chanbase.last; - break; - } - } - } - } - - if (!achan && !conchan) - return; + if (!act) return; - for (achan= act->chanbase.first; achan; achan= next) { - freechan = 0; - next= achan->next; - + for (achan= act->chanbase.first; achan; achan= achan->next){ if (VISIBLE_ACHAN(achan)) { - /* Remove action channels */ - if (SEL_ACHAN(achan)) { - if (achan->ipo) - achan->ipo->id.us--; /* Release the ipo */ - freechan = 1; - - /* Remove constraint channels */ - for (conchan=achan->constraintChannels.first; conchan; conchan=nextconchan) { - nextconchan= conchan->next; - if (freechan || SEL_CONCHAN(conchan)) { - if (conchan->ipo) - conchan->ipo->id.us--; - BLI_freelinkN(&achan->constraintChannels, conchan); - } - } + if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ + /* take it out off the chain keep data */ + BLI_remlink (&act->chanbase, achan); + /* make it first element */ + BLI_insertlinkbefore(&act->chanbase, act->chanbase.first, achan); + achan->flag |= ACHAN_MOVED; + /* restart with rest of list */ + achan= achan->next; } - - if (freechan) - BLI_freelinkN (&act->chanbase, achan); } } - - BIF_undo_push("Delete Action channels"); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - -} - -void clean_shapekeys(Key *key) -{ - int ok; - - /* don't proceed if user refuses */ - if (!key) return; - ok= fbutton(&G.scene->toolsettings->clean_thresh, - 0.0000001f, 1.0, 0.001, 0.1, - "Clean Threshold"); - if (!ok) return; - - /* viable option? */ - if (key->ipo) { - IpoCurve *icu; - - for (icu= key->ipo->curve.first; icu; icu=icu->next) - clean_ipo_curve(icu); - - /* admin and redraw stuff */ - BIF_undo_push("Clean Action"); - allqueue(REMAKEIPO, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } -} - -void clean_actionchannels(bAction *act) -{ - bActionChannel *achan; - bConstraintChannel *conchan; - - Ipo *ipo; - IpoCurve *icu; - - int ok; - - /* don't proceed any further if no action or user refuses */ - if (!act) return; - ok= fbutton(&G.scene->toolsettings->clean_thresh, - 0.0000001f, 1.0, 0.001, 0.1, - "Clean Threshold"); - if (!ok) return; - - /* clean selected channels only */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - if(EDITABLE_ACHAN(achan)) { - /* clean if action channel if selected */ - if (SEL_ACHAN(achan)) { - ipo= achan->ipo; - if (ipo) { - if (EXPANDED_ACHAN(achan) && FILTER_IPO_ACHAN(achan)) { - /* only clean selected ipo-curves */ - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (SEL_ICU(icu) && EDITABLE_ICU(icu)) - clean_ipo_curve(icu); - } - } - else { - /* clean all ipo-curves for action channel */ - for (icu= ipo->curve.first; icu; icu= icu->next) - clean_ipo_curve(icu); - } - } - } - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - /* clean action channel's constraint channels */ - for (conchan= achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (EDITABLE_CONCHAN(conchan)) { - ipo= conchan->ipo; - if (ipo) { - for (icu= ipo->curve.first; icu; icu= icu->next) - clean_ipo_curve(icu); - } - } - } - } - } + /* clear temp flags */ + for (achan= act->chanbase.first; achan; achan= achan->next){ + achan->flag = achan->flag & ~ACHAN_MOVED; } - /* admin and redraws */ - BIF_undo_push("Clean Action"); - allqueue(REMAKEIPO, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); -} - -void sethandles_meshchannel_keys(int code, Key *key) -{ - - sethandles_ipo_keys(key->ipo, code); - - BIF_undo_push("Set handles Action keys"); - meshkey_do_redraw(key); -} - -void sethandles_actionchannel_keys(int code) -{ - bAction *act; - bActionChannel *achan; - bConstraintChannel *conchan; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) - return; - - /* Loop through the channels and set the beziers - * of the selected keys based on the integer code - */ - for (achan = act->chanbase.first; achan; achan= achan->next){ - if (EDITABLE_ACHAN(achan)) { - sethandles_ipo_keys(achan->ipo, code); - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) { - if (EDITABLE_CONCHAN(conchan)) - sethandles_ipo_keys(conchan->ipo, code); - } - } - } - } - /* Clean up and redraw stuff */ - remake_action_ipos(act); - BIF_undo_push("Set handles Action channel"); + remake_action_ipos (act); + BIF_undo_push("Top Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); allqueue(REDRAWNLA, 0); } -void set_ipotype_actionchannels(int ipotype) +void up_sel_action() { - - bAction *act; - bActionChannel *achan; - bConstraintChannel *conchan; - short event; - + bAction *act; + bActionChannel *achan, *prev; + /* Get the selected action, exit if none are selected */ act = G.saction->action; - if (!act) - return; - - if (ipotype == SET_IPO_POPUP) { - /* Present a popup menu asking the user what type - * of IPO curve he/she/GreenBTH wants. ;) - */ - event - = pupmenu("Channel Ipo Type %t|" - "Constant %x1|" - "Linear %x2|" - "Bezier %x3"); - if(event < 1) return; - ipotype = event; - } + if (!act) return; - /* Loop through the channels and for the selected ones set - * the type for each Ipo curve in the channel Ipo (based on - * the value from the popup). - */ - for (achan = act->chanbase.first; achan; achan= achan->next){ - if (EDITABLE_ACHAN(achan)) { - if (SEL_ACHAN(achan)) { - if (achan->ipo) - setipotype_ipo(achan->ipo, ipotype); - } - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - /* constraint channels */ - for (conchan=achan->constraintChannels.first; conchan; conchan= conchan->next) { - if (EDITABLE_CONCHAN(conchan)) { - if (SEL_CONCHAN(conchan)) { - if (conchan->ipo) - setipotype_ipo(conchan->ipo, ipotype); - } - } + for (achan=act->chanbase.first; achan; achan= achan->next) { + if (VISIBLE_ACHAN(achan)) { + if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ + prev = achan->prev; + if (prev) { + /* take it out off the chain keep data */ + BLI_remlink (&act->chanbase, achan); + /* push it up */ + BLI_insertlinkbefore(&act->chanbase, prev, achan); + achan->flag |= ACHAN_MOVED; + /* restart with rest of list */ + achan= achan->next; } } } } - - /* Clean up and redraw stuff */ - remake_action_ipos(act); - BIF_undo_push("Set Ipo type Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -void set_extendtype_actionchannels(int extendtype) -{ - bAction *act; - bActionChannel *achan; - bConstraintChannel *conchan; - short event; - - /* Get the selected action, exit if none are selected - */ - act = G.saction->action; - if (!act) - return; - - if (extendtype == SET_EXTEND_POPUP) { - /* Present a popup menu asking the user what type - * of IPO curve he/she/GreenBTH wants. ;) - */ - event - = pupmenu("Channel Extending Type %t|" - "Constant %x1|" - "Extrapolation %x2|" - "Cyclic %x3|" - "Cyclic extrapolation %x4"); - if(event < 1) return; - extendtype = event; + /* clear temp flags */ + for (achan=act->chanbase.first; achan; achan= achan->next){ + achan->flag = achan->flag & ~ACHAN_MOVED; } - /* Loop through the channels and for the selected ones set - * the type for each Ipo curve in the channel Ipo (based on - * the value from the popup). - */ - for (achan = act->chanbase.first; achan; achan= achan->next) { - if (EDITABLE_ACHAN(achan)) { - if (SEL_ACHAN(achan)) { - if (achan->ipo) { - switch (extendtype) { - case SET_EXTEND_CONSTANT: - setexprap_ipoloop(achan->ipo, IPO_HORIZ); - break; - case SET_EXTEND_EXTRAPOLATION: - setexprap_ipoloop(achan->ipo, IPO_DIR); - break; - case SET_EXTEND_CYCLIC: - setexprap_ipoloop(achan->ipo, IPO_CYCL); - break; - case SET_EXTEND_CYCLICEXTRAPOLATION: - setexprap_ipoloop(achan->ipo, IPO_CYCLX); - break; - } - } - } - - if ((EXPANDED_ACHAN(achan)==0) || (FILTER_CON_ACHAN(achan)==0)) - continue; - - /* constraint channels */ - for (conchan=achan->constraintChannels.first; conchan; conchan= conchan->next) { - if (EDITABLE_CONCHAN(conchan)) { - if (SEL_CONCHAN(conchan)) { - if (conchan->ipo) { - switch (extendtype) { - case SET_EXTEND_CONSTANT: - setexprap_ipoloop(conchan->ipo, IPO_HORIZ); - break; - case SET_EXTEND_EXTRAPOLATION: - setexprap_ipoloop(conchan->ipo, IPO_DIR); - break; - case SET_EXTEND_CYCLIC: - setexprap_ipoloop(conchan->ipo, IPO_CYCL); - break; - case SET_EXTEND_CYCLICEXTRAPOLATION: - setexprap_ipoloop(conchan->ipo, IPO_CYCLX); - break; - } - } - } - } - } - } - } - /* Clean up and redraw stuff */ - remake_action_ipos(act); - BIF_undo_push("Set Ipo type Action channel"); + remake_action_ipos (act); + BIF_undo_push("Up Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); allqueue(REDRAWNLA, 0); } -static void set_snap_actionchannels(bAction *act, short snaptype) -{ - /* snapping function for action channels*/ - bActionChannel *achan; - bConstraintChannel *conchan; - - /* Loop through the channels */ - for (achan = act->chanbase.first; achan; achan= achan->next) { - if(EDITABLE_ACHAN(achan)) { - if (achan->ipo) { - if(G.saction->pin==0 && OBACT) { - actstrip_map_ipo_keys(OBACT, achan->ipo, 0, 1); - snap_ipo_keys(achan->ipo, snaptype); - actstrip_map_ipo_keys(OBACT, achan->ipo, 1, 1); - } - else { - snap_ipo_keys(achan->ipo, snaptype); - } - } - - if ((EXPANDED_ACHAN(achan)==0) || (FILTER_CON_ACHAN(achan)==0)) - continue; - - /* constraint channels */ - for (conchan=achan->constraintChannels.first; conchan; conchan= conchan->next) { - if (EDITABLE_CONCHAN(conchan)) { - if (conchan->ipo) { - if(G.saction->pin==0 && OBACT) { - actstrip_map_ipo_keys(OBACT, conchan->ipo, 0, 1); - snap_ipo_keys(conchan->ipo, snaptype); - actstrip_map_ipo_keys(OBACT, conchan->ipo, 1, 1); - } - else { - snap_ipo_keys(conchan->ipo, snaptype); - } - } - } - } - } - } -} - -static void set_snap_meshchannels(Key *key, short snaptype) -{ - /* snapping function for mesh channels */ - if(key->ipo) { - snap_ipo_keys(key->ipo, snaptype); - } -} - - -void snap_keys_to_frame(int snap_mode) +void down_sel_action() { - /* This function is the generic entry-point for snapping keyframes - * to a frame(s). It passes the work off to sub-functions for the - * different types in the action editor. - */ - - SpaceAction *saction; bAction *act; - Key *key; - char str[32]; - - /* get data */ - saction= curarea->spacedata.first; - if (!saction) return; - act = saction->action; - key = get_action_mesh_key(); - - /* determine mode */ - switch (snap_mode) { - case 1: - strcpy(str, "Snap Keys To Nearest Frame"); - break; - case 2: - strcpy(str, "Snap Keys To Current Frame"); - break; - case 3: - strcpy(str, "Snap Keys To Nearest Marker"); - break; - default: - return; - } - - /* snap to frame */ - if (act) { - set_snap_actionchannels(act, snap_mode); - remake_action_ipos (act); - } - else if (key) { - set_snap_meshchannels(key, snap_mode); - } - else { - return; - } + bActionChannel *achan, *next; - BIF_undo_push(str); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -static void mirror_actionchannels(bAction *act, short mirror_mode) -{ - /* mirror function for action channels */ - bActionChannel *achan; - bConstraintChannel *conchan; + /* Get the selected action, exit if none are selected */ + act = G.saction->action; + if (!act) return; - /* Loop through the channels */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - if (EDITABLE_ACHAN(achan)) { - if (achan->ipo) { - if (G.saction->pin==0 && OBACT) { - actstrip_map_ipo_keys(OBACT, achan->ipo, 0, 1); - mirror_ipo_keys(achan->ipo, mirror_mode); - actstrip_map_ipo_keys(OBACT, achan->ipo, 1, 1); + for (achan= act->chanbase.last; achan; achan= achan->prev) { + if (VISIBLE_ACHAN(achan)) { + if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ + next = achan->next; + if (next) next = next->next; + if (next) { + /* take it out off the chain keep data */ + BLI_remlink (&act->chanbase, achan); + /* move it down */ + BLI_insertlinkbefore(&act->chanbase, next, achan); + achan->flag |= ACHAN_MOVED; } else { - mirror_ipo_keys(achan->ipo, mirror_mode); + /* take it out off the chain keep data */ + BLI_remlink (&act->chanbase, achan); + /* add at end */ + BLI_addtail(&act->chanbase, achan); + achan->flag |= ACHAN_MOVED; } } - - if ((EXPANDED_ACHAN(achan)==0) || (FILTER_CON_ACHAN(achan)==0)) - continue; - - /* constraint channels */ - for (conchan=achan->constraintChannels.first; conchan; conchan= conchan->next) { - if (EDITABLE_CONCHAN(conchan)) { - if (conchan->ipo) { - if(G.saction->pin==0 && OBACT) { - actstrip_map_ipo_keys(OBACT, conchan->ipo, 0, 1); - mirror_ipo_keys(conchan->ipo, mirror_mode); - actstrip_map_ipo_keys(OBACT, conchan->ipo, 1, 1); - } - else { - mirror_ipo_keys(conchan->ipo, mirror_mode); - } - } - } - } } } -} - -static void mirror_meshchannels(Key *key, short mirror_mode) -{ - /* mirror function for mesh channels */ - if(key->ipo) { - mirror_ipo_keys(key->ipo, mirror_mode); - } -} - -void mirror_action_keys(short mirror_mode) -{ - /* This function is the generic entry-point for mirroring keyframes - * to over a frame. It passes the work off to sub-functions for the - * different types in the action editor. - */ - - SpaceAction *saction; - bAction *act; - Key *key; - char str[32]; - - /* get data */ - saction= curarea->spacedata.first; - if (!saction) return; - act = saction->action; - key = get_action_mesh_key(); - - /* determine mode */ - switch (mirror_mode) { - case 1: - strcpy(str, "Mirror Keys Over Current Frame"); - break; - case 2: - strcpy(str, "Mirror Keys Over Y-Axis"); - break; - case 3: - strcpy(str, "Mirror Keys Over X-Axis"); - break; - case 4: - strcpy(str, "Mirror Keys Over Marker"); - break; - default: - return; - } - - /* mirror */ - if (act) { - mirror_actionchannels(act, mirror_mode); - remake_action_ipos (act); - } - else if (key) { - mirror_meshchannels(key, mirror_mode); - } - else { - return; + /* clear temp flags */ + for (achan= act->chanbase.first; achan; achan= achan->next){ + achan->flag = achan->flag & ~ACHAN_MOVED; } - BIF_undo_push(str); + /* Clean up and redraw stuff */ + remake_action_ipos (act); + BIF_undo_push("Down Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); allqueue(REDRAWNLA, 0); } -/* This function allows the user to insert keyframes on the current - * frame from the Action Editor, using the current values of the channels - * to be keyframed. - */ -void insertkey_action(void) +void bottom_sel_action() { bAction *act; - Key *key; - Object *ob= OBACT; - IpoCurve *icu; - short mode; - float cfra; + bActionChannel *achan; - /* get data */ + /* Get the selected action, exit if none are selected */ act = G.saction->action; - key = get_action_mesh_key(); - cfra = frame_to_float(CFRA); + if (!act) return; - if (act) { - bActionChannel *achan; - bConstraintChannel *conchan; - - /* ask user what to keyframe */ - mode = pupmenu("Insert Key%t|All Channels%x1|Only Selected Channels%x2"); - if (mode == 0) return; - - for (achan= act->chanbase.first; achan; achan=achan->next) { - if (EDITABLE_ACHAN(achan)) { - if (achan->ipo && (SEL_ACHAN(achan) || (mode == 1))) { - for (icu= achan->ipo->curve.first; icu; icu=icu->next) { - if (ob) - insertkey((ID *)ob, icu->blocktype, achan->name, NULL, icu->adrcode); - else - insert_vert_ipo(icu, cfra, icu->curval); - } - } - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (EDITABLE_CONCHAN(conchan)) { - if (conchan->ipo && (SEL_ACHAN(conchan) || (mode == 1))) { - for (icu= conchan->ipo->curve.first; icu; icu=icu->next) { - /* // commented out as this doesn't seem to work right for some reason - if (ob) - insertkey((ID *)ob, ID_CO, achan->name, conchan->name, CO_ENFORCE); - else - insert_vert_ipo(icu, cfra, icu->curval); - */ - insert_vert_ipo(icu, cfra, icu->curval); - } - } - } - } - } + for (achan=act->chanbase.last; achan; achan= achan->prev) { + if (VISIBLE_ACHAN(achan)) { + if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { + /* take it out off the chain keep data */ + BLI_remlink (&act->chanbase, achan); + /* add at end */ + BLI_addtail(&act->chanbase, achan); + achan->flag |= ACHAN_MOVED; } - } + } } - else if (key) { - /* ask user if they want to insert a keyframe */ - mode = okee("Insert Keyframe?"); - if (mode == 0) return; - - if (key->ipo) { - for (icu= key->ipo->curve.first; icu; icu=icu->next) { - insert_vert_ipo(icu, cfra, icu->curval); - } - } + /* clear temp flags */ + for (achan=act->chanbase.first; achan; achan= achan->next) { + achan->flag = achan->flag & ~ACHAN_MOVED; } - BIF_undo_push("Insert Key"); + /* Clean up and redraw stuff */ + remake_action_ipos (act); + BIF_undo_push("Bottom Action channel"); allspace(REMAKEIPO, 0); allqueue(REDRAWACTION, 0); allqueue(REDRAWIPO, 0); allqueue(REDRAWNLA, 0); } -static void select_all_keys_frames(bAction *act, short *mval, - short *mvalo, int selectmode) -{ - - /* This function tries to select all action keys in - * every channel for a given range of keyframes that - * are within the mouse values mval and mvalo (usually - * the result of a border select). If mvalo is passed as - * NULL then the selection is treated as a one-click and - * the function tries to select all keys within half a - * frame of the click point. - */ - - rcti rect; - rctf rectf; - bActionChannel *achan; - bConstraintChannel *conchan; - - if (!act) - return; - - if (selectmode == SELECT_REPLACE) { - deselect_actionchannel_keys(act, 0, 0); - selectmode = SELECT_ADD; - } - - if (mvalo == NULL) { - rect.xmin = rect.xmax = mval[0]; - rect.ymin = rect.ymax = mval[1]; - } - else { - if (mval[0] < mvalo[0] ) { - rect.xmin = mval[0]; - rect.xmax = mvalo[0]; - } - else { - rect.xmin = mvalo[0]; - rect.xmax = mval[0]; - } - if (mval[1] < mvalo[1] ) { - rect.ymin = mval[1]; - rect.ymax = mvalo[1]; - } - else { - rect.ymin = mvalo[1]; - rect.ymax = mval[1]; - } - } - - mval[0]= rect.xmin; - mval[1]= rect.ymin+2; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); - mval[0]= rect.xmax; - mval[1]= rect.ymax-2; - areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); - - if (mvalo == NULL) { - rectf.xmin = rectf.xmin - 0.5; - rectf.xmax = rectf.xmax + 0.5; - } - - for (achan=act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); - - if (EXPANDED_ACHAN(achan) && FILTER_CON_ACHAN(achan)) { - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); - } - } - } - } - - allqueue(REDRAWNLA, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); -} - - -static void select_all_keys_channels(bAction *act, short *mval, - short *mvalo, int selectmode) -{ - bActionChannel *achan; - bConstraintChannel *conchan; - float click, x,y; - int clickmin, clickmax; - - /* This function selects all the action keys that - * are in the mouse selection range defined by - * the ordered pairs mval and mvalo (usually - * these 2 are obtained from a border select). - * If mvalo is NULL, then the selection is - * treated like a one-click action, and at most - * one channel is selected. - */ - - /* If the action is null then abort */ - if (!act) - return; - - if (selectmode == SELECT_REPLACE) { - deselect_actionchannel_keys(act, 0, 0); - selectmode = SELECT_ADD; - } - - areamouseco_to_ipoco(G.v2d, mval, &x, &y); - clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP)); - - /* Only one click */ - if (mvalo == NULL) { - clickmax = clickmin; - } - /* Two click values (i.e., border select) */ - else { - areamouseco_to_ipoco(G.v2d, mvalo, &x, &y); - click = (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP)); - - if ( ((int) click) < clickmin) { - clickmax = clickmin; - clickmin = (int) click; - } - else { - clickmax = (int) click; - } - } - - if (clickmax < 0) { - return; - } - - for (achan = act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (clickmax < 0) break; - - if (clickmin <= 0) { - /* Select the channel with the given mode. If the - * channel is freshly selected then set it to the - * active channel for the action - */ - select_ipo_bezier_keys(achan->ipo, selectmode); - } - --clickmin; - --clickmax; - - if ((EXPANDED_ACHAN(achan)==0) || (FILTER_CON_ACHAN(achan)==0)) - continue; - - /* Check for click in a constraint */ - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (clickmax < 0) break; - if (clickmin <= 0) { - select_ipo_bezier_keys(achan->ipo, selectmode); - } - --clickmin; - --clickmax; - } - } - } - - allqueue (REDRAWIPO, 0); - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWACTION, 0); - allqueue (REDRAWNLA, 0); -} - -static void borderselect_function(void (*select_func)(bAction *act, - short *mval, - short *mvalo, - int selectmode)) -{ - /* This function executes an arbitrary selection - * function as part of a border select. This - * way the same function that is used for - * right click selection points can generally - * be used as the argument to this function - */ - bAction *act; - rcti rect; - short mval[2], mvalo[2]; - int val; - - /* Get the selected action, exit if none are selected */ - act=G.saction->action; - if (!act) - return; - - /* Let the user draw a border (or abort) */ - if ( (val=get_border (&rect, 3)) ) { - mval[0]= rect.xmin; - mval[1]= rect.ymin+2; - mvalo[0]= rect.xmax; - mvalo[1]= rect.ymax-2; - - /* if the left mouse was used, do an additive - * selection with the user defined selection - * function. - */ - if (val == LEFTMOUSE) - select_func(act, mval, mvalo, SELECT_ADD); - - /* if the right mouse was used, do a subtractive - * selection with the user defined selection - * function. - */ - else if (val == RIGHTMOUSE) - select_func(act, mval, mvalo, SELECT_SUBTRACT); - } - - BIF_undo_push("Border Select Action"); -} - -static void clever_keyblock_names(Key *key, short* mval){ - int but=0, i, keynum; - char str[64]; - float x; - KeyBlock *kb; - /* get the keynum cooresponding to the y value - * of the mouse pointer, return if this is - * an invalid key number (and we don't deal - * with the speed ipo). - */ - - keynum = get_nearest_key_num(key, mval, &x); - if ( (keynum < 1) || (keynum >= key->totkey) ) - return; - - kb= key->block.first; - for (i=0; i<keynum; ++i) kb = kb->next; - - if (kb->name[0] == '\0') { - sprintf(str, "Key %d", keynum); - } - else { - strcpy(str, kb->name); - } - - if ( (kb->slidermin >= kb->slidermax) ) { - kb->slidermin = 0.0; - kb->slidermax = 1.0; - } - - add_numbut(but++, TEX, "KB: ", 0, 24, str, - "Does this really need a tool tip?"); - add_numbut(but++, NUM|FLO, "Slider Min:", - -10000, kb->slidermax, &kb->slidermin, 0); - add_numbut(but++, NUM|FLO, "Slider Max:", - kb->slidermin, 10000, &kb->slidermax, 0); - - if (do_clever_numbuts(str, but, REDRAW)) { - strcpy(kb->name, str); - allqueue (REDRAWACTION, 0); - allspace(REMAKEIPO, 0); - allqueue (REDRAWIPO, 0); - } - - -} - -static void clever_achannel_names(short *mval) -{ - void *act_channel; - bActionChannel *achan= NULL; - bConstraintChannel *conchan= NULL; - IpoCurve *icu= NULL; - - int but=0; - char str[64]; - short expand, protect, chantype; - float slidermin, slidermax; - - /* figure out what is under cursor */ - act_channel= get_nearest_act_channel(mval, &chantype); - - /* create items for clever-numbut */ - if (chantype == ACTTYPE_ACHAN) { - achan= (bActionChannel *)act_channel; - - strcpy(str, achan->name); - protect= (achan->flag & ACHAN_PROTECTED); - expand = (achan->flag & ACHAN_EXPANDED); - - add_numbut(but++, TEX, "ActChan: ", 0, 31, str, "Name of Action Channel"); - add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Channel is Expanded"); - add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); - } - else if (chantype == ACTTYPE_CONCHAN) { - conchan= (bConstraintChannel *)act_channel; - - strcpy(str, conchan->name); - protect= (conchan->flag & CONSTRAINT_CHANNEL_PROTECTED); - - add_numbut(but++, TEX, "ConChan: ", 0, 29, str, "Name of Constraint Channel"); - add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); - } - else if (chantype == ACTTYPE_ICU) { - icu= (IpoCurve *)act_channel; - - strcpy(str, getname_ipocurve(icu)); - - if (IS_EQ(icu->slide_max, icu->slide_min)) { - if (IS_EQ(icu->ymax, icu->ymin)) { - icu->slide_min= -100.0; - icu->slide_max= 100.0; - } - else { - icu->slide_min= icu->ymin; - icu->slide_max= icu->ymax; - } - } - slidermin= icu->slide_min; - slidermax= icu->slide_max; - - //protect= (icu->flag & IPO_PROTECT); - - add_numbut(but++, NUM|FLO, "Slider Min:", -10000, slidermax, &slidermin, 0); - add_numbut(but++, NUM|FLO, "Slider Max:", slidermin, 10000, &slidermax, 0); - //add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); - } - else { - /* nothing under-cursor */ - return; - } - - - /* draw clever-numbut */ - if (do_clever_numbuts(str, but, REDRAW)) { - /* restore settings based on type */ - if (icu) { - icu->slide_min= slidermin; - icu->slide_max= slidermax; - - //if (protect) icu->flag |= IPO_PROTECT; - //else icu->flag &= ~IPO_PROTECT; - } - else if (conchan) { - strcpy(conchan->name, str); - - if (protect) conchan->flag |= CONSTRAINT_CHANNEL_PROTECTED; - else conchan->flag &= ~CONSTRAINT_CHANNEL_PROTECTED; - } - else if (achan) { - strcpy(achan->name, str); - - if (expand) achan->flag |= ACHAN_EXPANDED; - else achan->flag &= ~ACHAN_EXPANDED; - - if (protect) achan->flag |= ACHAN_PROTECTED; - else achan->flag &= ~ACHAN_PROTECTED; - } - - allqueue (REDRAWACTION, 0); - allqueue (REDRAWVIEW3D, 0); - } -} - -/* this gets called when nkey is pressed (no Transform Properties panel yet) */ -static void numbuts_action(void) -{ - /* now called from action window event loop, plus reacts on mouseclick */ - /* removed Hos grunts for that reason! :) (ton) */ - bAction *act; - Key *key; - short mval[2]; - - key = get_action_mesh_key(); - act = G.saction->action; - - getmouseco_areawin (mval); - - if (mval[0] < NAMEWIDTH) { - if (act) - clever_achannel_names(mval); - else if (key) - clever_keyblock_names(key, mval); - } -} +/* **************************************************** */ +/* EVENT HANDLING */ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { @@ -3186,96 +2728,38 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case AKEY: - if (act) { - if (mval[0]<NAMEWIDTH) { - deselect_actionchannels (act, 1); - allqueue (REDRAWVIEW3D, 0); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } - else if (mval[0]>ACTWIDTH) { - if (G.qual == LR_CTRLKEY) { - deselect_markers (1, 0); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); - } - else { - deselect_actionchannel_keys (act, 1, 1); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } - } + if (mval[0]<NAMEWIDTH) { + deselect_action_channels (1); + allqueue (REDRAWVIEW3D, 0); + allqueue (REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); } - else if (key) { - if (mval[0]<ACTWIDTH) { - /* to do ??? */ + else if (mval[0]>ACTWIDTH) { + if (G.qual == LR_CTRLKEY) { + deselect_markers (1, 0); + allqueue(REDRAWTIME, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWSOUND, 0); } else { - if (G.qual == LR_CTRLKEY) { - deselect_markers(1, 0); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); - } - else { - deselect_meshchannel_keys(key, 1, 1); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } + deselect_action_keys (1, 1); + allqueue (REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); } } break; case BKEY: - if (G.qual & LR_CTRLKEY) + if (G.qual & LR_CTRLKEY) { borderselect_markers(); - else if (act) { - /* If the border select is initiated in the - * part of the action window where the channel - * names reside, then select the channels - */ - if (mval[0]<NAMEWIDTH) { - borderselect_function(borderselect_actionchannels); - BIF_undo_push("Select Action"); - } - else if (mval[0]>ACTWIDTH) { - /* If the border select is initiated in the - * vertical scrollbar, then (de)select all keys - * for the channels in the selection region - */ - if (IN_2D_VERT_SCROLL(mval)) { - borderselect_function(select_all_keys_channels); - } - - /* If the border select is initiated in the - * horizontal scrollbar, then (de)select all keys - * for the keyframes in the selection region - */ - else if (IN_2D_HORIZ_SCROLL(mval)) { - borderselect_function(select_all_keys_frames); - } - - /* Other wise, select the action keys */ - else { - borderselect_action(); - } - } } - else if (key) { - if (mval[0]<ACTWIDTH) { - /* to do?? */ - } - else { - borderselect_mesh(key); - } + else { + if (mval[0]>ACTWIDTH) + borderselect_action(); } break; @@ -3288,18 +2772,10 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case DKEY: if (mval[0]>ACTWIDTH) { - if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) { + if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) duplicate_marker(); - } - else if (G.qual == LR_SHIFTKEY) { - if (act) { - duplicate_actionchannel_keys(); - remake_action_ipos(act); - } - else if (key) { - duplicate_meshchannel_keys(key); - } - } + else if (G.qual == LR_SHIFTKEY) + duplicate_action_keys(); } break; @@ -3308,33 +2784,19 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) transform_markers('g', 0); } else { - if (mval[0]>=ACTWIDTH) { - if (act) { - transform_actionchannel_keys ('g', 0); - } - else if (key) { - transform_meshchannel_keys('g', key); - } - } + if (mval[0]>=ACTWIDTH) + transform_action_keys('g', 0); } break; case HKEY: if(G.qual & LR_SHIFTKEY) { - if(okee("Set Keys to Auto Handle")) { - if (act) - sethandles_actionchannel_keys(HD_AUTO); - else if (key) - sethandles_meshchannel_keys(HD_AUTO, key); - } + if(okee("Set Keys to Auto Handle")) + sethandles_action_keys(HD_AUTO); } else { - if(okee("Toggle Keys Aligned Handle")) { - if (act) - sethandles_actionchannel_keys(HD_ALIGN); - else if (key) - sethandles_meshchannel_keys(HD_ALIGN, key); - } + if(okee("Toggle Keys Aligned Handle")) + sethandles_action_keys(HD_ALIGN); } break; @@ -3344,11 +2806,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } else { val= (G.qual & LR_SHIFTKEY) ? 2 : 1; - - if (act) - column_select_actionkeys(act, val); - else if (key) - column_select_shapekeys(key, val); + column_select_action_keys(val); } allqueue(REDRAWTIME, 0); @@ -3392,10 +2850,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case OKEY: - if(act) - clean_actionchannels(act); - else if(key) - clean_shapekeys(key); + clean_action(); break; case PKEY: @@ -3415,35 +2870,24 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(G.qual & LR_SHIFTKEY) { if (act || key) { val = pupmenu("Snap Keys To%t|Nearest Frame%x1|Current Frame%x2|Nearest Marker %x3"); - snap_keys_to_frame(val); + snap_action_keys(val); } } - else { - if (act) - transform_actionchannel_keys ('s', 0); - else if (key) - transform_meshchannel_keys('s', key); - } + else + transform_action_keys ('s', 0); } break; case TKEY: - if (act) { - if(G.qual & LR_SHIFTKEY) - set_ipotype_actionchannels(SET_IPO_POPUP); - else - transform_actionchannel_keys ('t', 0); - } - /* else if (key) {} ... todo */ + if(G.qual & LR_SHIFTKEY) + action_set_ipo_flags(SET_IPO_POPUP); + else + transform_action_keys ('t', 0); break; case VKEY: - if(okee("Set Keys to Vector Handle")) { - if (act) - sethandles_actionchannel_keys(HD_VECT); - else if (key) - sethandles_meshchannel_keys(HD_VECT, key); - } + if(okee("Set Keys to Vector Handle")) + sethandles_action_keys(HD_VECT); break; case PAGEUPKEY: @@ -3478,15 +2922,10 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case DELKEY: case XKEY: if (okee("Erase selected")) { - if (act) { - if (mval[0]<NAMEWIDTH) - delete_actionchannels(); - else - delete_actionchannel_keys(); - } - else if (key) { - delete_meshchannel_keys(key); - } + if (mval[0]<NAMEWIDTH) + delete_action_channels(); + else + delete_action_keys(); if (mval[0] >= NAMEWIDTH) remove_marker(); @@ -3538,45 +2977,26 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else numbuts_action(); } else if (mval[0]>ACTWIDTH) { + short select_mode= (G.qual & LR_SHIFTKEY)? SELECT_INVERT: SELECT_REPLACE; + /* Clicking in the vertical scrollbar selects * all of the keys for that channel at that height */ - if (IN_2D_VERT_SCROLL(mval)) { - if(G.qual & LR_SHIFTKEY) - select_all_keys_channels(act, mval, NULL, SELECT_INVERT); - else - select_all_keys_channels(act, mval, NULL, SELECT_REPLACE); - } + if (IN_2D_VERT_SCROLL(mval)) + selectall_action_keys(mval, 0, select_mode); /* Clicking in the horizontal scrollbar selects * all of the keys within 0.5 of the nearest integer * frame */ - else if (IN_2D_HORIZ_SCROLL(mval)) { - if(G.qual & LR_SHIFTKEY) - select_all_keys_frames(act, mval, NULL, SELECT_INVERT); - else - select_all_keys_frames(act, mval, NULL, SELECT_REPLACE); - BIF_undo_push("Select all Action"); - } + else if (IN_2D_HORIZ_SCROLL(mval)) + selectall_action_keys(mval, 1, select_mode); /* Clicking in the main area of the action window * selects keys and markers */ - else { - if (act) { - if(G.qual & LR_SHIFTKEY) - mouse_action(SELECT_INVERT); - else - mouse_action(SELECT_REPLACE); - } - else if (key) { - if(G.qual & LR_SHIFTKEY) - mouse_mesh_action(SELECT_INVERT, key); - else - mouse_mesh_action(SELECT_REPLACE, key); - } - } + else + mouse_action(select_mode); } break; case PADPLUSKEY: @@ -3605,634 +3025,4 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } -Key *get_action_mesh_key(void) -{ - /* gets the key data from the currently selected - * mesh/lattice. If a mesh is not selected, or does not have - * key data, then we return NULL (currently only - * returns key data for RVK type meshes). If there - * is an action that is pinned, return null - */ - Object *ob; - Key *key; - - ob = OBACT; - if (!ob) return NULL; - - if (G.saction->pin) return NULL; - - if (ob->type==OB_MESH ) { - key = ((Mesh *)ob->data)->key; - } - else if (ob->type==OB_LATTICE ) { - key = ((Lattice *)ob->data)->key; - } - else return NULL; - - if (key) { - if (key->type == KEY_RELATIVE) - return key; - } - - return NULL; -} - -int get_nearest_key_num(Key *key, short *mval, float *x) -{ - /* returns the key num that cooresponds to the - * y value of the mouse click. Does not check - * if this is a valid keynum. Also gives the Ipo - * x coordinate. - */ - int num; - float ybase, y; - - areamouseco_to_ipoco(G.v2d, mval, x, &y); - - ybase = key->totkey * (CHANNELHEIGHT + CHANNELSKIP); - num = (int) ((ybase - y + CHANNELHEIGHT/2) / (CHANNELHEIGHT+CHANNELSKIP)); - - return (num + 1); -} - -void *get_nearest_act_channel(short mval[], short *ret_type) -{ - /* Returns the 'channel' that is under the mouse cursor. - * This 'channel' can either be an action channel, or a constraint channel. - * - * #ret_type# is used to denote what type of channel was found. - * It should only be one of the ACTTYPE_* constant values. - */ - - bAction *act= G.saction->action; - bActionChannel *achan; - bConstraintChannel *conchan; - IpoCurve *icu; - - float x,y; - int clickmin, clickmax; - - if (act == 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; - } - - /* try in action channels */ - for (achan = act->chanbase.first; achan; achan=achan->next) { - if(VISIBLE_ACHAN(achan)) { - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match - action channel */ - *ret_type= ACTTYPE_ACHAN; - return achan; - } - --clickmin; - --clickmax; - } - else - continue; - - if (EXPANDED_ACHAN(achan) == 0) - continue; - - /* try in ipo curves */ - if (achan->ipo) { - /* check header first */ - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match - ipo-curves show/hide */ - *ret_type= ACTTYPE_FILLIPO; - return achan; /* pointer to action-channel is returned in this case */ - } - --clickmin; - --clickmax; - - /* now the ipo-curve channels if they are exposed */ - if (FILTER_IPO_ACHAN(achan)) { - for (icu= achan->ipo->curve.first; icu; icu=icu->next) { - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match - ipo-curve channel */ - *ret_type= ACTTYPE_ICU; - return icu; - } - --clickmin; - --clickmax; - } - } - } - - /* try in constaint channels */ - if (achan->constraintChannels.first) { - /* check header first */ - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match - constraints show/hide */ - *ret_type= ACTTYPE_FILLCON; - return achan; /* pointer to action-channel is returned in this case */ - } - --clickmin; - --clickmax; - - /* now the constraint channels if they are exposed */ - if (FILTER_CON_ACHAN(achan)) { - for (conchan= achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match - constraint channel */ - *ret_type= ACTTYPE_CONCHAN; - return conchan; - } - --clickmin; - --clickmax; - } - } - } - } - - *ret_type= ACTTYPE_NONE; - return NULL; -} - -/* ************************************* Action Editor Markers ************************************* */ - -void markers_selectkeys_between(void) -{ - bAction *act; - Key *key; - float min, max; - - /* get extreme markers */ - get_minmax_markers(1, &min, &max); - if (min==max) return; - min -= 0.5f; - max += 0.5f; - - /* get keyframe data */ - act = G.saction->action; - key = get_action_mesh_key(); - - /* select keys in-between */ - if (act) { - bActionChannel *achan; - bConstraintChannel *conchan; - - for (achan= act->chanbase.first; achan; achan= achan->next) { - if (achan->ipo) { - if(G.saction->pin==0 && OBACT) { - actstrip_map_ipo_keys(OBACT, achan->ipo, 0, 1); - borderselect_ipo_key(achan->ipo, min, max, SELECT_ADD); - actstrip_map_ipo_keys(OBACT, achan->ipo, 1, 1); - } - else { - borderselect_ipo_key(achan->ipo, min, max, SELECT_ADD); - } - } - - if ((EXPANDED_ACHAN(achan)==0) || (FILTER_CON_ACHAN(achan)==0)) - continue; - - for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) { - if (conchan->ipo) { - if(G.saction->pin==0 && OBACT) { - actstrip_map_ipo_keys(OBACT, conchan->ipo, 0, 1); - borderselect_ipo_key(conchan->ipo, min, max, SELECT_ADD); - actstrip_map_ipo_keys(OBACT, conchan->ipo, 1, 1); - } - else { - borderselect_ipo_key(conchan->ipo, min, max, SELECT_ADD); - } - } - } - } - } - else if (key) { - if (key->ipo) - borderselect_ipo_key(key->ipo, min, max, SELECT_ADD); - } -} - -/* ************************************* Action Channel Ordering *********************************** */ - -void top_sel_action() -{ - bAction *act; - bActionChannel *achan; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; - - for (achan= act->chanbase.first; achan; achan= achan->next){ - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* make it first element */ - BLI_insertlinkbefore(&act->chanbase, act->chanbase.first, achan); - achan->flag |= ACHAN_MOVED; - /* restart with rest of list */ - achan= achan->next; - } - } - } - /* clear temp flags */ - for (achan= act->chanbase.first; achan; achan= achan->next){ - achan->flag = achan->flag & ~ACHAN_MOVED; - } - - /* Clean up and redraw stuff */ - remake_action_ipos (act); - BIF_undo_push("Top Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -void up_sel_action() -{ - bAction *act; - bActionChannel *achan, *prev; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; - - for (achan=act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ - prev = achan->prev; - if (prev) { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* push it up */ - BLI_insertlinkbefore(&act->chanbase, prev, achan); - achan->flag |= ACHAN_MOVED; - /* restart with rest of list */ - achan= achan->next; - } - } - } - } - /* clear temp flags */ - for (achan=act->chanbase.first; achan; achan= achan->next){ - achan->flag = achan->flag & ~ACHAN_MOVED; - } - - /* Clean up and redraw stuff */ - remake_action_ipos (act); - BIF_undo_push("Up Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -void down_sel_action() -{ - bAction *act; - bActionChannel *achan, *next; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; - - for (achan= act->chanbase.last; achan; achan= achan->prev) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)){ - next = achan->next; - if (next) next = next->next; - if (next) { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* move it down */ - BLI_insertlinkbefore(&act->chanbase, next, achan); - achan->flag |= ACHAN_MOVED; - } - else { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* add at end */ - BLI_addtail(&act->chanbase, achan); - achan->flag |= ACHAN_MOVED; - } - } - } - } - /* clear temp flags */ - for (achan= act->chanbase.first; achan; achan= achan->next){ - achan->flag = achan->flag & ~ACHAN_MOVED; - } - - /* Clean up and redraw stuff */ - remake_action_ipos (act); - BIF_undo_push("Down Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -void bottom_sel_action() -{ - bAction *act; - bActionChannel *achan; - - /* Get the selected action, exit if none are selected */ - act = G.saction->action; - if (!act) return; - - for (achan=act->chanbase.last; achan; achan= achan->prev) { - if (VISIBLE_ACHAN(achan)) { - if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) { - /* take it out off the chain keep data */ - BLI_remlink (&act->chanbase, achan); - /* add at end */ - BLI_addtail(&act->chanbase, achan); - achan->flag |= ACHAN_MOVED; - } - } - } - /* clear temp flags */ - for (achan=act->chanbase.first; achan; achan= achan->next) { - achan->flag = achan->flag & ~ACHAN_MOVED; - } - - /* Clean up and redraw stuff */ - remake_action_ipos (act); - BIF_undo_push("Bottom Action channel"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -/* ********************************* BAKING STUFF ********************************** */ -/* NOTE: these functions should probably be moved to their own file sometime - Aligorith */ - -void world2bonespace(float boneSpaceMat[][4], float worldSpace[][4], float restPos[][4], float armPos[][4]) -{ - float imatarm[4][4], imatbone[4][4], tmat[4][4], t2mat[4][4]; - - Mat4Invert(imatarm, armPos); - Mat4Invert(imatbone, restPos); - Mat4MulMat4(tmat, imatarm, worldSpace); - Mat4MulMat4(t2mat, tmat, imatbone); - Mat4MulMat4(boneSpaceMat, restPos, t2mat); -} - -bAction *bake_action_with_client (bAction *act, Object *armob, float tolerance) -{ - bArmature *arm; - bAction *result=NULL; - bActionChannel *achan; - bAction *temp; - bPoseChannel *pchan; - ID *id; - float actstart, actend; - int oldframe; - int curframe; - char newname[64]; - - if (!act) - return NULL; - - arm = get_armature(armob); - - if (G.obedit){ - error ("Actions can't be baked in Edit Mode"); - return NULL; - } - - if (!arm || armob->pose==NULL){ - error ("Select an armature before baking"); - return NULL; - } - - /* Get a new action */ - result = add_empty_action("Action"); - id= (ID *)armob; - - /* Assign the new action a unique name */ - sprintf (newname, "%s.BAKED", act->id.name+2); - rename_id(&result->id, newname); - - calc_action_range(act, &actstart, &actend, 1); - - oldframe = G.scene->r.cfra; - - temp = armob->action; - armob->action = result; - - for (curframe=1; curframe<ceil(actend+1.0f); curframe++){ - - /* Apply the old action */ - - G.scene->r.cfra = curframe; - - /* Apply the object ipo */ - extract_pose_from_action(armob->pose, act, curframe); - - where_is_pose(armob); - - /* For each channel: set quats and locs if channel is a bone */ - for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){ - - /* Apply to keys */ - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z); - } - } - - - /* Make another pass to ensure all keyframes are set to linear interpolation mode */ - for (achan = result->chanbase.first; achan; achan=achan->next){ - IpoCurve* icu; - if(achan->ipo) { - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - icu->ipo= IPO_LIN; - } - } - } - - notice ("Made a new action named \"%s\"", newname); - G.scene->r.cfra = oldframe; - armob->action = temp; - - /* restore */ - extract_pose_from_action(armob->pose, act, G.scene->r.cfra); - where_is_pose(armob); - - allqueue(REDRAWACTION, 1); - - return result; -} - - -bAction* bake_obIPO_to_action (Object *ob) -{ - bArmature *arm; - bAction *result=NULL; - bAction *temp; - Bone *bone; - ID *id; - ListBase elems; - int oldframe,testframe; - char newname[64]; - float quat[4],tmat[4][4],startpos[4][4]; - CfraElem *firstcfra, *lastcfra; - - arm = get_armature(ob); - - if (arm) { - - oldframe = CFRA; - result = add_empty_action("Action"); - id = (ID *)ob; - - sprintf (newname, "TESTOBBAKE"); - rename_id(&result->id, newname); - - if(ob!=G.obedit) { // make sure object is not in edit mode - if(ob->ipo) { - /* convert the ipo to a list of 'current frame elements' */ - - temp = ob->action; - ob->action = result; - - elems.first= elems.last= NULL; - make_cfra_list(ob->ipo, &elems); - /* set the beginning armature location */ - firstcfra=elems.first; - lastcfra=elems.last; - CFRA=firstcfra->cfra; - - where_is_object(ob); - Mat4CpyMat4(startpos,ob->obmat); - - /* loop from first key to last, sampling every 10 */ - for (testframe = firstcfra->cfra; testframe<=lastcfra->cfra; testframe=testframe+10) { - CFRA=testframe; - where_is_object(ob); - - for (bone = arm->bonebase.first; bone; bone=bone->next) { - if (!bone->parent) { /* this is a root bone, so give it a key! */ - world2bonespace(tmat,ob->obmat,bone->arm_mat,startpos); - Mat4ToQuat(tmat,quat); - printf("Frame: %i %f, %f, %f, %f\n",CFRA,quat[0],quat[1],quat[2],quat[3]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_X,tmat[3][0]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Y,tmat[3][1]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Z,tmat[3][2]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_X,quat[1]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Y,quat[2]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Z,quat[3]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_W,quat[0]); - //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_X,size[0]); - //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Y,size[1]); - //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Z,size[2]); - } - } - } - BLI_freelistN(&elems); - } - } - CFRA = oldframe; - } - return result; -} - -bAction *bake_everything_to_action (Object *ob) -{ - bArmature *arm; - bAction *result=NULL; - bAction *temp; - Bone *bone; - ID *id; - ListBase elems; - int oldframe,testframe; - char newname[64]; - float quat[4],tmat[4][4],startpos[4][4]; - CfraElem *firstcfra, *lastcfra; - - arm = get_armature(ob); - - if (arm) { - oldframe = CFRA; - result = add_empty_action("Action"); - id = (ID *)ob; - - sprintf (newname, "TESTOBBAKE"); - rename_id(&result->id, newname); - - if(ob!=G.obedit) { // make sure object is not in edit mode - if(ob->ipo) { - /* convert the ipo to a list of 'current frame elements' */ - - temp = ob->action; - ob->action = result; - - elems.first= elems.last= NULL; - make_cfra_list(ob->ipo, &elems); - /* set the beginning armature location */ - firstcfra=elems.first; - lastcfra=elems.last; - CFRA=firstcfra->cfra; - - where_is_object(ob); - Mat4CpyMat4(startpos,ob->obmat); - - /* loop from first key to last, sampling every 10 */ - for (testframe = firstcfra->cfra; testframe<=lastcfra->cfra; testframe=testframe+10) { - CFRA=testframe; - - do_all_pose_actions(ob); - where_is_object(ob); - for (bone = arm->bonebase.first; bone; bone=bone->next) { - if (!bone->parent) { /* this is a root bone, so give it a key! */ - world2bonespace(tmat,ob->obmat,bone->arm_mat,startpos); - - Mat4ToQuat(tmat,quat); - printf("Frame: %i %f, %f, %f, %f\n",CFRA,quat[0],quat[1],quat[2],quat[3]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_X,tmat[3][0]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Y,tmat[3][1]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_LOC_Z,tmat[3][2]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_X,quat[1]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Y,quat[2]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_Z,quat[3]); - insertmatrixkey(id, ID_PO, bone->name, NULL, AC_QUAT_W,quat[0]); - //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_X,size[0]); - //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Y,size[1]); - //insertmatrixkey(id, ID_PO, bone->name, NULL, AC_SIZE_Z,size[2]); - } - } - } - BLI_freelistN(&elems); - } - } - CFRA = oldframe; - } - return result; -} +/* **************************************************** */ diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index fe88d2da3c0..b8102aa0704 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -496,21 +496,40 @@ static int vis_edit_icu_bez(EditIpo *ei) 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; - } + /* 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; + } } void sethandles_ipo_keys(Ipo *ipo, int code) diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index 73eea2b5aa4..16952df953c 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -2199,7 +2199,8 @@ void bake_all_to_action(void) ob = get_object_from_active_strip(); if (ob) { if (ob->flag&OB_ARMATURE) { - newAction = bake_obIPO_to_action(ob); + //newAction = bake_obIPO_to_action(ob); + newAction = NULL; if (newAction) { /* unlink the object's IPO */ ipo=ob->ipo; diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c index 14a62d67231..340a8008883 100644 --- a/source/blender/src/header_action.c +++ b/source/blender/src/header_action.c @@ -149,10 +149,7 @@ void do_action_buttons(unsigned short event) { Object *ob= OBACT; - switch(event){ - case B_ACTBAKE: - bake_action_with_client(G.saction->action, ob, 0.01); - break; + switch(event) { case B_ACTHOME: /* Find X extents */ G.v2d->cur.xmin = 0; @@ -362,6 +359,7 @@ static void do_action_selectmenu_columnmenu(void *arg, int event) act = saction->action; key = get_action_mesh_key(); +#if 0 // actionrewite if (event == ACTMENU_SEL_COLUMN_MARKERSBETWEEN) { markers_selectkeys_between(); } @@ -373,6 +371,7 @@ static void do_action_selectmenu_columnmenu(void *arg, int event) } else return; +#endif // actionrewite allqueue(REDRAWTIME, 0); allqueue(REDRAWIPO, 0); @@ -422,12 +421,7 @@ static void do_action_selectmenu(void *arg, int event) switch(event) { case ACTMENU_SEL_BORDER: /* Border Select */ - if (act) { - borderselect_action(); - } - else if (key) { - borderselect_mesh(key); - } + borderselect_action(); break; case ACTMENU_SEL_BORDERM: /* Border Select */ @@ -435,22 +429,14 @@ static void do_action_selectmenu(void *arg, int event) break; case ACTMENU_SEL_ALL_KEYS: /* Select/Deselect All Keys */ - if (act) { - deselect_actionchannel_keys (act, 1, 1); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } - else if (key) { - deselect_meshchannel_keys(key, 1, 1); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } + deselect_action_keys(1, 1); + allqueue (REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); break; case ACTMENU_SEL_ALL_CHAN: /* Select/Deselect All Channels */ - deselect_actionchannels(act, 1); + deselect_action_channels(1); allqueue (REDRAWVIEW3D, 0); allqueue (REDRAWACTION, 0); allqueue(REDRAWNLA, 0); @@ -467,18 +453,10 @@ static void do_action_selectmenu(void *arg, int event) break; case ACTMENU_SEL_INVERSE_KEYS: /* invert selection status of keys */ - if (act) { - deselect_actionchannel_keys(act, 0, 2); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } - else if (key) { - deselect_meshchannel_keys(key, 0, 2); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } + deselect_action_keys(0, 2); + allqueue (REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); break; case ACTMENU_SEL_INVERSE_MARKERS: /* invert selection of markers */ @@ -558,42 +536,17 @@ static uiBlock *action_selectmenu(void *arg_unused) } static void do_action_keymenu_transformmenu(void *arg, int event) -{ - SpaceAction *saction; - bAction *act; - Key *key; - - saction = curarea->spacedata.first; - if (!saction) return; - - act = saction->action; - key = get_action_mesh_key(); - +{ switch (event) { case ACTMENU_KEY_TRANSFORM_MOVE: - if (act) { - transform_actionchannel_keys ('g', 0); - } - else if (key) { - transform_meshchannel_keys('g', key); - } + transform_action_keys('g', 0); break; case ACTMENU_KEY_TRANSFORM_SCALE: - if (act) { - transform_actionchannel_keys ('s', 0); - } - else if (key) { - transform_meshchannel_keys('s', key); - } + transform_action_keys ('s', 0); break; case ACTMENU_KEY_TRANSFORM_SLIDE: - if (act) { - transform_actionchannel_keys ('t', 0); - } - else if (key) { - //transform_meshchannel_keys('t', key); - } + transform_action_keys ('t', 0); break; } @@ -628,24 +581,9 @@ static uiBlock *action_keymenu_transformmenu(void *arg_unused) static void do_action_keymenu_handlemenu(void *arg, int event) { - SpaceAction *saction; - bAction *act; - Key *key; - - saction = curarea->spacedata.first; - if (!saction) return; - - act = saction->action; - key = get_action_mesh_key(); - switch (event) { case ACTMENU_KEY_HANDLE_AUTO: - if (act) { - sethandles_actionchannel_keys(HD_AUTO); - } - else if (key) { - sethandles_meshchannel_keys(HD_AUTO, key); - } + sethandles_action_keys(HD_AUTO); break; case ACTMENU_KEY_HANDLE_ALIGN: @@ -653,21 +591,11 @@ static void do_action_keymenu_handlemenu(void *arg, int event) /* OK, this is kinda dumb, need to fix the * toggle crap in sethandles_ipo_keys() */ - if (act) { - sethandles_actionchannel_keys(HD_ALIGN); - } - else if (key) { - sethandles_meshchannel_keys(HD_ALIGN, key); - } + sethandles_action_keys(HD_ALIGN); break; case ACTMENU_KEY_HANDLE_VECTOR: - if (act) { - sethandles_actionchannel_keys(HD_VECT); - } - else if (key) { - sethandles_meshchannel_keys(HD_VECT, key); - } + sethandles_action_keys(HD_VECT); break; } } @@ -705,32 +633,16 @@ static uiBlock *action_keymenu_handlemenu(void *arg_unused) static void do_action_keymenu_intpolmenu(void *arg, int event) { - SpaceAction *saction; - bAction *act; - //Key *key; - - saction = curarea->spacedata.first; - if (!saction) return; - - act = saction->action; - //key = get_action_mesh_key(); - switch(event) { case ACTMENU_KEY_INTERP_CONST: - if (act) - set_ipotype_actionchannels(SET_IPO_CONSTANT); - //else if (key) /* todo */ + action_set_ipo_flags(SET_IPO_CONSTANT); break; case ACTMENU_KEY_INTERP_LINEAR: - if (act) - set_ipotype_actionchannels(SET_IPO_LINEAR); - //else if (key) /* todo */ + action_set_ipo_flags(SET_IPO_LINEAR); break; case ACTMENU_KEY_INTERP_BEZIER: - if (act) - set_ipotype_actionchannels(SET_IPO_BEZIER); - //else if (key) /* todo */ + action_set_ipo_flags(SET_IPO_BEZIER); break; } @@ -767,37 +679,19 @@ static uiBlock *action_keymenu_intpolmenu(void *arg_unused) static void do_action_keymenu_extendmenu(void *arg, int event) { - SpaceAction *saction; - bAction *act; - //Key *key; - - saction = curarea->spacedata.first; - if (!saction) return; - - act = saction->action; - //key = get_action_mesh_key(); - switch(event) { case ACTMENU_KEY_EXTEND_CONST: - if (act) - set_extendtype_actionchannels(SET_EXTEND_CONSTANT); - //else if (key) /* todo */ + action_set_ipo_flags(SET_EXTEND_CONSTANT); break; case ACTMENU_KEY_EXTEND_EXTRAPOLATION: - if (act) - set_extendtype_actionchannels(SET_EXTEND_EXTRAPOLATION); - //else if (key) /* todo */ + action_set_ipo_flags(SET_EXTEND_EXTRAPOLATION); break; case ACTMENU_KEY_EXTEND_CYCLIC: - if (act) - set_extendtype_actionchannels(SET_EXTEND_CYCLIC); - //else if (key) /* todo */ + action_set_ipo_flags(SET_EXTEND_CYCLIC); break; case ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION: - if (act) - set_extendtype_actionchannels(SET_EXTEND_CYCLICEXTRAPOLATION); - //else if (key) /* todo */ + action_set_ipo_flags(SET_EXTEND_CYCLICEXTRAPOLATION); break; } @@ -900,7 +794,7 @@ static void do_action_keymenu_snapmenu(void *arg, int event) case ACTMENU_KEY_SNAP_NEARFRAME: case ACTMENU_KEY_SNAP_CURFRAME: case ACTMENU_KEY_SNAP_NEARMARK: - snap_keys_to_frame(event); + snap_action_keys(event); break; } @@ -995,31 +889,13 @@ static void do_action_keymenu(void *arg, int event) switch(event) { case ACTMENU_KEY_DUPLICATE: - if (act) { - duplicate_actionchannel_keys(); - remake_action_ipos(act); - } - else if (key) { - duplicate_meshchannel_keys(key); - } + duplicate_action_keys(); break; - case ACTMENU_KEY_DELETE: - if (act) { - delete_actionchannel_keys (); - } - else if (key) { - delete_meshchannel_keys(key); - } - break; - case ACTMENU_KEY_BAKE: - bake_action_with_client(G.saction->action, OBACT, 0.01); + delete_action_keys (); break; case ACTMENU_KEY_CLEAN: - if (act) - clean_actionchannels(act); - else if (key) - clean_shapekeys(key); + clean_action(); break; } } @@ -1062,11 +938,6 @@ static uiBlock *action_keymenu(void *arg_unused) "Clean Action|O", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, ACTMENU_KEY_CLEAN, ""); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, - "Bake Action to Ipo Keys", 0, yco-=20, - menuwidth, 19, NULL, 0.0, 0.0, 0, - ACTMENU_KEY_BAKE, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -1261,16 +1132,6 @@ void action_buttons(void) from, &(G.saction->actnr), B_ACTALONE, B_ACTLOCAL, B_ACTIONDELETE, 0, 0); - - /* Draw action baker */ - xco+= 8; - - uiDefBut(block, BUT, B_ACTBAKE, - "Bake", xco, 0, 64, YIC, 0, 0, 0, 0, 0, - "Create an action with the constraint effects " - "converted into Ipo keys"); - xco+=64; - uiClearButLock(); /* draw AUTOSNAP */ |