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