1ebb5417634ccfdfe35c1cca10b3e46d1e38e04b
[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 <string.h>
45 #include <stdio.h>
46
47 #include "DNA_view3d_types.h"
48 #include "DNA_screen_types.h"
49 #include "DNA_space_types.h"
50 #include "DNA_scene_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_curve_types.h"
53 #include "DNA_ipo_types.h"
54 #include "DNA_action_types.h"
55 #include "DNA_nla_types.h"
56 #include "DNA_constraint_types.h"
57
58 #include "BLI_blenlib.h"
59 #include "MEM_guardedalloc.h"
60
61 #include "BKE_action.h"
62 #include "BKE_depsgraph.h"
63 #include "BKE_global.h"
64
65 #include "BSE_drawnla.h"
66 #include "BSE_drawipo.h"
67 #include "BSE_editnla_types.h"
68 #include "BSE_headerbuttons.h"
69 #include "BSE_time.h"
70
71 #include "BIF_editnla.h"
72 #include "BIF_gl.h"
73 #include "BIF_glutil.h"
74 #include "BIF_interface.h"
75 #include "BIF_interface_icons.h"
76 #include "BIF_mywindow.h"
77 #include "BIF_resources.h"
78 #include "BIF_screen.h"
79 #include "BIF_space.h"
80
81 #include "BDR_drawaction.h"
82 #include "BDR_editcurve.h"
83
84 #include "blendef.h"
85 #include "butspace.h"
86 #include "mydevice.h"
87
88 #define TESTBASE_SAFE(base)     ((base)->flag & SELECT)
89
90 /* the left hand side with channels only */
91 static void draw_nla_channels(void)
92 {
93         bActionStrip *strip;
94         Base *base;
95         Object *ob;
96         float   x, y;
97         short ofsx, ofsy = 0; 
98
99         myortho2(0,     NLAWIDTH, G.v2d->cur.ymin, G.v2d->cur.ymax);    //      Scaling
100
101         /* Clip to the scrollable area */
102         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
103                 if(G.v2d->scroll) {     
104                         ofsx= curarea->winrct.xmin;     
105                         ofsy= curarea->winrct.ymin;
106                         glViewport(ofsx,  ofsy+G.v2d->mask.ymin, NLAWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin)); 
107                         glScissor(ofsx,  ofsy+G.v2d->mask.ymin, NLAWIDTH, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin));
108                 }
109         }
110         
111         glColor3ub(0x00, 0x00, 0x00);
112         
113         x = 0.0;
114         y = count_nla_levels();
115         y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
116         
117         for (base=G.scene->base.first; base; base=base->next){
118                 if (nla_filter(base)) {
119                         ob= base->object;
120                         
121                         BIF_ThemeColorShade(TH_HEADER, 20);
122                         glRectf(x,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
123
124                         /* Draw the name / ipo timeline*/
125                         if (TESTBASE_SAFE(base))
126                                 BIF_ThemeColor(TH_TEXT_HI);
127                         else
128                                 BIF_ThemeColor(TH_TEXT);
129                         glRasterPos2f(x+21,  y-4);
130
131                         BMF_DrawString(G.font, ob->id.name+2);
132                         
133                         /* icon to indicate nla or action */
134                         if(ob->nlastrips.first && ob->action) {
135                                 glEnable(GL_BLEND);
136                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
137                                 if(ob->nlaflag & OB_NLA_OVERRIDE)
138                                         BIF_icon_draw(x+5, y-8, ICON_NLA);
139                                 else
140                                         BIF_icon_draw(x+5, y-8, ICON_ACTION);
141                                 glDisable(GL_BLEND);
142                         }                       
143                         y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
144                         
145                         /* Draw the action timeline */
146                         if (ob->action){
147                                 BIF_ThemeColorShade(TH_HEADER, -20);
148                                 glRectf(x+16,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
149
150                                 if (TESTBASE_SAFE(base))
151                                         BIF_ThemeColor(TH_TEXT_HI);
152                                 else
153                                         BIF_ThemeColor(TH_TEXT);
154                                 glRasterPos2f(x+32,  y-4);
155                                 BMF_DrawString(G.font, ob->action->id.name+2);
156                                 
157                                 /* icon for active action (no strip mapping) */
158                                 for (strip = ob->nlastrips.first; strip; strip=strip->next)
159                                         if(strip->flag & ACTSTRIP_ACTIVE) break;
160                                 if(strip==NULL) {
161                                         glEnable(GL_BLEND);
162                                         BIF_icon_draw(x, y-8, ICON_DOT);
163                                         glDisable(GL_BLEND);
164                                 }
165                                 
166                                 y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
167                         }
168
169                         /* Draw the nla strips */
170                         for (strip = ob->nlastrips.first; strip; strip=strip->next){
171                                 BIF_ThemeColorShade(TH_HEADER, -40);
172                                 glRectf(x+32,  y-NLACHANNELHEIGHT/2,  (float)NLAWIDTH,  y+NLACHANNELHEIGHT/2);
173
174                                 if (TESTBASE_SAFE(base))
175                                         BIF_ThemeColor(TH_TEXT_HI);
176                                 else
177                                         BIF_ThemeColor(TH_TEXT);
178
179                                 // why this test? check freeing mem when deleting strips? (ton)
180                                 if(strip->act) {
181                                         glRasterPos2f(x+48,  y-4);
182                                         BMF_DrawString(G.font, strip->act->id.name+2);
183                                         
184                                         if(strip->flag & ACTSTRIP_ACTIVE) {
185                                                 glEnable(GL_BLEND);
186                                                 BIF_icon_draw(x+16, y-8, ICON_DOT);
187                                                 glDisable(GL_BLEND);
188                                         }
189                                         if(strip->modifiers.first) {
190                                                 glEnable(GL_BLEND);
191                                                 BIF_icon_draw(x+34, y-8, ICON_MODIFIER);
192                                                 glDisable(GL_BLEND);
193                                         }
194                                 }
195                                 
196                                 y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
197                         }
198                 }
199         }
200         
201         myortho2(0,     NLAWIDTH, 0, ( ofsy+G.v2d->mask.ymax)-( ofsy+G.v2d->mask.ymin));        //      Scaling
202 }
203
204 void map_active_strip(gla2DDrawInfo *di, Object *ob, int restore)
205 {
206         static rctf stored;
207         
208         if(restore)
209                 gla2DSetMap(di, &stored);
210         else {
211                 rctf map;
212                 
213                 gla2DGetMap(di, &stored);
214                 map= stored;
215                 map.xmin= get_action_frame(ob, map.xmin);
216                 map.xmax= get_action_frame(ob, map.xmax);
217                 if(map.xmin==map.xmax) map.xmax+= 1.0;
218                 gla2DSetMap(di, &map);
219         }
220 }
221
222 /* the right hand side, with strips and keys */
223 static void draw_nla_strips_keys(SpaceNla *snla)
224 {
225         Base *base;
226         rcti scr_rct;
227         gla2DDrawInfo *di;
228         float   y;
229         char col1[3], col2[3];
230         
231         BIF_GetThemeColor3ubv(TH_SHADE2, col2);
232         BIF_GetThemeColor3ubv(TH_HILITE, col1);
233         
234         /* Draw strips */
235
236         scr_rct.xmin= snla->area->winrct.xmin + snla->v2d.mask.xmin;
237         scr_rct.ymin= snla->area->winrct.ymin + snla->v2d.mask.ymin;
238         scr_rct.xmax= snla->area->winrct.xmin + snla->v2d.hor.xmax;
239         scr_rct.ymax= snla->area->winrct.ymin + snla->v2d.mask.ymax; 
240         di= glaBegin2DDraw(&scr_rct, &G.v2d->cur);
241         
242         y=count_nla_levels();
243         y*= (NLACHANNELHEIGHT+NLACHANNELSKIP);
244         
245         for (base=G.scene->base.first; base; base=base->next){
246                 Object *ob= base->object;
247                 bActionStrip *strip;
248                 int frame1_x, channel_y;
249                 
250                 if (nla_filter(base)==0)
251                         continue;
252                         
253                 /* Draw the field */
254                 glEnable (GL_BLEND);
255                 if (TESTBASE_SAFE(base))
256                         glColor4ub (col1[0], col1[1], col1[2], 0x22);
257                 else
258                         glColor4ub (col2[0], col2[1], col2[2], 0x22);
259                 
260                 gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
261                 glRectf(0,  channel_y-NLACHANNELHEIGHT/2,  frame1_x,  channel_y+NLACHANNELHEIGHT/2);
262                 
263                 
264                 if (TESTBASE_SAFE(base))
265                         glColor4ub (col1[0], col1[1], col1[2], 0x44);
266                 else
267                         glColor4ub (col2[0], col2[1], col2[2], 0x44);
268                 glRectf(frame1_x,  channel_y-NLACHANNELHEIGHT/2,   G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2);
269                 
270                 glDisable (GL_BLEND);
271                 
272                 /* Draw the ipo keys */
273                 draw_object_channel(di, ob, 0, y);
274                 
275                 y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
276                 
277                                 
278                 /* Draw the action strip */
279                 if (ob->action) {
280                         
281                         /* Draw the field */
282                         glEnable (GL_BLEND);
283                         if (TESTBASE_SAFE(base))
284                                 glColor4ub (col1[0], col1[1], col1[2], 0x22);
285                         else
286                                 glColor4ub (col2[0], col2[1], col2[2], 0x22);
287                         
288                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
289                         glRectf(0,  channel_y-NLACHANNELHEIGHT/2+4,  frame1_x,  channel_y+NLACHANNELHEIGHT/2-4);
290                         
291                         if (TESTBASE_SAFE(base))
292                                 glColor4ub (col1[0], col1[1], col1[2], 0x44);
293                         else
294                                 glColor4ub (col2[0], col2[1], col2[2], 0x44);
295                         glRectf(frame1_x,  channel_y-NLACHANNELHEIGHT/2+4,   G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2-4);
296                         
297                         glDisable (GL_BLEND);
298                         
299                         /* Draw the action keys, optionally corrected for active strip */
300                         map_active_strip(di, ob, 0);
301                         draw_action_channel(di, ob->action, 0, y);
302                         map_active_strip(di, ob, 1);
303                         
304                         y-=NLACHANNELHEIGHT+NLACHANNELSKIP;
305                         
306                 }
307
308                 /* Draw the nla strips */
309                 for (strip=ob->nlastrips.first; strip; strip=strip->next){
310                         int stripstart, stripend;
311                         int blendstart, blendend;
312                         
313                         /* Draw rect */
314                         if (strip->flag & ACTSTRIP_SELECT)
315                                 BIF_ThemeColor(TH_STRIP_SELECT);
316                         else
317                                 BIF_ThemeColor(TH_STRIP);
318                         
319                         gla2DDrawTranslatePt(di, strip->start+strip->blendin, y, &stripstart, &channel_y);
320                         gla2DDrawTranslatePt(di, strip->end-strip->blendout, y, &stripend, &channel_y);
321                         glRectf(stripstart,  channel_y-NLACHANNELHEIGHT/2+3,  stripend,  channel_y+NLACHANNELHEIGHT/2-3);
322                         
323                         if (strip->flag & ACTSTRIP_SELECT)
324                                 BIF_ThemeColorShade(TH_STRIP_SELECT, -60);
325                         else
326                                 BIF_ThemeColorShade(TH_STRIP, -60);
327                         
328                         /* Draw blendin */
329                         if (strip->blendin>0){
330                                 glBegin(GL_TRIANGLES);
331                                 
332                                 gla2DDrawTranslatePt(di, strip->start, y, &blendstart, &channel_y);
333                                 
334                                 glVertex2f(blendstart, channel_y-NLACHANNELHEIGHT/2+3);
335                                 glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
336                                 glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
337                                 
338                                 
339                                 glEnd();
340                         }
341                         if (strip->blendout>0){
342                                 glBegin(GL_TRIANGLES);
343                                 
344                                 gla2DDrawTranslatePt(di, strip->end, y, &blendend, &channel_y);
345
346                                 glVertex2f(blendend, channel_y-NLACHANNELHEIGHT/2+3);
347                                 glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
348                                 glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
349                                 glEnd();
350                         }
351                         
352                         gla2DDrawTranslatePt(di, strip->start, y, &stripstart, &channel_y);
353                         gla2DDrawTranslatePt(di, strip->end, y, &stripend, &channel_y);
354                         
355                         /* muted strip */
356                         if(strip->flag & ACTSTRIP_MUTE) {
357                                 glColor3f(1, 0, 0); 
358                                 glBegin(GL_LINES);
359                                 glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
360                                 glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
361                                 glEnd();
362                         }
363                         
364                         /* Draw border */
365                         glEnable (GL_BLEND);
366                         glBegin(GL_LINE_STRIP);
367                         glColor4f(1, 1, 1, 0.7); 
368                         
369                         glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
370                         glVertex2f(stripstart, channel_y+NLACHANNELHEIGHT/2-3);
371                         glVertex2f(stripend, channel_y+NLACHANNELHEIGHT/2-3);
372                         glColor4f(0, 0, 0, 0.7); 
373                         glVertex2f(stripend, channel_y-NLACHANNELHEIGHT/2+3);
374                         glVertex2f(stripstart, channel_y-NLACHANNELHEIGHT/2+3);
375                         glEnd();
376                         
377                         /* Show strip extension */
378                         if (strip->flag & ACTSTRIP_HOLDLASTFRAME){
379                                 if (strip->flag & ACTSTRIP_SELECT)
380                                         BIF_ThemeColorShadeAlpha(TH_STRIP_SELECT, 0, -180);
381                                 else
382                                         BIF_ThemeColorShadeAlpha(TH_STRIP, 0, -180);
383                                 
384                                 glRectf(stripend,  channel_y-NLACHANNELHEIGHT/2+4,  G.v2d->hor.xmax,  channel_y+NLACHANNELHEIGHT/2-2);
385                         }
386                         
387                         /* Show repeat */
388                         if (strip->repeat > 1.0 && !(strip->flag & ACTSTRIP_USESTRIDE)){
389                                 float rep = 1;
390                                 glBegin(GL_LINES);
391                                 while (rep<strip->repeat){
392                                         /* Draw line */ 
393                                         glColor4f(0, 0, 0, 0.5); 
394                                         gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
395                                         glVertex2f(frame1_x, channel_y-NLACHANNELHEIGHT/2+4);
396                                         glVertex2f(frame1_x, channel_y+NLACHANNELHEIGHT/2-2);
397                                         
398                                         glColor4f(1.0, 1.0, 1.0, 0.5); 
399                                         gla2DDrawTranslatePt(di, strip->start+(rep*((strip->end-strip->start)/strip->repeat)), y, &frame1_x, &channel_y);
400                                         glVertex2f(frame1_x+1, channel_y-NLACHANNELHEIGHT/2+4);
401                                         glVertex2f(frame1_x+1, channel_y+NLACHANNELHEIGHT/2-2);
402                                         rep+=1.0;
403                                 }
404                                 glEnd();
405                                 
406                         }
407                         glDisable (GL_BLEND);
408                         
409                         y-=(NLACHANNELHEIGHT+NLACHANNELSKIP);
410                 }
411         }
412         glaEnd2DDraw(di);
413         
414 }
415
416 /* ******* panel *********** */
417
418 #define B_NLA_PANEL             121
419 #define B_NLA_LOCK              122
420 #define B_NLA_MOD_ADD   123
421 #define B_NLA_MOD_NEXT  124
422 #define B_NLA_MOD_PREV  125
423 #define B_NLA_MOD_DEL   126
424 #define B_NLA_MOD_DEPS  127
425
426 /* For now just returns the first selected strip */
427 bActionStrip *get_active_nlastrip(Object **obpp)
428 {
429         Base *base;
430         bActionStrip *strip;
431         
432         for (base=G.scene->base.first; base; base=base->next){
433                 for (strip=base->object->nlastrips.first; strip; strip=strip->next){
434                         if (strip->flag & ACTSTRIP_SELECT) {
435                                 *obpp= base->object;
436                                 return strip;
437                         }
438                 }
439         }
440         
441         return NULL;
442 }
443
444 void do_nlabuts(unsigned short event)
445 {
446         Object *ob;
447         bActionStrip *strip;
448                 
449         /* Determine if an nla strip has been selected */
450         strip = get_active_nlastrip(&ob);
451         if (!strip) return;
452         
453         switch(event) {
454         case B_REDR:
455                 allqueue(REDRAWVIEW3D, 0);
456                 allqueue(REDRAWNLA, 0);
457                 break;
458         case B_NLA_PANEL:
459                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
460                 allqueue (REDRAWNLA, 0);
461                 allqueue (REDRAWVIEW3D, 0);
462                 break;
463         case B_NLA_LOCK:
464                 synchronize_action_strips();
465                 allqueue (REDRAWNLA, 0);
466                 allqueue (REDRAWACTION, 0);
467                 allqueue (REDRAWVIEW3D, 0);
468                 break;
469                 
470         case B_NLA_MOD_ADD:
471                 {
472                         bActionModifier *amod= MEM_callocN(sizeof(bActionModifier), "bActionModifier");
473                         
474                         BLI_addtail(&strip->modifiers, amod);
475                         strip->curmod= BLI_countlist(&strip->modifiers)-1;
476                         allqueue (REDRAWNLA, 0);
477                 }
478                 break;
479         case B_NLA_MOD_DEL:
480                 if(strip->modifiers.first) {
481                         bActionModifier *amod= BLI_findlink(&strip->modifiers, strip->curmod);
482                         BLI_remlink(&strip->modifiers, amod);
483                         MEM_freeN(amod);
484                         if(strip->curmod) strip->curmod--;
485                         allqueue (REDRAWNLA, 0);
486                 }
487                 break;
488         case B_NLA_MOD_NEXT:
489                 if(strip->curmod < BLI_countlist(&strip->modifiers)-1)
490                         strip->curmod++;
491                 allqueue (REDRAWNLA, 0);
492                 break;
493         case B_NLA_MOD_PREV:
494                 if(strip->curmod > 0)
495                         strip->curmod--;
496                 allqueue (REDRAWNLA, 0);
497                 break;
498         case B_NLA_MOD_DEPS:
499                 DAG_scene_sort(G.scene);
500                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
501                 break;
502         }
503 }
504
505 static char *make_modifier_menu(ListBase *lb)
506 {
507         bActionModifier *amod;
508         int index= 1;
509         char *str, item[64], *types[3]={"Deform", "Noise", "Oomph"};
510         
511         for (amod = lb->first; amod; amod=amod->next, index++);
512         str= MEM_mallocN(index*64, "key string");
513         str[0]= 0;
514         
515         index= 0;
516         for (amod = lb->first; amod; amod=amod->next, index++) {
517                 sprintf (item,  "|%s %s%%x%d", types[amod->type], amod->channel, index);
518                 strcat(str, item);
519         }
520         
521         return str;
522 }
523
524
525 static void nla_panel_properties(short cntrl)   // NLA_HANDLER_PROPERTIES
526 {
527         Object *ob;
528         bActionStrip *strip;
529         uiBlock *block;
530         uiBut *but;
531
532         block= uiNewBlock(&curarea->uiblocks, "nla_panel_properties", UI_EMBOSS, UI_HELV, curarea->win);
533         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl);
534         uiSetPanelHandler(NLA_HANDLER_PROPERTIES);  // for close and esc
535         if(uiNewPanel(curarea, block, "Transform Properties", "NLA", 10, 230, 318, 224)==0) return;
536
537         /* Determine if an nla strip has been selected */
538         strip = get_active_nlastrip(&ob);
539         if (!strip) return;
540         
541         /* first labels, for simpler align code :) */
542         uiDefBut(block, LABEL, 0, "Timeline Range:",    10,180,300,19, 0, 0, 0, 0, 0, "");
543         uiDefBut(block, LABEL, 0, "Blending:",                  10,120,150,19, 0, 0, 0, 0, 0, "");
544         uiDefBut(block, LABEL, 0, "Options:",                   160,120,150,19, 0, 0, 0, 0, 0, "");
545
546         uiBlockBeginAlign(block);
547         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");
548         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");
549
550         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");
551         if(strip->flag & ACTSTRIP_LOCK_ACTION) {
552                 char str[40];
553                 sprintf(str, "Action Start: %.2f", strip->actstart);
554                 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");
555                 sprintf(str, "Action End: %.2f", strip->actend);
556                 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");
557         }
558         else {
559                 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");
560                 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");
561         }
562         
563         uiBlockBeginAlign(block);
564         uiDefButF(block, NUM, B_NLA_PANEL, "Blendin:",                          10,100,145,19, &strip->blendin, 0.0, strip->end-strip->start, 100, 0, "Number of frames of ease-in");
565         uiDefButF(block, NUM, B_NLA_PANEL, "Blendout:",                         10,80,145,19, &strip->blendout, 0.0, strip->end-strip->start, 100, 0, "Number of frames of ease-out");
566         uiDefButBitS(block, TOG, ACTSTRIP_MUTE, B_NLA_PANEL, "Mute", 10,60,145,19, &strip->flag, 0, 0, 0, 0, "Toggles whether the strip contributes to the NLA solution");
567         
568         uiBlockBeginAlign(block);
569         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");
570         but= uiDefButC(block, TEX, B_NLA_PANEL, "OffsBone:", 160,80,150,19, strip->offs_bone, 0, 31.0f, 0, 0, "Name of Bone that defines offset for repeat");
571         uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob);
572         uiDefButBitS(block, TOG, ACTSTRIP_HOLDLASTFRAME, B_NLA_PANEL, "Hold",   160,60,75,19, &strip->flag, 0, 0, 0, 0, "Toggles whether to continue displaying the last frame past the end of the strip");
573         uiDefButS(block, TOG, B_NLA_PANEL, "Add",                                                               235,60,75,19, &strip->mode, 0, 0, 0, 0, "Toggles additive blending mode");
574         uiBlockEndAlign(block);
575         
576         uiDefButBitS(block, TOG, ACTSTRIP_USESTRIDE, B_NLA_PANEL, "Stride Path",        10, 30,140,19, &strip->flag, 0, 0, 0, 0, "Plays action based on path position & stride");
577         
578         if(ob->dup_group)
579                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_NLA_PANEL, "Target:",   160,30, 150, 19, &strip->object, "Target Object in this group"); 
580         
581         if(strip->flag & ACTSTRIP_USESTRIDE) {
582                 uiBlockBeginAlign(block);
583                 uiDefButBitS(block, TOG, OB_DISABLE_PATH, B_NLA_PANEL, "Disable",       10,0,60,19, &ob->ipoflag, 0, 0, 0, 0, "Disable path temporally, for editing cycles");
584                 
585                 uiDefButF(block, NUM, B_NLA_PANEL, "Offs:",                     70,0,120,19, &strip->actoffs, -500, 500.0, 100, 0, "Action offset in frames to tweak cycle of the action within the stride");
586                 uiDefButF(block, NUM, B_NLA_PANEL, "Stri:",                     190,0,120,19, &strip->stridelen, 0.0001, 1000.0, 100, 0, "Distance covered by one complete cycle of the action specified in the Action Range");
587                 
588                 uiDefButS(block, ROW, B_NLA_PANEL, "X",                         10, -20, 33, 19, &strip->stride_axis, 1, 0, 0, 0, "Dominant axis for Stride Bone");
589                 uiDefButS(block, ROW, B_NLA_PANEL, "Y",                         43, -20, 33, 19, &strip->stride_axis, 1, 1, 0, 0, "Dominant axis for Stride Bone");
590                 uiDefButS(block, ROW, B_NLA_PANEL, "Z",                         76, -20, 34, 19, &strip->stride_axis, 1, 2, 0, 0, "Dominant axis for Stride Bone");
591                 
592                 but= uiDefBut(block, TEX, B_NLA_PANEL, "Stride Bone:",  110, -20, 200, 19, strip->stridechannel, 1, 31, 0, 0, "Name of Bone used for stride");
593                 uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob);
594         }
595         else {  /* modifiers */
596                 bActionModifier *amod= BLI_findlink(&strip->modifiers, strip->curmod);
597                 
598                 uiBlockBeginAlign(block);
599                 uiDefBut(block, BUT, B_NLA_MOD_ADD, "Add Modifier",                             10,0,140,19, NULL, 0, 0, 0, 0, "");
600                 if(amod) {
601                         char *strp= make_modifier_menu(&strip->modifiers);
602                         
603                         uiDefIconBut(block, BUT, B_NLA_MOD_NEXT, ICON_TRIA_LEFT,        150,0,20,19, NULL, 0, 0, 0, 0, "Previous Modifier");
604                         uiDefButS(block, MENU, B_NLA_PANEL, strp,                                       170,0,20,19, &strip->curmod, 0, 0, 0, 0, "Browse modifier");
605                         MEM_freeN(strp);
606                         uiDefIconBut(block, BUT, B_NLA_MOD_PREV, ICON_TRIA_RIGHT,       190,0,20,19, NULL, 0, 0, 0, 0, "Next Modifier");
607                         uiDefButS(block, MENU, B_REDR, "Deform %x0|Noise %x1|Oomph %x2",        210,0,80,19, &amod->type, 0, 0, 0, 0, "Modifier type");
608                         uiDefIconBut(block, BUT, B_NLA_MOD_DEL, ICON_X,                         290,0,20,19, NULL, 0, 0, 0, 0, "Delete Modifier");
609                         
610                         if(amod->type==ACTSTRIP_MOD_DEFORM) {
611                                 but= uiDefBut(block, TEX, B_NLA_PANEL, "Chan:",                         10, -20, 130, 19, amod->channel, 1, 31, 0, 0, "Name of channel used for modifier");
612                                 uiButSetCompleteFunc(but, autocomplete_bone, (void *)ob);
613                                 uiDefButS(block, MENU, B_REDR, "All%x0|XY%x3|XZ%x2|YZ%x1",      140,-20,40,19, &amod->no_rot_axis, 0, 0, 0, 0, "Enable rotation axes (local for curve)");
614                                 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_NLA_MOD_DEPS, "Ob:",    180,-20, 130, 19, &amod->ob, "Curve Object"); 
615                         }
616                         else
617                                 uiDefBut(block, LABEL, B_NOP, "Ack! Not implemented.",  10, -20, 150, 19, NULL, 0, 0, 0, 0, "");
618                                 
619                 }
620                 else { /* for panel aligning */
621                         uiBlockEndAlign(block);
622                         uiDefBut(block, LABEL, B_NOP, " ",                              10, -20, 150, 19, NULL, 0, 0, 0, 0, "");
623                 }
624         }
625 }
626
627 static void nla_blockhandlers(ScrArea *sa)
628 {
629         SpaceNla *snla= sa->spacedata.first;
630         short a;
631         
632         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
633                 switch(snla->blockhandler[a]) {
634
635                 case NLA_HANDLER_PROPERTIES:
636                         nla_panel_properties(snla->blockhandler[a+1]);
637                         break;
638                 
639                 }
640                 /* clear action value for event */
641                 snla->blockhandler[a+1]= 0;
642         }
643         uiDrawBlocksPanels(sa, 0);
644 }
645
646
647 void drawnlaspace(ScrArea *sa, void *spacedata)
648 {
649         SpaceNla *snla= G.snla;
650         float col[3];
651         short ofsx = 0, ofsy = 0;
652         
653         uiFreeBlocksWin(&sa->uiblocks, sa->win);        /* for panel handler to work */
654
655         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
656         
657         calc_scrollrcts(sa, G.v2d, curarea->winx, curarea->winy);
658         
659         /* clear all, becomes the color for left part */
660         BIF_GetThemeColor3fv(TH_HEADER, col);
661         glClearColor(col[0], col[1], col[2], 0.0); 
662         glClear(GL_COLOR_BUFFER_BIT);
663         
664         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
665                 if(G.v2d->scroll) {     
666                         ofsx= curarea->winrct.xmin;     
667                         ofsy= curarea->winrct.ymin;
668                         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); 
669                         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);
670                 }
671         }
672         
673         BIF_GetThemeColor3fv(TH_BACK, col);
674         glClearColor(col[0], col[1], col[2], 0.0);
675         glClear(GL_COLOR_BUFFER_BIT);
676         
677         myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
678         bwin_clear_viewmat(sa->win);    /* clear buttons view */
679         glLoadIdentity();
680         
681         /*      Draw backdrop */
682         calc_ipogrid(); 
683         draw_ipogrid();
684
685         /* the right hand side, with strips and keys */
686         draw_nla_strips_keys(G.snla);
687
688         /* Draw current frame */
689         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); 
690         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);
691         myortho2 (G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
692         draw_cfra_action();
693         
694         /* draw markers */
695         draw_markers_timespace(&(snla->v2d));
696
697         /* Draw scroll */
698         mywinset(curarea->win); // reset scissor too
699         if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
700                 myortho2(-0.375, curarea->winx-0.375, -0.375, curarea->winy-0.375);
701                 if(G.v2d->scroll) drawscroll(0);
702         }
703         if(G.v2d->mask.xmin!=0) {
704                 /* Draw channel names */
705                 draw_nla_channels();
706         }
707         mywinset(curarea->win); // reset scissor too
708         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
709         draw_area_emboss(sa);
710         
711         /* it is important to end a view in a transform compatible with buttons */
712         bwin_scalematrix(sa->win, G.snla->blockscale, G.snla->blockscale, G.snla->blockscale);
713         nla_blockhandlers(sa);
714
715         curarea->win_swap= WIN_BACK_OK;
716 }
717
718 int count_nla_levels(void)
719 {
720         Base *base;
721         int y=0;
722
723         for (y=0, base=G.scene->base.first; base; base=base->next) {
724                 if (nla_filter(base)) {
725                         /* object level */
726                         y++;
727
728                         if(base->object->action)
729                                 y++;
730                         
731                         /* Nla strips */
732                         y+= BLI_countlist(&base->object->nlastrips);
733                 }
734         }
735
736         return y;
737 }
738
739 int nla_filter (Base *base)
740 {
741         Object *ob = base->object;
742         
743         if(base->lay & G.scene->lay) {
744                 if(ob->action || ob->nlastrips.first) 
745                         return 1;
746
747                 /* should become option */
748                 if (ob->ipo)
749                         return 1;
750
751                 if (ob->constraintChannels.first)
752                         return 1;
753         }
754         return 0;
755 }
756