
- border select initiated in the channel names border selects the channels and constraint channels. - right click or border select initiated in the horizontal scroll causes blender to select all keys for the selected frames. - right click or border select in the vertical scroll causes blender to select all keys for the channel or constraint channels that are to the left of the selection.
1661 lines
41 KiB
C
1661 lines
41 KiB
C
/**
|
|
* $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"
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
/* 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(int selectmode);
|
|
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(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) {
|
|
if(G.qual & LR_SHIFTKEY)
|
|
mouse_nla(SELECT_INVERT);
|
|
else
|
|
mouse_nla(SELECT_REPLACE);
|
|
}
|
|
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:
|
|
case WHEELUPMOUSE:
|
|
case WHEELDOWNMOUSE:
|
|
view2dmove(event); /* 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 */
|
|
calc_memleak(¶m); /* enable NLA */
|
|
}
|
|
|
|
static void convert_nla(short mval[2])
|
|
{
|
|
short event;
|
|
float ymax, ymin;
|
|
Base *base;
|
|
float x,y;
|
|
int sel=0;
|
|
bActionStrip *strip, *nstrip;
|
|
/* 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;
|
|
float ymin, ymax;
|
|
float x, y;
|
|
rctf rectf;
|
|
short event;
|
|
char *str;
|
|
short nr;
|
|
int cur;
|
|
|
|
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 (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;
|
|
|
|
/* 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 (!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;
|
|
|
|
/* 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, selectmode;
|
|
short mval[2];
|
|
float ymin, ymax;
|
|
bActionStrip *strip;
|
|
bConstraintChannel *conchan;
|
|
|
|
if ( (val = get_border (&rect, 3)) ){
|
|
if (val == LEFTMOUSE)
|
|
selectmode = SELECT_ADD;
|
|
else
|
|
selectmode = 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 = 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,
|
|
selectmode);
|
|
}
|
|
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,
|
|
selectmode);
|
|
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,
|
|
selectmode);
|
|
/* Check action constraint ipos */
|
|
for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
|
|
borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax,
|
|
selectmode);
|
|
}
|
|
}
|
|
}
|
|
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(int selectmode)
|
|
{
|
|
short sel;
|
|
float selx;
|
|
short mval[2];
|
|
Base *base;
|
|
bAction *act;
|
|
bActionChannel *chan;
|
|
bActionStrip *rstrip;
|
|
bConstraintChannel *conchan;
|
|
|
|
getmouseco_areawin (mval);
|
|
|
|
/* Try object ipo selection */
|
|
base=get_nearest_nlachannel_ob_key(&selx, &sel);
|
|
if (base){
|
|
if (selectmode == SELECT_REPLACE){
|
|
deselect_nlachannel_keys(0);
|
|
selectmode = SELECT_ADD;
|
|
}
|
|
|
|
select_ipo_key(base->object->ipo, selx, selectmode);
|
|
|
|
/* Try object constraint selection */
|
|
for (conchan=base->object->constraintChannels.first; conchan; conchan=conchan->next)
|
|
select_ipo_key(conchan->ipo, selx, selectmode);
|
|
|
|
|
|
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 (selectmode == SELECT_REPLACE){
|
|
deselect_nlachannel_keys(0);
|
|
selectmode = SELECT_ADD;
|
|
}
|
|
|
|
for (chan=act->chanbase.first; chan; chan=chan->next){
|
|
select_ipo_key(chan->ipo, selx, selectmode);
|
|
/* Try action constraint selection */
|
|
for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next)
|
|
select_ipo_key(conchan->ipo, selx, selectmode);
|
|
}
|
|
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
|
|
*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;
|
|
}
|
|
|
|
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;
|
|
|
|
*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;
|
|
}
|
|
|
|
static bActionStrip *get_active_nlastrip(void)
|
|
/* For now just returns the first selected strip */
|
|
{
|
|
Base *base;
|
|
bActionStrip *strip;
|
|
|
|
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;
|
|
}
|
|
|
|
void clever_numbuts_nla(void){
|
|
bActionStrip *strip;
|
|
int but=0;
|
|
|
|
/* 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|