diff options
Diffstat (limited to 'source/blender/src/editaction.c')
-rw-r--r-- | source/blender/src/editaction.c | 3097 |
1 files changed, 0 insertions, 3097 deletions
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c deleted file mode 100644 index cb032ddfb61..00000000000 --- a/source/blender/src/editaction.c +++ /dev/null @@ -1,3097 +0,0 @@ -/** - * $Id$ - * - * ***** 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 rewrite of Action Editor) - * - * ***** END GPL/BL DUAL LICENSE BLOCK ***** - */ - -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - -#include "PIL_time.h" - -#include "BLI_blenlib.h" -#include "BLI_arithb.h" - -#include "DNA_action_types.h" -#include "DNA_armature_types.h" -#include "DNA_curve_types.h" -#include "DNA_ipo_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_userdef_types.h" -#include "DNA_constraint_types.h" -#include "DNA_key_types.h" -#include "DNA_mesh_types.h" -#include "DNA_nla_types.h" -#include "DNA_lattice_types.h" - -#include "BKE_action.h" -#include "BKE_armature.h" -#include "BKE_constraint.h" -#include "BKE_curve.h" -#include "BKE_depsgraph.h" -#include "BKE_global.h" -#include "BKE_ipo.h" -#include "BKE_key.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_utildefines.h" -#include "BKE_object.h" /* for where_is_object in obanim -> action baking */ - -#include "BIF_butspace.h" -#include "BIF_editaction.h" -#include "BIF_editarmature.h" -#include "BIF_editnla.h" -#include "BIF_editview.h" -#include "BIF_gl.h" -#include "BIF_interface.h" -#include "BIF_mywindow.h" -#include "BIF_poseobject.h" -#include "BIF_screen.h" -#include "BIF_space.h" -#include "BIF_toolbox.h" -#include "BIF_transform.h" - -#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" - -#include "BDR_drawaction.h" -#include "BDR_editobject.h" - -#include "mydevice.h" -#include "blendef.h" -#include "nla.h" - -/* **************************************************** */ -/* ACTION API */ - -/* this function adds a new Action block */ -bAction *add_empty_action (char *name) -{ - bAction *act; - - act= alloc_libblock(&G.main->action, ID_AC, name); - act->id.flag |= LIB_FAKEUSER; - act->id.us++; - - return act; -} - -/* generic get current action call, for action window context */ -bAction *ob_get_action (Object *ob) -{ - bActionStrip *strip; - - 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; -} - -/* used by ipo, outliner, buttons to find the active channel */ -bActionChannel *get_hilighted_action_channel (bAction *action) -{ - bActionChannel *achan; - - if (!action) - 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; -} - -/* ----------------------------------------- */ - -void remake_action_ipos (bAction *act) -{ - bActionChannel *achan; - bConstraintChannel *conchan; - IpoCurve *icu; - - for (achan= act->chanbase.first; achan; achan= achan->next) { - if (achan->ipo) { - for (icu = achan->ipo->curve.first; icu; icu=icu->next) { - sort_time_ipocurve(icu); - testhandles_ipocurve(icu); - } - } - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){ - if (conchan->ipo) { - for (icu = conchan->ipo->curve.first; icu; icu=icu->next){ - sort_time_ipocurve(icu); - testhandles_ipocurve(icu); - } - } - } - } - - synchronize_action_strips(); -} - -/* **************************************************** */ -/* 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) -{ - 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; -} - -/* ----------------------------------------- */ - -static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode) -{ - 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); - } - } - else { - /* only consider selected channels - achan not selected */ - continue; - } - - /* 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); - } - } - } - } - } - } - } - } - } -} - -static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mode) -{ - bActListElem *ale; - KeyBlock *kb; - IpoCurve *icu; - int i; - - /* are we filtering for display or editing */ - if (filter_mode & ACTFILTER_FORDRAWING) { - /* for display - loop over shapekeys, adding ipo-curve references where needed */ - kb= key->block.first; - - /* loop through possible shapekeys, manually creating entries */ - for (i= 1; i < key->totkey; i++) { - ale= MEM_callocN(sizeof(bActListElem), "bActListElem"); - kb = kb->next; - - ale->data= kb; - ale->type= ACTTYPE_SHAPEKEY; /* 'abused' usage of this type */ - ale->owner= key; - ale->ownertype= ACTTYPE_SHAPEKEY; - ale->datatype= ALE_NONE; - ale->index = i; - - if (key->ipo) { - for (icu= key->ipo->curve.first; icu; icu=icu->next) { - if (icu->adrcode == i) { - ale->key_data= icu; - ale->datatype= ALE_ICU; - break; - } - } - } - - BLI_addtail(act_data, ale); - } - } - else { - /* loop over ipo curves if present - for editing */ - 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; - } - - /* 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 - */ -/* Note: there's a similar function in key.c (ob_get_key) */ -Key *get_action_mesh_key(void) -{ - Object *ob; - Key *key; - - ob = OBACT; - if (ob == NULL) - 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; -} - -/* 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 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_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS); - actdata_filter(&act_data, filter, data, datatype); - - for (ale= act_data.first; ale; ale= ale->next) { - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match */ - *ret_type= ale->type; - data= ale->data; - - BLI_freelistN(&act_data); - - return data; - } - --clickmin; - --clickmax; - } - - /* cleanup */ - BLI_freelistN(&act_data); - - *ret_type= ACTTYPE_NONE; - return NULL; -} - -/* 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) -{ - ListBase act_data = {NULL, NULL}; - ListBase act_keys = {NULL, NULL}; - bActListElem *ale; - ActKeyColumn *ak; - void *data; - short datatype; - int filter; - - rctf rectf; - float xmin, xmax, x, y; - int clickmin, clickmax; - short mval[2]; - short found = 0; - - getmouseco_areawin (mval); - - /* action-channel */ - *par= NULL; - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) { - *ret_type= ACTTYPE_NONE; - return NULL; - } - - areamouseco_to_ipoco(G.v2d, mval, &x, &y); - clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP)); - clickmax = clickmin; - - 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); - - /* if action is mapped in NLA, it returns a correction */ - if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { - xmin= get_action_frame(OBACT, rectf.xmin); - xmax= get_action_frame(OBACT, rectf.xmax); - } - else { - xmin= rectf.xmin; - xmax= rectf.xmax; - } - - if (clickmax < 0) { - *ret_type= ACTTYPE_NONE; - return NULL; - } - - /* filter data */ - filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS); - actdata_filter(&act_data, filter, data, datatype); - - for (ale= act_data.first; ale; ale= ale->next) { - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match */ - - /* make list of keyframes */ - if (ale->key_data) { - switch (ale->datatype) { - case ALE_IPO: - { - Ipo *ipo= (Ipo *)ale->key_data; - ipo_to_keylist(ipo, &act_keys, NULL); - } - break; - case ALE_ICU: - { - IpoCurve *icu= (IpoCurve *)ale->key_data; - icu_to_keylist(icu, &act_keys, NULL); - } - break; - } - } - - /* loop through keyframes, finding one that was clicked on */ - for (ak= act_keys.first; ak; ak= ak->next) { - if (IN_RANGE(ak->cfra, xmin, xmax)) { - *selx= ak->cfra; - found= 1; - break; - } - } - /* no matching keyframe found - set to mean frame value so it doesn't actually select anything */ - if (found == 0) - *selx= ((xmax+xmin) / 2); - - /* figure out what to return */ - if (datatype == ACTCONT_ACTION) { - *par= ale->owner; /* assume that this is an action channel */ - *ret_type= ale->type; - data = ale->data; - } - else if (datatype == ACTCONT_SHAPEKEY) { - data = ale->key_data; - *ret_type= ACTTYPE_ICU; - } - - /* cleanup tempolary lists */ - BLI_freelistN(&act_keys); - act_keys.first = act_keys.last = NULL; - - BLI_freelistN(&act_data); - - return data; - } - --clickmin; - --clickmax; - } - - /* cleanup */ - BLI_freelistN(&act_data); - - *ret_type= ACTTYPE_NONE; - return NULL; -} - -void *get_action_context (short *datatype) -{ - bAction *act; - Key *key; - - /* get pointers to active action/shapekey blocks */ - act = (G.saction)? G.saction->action: NULL; - key = get_action_mesh_key(); - - if (act) { - *datatype= ACTCONT_ACTION; - return act; - } - else if (key) { - *datatype= ACTCONT_SHAPEKEY; - return key; - } - else { - *datatype= ACTCONT_NONE; - return NULL; - } -} - -/* **************************************************** */ -/* TRANSFORM TOOLS */ - -/* main call to start transforming keyframes */ -void transform_action_keys (int mode, int dummy) -{ - void *data; - short datatype; - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) return; - - switch (mode) { - case 'g': - { - initTransform(TFM_TIME_TRANSLATE, CTX_NONE); - Transform(); - } - break; - case 's': - { - initTransform(TFM_TIME_SCALE, CTX_NONE); - Transform(); - } - break; - case 't': - { - initTransform(TFM_TIME_SLIDE, CTX_NONE); - Transform(); - } - break; - case 'e': - { - initTransform(TFM_TIME_EXTEND, CTX_NONE); - Transform(); - } - break; - } -} - -/* ----------------------------------------- */ - -/* duplicate keyframes */ -void duplicate_action_keys (void) -{ - 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 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); -} - -/* this function is responsible for snapping the current frame to selected data */ -void snap_cfra_action() -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - - /* get data */ - data= get_action_context(&datatype); - if (data == NULL) return; - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - /* snap current frame to selected data */ - snap_cfra_ipo_keys(NULL, -1); - - for (ale= act_data.first; ale; ale= ale->next) { - if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { - actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); - snap_cfra_ipo_keys(ale->key_data, 0); - actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); - } - else - snap_cfra_ipo_keys(ale->key_data, 0); - } - BLI_freelistN(&act_data); - - snap_cfra_ipo_keys(NULL, 1); - - BIF_undo_push("Snap Current Frame to Keys"); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -/* this function is responsible for snapping keyframes to frame-times */ -void snap_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; - - /* determine mode */ - switch (mode) { - case 1: - strcpy(str, "Snap Keys To Nearest Frame"); - break; - case 2: - if (G.saction->flag & SACTION_DRAWTIME) - strcpy(str, "Snap Keys To Current Time"); - else - strcpy(str, "Snap Keys To Current Frame"); - break; - case 3: - strcpy(str, "Snap Keys To Nearest Marker"); - break; - case 4: - strcpy(str, "Snap Keys To Nearest Second"); - break; - default: - return; - } - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - /* snap to frame */ - for (ale= act_data.first; ale; ale= ale->next) { - if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { - actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); - snap_ipo_keys(ale->key_data, mode); - actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); - } - else - snap_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); -} - -/* 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; - - /* 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; - } - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - /* mirror */ - for (ale= act_data.first; ale; ale= ale->next) { - if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { - actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1); - mirror_ipo_keys(ale->key_data, mode); - actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); - } - else - 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); -} - -/* **************************************************** */ -/* ADD/REMOVE KEYFRAMES */ - -/* 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; - - if (ob) - insertkey((ID *)ob, icu->blocktype, achan->name, NULL, icu->adrcode, 0); - else - insert_vert_icu(icu, cfra, icu->curval, 0); - } - } - - /* cleanup */ - BLI_freelistN(&act_data); - } - else if (datatype == ACTCONT_SHAPEKEY) { - Key *key= (Key *)data; - IpoCurve *icu; - - /* 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_icu(icu, cfra, icu->curval, 0); - } - } - } - - BIF_undo_push("Insert Key"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -/* delete selected keyframes */ -void delete_action_keys (void) -{ - 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); -} - -/* 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); -} - -/* '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); -} - -/* **************************************************** */ -/* COPY/PASTE FOR ACTIONS */ -/* - The copy/paste buffer currently stores a set of Action Channels, with temporary - * IPO-blocks, and also temporary IpoCurves which only contain the selected keyframes. - * - Only pastes between compatable data is possible (i.e. same achan->name, ipo-curve type, etc.) - */ - -/* globals for copy/paste data (like for other copy/paste buffers) */ -ListBase actcopybuf = {NULL, NULL}; - -/* This function frees any MEM_calloc'ed copy/paste buffer data */ -void free_actcopybuf () -{ - bActionChannel *achan, *anext; - bConstraintChannel *conchan, *cnext; - - for (achan= actcopybuf.first; achan; achan= anext) { - anext= achan->next; - - if (achan->ipo) { - free_ipo(achan->ipo); - MEM_freeN(achan->ipo); - } - - for (conchan=achan->constraintChannels.first; conchan; conchan=cnext) { - cnext= conchan->next; - - if (conchan->ipo) { - free_ipo(conchan->ipo); - MEM_freeN(conchan->ipo); - } - - BLI_freelinkN(&achan->constraintChannels, conchan); - } - - BLI_freelinkN(&actcopybuf, achan); - } -} - -/* This function adds data to the copy/paste buffer, freeing existing data first - * Only the selected action channels gets their selected keyframes copied. - */ -void copy_actdata () -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - - /* clear buffer first */ - free_actcopybuf(); - - /* get data */ - data= get_action_context(&datatype); - if (data == NULL) return; - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - /* assume that each of these is an ipo-block */ - for (ale= act_data.first; ale; ale= ale->next) { - bActionChannel *achan; - Ipo *ipo= ale->key_data; - Ipo *ipn; - IpoCurve *icu, *icn; - BezTriple *bezt; - int i; - - /* coerce an action-channel out of owner */ - if (ale->ownertype == ACTTYPE_ACHAN) { - bActionChannel *achanO= ale->owner; - achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan"); - strcpy(achan->name, achanO->name); - } - else if (ale->ownertype == ACTTYPE_SHAPEKEY) { - achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan"); - strcpy(achan->name, "#ACP_ShapeKey"); - } - else - continue; - BLI_addtail(&actcopybuf, achan); - - /* add constraint channel if needed, then add new ipo-block */ - if (ale->type == ACTTYPE_CONCHAN) { - bConstraintChannel *conchanO= ale->data; - bConstraintChannel *conchan; - - conchan= MEM_callocN(sizeof(bConstraintChannel), "ActCopyPasteConchan"); - strcpy(conchan->name, conchanO->name); - BLI_addtail(&achan->constraintChannels, conchan); - - conchan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo"); - } - else { - achan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo"); - } - ipn->blocktype = ipo->blocktype; - - /* now loop through curves, and only copy selected keyframes */ - for (icu= ipo->curve.first; icu; icu= icu->next) { - /* allocate a new curve */ - icn= MEM_callocN(sizeof(IpoCurve), "ActCopyPasteIcu"); - icn->blocktype = icu->blocktype; - icn->adrcode = icu->adrcode; - BLI_addtail(&ipn->curve, icn); - - /* find selected BezTriples to add to the buffer */ - for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { - if (BEZSELECTED(bezt)) - insert_bezt_icu(icn, bezt); - } - } - } - - /* check if anything ended up in the buffer */ - if (actcopybuf.first==NULL || actcopybuf.last==NULL) - error("Nothing copied to buffer"); - - /* free temp memory */ - BLI_freelistN(&act_data); -} - -void paste_actdata () -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - - /* check if buffer is empty */ - if (actcopybuf.first==NULL || actcopybuf.last==NULL) { - error("No data in buffer to paste"); - return; - } - - /* get data */ - data= get_action_context(&datatype); - if (data == NULL) return; - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - /* from selected channels */ - for (ale= act_data.first; ale; ale= ale->next) { - Ipo *ipo_src=NULL, *ipo_dst=ale->key_data; - bActionChannel *achan; - IpoCurve *ico, *icu; - BezTriple *bezt; - int i; - float offset= 0.0f; - short offsetInit= 1; - - /* find matching ipo-block */ - for (achan= actcopybuf.first; achan; achan= achan->next) { - /* try to match data */ - if (ale->ownertype == ACTTYPE_ACHAN) { - bActionChannel *achant= ale->owner; - - /* check if we have a corresponding action channel */ - if (strcmp(achan->name, achant->name)==0) { - /* check if this is a constraint channel */ - if (ale->type == ACTTYPE_CONCHAN) { - bConstraintChannel *conchant= ale->data; - bConstraintChannel *conchan; - - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) { - if (strcmp(conchan->name, conchant->name)==0) { - ipo_src= conchan->ipo; - break; - } - } - if (ipo_src) break; - } - else { - ipo_src= achan->ipo; - break; - } - } - } - else if (ale->ownertype == ACTTYPE_SHAPEKEY) { - /* check if this action channel is "#ACP_ShapeKey" */ - if (strcmp(achan->name, "#ACP_ShapeKey")==0) { - ipo_src= achan->ipo; - break; - } - } - } - - /* loop over curves, pasting keyframes */ - for (icu= ipo_dst->curve.first; icu; icu= icu->next) { - for (ico= ipo_src->curve.first; ico; ico= ico->next) { - /* only paste if compatable blocktype + adrcode */ - if ((ico->blocktype==icu->blocktype) && (ico->adrcode==icu->adrcode)) { - /* just start pasting, with the the first keyframe on the current frame, and so on */ - for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) { - /* initialise offset (if not already done) */ - if (offsetInit) { - offset= CFRA - bezt->vec[1][0]; - offsetInit= 0; - } - - /* temporarily apply offset to src beztriple while copying */ - bezt->vec[0][0] += offset; - bezt->vec[1][0] += offset; - bezt->vec[2][0] += offset; - - /* insert the keyframe */ - insert_bezt_icu(icu, bezt); - - /* un-apply offset from src beztriple after copying */ - bezt->vec[0][0] -= offset; - bezt->vec[1][0] -= offset; - bezt->vec[2][0] -= offset; - } - - /* recalculate channel's handles? */ - calchandles_ipocurve(icu); - - /* done for this channel */ - break; - } - } - } - } - - /* free temp memory */ - BLI_freelistN(&act_data); - - /* undo and redraw stuff */ - allqueue(REDRAWVIEW3D, 0); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); - BIF_undo_push("Paste Action Keyframes"); -} - -/* **************************************************** */ -/* VARIOUS SETTINGS */ - -/* This function combines several features related to setting - * various ipo extrapolation/interpolation - */ -void action_set_ipo_flags (short mode, short event) -{ - 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; - - /* 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; - - case SET_IPO_MENU: /* called from menus */ - case SET_EXTEND_MENU: - break; - - default: /* weird, unhandled case */ - return; - } - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | 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 */ - case SET_EXTEND_MENU: - { - 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 */ - case SET_IPO_MENU: - { - 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); -} - -/* this function sets the handles on keyframes */ -void sethandles_action_keys (int code) -{ - 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); - } - - /* 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); -} - -/* ----------------------------------------- */ - -/* this gets called when nkey is pressed (no Transform Properties panel yet) */ -static void numbuts_action () -{ - void *data; - short datatype; - - void *act_channel; - short chantype; - - bActionChannel *achan= NULL; - bConstraintChannel *conchan= NULL; - IpoCurve *icu= NULL; - KeyBlock *kb= NULL; - - short mval[2]; - - int but=0; - char str[64]; - short expand, protect, mute; - float slidermin, slidermax; - - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) return; - - /* figure out what is under cursor */ - getmouseco_areawin(mval); - if (mval[0] < NAMEWIDTH) - return; - act_channel= get_nearest_act_channel(mval, &chantype); - - /* create items for clever-numbut */ - if (chantype == ACTTYPE_ACHAN) { - /* Action Channel */ - achan= (bActionChannel *)act_channel; - - strcpy(str, achan->name); - protect= (achan->flag & ACHAN_PROTECTED); - expand = (achan->flag & ACHAN_EXPANDED); - mute = (achan->ipo)? (achan->ipo->muteipo): 0; - - 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, "Muted", 0, 24, &mute, "Channel is Muted"); - add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); - } - else if (chantype == ACTTYPE_CONCHAN) { - /* Constraint Channel */ - conchan= (bConstraintChannel *)act_channel; - - strcpy(str, conchan->name); - protect= (conchan->flag & CONSTRAINT_CHANNEL_PROTECTED); - mute = (conchan->ipo)? (conchan->ipo->muteipo): 0; - - add_numbut(but++, TEX, "ConChan: ", 0, 29, str, "Name of Constraint Channel"); - add_numbut(but++, TOG|SHO, "Muted", 0, 24, &mute, "Channel is Muted"); - add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); - } - else if (chantype == ACTTYPE_ICU) { - /* IPO Curve */ - icu= (IpoCurve *)act_channel; - - if (G.saction->pin) - sprintf(str, getname_ipocurve(icu, NULL)); - else - sprintf(str, getname_ipocurve(icu, OBACT)); - - 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); - mute = (icu->flag & IPO_MUTE); - - 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, "Muted", 0, 24, &mute, "Channel is Muted"); - //add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected"); - } - else if (chantype == ACTTYPE_SHAPEKEY) { - /* Shape Key */ - kb= (KeyBlock *)act_channel; - - if (kb->name[0] == '\0') { - Key *key= (Key *)data; - int keynum= BLI_findindex(&key->block, kb); - - 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); - } - 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; - if (mute) icu->flag |= IPO_MUTE; - else icu->flag &= ~IPO_MUTE; - } - else if (conchan) { - strcpy(conchan->name, str); - - if (protect) conchan->flag |= CONSTRAINT_CHANNEL_PROTECTED; - else conchan->flag &= ~CONSTRAINT_CHANNEL_PROTECTED; - - if (conchan->ipo) - conchan->ipo->muteipo = mute; - } - 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; - - if (achan->ipo) - achan->ipo->muteipo = mute; - } - - allqueue(REDRAWACTION, 0); - allspace(REMAKEIPO, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - } -} - - - -/* **************************************************** */ -/* CHANNEL SELECTION */ - -static void hilight_channel(bAction *act, bActionChannel *achan, short select) -{ - bActionChannel *curchan; - - if (!act) - return; - - for (curchan=act->chanbase.first; curchan; curchan=curchan->next) { - if (curchan==achan && select) - curchan->flag |= ACHAN_HILIGHTED; - else - curchan->flag &= ~ACHAN_HILIGHTED; - } -} - -/* 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 - * = SELECT_INVERT - */ - -/* exported for outliner (ton) */ -/* apparently within active object context */ -int select_channel(bAction *act, bActionChannel *achan, int selectmode) -{ - /* Select the channel based on the selection mode */ - int flag; - - switch (selectmode) { - case SELECT_ADD: - achan->flag |= ACHAN_SELECTED; - break; - case SELECT_SUBTRACT: - achan->flag &= ~ACHAN_SELECTED; - break; - case SELECT_INVERT: - achan->flag ^= ACHAN_SELECTED; - break; - } - flag = (achan->flag & ACHAN_SELECTED) ? 1 : 0; - - hilight_channel(act, achan, flag); - select_poseelement_by_name(achan->name, flag); - - return flag; -} - -static int select_constraint_channel(bAction *act, - bConstraintChannel *conchan, - int selectmode) -{ - /* Select the constraint channel based on the selection mode */ - int flag; - - switch (selectmode) { - case SELECT_ADD: - conchan->flag |= CONSTRAINT_CHANNEL_SELECT; - break; - case SELECT_SUBTRACT: - conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT; - break; - case SELECT_INVERT: - conchan->flag ^= CONSTRAINT_CHANNEL_SELECT; - break; - } - flag = (conchan->flag & CONSTRAINT_CHANNEL_SELECT) ? 1 : 0; - - return flag; -} - -int select_icu_channel(bAction *act, IpoCurve *icu, int selectmode) -{ - /* Select the channel based on the selection mode */ - int flag; - - switch (selectmode) { - case SELECT_ADD: - icu->flag |= IPO_SELECT; - break; - case SELECT_SUBTRACT: - icu->flag &= ~IPO_SELECT; - break; - case SELECT_INVERT: - icu->flag ^= IPO_SELECT; - break; - } - flag = (icu->flag & IPO_SELECT) ? 1 : 0; - return flag; -} - -/* ----------------------------------------- */ - -/* deselects action channels in given action */ -void deselect_actionchannels (bAction *act, short test) -{ - 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); -} - -/* 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); -} - -/* 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; - - /* 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; - } - - /* 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); -} - -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(NLA_ACTION_SCALED && 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 { - borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD); - } - } - - /* Cleanup */ - BLI_freelistN(&act_data); -} - -void selectkeys_leftright (short leftright, short select_mode) -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - float min, max; - - if (select_mode==SELECT_REPLACE) { - select_mode=SELECT_ADD; - deselect_action_keys(0, 0); - } - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) return; - - if (leftright==1) { - min = -MAXFRAMEF; - max = (float)CFRA+0.1f; - } - else { - min = (float)CFRA-0.1f; - max = MAXFRAMEF; - } - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - /* select keys to the right */ - for (ale= act_data.first; ale; ale= ale->next) { - if(NLA_ACTION_SCALED && 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 { - borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD); - } - } - - /* Cleanup */ - BLI_freelistN(&act_data); - - allqueue(REDRAWNLA, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - -} - - -/* ----------------------------------------- */ - -/* 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); - } - } -} - -/* 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); - - 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); - - /* apply scaled action correction if needed */ - if (NLA_ACTION_SCALED && 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); -} - -/* some quick defines for borderselect modes */ -#define ACTEDIT_BORDERSEL_ALL 0 -#define ACTEDIT_BORDERSEL_FRA 1 -#define ACTEDIT_BORDERSEL_CHA 2 - -/* 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, mode; - 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; - - /* what should be selected (based on the starting location of cursor) */ - getmouseco_areawin(mval); - if (IN_2D_VERT_SCROLL(mval)) - mode = ACTEDIT_BORDERSEL_CHA; - else if (IN_2D_HORIZ_SCROLL(mval)) - mode = ACTEDIT_BORDERSEL_FRA; - else - mode = ACTEDIT_BORDERSEL_ALL; - - /* 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 action is mapped in NLA, it returns a correction */ - if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) { - rectf.xmin= get_action_frame(OBACT, rectf.xmin); - rectf.xmax= get_action_frame(OBACT, rectf.xmax); - } - - 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); - - /* what gets selected depends on the mode (based on initial position of cursor) */ - switch (mode) { - case ACTEDIT_BORDERSEL_FRA: /* all in frame(s) */ - 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); - } - break; - case ACTEDIT_BORDERSEL_CHA: /* all in channel(s) */ - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { - if (ale->key_data) { - if (ale->datatype == ALE_IPO) - select_ipo_bezier_keys(ale->key_data, selectmode); - else if (ale->datatype == ALE_ICU) - select_icu_bezier_keys(ale->key_data, selectmode); - } - } - break; - default: /* any keyframe inside region defined by region */ - 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); - } - } - } - - ymax=ymin; - } - - /* 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= NULL; - bActionChannel *achan= NULL; - 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; - if (datatype == ACTCONT_ACTION) act= (bAction *)data; - - 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; - case ACTTYPE_ACHAN: - achan= (bActionChannel *)act_channel; - break; - default: - return; - } - - if (selectmode == SELECT_REPLACE) { - selectmode = SELECT_ADD; - - deselect_action_keys(0, 0); - - if (datatype == ACTCONT_ACTION) { - deselect_action_channels(0); - - 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(REDRAWMARKER, 0); - } -} - -/* lefthand side - mouse-click */ -static void mouse_actionchannels (short mval[]) -{ - bAction *act= G.saction->action; - 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, &chantype); - - /* action to take depends on what channel we've got */ - switch (chantype) { - case ACTTYPE_ACHAN: - { - bActionChannel *achan= (bActionChannel *)act_channel; - - if (mval[0] >= (NAMEWIDTH-16)) { - /* toggle protect */ - achan->flag ^= ACHAN_PROTECTED; - } - else if ((mval[0] >= (NAMEWIDTH-32)) && (achan->ipo)) { - /* toggle mute */ - achan->ipo->muteipo = (achan->ipo->muteipo)? 0: 1; - } - else if (mval[0] <= 17) { - /* toggle expand */ - achan->flag ^= ACHAN_EXPANDED; - } - else { - /* select/deselect achan */ - if (G.qual & LR_SHIFTKEY) { - select_channel(act, achan, SELECT_INVERT); - } - else { - deselect_actionchannels(act, 0); - select_channel(act, achan, SELECT_ADD); - } - - /* messy... set active bone */ - select_poseelement_by_name(achan->name, 2); - } - } - break; - case ACTTYPE_FILLIPO: - { - bActionChannel *achan= (bActionChannel *)act_channel; - - achan->flag ^= ACHAN_SHOWIPO; - - if ((mval[0] > 24) && (achan->flag & ACHAN_SHOWIPO)) { - /* select+make active achan */ - deselect_actionchannels(act, 0); - select_channel(act, achan, SELECT_ADD); - - /* messy... set active bone */ - select_poseelement_by_name(achan->name, 2); - } - } - break; - case ACTTYPE_FILLCON: - { - bActionChannel *achan= (bActionChannel *)act_channel; - - achan->flag ^= ACHAN_SHOWCONS; - - if ((mval[0] > 24) && (achan->flag & ACHAN_SHOWCONS)) { - /* select+make active achan */ - deselect_actionchannels(act, 0); - select_channel(act, achan, SELECT_ADD); - - /* messy... set active bone */ - select_poseelement_by_name(achan->name, 2); - } - } - break; - case ACTTYPE_ICU: - { - IpoCurve *icu= (IpoCurve *)act_channel; - -#if 0 /* disabled until all ipo tools support this -------> */ - if (mval[0] >= (NAMEWIDTH-16)) { - /* toggle protection */ - icu->flag ^= IPO_PROTECT; - } -#endif /* <------- end of disabled code */ - if (mval[0] >= (NAMEWIDTH-16)) { - /* toggle mute */ - icu->flag ^= IPO_MUTE; - } - else { - /* select/deselect */ - select_icu_channel(act, icu, SELECT_INVERT); - } - } - break; - case ACTTYPE_CONCHAN: - { - bConstraintChannel *conchan= (bConstraintChannel *)act_channel; - - if (mval[0] >= (NAMEWIDTH-16)) { - /* toggle protection */ - conchan->flag ^= CONSTRAINT_CHANNEL_PROTECTED; - } - else if ((mval[0] >= (NAMEWIDTH-32)) && (conchan->ipo)) { - /* toggle mute */ - conchan->ipo->muteipo = (conchan->ipo->muteipo)? 0: 1; - } - else { - /* select/deselect */ - select_constraint_channel(act, conchan, SELECT_INVERT); - } - } - break; - default: - return; - } - - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWOOPS, 0); - allqueue(REDRAWBUTSALL, 0); -} - -/* **************************************************** */ -/* ACTION CHANNEL RE-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); -} - -/* **************************************************** */ -/* EVENT HANDLING */ - -void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt) -{ - extern void do_actionbuts(unsigned short event); // drawaction.c - SpaceAction *saction; - void *data; - short datatype; - float dx, dy; - int doredraw= 0; - int cfra; - short mval[2]; - unsigned short event= evt->event; - short val= evt->val; - short mousebut = L_MOUSE; - - if (curarea->win==0) return; - - saction= curarea->spacedata.first; - if (!saction) - return; - - data= get_action_context(&datatype); - - if (val) { - if ( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0; - - /* swap mouse buttons based on user preference */ - if (U.flag & USER_LMOUSESELECT) { - if (event == LEFTMOUSE) { - event = RIGHTMOUSE; - mousebut = L_MOUSE; - } else if (event == RIGHTMOUSE) { - event = LEFTMOUSE; - mousebut = R_MOUSE; - } - } - - getmouseco_areawin(mval); - - switch(event) { - case UI_BUT_EVENT: - do_actionbuts(val); // window itself - break; - - case HOMEKEY: - do_action_buttons(B_ACTHOME); // header - break; - - case AKEY: - if (mval[0]<NAMEWIDTH) { - deselect_action_channels (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_action_keys (1, 1); - allqueue (REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue (REDRAWIPO, 0); - } - } - break; - - case BKEY: - if (G.qual & LR_CTRLKEY) { - borderselect_markers(); - } - else { - if (mval[0]>ACTWIDTH) - borderselect_action(); - } - break; - - case CKEY: - /* scroll the window so the current - * frame is in the center. - */ - center_currframe(); - break; - - case DKEY: - if (mval[0]>ACTWIDTH) { - if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - duplicate_marker(); - else if (G.qual == LR_SHIFTKEY) - duplicate_action_keys(); - } - break; - - case EKEY: - if (mval[0] >= ACTWIDTH) - transform_action_keys('e', 0); - break; - - case GKEY: - if (G.qual & LR_CTRLKEY) { - transform_markers('g', 0); - } - else { - if (mval[0]>=ACTWIDTH) - transform_action_keys('g', 0); - } - break; - - case HKEY: - if (G.qual & LR_SHIFTKEY) { - if (okee("Set Keys to Auto Handle")) - sethandles_action_keys(HD_AUTO); - } - else { - if (okee("Toggle Keys Aligned Handle")) - sethandles_action_keys(HD_ALIGN); - } - break; - - case KKEY: - if (G.qual & LR_CTRLKEY) { - markers_selectkeys_between(); - } - else { - val= (G.qual & LR_SHIFTKEY) ? 2 : 1; - column_select_action_keys(val); - } - - allqueue(REDRAWMARKER, 0); - break; - - case MKEY: - if (G.qual & LR_SHIFTKEY) { - /* mirror keyframes */ - if (data) { - if (G.saction->flag & SACTION_DRAWTIME) - val = pupmenu("Mirror Keys Over%t|Current Time%x1|Vertical Axis%x2|Horizontal Axis %x3|Selected Marker %x4"); - else - val = pupmenu("Mirror Keys Over%t|Current Frame%x1|Vertical Axis%x2|Horizontal Axis %x3|Selected Marker %x4"); - - mirror_action_keys(val); - } - } - else { - /* marker operations */ - if (G.qual == 0) - add_marker(CFRA); - else if (G.qual == LR_CTRLKEY) - rename_marker(); - else - break; - allqueue(REDRAWMARKER, 0); - } - break; - - case NKEY: - if(G.qual==0) { - numbuts_action(); - - /* no panel (yet). current numbuts are not easy to put in panel... */ - //add_blockhandler(curarea, ACTION_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE); - //scrarea_queue_winredraw(curarea); - } - break; - - case OKEY: - clean_action(); - break; - - case PKEY: - if (G.qual & LR_CTRLKEY) /* set preview range */ - anim_previewrange_set(); - else if (G.qual & LR_ALTKEY) /* clear preview range */ - anim_previewrange_clear(); - - allqueue(REDRAWMARKER, 0); - allqueue(REDRAWBUTSALL, 0); - break; - - case SKEY: - if (mval[0]>=ACTWIDTH) { - if (G.qual == (LR_SHIFTKEY|LR_CTRLKEY)) { - if (data) { - snap_cfra_action(); - } - } - else if (G.qual & LR_SHIFTKEY) { - if (data) { - if (G.saction->flag & SACTION_DRAWTIME) - val = pupmenu("Snap Keys To%t|Nearest Second%x4|Current Time%x2|Nearest Marker %x3"); - else - val = pupmenu("Snap Keys To%t|Nearest Frame%x1|Current Frame%x2|Nearest Marker %x3"); - - snap_action_keys(val); - } - } - else { - transform_action_keys('s', 0); - } - } - break; - - case TKEY: - if (G.qual & LR_SHIFTKEY) - action_set_ipo_flags(SET_IPO_POPUP, 0); - else if (G.qual & LR_CTRLKEY) { - val= pupmenu("Time value%t|Frames %x1|Seconds%x2"); - - if (val > 0) { - if (val == 2) saction->flag |= SACTION_DRAWTIME; - else saction->flag &= ~SACTION_DRAWTIME; - - doredraw= 1; - } - } - else - transform_action_keys ('t', 0); - break; - - case VKEY: - if (okee("Set Keys to Vector Handle")) - sethandles_action_keys(HD_VECT); - break; - - case PAGEUPKEY: - if (datatype == ACTCONT_ACTION) { - if(G.qual & LR_SHIFTKEY) - top_sel_action(); - else if (G.qual & LR_CTRLKEY) - up_sel_action(); - else - nextprev_marker(1); - } - else if (datatype == ACTCONT_SHAPEKEY) { - /* only jump to markers possible (key channels can't be moved yet) */ - nextprev_marker(1); - } - break; - case PAGEDOWNKEY: - if (datatype == ACTCONT_ACTION) { - if(G.qual & LR_SHIFTKEY) - bottom_sel_action(); - else if (G.qual & LR_CTRLKEY) - down_sel_action(); - else - nextprev_marker(-1); - } - else if (datatype == ACTCONT_SHAPEKEY) { - /* only jump to markers possible (key channels can't be moved yet) */ - nextprev_marker(-1); - } - break; - - case DELKEY: - case XKEY: - if (okee("Erase selected")) { - if (mval[0]<NAMEWIDTH) - delete_action_channels(); - else - delete_action_keys(); - - if (mval[0] >= NAMEWIDTH) - remove_marker(); - - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); - } - break; - - /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above, - * based on user preference USER_LMOUSESELECT - */ - case LEFTMOUSE: - if (view2dmove(LEFTMOUSE)) /* only checks for sliders */ - break; - else if ((G.v2d->mask.xmin==0) || (mval[0]>ACTWIDTH)) { - /* moving time-marker / current frame */ - do { - getmouseco_areawin(mval); - areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); - - cfra= (int)dx; - if (cfra < 1) cfra= 1; - - if (cfra != CFRA) { - CFRA= cfra; - update_for_newframe(); - force_draw_all(0); - } - else PIL_sleep_ms(30); - - } while(get_mbut() & mousebut); - break; - } - /* passed on as selection */ - case RIGHTMOUSE: - /* Clicking in the channel area */ - if ((G.v2d->mask.xmin) && (mval[0]<NAMEWIDTH)) { - if (datatype == ACTCONT_ACTION) { - /* mouse is over action channels */ - if (G.qual & LR_CTRLKEY) - numbuts_action(); - else - mouse_actionchannels(mval); - } - else numbuts_action(); - } - else { - 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)) - 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)) - selectall_action_keys(mval, 1, select_mode); - - /* Clicking in the main area of the action window - * selects keys and markers - */ - else if (G.qual & LR_ALTKEY) { - areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); - - /* sends a 1 for left and 0 for right */ - selectkeys_leftright((dx < (float)CFRA), select_mode); - } - else - mouse_action(select_mode); - } - break; - case PADPLUSKEY: - view2d_zoom(G.v2d, 0.1154, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); - - doredraw= 1; - break; - case PADMINUS: - view2d_zoom(G.v2d, -0.15, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); - - doredraw= 1; - break; - case MIDDLEMOUSE: - case WHEELUPMOUSE: - case WHEELDOWNMOUSE: - view2dmove(event); /* in drawipo.c */ - break; - } - } - - if(doredraw) addqueue(curarea->win, REDRAW, 1); - -} - -/* **************************************************** */ |