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