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