Support for using the action window as a tool for modifying

(mesh or lattice) RVK IpoCurves: support currently includes:

	- RVK sliders. Pressing the little triangle next to
	  the word 'sliders' in the channel names opens them up.
	- NKEY in the area where the key block names are allows the
	  user to change the name of the keyblock, and the max and min
	  values of the RVK sliders.
	- ability to visualize the keyframes for the IpoCurves when
	  the object is selected.
	- right mouse can be used to select the keys
	- border select in the main area can be used to border
	  select keys.
	- AKEY selects/deselects all of the keys
	- GKEY and SKEY can be used to grab or scale the key
	  selections.
	- XKEY deletes the selected keys.
	- DKEY duplicated the selected keys.
	- VKEY, HKEY and shift-HKEY change the bezier handles for
	  the selected keys.

Please, please, please test!
This commit is contained in:
Chris Want
2003-07-20 23:04:09 +00:00
parent 9a9cb5448b
commit cf495e6655
11 changed files with 1418 additions and 192 deletions

View File

@@ -39,6 +39,7 @@ struct bPoseChannel;
struct Object;
struct Ipo;
struct BWinEvent;
struct Key;
struct bActionChannel* get_hilighted_action_channel(struct bAction* action);
void set_exprap_action(int mode);
@@ -49,10 +50,13 @@ void set_action_key (struct bAction *act, struct bPoseChannel *chan, int adrcode
struct bAction *add_empty_action(void);
void deselect_actionchannel_keys (struct bAction *act, int test);
void deselect_actionchannels (struct bAction *act, int test);
void deselect_meshchannel_keys (struct Key *key, int test);
void winqreadactionspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt);
void remake_action_ipos(struct bAction *act);
void select_actionchannel_by_name (struct bAction *act, char *name, int select);
struct bAction *bake_action_with_client (struct bAction *act, struct Object *arm, float tolerance);
struct Key *get_action_mesh_key(void);
int get_nearest_key_num(struct Key *key, short *mval, float *x);
void stupid_damn_numbuts_action(void);
#endif /* BSE_EDITACTION_H */

View File

@@ -35,7 +35,8 @@
#define CHANNELHEIGHT 16
#define CHANNELSKIP 2
#define ACTWIDTH 128
#define NAMEWIDTH 128
#define SLIDERWIDTH 125
#define CHANNEL_FILTER_LOC 0x00000001 /* Show location keys */
#define CHANNEL_FILTER_ROT 0x00000002 /* Show rotation keys */

View File

@@ -90,6 +90,7 @@ void move_to_frame(void);
void do_ipowin_buts(short event);
void do_ipo_selectbuttons(void);
struct EditIpo *get_editipo(void);
struct Ipo *get_ipo(struct ID *from, short type, int make);
struct IpoCurve *get_ipocurve(struct ID *from, short type, int adrcode, struct Ipo* useipo);
void insert_vert_ipo(struct IpoCurve *icu, float x, float y);
void add_vert_ipo(void);
@@ -116,6 +117,7 @@ void common_insertkey(void);
void free_ipokey(struct ListBase *lb);
void add_to_ipokey(struct ListBase *lb, struct BezTriple *bezt, int nr, int len);
void make_ipokey(void);
void make_ipokey_spec(struct ListBase *lb, struct Ipo *ipo);
void make_ipokey_transform(struct Object *ob, struct ListBase *lb, int sel);
void update_ipokey_val(void);
void set_tob_old(float *old, float *poin);
@@ -141,6 +143,8 @@ int fullselect_ipo_keys(struct Ipo *ipo);
int add_trans_ipo_keys(struct Ipo *ipo, struct TransVert *tv, int tvtot);
void duplicate_ipo_keys(struct Ipo *ipo);
void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val);
void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax,
int (*select_function)(struct BezTriple *));
void select_ipo_key(struct Ipo *ipo, float selx, int sel);
void select_icu_key(struct IpoCurve *icu, float selx, int selectmode);
int select_bezier_add(struct BezTriple *bezt);

View File

@@ -48,7 +48,10 @@ typedef struct KeyBlock {
int pad;
void *data;
char name[32];
float slidermin;
float slidermax;
} KeyBlock;

View File

