Stage two of the giant animation recode project; Ipo/Action/NLA cleanup
[blender.git] / source / blender / src / drawnla.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  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #ifdef _WIN32
38 #pragma warning (once : 4761)
39 #endif
40
41 #include "BMF_Api.h"
42
43 #include <stdlib.h>
44 #include <stdio.h>
45
46 #include "DNA_view3d_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_space_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_object_types.h"
51 #include "DNA_curve_types.h"
52 #include "DNA_ipo_types.h"
53 #include "DNA_action_types.h"
54 #include "DNA_nla_types.h"
55 #include "DNA_constraint_types.h"
56
57 #include "BLI_blenlib.h"
58 #include "MEM_guardedalloc.h"
59
60 #include "BKE_action.h"
61 #include "BKE_global.h"
62
63 #include "BSE_drawnla.h"
64 #include "BSE_drawipo.h"
65 #include "BSE_editnla_types.h"
66 #include "BSE_headerbuttons.h"
67
68 #include "BIF_gl.h"
69 #include "BIF_resources.h"
70 #include "BIF_screen.h"
71 #include "BIF_mywindow.h"
72 #include "BIF_space.h"
73 #include "BIF_interface.h"
74 #include "BIF_glutil.h"
75
76 #include "BDR_drawaction.h"
77 #include "BDR_editcurve.h"
78
79 #include "blendef.h"
80 #include "mydevice.h"
81
82 #define TESTBASE_SAFE(base)     ((base)->flag & SELECT)
83
84 /* the left hand side with channels only */
85 static void draw_nla_channels(void)
86 {
87         bActionStrip *strip;
88         Base *base;
89         Object *ob;
90         float   x, y;
91         short ofsx, ofsy = 0; 
92
93         myortho2(0,     NLAWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);    //      Scaling
94
95         /* Clip to the scrollable area */
96         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
97                 if(G.v2d->scroll) {     
98                         ofsx= curarea->winrct.xmin;     
99                         ofsy= curarea->winrct.ymin;
100                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin, NLAWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin)); 
101                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin, NLAWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin));
102                 }
103         }
104         
105         glColor3ub(0x00, 0x00, 0x00);
106         
107         x = 0.0;
108         y = count_nla_levels();
109         y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
110         
111         for (base=G.scene->base.first; base; base=base->next){
112                 if (nla_filter(base)) {
113                         ob= base->object;
114                         
115                         BIF_ThemeColorShade(TH_HEADER, 20);
116                         glRectf(x,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
117
118                         /* Draw the name / ipo timeline*/
119                         if (TESTBASE_SAFE(base))
120                                 BIF_ThemeColor(TH_TEXT_HI);
121                         else
122                                 BIF_ThemeColor(TH_TEXT);
123                         glRasterPos2f(x+21,  y-4);
124
125                         BMF_DrawString(G.font, ob->id.name+2);
126                         
127                         /* icon to indicate nla or action */
128                         if(ob->nlastrips.first && ob->action) {
129                                 if(ob->nlaflag & OB_NLA_OVERRIDE)
130                                         BIF_draw_icon(x+5, y-8, ICON_NLA);
131                                 else
132                                         BIF_draw_icon(x+5, y-8, ICON_ACTION);
133                         }                       
134                         y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
135                         
136                         /* Draw the action timeline */
137                         if (ob->action){
138                                 BIF_ThemeColorShade(TH_HEADER, -20);
139                                 glRectf(x+16,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
140
141                                 if (TESTBASE_SAFE(base))
142                                         BIF_ThemeColor(TH_TEXT_HI);
143                                 else
144                                         BIF_ThemeColor(TH_TEXT);
145                                 glRasterPos2f(x+32,  y-4);
146                                 BMF_DrawString(G.font, ob->action->id.name+2);
147                                 
148                                 y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
149                         }
150
151                         /* Draw the nla strips */
152                         for (strip = ob->nlastrips.first; strip; strip=strip->next){
153                                 BIF_ThemeColorShade(TH_HEADER, -40);
154                                 glRectf(x+32,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
155
156                                 if (TESTBASE_SAFE(base))
157                                         BIF_ThemeColor(TH_TEXT_HI);
158                                 else
159                                         BIF_ThemeColor(TH_TEXT);
160
161                                 // why this test? check freeing mem when deleting strips? (ton)
162                                 if(strip->act) {
163                                         glRasterPos2f(x+48,  y-4);
164                                         BMF_DrawString(G.font, strip->act->id.name+2);
165                                         
166                                         if(strip->flag & ACTSTRIP_ACTIVE) {
167                                                 glEnable(GL_BLEND);
168                                                 BIF_draw_icon_blended(x+16, y-8, ICON_DOT, TH_BACK, 0);
169                                                 glDisable(GL_BLEND);
170                                         }
171                                 }
172                                 y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
173                         }
174                 }
175         }
176         
177         myortho2(0,     NLAWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin));        //      Scaling
178 }
179
180 void map_active_strip(gla2DDrawInfo *di, Object *ob, int restore)
181 {
182         static rctf stored;
183         
184         if(restore)
185                 gla2DSetMap(di, &stored);
186         else {
187                 rctf map;
188                 
189                 gla2DGetMap(di, &stored);
190                 map= stored;
191                 map.xmin= get_action_frame(ob, map.xmin);
192                 map.xmax= get_action_frame(ob, map.xmax);
193                 gla2DSetMap(di, &map);
194         }
195 }
196
197 /* the right hand side, with strips and keys */
198 static void draw_nla_strips_keys(SpaceNla *snla)
199 {
200         Base *base;
201         rcti scr_rct;
202         gla2DDrawInfo *di;
203         float   y;
204         char col1[3], col2[3];
205         
206         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
207         BIF_GetThemeColor3ubv(TH_HILITE, col1);
208         
209         /* Draw strips */
210
211         scr_rct.xmin= snla->area->winrct.xmin + snla->v2d.mask.xmin;
212         scr_rct.ymin= snla->area->winrct.ymin + snla->v2d.mask.ymin;
213         scr_rct.xmax= snla->area->winrct.xmin + snla->v2d.hor.xmax;
214         scr_rct.ymax= snla->area->winrct.ymin + snla->v2d.mask.ymax; 
215         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
216         
217         y=count_nla_levels();
218         y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
219         
220         for (base=G.scene->base.first; base; base=base->next){
221                 Object *ob= base->object;
222                 bActionStrip *strip;
223                 int frame1_x, channel_y;
224                 
225                 if (nla_filter(base)) {
226                         
227                         /* Draw the field */
228                         glEnable (GL_BLEND);
229                         if (TESTBASE_SAFE(base))
230                                 glColor4ub (col1[0], col1[1], col1[2], 0x22);
231                         else
232                                 glColor4ub (col2[0], col2[1], col2[2], 0x22);
233                         
234                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
235                         glRectf(0,  channel_y-NLACHANNELHEIGHT/2,  frame1_x,  channel_y+NLACHANNELHEIGHT/2);
236                         
237                         
238                         if (TESTBASE_SAFE(base))
239                                 glColor4ub (col1[0], col1[1], col1[2], 0x44);
240                         else
241                                 glColor4ub (col2[0], col2[1], col2[2], 0x44);
242                         glRectf(frame1_x,  channel_y-NLACHANNELHEIGHT/2,   G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2);
243                         
244                         glDisable (GL_BLEND);
245                         
246                         /* Draw the ipo keys */
247                         draw_object_channel(di, ob, 0, y);
248                         
249                         y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
250                 }
251                                 
252                 /* Draw the action strip */
253                 if (ob->action){
254                         
255                         /* Draw the field */
256                         glEnable (GL_BLEND);
257                         if (TESTBASE_SAFE(base))
258                                 glColor4ub (col1[0], col1[1], col1[2], 0x22);
259                         else
260                                 glColor4ub (col2[0], col2[1], col2[2], 0x22);
261                         
262                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
263                         glRectf(0,  channel_y-NLACHANNELHEIGHT/2+4,  frame1_x,  channel_y+NLACHANNELHEIGHT/2-4);
264                         
265                         if (TESTBASE_SAFE(base))
266                                 glColor4ub (col1[0], col1[1], col1[2], 0x44);
267                         else
268                                 glColor4ub (col2[0], col2[1], col2[2], 0x44);
269                         glRectf(frame1_x,  channel_y-NLACHANNELHEIGHT/2+4,   G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2-4);
270                         
271                         glDisable (GL_BLEND);
272                         
273                         /* Draw the action keys, optionally corrected for active strip */
274                         map_active_strip(di, ob, 0);
275                         draw_action_channel(di, ob->action, 0, y);
276                         map_active_strip(di, ob, 1);
277                         
278                         y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
279                         
280                 }
281
282                 /* Draw the nla strips */
283                 for (strip=ob->nlastrips.first; strip; strip=strip->next){
284                         int stripstart, stripend;
285                         int blendstart, blendend;
286                         
287                         /* Draw rect */
288                         if (strip->flag & ACTSTRIP_SELECT)
289                                 BIF_ThemeColor(TH_STRIP_SELECT);
290                         else
291                                 BIF_ThemeColor(TH_STRIP);
292                         
293                         gla2DDrawTranslatePt(di, strip->start+strip->blendin, y, &stripstart, &channel_y);
294                         gla2DDrawTranslatePt(di, strip->end-strip->blendout, y, &stripend, &channel_y);
295                         glRectf(stripstart,  channel_y-NLACHANNELHEIGHT/2+3,  stripend,  channel_y+NLACHANNELHEIGHT/2-3);
296                         
297                         if (strip->flag & ACTSTRIP_SELECT)
298                                 BIF_ThemeColorShade(TH_STRIP_SELECT, -60);
299                         else
300                                 BIF_ThemeColorShade(TH_STRIP, -60);
301                         
302                         /* Draw blendin */
303                         if (strip->blendin>0){
304                                 glBegin(GL_TRIANGLES);
305                                 
306                                 gla2DDrawTranslatePt(di, strip->start, y, &blendstart, &channel_y);
307                                 
308                                 glVertex2f(blendstart, channel_y-NLACHANNELHEIGHT/2+3);
309                                 glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
310                                 glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
311                                 
312                                 
313                                 glEnd();
314                         }
315                         if (strip->blendout>0){
316                                 glBegin(GL_TRIANGLES);
317                                 
318                                 gla2DDrawTranslatePt(di, strip->end, y, &blendend, &channel_y);
319
320                                 glVertex2f(blendend, channel_y-NLACHANNELHEIGHT/2+3);
321                                 glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
322                                 glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
323                                 glEnd();
324                         }
325                         
326                         /* Draw border */
327                         glBegin(GL_LINE_STRIP);
328                         glColor4f(1, 1, 1, 0.5); 
329                         gla2DDrawTranslatePt(di, strip->start, y, &stripstart, &channel_y);
330                         gla2DDrawTranslatePt(di, strip->end, y, &stripend, &channel_y);
331                         
332                         glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
333                         glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
334                         glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
335                         glColor4f(0, 0, 0, 0.5); 
336                         glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
337                         glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
338                         glEnd();
339                         
340                         glEnable (GL_BLEND);
341
342                         /* Show strip extension */
343                         if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
344                                 if (strip->flag & ACTSTRIP_SELECT)
345                                         BIF_ThemeColorShadeAlpha(TH_STRIP_SELECT, 0, -180);
346                                 else
347                                         BIF_ThemeColorShadeAlpha(TH_STRIP, 0, -180);
348                                 
349                                 glRectf(stripend,  channel_y-NLACHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2-2);
350                         }
351                         
352                         /* Show repeat */
353                         if (strip->repeat > 1.0 && !(strip->flag & ACTSTRIP_USESTRIDE)){
354                                 float rep = 1;
355                                 glBegin(GL_LINES);
356                                 while (rep<strip->repeat){
357                                         /* Draw line */ 
358                                         glColor4f(0, 0, 0, 0.5); 
359                                         gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
360                                         glVertex2f(frame1_x, channel_y-NLACHANNELHEIGHT/2+4);
361                                         glVertex2f(frame1_x, channel_y+NLACHANNELHEIGHT/2-2);
362                                         
363                                         glColor4f(1.0, 1.0, 1.0, 0.5); 
364                                         gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
365                                         glVertex2f(frame1_x+1, channel_y-NLACHANNELHEIGHT/2+4);
366                                         glVertex2f(frame1_x+1, channel_y+NLACHANNELHEIGHT/2-2);
367                                         rep+=1.0;
368                                 }
369                                 glEnd();
370                                 
371                         }
372                         glDisable (GL_BLEND);
373                         
374                         y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
375                 }
376         }
377         glaEnd2DDraw(di);
378         
379 }
380
381 /* ******* panel *********** */
382
383 #define B_NLA_PANEL             121
384
385 /* For now just returns the first selected strip */
386 bActionStrip *get_active_nlastrip(void)
387 {
388         Base *base;
389         bActionStrip *strip;
390         
391         for (base=G.scene->base.first; base; base=base->next){
392                 for (strip=base->object->nlastrips.first; strip; strip=strip->next){
393                         if (strip->flag & ACTSTRIP_SELECT)
394                                 return strip;
395                 }
396         }
397         
398         return NULL;
399 }
400
401 void do_nlabuts(unsigned short event)
402 {
403         bActionStrip *strip;
404                 
405         /* Determine if an nla strip has been selected */
406         strip = get_active_nlastrip();
407         if (!strip) return;
408         
409         switch(event) {
410         case B_REDR:
411                 allqueue(REDRAWVIEW3D, 0);
412                 allqueue(REDRAWNLA, 0);
413                 break;
414         case B_NLA_PANEL:
415                 if (strip->end<strip->start)
416                         strip->end=strip->start;
417         
418         
419                 if (strip->blendin>(strip->end-strip->start))
420                         strip->blendin = strip->end-strip->start;
421         
422                 if (strip->blendout>(strip->end-strip->start))
423                         strip->blendout = strip->end-strip->start;
424         
425                 if (strip->blendin > (strip->end-strip->start-strip->blendout))
426                         strip->blendin = (strip->end-strip->start-strip->blendout);
427         
428                 if (strip->blendout > (strip->end-strip->start-strip->blendin))
429                         strip->blendout = (strip->end-strip->start-strip->blendin);
430                 
431                 
432                 update_for_newframe_muted();
433                 allqueue (REDRAWNLA, 0);
434                 allqueue (REDRAWVIEW3D, 0);
435                 
436                 break;
437         }
438 }
439
440 static void nla_panel_properties(short cntrl)   // NLA_HANDLER_PROPERTIES
441 {
442         bActionStrip *strip;
443         uiBlock *block;
444
445         block= uiNewBlock(&curarea->uiblocks, "nla_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
446         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
447         uiSetPanelHandler(NLA_HANDLER_PROPERTIES);  // for close and esc
448         if(uiNewPanel(curarea, block, "Transform Properties", "NLA", 10, 230, 318, 204)==0) return;
449
450         /* Determine if an nla strip has been selected */
451         strip = get_active_nlastrip();
452         if (!strip) return;
453         
454         /* first labels, for simpler align code :) */
455         uiDefBut(block, LABEL, 0, "Timeline Range:",    10,180,300,19, 0, 0, 0, 0, 0, "");
456         uiDefBut(block, LABEL, 0, "Action Range:",              10,140,300,19, 0, 0, 0, 0, 0, "");
457         uiDefBut(block, LABEL, 0, "Blending:",                  10,100,300,19, 0, 0, 0, 0, 0, "");
458         uiDefBut(block, LABEL, 0, "Options:",                   10,60,300,19, 0, 0, 0, 0, 0, "");
459
460         uiBlockBeginAlign(block);
461         uiDefButF(block, NUM, B_REDR, "Strip Start:", 10,160,150,19, &strip->start, -1000.0, MAXFRAMEF, 100, 0, "First frame in the timeline");
462         uiDefButF(block, NUM, B_REDR, "Strip End:",     160,160,150,19, &strip->end, -1000.0, MAXFRAMEF, 100, 0, "Last frame in the timeline");
463
464         uiBlockBeginAlign(block);
465         uiDefButF(block, NUM, B_REDR, "Action Start:", 10,120,150,19, &strip->actstart, 1.0, MAXFRAMEF, 100, 0, "First frame of the action to map to the playrange");
466         uiDefButF(block, NUM, B_REDR, "Action End:", 160,120,150,19, &strip->actend, 1.0, MAXFRAMEF, 100, 0, "Last frame of the action to map to the playrange");
467
468         uiBlockBeginAlign(block);
469         uiDefButF(block, NUM, B_REDR, "Blendin:",       10,80,150,19, &strip->blendin, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-in");
470         uiDefButF(block, NUM, B_REDR, "Blendout:",      160,80,150,19, &strip->blendout, 0.0, strip->actend-strip->actstart, 100, 0, "Number of frames of ease-out");
471
472         uiBlockBeginAlign(block);
473         uiDefButF(block, NUM, B_REDR, "Repeat:",        10,40,150,19, &strip->repeat, 0.0001, 1000.0f, 100, 0, "Number of times the action should repeat");
474         uiDefButF(block, NUM, B_REDR, "Stride:",        160,40,150,19, &strip->stridelen, 0.0001, 1000.0, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range");
475
476         uiBlockBeginAlign(block);
477         uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_REDR, "Use Path",        10,0,100,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride");
478         uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_REDR, "Hold",        110,0,100,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip");
479         uiDefButS(block, TOG, B_REDR, "Add",    210,0,100,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode");
480 }
481
482 static void nla_blockhandlers(ScrArea *sa)
483 {
484         SpaceNla *snla= sa->spacedata.first;
485         short a;
486         
487         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
488                 switch(snla->blockhandler[a]) {
489
490                 case NLA_HANDLER_PROPERTIES:
491                         nla_panel_properties(snla->blockhandler[a+1]);
492                         break;
493                 
494                 }
495                 /* clear action value for event */
496                 snla->blockhandler[a+1]= 0;
497         }
498         uiDrawBlocksPanels(sa, 0);
499 }
500
501
502 void drawnlaspace(ScrArea *sa, void *spacedata)
503 {
504         float col[3];
505         short ofsx = 0, ofsy = 0;
506         
507         uiFreeBlocksWin(&sa->uiblocks, sa->win);        /* for panel handler to work */
508
509         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
510         
511         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
512         
513         /* clear all, becomes the color for left part */
514         BIF_GetThemeColor3fv(TH_HEADER, col);
515         glClearColor(col[0], col[1], col[2], 0.0); 
516         glClear(GL_COLOR_BUFFER_BIT);
517         
518         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
519                 if(G.v2d->scroll) {     
520                         ofsx= curarea->winrct.xmin;     
521                         ofsy= curarea->winrct.ymin;
522                         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); 
523                         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);
524                 }
525         }
526         
527         BIF_GetThemeColor3fv(TH_BACK, col);
528         glClearColor(col[0], col[1], col[2], 0.0);
529         glClear(GL_COLOR_BUFFER_BIT);
530         
531         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
532         bwin_clear_viewmat(sa->win);    /* clear buttons view */
533         glLoadIdentity();
534         
535         /*      Draw backdrop */
536         calc_ipogrid(); 
537         draw_ipogrid();
538
539         /* the right hand side, with strips and keys */
540         draw_nla_strips_keys(G.snla);
541
542         /* Draw current frame */
543         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); 
544         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);
545         myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
546         draw_cfra_action();
547
548         /* Draw scroll */
549         mywinset(curarea->win); // reset scissor too
550         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
551                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
552                 if(G.v2d->scroll) drawscroll(0);
553         }
554         if(G.v2d->mask.xmin!=0) {
555                 /* Draw channel names */
556                 draw_nla_channels();
557         }
558         mywinset(curarea->win); // reset scissor too
559         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
560         draw_area_emboss(sa);
561         
562         /* it is important to end a view in a transform compatible with buttons */
563         bwin_scalematrix(sa->win, G.snla->blockscale, G.snla->blockscale, G.snla->blockscale);
564         nla_blockhandlers(sa);
565
566         curarea->win_swap= WIN_BACK_OK;
567 }
568
569 int count_nla_levels(void)
570 {
571         Base *base;
572         int y=0;
573
574         for (y=0, base=G.scene->base.first; base; base=base->next) {
575                 if (nla_filter(base)) {
576                         /* object level */
577                         y++;
578
579                         if(base->object->action)
580                                 y++;
581                         
582                         /* Nla strips */
583                         y+= BLI_countlist(&base->object->nlastrips);
584                 }
585         }
586
587         return y;
588 }
589
590 int nla_filter (Base *base)
591 {
592         Object *ob = base->object;
593         
594         if(ob->action || ob->nlastrips.first) 
595                 return 1;
596
597         /* should become option */
598         if (ob->ipo)
599                 return 1;
600
601         if (ob->constraintChannels.first)
602                 return 1;
603
604         return 0;
605 }
606