diff options
Diffstat (limited to 'source/blender/src/editnla.c')
-rw-r--r-- | source/blender/src/editnla.c | 1738 |
1 files changed, 1738 insertions, 0 deletions
diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c new file mode 100644 index 00000000000..54ee4682c0e --- /dev/null +++ b/source/blender/src/editnla.c @@ -0,0 +1,1738 @@ +/** +* $Id$ +* + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +* This file is a horrible mess: An attmept to cram some +* final functionality into blender before it is too late. +* +* Hopefully it can be tidied up at a later date... +*/ + +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#include "PIL_time.h" + +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_library.h" +#include "BKE_nla.h" +#include "BKE_action.h" + +#include "BIF_screen.h" +#include "BIF_interface.h" +#include "BIF_buttons.h" +#include "BIF_space.h" +#include "BIF_mywindow.h" +#include "BIF_editview.h" +#include "BIF_toolbox.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" +#include "DNA_ipo_types.h" +#include "DNA_curve_types.h" +#include "DNA_object_types.h" +#include "DNA_userdef_types.h" +#include "DNA_action_types.h" +#include "DNA_nla_types.h" +#include "DNA_constraint_types.h" + +#include "BSE_editipo.h" +#include "BSE_editnla_types.h" +#include "BSE_headerbuttons.h" +#include "BSE_drawipo.h" +#include "BSE_trans_types.h" +#include "BSE_edit.h" +#include "BDR_editobject.h" + +#include "interface.h" +#include "blendef.h" +#include "mydevice.h" +#include "blendertimer.h" +#include "license_key.h" +#include "keyed_functions.h" + +/* Note: A lot of these pretty much duplicate the behaviour of the +action windows. The functions should be shared, not copy-pasted */ +typedef struct NlaParam{ + SpaceNla *snla; + unsigned short event; + short val; +}NlaParam; + +static void deselect_nlachannel_keys (int test); +static void deselect_nlachannels(int test); +static void transform_nlachannel_keys(char mode); +static void delete_nlachannel_keys(void); +static void delete_nlachannels(void); +static void duplicate_nlachannel_keys(void); +static void borderselect_nla(void); +static void mouse_nla(void); +static Base *get_nearest_nlachannel_ob_key (float *index, short *sel); +static bAction *get_nearest_nlachannel_ac_key (float *index, short *sel); +static Base *get_nearest_nlastrip (bActionStrip **rstrip, short *sel); + +static void mouse_nlachannels(short mval[2]); +static void add_nlablock(short mval[2]); +static bActionStrip *get_active_nlastrip(void); +static void convert_nla(short mval[2]); + +extern int count_nla_levels(void); /* From drawnla.c */ +extern int nla_filter (Base* base, int flags); /* From drawnla.c */ + +/* ******************** SPACE: NLA ********************** */ + +/* Protected creator function */ +int calc_memleak (void* ptr){ + int doredraw= 0; + short mval[2]; + float dx,dy; + int cfra; + SpaceNla *snla; + NlaParam *params=(NlaParam*) ptr; + unsigned short event; + short val ; + + if (!ptr) + return -1; + + snla= params->snla; + event = params->event; + val = params->val; + + if (LICENSE_KEY_VALID){ + if(curarea->win==0) return 0; + + if (!snla) + return 0; + + if(val) { + if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0; + + getmouseco_areawin(mval); + + switch(event) { + case UI_BUT_EVENT: + do_blenderbuttons(val); + break; + case HOMEKEY: + do_nla_buttons(B_NLAHOME); + break; + case DKEY: + if (G.qual & LR_SHIFTKEY && mval[0]>=NLAWIDTH){ + duplicate_nlachannel_keys(); + update_for_newframe(); + } + break; + case DELKEY: + case XKEY: + if (mval[0]>=NLAWIDTH) + delete_nlachannel_keys (); + else + delete_nlachannels(); + update_for_newframe(); + break; + case GKEY: + if (mval[0]>=NLAWIDTH) + transform_nlachannel_keys ('g'); + update_for_newframe(); + break; + case SKEY: + if (mval[0]>=NLAWIDTH) + transform_nlachannel_keys ('s'); + update_for_newframe(); + break; + case BKEY: + borderselect_nla(); + break; + case CKEY: + convert_nla(mval); + break; + + case AKEY: + if (G.qual & LR_SHIFTKEY){ + add_nlablock(mval); + allqueue (REDRAWNLA, 0); + allqueue (REDRAWVIEW3D, 0); + } + else{ + if (mval[0]>=NLAWIDTH) + deselect_nlachannel_keys(1); + else{ + deselect_nlachannels(1); + allqueue (REDRAWVIEW3D, 0); + } + allqueue (REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); + } + break; + case RIGHTMOUSE: + if (mval[0]>=NLAWIDTH) + mouse_nla(); + else + mouse_nlachannels(mval); + break; + case LEFTMOUSE: + if (mval[0]>NLAWIDTH){ + do { + getmouseco_areawin(mval); + + areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); + + cfra= (int)dx; + if(cfra< 1) cfra= 1; + + if( cfra!=CFRA ) { + CFRA= cfra; + update_for_newframe(); + force_draw_plus(SPACE_VIEW3D); + force_draw_plus(SPACE_IPO); + } + + } while(get_mbut()&L_MOUSE); + } + + break; + case MIDDLEMOUSE: + view2dmove(); /* in drawipo.c */ + break; + } + } + + if(doredraw) scrarea_queue_winredraw(curarea); + } + return 0; +} + +void winqreadnlaspace(unsigned short event, short val, char ascii) +{ + NlaParam param; + Base *base; + bActionStrip *strip, *next; + short mval[2]; + float dx, dy; + int cfra; + + param.event = event; + param.val = val; + param.snla = curarea->spacedata.first; + + + /* Call the protected (&obfuscated) eventloop function */ + if (KEY_NLA_EVENT){ + KEY_NLA_EVENT(¶m); + } + else{ + getmouseco_areawin(mval); + switch(event) { + case GKEY: + case SKEY: + case AKEY: + case CKEY: + case NKEY: + case RIGHTMOUSE: + notice ("NLA window editing only available in Blender Publisher"); + break; + case LEFTMOUSE: + if (mval[0]>NLAWIDTH){ + do { + getmouseco_areawin(mval); + + areamouseco_to_ipoco(G.v2d, mval, &dx, &dy); + + cfra= (int)dx; + if(cfra< 1) cfra= 1; + + if( cfra!=CFRA ) { + CFRA= cfra; + update_for_newframe(); + force_draw_plus(SPACE_VIEW3D); + force_draw_plus(SPACE_IPO); + } + + } while(get_mbut()&L_MOUSE); + } + + break; + case MIDDLEMOUSE: + view2dmove(); /* in drawipo.c */ + break; + case DELKEY: + case XKEY: + if (okee ("This will remove all NLA information from all objects!")){ + for (base = G.scene->base.first; base; base=base->next){ + for (strip=base->object->nlastrips.first; strip; strip=next){ + next=strip->next; + free_actionstrip(strip); + BLI_freelinkN(&base->object->nlastrips, strip); + } + } + update_for_newframe(); + } + break; + + default: + break; + } + } +} + +static void convert_nla(short mval[2]) +{ + short event; + float ymax, ymin; + Base *base; + float x,y; + int sel=0; + bActionStrip *strip, *nstrip; + if (LICENSE_KEY_VALID){ + /* Find out what strip we're over */ + ymax = count_nla_levels() * (NLACHANNELSKIP+NLACHANNELHEIGHT); + areamouseco_to_ipoco(G.v2d, mval, &x, &y); + + for (base=G.scene->base.first; base; base=base->next){ + if (nla_filter(base, 0)){ + /* Check object ipo */ + ymin=ymax-(NLACHANNELSKIP+NLACHANNELHEIGHT); + if (y>=ymin && y<=ymax) + break; + ymax=ymin; + + if (base->object->type==OB_ARMATURE){ + /* Check action ipo */ + ymin=ymax-(NLACHANNELSKIP+NLACHANNELHEIGHT); + if (y>=ymin && y<=ymax) + break; + ymax=ymin; + + /* Check nlastrips */ + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + ymin=ymax-(NLACHANNELSKIP+NLACHANNELHEIGHT); + if (y>=ymin && y<=ymax){ + sel = 1; + break; + } + ymax=ymin; + } + if (sel) + break; + } + } + } + + if (!base) + return; + + if (base->object->type==OB_ARMATURE){ + event = pupmenu("Convert%t|Action to NLAstrip%x1"); + switch (event){ + case 1: + if (base->object->action){ + /* Make new actionstrip */ + nstrip = MEM_callocN(sizeof(bActionStrip), "bActionStrip"); + + deselect_nlachannel_keys(0); + + /* Link the action to the nstrip */ + nstrip->act = base->object->action; + nstrip->actstart = calc_action_start(base->object->action); /* MAKE THIS THE FIRST FRAME OF THE ACTION */ + nstrip->actend = calc_action_end(base->object->action); + nstrip->start = nstrip->actstart; + nstrip->end = nstrip->actend; + nstrip->flag = ACTSTRIP_SELECT; + nstrip->repeat = 1.0; + + BLI_addtail(&base->object->nlastrips, nstrip); + + /* Unlink action */ + base->object->action = NULL; + + allqueue (REDRAWNLA, 0); + } + + + break; + default: + break; + } + } + } +} + +static void add_nlablock(short mval[2]) +{ + /* Make sure we are over an armature */ + Base *base; + bAction *act=NULL; + bActionStrip *strip; + int foundsel=0; + float ymin, ymax; + float x, y; + rctf rectf; + short event; + char *str; + short nr; + int cur; + + if (LICENSE_KEY_VALID){ + areamouseco_to_ipoco(G.v2d, mval, &x, &y); + + 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); + + ymax = count_nla_levels(); + ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP); + + for (base=G.scene->base.first; base; base=base->next){ + /* Handle object ipo selection */ + if (nla_filter(base, 0)){ + + /* STUPID STUPID STUPID */ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + + /* Handle object ipos */ + if (base->object->type==OB_ARMATURE){ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) + break; + } + + ymax=ymin; + + /* Handle action ipos & Action strips */ + if (base->object->type==OB_ARMATURE){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP)*(BLI_countlist(&base->object->nlastrips) + 1); + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) + break; + ymax=ymin; + + + } + } + } + + /* Make sure we have an armature */ + if (!base){ + error ("Not an armature!"); + return; + } + + /* Popup action menu */ + IDnames_to_pupstring(&str, "Add action", NULL, &G.main->action, (ID *)G.scene, &nr); + + event = pupmenu(str); + + if (event!=-1){ + for (cur = 1, act=G.main->action.first; act; act=act->id.next, cur++){ + if (cur==event){ + break; + } + } + } + + MEM_freeN(str); + + /* Bail out if no action was chosen */ + if (!act){ + return; + } + + /* Initialize the new action block */ + strip = MEM_callocN(sizeof(bActionStrip), "bActionStrip"); + + deselect_nlachannel_keys(0); + + /* Link the action to the strip */ + strip->act = act; + strip->actstart = 1.0; + strip->actend = calc_action_end(act); + strip->start = G.scene->r.cfra; /* Should be mval[0] */ + strip->end = strip->start + (strip->actend-strip->actstart); + strip->flag = ACTSTRIP_SELECT; + strip->repeat = 1.0; + + act->id.us++; + + BLI_addtail(&base->object->nlastrips, strip); + } +} + +static void mouse_nlachannels(short mval[2]) +{ + /* Find which strip has been clicked */ +// bActionChannel *chan; + bConstraintChannel *conchan=NULL; + bActionStrip *strip; + float click; + int wsize; + int sel; + Base *base; + + wsize = (count_nla_levels ()*(NLACHANNELHEIGHT+NLACHANNELSKIP)); + + + click = (wsize-(mval[1]+G.v2d->cur.ymin)); + click += NLACHANNELHEIGHT/2; + click /= (NLACHANNELHEIGHT+NLACHANNELSKIP); + + if (click<0) + return; + + for (base = G.scene->base.first; base; base=base->next){ + if (nla_filter(base, 0)){ + /* See if this is a base selected */ + if ((int)click==0) + break; + + click--; + + /* Check for click in a constraint */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + if ((int)click==0){ + base=G.scene->base.last; + break; + } + click--; + } + + /* See if this is an action */ + if (base->object->type==OB_ARMATURE && base->object->action){ + if ((int)click==0){ + break; + } + click--; + } + + /* See if this is an nla strip */ + for (strip = base->object->nlastrips.first; strip; strip=strip->next){ + if ((int)click==0){ + base=G.scene->base.last; + break; + } + click--; + } + } + } + + if (!base && !conchan) + return; + + /* Handle constraint strip selection */ + if (conchan){ + if (conchan->flag & CONSTRAINT_CHANNEL_SELECT) + sel = 0; + else + sel =1; + + /* Channel names clicking */ + if (G.qual & LR_SHIFTKEY){ + // select_poseelement_by_name(chan->name, !(chan->flag & ACHAN_SELECTED)); + if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){ + conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT; + // hilight_channel(act, chan, 0); + } + else{ + conchan->flag |= CONSTRAINT_CHANNEL_SELECT; + // hilight_channel(act, chan, 1); + } + } + else{ + deselect_nlachannels (0); // Auto clear + conchan->flag |= CONSTRAINT_CHANNEL_SELECT; + // hilight_channel(act, chan, 1); + // act->achan = chan; + // select_poseelement_by_name(chan->name, 1); + } + + } + + /* Handle object strip selection */ + else if (base) + { + /* Choose the mode */ + if (base->flag & SELECT) + sel = 0; + else + sel =1; + + /* Channel names clicking */ + if (G.qual & LR_SHIFTKEY){ + // select_poseelement_by_name(chan->name, !(chan->flag & ACHAN_SELECTED)); + if (base->flag & SELECT){ + base->flag &= ~SELECT; + // hilight_channel(act, chan, 0); + } + else{ + base->flag |= SELECT; + // hilight_channel(act, chan, 1); + } + } + else{ + deselect_nlachannels (0); // Auto clear + base->flag |= SELECT; + // hilight_channel(act, chan, 1); + // act->achan = chan; + // select_poseelement_by_name(chan->name, 1); + } + + } + allqueue (REDRAWIPO, 0); + allqueue (REDRAWVIEW3D, 0); + allqueue (REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + +} + +void init_nlaspace(ScrArea *sa) +{ + SpaceNla *snla; + + snla= MEM_callocN(sizeof(SpaceNla), "initnlaspace"); + BLI_addhead(&sa->spacedata, snla); + + snla->spacetype= SPACE_NLA; + + snla->v2d.tot.xmin= 1.0; + snla->v2d.tot.ymin= 0.0; + snla->v2d.tot.xmax= 1000.0; + snla->v2d.tot.ymax= 1000.0; + + snla->v2d.cur.xmin= -5.0; + snla->v2d.cur.ymin= 0.0; + snla->v2d.cur.xmax= 65.0; + snla->v2d.cur.ymax= 1000.0; + + snla->v2d.min[0]= 0.0; + snla->v2d.min[1]= 0.0; + + snla->v2d.max[0]= 1000.0; + snla->v2d.max[1]= 1000.0; + + snla->v2d.minzoom= 0.1F; + snla->v2d.maxzoom= 10; + + snla->v2d.scroll= R_SCROLL+B_SCROLL; + snla->v2d.keepaspect= 0; + snla->v2d.keepzoom= V2D_LOCKZOOM_Y; + snla->v2d.keeptot= 0; + + snla->lock = 0; +}; + +static void deselect_nlachannel_keys (int test) +{ + Base *base; + int sel=1; + bActionChannel *chan; + bActionStrip *strip; + bConstraintChannel *conchan; + + /* Determine if this is selection or deselection */ + if (LICENSE_KEY_VALID){ + if (test){ + for (base=G.scene->base.first; base && sel; base=base->next){ + + /* Test object ipos */ + if (is_ipo_key_selected(base->object->ipo)){ + sel = 0; + break; + } + + /* Test object constraint ipos */ + if (sel){ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + if (is_ipo_key_selected(conchan->ipo)){ + sel=0; + break; + } + } + } + + /* Test action ipos */ + if (sel){ + if (base->object->type==OB_ARMATURE && base->object->action){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + if (is_ipo_key_selected(chan->ipo)){ + sel=0; + break; + } + + /* Test action constraints */ + if (sel){ + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){ + if (is_ipo_key_selected(conchan->ipo)){ + sel=0; + break; + } + } + } + } + } + } + + /* Test NLA strips */ + if (sel){ + if (base->object->type==OB_ARMATURE){ + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + if (strip->flag & ACTSTRIP_SELECT){ + sel = 0; + break; + } + } + } + } + } + } + else + sel=0; + + + /* Set the flags */ + for (base=G.scene->base.first; base; base=base->next){ + /* Set the object ipos */ + set_ipo_key_selection(base->object->ipo, sel); + + + /* Set the object constraint ipos */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + set_ipo_key_selection(conchan->ipo, sel); + } + + /* Set the action ipos */ + if (base->object->type==OB_ARMATURE && base->object->action){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + set_ipo_key_selection(chan->ipo, sel); + /* Set the action constraint ipos */ + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) + set_ipo_key_selection(conchan->ipo, sel); + } + } + + /* Set the nlastrips */ + if (base->object->type==OB_ARMATURE){ + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + if (sel) + strip->flag |= ACTSTRIP_SELECT; + else + strip->flag &= ~ACTSTRIP_SELECT; + } + } + } + } +} + + +static void transform_nlachannel_keys(char mode) +{ + Base *base; + TransVert *tv; + int /*sel=0,*/ i; + short mvals[2], mvalc[2]; + // short cent[2]; + float sval[2], cval[2], lastcval[2]; + short cancel=0; + float fac=0.0F; + int loop=1; + int tvtot=0; + float deltax, startx; + // float cenf[2]; + int invert=0, firsttime=1; + char str[256]; + bActionChannel *chan; + bActionStrip *strip; + bConstraintChannel *conchan; + + if (LICENSE_KEY_VALID){ + /* Ensure that partial selections result in beztriple selections */ + for (base=G.scene->base.first; base; base=base->next){ + + /* Check object ipos */ + tvtot+=fullselect_ipo_keys(base->object->ipo); + + /* Check object constraint ipos */ + for(conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next) + tvtot+=fullselect_ipo_keys(conchan->ipo); + + /* Check action ipos */ + if (base->object->type == OB_ARMATURE && base->object->action){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + tvtot+=fullselect_ipo_keys(chan->ipo); + + /* Check action constraint ipos */ + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) + tvtot+=fullselect_ipo_keys(conchan->ipo); + } + + } + + /* Check nlastrips */ + if (base->object->type==OB_ARMATURE){ + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + if (strip->flag & ACTSTRIP_SELECT) + tvtot+=2; + } + } + } + + /* If nothing is selected, bail out */ + if (!tvtot) + return; + + + /* Build the transvert structure */ + tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert"); + tvtot=0; + for (base=G.scene->base.first; base; base=base->next){ + /* Manipulate object ipos */ + tvtot=add_trans_ipo_keys(base->object->ipo, tv, tvtot); + + /* Manipulate object constraint ipos */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next) + tvtot=add_trans_ipo_keys(conchan->ipo, tv, tvtot); + + /* Manipulate action ipos */ + if (base->object->type==OB_ARMATURE && base->object->action){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + tvtot=add_trans_ipo_keys(chan->ipo, tv, tvtot); + + /* Manipulate action constraint ipos */ + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) + tvtot=add_trans_ipo_keys(conchan->ipo, tv, tvtot); + } + } + + /* Manipulate nlastrips */ + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + if (strip->flag & ACTSTRIP_SELECT){ + tv[tvtot+0].val=&strip->start; + tv[tvtot+1].val=&strip->end; + + tv[tvtot+0].oldval = strip->start; + tv[tvtot+1].oldval = strip->end; + + tvtot+=2; + } + } + } + + /* Do the event loop */ + // cent[0] = curarea->winx + (G.snla->v2d.hor.xmax)/2; + // cent[1] = curarea->winy + (G.snla->v2d.hor.ymax)/2; + + // areamouseco_to_ipoco(cent, &cenf[0], &cenf[1]); + + getmouseco_areawin (mvals); + areamouseco_to_ipoco(G.v2d, mvals, &sval[0], &sval[1]); + + startx=sval[0]; + while (loop) { + /* Get the input */ + /* If we're cancelling, reset transformations */ + /* Else calc new transformation */ + /* Perform the transformations */ + while (qtest()) { + short val; + unsigned short event= extern_qread(&val); + + if (val) { + switch (event) { + case LEFTMOUSE: + case SPACEKEY: + case RETKEY: + loop=0; + break; + case XKEY: + break; + case ESCKEY: + case RIGHTMOUSE: + cancel=1; + loop=0; + break; + default: + arrows_move_cursor(event); + break; + }; + } + } + + if (cancel) { + for (i=0; i<tvtot; i++) { + if (tv[i].loc){ + tv[i].loc[0]=tv[i].oldloc[0]; + tv[i].loc[1]=tv[i].oldloc[1]; + } + if (tv[i].val) + tv[i].val[0]=tv[i].oldval; + } + } + else { + getmouseco_areawin (mvalc); + areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]); + + if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) { + PIL_sleep_ms(1); + } + else { + for (i=0; i<tvtot; i++){ + if (tv[i].loc) + tv[i].loc[0]=tv[i].oldloc[0]; + if (tv[i].val) + tv[i].val[0]=tv[i].oldval; + + switch (mode){ + case 'g': + deltax = cval[0]-sval[0]; + fac= deltax; + + apply_keyb_grid(&fac, 0.0F, 1.0F, 0.1F, U.flag & AUTOGRABGRID); + + if (tv[i].loc) + tv[i].loc[0]+=fac; + if (tv[i].val) + tv[i].val[0]+=fac; + break; + case 's': + startx=mvals[0]-(NLAWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2); + deltax=mvalc[0]-(NLAWIDTH/2+(curarea->winrct.xmax-curarea->winrct.xmin)/2); + fac= (float)fabs(deltax/startx); + + apply_keyb_grid(&fac, 0.0F, 0.2F, 0.1F, U.flag & AUTOSIZEGRID); + + if (invert){ + if (i % 03 == 0){ + memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i+2].oldloc)); + } + if (i % 03 == 2){ + memcpy (tv[i].loc, tv[i].oldloc, sizeof(tv[i-2].oldloc)); + } + + fac*=-1; + } + startx= (G.scene->r.cfra); + + if (tv[i].loc){ + tv[i].loc[0]-= startx; + tv[i].loc[0]*=fac; + tv[i].loc[0]+= startx; + } + if (tv[i].val){ + tv[i].val[0]-= startx; + tv[i].val[0]*=fac; + tv[i].val[0]+= startx; + } + + break; + } + } + } + + if (mode=='s'){ + sprintf(str, "sizeX: %.3f", fac); + headerprint(str); + } + else if (mode=='g'){ + sprintf(str, "deltaX: %.3f", fac); + headerprint(str); + } + + if (G.snla->lock){ + allqueue (REDRAWVIEW3D, 0); + allqueue (REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); + force_draw_all(); + } + else { + addqueue (curarea->win, REDRAWALL, 0); + force_draw (); + } + } + + lastcval[0]= cval[0]; + lastcval[1]= cval[1]; + firsttime= 0; + } + + allspace(REMAKEALLIPO, 0); + allqueue (REDRAWVIEW3D, 0); + allqueue (REDRAWNLA, 0); + allqueue (REDRAWIPO, 0); + MEM_freeN (tv); + } +} + +static void delete_nlachannel_keys(void) +{ + Base *base; + bActionChannel *chan; + bConstraintChannel *conchan; + bActionStrip *strip, *nextstrip; + + if (LICENSE_KEY_VALID){ + if (!okee("Erase selected keys")) + return; + + for (base = G.scene->base.first; base; base=base->next){ + + /* Delete object ipos */ + delete_ipo_keys(base->object->ipo); + + /* Delete object constraint keys */ + for(conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next) + delete_ipo_keys(conchan->ipo); + + /* Delete NLA strips */ + if (base->object->type==OB_ARMATURE){ + for (strip = base->object->nlastrips.first; strip; strip=nextstrip){ + nextstrip=strip->next; + if (strip->flag & ACTSTRIP_SELECT){ + free_actionstrip(strip); + BLI_remlink(&base->object->nlastrips, strip); + MEM_freeN(strip); + } + } + } + + /* Delete action ipos */ + if (base->object->type==OB_ARMATURE && base->object->action){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + delete_ipo_keys(chan->ipo); + /* Delete action constraint keys */ + for(conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) + delete_ipo_keys(conchan->ipo); + } + } + } + + allspace(REMAKEALLIPO, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWIPO, 0); + } +} + +static void duplicate_nlachannel_keys(void) +{ + Base *base; + bActionChannel *chan; + bConstraintChannel *conchan; + bActionStrip *strip, *laststrip; + if (LICENSE_KEY_VALID){ + + /* Find selected items */ + for (base = G.scene->base.first; base; base=base->next){ + /* Duplicate object keys */ + duplicate_ipo_keys(base->object->ipo); + + /* Duplicate object constraint keys */ + for(conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next) + duplicate_ipo_keys(conchan->ipo); + + /* Duplicate nla strips */ + if (base->object->type == OB_ARMATURE){ + laststrip = base->object->nlastrips.last; + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + if (strip->flag & ACTSTRIP_SELECT){ + bActionStrip *newstrip; + + copy_actionstrip(&newstrip, &strip); + + BLI_addtail(&base->object->nlastrips, newstrip); + + strip->flag &= ~ACTSTRIP_SELECT; + newstrip->flag |= ACTSTRIP_SELECT; + + } + if (strip==laststrip) + break; + } + } + + /* Duplicate actionchannel keys */ + if (base->object->type == OB_ARMATURE && base->object->action){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + duplicate_ipo_keys(chan->ipo); + /* Duplicate action constraint keys */ + for(conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) + duplicate_ipo_keys(conchan->ipo); + } + } + } + + transform_nlachannel_keys ('g'); + } +} + +static void borderselect_nla(void) +{ + Base *base; + rcti rect; + rctf rectf; + int val; + short mval[2]; + float ymin, ymax; + bActionStrip *strip; + bConstraintChannel *conchan; + + if (LICENSE_KEY_VALID){ + val= get_border (&rect, 3); + + if (val){ + 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 = count_nla_levels(); + ymax*= (NLACHANNELHEIGHT+NLACHANNELSKIP); + + for (base=G.scene->base.first; base; base=base->next){ + /* Check object ipos */ + if (nla_filter(base, 0)){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + if (base->object->ipo){ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) + borderselect_ipo_key(base->object->ipo, rectf.xmin, rectf.xmax, val); + } + ymax=ymin; + + /* Check object constraint ipos */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) + borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, val); + ymax=ymin; + } + + /* Check action ipos */ + if (ACTIVE_ARMATURE(base)){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + if (base->object->action){ + bActionChannel *chan; + + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + borderselect_ipo_key(chan->ipo, rectf.xmin, rectf.xmax, val); + /* Check action constraint ipos */ + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) + borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, val); + } + } + } + ymax=ymin; + } /* End of if armature */ + + /* Skip nlastrips */ + if (base->object->type==OB_ARMATURE){ + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + // + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){ + if (!((rectf.xmax<strip->start) || (rectf.xmin>strip->end))){ + if (val==1) + strip->flag |= ACTSTRIP_SELECT; + else + strip->flag &= ~ACTSTRIP_SELECT; + } + } + + ymax=ymin; + } + } + + } /* End of object filter */ + } + allqueue(REDRAWNLA, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWIPO, 0); + } + } +} + +static void mouse_nla(void) +{ + short sel; + float selx; + short mval[2]; + Base *base; + bAction *act; + bActionChannel *chan; + bActionStrip *rstrip; + bConstraintChannel *conchan; + + if (LICENSE_KEY_VALID){ + getmouseco_areawin (mval); + + /* Try object ipo selection */ + base=get_nearest_nlachannel_ob_key(&selx, &sel); + if (base){ + if (!(G.qual & LR_SHIFTKEY)){ + deselect_nlachannel_keys(0); + sel = 0; + } + + select_ipo_key(base->object->ipo, selx, sel); + + /* Try object constraint selection */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next) + select_ipo_key(conchan->ipo, selx, sel); + + + allqueue(REDRAWIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWNLA, 0); + return; + } + + /* Try action ipo selection */ + act=get_nearest_nlachannel_ac_key(&selx, &sel); + if (act){ + if (!(G.qual & LR_SHIFTKEY)){ + deselect_nlachannel_keys(0); + sel = 0; + } + + for (chan=act->chanbase.first; chan; chan=chan->next){ + select_ipo_key(chan->ipo, selx, sel); + /* Try action constraint selection */ + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) + select_ipo_key(conchan->ipo, selx, sel); + } + + allqueue(REDRAWIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWNLA, 0); + return; + } + + /* Try nla strip selection */ + base=get_nearest_nlastrip(&rstrip, &sel); + if (base){ + if (!(G.qual & LR_SHIFTKEY)){ + deselect_nlachannel_keys(0); + sel = 0; + } + + if (sel) + rstrip->flag &= ~ACTSTRIP_SELECT; + else + rstrip->flag |= ACTSTRIP_SELECT; + + allqueue(REDRAWIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWNLA, 0); + return; + + } + + } + +} + +static Base *get_nearest_nlastrip (bActionStrip **rstrip, short *sel) +/* This function is currently more complicated than it seems like it should be. +* However, this will be needed once the nla strip timeline is more complex */ +{ + Base *base, *firstbase=NULL; + short mval[2]; + short foundsel = 0; + rctf rectf; + float ymin, ymax; + bActionStrip *strip, *firststrip, *foundstrip; + + if (LICENSE_KEY_VALID){ + getmouseco_areawin (mval); + + mval[0]-=7; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + + mval[0]+=14; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); + + ymax = count_nla_levels(); + ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP); + + for (base = G.scene->base.first; base; base=base->next){ + if (nla_filter(base, 0)){ + /* Skip object ipos */ + // if (base->object->ipo) + ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP); + + if (base->object->type==OB_ARMATURE){ + /* Skip action ipos */ + if (base->object->action) + ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP); + + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + /* Do Ytest */ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){ + /* Do XTest */ + if (!((rectf.xmax<strip->start) || (rectf.xmin>strip->end))){ + if (!firstbase){ + firstbase=base; + firststrip=strip; + *sel = strip->flag & ACTSTRIP_SELECT; + } + + if (strip->flag & ACTSTRIP_SELECT){ + if (!foundsel){ + foundsel=1; + foundstrip = strip; + } + } + else if (foundsel && strip != foundstrip){ + *rstrip=strip; + *sel = 0; + return base; + } + } + } + ymax=ymin; + } + } + } + } + *rstrip=firststrip; + return firstbase; + } + else + return NULL; +} + +static Base *get_nearest_nlachannel_ob_key (float *index, short *sel) +{ + Base *base; + IpoCurve *icu; + Base *firstbase=NULL; + bConstraintChannel *conchan; + int foundsel=0; + float firstvert=-1, foundx=-1; + int i; + short mval[2]; + float ymin, ymax; + rctf rectf; + + if (LICENSE_KEY_VALID){ + *index=0; + + getmouseco_areawin (mval); + + mval[0]-=7; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + + mval[0]+=14; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); + + ymax = count_nla_levels(); + + ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP); + + *sel=0; + + for (base=G.scene->base.first; base; base=base->next){ + /* Handle object ipo selection */ + if (nla_filter(base, 0)){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + if (base->object->ipo){ + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){ + for (icu=base->object->ipo->curve.first; icu; icu=icu->next){ + for (i=0; i<icu->totvert; i++){ + if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){ + if (!firstbase){ + firstbase=base; + firstvert=icu->bezt[i].vec[1][0]; + *sel = icu->bezt[i].f2 & 1; + } + + if (icu->bezt[i].f2 & 1){ + if (!foundsel){ + foundsel=1; + foundx = icu->bezt[i].vec[1][0]; + } + } + else if (foundsel && icu->bezt[i].vec[1][0] != foundx){ + *index=icu->bezt[i].vec[1][0]; + *sel = 0; + return base; + } + } + } + } + } + } + + ymax=ymin; + + /* Handle object constraint ipos */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){ + for (icu=conchan->ipo->curve.first; icu; icu=icu->next){ + for (i=0; i<icu->totvert; i++){ + if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){ + if (!firstbase){ + firstbase=base; + firstvert=icu->bezt[i].vec[1][0]; + *sel = icu->bezt[i].f2 & 1; + } + + if (icu->bezt[i].f2 & 1){ + if (!foundsel){ + foundsel=1; + foundx = icu->bezt[i].vec[1][0]; + } + } + else if (foundsel && icu->bezt[i].vec[1][0] != foundx){ + *index=icu->bezt[i].vec[1][0]; + *sel = 0; + return base; + } + } + } + } + } + ymax=ymin; + } + + /* Skip action ipos */ + if (ACTIVE_ARMATURE(base)){ + ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP); + } + /* Skip nlastrips */ + if (base->object->type==OB_ARMATURE){ + ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP)*BLI_countlist(&base->object->nlastrips); + } + } + } + + *index=firstvert; + return firstbase; + } + else + return NULL; +} + +static bAction *get_nearest_nlachannel_ac_key (float *index, short *sel) +{ + Base *base; + IpoCurve *icu; + bAction *firstact=NULL; + int foundsel=0; + float firstvert=-1, foundx=-1; + int i; + short mval[2]; + float ymin, ymax; + rctf rectf; + bActionChannel *chan; + bConstraintChannel *conchan; + + if (LICENSE_KEY_VALID){ + *index=0; + + getmouseco_areawin (mval); + + mval[0]-=7; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin); + + mval[0]+=14; + areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax); + + ymax = count_nla_levels(); + + ymax*=(NLACHANNELHEIGHT + NLACHANNELSKIP); + + *sel=0; + + for (base=G.scene->base.first; base; base=base->next){ + /* Handle object ipo selection */ + if (nla_filter(base, 0)){ + /* Skip object ipo */ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + ymax=ymin; + + /* Handle action ipos */ + if (ACTIVE_ARMATURE(base)){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){ + for (chan=base->object->action->chanbase.first; chan; chan=chan->next){ + for (icu=chan->ipo->curve.first; icu; icu=icu->next){ + for (i=0; i<icu->totvert; i++){ + if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){ + if (!firstact){ + firstact=base->object->action; + firstvert=icu->bezt[i].vec[1][0]; + *sel = icu->bezt[i].f2 & 1; + } + + if (icu->bezt[i].f2 & 1){ + if (!foundsel){ + foundsel=1; + foundx = icu->bezt[i].vec[1][0]; + } + } + else if (foundsel && icu->bezt[i].vec[1][0] != foundx){ + *index=icu->bezt[i].vec[1][0]; + *sel = 0; + return base->object->action; + } + } + } + } + + + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){ + ymin=ymax-(NLACHANNELHEIGHT+NLACHANNELSKIP); + if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){ + for (icu=conchan->ipo->curve.first; icu; icu=icu->next){ + for (i=0; i<icu->totvert; i++){ + if (icu->bezt[i].vec[1][0] > rectf.xmin && icu->bezt[i].vec[1][0] <= rectf.xmax ){ + if (!firstact){ + firstact=base->object->action; + firstvert=icu->bezt[i].vec[1][0]; + *sel = icu->bezt[i].f2 & 1; + } + + if (icu->bezt[i].f2 & 1){ + if (!foundsel){ + foundsel=1; + foundx = icu->bezt[i].vec[1][0]; + } + } + else if (foundsel && icu->bezt[i].vec[1][0] != foundx){ + *index=icu->bezt[i].vec[1][0]; + *sel = 0; + return base->object->action; + } + } + } + } + } + ymax=ymin; + } + + + } + } + ymax=ymin; + } + + /* Skip nlastrips */ + if (base->object->type==OB_ARMATURE){ + ymax-=(NLACHANNELHEIGHT+NLACHANNELSKIP)*BLI_countlist(&base->object->nlastrips); + } + } + } + + *index=firstvert; + return firstact; + } + else + return NULL; +} + +static bActionStrip *get_active_nlastrip(void) +/* For now just returns the first selected strip */ +{ + Base *base; + bActionStrip *strip; + + if (LICENSE_KEY_VALID){ + for (base=G.scene->base.first; base; base=base->next){ + if (nla_filter(base, 0) && base->object->type==OB_ARMATURE){ + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + if (strip->flag & ACTSTRIP_SELECT) + return strip; + } + } + } + + return NULL; + } + else + return NULL; +} + +void clever_numbuts_nla(void){ + bActionStrip *strip; + int but=0; + if (LICENSE_KEY_VALID){ + + /* Determine if an nla strip has been selected */ + strip = get_active_nlastrip(); + if (!strip) + return; + + add_numbut(but++, LABEL, "Timeline Range:", 1.0, 18000.0, 0, 0); + add_numbut(but++, NUM|FLO, "Strip Start:", 1.0, 18000.0, &strip->start, "First frame in the timeline"); + add_numbut(but++, NUM|FLO, "Strip End:", 1.0, 18000.0, &strip->end, "Last frame in the timeline"); + add_numbut(but++, LABEL, "Action Range:", 1.0, 18000.0, 0, 0); + add_numbut(but++, NUM|FLO, "Action Start:", 1.0, 18000.0, &strip->actstart, "First frame of the action to map to the playrange"); + add_numbut(but++, NUM|FLO, "Action End:", 1.0, 18000.0, &strip->actend, "Last frame of the action to map to the playrange"); + add_numbut(but++, LABEL, "Blending:", 1.0, 18000.0, 0, 0); + add_numbut(but++, NUM|FLO, "Blendin:", 0.0, 18000.0, &strip->blendin, "Number of frames of ease-in"); + add_numbut(but++, NUM|FLO, "Blendout:", 0.0, 18000.0, &strip->blendout, "Number of frames of ease-out"); + add_numbut(but++, LABEL, "Options:", 1.0, 18000.0, 0, 0); + add_numbut(but++, NUM|FLO, "Repeat:", 0.0001, 18000.0, &strip->repeat, "Number of times the action should repeat"); + add_numbut(but++, NUM|FLO, "Stride:", 0.0001, 1000.0, &strip->stridelen, "Distance covered by one complete cycle of the action specified in the Action Range"); + { + /* STUPID HACK BECAUSE NUMBUTS ARE BROKEN WITH MULTIPLE TOGGLES */ + short hold= (strip->flag & ACTSTRIP_HOLDLASTFRAME) ? 1 : 0; + short frompath=(strip->flag & ACTSTRIP_USESTRIDE) ? 1 : 0; + + add_numbut(but++, TOG|SHO, "Use Path", 0, 0, &frompath, "Plays action based on position on path & stride length. Only valid for armatures that are parented to a path"); + add_numbut(but++, TOG|SHO, "Hold", 0, 0, &hold, "Toggles whether or not to continue displaying the last frame past the end of the strip"); + add_numbut(but++, TOG|SHO, "Add", 0, 0, &strip->mode, "Toggles additive blending mode"); + + do_clever_numbuts("Action", but, REDRAW); + + /* STUPID HACK BECAUSE NUMBUTS ARE BROKEN WITH MULTIPLE TOGGLES */ + if (hold) strip->flag |= ACTSTRIP_HOLDLASTFRAME; + else strip->flag &= ~ACTSTRIP_HOLDLASTFRAME; + + if (frompath) strip->flag |= ACTSTRIP_USESTRIDE; + else strip->flag &= ~ACTSTRIP_USESTRIDE; + + } + + if (strip->end<strip->start) + strip->end=strip->start; + + + if (strip->blendin>(strip->end-strip->start)) + strip->blendin = strip->end-strip->start; + + if (strip->blendout>(strip->end-strip->start)) + strip->blendout = strip->end-strip->start; + + if (strip->blendin > (strip->end-strip->start-strip->blendout)) + strip->blendin = (strip->end-strip->start-strip->blendout); + + if (strip->blendout > (strip->end-strip->start-strip->blendin)) + strip->blendout = (strip->end-strip->start-strip->blendin); + + + update_for_newframe(); + allqueue (REDRAWNLA, 0); + allqueue (REDRAWVIEW3D, 0); + } +} + +static void deselect_nlachannels(int test){ + int sel = 1; + Base *base; + bConstraintChannel *conchan; + + if (test){ + for (base=G.scene->base.first; base; base=base->next){ + /* Check base flags for previous selection */ + if (base->flag & SELECT){ + sel=0; + break; + } + + /* Check constraint flags for previous selection */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){ + sel=0; + base = G.scene->base.last; + break; + } + } + } + } + else + sel = 0; + + /* Select objects */ + for (base=G.scene->base.first; base; base=base->next){ + if (sel){ + if (nla_filter(base, 0)) + base->flag |= SELECT; + } + else + base->flag &= ~SELECT; + + /* Select constraint channels */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + if (sel){ + if (nla_filter(base, 0)) + conchan->flag |= CONSTRAINT_CHANNEL_SELECT; + } + else + conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT; + } + } +} + +static void delete_nlachannels(void){ + Base *base; + bConstraintChannel *conchan, *nextchan; + int sel=0; + + /* See if there is anything selected */ + for (base = G.scene->base.first; base && (!sel); base=base->next){ + /* Check constraints */ + for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next){ + if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){ + sel = 1; + break; + } + } + } + + if (!sel) + return; + + if (okee ("Delete selected channels")){ + for (base=G.scene->base.first; base; base=base->next){ + for (conchan=base->object->constraintChannels.first; conchan; conchan=nextchan){ + nextchan = conchan->next; + + if (conchan->flag & CONSTRAINT_CHANNEL_SELECT){ + /* If we're the active constraint, unlink us */ + if (conchan==base->object->activecon) + base->object->activecon = NULL; + + if (conchan->ipo) + conchan->ipo->id.us--; + BLI_freelinkN(&base->object->constraintChannels, conchan); + } + } + } + } +}
\ No newline at end of file |