/** * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** * Drawing routines for the Action window type */ /* System includes ----------------------------------------------------- */ #include #include #ifdef HAVE_CONFIG_H #include #endif #include "MEM_guardedalloc.h" #include "BMF_Api.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" /* Types --------------------------------------------------------------- */ #include "DNA_action_types.h" #include "DNA_curve_types.h" #include "DNA_ipo_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_space_types.h" #include "DNA_constraint_types.h" #include "DNA_key_types.h" #include "BKE_action.h" #include "BKE_global.h" /* Everything from source (BIF, BDR, BSE) ------------------------------ */ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_interface.h" #include "BIF_mywindow.h" #include "BIF_space.h" #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 "mydevice.h" #include "BKE_ipo.h" /* local functions ----------------------------------------------------- */ void drawactionspace(ScrArea *sa, void *spacedata); static void draw_channel_names(void); static void draw_channel_strips(SpaceAction *saction); 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); /* missing local prototypes -------------------------------------------- */ void meshactionbuts(SpaceAction *saction, Key *key); void do_actionbuts(unsigned short event); /* 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]; float x, y; uiBlock *block; uiBut *but; #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.375, curarea->winx-0.375, -0.375, curarea->winy-0.375); sprintf(str, "actionbuttonswin %d", curarea->win); block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS, UI_HELV, curarea->win); x = NAMEWIDTH + 1; y = key->totkey*(CHANNELHEIGHT+CHANNELSKIP) + CHANNELHEIGHT/2 - G.v2d->cur.ymin; /* make the little 'open the sliders' widget */ BIF_ThemeColor(TH_FACE); // this slot was open... 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; but=uiDefIconButS(block, TOG, B_REDR, ICON_DISCLOSURE_TRI_RIGHT, NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT, XIC,YIC-2, &(showsliders), 0, 0, 0, 0, "Show action window sliders"); // no hilite, the winmatrix is not correct later on... uiButSetFlag(but, UI_NO_HILITE); } else { but= uiDefIconButS(block, TOG, B_REDR, ICON_DISCLOSURE_TRI_DOWN, NAMEWIDTH - XIC - 5, y + CHANNELHEIGHT, XIC,YIC-2, &(showsliders), 0, 0, 0, 0, "Hide action window sliders"); // no hilite, the winmatrix is not correct later on... uiButSetFlag(but, UI_NO_HILITE); ACTWIDTH = NAMEWIDTH + SLIDERWIDTH; /* sliders are open so draw them */ BIF_ThemeColor(TH_FACE); glRects(NAMEWIDTH, 0, NAMEWIDTH+SLIDERWIDTH, curarea->winy); uiBlockSetEmboss(block, UI_EMBOSS); 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; float vec[2]; vec[0]= (G.scene->r.cfra); vec[0]*= G.scene->r.framelen; vec[1]= G.v2d->cur.ymin; glColor3ub(0x60, 0xc0, 0x40); glLineWidth(2.0); glBegin(GL_LINE_STRIP); glVertex2fv(vec); vec[1]= G.v2d->cur.ymax; glVertex2fv(vec); glEnd(); ob= (G.scene->basact) ? (G.scene->basact->object) : 0; if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) { vec[0]-= ob->sf; glColor3ub(0x10, 0x60, 0); glBegin(GL_LINE_STRIP); glVertex2fv(vec); vec[1]= G.v2d->cur.ymin; glVertex2fv(vec); glEnd(); } 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){ BIF_ThemeColorShade(TH_HEADER, 20); glRectf(x, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2); if (chan->flag & ACHAN_SELECTED) BIF_ThemeColor(TH_TEXT_HI); else BIF_ThemeColor(TH_TEXT); 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) BIF_ThemeColor(TH_TEXT_HI); else BIF_ThemeColor(TH_TEXT); 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; bAction *act; Key *key; /* Clip to the scrollable 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, NAMEWIDTH, (ofsy+G.v2d->mask.ymax) - (ofsy+G.v2d->mask.ymin)); glScissor(ofsx, ofsy+G.v2d->mask.ymin, NAMEWIDTH, (ofsy+G.v2d->mask.ymax) - (ofsy+G.v2d->mask.ymin)); } } myortho2(0, NAMEWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax); // Scaling glColor3ub(0x00, 0x00, 0x00); act=G.saction->action; if (act) { /* if there is a selected action then * draw the channel names */ draw_action_channel_names(act); } 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)); // Scaling } int count_action_levels(bAction *act) { int y=0; bActionChannel *achan; if (!act) return 0; for (achan=act->chanbase.first; achan; achan=achan->next){ y+=1; y+=BLI_countlist(&achan->constraintChannels); } return y; } /** Draw a nicely beveled button (in screen space) */ void draw_bevel_but(int x, int y, int w, int h, int sel) { int xmin= x, ymin= y; int xmax= x+w-1, ymax= y+h-1; int i; glColor3ub(0,0,0); glBegin(GL_LINE_LOOP); glVertex2i(xmin, ymin); glVertex2i(xmax, ymin); glVertex2i(xmax, ymax); glVertex2i(xmin, ymax); glEnd(); glBegin(GL_LINE_LOOP); if (sel) glColor3ub(0xD0, 0x7E, 0x06); else glColor3ub(0x8C, 0x8C, 0x8C); glVertex2i(xmax-1, ymin+1); glVertex2i(xmax-1, ymax-1); if (sel) glColor3ub(0xF4, 0xEE, 0x8E); else glColor3ub(0xDF, 0xDF, 0xDF); glVertex2i(xmin+1, ymax-1); glVertex2i(xmin+1, ymin+1); glEnd(); if (sel) glColor3ub(0xF1, 0xCA, 0x13); else glColor3ub(0xAC, 0xAC, 0xAC); glBegin(GL_LINES); for (i=xmin+2; i<=xmax-2; i++) { glVertex2f(i, ymin+2); glVertex2f(i, ymax-1); } glEnd(); } static void draw_channel_strips(SpaceAction *saction) { rcti scr_rct; gla2DDrawInfo *di; bAction *act; bActionChannel *chan; bConstraintChannel *conchan; float y; char col1[3], col2[3]; BIF_GetThemeColor3ubv(TH_SHADE2, col2); BIF_GetThemeColor3ubv(TH_HILITE, col1); act= saction->action; if (!act) return; scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH; scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin; 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); y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP); for (chan=act->chanbase.first; chan; chan=chan->next){ int frame1_x, channel_y; gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y); glEnable(GL_BLEND); if (chan->flag & ACHAN_SELECTED) glColor4b(col1[0], col1[1], col1[2], 0x22); else glColor4b(col2[0], col2[1], col2[2], 0x22); glRectf(0, channel_y-CHANNELHEIGHT/2, frame1_x, channel_y+CHANNELHEIGHT/2); if (chan->flag & ACHAN_SELECTED) glColor4b(col1[0], col1[1], col1[2], 0x44); else glColor4b(col2[0], col2[1], col2[2], 0x44); glRectf(frame1_x, channel_y-CHANNELHEIGHT/2, G.v2d->hor.xmax, channel_y+CHANNELHEIGHT/2); glDisable(GL_BLEND); draw_ipo_channel(di, chan->ipo, 0, y); /* Increment the step */ y-=CHANNELHEIGHT+CHANNELSKIP; /* Draw constraint channels */ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){ gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y); glEnable(GL_BLEND); if (conchan->flag & ACHAN_SELECTED) glColor4b(col1[0], col1[1], col1[2], 0x22); else glColor4b(col2[0], col2[1], col2[2], 0x22); glRectf(0, channel_y-CHANNELHEIGHT/2+4, frame1_x, channel_y+CHANNELHEIGHT/2-4); if (conchan->flag & ACHAN_SELECTED) glColor4b(col1[0], col1[1], col1[2], 0x44); else glColor4b(col2[0], col2[1], col2[2], 0x44); glRectf(frame1_x, channel_y-CHANNELHEIGHT/2+4, G.v2d->hor.xmax, channel_y+CHANNELHEIGHT/2-4); glDisable(GL_BLEND); draw_ipo_channel(di, conchan->ipo, 0, y); y-=CHANNELHEIGHT+CHANNELSKIP; } } 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; char col1[3], col2[3]; BIF_GetThemeColor3ubv(TH_SHADE2, col2); BIF_GetThemeColor3ubv(TH_HILITE, col1); if (!key->ipo) return; scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH; scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin; 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(col2[0], col2[1], col2[2], 0x22); glRectf(0, channel_y-CHANNELHEIGHT/2, frame1_x, channel_y+CHANNELHEIGHT/2); /* frames one and higher get a saturated orange background */ glColor4b(col2[0], col2[1], col2[2], 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); } /* ********* action panel *********** */ void do_actionbuts(unsigned short event) { switch(event) { case REDRAWVIEW3D: allqueue(REDRAWVIEW3D, 0); break; case B_REDR: allqueue(REDRAWACTION, 0); break; } } static void action_panel_properties(short cntrl) // ACTION_HANDLER_PROPERTIES { uiBlock *block; block= uiNewBlock(&curarea->uiblocks, "action_panel_properties", UI_EMBOSS, UI_HELV, curarea->win); uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); uiSetPanelHandler(ACTION_HANDLER_PROPERTIES); // for close and esc if(uiNewPanel(curarea, block, "Transform Properties", "Action", 10, 230, 318, 204)==0) return; uiDefBut(block, LABEL, 0, "test text", 10,180,300,19, 0, 0, 0, 0, 0, ""); } static void action_blockhandlers(ScrArea *sa) { SpaceAction *sact= sa->spacedata.first; short a; for(a=0; ablockhandler[a]) { case ACTION_HANDLER_PROPERTIES: action_panel_properties(sact->blockhandler[a+1]); break; } /* clear action value for event */ sact->blockhandler[a+1]= 0; } uiDrawBlocksPanels(sa, 0); } void drawactionspace(ScrArea *sa, void *spacedata) { short ofsx = 0, ofsy = 0; Key *key; float col[3]; short maxymin; if (!G.saction) return; /* warning; blocks need to be freed each time, handlers dont remove */ uiFreeBlocksWin(&sa->uiblocks, sa->win); 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) ; calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy); /* background color for entire window (used in lefthand part tho) */ BIF_GetThemeColor3fv(TH_HEADER, col); glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) { 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); } } BIF_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax); bwin_clear_viewmat(sa->win); /* clear buttons view */ glLoadIdentity(); /* Draw backdrop */ calc_ipogrid(); draw_ipogrid(); /* 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); draw_cfra_action(); /* Draw scroll */ mywinset(curarea->win); // reset scissor too if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) { myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375); 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); } mywinset(curarea->win); // reset scissor too myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375); draw_area_emboss(sa); /* it is important to end a view in a transform compatible with buttons */ bwin_scalematrix(sa->win, G.saction->blockscale, G.saction->blockscale, G.saction->blockscale); action_blockhandlers(sa); curarea->win_swap= WIN_BACK_OK; } /* unused and blank void draw_channel_name(const char* name, short type, float ypos, int selected) { } */ static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos) { int v; if (!blist) return; for (v = 0; vvec[1][0] != blist[v-1]->vec[1][0])){ int sc_x, sc_y; gla2DDrawTranslatePt(di, blist[v]->vec[1][0], ypos, &sc_x, &sc_y); draw_bevel_but(sc_x-2, sc_y-5, 7, 13, (blist[v]->f2 & 1)); } } } void draw_object_channel(gla2DDrawInfo *di, Object *ob, int flags, float ypos) { BezTriple **blist; int totvert; blist = ob_to_keylist(ob, flags, &totvert); if (blist){ draw_keylist(di,totvert, blist, ypos); MEM_freeN(blist); } } void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, int flags, float ypos) { BezTriple **blist; int totvert; blist = ipo_to_keylist(ipo, flags, &totvert); if (blist){ draw_keylist(di,totvert, blist, ypos); MEM_freeN(blist); } } 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; int totvert; blist = action_to_keylist(act, flags, &totvert); if (blist){ draw_keylist(di,totvert, blist, ypos); MEM_freeN(blist); } } static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert) { IpoCurve *icu; int v, count=0; BezTriple **list = NULL; if (ob){ /* Count Object Keys */ if (ob->ipo){ for (icu=ob->ipo->curve.first; icu; icu=icu->next){ count+=icu->totvert; } } /* Count Constraint Keys */ /* Count object data keys */ /* Build the list */ if (count){ list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist"); count=0; /* Add object keyframes */ for (icu=ob->ipo->curve.first; icu; icu=icu->next){ for (v=0; vtotvert; v++){ list[count++]=&icu->bezt[v]; } } /* Add constraint keyframes */ /* Add object data keyframes */ /* Sort */ qsort(list, count, sizeof(BezTriple*), bezt_compare); } } (*totvert)=count; 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; vtotvert; 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; int v, count=0; BezTriple **list = NULL; if (ipo){ /* Count required keys */ for (icu=ipo->curve.first; icu; icu=icu->next){ count+=icu->totvert; } /* Build the list */ if (count){ list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist"); count=0; for (icu=ipo->curve.first; icu; icu=icu->next){ for (v=0; vtotvert; v++){ list[count++]=&icu->bezt[v]; } } qsort(list, count, sizeof(BezTriple*), bezt_compare); } } (*totvert)=count; return list; } static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert) { IpoCurve *icu; bActionChannel *achan; bConstraintChannel *conchan; int v, count=0; BezTriple **list = NULL; if (act){ /* Count required keys */ for (achan=act->chanbase.first; achan; achan=achan->next){ /* Count transformation keys */ if(achan->ipo) { for (icu=achan->ipo->curve.first; icu; icu=icu->next) count+=icu->totvert; /* Count constraint keys */ for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) for (icu=conchan->ipo->curve.first; icu; icu=icu->next) count+=icu->totvert; } } /* Build the list */ if (count){ list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist"); count=0; for (achan=act->chanbase.first; achan; achan=achan->next){ /* Add transformation keys */ for (icu=achan->ipo->curve.first; icu; icu=icu->next){ for (v=0; vtotvert; v++) list[count++]=&icu->bezt[v]; } /* Add constraint keys */ for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){ for (icu=conchan->ipo->curve.first; icu; icu=icu->next) for (v=0; vtotvert; v++) list[count++]=&icu->bezt[v]; } } qsort(list, count, sizeof(BezTriple*), bezt_compare); } } (*totvert)=count; return list; }