diff options
Diffstat (limited to 'source/blender/src/drawaction.c')
-rw-r--r-- | source/blender/src/drawaction.c | 583 |
1 files changed, 583 insertions, 0 deletions
diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c new file mode 100644 index 00000000000..77319e5804b --- /dev/null +++ b/source/blender/src/drawaction.c @@ -0,0 +1,583 @@ +/** + * $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 <math.h> +#include <stdlib.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#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 "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 "BDR_editcurve.h" +#include "BSE_view.h" +#include "BSE_drawipo.h" +#include "BSE_editaction_types.h" +#include "BDR_drawaction.h" + +/* 'old' stuff": defines and types, and own include -------------------- */ + +#include "blendef.h" + +/* local functions ----------------------------------------------------- */ +void drawactionspace(void); +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 void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos); + + +/* implementation ------------------------------------------------------ */ +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_channel_names(void) +{ + short ofsx, ofsy = 0; + + bAction *act; + bActionChannel *chan; + bConstraintChannel *conchan; + float x, y; + + myortho2 (0, ACTWIDTH, 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)); + } + } + + glClearColor(.8, .8, .8, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* Clip to the scrollable area */ + + 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); + + 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); + + glEnd(); +*/ + glDisable (GL_BLEND); + + glShadeModel(GL_FLAT); + +} + +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; + + 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-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); + + 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(0x11, 0x22, 0x55, 0x22); + else glColor4b(0x55, 0x22, 0x11, 0x22); + glRectf(0, channel_y-CHANNELHEIGHT/2, frame1_x, channel_y+CHANNELHEIGHT/2); + + if (chan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44); + else glColor4b(0x55, 0x22, 0x11, 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(0x11, 0x22, 0x55, 0x22); + else glColor4b(0x55, 0x22, 0x11, 0x22); + glRectf(0, channel_y-CHANNELHEIGHT/2+4, frame1_x, channel_y+CHANNELHEIGHT/2-4); + + if (conchan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44); + else glColor4b(0x55, 0x22, 0x11, 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); +} + +void drawactionspace(void) +{ + + short ofsx = 0, ofsy = 0; + + if (!G.saction) + return; + + + if (!G.saction->pin) { + if (OBACT) + G.saction->action = OBACT->action; + else + G.saction->action=NULL; + } + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ; + + calc_scrollrcts(G.v2d, curarea->winx, curarea->winy); + + 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); + } + } + + 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); + + /* Draw backdrop */ + calc_ipogrid(); + draw_ipogrid(); + + /* Draw channel strips */ + draw_channel_strips(G.saction); + + /* 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); + 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); + } + + /* Draw channel names */ + draw_channel_names(); + + curarea->win_swap= WIN_BACK_OK; +} + +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; v<totvert; v++){ + if (v==0 || (blist[v]->vec[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_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; v<icu->totvert; 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 **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; v<icu->totvert; 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 */ + 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; v<icu->totvert; 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; v<icu->totvert; v++) + list[count++]=&icu->bezt[v]; + } + + } + qsort(list, count, sizeof(BezTriple*), bezt_compare); + + } + } + (*totvert)=count; + return list; +} + |