diff options
author | Chris Want <cwant@ualberta.ca> | 2003-07-21 03:04:09 +0400 |
---|---|---|
committer | Chris Want <cwant@ualberta.ca> | 2003-07-21 03:04:09 +0400 |
commit | cf495e6655de7e7dce5115d487460a33fcb8b488 (patch) | |
tree | 88c14a4ba94f610ccf909bd68af4b0f786cee4e6 /source | |
parent | 9a9cb5448b090ff88c6c46fec312c7f98941c248 (diff) |
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!
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/include/BSE_editaction.h | 6 | ||||
-rw-r--r-- | source/blender/include/BSE_editaction_types.h | 3 | ||||
-rw-r--r-- | source/blender/include/BSE_editipo.h | 4 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_key_types.h | 5 | ||||
-rw-r--r-- | source/blender/src/drawaction.c | 475 | ||||
-rw-r--r-- | source/blender/src/drawipo.c | 2 | ||||
-rw-r--r-- | source/blender/src/editaction.c | 872 | ||||
-rw-r--r-- | source/blender/src/editipo.c | 2 | ||||
-rw-r--r-- | source/blender/src/editkey.c | 207 | ||||
-rw-r--r-- | source/blender/src/headerbuttons.c | 22 | ||||
-rw-r--r-- | source/blender/src/toolbox.c | 6 |
11 files changed, 1415 insertions, 189 deletions
diff --git a/source/blender/include/BSE_editaction.h b/source/blender/include/BSE_editaction.h index 5e88ba90bf2..13539c111f0 100644 --- a/source/blender/include/BSE_editaction.h +++ b/source/blender/include/BSE_editaction.h @@ -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 */ diff --git a/source/blender/include/BSE_editaction_types.h b/source/blender/include/BSE_editaction_types.h index 16e4890daef..4df6c6712fb 100644 --- a/source/blender/include/BSE_editaction_types.h +++ b/source/blender/include/BSE_editaction_types.h @@ -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 */ diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index 3522056f21e..9ae57db0a22 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -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); diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h index 55f6d81aa06..6c36febbff7 100644 --- a/source/blender/makesdna/DNA_key_types.h +++ b/source/blender/makesdna/DNA_key_types.h @@ -48,7 +48,10 @@ typedef struct KeyBlock { int pad; void *data; - + char name[32]; + + float slidermin; + float slidermax; } KeyBlock; diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 80af4d27676..482fb4448e6 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -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; - } - } - } - - myortho2 (0, ACTWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB)); // Scaling - - glShadeModel(GL_SMOOTH); + + 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, NAMEWIDTH, 0, + (ofsy+G.v2d->mask.ymax) - + (ofsy+G.v2d->mask.ymin-SCROLLB)); // Scaling + + glShadeModel(GL_SMOOTH); - 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); - - glColor4ub (0xCC,0xCC,0xCC,0xFF); - glVertex2f (0,SCROLLB-y); - glVertex2f (ACTWIDTH,SCROLLB-y); - - glColor4ub (0xCC,0xCC,0xCC,0xFF); - glVertex2f (0,0-y); - glVertex2f (ACTWIDTH,0-y); - - glEnd(); - -/* 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); + y=9; + + /* 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 (NAMEWIDTH,SCROLLB-y); + + glColor4ub (0xCC,0xCC,0xCC,0xFF); + glVertex2f (0,0-y); + glVertex2f (NAMEWIDTH,0-y); + + glEnd(); + */ + + /* 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 (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; diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 0fa5e6d365f..e82e19b3cff 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -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) { diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 01f0ff4ff2b..dbde1c22d84 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -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); + } + } + else { + if (G.qual & LR_SHIFTKEY && mval[0]>ACTWIDTH){ + duplicate_actionchannel_keys(); + remake_action_ipos(act); + } } break; + case DELKEY: + case XKEY: - if (mval[0]<ACTWIDTH) - delete_actionchannels (); - else - delete_actionchannel_keys (); + if (key) { + delete_meshchannel_keys(key); + } + else { + if (mval[0]<NAMEWIDTH) + delete_actionchannels (); + else + delete_actionchannel_keys (); + } break; + case GKEY: - if (mval[0]>=ACTWIDTH) - transform_actionchannel_keys ('g'); + if (mval[0]>=ACTWIDTH) { + if (key) { + transform_meshchannel_keys('g', key); + } + else { + transform_actionchannel_keys ('g'); + } + } break; + case SKEY: - if (mval[0]>=ACTWIDTH) - transform_actionchannel_keys ('s'); + if (mval[0]>=ACTWIDTH) { + if (key) { + transform_meshchannel_keys('s', key); + } + else { + 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); + if (key) { + if (mval[0]<ACTWIDTH){ + /* to do ??? */ + } + else{ + deselect_meshchannel_keys(key, 1); + 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 (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); + } } + else { - /* 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 + * 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); - } + /* 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(); + /* 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 + */ + 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 - */ - 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 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); + } + } +} diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index b0cf75ff7da..b799d9d99f0 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -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; diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c index 0d8b04339c1..3f8a3e98705 100644 --- a/source/blender/src/editkey.c +++ b/source/blender/src/editkey.c @@ -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; diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index eaa66bd5b22..1a7b24aff85 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -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 */ diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 364193c52e1..4c879b5a94e 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -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(); } |