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