diff options
Diffstat (limited to 'source/blender/src/editaction.c')
-rw-r--r-- | source/blender/src/editaction.c | 5244 |
1 files changed, 0 insertions, 5244 deletions
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c deleted file mode 100644 index e230c97f010..00000000000 --- a/source/blender/src/editaction.c +++ /dev/null @@ -1,5244 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): 2007, Joshua Leung (major rewrite of Action Editor) - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include <string.h> -#include <stddef.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 "DNA_gpencil_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_keyframing.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 "BDR_gpencil.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; - - if ((owner) && (ownertype == ACTTYPE_ACHAN)) { - bActionChannel *ochan= (bActionChannel *)owner; - ale->grp= ochan->grp; - } - else - ale->grp= NULL; - - /* do specifics */ - switch (datatype) { - case ACTTYPE_GROUP: - { - bActionGroup *agrp= (bActionGroup *)data; - - ale->flag= agrp->flag; - - ale->key_data= NULL; - ale->datatype= ALE_GROUP; - } - break; - 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: - case ACTTYPE_CONCHAN2: - { - bConstraintChannel *conchan= (bConstraintChannel *)data; - - ale->flag= conchan->flag; - - if (datatype == ACTTYPE_CONCHAN2) { - /* CONCHAN2 is a hack so that constraint-channels keyframes can be edited */ - if (conchan->ipo) { - ale->key_data= conchan->ipo; - ale->datatype= ALE_IPO; - } - else { - ale->key_data= NULL; - ale->datatype= ALE_NONE; - } - } - else { - 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; - case ACTTYPE_GPLAYER: - { - bGPDlayer *gpl= (bGPDlayer *)data; - - ale->flag= gpl->flag; - - ale->key_data= NULL; - ale->datatype= ALE_GPFRAME; - } - break; - } - } - - /* return created datatype */ - return ale; -} - -/* ----------------------------------------- */ - -static void actdata_filter_actionchannel (ListBase *act_data, bActionChannel *achan, int filter_mode) -{ - bActListElem *ale; - bConstraintChannel *conchan; - IpoCurve *icu; - - /* 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 { - /* for insert key... this check could be improved */ - return; - } - - /* check if expanded - if not, continue on to next action channel */ - if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ACTFILTER_ONLYICU)==0) { - /* only exit if we don't need to include constraint channels for group-channel keyframes */ - if ( !(filter_mode & ACTFILTER_IPOKEYS) || (achan->grp == NULL) || (EXPANDED_AGRP(achan->grp)==0) ) - return; - } - - /* ipo channels */ - if ((achan->ipo) && (filter_mode & ACTFILTER_IPOKEYS)==0) { - /* 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) - && !(filter_mode & ACTFILTER_IPOKEYS) ) - { - ale= make_new_actlistelem(achan, ACTTYPE_FILLCON, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); - } - - /* add constraint channels? */ - if (FILTER_CON_ACHAN(achan) || (filter_mode & ACTFILTER_IPOKEYS) || (filter_mode & ACTFILTER_ONLYICU)) { - /* 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_IPOKEYS) { - ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN2, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); - } - else { - ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN, achan, ACTTYPE_ACHAN); - if (ale) BLI_addtail(act_data, ale); - } - } - } - } - } - } - } - } -} - -static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode) -{ - bActListElem *ale=NULL; - bActionGroup *agrp; - bActionChannel *achan, *lastchan=NULL; - - /* loop over groups */ - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - /* add this group as a channel first */ - if (!(filter_mode & ACTFILTER_ONLYICU) && !(filter_mode & ACTFILTER_IPOKEYS)) { - /* check if filtering by selection */ - if ( !(filter_mode & ACTFILTER_SEL) || SEL_AGRP(agrp) ) { - ale= make_new_actlistelem(agrp, ACTTYPE_GROUP, NULL, ACTTYPE_NONE); - if (ale) BLI_addtail(act_data, ale); - } - } - - /* store reference to last channel of group */ - if (agrp->channels.last) - lastchan= agrp->channels.last; - - - /* there are some situations, where only the channels of the active group should get considered */ - if (!(filter_mode & ACTFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) { - /* filters here are a bit convoulted... - * - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes - * - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed) - * - * cases when we should include action-channels and so-forth inside group: - * - we don't care about visibility - * - group is expanded - * - we're interested in keyframes, but not if they appear in selected channels - */ - if ( (!(filter_mode & ACTFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) || - ( ((filter_mode & ACTFILTER_IPOKEYS) || (filter_mode & ACTFILTER_ONLYICU)) && - (!(filter_mode & ACTFILTER_SEL) || (SEL_AGRP(agrp))) ) ) - { - if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) { - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - actdata_filter_actionchannel(act_data, achan, filter_mode); - } - - /* remove group from filtered list if last element is group - * (i.e. only if group had channels, which were all hidden) - */ - if ( (ale) && (act_data->last == ale) && - (ale->data == agrp) && (agrp->channels.first) ) - { - BLI_freelinkN(act_data, ale); - } - } - } - } - } - - /* loop over un-grouped action channels (only if we're not only considering those channels in the active group) */ - if (!(filter_mode & ACTFILTER_ACTGROUPED)) { - for (achan=(lastchan)?lastchan->next:act->chanbase.first; achan; achan=achan->next) { - actdata_filter_actionchannel(act_data, achan, filter_mode); - } - } -} - -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); - } - } - } - } -} - - -static void actdata_filter_gpencil (ListBase *act_data, bScreen *sc, int filter_mode) -{ - bActListElem *ale; - ScrArea *sa; - bGPdata *gpd; - bGPDlayer *gpl; - - /* check if filtering types are appropriate */ - if ( !(filter_mode & (ACTFILTER_IPOKEYS|ACTFILTER_ONLYICU|ACTFILTER_ACTGROUPED)) ) - { - /* special hack for fullscreen area (which must be this one then): - * - we use the curarea->full as screen to get spaces from, since the - * old (pre-fullscreen) screen was stored there... - * - this is needed as all data would otherwise disappear - */ - if ((curarea->full) && (curarea->spacetype==SPACE_ACTION)) - sc= curarea->full; - - /* loop over spaces in current screen, finding gpd blocks (could be slow!) */ - for (sa= sc->areabase.first; sa; sa= sa->next) { - /* try to get gp data */ - gpd= gpencil_data_getactive(sa); - if (gpd == NULL) continue; - - /* add gpd as channel too (if for drawing, and it has layers) */ - if ((filter_mode & ACTFILTER_FORDRAWING) && (gpd->layers.first)) { - /* add to list */ - ale= make_new_actlistelem(gpd, ACTTYPE_GPDATABLOCK, sa, ACTTYPE_SPECIALDATA); - if (ale) BLI_addtail(act_data, ale); - } - - /* only add layers if they will be visible (if drawing channels) */ - if ( !(filter_mode & ACTFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) { - /* loop over layers as the conditions are acceptable */ - for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { - /* only if selected */ - if (!(filter_mode & ACTFILTER_SEL) || SEL_GPL(gpl)) { - /* only if editable */ - if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_GPL(gpl)) { - /* add to list */ - ale= make_new_actlistelem(gpl, ACTTYPE_GPLAYER, gpd, ACTTYPE_GPDATABLOCK); - 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; - case ACTCONT_GPENCIL: - actdata_filter_gpencil(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 if (ELEM(ob->type, OB_CURVE, OB_SURF)) - key= ((Curve *)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 finds the channel that mouse is floating over */ -void *get_nearest_act_channel (short mval[], short *ret_type, void **owner) -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - void *data; - short datatype; - int filter; - - int clickmin, clickmax; - float x,y; - - /* init 'owner' return val */ - *owner= NULL; - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) { - *ret_type= ACTTYPE_NONE; - return NULL; - } - - areamouseco_to_ipoco(G.v2d, mval, &x, &y); - clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP)); - clickmax = clickmin; - - if (clickmax < 0) { - *ret_type= ACTTYPE_NONE; - return NULL; - } - - /* filter data */ - filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS); - actdata_filter(&act_data, filter, data, datatype); - - for (ale= act_data.first; ale; ale= ale->next) { - if (clickmax < 0) - break; - if (clickmin <= 0) { - /* found match */ - *ret_type= ale->type; - data= ale->data; - *owner= ale->owner; - - 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, NULL); - } - break; - case ALE_ICU: - { - IpoCurve *icu= (IpoCurve *)ale->key_data; - icu_to_keylist(icu, &act_keys, NULL, NULL); - } - break; - } - } - else if (ale->type == ACTTYPE_GROUP) { - bActionGroup *agrp= (bActionGroup *)ale->data; - agroup_to_keylist(agrp, &act_keys, NULL, NULL); - } - else if (ale->type == ACTTYPE_GPDATABLOCK) { - /* cleanup */ - BLI_freelistN(&act_data); - - /* this channel currently doens't have any keyframes... must ignore! */ - *ret_type= ACTTYPE_NONE; - return NULL; - } - else if (ale->type == ACTTYPE_GPLAYER) { - bGPDlayer *gpl= (bGPDlayer *)ale->data; - gpl_to_keylist(gpl, &act_keys, NULL, NULL); - } - - /* 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; - } - else if (datatype == ACTCONT_GPENCIL) { - data = ale->data; - *ret_type= ACTTYPE_GPLAYER; - } - - /* 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(); - - /* check mode selector */ - if (G.saction) { - switch (G.saction->mode) { - case SACTCONT_ACTION: - *datatype= ACTCONT_ACTION; - return act; - - case SACTCONT_SHAPEKEY: - *datatype= ACTCONT_SHAPEKEY; - return key; - - case SACTCONT_GPENCIL: - *datatype= ACTCONT_GPENCIL; - return G.curscreen; // FIXME: add that dopesheet type thing here! - - default: /* includes SACTCONT_DOPESHEET for now */ - *datatype= ACTCONT_NONE; - return NULL; - } - } - else { - /* resort to guessing based on what is available */ - if (act) { - *datatype= ACTCONT_ACTION; - return act; - } - else if (key) { - *datatype= ACTCONT_SHAPEKEY; - return key; - } - else { - *datatype= ACTCONT_NONE; - return NULL; - } - } -} - -/* Quick-tool for preview-range functionality in Action Editor for setting Preview-Range - * bounds to extents of Action, when Ctrl-Alt-P is used. Only available for actions. - */ -void action_previewrange_set (bAction *act) -{ - float start, end; - - /* sanity check */ - if (act == NULL) - return; - - /* calculate range + make sure it is adjusted for nla-scaling */ - calc_action_range(act, &start, &end, 0); - if (NLA_ACTION_SCALED) { - start= get_action_frame_inv(OBACT, start); - end= get_action_frame_inv(OBACT, end); - } - - /* set preview range */ - G.scene->r.psfra= (int)start; - G.scene->r.pefra= (int)end; - - BIF_undo_push("Set anim-preview range"); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWBUTSALL, 0); -} - -/* **************************************************** */ -/* ACTION CHANNEL GROUPS */ - -/* Get the active action-group for an Action */ -bActionGroup *get_active_actiongroup (bAction *act) -{ - bActionGroup *agrp= NULL; - - if (act && act->groups.first) { - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - if (agrp->flag & AGRP_ACTIVE) - break; - } - } - - return agrp; -} - -/* Make the given Action-Group the active one */ -void set_active_actiongroup (bAction *act, bActionGroup *agrp, short select) -{ - bActionGroup *grp; - - /* sanity checks */ - if (act == NULL) - return; - - /* Deactive all others */ - for (grp= act->groups.first; grp; grp= grp->next) { - if ((grp==agrp) && (select)) - grp->flag |= AGRP_ACTIVE; - else - grp->flag &= ~AGRP_ACTIVE; - } -} - -/* Add given channel into (active) group - * - assumes that channel is not linked to anything anymore - * - always adds at the end of the group - */ -static void action_groups_addachan (bAction *act, bActionGroup *agrp, bActionChannel *achan) -{ - bActionChannel *chan; - short done=0; - - /* sanity checks */ - if (ELEM3(NULL, act, agrp, achan)) - return; - - /* if no channels, just add to two lists at the same time */ - if (act->chanbase.first == NULL) { - achan->next = achan->prev = NULL; - - agrp->channels.first = agrp->channels.last = achan; - act->chanbase.first = act->chanbase.last = achan; - - achan->grp= agrp; - return; - } - - /* try to find a channel to slot this in before/after */ - for (chan= act->chanbase.first; chan; chan= chan->next) { - /* if channel has no group, then we have ungrouped channels, which should always occur after groups */ - if (chan->grp == NULL) { - BLI_insertlinkbefore(&act->chanbase, chan, achan); - - if (agrp->channels.first == NULL) - agrp->channels.first= achan; - agrp->channels.last= achan; - - done= 1; - break; - } - - /* if channel has group after current, we can now insert (otherwise we have gone too far) */ - else if (chan->grp == agrp->next) { - BLI_insertlinkbefore(&act->chanbase, chan, achan); - - if (agrp->channels.first == NULL) - agrp->channels.first= achan; - agrp->channels.last= achan; - - done= 1; - break; - } - - /* if channel has group we're targeting, check whether it is the last one of these */ - else if (chan->grp == agrp) { - if ((chan->next) && (chan->next->grp != agrp)) { - BLI_insertlinkafter(&act->chanbase, chan, achan); - agrp->channels.last= achan; - done= 1; - break; - } - else if (chan->next == NULL) { - BLI_addtail(&act->chanbase, achan); - agrp->channels.last= achan; - done= 1; - break; - } - } - - /* if channel has group before target, check whether the next one is something after target */ - else if (chan->grp == agrp->prev) { - if (chan->next) { - if ((chan->next->grp != chan->grp) && (chan->next->grp != agrp)) { - BLI_insertlinkafter(&act->chanbase, chan, achan); - - agrp->channels.first= achan; - agrp->channels.last= achan; - - done= 1; - break; - } - } - else { - BLI_insertlinkafter(&act->chanbase, chan, achan); - - agrp->channels.first= achan; - agrp->channels.last= achan; - - done= 1; - break; - } - } - } - - /* only if added, set channel as belonging to this group */ - if (done) { - achan->grp= agrp; - } - else - printf("Error: ActionChannel: '%s' couldn't be added to Group: '%s' \n", achan->name, agrp->name); -} - -/* Remove the given channel from all groups */ -static void action_groups_removeachan (bAction *act, bActionChannel *achan) -{ - /* sanity checks */ - if (ELEM(NULL, act, achan)) - return; - - /* check if any group used this directly */ - if (achan->grp) { - bActionGroup *agrp= achan->grp; - - if (agrp->channels.first == agrp->channels.last) { - if (agrp->channels.first == achan) { - agrp->channels.first= NULL; - agrp->channels.last= NULL; - } - } - else if (agrp->channels.first == achan) { - if ((achan->next) && (achan->next->grp==agrp)) - agrp->channels.first= achan->next; - else - agrp->channels.first= NULL; - } - else if (agrp->channels.last == achan) { - if ((achan->prev) && (achan->prev->grp==agrp)) - agrp->channels.last= achan->prev; - else - agrp->channels.last= NULL; - } - - achan->grp= NULL; - } - - /* now just remove from list */ - BLI_remlink(&act->chanbase, achan); -} - -/* Add a new Action-Group or add channels to active one */ -void action_groups_group (short add_group) -{ - bAction *act; - bActionChannel *achan, *anext; - bActionGroup *agrp; - void *data; - short datatype; - - /* validate type of data we are working on */ - data = get_action_context(&datatype); - if (data == NULL) return; - if (datatype != ACTCONT_ACTION) return; - act= (bAction *)data; - - /* get active group */ - if ((act->groups.first==NULL) || (add_group)) { - /* Add a new group, and make it active */ - agrp= MEM_callocN(sizeof(bActionGroup), "bActionGroup"); - - agrp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED); - sprintf(agrp->name, "Group"); - - BLI_addtail(&act->groups, agrp); - BLI_uniquename(&act->groups, agrp, "Group", offsetof(bActionGroup, name), 32); - - set_active_actiongroup(act, agrp, 1); - - add_group= 1; - } - else { - agrp= get_active_actiongroup(act); - - if (agrp == NULL) { - error("No Active Action Group"); - return; - } - } - - /* loop through action-channels, finding those that are selected + visible to move */ - // FIXME: this should be done with action api instead - for (achan= act->chanbase.first; achan; achan= anext) { - anext= achan->next; - - /* make sure not already in new-group */ - if (achan->grp != agrp) { - if ((achan->grp==NULL) || (EXPANDED_AGRP(achan->grp))) { - if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { - /* unlink from everything else */ - action_groups_removeachan(act, achan); - - /* add to end of group's channels */ - action_groups_addachan(act, agrp, achan); - } - } - } - } - - /* updates and undo */ - if (add_group) - BIF_undo_push("Add Action Group"); - else - BIF_undo_push("Add to Action Group"); - - allqueue(REDRAWACTION, 0); -} - -/* Remove selected channels from their groups */ -void action_groups_ungroup (void) -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - bAction *act; - void *data; - short datatype; - short filter; - - /* validate type of data we are working on */ - data = get_action_context(&datatype); - if (data == NULL) return; - if (datatype != ACTCONT_ACTION) return; - act= (bAction *)data; - - /* filter data */ - filter= (ACTFILTER_VISIBLE|ACTFILTER_SEL); - actdata_filter(&act_data, filter, act, ACTCONT_ACTION); - - /* Only ungroup selected action-channels */ - for (ale= act_data.first; ale; ale= ale->next) { - if (ale->type == ACTTYPE_ACHAN) { - action_groups_removeachan(act, ale->data); - BLI_addtail(&act->chanbase, ale->data); - } - } - - BLI_freelistN(&act_data); - - /* updates and undo */ - BIF_undo_push("Remove From Action Groups"); - - allqueue(REDRAWACTION, 0); -} - -/* Copy colors from a specified theme's color set to an Action/Bone Group */ -void actionbone_group_copycolors (bActionGroup *grp, short init_new) -{ - /* error checking */ - if (grp == NULL) - return; - - /* only do color copying if using a custom color */ - if (grp->customCol) { - if (grp->customCol > 0) { - /* copy theme colors on-to group's custom color in case user tries to edit color */ - bTheme *btheme= U.themes.first; - ThemeWireColor *col_set= &btheme->tarm[(grp->customCol - 1)]; - - memcpy(&grp->cs, col_set, sizeof(ThemeWireColor)); - } - else if (init_new) { - /* init custom colors with a generic multi-color rgb set, if not initialised already (and allowed to do so) */ - if (grp->cs.solid[0] == 0) { - /* define for setting colors in theme below */ - #define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a; - - SETCOL(grp->cs.solid, 0xff, 0x00, 0x00, 255); - SETCOL(grp->cs.select, 0x81, 0xe6, 0x14, 255); - SETCOL(grp->cs.active, 0x18, 0xb6, 0xe0, 255); - - #undef SETCOL - } - } - } -} - -/* This function is used when inserting keyframes for pose-channels. It assigns the - * action-channel with the nominated name to a group with the same name as that of - * the pose-channel with the nominated name. - * - * Note: this function calls validate_action_channel if action channel doesn't exist - */ -void verify_pchan2achan_grouping (bAction *act, bPose *pose, char name[]) -{ - bActionChannel *achan; - bPoseChannel *pchan; - - /* sanity checks */ - if (ELEM3(NULL, act, pose, name)) - return; - if (name[0] == 0) - return; - - /* try to get the channels */ - pchan= get_pose_channel(pose, name); - if (pchan == NULL) return; - achan= verify_action_channel(act, name); - - /* check if pchan has a group */ - if ((pchan->agrp_index > 0) && (achan->grp == NULL)) { - bActionGroup *agrp, *grp=NULL; - - /* get group to try to be like */ - agrp= (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1)); - if (agrp == NULL) { - error("PoseChannel has invalid group!"); - return; - } - - /* try to find a group which is similar to the one we want (or add one) */ - for (grp= act->groups.first; grp; grp= grp->next) { - if (!strcmp(grp->name, agrp->name)) - break; - } - if (grp == NULL) { - grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup"); - - grp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED); - - /* copy name */ - sprintf(grp->name, agrp->name); - - /* deal with group-color copying (grp is destination, agrp is source) */ - memcpy(grp, agrp, sizeof(bActionGroup)); - actionbone_group_copycolors(grp, 1); - - BLI_addtail(&act->groups, grp); - } - - /* make sure this channel is definitely not connected to anything before adding to group */ - action_groups_removeachan(act, achan); - action_groups_addachan(act, grp, achan); - } -} - -/* This function is used when the user specifically requests to sync changes of pchans + bone groups - * to achans + action groups. All achans are detached from their groups, and all groups are destroyed. - * They are then recreated when the achans are reassigned to groups. - * - * Note: This doesn't preserve hand-created groups, and will operate on ALL action-channels regardless of - * whether they were selected or active. More specific filtering can be added later. - */ -void sync_pchan2achan_grouping () -{ - void *data; - short datatype; - bAction *act; - bActionChannel *achan, *next, *last; - bPose *pose; - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if ((datatype != ACTCONT_ACTION) || (data==NULL)) return; - if ((G.saction->pin) || (OBACT==NULL) || (OBACT->type != OB_ARMATURE)) { - error("Action doesn't belong to active armature"); - return; - } - - /* get data */ - act= (bAction *)data; - pose= OBACT->pose; - - /* remove achan->group links, then delete all groups */ - for (achan= act->chanbase.first; achan; achan= achan->next) - achan->grp = NULL; - BLI_freelistN(&act->groups); - - /* loop through all achans, reassigning them to groups (colors are resyncronised) */ - last= act->chanbase.last; - for (achan= act->chanbase.first; achan && achan!=last; achan= next) { - next= achan->next; - verify_pchan2achan_grouping(act, pose, achan->name); - } - - /* undo and redraw */ - BIF_undo_push("Sync Armature-Data and Action"); - allqueue(REDRAWACTION, 0); -} - -/* **************************************************** */ -/* TRANSFORM TOOLS */ - -/* main call to start transforming keyframes */ -void transform_action_keys (int mode, int dummy) -{ - void *data; - short datatype; - short context = (U.flag & USER_DRAGIMMEDIATE)?CTX_TWEAK:CTX_NONE; - - /* 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, context); - Transform(); - } - break; - case 's': - { - initTransform(TFM_TIME_SCALE, context); - Transform(); - } - break; - case 't': - { - initTransform(TFM_TIME_SLIDE, context); - Transform(); - } - break; - case 'e': - { - initTransform(TFM_TIME_EXTEND, context); - 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 */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT); - else - 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) { - if (ale->type == ACTTYPE_GPLAYER) - duplicate_gplayer_frames(ale->data); - else - duplicate_ipo_keys((Ipo *)ale->key_data); - } - - /* free filtered list */ - BLI_freelistN(&act_data); - - /* now, go into transform-grab mode, to move keys */ - BIF_TransformSetUndo("Add Duplicate"); - 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 */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT); - else - 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 if (ale->type == ACTTYPE_GPLAYER) - snap_gplayer_frames(ale->data, mode); - 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); - allqueue(REDRAWVIEW3D, 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 */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT); - else - 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 if (ale->type == ACTTYPE_GPLAYER) - mirror_gplayer_frames(ale->data, mode); - 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|In Active Group%x3"); - if (mode <= 0) return; - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU ); - if (mode == 2) filter |= ACTFILTER_SEL; - else if (mode == 3) filter |= ACTFILTER_ACTGROUPED; - - 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; - bConstraintChannel *conchan= (ale->type==ACTTYPE_CONCHAN) ? ale->data : NULL; - IpoCurve *icu= (IpoCurve *)ale->key_data; - - if (ob) - insertkey((ID *)ob, icu->blocktype, achan->name, ((conchan)?(conchan->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); - } - } - } - else { - /* this tool is not supported in this mode */ - return; - } - - BIF_undo_push("Insert Key"); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWBUTSOBJECT, 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 */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT); - else - 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) { - if (ale->type == ACTTYPE_GPLAYER) - delete_gplayer_frames((bGPDlayer *)ale->data); - else - 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 action-channels (only achans and conchans are considered) */ -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; - - /* deal with groups first */ - if (act->groups.first) { - bActionGroup *agrp, *grp; - bActionChannel *chan, *nchan; - - /* unlink achan's that belonged to this group (and make sure they're not selected if they weren't visible) */ - for (agrp= act->groups.first; agrp; agrp= grp) { - grp= agrp->next; - - /* remove if group is selected */ - if (SEL_AGRP(agrp)) { - for (chan= agrp->channels.first; chan && chan->grp==agrp; chan= nchan) { - nchan= chan->next; - - action_groups_removeachan(act, chan); - BLI_addtail(&act->chanbase, chan); - - if (EXPANDED_AGRP(agrp) == 0) - chan->flag &= ~(ACHAN_SELECTED|ACHAN_HILIGHTED); - } - - BLI_freelinkN(&act->groups, agrp); - } - } - } - - /* 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 references 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--; - } - - /* remove action-channel from group(s) */ - if (achan->grp) - action_groups_removeachan(act, achan); - - /* 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.0f, 0.001f, 0.1f, - "Clean Threshold"); - if (!ok) return; - if (datatype == ACTCONT_GPENCIL) 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); -} - - -/* little cache for values... */ -typedef struct tempFrameValCache { - float frame, val; -} tempFrameValCache; - -/* Evaluates the curves between each selected keyframe on each frame, and keys the value */ -void sample_action_keys (void) -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - - /* sanity checks */ - data= get_action_context(&datatype); - if (data == NULL) return; - if (datatype == ACTCONT_GPENCIL) return; - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU); - actdata_filter(&act_data, filter, data, datatype); - - /* loop through filtered data and add keys between selected keyframes on every frame */ - for (ale= act_data.first; ale; ale= ale->next) { - IpoCurve *icu= (IpoCurve *)ale->key_data; - BezTriple *bezt, *start=NULL, *end=NULL; - tempFrameValCache *value_cache, *fp; - int sfra, range; - int i, n; - - /* find selected keyframes... once pair has been found, add keyframes */ - for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { - /* check if selected, and which end this is */ - if (BEZSELECTED(bezt)) { - if (start) { - /* set end */ - end= bezt; - - /* cache values then add keyframes using these values, as adding - * keyframes while sampling will affect the outcome... - */ - range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) ); - sfra= (int)( floor(start->vec[1][0]) ); - - if (range) { - value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache"); - - /* sample values */ - for (n=0, fp=value_cache; n<range && fp; n++, fp++) { - fp->frame= (float)(sfra + n); - fp->val= eval_icu(icu, fp->frame); - } - - /* add keyframes with these */ - for (n=0, fp=value_cache; n<range && fp; n++, fp++) { - insert_vert_icu(icu, fp->frame, fp->val, 1); - } - - /* free temp cache */ - MEM_freeN(value_cache); - - /* as we added keyframes, we need to compensate so that bezt is at the right place */ - bezt = icu->bezt + i + range - 1; - i += (range - 1); - } - - /* bezt was selected, so it now marks the start of a whole new chain to search */ - start= bezt; - end= NULL; - } - else { - /* just set start keyframe */ - start= bezt; - end= NULL; - } - } - } - - /* recalculate channel's handles? */ - calchandles_ipocurve(icu); - } - - /* admin and redraws */ - BLI_freelistN(&act_data); - - BIF_undo_push("Sample Action Keys"); - 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.) - * Unless there is only one element in the buffer, names are also tested to check for compatability. - * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of - * the current frame and the 'first keyframe' (i.e. the earliest one in all channels). - * - The earliest frame is calculated per copy operation. - */ - -/* globals for copy/paste data (like for other copy/paste buffers) */ -ListBase actcopybuf = {NULL, NULL}; -static float actcopy_firstframe= 999999999.0f; - -/* 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); - } - - actcopybuf.first= actcopybuf.last= NULL; - actcopy_firstframe= 999999999.0f; -} - -/* 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 (and set first frame) */ - for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { - if (BEZSELECTED(bezt)) { - /* add to buffer ipo-curve */ - insert_bezt_icu(icn, bezt); - - /* check if this is the earliest frame encountered so far */ - if (bezt->vec[1][0] < actcopy_firstframe) - actcopy_firstframe= bezt->vec[1][0]; - } - } - } - } - - /* check if anything ended up in the buffer */ - if (ELEM(NULL, actcopybuf.first, actcopybuf.last)) - 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; - Object *ob= OBACT; - - const float offset = (float)(CFRA - actcopy_firstframe); - char *actname = NULL, *conname = NULL; - short no_name= 0; - - /* check if buffer is empty */ - if (ELEM(NULL, actcopybuf.first, actcopybuf.last)) { - error("No data in buffer to paste"); - return; - } - /* check if single channel in buffer (disregard names if so) */ - if (actcopybuf.first == actcopybuf.last) - no_name= 1; - - /* 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; - bActionChannel *achan; - IpoCurve *ico, *icu; - BezTriple *bezt; - int i; - - /* find suitable IPO-block from buffer to paste from */ - 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 ((no_name) || (strcmp(achan->name, achant->name)==0)) { - actname= achant->name; - - /* 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) { - conname= conchant->name; - 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 ((no_name) || (strcmp(achan->name, "#ACP_ShapeKey")==0)) { - actname= NULL; - ipo_src= achan->ipo; - break; - } - } - } - - /* this shouldn't happen, but it might */ - if (ipo_src == NULL) - continue; - - /* loop over curves, pasting keyframes */ - for (ico= ipo_src->curve.first; ico; ico= ico->next) { - /* get IPO-curve to paste to (IPO-curve might not exist for destination, so gets created) */ - icu= verify_ipocurve((ID *)ob, ico->blocktype, actname, conname, NULL, ico->adrcode, 1); - - if (icu) { - /* 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++) { - /* 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); - } - } - } - - /* free temp memory */ - BLI_freelistN(&act_data); - - /* do depsgraph updates (for 3d-view)? */ - if ((ob) && (G.saction->pin==0)) { - if (ob->type == OB_ARMATURE) - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA); - else - DAG_object_flush_update(G.scene, ob, OB_RECALC_OB); - } - - /* 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; - if (datatype == ACTCONT_GPENCIL) 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; - if (datatype == ACTCONT_GPENCIL) 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, *channel_owner; - short chantype; - - bActionGroup *agrp= NULL; - bActionChannel *achan= NULL; - bConstraintChannel *conchan= NULL; - IpoCurve *icu= NULL; - KeyBlock *kb= NULL; - bGPdata *gpd= NULL; - bGPDlayer *gpl= NULL; - - short mval[2]; - - int but=0; - char str[128]; - 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, &channel_owner); - - /* 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 if (chantype == ACTTYPE_GROUP) { - /* Action Group */ - agrp= (bActionGroup *)act_channel; - - strcpy(str, agrp->name); - protect= (agrp->flag & AGRP_PROTECTED); - expand = (agrp->flag & AGRP_EXPANDED); - - add_numbut(but++, TEX, "ActGroup: ", 0, 31, str, "Name of Action Group"); - add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Group is Expanded"); - add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Group is Protected"); - } - else if (chantype == ACTTYPE_GPLAYER) { - /* Grease-Pencil Layer */ - gpd= (bGPdata *)channel_owner; - gpl= (bGPDlayer *)act_channel; - - strcpy(str, gpl->info); - protect= (gpl->flag & GP_LAYER_LOCKED); - mute = (gpl->flag & GP_LAYER_HIDE); - - add_numbut(but++, TEX, "GP-Layer: ", 0, 128, str, "Name of Grease Pencil Layer"); - add_numbut(but++, TOG|SHO, "Hide", 0, 24, &mute, "Grease Pencil Layer is Visible"); - add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Grease Pencil Layer 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; - 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; - } - else if (agrp) { - strcpy(agrp->name, str); - BLI_uniquename(&( ((bAction *)data)->groups ), agrp, "Group", offsetof(bActionGroup, name), 32); - - if (expand) agrp->flag |= AGRP_EXPANDED; - else agrp->flag &= ~AGRP_EXPANDED; - - if (protect) agrp->flag |= AGRP_PROTECTED; - else agrp->flag &= ~AGRP_PROTECTED; - } - else if (gpl) { - strcpy(gpl->info, str); - BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info), 128); - - if (mute) gpl->flag |= GP_LAYER_HIDE; - else gpl->flag &= ~GP_LAYER_HIDE;; - - if (protect) gpl->flag |= GP_LAYER_LOCKED; - else gpl->flag &= ~GP_LAYER_LOCKED; - } - - allqueue(REDRAWACTION, 0); - allspace(REMAKEIPO, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - } -} - -/* Set/clear a particular flag (setting) for all selected + visible channels - * mode: 0 = toggle, 1 = turn on, 2 = turn off - */ -void setflag_action_channels (short mode) -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - char str[32]; - short val; - - /* get data */ - data= get_action_context(&datatype); - if (data == NULL) return; - - /* get setting to affect */ - if (mode == 2) { - val= pupmenu("Disable Setting%t|Protect %x1|Mute%x2"); - sprintf(str, "Disable Action Setting"); - } - else if (mode == 1) { - val= pupmenu("Enable Setting%t|Protect %x1|Mute%x2"); - sprintf(str, "Enable Action Setting"); - } - else { - val= pupmenu("Toggle Setting%t|Protect %x1|Mute%x2"); - sprintf(str, "Toggle Action Setting"); - } - if (val <= 0) return; - - /* filter data */ - filter= (ACTFILTER_VISIBLE | ACTFILTER_CHANNELS | ACTFILTER_SEL); - actdata_filter(&act_data, filter, data, datatype); - - /* affect selected channels */ - for (ale= act_data.first; ale; ale= ale->next) { - switch (ale->type) { - case ACTTYPE_GROUP: - { - bActionGroup *agrp= (bActionGroup *)ale->data; - - /* only 'protect' is available */ - if (val == 1) { - if (mode == 2) - agrp->flag &= ~AGRP_PROTECTED; - else if (mode == 1) - agrp->flag |= AGRP_PROTECTED; - else - agrp->flag ^= AGRP_PROTECTED; - } - } - break; - case ACTTYPE_ACHAN: - { - bActionChannel *achan= (bActionChannel *)ale->data; - - /* 'protect' and 'mute' */ - if ((val == 2) && (achan->ipo)) { - Ipo *ipo= achan->ipo; - - /* mute */ - if (mode == 2) - ipo->muteipo= 0; - else if (mode == 1) - ipo->muteipo= 1; - else - ipo->muteipo= (ipo->muteipo) ? 0 : 1; - } - else if (val == 1) { - /* protected */ - if (mode == 2) - achan->flag &= ~ACHAN_PROTECTED; - else if (mode == 1) - achan->flag |= ACHAN_PROTECTED; - else - achan->flag ^= ACHAN_PROTECTED; - } - } - break; - case ACTTYPE_CONCHAN: - { - bConstraintChannel *conchan= (bConstraintChannel *)ale->data; - - /* 'protect' and 'mute' */ - if ((val == 2) && (conchan->ipo)) { - Ipo *ipo= conchan->ipo; - - /* mute */ - if (mode == 2) - ipo->muteipo= 0; - else if (mode == 1) - ipo->muteipo= 1; - else - ipo->muteipo= (ipo->muteipo) ? 0 : 1; - } - else if (val == 1) { - /* protect */ - if (mode == 2) - conchan->flag &= ~CONSTRAINT_CHANNEL_PROTECTED; - else if (mode == 1) - conchan->flag |= CONSTRAINT_CHANNEL_PROTECTED; - else - conchan->flag ^= CONSTRAINT_CHANNEL_PROTECTED; - } - } - break; - case ACTTYPE_ICU: - { - IpoCurve *icu= (IpoCurve *)ale->data; - - /* mute */ - if (val == 2) { - if (mode == 2) - icu->flag &= ~IPO_MUTE; - else if (mode == 1) - icu->flag |= IPO_MUTE; - else - icu->flag ^= IPO_MUTE; - } - } - break; - case ACTTYPE_GPLAYER: - { - bGPDlayer *gpl= (bGPDlayer *)ale->data; - - /* 'protect' and 'mute' */ - if (val == 2) { - /* mute */ - if (mode == 2) - gpl->flag &= ~GP_LAYER_HIDE; - else if (mode == 1) - gpl->flag |= GP_LAYER_HIDE; - else - gpl->flag ^= GP_LAYER_HIDE; - } - else if (val == 1) { - /* protected */ - if (mode == 2) - gpl->flag &= ~GP_LAYER_LOCKED; - else if (mode == 1) - gpl->flag |= GP_LAYER_LOCKED; - else - gpl->flag ^= GP_LAYER_LOCKED; - } - } - break; - } - } - BLI_freelistN(&act_data); - - BIF_undo_push(str); - allspace(REMAKEIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWNLA, 0); -} - -/* **************************************************** */ -/* CHANNEL SELECTION */ - -/* select_mode = SELECT_REPLACE - * = SELECT_ADD - * = SELECT_SUBTRACT - * = SELECT_INVERT - */ -static void select_action_group (bAction *act, bActionGroup *agrp, int selectmode) -{ - /* Select the channel based on the selection mode */ - short select; - - switch (selectmode) { - case SELECT_ADD: - agrp->flag |= AGRP_SELECTED; - break; - case SELECT_SUBTRACT: - agrp->flag &= ~AGRP_SELECTED; - break; - case SELECT_INVERT: - agrp->flag ^= AGRP_SELECTED; - break; - } - select = (agrp->flag & AGRP_SELECTED) ? 1 : 0; - - set_active_actiongroup(act, agrp, select); -} - -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; - } -} - -/* Syncs selection of channels with selection of object elements in posemode */ -/* messy call... */ -static void select_poseelement_by_name (char *name, int select) -{ - Object *ob= OBACT; - bPoseChannel *pchan; - - if ((ob==NULL) || (ob->type!=OB_ARMATURE)) - return; - - if (abs(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 == NULL) - 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; -} - -int select_gplayer_channel (bGPdata *gpd, bGPDlayer *gpl, int selectmode) -{ - /* Select the channel based on the selection mode */ - int flag; - - switch (selectmode) { - case SELECT_ADD: - gpl->flag |= GP_LAYER_SELECT; - break; - case SELECT_SUBTRACT: - gpl->flag &= ~GP_LAYER_SELECT; - break; - case SELECT_INVERT: - gpl->flag ^= GP_LAYER_SELECT; - break; - } - - flag = (gpl->flag & GP_LAYER_SELECT) ? 1 : 0; - if (flag) - gpencil_layer_setactive(gpd, gpl); - - return flag; -} - - -/* select only the active action-group's action channels */ -void select_action_group_channels (bAction *act, bActionGroup *agrp) -{ - bActionChannel *achan; - - /* error checking */ - if (ELEM(NULL, act, agrp)) - return; - - /* deselect all other channels */ - deselect_actionchannels(act, 0); - - /* only select channels in group */ - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - select_channel(act, achan, SELECT_ADD); - - /* messy... set active bone */ - select_poseelement_by_name(achan->name, 1); - } -} - -/* ----------------------------------------- */ - -/* De-selects or inverts the selection of Channels in a given Action - * mode: 0 = default behaviour (select all), 1 = test if (de)select all, 2 = invert all - */ -void deselect_actionchannels (bAction *act, short mode) -{ - 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 (mode == 1) { - for (ale= act_data.first; ale; ale= ale->next) { - if (sel == 0) - break; - - switch (ale->type) { - case ACTTYPE_GROUP: - if (ale->flag & AGRP_SELECTED) - sel= 0; - break; - 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_GROUP: - { - bActionGroup *agrp= (bActionGroup *)ale->data; - - if (mode == 2) - agrp->flag ^= AGRP_SELECTED; - else if (sel) - agrp->flag |= AGRP_SELECTED; - else - agrp->flag &= ~AGRP_SELECTED; - - agrp->flag &= ~AGRP_ACTIVE; - } - break; - case ACTTYPE_ACHAN: - { - bActionChannel *achan= (bActionChannel *)ale->data; - - if (mode == 2) - achan->flag ^= AGRP_SELECTED; - else if (sel) - achan->flag |= ACHAN_SELECTED; - else - achan->flag &= ~ACHAN_SELECTED; - - select_poseelement_by_name(achan->name, sel); - achan->flag &= ~ACHAN_HILIGHTED; - } - break; - case ACTTYPE_CONCHAN: - { - bConstraintChannel *conchan= (bConstraintChannel *)ale->data; - - if (mode == 2) - conchan->flag ^= CONSTRAINT_CHANNEL_SELECT; - else if (sel) - conchan->flag |= CONSTRAINT_CHANNEL_SELECT; - else - conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT; - } - break; - case ACTTYPE_ICU: - { - IpoCurve *icu= (IpoCurve *)ale->data; - - if (mode == 2) - icu->flag ^= IPO_SELECT; - else if (sel) - icu->flag |= IPO_SELECT; - else - icu->flag &= ~IPO_SELECT; - - icu->flag &= ~IPO_ACTIVE; - } - break; - } - } - - /* Cleanup */ - BLI_freelistN(&act_data); -} - -/* deselects channels in the action editor */ -void deselect_action_channels (short mode) -{ - 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, mode); - else if (datatype == ACTCONT_GPENCIL) - deselect_gpencil_layers(data, mode); - // 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; - - /* determine type-based settings */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE); - else - filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); - - /* filter data */ - 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 (ale->type == ACTTYPE_GPLAYER) { - if (is_gplayer_frame_selected(ale->data)) { - sel= 0; - break; - } - } - else { - if (is_ipo_key_selected(ale->key_data)) { - sel= 0; - break; - } - } - } - } - - /* Now set the flags */ - for (ale= act_data.first; ale; ale= ale->next) { - if (ale->type == ACTTYPE_GPLAYER) - set_gplayer_frame_selection(ale->data, sel); - else - 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, *channel_owner; - short chantype; - - /* get channel, and act according to type */ - act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner); - switch (chantype) { - case ACTTYPE_GROUP: - { - bActionGroup *agrp= (bActionGroup *)act_channel; - bActionChannel *achan; - bConstraintChannel *conchan; - - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - select_ipo_bezier_keys(achan->ipo, select_mode); - - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) - select_ipo_bezier_keys(conchan->ipo, select_mode); - } - } - break; - 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; - case ACTTYPE_GPLAYER: - { - bGPDlayer *gpl= (bGPDlayer *)act_channel; - select_gpencil_frames(gpl, 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.5f; - rectf.xmax = rectf.xmax + 0.5f; - - /* filter data */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE); - else - 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); -} - -/* Selects all visible keyframes between the specified markers */ -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); -} - -/* Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */ -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 */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE); - else - filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - /* select keys on the side where most data occurs */ - 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 if (ale->type == ACTTYPE_GPLAYER) - borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD); - 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); -} - -/* ----------------------------------------- */ - -/* Jumps to the frame where the next/previous keyframe (that is visible) occurs - * dir: indicates direction - */ -void nextprev_action_keyframe (short dir) -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - - ListBase elems= {NULL, NULL}; - CfraElem *ce, *nearest=NULL; - float dist, min_dist= 1000000; - - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) return; - - /* abort if no direction */ - if (dir == 0) - return; - - /* get list of keyframes that can be used (in global-time) */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE); - else - filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS); - actdata_filter(&act_data, filter, data, datatype); - - 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); - make_cfra_list(ale->key_data, &elems); - actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1); - } - else if (ale->type == ACTTYPE_GPLAYER) - gplayer_make_cfra_list(ale->key_data, &elems, 0); - else - make_cfra_list(ale->key_data, &elems); - } - - BLI_freelistN(&act_data); - - /* find nearest keyframe to current frame */ - for (ce= elems.first; ce; ce= ce->next) { - dist= ABS(ce->cfra - CFRA); - - if (dist < min_dist) { - min_dist= dist; - nearest= ce; - } - } - - /* if a nearest keyframe was found, use the one either side */ - if (nearest) { - short changed= 0; - - if ((dir > 0) && (nearest->next)) { - CFRA= (int)nearest->next->cfra; - changed= 1; - } - else if ((dir < 0) && (nearest->prev)) { - CFRA= (int)nearest->prev->cfra; - changed= 1; - } - - if (changed) { - update_for_newframe(); - allqueue(REDRAWALL, 0); - } - } - - /* free temp data */ - BLI_freelistN(&elems); -} - -/* ----------------------------------------- */ - -/* 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 */ - if (datatype == ACTCONT_GPENCIL) { - filter= (ACTFILTER_VISIBLE); - actdata_filter(&act_data, filter, data, datatype); - - for (ale= act_data.first; ale; ale= ale->next) - gplayer_make_cfra_list(ale->data, &elems, 1); - } - else { - 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; - case 3: /* current frame */ - /* make a single CfraElem */ - ce= MEM_callocN(sizeof(CfraElem), "cfraElem"); - BLI_addtail(&elems, ce); - - /* apply scaled action correction if needed */ - if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) - ce->cfra= (float)get_action_frame(OBACT, (float)CFRA); - else - ce->cfra= (float)CFRA; - } - - /* loop through all of the keys and select additional keyframes - * based on the keys found to be selected above - */ - if (datatype == ACTCONT_GPENCIL) - filter= (ACTFILTER_VISIBLE); - else - 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) { - /* select elements with frame number matching cfraelem */ - if (ale->type == ACTTYPE_GPLAYER) { - bGPDlayer *gpl= (bGPDlayer *)ale->data; - bGPDframe *gpf; - - for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { - if ( (int)ce->cfra == gpf->framenum ) - gpf->flag |= GP_FRAME_SELECT; - } - } - else { - 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 action-channels */ -void borderselect_actionchannels (void) -{ - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - int filter; - void *data; - short datatype; - - rcti rect; - rctf rectf; - int val, selectmode; - short mval[2]; - float ymin, ymax; - - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) return; - if (ELEM(datatype, ACTCONT_ACTION, ACTCONT_GPENCIL)==0) return; - - /* draw and handle the borderselect stuff (ui) and get the select rect */ - if ( (val = get_border(&rect, 3)) ) { - selectmode= ((val==LEFTMOUSE) ? SELECT_ADD : SELECT_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); - - 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 channel is within border-select region, alter it */ - if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) { - /* only the following types can be selected */ - switch (ale->type) { - case ACTTYPE_GROUP: /* action group */ - { - bActionGroup *agrp= (bActionGroup *)ale->data; - - if (selectmode == SELECT_ADD) - agrp->flag |= AGRP_SELECTED; - else - agrp->flag &= ~AGRP_SELECTED; - } - break; - case ACTTYPE_ACHAN: /* action channel */ - case ACTTYPE_FILLIPO: /* expand ipo curves = action channel */ - case ACTTYPE_FILLCON: /* expand constraint channels = action channel */ - { - bActionChannel *achan= (bActionChannel *)ale->data; - - if (selectmode == SELECT_ADD) - achan->flag |= ACHAN_SELECTED; - else - achan->flag &= ~ACHAN_SELECTED; - - /* messy... set active bone */ - select_poseelement_by_name(achan->name, selectmode); - } - break; - case ACTTYPE_CONCHAN: /* constraint channel */ - { - bConstraintChannel *conchan = (bConstraintChannel *)ale->data; - - if (selectmode == SELECT_ADD) - conchan->flag |= CONSTRAINT_CHANNEL_SELECT; - else - conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT; - } - break; - case ACTTYPE_ICU: /* ipo-curve channel */ - { - IpoCurve *icu = (IpoCurve *)ale->data; - - if (selectmode == SELECT_ADD) - icu->flag |= IPO_SELECT; - else - icu->flag &= ~IPO_SELECT; - } - break; - case ACTTYPE_GPLAYER: /* grease-pencil layer */ - { - bGPDlayer *gpl = (bGPDlayer *)ale->data; - - if (selectmode == SELECT_ADD) - gpl->flag |= GP_LAYER_SELECT; - else - gpl->flag &= ~GP_LAYER_SELECT; - } - break; - } - - /* select action-channel 'owner' */ - if ((ale->owner) && (ale->ownertype == ACTTYPE_ACHAN)) { - bActionChannel *achano= (bActionChannel *)ale->owner; - - /* messy... set active bone */ - select_poseelement_by_name(achano->name, selectmode); - } - } - - ymax=ymin; - } - - /* cleanup */ - BLI_freelistN(&act_data); - - BIF_undo_push("Border Select Action"); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWVIEW3D, 0); - } -} - -/* some quick defines for borderselect modes */ -enum { - ACTEDIT_BORDERSEL_ALL = 0, - ACTEDIT_BORDERSEL_FRA, - ACTEDIT_BORDERSEL_CHA -}; - -/* 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); - } - else if (ale->type == ACTTYPE_GROUP) { - bActionGroup *agrp= ale->data; - bActionChannel *achan; - bConstraintChannel *conchan; - - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); - - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) - borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); - } - } - else if (ale->type == ACTTYPE_GPLAYER) { - borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); - } - 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); - } - else if (ale->type == ACTTYPE_GROUP) { - bActionGroup *agrp= ale->data; - bActionChannel *achan; - bConstraintChannel *conchan; - - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - select_ipo_bezier_keys(achan->ipo, selectmode); - - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) - select_ipo_bezier_keys(conchan->ipo, selectmode); - } - } - else if (ale->type == ACTTYPE_GPLAYER) { - select_gpencil_frames(ale->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); - } - else if (ale->type == ACTTYPE_GROUP) { - bActionGroup *agrp= ale->data; - bActionChannel *achan; - bConstraintChannel *conchan; - - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode); - - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) - borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode); - } - } - else if (ale->type == ACTTYPE_GPLAYER) { - borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode); - } - } - } - - 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; - bActionGroup *agrp= NULL; - bActionChannel *achan= NULL; - bConstraintChannel *conchan= NULL; - IpoCurve *icu= NULL; - bGPdata *gpd = NULL; - bGPDlayer *gpl = NULL; - TimeMarker *marker, *pmarker; - - void *act_channel; - short sel, act_type = 0; - float selx = 0.0; - - /* 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; - if (datatype == ACTCONT_GPENCIL) gpd= (bGPdata *)data; - - act_channel= get_nearest_action_key(&selx, &sel, &act_type, &achan); - marker= find_nearest_marker(SCE_MARKERS, 1); - pmarker= (act) ? find_nearest_marker(&act->markers, 1) : NULL; - - if (marker) { - /* what about scene's markers? */ - 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); - } - else if (pmarker) { - /* action's markers are drawn behind scene markers */ - if (selectmode == SELECT_REPLACE) { - action_set_activemarker(act, pmarker, 1); - pmarker->flag |= SELECT; - } - else if (selectmode == SELECT_INVERT) { - if (pmarker->flag & SELECT) { - pmarker->flag &= ~SELECT; - action_set_activemarker(act, NULL, 0); - } - else { - pmarker->flag |= SELECT; - action_set_activemarker(act, pmarker, 0); - } - } - else if (selectmode == SELECT_ADD) { - pmarker->flag |= SELECT; - action_set_activemarker(act, pmarker, 0); - } - else if (selectmode == SELECT_SUBTRACT) { - pmarker->flag &= ~SELECT; - action_set_activemarker(act, NULL, 0); - } - - // TODO: local-markers cannot be moved atm... - //std_rmouse_transform(transform_markers); - - allqueue(REDRAWACTION, 0); - allqueue(REDRAWBUTSEDIT, 0); - } - else if (act_channel) { - /* must have been a 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; - case ACTTYPE_GROUP: - agrp= (bActionGroup *)act_channel; - break; - case ACTTYPE_GPLAYER: - gpl= (bGPDlayer *)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); - - /* Highlight either an Action-Channel or Action-Group */ - if (achan) { - achan->flag |= ACHAN_SELECTED; - hilight_channel(act, achan, 1); - select_poseelement_by_name(achan->name, 2); /* 2 is activate */ - } - else if (agrp) { - agrp->flag |= AGRP_SELECTED; - set_active_actiongroup(act, agrp, 1); - } - } - else if (datatype == ACTCONT_GPENCIL) { - deselect_action_channels(0); - - /* Highlight gpencil layer */ - gpl->flag |= GP_LAYER_SELECT; - gpencil_layer_setactive(gpd, gpl); - } - } - - if (icu) - select_icu_key(icu, selx, selectmode); - else if (conchan) - select_ipo_key(conchan->ipo, selx, selectmode); - else if (achan) - select_ipo_key(achan->ipo, selx, selectmode); - else if (agrp) { - for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) { - select_ipo_key(achan->ipo, selx, selectmode); - - for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) - select_ipo_key(conchan->ipo, selx, selectmode); - } - } - else if (gpl) - select_gpencil_frame(gpl, (int)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); - } -} - -/* lefthand side - mouse-click */ -static void mouse_actionchannels (short mval[]) -{ - bAction *act= G.saction->action; - void *data, *act_channel, *channel_owner; - 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, &channel_owner); - - /* action to take depends on what channel we've got */ - switch (chantype) { - case ACTTYPE_GROUP: - { - bActionGroup *agrp= (bActionGroup *)act_channel; - - if ((mval[0] < 16) && (agrp->channels.first)) { - /* toggle expand */ - agrp->flag ^= AGRP_EXPANDED; - } - else if (mval[0] >= (NAMEWIDTH-16)) { - /* toggle protection/locking */ - agrp->flag ^= AGRP_PROTECTED; - } - else { - /* select/deselect group */ - if (G.qual == LR_SHIFTKEY) { - /* inverse selection status of group */ - select_action_group(act, agrp, SELECT_INVERT); - } - else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) { - /* select all in group (and deselect everthing else) */ - select_action_group_channels(act, agrp); - select_action_group(act, agrp, SELECT_ADD); - } - else { - /* select group by itself */ - deselect_actionchannels(act, 0); - select_action_group(act, agrp, SELECT_ADD); - } - } - } - break; - 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); - } - - allspace(REMAKEIPO, 0); - } - 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; - case ACTTYPE_GPDATABLOCK: - { - bGPdata *gpd= (bGPdata *)act_channel; - - /* toggle expand */ - gpd->flag ^= GP_DATA_EXPAND; - } - break; - case ACTTYPE_GPLAYER: - { - bGPdata *gpd= (bGPdata *)channel_owner; - bGPDlayer *gpl= (bGPDlayer *)act_channel; - - if (mval[0] >= (NAMEWIDTH-16)) { - /* toggle lock */ - gpl->flag ^= GP_LAYER_LOCKED; - } - else if (mval[0] >= (NAMEWIDTH-32)) { - /* toggle hide */ - gpl->flag ^= GP_LAYER_HIDE; - } - else { - /* select/deselect */ - if (G.qual & LR_SHIFTKEY) { - select_gplayer_channel(gpd, gpl, SELECT_INVERT); - } - else { - deselect_gpencil_layers(data, 0); - select_gplayer_channel(gpd, gpl, 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 */ - -/* make sure all action-channels belong to a group (and clear action's list) */ -static void split_groups_action_temp (bAction *act, bActionGroup *tgrp) -{ - bActionChannel *achan; - bActionGroup *agrp; - - /* Separate action-channels into lists per group */ - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - if (agrp->channels.first) { - achan= agrp->channels.last; - act->chanbase.first= achan->next; - - achan= agrp->channels.first; - achan->prev= NULL; - - achan= agrp->channels.last; - achan->next= NULL; - } - } - - /* Initialise memory for temp-group */ - memset(tgrp, 0, sizeof(bActionGroup)); - tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP); - strcpy(tgrp->name, "#TempGroup"); - - /* Move any action-channels not already moved, to the temp group */ - if (act->chanbase.first) { - /* start of list */ - achan= act->chanbase.first; - achan->prev= NULL; - tgrp->channels.first= achan; - act->chanbase.first= NULL; - - /* end of list */ - achan= act->chanbase.last; - achan->next= NULL; - tgrp->channels.last= achan; - act->chanbase.last= NULL; - } - - /* Add temp-group to list */ - BLI_addtail(&act->groups, tgrp); -} - -/* link lists of channels that groups have */ -static void join_groups_action_temp (bAction *act) -{ - bActionGroup *agrp; - bActionChannel *achan; - - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - ListBase tempGroup; - - /* add list of channels to action's channels */ - tempGroup= agrp->channels; - addlisttolist(&act->chanbase, &agrp->channels); - agrp->channels= tempGroup; - - /* clear moved flag */ - agrp->flag &= ~AGRP_MOVED; - - /* if temp-group... remove from list (but don't free as it's on the stack!) */ - if (agrp->flag & AGRP_TEMP) { - BLI_remlink(&act->groups, agrp); - break; - } - } - - /* clear "moved" flag from all achans */ - for (achan= act->chanbase.first; achan; achan= achan->next) - achan->flag &= ~ACHAN_MOVED; -} - - -static short rearrange_actchannel_is_ok (Link *channel, short type) -{ - if (type == ACTTYPE_GROUP) { - bActionGroup *agrp= (bActionGroup *)channel; - - if (SEL_AGRP(agrp) && !(agrp->flag & AGRP_MOVED)) - return 1; - } - else if (type == ACTTYPE_ACHAN) { - bActionChannel *achan= (bActionChannel *)channel; - - if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) - return 1; - } - - return 0; -} - -static short rearrange_actchannel_after_ok (Link *channel, short type) -{ - if (type == ACTTYPE_GROUP) { - bActionGroup *agrp= (bActionGroup *)channel; - - if (agrp->flag & AGRP_TEMP) - return 0; - } - - return 1; -} - - -static short rearrange_actchannel_top (ListBase *list, Link *channel, short type) -{ - if (rearrange_actchannel_is_ok(channel, type)) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* make it first element */ - BLI_insertlinkbefore(list, list->first, channel); - - return 1; - } - - return 0; -} - -static short rearrange_actchannel_up (ListBase *list, Link *channel, short type) -{ - if (rearrange_actchannel_is_ok(channel, type)) { - Link *prev= channel->prev; - - if (prev) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* push it up */ - BLI_insertlinkbefore(list, prev, channel); - - return 1; - } - } - - return 0; -} - -static short rearrange_actchannel_down (ListBase *list, Link *channel, short type) -{ - if (rearrange_actchannel_is_ok(channel, type)) { - Link *next = (channel->next) ? channel->next->next : NULL; - - if (next) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* move it down */ - BLI_insertlinkbefore(list, next, channel); - - return 1; - } - else if (rearrange_actchannel_after_ok(list->last, type)) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* add at end */ - BLI_addtail(list, channel); - - return 1; - } - else { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* add just before end */ - BLI_insertlinkbefore(list, list->last, channel); - - return 1; - } - } - - return 0; -} - -static short rearrange_actchannel_bottom (ListBase *list, Link *channel, short type) -{ - if (rearrange_actchannel_is_ok(channel, type)) { - if (rearrange_actchannel_after_ok(list->last, type)) { - /* take it out off the chain keep data */ - BLI_remlink(list, channel); - - /* add at end */ - BLI_addtail(list, channel); - - return 1; - } - } - - return 0; -} - - -/* Change the order of action-channels - * mode: REARRANGE_ACTCHAN_* - */ -void rearrange_action_channels (short mode) -{ - bAction *act; - bActionChannel *achan, *chan; - bActionGroup *agrp, *grp; - bActionGroup tgrp; - - void *data; - short datatype; - - short (*rearrange_func)(ListBase *, Link *, short); - short do_channels = 1; - char undostr[60]; - - /* Get the active action, exit if none are selected */ - data = get_action_context(&datatype); - if (data == NULL) return; - if (datatype != ACTCONT_ACTION) return; - act= (bAction *)data; - - /* exit if invalid mode */ - switch (mode) { - case REARRANGE_ACTCHAN_TOP: - strcpy(undostr, "Channel(s) to Top"); - rearrange_func= rearrange_actchannel_top; - break; - case REARRANGE_ACTCHAN_UP: - strcpy(undostr, "Channel(s) Move Up"); - rearrange_func= rearrange_actchannel_up; - break; - case REARRANGE_ACTCHAN_DOWN: - strcpy(undostr, "Channel(s) Move Down"); - rearrange_func= rearrange_actchannel_down; - break; - case REARRANGE_ACTCHAN_BOTTOM: - strcpy(undostr, "Channel(s) to Bottom"); - rearrange_func= rearrange_actchannel_bottom; - break; - default: - return; - } - - /* make sure we're only operating with groups */ - split_groups_action_temp(act, &tgrp); - - /* rearrange groups first (and then, only consider channels if the groups weren't moved) */ - #define GET_FIRST(list) ((mode > 0) ? (list.first) : (list.last)) - #define GET_NEXT(item) ((mode > 0) ? (item->next) : (item->prev)) - - for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) { - /* Get next group to consider */ - grp= GET_NEXT(agrp); - - /* try to do group first */ - if (rearrange_func(&act->groups, (Link *)agrp, ACTTYPE_GROUP)) { - do_channels= 0; - agrp->flag |= AGRP_MOVED; - } - } - - if (do_channels) { - for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) { - /* Get next group to consider */ - grp= GET_NEXT(agrp); - - /* only consider action-channels if they're visible (group expanded) */ - if (EXPANDED_AGRP(agrp)) { - for (achan= GET_FIRST(agrp->channels); achan; achan= chan) { - /* Get next channel to consider */ - chan= GET_NEXT(achan); - - /* Try to do channel */ - if (rearrange_func(&agrp->channels, (Link *)achan, ACTTYPE_ACHAN)) - achan->flag |= ACHAN_MOVED; - } - } - } - } - #undef GET_FIRST - #undef GET_NEXT - - /* assemble lists into one list (and clear moved tags) */ - join_groups_action_temp(act); - - /* Undo + redraw */ - BIF_undo_push(undostr); - allqueue(REDRAWACTION, 0); -} - -/* ******************************************************************* */ -/* CHANNEL VISIBILITY/FOLDING */ - -/* Expand all channels to show full hierachy */ -void expand_all_action (void) -{ - void *data; - short datatype; - - bAction *act; - bActionChannel *achan; - bActionGroup *agrp; - short mode= 1; - - /* Get the selected action, exit if none are selected */ - data = get_action_context(&datatype); - if (data == NULL) return; - if (datatype != ACTCONT_ACTION) return; - act= (bAction *)data; - - /* check if expand all, or close all */ - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - if (EXPANDED_AGRP(agrp)) { - mode= 0; - break; - } - } - - if (mode == 0) { - for (achan= act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (EXPANDED_ACHAN(achan)) { - mode= 0; - break; - } - } - } - } - - /* expand/collapse depending on mode */ - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - if (mode == 1) - agrp->flag |= AGRP_EXPANDED; - else - agrp->flag &= ~AGRP_EXPANDED; - } - - for (achan=act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan)) { - if (mode == 1) - achan->flag |= (ACHAN_EXPANDED|ACHAN_SHOWIPO|ACHAN_SHOWCONS); - else - achan->flag &= ~(ACHAN_EXPANDED|ACHAN_SHOWIPO|ACHAN_SHOWCONS); - } - } - - /* Cleanup and do redraws */ - BIF_undo_push("Expand Action Hierachy"); - allqueue(REDRAWACTION, 0); -} - -/* Expands those groups which are hiding a selected actionchannel */ -void expand_obscuregroups_action (void) -{ - void *data; - short datatype; - - bAction *act; - bActionChannel *achan; - - /* Get the selected action, exit if none are selected */ - data = get_action_context(&datatype); - if (data == NULL) return; - if (datatype != ACTCONT_ACTION) return; - act= (bAction *)data; - - /* check if expand all, or close all */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { - if (achan->grp) - achan->grp->flag |= AGRP_EXPANDED; - } - } - - /* Cleanup and do redraws */ - BIF_undo_push("Show Group-Hidden Channels"); - allqueue(REDRAWACTION, 0); -} - -/* For visible channels, expand/collapse one level */ -void openclose_level_action (short mode) -{ - void *data; - short datatype; - - bAction *act; - bActionChannel *achan; - bActionGroup *agrp; - - /* Get the selected action, exit if none are selected */ - data = get_action_context(&datatype); - if (data == NULL) return; - if (datatype != ACTCONT_ACTION) return; - act= (bAction *)data; - - /* Abort if no operation required */ - if (mode == 0) return; - - /* Only affect selected channels */ - for (achan= act->chanbase.first; achan; achan= achan->next) { - /* make sure if there is a group, it isn't about to be collapsed and is open */ - if ( (achan->grp==NULL) || (EXPANDED_AGRP(achan->grp) && SEL_AGRP(achan->grp)==0) ) { - if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) { - if (EXPANDED_ACHAN(achan)) { - if (FILTER_IPO_ACHAN(achan) || FILTER_CON_ACHAN(achan)) { - if (mode < 0) - achan->flag &= ~(ACHAN_SHOWIPO|ACHAN_SHOWCONS); - } - else { - if (mode > 0) - achan->flag |= (ACHAN_SHOWIPO|ACHAN_SHOWCONS); - else - achan->flag &= ~ACHAN_EXPANDED; - } - } - else { - if (mode > 0) - achan->flag |= ACHAN_EXPANDED; - } - } - } - } - - /* Expand/collapse selected groups */ - for (agrp= act->groups.first; agrp; agrp= agrp->next) { - if (SEL_AGRP(agrp)) { - if (mode < 0) - agrp->flag &= ~AGRP_EXPANDED; - else - agrp->flag |= AGRP_EXPANDED; - } - } - - /* Cleanup and do redraws */ - BIF_undo_push("Expand/Collapse Action Level"); - allqueue(REDRAWACTION, 0); -} - -/* **************************************************** */ -/* ACTION MARKERS (PoseLib features) */ -/* NOTE: yes, these duplicate code from edittime.c a bit, but these do a bit more... - * These could get merged with those someday if need be... (Aligorith, 20071230) - */ - -/* Makes the given marker the active one - * - deselect indicates whether unactive ones should be deselected too - */ -void action_set_activemarker (bAction *act, TimeMarker *active, short deselect) -{ - TimeMarker *marker; - int index= 0; - - /* sanity checks */ - if (act == NULL) - return; - act->active_marker= 0; - - /* set appropriate flags for all markers */ - for (marker=act->markers.first; marker; marker=marker->next, index++) { - /* only active may be active */ - if (marker == active) { - act->active_marker= index + 1; - marker->flag |= (SELECT|ACTIVE); - } - else { - if (deselect) - marker->flag &= ~(SELECT|ACTIVE); - else - marker->flag &= ~ACTIVE; - } - } -} - -/* Adds a local marker to the active action */ -void action_add_localmarker (bAction *act, int frame) -{ - TimeMarker *marker; - char name[64]; - - /* sanity checks */ - if (act == NULL) - return; - - /* get name of marker */ - sprintf(name, "Pose"); - if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0) - return; - - /* add marker to action - replaces any existing marker there */ - for (marker= act->markers.first; marker; marker= marker->next) { - if (marker->frame == frame) { - BLI_strncpy(marker->name, name, sizeof(marker->name)); - break; - } - } - if (marker == NULL) { - marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker"); - - BLI_strncpy(marker->name, name, sizeof(marker->name)); - marker->frame= frame; - - BLI_addtail(&act->markers, marker); - } - - /* validate the name */ - BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); - - /* sets the newly added marker as the active one */ - action_set_activemarker(act, marker, 1); - - BIF_undo_push("Action Add Marker"); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWBUTSEDIT, 0); -} - -/* Renames the active local marker to the active action */ -void action_rename_localmarker (bAction *act) -{ - TimeMarker *marker; - char name[64]; - int val; - - /* sanity checks */ - if (act == NULL) - return; - - /* get active marker to rename */ - if (act->active_marker == 0) - return; - else - val= act->active_marker; - - if (val <= 0) return; - marker= BLI_findlink(&act->markers, val-1); - if (marker == NULL) return; - - /* get name of marker */ - sprintf(name, marker->name); - if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0) - return; - - /* copy then validate name */ - BLI_strncpy(marker->name, name, sizeof(marker->name)); - BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64); - - /* undo and update */ - BIF_undo_push("Action Rename Marker"); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWACTION, 0); -} - -/* Deletes all selected markers, and adjusts things as appropriate */ -void action_remove_localmarkers (bAction *act) -{ - TimeMarker *marker, *next; - - /* sanity checks */ - if (act == NULL) - return; - - /* remove selected markers */ - for (marker= act->markers.first; marker; marker= next) { - next= marker->next; - - if (marker->flag & SELECT) - BLI_freelinkN(&act->markers, marker); - } - - /* clear active just in case */ - act->active_marker= 0; - - /* undo and update */ - BIF_undo_push("Action Remove Marker(s)"); - allqueue(REDRAWBUTSEDIT, 0); - allqueue(REDRAWACTION, 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; - - /* 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+0.5f); - 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 (ELEM(datatype, ACTCONT_ACTION, ACTCONT_GPENCIL)) { - /* 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 MIDDLEMOUSE: - case WHEELUPMOUSE: - case WHEELDOWNMOUSE: - view2dmove(event); /* in drawipo.c */ - break; - - case AKEY: - if (mval[0] < NAMEWIDTH) { - deselect_action_channels(1); - BIF_undo_push("(De)Select Action Channels"); - 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); - BIF_undo_push("(De)Select Markers"); - allqueue(REDRAWTIME, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWSOUND, 0); - } - else { - deselect_action_keys(1, 1); - BIF_undo_push("(De)Select Keys"); - 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_actionchannels(); - else - 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: - /* Action Channel Groups */ - if (G.qual == LR_SHIFTKEY) - action_groups_group(0); - else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - action_groups_group(1); - else if (G.qual == LR_ALTKEY) - action_groups_ungroup(); - - /* Transforms */ - else { - if (mval[0] >= ACTWIDTH) { - if (G.qual == LR_CTRLKEY) - transform_markers('g', 0); - else - 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 IKEY: - if (G.qual & LR_CTRLKEY) { - if (mval[0] < ACTWIDTH) { - deselect_action_channels(2); - BIF_undo_push("Inverse Action Channels"); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0); - } - else if (G.qual & LR_SHIFTKEY) { - deselect_markers(0, 2); - BIF_undo_push("Inverse Markers"); - allqueue(REDRAWMARKER, 0); - } - else { - deselect_action_keys(0, 2); - BIF_undo_push("Inverse Keys"); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0); - } - } - break; - - case KKEY: - if (G.qual == LR_ALTKEY) - markers_selectkeys_between(); - else if (G.qual == LR_SHIFTKEY) - column_select_action_keys(2); - else if (G.qual == LR_CTRLKEY) - column_select_action_keys(3); - else - column_select_action_keys(1); - - allqueue(REDRAWMARKER, 0); - break; - - case LKEY: - /* poselib manipulation - only for actions */ - if (datatype == ACTCONT_ACTION) { - if (G.qual == LR_SHIFTKEY) - action_add_localmarker(data, CFRA); - else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - action_rename_localmarker(data); - else if (G.qual == LR_ALTKEY) - action_remove_localmarkers(data); - else if (G.qual == LR_CTRLKEY) { - G.saction->flag |= SACTION_POSEMARKERS_MOVE; - transform_markers('g', 0); - G.saction->flag &= ~SACTION_POSEMARKERS_MOVE; - } - } - 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) { - /* panel will not always show useful info! */ - if (mval[0] > ACTWIDTH) { - add_blockhandler(curarea, ACTION_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE); - scrarea_queue_winredraw(curarea); - } - else - numbuts_action(); - } - break; - - case OKEY: - if (G.qual & LR_ALTKEY) - sample_action_keys(); - else - clean_action(); - break; - - case PKEY: - if (G.qual == (LR_CTRLKEY|LR_ALTKEY)) /* set preview range to range of action */ - action_previewrange_set(G.saction->action); - else 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 WKEY: - /* toggle/turn-on\off-based-on-setting */ - if (G.qual) { - if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - val= 1; - else if (G.qual == LR_ALTKEY) - val= 2; - else - val= 0; - - setflag_action_channels(val); - } - break; - - case PAGEUPKEY: - if (datatype == ACTCONT_ACTION) { - if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - rearrange_action_channels(REARRANGE_ACTCHAN_TOP); - else if (G.qual == LR_SHIFTKEY) - rearrange_action_channels(REARRANGE_ACTCHAN_UP); - else if (G.qual == LR_CTRLKEY) - nextprev_action_keyframe(1); - else - nextprev_marker(1); - } - else if (datatype == ACTCONT_SHAPEKEY) { - /* only jump to markers possible (key channels can't be moved yet) */ - if (G.qual == LR_CTRLKEY) - nextprev_action_keyframe(1); - else - nextprev_marker(1); - } - break; - case PAGEDOWNKEY: - if (datatype == ACTCONT_ACTION) { - if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) - rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM); - else if (G.qual == LR_SHIFTKEY) - rearrange_action_channels(REARRANGE_ACTCHAN_DOWN); - else if (G.qual == LR_CTRLKEY) - nextprev_action_keyframe(-1); - else - nextprev_marker(-1); - } - else if (datatype == ACTCONT_SHAPEKEY) { - /* only jump to markers possible (key channels can't be moved yet) */ - if (G.qual == LR_CTRLKEY) - nextprev_action_keyframe(-1); - else - nextprev_marker(-1); - } - break; - - case DELKEY: - case XKEY: - /* markers are incorported under shift-modifier (it does go against conventions, but oh well :/) */ - if (G.qual == LR_SHIFTKEY) { - if (okee("Erase selected marker(s)?")) { - if (mval[0] >= NAMEWIDTH) - remove_marker(); - } - } - else { - if (okee("Erase selected?")) { - if (mval[0] < NAMEWIDTH) { - if (datatype == ACTCONT_ACTION) - delete_action_channels(); - else if (datatype == ACTCONT_GPENCIL) - delete_gpencil_layers(); - } - else - delete_action_keys(); - } - } - - allqueue(REDRAWMARKER, 0); - - break; - - case ACCENTGRAVEKEY: - if (datatype == ACTCONT_ACTION) { - if (G.qual == LR_SHIFTKEY) - expand_obscuregroups_action(); - else - expand_all_action(); - } - break; - - case PADPLUSKEY: - if (G.qual == LR_CTRLKEY) { - if (datatype == ACTCONT_ACTION) - openclose_level_action(1); - } - else { - view2d_zoom(G.v2d, 0.1154f, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); - - doredraw= 1; - } - break; - case PADMINUS: - if (G.qual == LR_CTRLKEY) { - if (datatype == ACTCONT_ACTION) - openclose_level_action(-1); - } - else { - view2d_zoom(G.v2d, -0.15f, sa->winx, sa->winy); - test_view2d(G.v2d, sa->winx, sa->winy); - view2d_do_locks(curarea, V2D_LOCK_COPY); - - doredraw= 1; - } - break; - - case HOMEKEY: - do_action_buttons(B_ACTHOME); /* header */ - break; - } - } - - if (doredraw) addqueue(curarea->win, REDRAW, 1); -} - -/* **************************************************** */ |