@@ -60,6 +60,8 @@
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_constraint_types.h"
#include "DNA_mesh_types.h"
#include "DNA_key_types.h"
#include "BKE_action.h"
#include "BKE_global.h"
@@ -76,12 +78,17 @@
#include "BDR_editcurve.h"
#include "BSE_view.h"
#include "BSE_drawipo.h"
#include "BSE_editaction.h"
#include "BSE_editaction_types.h"
#include "BDR_drawaction.h"
/* 'old' stuff": defines and types, and own include -------------------- */
#include "blendef.h"
#include "interface.h"
#include "mydevice.h"
#include "BKE_ipo.h"
/* local functions ----------------------------------------------------- */
void drawactionspace(ScrArea *sa, void *spacedata);
@@ -91,10 +98,93 @@ int count_action_levels(bAction *act);
static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert);
static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert);
static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert);
static BezTriple **icu_to_keylist(IpoCurve *icu, int flags, int *totvert);
static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos);
void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, int flags, float ypos);
static void draw_action_mesh_names(Key *key);
/* implementation ------------------------------------------------------ */
extern void make_rvk_slider(uiBlock *block, Key *key, int i,
int x, int y, int w, int h); /* editkey.c */
extern short showsliders; /* editaction .c */
extern short ACTWIDTH;
void meshactionbuts(SpaceAction *saction, Key *key)
{
int i;
char str[64];
char keyname[32];
float x, y, ybase;
uiBlock *block;
uiBut *but;
short ofsx, ofsy = 0;
#define RVKBGCOL .6, .6, .8
#define XIC 20
#define YIC 20
/* lets make the rvk sliders */
/* reset the damn myortho2 or the sliders won't draw/redraw
* correctly *grumble*
*/
mywinset(curarea->win);
myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
sprintf(str, "actionbuttonswin %d", curarea->win);
block= uiNewBlock (&curarea->uiblocks, str,
UI_EMBOSSX, UI_HELV, curarea->win);
x = NAMEWIDTH + 1;
y = key->totkey*(CHANNELHEIGHT+CHANNELSKIP)
- CHANNELHEIGHT/2 - G.v2d->cur.ymin;
uiBlockSetCol(block, BUTPURPLE);
/* make the little 'open the sliders' widget */
glColor3f(RVKBGCOL);
glRects(2, y + 2*CHANNELHEIGHT - 2,
ACTWIDTH - 2, y + CHANNELHEIGHT + 2);
glColor3ub(0, 0, 0);
glRasterPos2f(4, y + CHANNELHEIGHT + 6);
BMF_DrawString(G.font, "Sliders");
uiBlockSetEmboss(block, UI_EMBOSSN);
if (!showsliders) {
ACTWIDTH = NAMEWIDTH;
uiDefIconButS(block, TOG, B_FLIPINFOMENU,
ICON_DISCLOSURE_TRI_RIGHT,
NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
XIC,YIC-2,
&(showsliders), 0, 0, 0, 0,
"Show action window sliders");
}
else {
uiDefIconButS(block, TOG, B_FLIPINFOMENU,
ICON_DISCLOSURE_TRI_DOWN,
NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT,
XIC,YIC-2,
&(showsliders), 0, 0, 0, 0,
"Hide action window sliders");
ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
/* sliders are open so draw them */
glColor3f(RVKBGCOL);
glRects(NAMEWIDTH, 0, NAMEWIDTH+SLIDERWIDTH, curarea->winy);
uiBlockSetEmboss(block, UI_EMBOSSX);
for (i=1 ; i < key->totkey ; ++ i) {
make_rvk_slider(block, key, i,
x, y, SLIDERWIDTH-2, CHANNELHEIGHT-1);
y-=CHANNELHEIGHT+CHANNELSKIP;
}
}
uiDrawBlock(block);
}
void draw_cfra_action(void)
{
Object *ob;
@@ -129,24 +219,105 @@ void draw_cfra_action(void)
glLineWidth(1.0);
}
static void draw_action_channel_names(bAction *act) {
bActionChannel *chan;
bConstraintChannel *conchan;
float x, y;
x = 0.0;
y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
for (chan=act->chanbase.first; chan; chan=chan->next){
glColor3ub(0xAA, 0xAA, 0xAA);
glRectf(x, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2);
if (chan->flag & ACHAN_SELECTED)
glColor3ub(255, 255, 255);
else
glColor3ub(0, 0, 0);
glRasterPos2f(x+8, y-4);
BMF_DrawString(G.font, chan->name);
y-=CHANNELHEIGHT+CHANNELSKIP;
/* Draw constraint channels */
for (conchan=chan->constraintChannels.first;
conchan; conchan=conchan->next){
if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
glColor3ub(255, 255, 255);
else
glColor3ub(0, 0, 0);
glRasterPos2f(x+32, y-4);
BMF_DrawString(G.font, conchan->name);
y-=CHANNELHEIGHT+CHANNELSKIP;
}
}
}
static void draw_action_mesh_names(Key *key) {
/* draws the names of the rvk keys in the
* left side of the action window
*/
int i;
char keyname[32];
float x, y;
KeyBlock *kb;
x = 0.0;
y= key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
kb= key->block.first;
for (i=1 ; i < key->totkey ; ++ i) {
glColor3ub(0xAA, 0xAA, 0xAA);
glRectf(x, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2);
glColor3ub(0, 0, 0);
glRasterPos2f(x+8, y-4);
kb = kb->next;
/* Blender now has support for named
* key blocks. If a name hasn't
* been set for an key block then
* just display the key number --
* otherwise display the name stored
* in the keyblock.
*/
if (kb->name[0] == '\0') {
sprintf(keyname, "Key %d", i);
BMF_DrawString(G.font, keyname);
}
else {
BMF_DrawString(G.font, kb->name);
}
y-=CHANNELHEIGHT+CHANNELSKIP;
}
}
static void draw_channel_names(void)
{
short ofsx, ofsy = 0;
float y;
bAction *act;
bActionChannel *chan;
bConstraintChannel *conchan;
float x, y;
myortho2 (0, ACTWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax); // Scaling
Key *key;
myortho2 (0, NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax); // Scaling
/* Blank out the area */
if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
if(G.v2d->scroll) {
ofsx= curarea->winrct.xmin;
ofsy= curarea->winrct.ymin;
glViewport(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, ACTWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));
glScissor(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, ACTWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));
glViewport(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, NAMEWIDTH,
(ofsy+G.v2d->mask.ymax) -
(ofsy+G.v2d->mask.ymin-SCROLLB));
glScissor(ofsx, ofsy+G.v2d->mask.ymin-SCROLLB, NAMEWIDTH,
(ofsy+G.v2d->mask.ymax) -
(ofsy+G.v2d->mask.ymin-SCROLLB));
}
}
@@ -158,76 +329,67 @@ static void draw_channel_names(void)
glColor3ub(0x00, 0x00, 0x00);
act=G.saction->action;
x = 0.0;
if (act) {
y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
for (chan=act->chanbase.first; chan; chan=chan->next){
glColor3ub(0xAA, 0xAA, 0xAA);
glRectf(x, y-CHANNELHEIGHT/2, (float)ACTWIDTH, y+CHANNELHEIGHT/2);
if (chan->flag & ACHAN_SELECTED)
glColor3ub(255, 255, 255);
else
glColor3ub(0, 0, 0);
glRasterPos2f(x+8, y-4);
BMF_DrawString(G.font, chan->name);
y-=CHANNELHEIGHT+CHANNELSKIP;
/* Draw constraint channels */
for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
glColor3ub(255, 255, 255);
else
glColor3ub(0, 0, 0);
glRasterPos2f(x+32, y-4);
BMF_DrawString(G.font, conchan->name);
y-=CHANNELHEIGHT+CHANNELSKIP;
}
}
if (act) {
/* if there is a selected action then
* draw the channel names
*/
draw_action_channel_names(act);
}
else {
if ( (key = get_action_mesh_key()) ) {
/* if there is a mesh selected with rvk's,
* then draw the RVK names
*/
draw_action_mesh_names(key);
}
}
myortho2 (0, ACTWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB)); // Scaling
myortho2 (0, NAMEWIDTH, 0,
(ofsy+G.v2d->mask.ymax) -
(ofsy+G.v2d->mask.ymin-SCROLLB)); // Scaling
glShadeModel(GL_SMOOTH);
glShadeModel(GL_SMOOTH);
y=9;
y=9;
/* Draw sexy shaded block thingies */
glEnable (GL_BLEND);
glBegin(GL_QUAD_STRIP);
glColor4ub (0xCC,0xCC,0xCC,0x00);
glVertex2f (0,SCROLLB*2-y);
glVertex2f (ACTWIDTH,SCROLLB*2-y);
/* Draw sexy shaded block thingies
Reevan: if you start developing this stuff again
you can have your blend's back
glEnable (GL_BLEND);
glBegin(GL_QUAD_STRIP);
glColor4ub (0xCC,0xCC,0xCC,0x00);
glVertex2f (0,SCROLLB*2-y);
glVertex2f (NAMEWIDTH,SCROLLB*2-y);
glColor4ub (0xCC,0xCC,0xCC,0xFF);
glVertex2f (0,SCROLLB-y);
glVertex2f (ACTWIDTH,SCROLLB-y);
glColor4ub (0xCC,0xCC,0xCC,0xFF);
glVertex2f (0,SCROLLB-y);
glVertex2f (NAMEWIDTH,SCROLLB-y);
glColor4ub (0xCC,0xCC,0xCC,0xFF);
glVertex2f (0,0-y);
glVertex2f (ACTWIDTH,0-y);
glColor4ub (0xCC,0xCC,0xCC,0xFF);
glVertex2f (0,0-y);
glVertex2f (NAMEWIDTH,0-y);
glEnd();
glEnd();
*/
/* y=( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB);
/* y=( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB);
glBegin(GL_QUAD_STRIP);
glColor4ub (0x88,0x88,0x88,0xFF);
glVertex2f (0,y);
glVertex2f (ACTWIDTH,y);
glColor4ub (0x88,0x88,0x88,0x00);
glVertex2f (0,y-SCROLLB);
glVertex2f (ACTWIDTH,y-SCROLLB);
glBegin(GL_QUAD_STRIP);
glColor4ub (0x88,0x88,0x88,0xFF);
glVertex2f (0,y);
glVertex2f (NAMEWIDTH,y);
glColor4ub (0x88,0x88,0x88,0x00);
glVertex2f (0,y-SCROLLB);
glVertex2f (NAMEWIDTH,y-SCROLLB);
glEnd();
*/
glDisable (GL_BLEND);
glEnd();
*/
glDisable (GL_BLEND);
glShadeModel(GL_FLAT);
glShadeModel(GL_FLAT);
}
@@ -345,21 +507,96 @@ static void draw_channel_strips(SpaceAction *saction)
glaEnd2DDraw(di);
}
static void draw_mesh_strips(SpaceAction *saction, Key *key)
{
/* draw the RVK keyframes as those little square button things
*/
rcti scr_rct;
gla2DDrawInfo *di;
float y, ybase;
IpoCurve *icu;
if (!key->ipo) return;
scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin-SCROLLB;
scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax;
di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
ybase = key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
int frame1_x, channel_y;
/* lets not deal with the "speed" Ipo
*/
if (icu->adrcode==0) continue;
y = ybase - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1);
gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
/* all frames that have a frame number less than one
* get a desaturated orange background
*/
glEnable(GL_BLEND);
glColor4b(0x55, 0x22, 0x11, 0x22);
glRectf(0, channel_y-CHANNELHEIGHT/2,
frame1_x, channel_y+CHANNELHEIGHT/2);
/* frames one and higher get a saturated orange background
*/
glColor4b(0x55, 0x22, 0x11, 0x44);
glRectf(frame1_x, channel_y-CHANNELHEIGHT/2,
G.v2d->hor.xmax, channel_y+CHANNELHEIGHT/2);
glDisable(GL_BLEND);
/* draw the little squares
*/
draw_icu_channel(di, icu, 0, y);
}
glaEnd2DDraw(di);
}
void drawactionspace(ScrArea *sa, void *spacedata)
{
short ofsx = 0, ofsy = 0;
Key *key;
short maxymin;
if (!G.saction)
return;
if (!G.saction->pin) {
if (OBACT)
G.saction->action = OBACT->action;
else
G.saction->action=NULL;
}
key = get_action_mesh_key();
/* Damn I hate hunting to find my rvk's because
* they have scrolled off of the screen ... this
* oughta fix it
*/
if (key) {
if (G.v2d->cur.ymin < -CHANNELHEIGHT)
G.v2d->cur.ymin = -CHANNELHEIGHT;
maxymin = key->totkey*(CHANNELHEIGHT+CHANNELSKIP);
if (G.v2d->cur.ymin > maxymin) G.v2d->cur.ymin = maxymin;
}
/* Lets make sure the width of the left hand of the screen
* is set to an appropriate value based on whether sliders
* are showing of not
*/
if (key && showsliders) ACTWIDTH = NAMEWIDTH + SLIDERWIDTH;
else ACTWIDTH = NAMEWIDTH;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
@@ -369,15 +606,20 @@ void drawactionspace(ScrArea *sa, void *spacedata)
if(G.v2d->scroll) {
ofsx= curarea->winrct.xmin;
ofsy= curarea->winrct.ymin;
glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin,
( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1,
( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin,
( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1,
( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
}
}
glClearColor(.45, .45, .45, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax,
G.v2d->cur.ymin, G.v2d->cur.ymax);
/* Draw backdrop */
calc_ipogrid();
@@ -386,25 +628,49 @@ void drawactionspace(ScrArea *sa, void *spacedata)
/* Draw channel strips */
draw_channel_strips(G.saction);
if (key) {
/* if there is a mesh with rvk's selected,
* then draw the key frames in the action window
*/
draw_mesh_strips(G.saction, key);
/*meshactionbuts(G.saction, key);*/
}
/* Draw current frame */
glViewport(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
glScissor(ofsx+G.v2d->mask.xmin, ofsy+G.v2d->mask.ymin, ( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1, ( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
glViewport(ofsx+G.v2d->mask.xmin,
ofsy+G.v2d->mask.ymin,
( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1,
( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
glScissor(ofsx+G.v2d->mask.xmin,
ofsy+G.v2d->mask.ymin,
( ofsx+G.v2d->mask.xmax-1)-(ofsx+G.v2d->mask.xmin)+1,
( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax,
G.v2d->cur.ymin, G.v2d->cur.ymax);
draw_cfra_action();
/* Draw scroll */
mywinset(curarea->win);
if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
if(G.v2d->scroll) drawscroll(0);
myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
if(G.v2d->scroll) drawscroll(0);
}
/* Draw channel names */
draw_channel_names();
if ( key ) {
/* if there is a mesh with rvk's selected,
* then draw the key frames in the action window
*/
meshactionbuts(G.saction, key);
}
curarea->win_swap= WIN_BACK_OK;
}
void draw_channel_name(const char* name, short type, float ypos, int selected)
{
}
@@ -449,6 +715,20 @@ void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, int flags, float ypos)
}
}
void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, int flags, float ypos)
{
/* draw the keys for an IpoCurve
*/
BezTriple **blist;
int totvert;
blist = icu_to_keylist(icu, flags, &totvert);
if (blist){
draw_keylist(di,totvert, blist, ypos);
MEM_freeN(blist);
}
}
void draw_action_channel(gla2DDrawInfo *di, bAction *act, int flags, float ypos)
{
BezTriple **blist;
@@ -503,6 +783,31 @@ static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
return list;
}
static BezTriple **icu_to_keylist(IpoCurve *icu, int flags, int *totvert)
{
/* compile a list of all bezier triples in an
* IpoCurve.
*/
int v, count = 0;
BezTriple **list = NULL;
count=icu->totvert;
if (count){
list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
count=0;
for (v=0; v<icu->totvert; v++){
list[count++]=&icu->bezt[v];
}
qsort(list, count, sizeof(BezTriple*), bezt_compare);
}
(*totvert)=count;
return list;
}
static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert)
{
IpoCurve *icu;

View File

@@ -94,7 +94,7 @@ static int ipomachtx, ipomachty;
static int vertymin, vertymax, horxmin, horxmax; /* globals om LEFTMOUSE op scrollbar te testen */
extern short ACTWIDTH;
static void scroll_prstr(float x, float y, float val, char dir, int disptype)
{

View File

@@ -57,6 +57,9 @@
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "DNA_constraint_types.h"
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_lattice_types.h"
#include "BKE_armature.h"
#include "BKE_constraint.h"
@@ -67,6 +70,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_action.h"
#include "BKE_key.h"
#include "BIF_gl.h"
#include "BIF_mywindow.h"
@@ -107,17 +111,24 @@ static void mouse_actionchannels(bAction *act, short *mval,
short *mvalo, int selectmode);
static void borderselect_action(void);
static void mouse_action(int selectmode);
static void mouse_mesh_action(int selectmode, Key *key);
static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel, bConstraintChannel **conchan);
static void sethandles_actionchannel_keys(int code);
static void delete_actionchannels(void);
static void delete_actionchannel_keys(void);
static void duplicate_actionchannel_keys(void);
static void transform_actionchannel_keys(char mode);
static void transform_meshchannel_keys(char mode, Key *key);
static void select_poseelement_by_name (char *name, int select);
static void hilight_channel (bAction *act, bActionChannel *chan, short hilight);
static void set_action_key_time (bAction *act, bPoseChannel *chan, int adrcode, short makecurve, float time);
static void clever_numbuts_meshaction(Key *key, short* mval);
/* Implementation */
short showsliders = 0;
short ACTWIDTH = NAMEWIDTH;
static void select_poseelement_by_name (char *name, int select)
{
/* Synchs selection of channels with selection of object elements in posemode */
@@ -277,6 +288,40 @@ void remake_action_ipos(bAction *act)
}
}
void remake_meshaction_ipos(Ipo *ipo)
{
/* this puts the bezier triples in proper
* order and makes sure the bezier handles
* aren't too strange.
*/
IpoCurve *icu;
for (icu = ipo->curve.first; icu; icu=icu->next){
sort_time_ipocurve(icu);
testhandles_ipocurve(icu);
}
}
static void meshkey_do_redraw(Key *key)
{
remake_meshaction_ipos(key->ipo);
do_all_ipos();
do_spec_key(key);
allspace(REMAKEIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWNLA, 0);
}
static void duplicate_meshchannel_keys(Key *key)
{
duplicate_ipo_keys(key->ipo);
transform_meshchannel_keys ('g', key);
}
static void duplicate_actionchannel_keys(void)
{
bAction *act;
@@ -396,6 +441,110 @@ static bActionChannel *get_nearest_actionchannel_key (float *index, short *sel,
return firstchan;
}
static IpoCurve *get_nearest_meshchannel_key (float *index, short *sel)
{
/* This function tries to find the RVK key that is
* closest to the user's mouse click
*/
Key *key;
IpoCurve *icu;
IpoCurve *firsticu=NULL;
int foundsel=0;
float firstvert=-1, foundx=-1;
int i;
short mval[2];
float ymin, ymax, ybase;
rctf rectf;
*index=0;
key = get_action_mesh_key();
/* lets get the mouse position and process it so
* we can start testing selections
*/
getmouseco_areawin (mval);
mval[0]-=7;
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
mval[0]+=14;
areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
ybase = key->totkey * (CHANNELHEIGHT + CHANNELSKIP);
*sel=0;
/* lets loop through the IpoCurves trying to find the closest
* bezier
*/
for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
/* lets not deal with the "speed" Ipo
*/
if (!icu->adrcode) continue;
ymax = ybase - (CHANNELHEIGHT+CHANNELSKIP)*(icu->adrcode-1);
ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
/* Does this curve coorespond to the right
* strip?
*/
if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))){
/* loop through the beziers in the curve
*/
for (i=0; i<icu->totvert; i++){
/* Is this bezier in the right area?
*/
if (icu->bezt[i].vec[1][0] > rectf.xmin &&
icu->bezt[i].vec[1][0] <= rectf.xmax ){
/* if no other curves have been picked ...
*/
if (!firsticu){
/* mark this curve/bezier as the first
* selected
*/
firsticu=icu;
firstvert=icu->bezt[i].vec[1][0];
/* sel = (is the bezier is already selected) ? 1 : 0;
*/
*sel = icu->bezt[i].f2 & 1;
}
/* if the bezier is selected ...
*/
if (icu->bezt[i].f2 & 1){
/* if we haven't found a selected one yet ...
*/
if (!foundsel){
/* record the found x value
*/
foundsel=1;
foundx = icu->bezt[i].vec[1][0];
}
}
/* if the bezier is unselected and not at the x
* position of a previous found selected bezier ...
*/
else if (foundsel && icu->bezt[i].vec[1][0] != foundx){
/* lets return this found curve/bezier
*/
*index=icu->bezt[i].vec[1][0];
*sel = 0;
return icu;
}
}
}
}
}
/* return what we've found
*/
*index=firstvert;
return firsticu;
}
static void mouse_action(int selectmode)
{
bAction *act;
@@ -439,6 +588,63 @@ static void mouse_action(int selectmode)
}
}
static void mouse_mesh_action(int selectmode, Key *key)
{
/* Handle a right mouse click selection in an
* action window displaying RVK data
*/
IpoCurve *icu;
short sel;
float selx;
short mval[2];
/* going to assume that the only reason
* we got here is because it has been
* determined that we are a mesh with
* the right properties (i.e., have key
* data, etc)
*/
/* get the click location, and the cooresponding
* ipo curve and selection time value
*/
getmouseco_areawin (mval);
icu = get_nearest_meshchannel_key(&selx, &sel);
if (icu){
if (selectmode == SELECT_REPLACE) {
/* if we had planned to replace the
* selection, then we will first deselect
* all of the keys, and if the clicked on
* key had been unselected, we will select
* it, otherwise, we are done.
*/
deselect_meshchannel_keys(key, 0);
if (sel == 0)
selectmode = SELECT_ADD;
else
/* the key is selected so we should
* deselect -- but everything is now deselected
* so we are done.
*/
return;
}
/* select the key using the given mode
* and redraw as mush stuff as needed.
*/
select_icu_key(icu, selx, selectmode);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
}
}
static void borderselect_action(void)
{
rcti rect;
@@ -496,6 +702,61 @@ static void borderselect_action(void)
}
}
static void borderselect_mesh(Key *key)
{
rcti rect;
int val, adrcodemax, adrcodemin;
short mval[2];
float xmin, xmax;
int (*select_function)(BezTriple *);
IpoCurve *icu;
if ( (val = get_border(&rect, 3)) ){
/* set the selection function based on what
* mouse button had been used in the border
* select
*/
if (val == LEFTMOUSE)
select_function = select_bezier_add;
else
select_function = select_bezier_subtract;
/* get the minimum and maximum adrcode numbers
* for the IpoCurves (this is the number that
* relates an IpoCurve to the keyblock it
* controls).
*/
mval[0]= rect.xmin;
mval[1]= rect.ymin+2;
adrcodemax = get_nearest_key_num(key, mval, &xmin);
adrcodemax = (adrcodemax >= key->totkey) ? key->totkey : adrcodemax;
mval[0]= rect.xmax;
mval[1]= rect.ymax-2;
adrcodemin = get_nearest_key_num(key, mval, &xmax);
adrcodemin = (adrcodemin < 1) ? 1 : adrcodemin;
/* Lets loop throug the IpoCurves and do borderselect
* on the curves with adrcodes in our selected range.
*/
for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
/* lets not deal with the "speed" Ipo
*/
if (!icu->adrcode) continue;
if ( (icu->adrcode >= adrcodemin) &&
(icu->adrcode <= adrcodemax) ) {
borderselect_icu_key(icu, xmin, xmax, select_function);
}
}
/* redraw stuff */
allqueue(REDRAWNLA, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
}
}
bActionChannel* get_hilighted_action_channel(bAction* action)
{
bActionChannel *chan;
@@ -1017,6 +1278,192 @@ static void transform_actionchannel_keys(char mode)
MEM_freeN (tv);
}
static void transform_meshchannel_keys(char mode, Key *key)
{
/* this is the function that determines what happens
* to those little blocky rvk key things you have selected
* after you press a 'g' or an 's'. I'd love to say that
* I have an intimate knowledge of all of what this function
* is doing, but instead I'm just going to pretend.
*/
TransVert *tv;
int /*sel=0,*/ i;
short mvals[2], mvalc[2], cent[2];
float sval[2], cval[2], lastcval[2];
short cancel=0;
float fac=0.0F;
int loop=1;
int tvtot=0;
float deltax, startx;
float cenf[2];
int invert=0, firsttime=1;
char str[256];
/* count all of the selected beziers, and
* set all 3 control handles to selected
*/
tvtot=fullselect_ipo_keys(key->ipo);
/* If nothing is selected, bail out
*/
if (!tvtot)
return;
/* Build the transvert structure
*/
tv = MEM_callocN (sizeof(TransVert) * tvtot, "transVert");
tvtot=0;
tvtot = add_trans_ipo_keys(key->ipo, tv, tvtot);
/* Do the event loop
*/
cent[0] = curarea->winx + (G.saction->v2d.hor.xmax)/2;
cent[1] = curarea->winy + (G.saction->v2d.hor.ymax)/2;
areamouseco_to_ipoco(G.v2d, cent, &cenf[0], &cenf[1]);
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++) {
tv[i].loc[0]=tv[i].oldloc[0];
tv[i].loc[1]=tv[i].oldloc[1];
}
}
else {
getmouseco_areawin (mvalc);
areamouseco_to_ipoco(G.v2d, mvalc, &cval[0], &cval[1]);
if (!firsttime && lastcval[0]==cval[0] && lastcval[1]==cval[1]) {
PIL_sleep_ms(1);
} else {
for (i=0; i<tvtot; i++){
tv[i].loc[0]=tv[i].oldloc[0];
switch (mode){
case 'g':
deltax = cval[0]-sval[0];
fac= deltax;
apply_keyb_grid(&fac, 0.0, 1.0, 0.1,
U.flag & AUTOGRABGRID);
tv[i].loc[0]+=fac;
break;
case 's':
startx=mvals[0]-(ACTWIDTH/2+(curarea->winrct.xmax
-curarea->winrct.xmin)/2);
deltax=mvalc[0]-(ACTWIDTH/2+(curarea->winrct.xmax
-curarea->winrct.xmin)/2);
fac= fabs(deltax/startx);
apply_keyb_grid(&fac, 0.0, 0.2, 0.1,
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);
tv[i].loc[0]-= startx;
tv[i].loc[0]*=fac;
tv[i].loc[0]+= startx;
break;
}
}
}
/* Display a message showing the magnitude of
* the grab/scale we are performing
*/
if (mode=='s'){
sprintf(str, "sizeX: %.3f", fac);
headerprint(str);
}
else if (mode=='g'){
sprintf(str, "deltaX: %.3f", fac);
headerprint(str);
}
if (G.saction->lock){
/* doubt any of this code ever gets
* executed, but it might in the
* future
*/
do_all_actions();
allqueue (REDRAWVIEW3D, 0);
allqueue (REDRAWACTION, 0);
allqueue (REDRAWIPO, 0);
allqueue(REDRAWNLA, 0);
force_draw_all();
}
else {
addqueue (curarea->win, REDRAWALL, 0);
force_draw ();
}
}
lastcval[0]= cval[0];
lastcval[1]= cval[1];
firsttime= 0;
}
/* fix up the Ipocurves and redraw stuff
*/
meshkey_do_redraw(key);
MEM_freeN (tv);
/* did you understand all of that? I pretty much understand
* what it does, but the specifics seem a little weird and crufty.
*/
}
void deselect_actionchannel_keys (bAction *act, int test)
{
bActionChannel *chan;
@@ -1059,6 +1506,26 @@ void deselect_actionchannel_keys (bAction *act, int test)
}
}
void deselect_meshchannel_keys (Key *key, int test)
{
/* should deselect the rvk keys
*/
int sel=1;
/* Determine if this is selection or deselection */
if (test){
if (is_ipo_key_selected(key->ipo)){
sel = 0;
}
}
else {
sel=0;
}
/* Set the flags */
set_ipo_key_selection(key->ipo, sel);
}
void deselect_actionchannels (bAction *act, int test)
{
bActionChannel *chan;
@@ -1125,6 +1592,12 @@ static void hilight_channel (bAction *act, bActionChannel *chan, short select)
}
}
/* select_mode = SELECT_REPLACE
* = SELECT_ADD
* = SELECT_SUBTRACT
* = SELECT_INVERT
*/
static int select_channel(bAction *act, bActionChannel *chan,
int selectmode) {
/* Select the channel based on the selection mode
@@ -1277,6 +1750,15 @@ static void mouse_actionchannels(bAction *act, short *mval,
allqueue (REDRAWNLA, 0);
}
static void delete_meshchannel_keys(Key *key)
{
if (!okee("Erase selected keys"))
return;
delete_ipo_keys(key->ipo);
meshkey_do_redraw(key);
}
static void delete_actionchannel_keys(void)
{
@@ -1369,6 +1851,13 @@ static void delete_actionchannels (void)
}
static void sethandles_meshchannel_keys(int code, Key *key)
{
sethandles_ipo_keys(key->ipo, code);
meshkey_do_redraw(key);
}
static void sethandles_actionchannel_keys(int code)
{
bAction *act;
@@ -1660,7 +2149,8 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
short mval[2];
float dx,dy;
int cfra;
Key *key;
if(curarea->win==0) return;
saction= curarea->spacedata.first;
@@ -1674,6 +2164,8 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
getmouseco_areawin(mval);
key = get_action_mesh_key();
switch(event) {
case UI_BUT_EVENT:
do_blenderbuttons(val);
@@ -1690,92 +2182,172 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
break;
case DKEY:
if (G.qual & LR_SHIFTKEY && mval[0]>ACTWIDTH){
duplicate_actionchannel_keys();
remake_action_ipos(act);
if (key) {
if (G.qual & LR_SHIFTKEY && mval[0]>ACTWIDTH) {
duplicate_meshchannel_keys(key);
}
}
break;
case DELKEY:
case XKEY:
if (mval[0]<ACTWIDTH)
delete_actionchannels ();
else
delete_actionchannel_keys ();
break;
case GKEY:
if (mval[0]>=ACTWIDTH)
transform_actionchannel_keys ('g');
break;
case SKEY:
if (mval[0]>=ACTWIDTH)
transform_actionchannel_keys ('s');
break;
case AKEY:
if (mval[0]<ACTWIDTH){
deselect_actionchannels (act, 1);
allqueue (REDRAWVIEW3D, 0);
allqueue (REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue (REDRAWIPO, 0);
}
else{
deselect_actionchannel_keys (act, 1);
allqueue (REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue (REDRAWIPO, 0);
else {
if (G.qual & LR_SHIFTKEY && mval[0]>ACTWIDTH){
duplicate_actionchannel_keys();
remake_action_ipos(act);
}
}
break;
case DELKEY:
case XKEY:
if (key) {
delete_meshchannel_keys(key);
}
else {
if (mval[0]<NAMEWIDTH)
delete_actionchannels ();
else
delete_actionchannel_keys ();
}
break;
case GKEY:
if (mval[0]>=ACTWIDTH) {
if (key) {
transform_meshchannel_keys('g', key);
}
else {
transform_actionchannel_keys ('g');
}
}
break;
case SKEY:
if (mval[0]>=ACTWIDTH) {
if (key) {
transform_meshchannel_keys('s', key);
}
else {
transform_actionchannel_keys ('s');
}
}
break;
case AKEY:
if (key) {
if (mval[0]<ACTWIDTH){
/* to do ??? */
}
else{
deselect_meshchannel_keys(key, 1);
allqueue (REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue (REDRAWIPO, 0);
}
}
else {
if (mval[0]<NAMEWIDTH){
deselect_actionchannels (act, 1);
allqueue (REDRAWVIEW3D, 0);
allqueue (REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue (REDRAWIPO, 0);
}
else if (mval[0]>ACTWIDTH){
deselect_actionchannel_keys (act, 1);
allqueue (REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue (REDRAWIPO, 0);
}
}
break;
/*** set the Ipo handles ***/
case VKEY:
sethandles_actionchannel_keys(HD_VECT);
if (key) {
sethandles_meshchannel_keys(HD_VECT, key);
/* to do */
}
else {
sethandles_actionchannel_keys(HD_VECT);
}
break;
case HKEY:
if(G.qual & LR_SHIFTKEY) sethandles_actionchannel_keys(HD_AUTO);
else sethandles_actionchannel_keys(HD_ALIGN);
if (key) {
if(G.qual & LR_SHIFTKEY) {
sethandles_meshchannel_keys(HD_AUTO, key);
}
else {
sethandles_meshchannel_keys(HD_ALIGN, key);
}
}
else {
if(G.qual & LR_SHIFTKEY) {
sethandles_actionchannel_keys(HD_AUTO);
}
else {
sethandles_actionchannel_keys(HD_ALIGN);
}
}
break;
/*** set the Ipo type ***/
case TKEY:
set_ipotype_actionchannels();
if (key) {
/* to do */
}
else {
set_ipotype_actionchannels();
}
break;
case BKEY:
/* If the border select is initiated in the
* part of the action window where the channel
* names reside, then select the channels
*/
if (mval[0]<ACTWIDTH){
borderselect_function(mouse_actionchannels);
if (key) {
if (mval[0]<ACTWIDTH){
/* to do?? */
}
else {
borderselect_mesh(key);
}
}
/* If the border select is initiated in the
* vertical scrollbar, then (de)select all keys
* for the channels in the selection region
*/
else if (IN_2D_VERT_SCROLL(mval)) {
borderselect_function(select_all_keys_channels);
}
/* If the border select is initiated in the
* horizontal scrollbar, then (de)select all keys
* for the keyframes in the selection region
*/
else if (IN_2D_HORIZ_SCROLL(mval)) {
borderselect_function(select_all_keys_frames);
}
/* Other wise, select the action keys
*/
else {
borderselect_action();
/* If the border select is initiated in the
* part of the action window where the channel
* names reside, then select the channels
*/
if (mval[0]<NAMEWIDTH){
borderselect_function(mouse_actionchannels);
}
else if (mval[0]>ACTWIDTH){
/* If the border select is initiated in the
* vertical scrollbar, then (de)select all keys
* for the channels in the selection region
*/
if (IN_2D_VERT_SCROLL(mval)) {
borderselect_function(select_all_keys_channels);
}
/* If the border select is initiated in the
* horizontal scrollbar, then (de)select all keys
* for the keyframes in the selection region
*/
else if (IN_2D_HORIZ_SCROLL(mval)) {
borderselect_function(select_all_keys_frames);
}
/* Other wise, select the action keys
*/
else {
borderselect_action();
}
}
}
break;
case RIGHTMOUSE:
/* Right clicking in the channel area selects the
* channel or constraint channel
*/
if (mval[0]<ACTWIDTH) {
if (mval[0]<NAMEWIDTH) {
if(G.qual & LR_SHIFTKEY)
mouse_actionchannels(act, mval, NULL,
SELECT_INVERT);
@@ -1783,40 +2355,50 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
mouse_actionchannels(act, mval, NULL,
SELECT_REPLACE);
}
else if (mval[0]>ACTWIDTH) {
/* Right clicking in the vertical scrollbar selects
* all of the keys for that channel at that height
*/
else if (IN_2D_VERT_SCROLL(mval)) {
if(G.qual & LR_SHIFTKEY)
select_all_keys_channels(act, mval, NULL,
SELECT_INVERT);
else
select_all_keys_channels(act, mval, NULL,
SELECT_REPLACE);
}
/* Right clicking in the vertical scrollbar selects
* all of the keys for that channel at that height
*/
if (IN_2D_VERT_SCROLL(mval)) {
if(G.qual & LR_SHIFTKEY)
select_all_keys_channels(act, mval, NULL,
SELECT_INVERT);
else
select_all_keys_channels(act, mval, NULL,
SELECT_REPLACE);
}
/* Right clicking in the horizontal scrollbar selects
* all of the keys within 0.5 of the nearest integer
* frame
*/
else if (IN_2D_HORIZ_SCROLL(mval)) {
if(G.qual & LR_SHIFTKEY)
select_all_keys_frames(act, mval, NULL,
SELECT_INVERT);
else
select_all_keys_frames(act, mval, NULL,
SELECT_REPLACE);
}
/* Clicking in the main area of the action window
* selects keys
*/
else {
if(G.qual & LR_SHIFTKEY)
mouse_action(SELECT_INVERT);
else
mouse_action(SELECT_REPLACE);
/* Right clicking in the horizontal scrollbar selects
* all of the keys within 0.5 of the nearest integer
* frame
*/
else if (IN_2D_HORIZ_SCROLL(mval)) {
if(G.qual & LR_SHIFTKEY)
select_all_keys_frames(act, mval, NULL,
SELECT_INVERT);
else
select_all_keys_frames(act, mval, NULL,
SELECT_REPLACE);
}
/* Clicking in the main area of the action window
* selects keys
*/
else {
if (key) {
if(G.qual & LR_SHIFTKEY)
mouse_mesh_action(SELECT_INVERT, key);
else
mouse_mesh_action(SELECT_REPLACE, key);
}
else {
if(G.qual & LR_SHIFTKEY)
mouse_action(SELECT_INVERT);
else
mouse_action(SELECT_REPLACE);
}
}
}
break;
@@ -1854,3 +2436,119 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
}
Key *get_action_mesh_key(void) {
/* gets the key data from the currently selected
* mesh/lattice. If a mesh is not selected, or does not have
* key data, then we return NULL (currently only
* returns key data for RVK type meshes). If there
* is an action that is pinned, return null
*/
Object *ob;
Key *key;
ob = OBACT;
if (!ob) return NULL;
if (G.saction->pin) return NULL;
if (ob->type==OB_MESH ) {
key = ((Mesh *)ob->data)->key;
}
else if (ob->type==OB_LATTICE ) {
key = ((Lattice *)ob->data)->key;
}
else return NULL;
if (key) {
if (key->type == KEY_RELATIVE)
return key;
}
return NULL;
}
int get_nearest_key_num(Key *key, short *mval, float *x) {
/* returns the key num that cooresponds to the
* y value of the mouse click. Does not check
* if this is a valid keynum. Also gives the Ipo
* x coordinate.
*/
int num;
float ybase, y;
areamouseco_to_ipoco(G.v2d, mval, x, &y);
ybase = key->totkey * (CHANNELHEIGHT + CHANNELSKIP);
num = (int) ((ybase - y) / (CHANNELHEIGHT+CHANNELSKIP));
return (num + 1);
}
static void clever_keyblock_names(Key *key, short* mval){
int but=0, i, keynum;
char str[64];
float x, min, max;
KeyBlock *kb;
/* get the keynum cooresponding to the y value
* of the mouse pointer, return if this is
* an invalid key number (and we don't deal
* with the speed ipo).
*/
keynum = get_nearest_key_num(key, mval, &x);
if ( (keynum < 1) || (keynum >= key->totkey) )
return;
kb= key->block.first;
for (i=0; i<keynum; ++i) kb = kb->next;
if (kb->name[0] == '\0') {
sprintf(str, "Key %d", keynum);
}
else {
strcpy(str, kb->name);
}
if ( (kb->slidermin >= kb->slidermax) ) {
kb->slidermin = 0.0;
kb->slidermax = 1.0;
}
add_numbut(but++, TEX, "KB: ", 0, 24, str,
"Does this really need a tool tip?");
add_numbut(but++, NUM|FLO, "Slider min:",
-10000, kb->slidermax, &kb->slidermin, 0);
add_numbut(but++, NUM|FLO, "Slider max:",
kb->slidermin, 10000, &kb->slidermax, 0);
if (do_clever_numbuts(str, but, REDRAW)) {
strcpy(kb->name, str);
allqueue (REDRAWACTION, 0);
allqueue (REDRAWIPO, 0);
}
}
void stupid_damn_numbuts_action(void){
/* I think this function might have been
* deemed clever if it could have been
* called from the event processing
* routine in this file -- rather than having
* to go from the NKEY event from blenderqread
* in toets.c (which returns 0 so nobody else
* can use the NKEY) then into the clever_numbuts
* routine in toolbox.c, the finally to this
* function. Grumble, grumble, grumble ...
*/
Key *key;
short mval[2];
if ( (key = get_action_mesh_key()) ) {
getmouseco_areawin (mval);
if (mval[0]<NAMEWIDTH) {
clever_keyblock_names(key, mval);
}
}
}

View File

@@ -1866,7 +1866,7 @@ EditIpo *get_editipo()
}
static Ipo *get_ipo(ID *from, short type, int make)
Ipo *get_ipo(ID *from, short type, int make)
{
Object *ob;
Material *ma;

View File

@@ -69,6 +69,7 @@
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_displist.h"
#include "BIF_editkey.h"
#include "BIF_editview.h"
@@ -76,6 +77,7 @@
#include "BIF_screen.h"
#include "BIF_space.h"
#include "BIF_toolbox.h"
#include "BIF_interface.h"
#include "BSE_editipo.h"
#include "BSE_trans_types.h"
@@ -85,9 +87,200 @@
#include "blendef.h"
#include "mydevice.h"
#include "ipo.h"
#include "interface.h"
extern ListBase editNurb; /* in editcurve.c */
/* temporary storage for slider values */
float meshslidervals[32] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
static IpoCurve *get_key_icu(Key *key, int keynum) {
/* return the Ipocurve that has the specified
* keynum as ardcode -- return NULL if no such
* curve exists.
*/
IpoCurve *icu;
if (!(key->ipo)) {
key->ipo = get_ipo(key, ID_KE, 1);
return NULL;
}
for (icu = key->ipo->curve.first; icu ; icu = icu->next) {
if (!icu->adrcode) continue;
if (icu->adrcode == keynum) return icu;
}
return NULL;
}
static BezTriple *get_bezt_icu_time(IpoCurve *icu, float *frame, float *val) {
/* this function tries to find a bezier that is within
* 0.25 time units from the specified frame. If there
* are more than one such beziers, it returns the
* closest one.
*/
int i;
float d, dmin = 0.25, newframe;
BezTriple *bezt = NULL;
newframe = *frame;
for (i=0; i<icu->totvert; i++){
d = fabs(icu->bezt[i].vec[1][0] - *frame);
if (d < dmin) {
dmin = d;
newframe = icu->bezt[i].vec[1][0];
*val = icu->bezt[i].vec[1][1];
bezt = icu->bezt + i;
}
}
*frame = newframe;
return bezt;
}
static void rvk_slider_func(void *voidkey, void *voidkeynum) {
/* the callback for the rvk sliders ... copies the
* value from the temporary array into a bezier at the
* right frame on the right ipo curve (creating both the
* ipo curve and the bezier if needed).
*/
int *keynum = (int *) voidkeynum;
Key *key = (Key *) voidkey;
float cfra, rvkval;
IpoCurve *icu=NULL;
BezTriple *bezt=NULL;
cfra = frame_to_float(CFRA);
icu = get_key_icu(key, *keynum);
if (icu) {
/* if the ipocurve exists, try to get a bezier
* for this frame
*/
bezt = get_bezt_icu_time(icu, &cfra, &rvkval);
}
else {
/* create an IpoCurve if one doesn't already
* exist.
*/
icu = get_ipocurve(key->from, GS(key->from->name),
*keynum, key->ipo);
}
/* create the bezier triple if one doesn't exist,
* otherwise modify it's value
*/
if (!bezt) {
insert_vert_ipo(icu, cfra, meshslidervals[*keynum]);
}
else {
bezt->vec[1][1] = meshslidervals[*keynum];
}
/* make sure the Ipo's are properly process and
* redraw as necessary
*/
sort_time_ipocurve(icu);
testhandles_ipocurve(icu);
do_all_ipos();
do_spec_key(key);
/* if I'm deformed by a lattice, update my
* displists
*/
makeDispList(OBACT);
/* if I'm a lattice, update the displists of
* my children
*/
if (OBACT->type==OB_LATTICE ) {
Base *base;
base= FIRSTBASE;
while(base) {
if (base->object->parent == OBACT) {
makeDispList(base->object);
}
base= base->next;
}
}
allqueue (REDRAWVIEW3D, 0);
allqueue (REDRAWACTION, 0);
allqueue (REDRAWNLA, 0);
allqueue (REDRAWIPO, 0);
}
static float getrvkval(Key *key, int keynum) {
/* get the value of the rvk from the
* ipo curve at the current time -- return 0
* if no ipo curve exists
*/
IpoCurve *icu=NULL;
BezTriple *bezt=NULL;
float rvkval = 0.0;
float cfra;
cfra = frame_to_float(CFRA);
icu = get_key_icu(key, keynum);
if (icu) {
bezt = get_bezt_icu_time(icu, &cfra, &rvkval);
if (!bezt) {
rvkval = eval_icu(icu, cfra);
}
}
return rvkval;
}
void make_rvk_slider(uiBlock *block, Key *key, int keynum,
int x, int y, int w, int h)
{
/* create a slider for the rvk */
uiBut *but;
KeyBlock *kb;
float min, max;
int i;
/* dang, need to pass a pointer to int to uiButSetFunc
* that is on the heap, not the stack ... hence this
* kludgy static array
*/
static int keynums[] = {0,1,2,3,4,5,6,7,
8,9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,
24,25,26,27,28,29,30,31};
meshslidervals[keynum] = getrvkval(key, keynum);
kb= key->block.first;
for (i=0; i<keynum; ++i) kb = kb->next;
if ( (kb->slidermin >= kb->slidermax) ) {
kb->slidermin = 0.0;
kb->slidermax = 1.0;
}
min = (kb->slidermin < meshslidervals[keynum]) ?
kb->slidermin: meshslidervals[keynum];
max = (kb->slidermax > meshslidervals[keynum]) ?
kb->slidermax: meshslidervals[keynum];
but=uiDefButF(block, NUMSLI, REDRAWVIEW3D, "",
x, y , w, h,
meshslidervals+keynum, min, max, 10, 2,
"Slider to control rvk");
uiButSetFunc(but, rvk_slider_func, key, keynums+keynum);
}
static void default_key_ipo(Key *key)
{
IpoCurve *icu;
@@ -168,10 +361,20 @@ void insert_meshkey(Mesh *me)
Key *key;
KeyBlock *kb, *kkb;
float curpos;
short rel;
if(me->key==0) {
me->key= add_key( (ID *)me);
default_key_ipo(me->key);
rel = pupmenu("Relative Vertex Keys? %t|Yes Please! %x1"
"|Naw, the other kind %x2");
switch (rel) {
case 1:
me->key->type = KEY_RELATIVE;
break;
default:
default_key_ipo(me->key);
break;
}
}
key= me->key;

View File

@@ -4032,17 +4032,25 @@ void action_buttons(void)
uiDefIconBut(block, BUT, B_ACTHOME, ICON_HOME, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms window to home view showing all items (HOMEKEY)");
/* NAME ETC */
ob=OBACT;
from = (ID*) ob;
if (!get_action_mesh_key()) {
/* NAME ETC */
ob=OBACT;
from = (ID*) ob;
xco= std_libbuttons(block, xco+1.5*XIC, B_ACTPIN, &G.saction->pin, B_ACTIONBROWSE, (ID*)G.saction->action, from, &(G.saction->actnr), B_ACTALONE, B_ACTLOCAL, B_ACTIONDELETE, 0, 0);
xco= std_libbuttons(block, xco+1.5*XIC, B_ACTPIN, &G.saction->pin,
B_ACTIONBROWSE, (ID*)G.saction->action,
from, &(G.saction->actnr), B_ACTALONE,
B_ACTLOCAL, B_ACTIONDELETE, 0, 0);
#ifdef __NLA_BAKE
/* Draw action baker */
uiDefBut(block, BUT, B_ACTBAKE, "Bake", xco+=XIC, 0, 64, YIC, 0, 0, 0, 0, 0, "Generates an Action with the constraint effects converted into ipo keys");
xco+=64;
/* Draw action baker */
uiDefBut(block, BUT, B_ACTBAKE, "Bake",
xco+=XIC, 0, 64, YIC, 0, 0, 0, 0, 0,
"Generate an action with the constraint "
"effects converted into ipo keys");
xco+=64;
#endif
}
uiClearButLock();
/* draw LOCK */

View File

@@ -1452,9 +1452,9 @@ void clever_numbuts(void)
else if(curarea->spacetype==SPACE_OOPS) {
clever_numbuts_oops();
}
// else if(curarea->spacetype==SPACE_ACTION){
// stupid_damn_numbuts_action();
// }
else if(curarea->spacetype==SPACE_ACTION){
stupid_damn_numbuts_action();
}
else if(curarea->spacetype==SPACE_FILE) {
clever_numbuts_filesel();
}