80af4d27676d2b6f859b520d0971661ff92c8312
[blender.git] / source / blender / src / drawaction.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  * Drawing routines for the Action window type
32  */
33
34 /* System includes ----------------------------------------------------- */
35
36 #include <math.h>
37 #include <stdlib.h>
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #ifdef WIN32
44 #include "BLI_winstuff.h"
45 #endif
46
47 #include "MEM_guardedalloc.h"
48
49 #include "BMF_Api.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_arithb.h"
53
54 /* Types --------------------------------------------------------------- */
55 #include "DNA_action_types.h"
56 #include "DNA_curve_types.h"
57 #include "DNA_ipo_types.h"
58 #include "DNA_object_types.h"
59 #include "DNA_screen_types.h"
60 #include "DNA_scene_types.h"
61 #include "DNA_space_types.h"
62 #include "DNA_constraint_types.h"
63
64 #include "BKE_action.h"
65 #include "BKE_global.h"
66
67 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
68
69 #include "BIF_gl.h"
70 #include "BIF_glutil.h"
71 #include "BIF_resources.h"
72 #include "BIF_screen.h"
73 #include "BIF_interface.h"
74 #include "BIF_mywindow.h"
75
76 #include "BDR_editcurve.h"
77 #include "BSE_view.h"
78 #include "BSE_drawipo.h"
79 #include "BSE_editaction_types.h"
80 #include "BDR_drawaction.h"
81
82 /* 'old' stuff": defines and types, and own include -------------------- */
83
84 #include "blendef.h"
85
86 /* local functions ----------------------------------------------------- */
87 void drawactionspace(ScrArea *sa, void *spacedata);
88 static void draw_channel_names(void);
89 static void draw_channel_strips(SpaceAction *saction);
90 int count_action_levels(bAction *act);
91 static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert);
92 static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert);
93 static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert);
94 static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos);
95
96
97 /* implementation ------------------------------------------------------ */
98 void draw_cfra_action(void)
99 {
100         Object *ob;
101         float vec[2];
102         
103         vec[0]= (G.scene->r.cfra);
104         vec[0]*= G.scene->r.framelen;
105         
106         vec[1]= G.v2d->cur.ymin;
107         glColor3ub(0x60, 0xc0, 0x40);
108         glLineWidth(2.0);
109         
110         glBegin(GL_LINE_STRIP);
111         glVertex2fv(vec);
112         vec[1]= G.v2d->cur.ymax;
113         glVertex2fv(vec);
114         glEnd();
115         
116         ob= (G.scene->basact) ? (G.scene->basact->object) : 0;
117         if(ob && ob->sf!=0.0 && (ob->ipoflag & OB_OFFS_OB) ) {
118                 vec[0]-= ob->sf;
119                 
120                 glColor3ub(0x10, 0x60, 0);
121                 
122                 glBegin(GL_LINE_STRIP);
123                 glVertex2fv(vec);
124                 vec[1]= G.v2d->cur.ymin;
125                 glVertex2fv(vec);
126                 glEnd();
127         }
128         
129         glLineWidth(1.0);
130 }
131
132 static void draw_channel_names(void) 
133 {
134         short ofsx, ofsy = 0; 
135
136         bAction *act;
137         bActionChannel *chan;
138         bConstraintChannel *conchan;
139         float   x, y;
140         
141         myortho2                (0,     ACTWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);    //      Scaling
142
143         /* Blank out the area */
144         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
145                 if(G.v2d->scroll) {     
146                         ofsx= curarea->winrct.xmin;     
147                         ofsy= curarea->winrct.ymin;
148                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin-SCROLLB, ACTWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB)); 
149                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin-SCROLLB, ACTWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));
150                 }
151         }
152         
153         glClearColor(.8, .8, .8, 0.0); 
154         glClear(GL_COLOR_BUFFER_BIT);
155
156         /* Clip to the scrollable area */
157
158         glColor3ub(0x00, 0x00, 0x00);
159
160         act=G.saction->action;
161         x = 0.0;
162
163         if (act) {              
164                 y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
165
166                 for (chan=act->chanbase.first; chan; chan=chan->next){
167                         glColor3ub(0xAA, 0xAA, 0xAA);
168                         glRectf(x,  y-CHANNELHEIGHT/2,  (float)ACTWIDTH,  y+CHANNELHEIGHT/2);
169
170                         if (chan->flag & ACHAN_SELECTED)
171                                 glColor3ub(255, 255, 255);
172                         else
173                                 glColor3ub(0, 0, 0);
174                         glRasterPos2f(x+8,  y-4);
175                         BMF_DrawString(G.font, chan->name);
176                         y-=CHANNELHEIGHT+CHANNELSKIP;
177
178                         /* Draw constraint channels */
179                         for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
180                                 if (conchan->flag & CONSTRAINT_CHANNEL_SELECT)
181                                         glColor3ub(255, 255, 255);
182                                 else
183                                         glColor3ub(0, 0, 0);
184                                 
185                                 glRasterPos2f(x+32,  y-4);
186                                 BMF_DrawString(G.font, conchan->name);
187                                 y-=CHANNELHEIGHT+CHANNELSKIP;
188                         }
189                 }
190         }
191         
192
193         myortho2                (0,     ACTWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB));        //      Scaling
194
195         glShadeModel(GL_SMOOTH);
196  
197         y=9;
198
199         /* Draw sexy shaded block thingies */
200         glEnable (GL_BLEND);
201         glBegin(GL_QUAD_STRIP);
202         glColor4ub (0xCC,0xCC,0xCC,0x00);
203         glVertex2f (0,SCROLLB*2-y);
204         glVertex2f (ACTWIDTH,SCROLLB*2-y);
205
206         glColor4ub (0xCC,0xCC,0xCC,0xFF);
207         glVertex2f (0,SCROLLB-y);
208         glVertex2f (ACTWIDTH,SCROLLB-y);
209
210         glColor4ub (0xCC,0xCC,0xCC,0xFF);
211         glVertex2f (0,0-y);
212         glVertex2f (ACTWIDTH,0-y);
213
214         glEnd();
215
216 /*      y=( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin-SCROLLB);
217
218         glBegin(GL_QUAD_STRIP);
219         glColor4ub (0x88,0x88,0x88,0xFF);
220         glVertex2f (0,y);
221         glVertex2f (ACTWIDTH,y);
222         glColor4ub (0x88,0x88,0x88,0x00);
223         glVertex2f (0,y-SCROLLB);
224         glVertex2f (ACTWIDTH,y-SCROLLB);
225         
226         glEnd();
227 */
228         glDisable (GL_BLEND);
229
230         glShadeModel(GL_FLAT);
231
232 }
233
234 int count_action_levels(bAction *act)
235 {
236         int y=0;
237         bActionChannel *achan;
238
239         if (!act)
240                 return 0;
241
242         for (achan=act->chanbase.first; achan; achan=achan->next){
243                 y+=1;
244                 y+=BLI_countlist(&achan->constraintChannels);
245         }
246
247         return y;
248 }
249         /** Draw a nicely beveled button (in screen space) */
250 void draw_bevel_but(int x, int y, int w, int h, int sel)
251 {
252         int xmin= x, ymin= y;
253         int xmax= x+w-1, ymax= y+h-1;
254         int i;
255
256         glColor3ub(0,0,0);
257         glBegin(GL_LINE_LOOP);
258         glVertex2i(xmin, ymin);
259         glVertex2i(xmax, ymin);
260         glVertex2i(xmax, ymax);
261         glVertex2i(xmin, ymax);
262         glEnd();
263
264         glBegin(GL_LINE_LOOP);
265         if (sel) glColor3ub(0xD0, 0x7E, 0x06);
266         else glColor3ub(0x8C, 0x8C, 0x8C);
267         glVertex2i(xmax-1, ymin+1);
268         glVertex2i(xmax-1, ymax-1);
269         if (sel) glColor3ub(0xF4, 0xEE, 0x8E);
270         else glColor3ub(0xDF, 0xDF, 0xDF);
271         glVertex2i(xmin+1, ymax-1);
272         glVertex2i(xmin+1, ymin+1);
273         glEnd();
274
275         if (sel) glColor3ub(0xF1, 0xCA, 0x13);
276         else glColor3ub(0xAC, 0xAC, 0xAC);
277         glBegin(GL_LINES);
278         for (i=xmin+2; i<=xmax-2; i++) {
279                 glVertex2f(i, ymin+2);
280                 glVertex2f(i, ymax-1);
281         }
282         glEnd();
283 }
284
285 static void draw_channel_strips(SpaceAction *saction)
286 {
287         rcti scr_rct;
288         gla2DDrawInfo *di;
289         bAction *act;
290         bActionChannel *chan;
291         bConstraintChannel *conchan;
292         float   y;
293
294         act= saction->action;
295         if (!act)
296                 return;
297
298         scr_rct.xmin= saction->area->winrct.xmin + ACTWIDTH;
299         scr_rct.ymin= saction->area->winrct.ymin + saction->v2d.mask.ymin-SCROLLB;
300         scr_rct.xmax= saction->area->winrct.xmin + saction->v2d.hor.xmax;
301         scr_rct.ymax= saction->area->winrct.ymin + saction->v2d.mask.ymax; 
302         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
303
304         y= count_action_levels(act)*(CHANNELHEIGHT+CHANNELSKIP);
305
306         for (chan=act->chanbase.first; chan; chan=chan->next){
307                 int frame1_x, channel_y;
308
309                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
310
311                 glEnable(GL_BLEND);
312                 if (chan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x22);
313                 else glColor4b(0x55, 0x22, 0x11, 0x22);
314                 glRectf(0,  channel_y-CHANNELHEIGHT/2,  frame1_x,  channel_y+CHANNELHEIGHT/2);
315
316                 if (chan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44);
317                 else glColor4b(0x55, 0x22, 0x11, 0x44);
318                 glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2);
319                 glDisable(GL_BLEND);
320         
321                 draw_ipo_channel(di, chan->ipo, 0, y);
322
323                 /*      Increment the step */
324                 y-=CHANNELHEIGHT+CHANNELSKIP;
325
326
327                 /* Draw constraint channels */
328                 for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){
329                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
330                         glEnable(GL_BLEND);
331                         if (conchan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x22);
332                         else glColor4b(0x55, 0x22, 0x11, 0x22);
333                         glRectf(0,  channel_y-CHANNELHEIGHT/2+4,  frame1_x,  channel_y+CHANNELHEIGHT/2-4);
334                         
335                         if (conchan->flag & ACHAN_SELECTED) glColor4b(0x11, 0x22, 0x55, 0x44);
336                         else glColor4b(0x55, 0x22, 0x11, 0x44);
337                         glRectf(frame1_x,  channel_y-CHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+CHANNELHEIGHT/2-4);
338                         glDisable(GL_BLEND);
339                         
340                         draw_ipo_channel(di, conchan->ipo, 0, y);
341                         y-=CHANNELHEIGHT+CHANNELSKIP;
342                 }
343         }
344
345         glaEnd2DDraw(di);
346 }
347
348 void drawactionspace(ScrArea *sa, void *spacedata)
349 {
350
351         short ofsx = 0, ofsy = 0;
352         
353         if (!G.saction)
354                 return;
355
356
357         if (!G.saction->pin) {
358                 if (OBACT)
359                         G.saction->action = OBACT->action;
360                 else
361                         G.saction->action=NULL;
362         }
363
364         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
365
366         calc_scrollrcts(G.v2d, curarea->winx, curarea->winy);
367
368         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
369                 if(G.v2d->scroll) {     
370                         ofsx= curarea->winrct.xmin;     
371                         ofsy= curarea->winrct.ymin;
372                         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); 
373                         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);
374                 }
375         }
376
377         glClearColor(.45, .45, .45, 0.0); 
378         glClear(GL_COLOR_BUFFER_BIT);
379
380         myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
381
382         /*      Draw backdrop */
383         calc_ipogrid(); 
384         draw_ipogrid();
385
386         /* Draw channel strips */
387         draw_channel_strips(G.saction);
388
389         /* Draw current frame */
390         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); 
391         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);
392         myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
393         draw_cfra_action();
394
395         /* Draw scroll */
396         mywinset(curarea->win);
397         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
398                 myortho2(-0.5, curarea->winx+0.5, -0.5, curarea->winy+0.5);
399                 if(G.v2d->scroll) drawscroll(0);
400         }
401
402         /* Draw channel names */
403         draw_channel_names();
404
405         curarea->win_swap= WIN_BACK_OK;
406 }
407
408 void draw_channel_name(const char* name, short type, float ypos, int selected)
409 {
410 }
411
412 static void draw_keylist(gla2DDrawInfo *di, int totvert, BezTriple **blist, float ypos)
413 {
414         int v;
415
416         if (!blist)
417                 return;
418
419         for (v = 0; v<totvert; v++){
420                 if (v==0 || (blist[v]->vec[1][0] != blist[v-1]->vec[1][0])){
421                         int sc_x, sc_y;
422                         gla2DDrawTranslatePt(di, blist[v]->vec[1][0], ypos, &sc_x, &sc_y);
423                         draw_bevel_but(sc_x-2, sc_y-5, 7, 13, (blist[v]->f2 & 1));
424                 }
425         }                       
426 }
427
428 void draw_object_channel(gla2DDrawInfo *di, Object *ob, int flags, float ypos)
429 {
430         BezTriple **blist;
431         int totvert;
432
433         blist = ob_to_keylist(ob, flags, &totvert);
434         if (blist){
435                 draw_keylist(di,totvert, blist, ypos);
436                 MEM_freeN(blist);
437         }
438 }
439
440 void draw_ipo_channel(gla2DDrawInfo *di, Ipo *ipo, int flags, float ypos)
441 {
442         BezTriple **blist;
443         int totvert;
444
445         blist = ipo_to_keylist(ipo, flags, &totvert);
446         if (blist){
447                 draw_keylist(di,totvert, blist, ypos);
448                 MEM_freeN(blist);
449         }
450 }
451
452 void draw_action_channel(gla2DDrawInfo *di, bAction *act, int flags, float ypos)
453 {
454         BezTriple **blist;
455         int totvert;
456
457         blist = action_to_keylist(act, flags, &totvert);
458         if (blist){
459                 draw_keylist(di,totvert, blist, ypos);
460                 MEM_freeN(blist);
461         }
462 }
463
464 static BezTriple **ob_to_keylist(Object *ob, int flags, int *totvert)
465 {
466         IpoCurve *icu;
467         int v, count=0;
468
469         BezTriple **list = NULL;
470
471         if (ob){
472
473                 /* Count Object Keys */
474                 if (ob->ipo){
475                         for (icu=ob->ipo->curve.first; icu; icu=icu->next){
476                                 count+=icu->totvert;
477                         }
478                 }
479                 
480                 /* Count Constraint Keys */
481                 /* Count object data keys */
482
483                 /* Build the list */
484                 if (count){
485                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
486                         count=0;
487                         
488                         /* Add object keyframes */
489                         for (icu=ob->ipo->curve.first; icu; icu=icu->next){
490                                 for (v=0; v<icu->totvert; v++){
491                                         list[count++]=&icu->bezt[v];
492                                 }
493                         }
494                         
495                         /* Add constraint keyframes */
496                         /* Add object data keyframes */
497
498                         /* Sort */
499                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
500                 }
501         }
502         (*totvert)=count;
503         return list;
504 }
505
506 static BezTriple **ipo_to_keylist(Ipo *ipo, int flags, int *totvert)
507 {
508         IpoCurve *icu;
509         int v, count=0;
510
511         BezTriple **list = NULL;
512
513         if (ipo){
514                 /* Count required keys */
515                 for (icu=ipo->curve.first; icu; icu=icu->next){
516                         count+=icu->totvert;
517                 }
518                 
519                 /* Build the list */
520                 if (count){
521                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
522                         count=0;
523                         
524                         for (icu=ipo->curve.first; icu; icu=icu->next){
525                                 for (v=0; v<icu->totvert; v++){
526                                         list[count++]=&icu->bezt[v];
527                                 }
528                         }                       
529                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
530                 }
531         }
532         (*totvert)=count;
533         return list;
534 }
535
536 static BezTriple **action_to_keylist(bAction *act, int flags, int *totvert)
537 {
538         IpoCurve *icu;
539         bActionChannel *achan;
540         bConstraintChannel *conchan;
541         int v, count=0;
542
543         BezTriple **list = NULL;
544
545         if (act){
546                 /* Count required keys */
547                 for (achan=act->chanbase.first; achan; achan=achan->next){
548                         /* Count transformation keys */
549                         for (icu=achan->ipo->curve.first; icu; icu=icu->next)
550                                 count+=icu->totvert;
551                         
552                         /* Count constraint keys */
553                         for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
554                                 for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
555                                         count+=icu->totvert;
556                         
557
558                 }
559                 
560                 /* Build the list */
561                 if (count){
562                         list = MEM_callocN(sizeof(BezTriple*)*count, "beztlist");
563                         count=0;
564                         
565                         for (achan=act->chanbase.first; achan; achan=achan->next){
566                                 /* Add transformation keys */
567                                 for (icu=achan->ipo->curve.first; icu; icu=icu->next){
568                                         for (v=0; v<icu->totvert; v++)
569                                                 list[count++]=&icu->bezt[v];
570                                 }
571                                         
572                                         /* Add constraint keys */
573                                 for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next){
574                                         for (icu=conchan->ipo->curve.first; icu; icu=icu->next)
575                                                 for (v=0; v<icu->totvert; v++)
576                                                         list[count++]=&icu->bezt[v];
577                                 }
578                                                         
579                         }               
580                         qsort(list, count, sizeof(BezTriple*), bezt_compare);
581                         
582                 }
583         }
584         (*totvert)=count;
585         return list;
586 }
587