cd92621875769e9108c9171abd2119ce080ea16e
[blender-staging.git] / source / blender / editors / space_nla / nla_buttons.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL 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. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation, Joshua Leung
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <string.h>
30 #include <stdio.h>
31 #include <math.h>
32 #include <float.h>
33
34 #include "DNA_anim_types.h"
35 #include "DNA_action_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_space_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_userdef_types.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_math.h"
45 #include "BLI_blenlib.h"
46 #include "BLI_editVert.h"
47 #include "BLI_rand.h"
48
49 #include "BKE_animsys.h"
50 #include "BKE_nla.h"
51 #include "BKE_action.h"
52 #include "BKE_context.h"
53 #include "BKE_curve.h"
54 #include "BKE_customdata.h"
55 #include "BKE_depsgraph.h"
56 #include "BKE_fcurve.h"
57 #include "BKE_object.h"
58 #include "BKE_global.h"
59 #include "BKE_scene.h"
60 #include "BKE_screen.h"
61 #include "BKE_utildefines.h"
62
63 #include "BIF_gl.h"
64
65 #include "WM_api.h"
66 #include "WM_types.h"
67
68 #include "RNA_access.h"
69 #include "RNA_define.h"
70
71 #include "ED_anim_api.h"
72 #include "ED_keyframing.h"
73 #include "ED_screen.h"
74 #include "ED_types.h"
75 #include "ED_util.h"
76
77 #include "UI_interface.h"
78 #include "UI_resources.h"
79 #include "UI_view2d.h"
80
81 #include "nla_intern.h" // own include
82
83
84 /* ******************* nla editor space & buttons ************** */
85
86 #define B_NOP           1
87 #define B_REDR          2
88
89 /* -------------- */
90
91 static void do_nla_region_buttons(bContext *C, void *arg, int event)
92 {
93         //Scene *scene= CTX_data_scene(C);
94         
95         switch(event) {
96
97         }
98         
99         /* default for now */
100         WM_event_add_notifier(C, NC_SCENE|NC_OBJECT|ND_TRANSFORM, NULL);
101 }
102
103 static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_ptr, PointerRNA *strip_ptr)
104 {
105         bAnimContext ac;
106         bAnimListElem *ale= NULL;
107         ListBase anim_data = {NULL, NULL};
108         short found=0;
109         int filter;
110         
111         /* for now, only draw if we could init the anim-context info (necessary for all animation-related tools) 
112          * to work correctly is able to be correctly retrieved. There's no point showing empty panels?
113          */
114         if (ANIM_animdata_get_context(C, &ac) == 0) 
115                 return 0;
116         
117         /* extract list of active channel(s), of which we should only take the first one 
118          *      - we need the channels flag to get the active AnimData block when there are no NLA Tracks
119          */
120         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_ACTIVE|ANIMFILTER_CHANNELS);
121         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
122         
123         for (ale= anim_data.first; ale; ale= ale->next) {
124                 switch (ale->type) {
125                         case ANIMTYPE_NLATRACK: /* NLA Track - The primary data type which should get caught */
126                         {
127                                 NlaTrack *nlt= (NlaTrack *)ale->data;
128                                 AnimData *adt= ale->adt;
129                                 
130                                 /* found it, now set the pointers */
131                                 if (adt_ptr) {
132                                         /* AnimData pointer */
133                                         RNA_pointer_create(ale->id, &RNA_AnimData, adt, adt_ptr);
134                                 }
135                                 if (nlt_ptr) {
136                                         /* NLA-Track pointer */
137                                         RNA_pointer_create(ale->id, &RNA_NlaTrack, nlt, nlt_ptr);
138                                 }
139                                 if (strip_ptr) {
140                                         /* NLA-Strip pointer */
141                                         NlaStrip *strip= BKE_nlastrip_find_active(nlt);
142                                         RNA_pointer_create(ale->id, &RNA_NlaStrip, strip, strip_ptr);
143                                 }
144                                 
145                                 found= 1;
146                         }
147                                 break;
148                                 
149                         case ANIMTYPE_SCENE:    /* Top-Level Widgets doubling up as datablocks */
150                         case ANIMTYPE_OBJECT:
151                         case ANIMTYPE_FILLACTD: /* Action Expander */
152                         case ANIMTYPE_DSMAT:    /* Datablock AnimData Expanders */
153                         case ANIMTYPE_DSLAM:
154                         case ANIMTYPE_DSCAM:
155                         case ANIMTYPE_DSCUR:
156                         case ANIMTYPE_DSSKEY:
157                         case ANIMTYPE_DSWOR:
158                         case ANIMTYPE_DSNTREE:
159                         case ANIMTYPE_DSPART:
160                         case ANIMTYPE_DSMBALL:
161                         case ANIMTYPE_DSARM:
162                         {
163                                 /* for these channels, we only do AnimData */
164                                 if (ale->id && ale->adt) {
165                                         if (adt_ptr) {
166                                                 /* AnimData pointer */
167                                                 RNA_pointer_create(ale->id, &RNA_AnimData, ale->adt, adt_ptr);
168                                                 
169                                                 /* set found status to -1, since setting to 1 would break the loop 
170                                                  * and potentially skip an active NLA-Track in some cases...
171                                                  */
172                                                 found= -1;
173                                         }
174                                 }
175                         }       
176                                 break;
177                 }
178                 
179                 if (found > 0)
180                         break;
181         }
182         
183         /* free temp data */
184         BLI_freelistN(&anim_data);
185         
186         return found;
187 }
188
189 #if 0
190 static int nla_panel_poll(const bContext *C, PanelType *pt)
191 {
192         return nla_panel_context(C, NULL, NULL);
193 }
194 #endif
195
196 static int nla_animdata_panel_poll(const bContext *C, PanelType *pt)
197 {
198         PointerRNA ptr;
199         return (nla_panel_context(C, &ptr, NULL, NULL) && (ptr.data != NULL));
200 }
201
202 static int nla_track_panel_poll(const bContext *C, PanelType *pt)
203 {
204         PointerRNA ptr;
205         return (nla_panel_context(C, NULL, &ptr, NULL) && (ptr.data != NULL));
206 }
207
208 static int nla_strip_panel_poll(const bContext *C, PanelType *pt)
209 {
210         PointerRNA ptr;
211         return (nla_panel_context(C, NULL, NULL, &ptr) && (ptr.data != NULL));
212 }
213
214 static int nla_strip_actclip_panel_poll(const bContext *C, PanelType *pt)
215 {
216         PointerRNA ptr;
217         NlaStrip *strip;
218         
219         if (!nla_panel_context(C, NULL, NULL, &ptr))
220                 return 0;
221         if (ptr.data == NULL)
222                 return 0;
223         
224         strip= ptr.data;
225         return (strip->type == NLASTRIP_TYPE_CLIP);
226 }
227
228 /* -------------- */
229
230 /* active AnimData */
231 static void nla_panel_animdata (const bContext *C, Panel *pa)
232 {
233         PointerRNA adt_ptr;
234         AnimData *adt;
235         uiLayout *layout= pa->layout;
236         uiLayout *row;
237         uiBlock *block;
238         
239         /* check context and also validity of pointer */
240         if (!nla_panel_context(C, &adt_ptr, NULL, NULL))
241                 return;
242         adt= adt_ptr.data;
243         
244         block= uiLayoutGetBlock(layout);
245         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
246         
247         /* Active Action Properties ------------------------------------- */
248         /* action */
249         row= uiLayoutRow(layout, 1);
250                 uiTemplateID(row, (bContext *)C, &adt_ptr, "action", "ACTION_OT_new", NULL, NULL /*"ACTION_OT_unlink"*/); // XXX: need to make these operators
251         
252         /* extrapolation */
253         row= uiLayoutRow(layout, 1);
254                 uiItemR(row, NULL, 0, &adt_ptr, "action_extrapolation", 0);
255         
256         /* blending */
257         row= uiLayoutRow(layout, 1);
258                 uiItemR(row, NULL, 0, &adt_ptr, "action_blending", 0);  
259                 
260         /* influence */
261         row= uiLayoutRow(layout, 1);
262                 uiItemR(row, NULL, 0, &adt_ptr, "action_influence", 0);
263 }
264
265 /* active NLA-Track */
266 static void nla_panel_track (const bContext *C, Panel *pa)
267 {
268         PointerRNA nlt_ptr;
269         uiLayout *layout= pa->layout;
270         uiLayout *row;
271         uiBlock *block;
272         
273         /* check context and also validity of pointer */
274         if (!nla_panel_context(C, NULL, &nlt_ptr, NULL))
275                 return;
276         
277         block= uiLayoutGetBlock(layout);
278         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
279         
280         /* Info - Active NLA-Context:Track ----------------------  */
281         row= uiLayoutRow(layout, 1);
282                 uiItemR(row, NULL, ICON_NLA, &nlt_ptr, "name", 0);
283 }
284
285 /* generic settings for active NLA-Strip */
286 static void nla_panel_properties(const bContext *C, Panel *pa)
287 {
288         PointerRNA strip_ptr;
289         uiLayout *layout= pa->layout;
290         uiLayout *column, *row, *subcol;
291         uiBlock *block;
292         
293         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
294                 return;
295         
296         block= uiLayoutGetBlock(layout);
297         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
298         
299         /* Strip Properties ------------------------------------- */
300         /* strip type */
301         row= uiLayoutColumn(layout, 1);
302                 uiItemR(row, NULL, ICON_NLA, &strip_ptr, "name", 0); // XXX icon?
303                 uiItemR(row, NULL, 0, &strip_ptr, "type", 0);
304         
305         /* strip extents */
306         column= uiLayoutColumn(layout, 1);
307                 uiItemL(column, "Strip Extents:", 0);
308                 uiItemR(column, NULL, 0, &strip_ptr, "start_frame", 0);
309                 uiItemR(column, NULL, 0, &strip_ptr, "end_frame", 0);
310         
311         /* extrapolation */
312         row= uiLayoutRow(layout, 1);
313                 uiItemR(row, NULL, 0, &strip_ptr, "extrapolation", 0);
314         
315         /* blending */
316         row= uiLayoutRow(layout, 1);
317                 uiItemR(row, NULL, 0, &strip_ptr, "blending", 0);
318                 
319         /* blend in/out + autoblending
320          *      - blend in/out can only be set when autoblending is off
321          */
322         column= uiLayoutColumn(layout, 1);
323                 uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_influence")==0); 
324                 uiItemR(column, NULL, 0, &strip_ptr, "auto_blending", 0); // XXX as toggle?
325                 
326                 subcol= uiLayoutColumn(column, 1);
327                         uiLayoutSetActive(subcol, RNA_boolean_get(&strip_ptr, "auto_blending")==0); 
328                         uiItemR(subcol, NULL, 0, &strip_ptr, "blend_in", 0);
329                         uiItemR(subcol, NULL, 0, &strip_ptr, "blend_out", 0);
330                 
331         /* settings */
332         column= uiLayoutColumn(layout, 1);
333                 uiLayoutSetActive(column, !(RNA_boolean_get(&strip_ptr, "animated_influence") || RNA_boolean_get(&strip_ptr, "animated_time"))); 
334                 uiItemL(column, "Playback Settings:", 0);
335                 uiItemR(column, NULL, 0, &strip_ptr, "muted", 0);
336                 uiItemR(column, NULL, 0, &strip_ptr, "reversed", 0);
337 }
338
339
340 /* action-clip only settings for active NLA-Strip */
341 static void nla_panel_actclip(const bContext *C, Panel *pa)
342 {
343         PointerRNA strip_ptr;
344         uiLayout *layout= pa->layout;
345         uiLayout *column, *row;
346         uiBlock *block;
347
348         /* check context and also validity of pointer */
349         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
350                 return;
351         
352         block= uiLayoutGetBlock(layout);
353         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
354                 
355         /* Strip Properties ------------------------------------- */
356         /* action pointer */
357         row= uiLayoutRow(layout, 1);
358                 uiItemR(row, NULL, ICON_ACTION, &strip_ptr, "action", 0);
359                 
360         /* action extents */
361         // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future?
362         column= uiLayoutColumn(layout, 1);
363                 uiItemL(column, "Action Extents:", 0);
364                 uiItemR(column, "Start Frame", 0, &strip_ptr, "action_start_frame", 0);
365                 uiItemR(column, "End Frame", 0, &strip_ptr, "action_end_frame", 0);
366                 uiItemO(column, NULL, 0, "NLA_OT_action_sync_length");
367                 
368         /* action usage */
369         column= uiLayoutColumn(layout, 1);
370                 uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "animated_time")==0); 
371                 uiItemL(column, "Playback Settings:", 0);
372                 uiItemR(column, NULL, 0, &strip_ptr, "scale", 0);
373                 uiItemR(column, NULL, 0, &strip_ptr, "repeat", 0);
374 }
375
376 /* evaluation settings for active NLA-Strip */
377 static void nla_panel_evaluation(const bContext *C, Panel *pa)
378 {
379         PointerRNA strip_ptr;
380         uiLayout *layout= pa->layout;
381         uiLayout *column, *subcolumn;
382         uiBlock *block;
383
384         /* check context and also validity of pointer */
385         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
386                 return;
387                 
388         block= uiLayoutGetBlock(layout);
389         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
390                 
391         column= uiLayoutColumn(layout, 1);
392                 uiItemR(column, NULL, 0, &strip_ptr, "animated_influence", 0);
393                 
394                 subcolumn= uiLayoutColumn(column, 1);
395                 uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_influence"));       
396                         uiItemR(subcolumn, NULL, 0, &strip_ptr, "influence", 0);
397                 
398         
399         column= uiLayoutColumn(layout, 1);
400                 uiItemR(column, NULL, 0, &strip_ptr, "animated_time", 0);
401                 
402                 subcolumn= uiLayoutColumn(column, 1);
403                 uiLayoutSetEnabled(subcolumn, RNA_boolean_get(&strip_ptr, "animated_time"));
404                         uiItemR(subcolumn, NULL, 0, &strip_ptr, "strip_time", 0);
405 }
406
407 /* F-Modifiers for active NLA-Strip */
408 static void nla_panel_modifiers(const bContext *C, Panel *pa)
409 {
410         PointerRNA strip_ptr;
411         NlaStrip *strip;
412         FModifier *fcm;
413         uiLayout *col, *row;
414         uiBlock *block;
415
416         /* check context and also validity of pointer */
417         if (!nla_panel_context(C, NULL, NULL, &strip_ptr))
418                 return;
419         strip= strip_ptr.data;
420                 
421         block= uiLayoutGetBlock(pa->layout);
422         uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL);
423         
424         /* 'add modifier' button at top of panel */
425         {
426                 row= uiLayoutRow(pa->layout, 0);
427                 block= uiLayoutGetBlock(row);
428                 
429                 // XXX for now, this will be a operator button which calls a temporary 'add modifier' operator
430                 // FIXME: we need to set the only-active property so that this will only add modifiers for the active strip (not all selected)
431                 uiDefButO(block, BUT, "NLA_OT_fmodifier_add", WM_OP_INVOKE_REGION_WIN, "Add Modifier", 10, 0, 150, 20, "Adds a new F-Modifier for the active NLA Strip");
432         }
433         
434         /* draw each modifier */
435         for (fcm= strip->modifiers.first; fcm; fcm= fcm->next) {
436                 col= uiLayoutColumn(pa->layout, 1);
437                 
438                 ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm);
439         }
440 }
441
442 /* ******************* general ******************************** */
443
444
445 void nla_buttons_register(ARegionType *art)
446 {
447         PanelType *pt;
448         
449         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel animdata");
450         strcpy(pt->idname, "NLA_PT_animdata");
451         strcpy(pt->label, "Animation Data");
452         pt->draw= nla_panel_animdata;
453         pt->poll= nla_animdata_panel_poll;
454         pt->flag= PNL_DEFAULT_CLOSED;
455         BLI_addtail(&art->paneltypes, pt);
456         
457         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel track");
458         strcpy(pt->idname, "NLA_PT_track");
459         strcpy(pt->label, "Active Track");
460         pt->draw= nla_panel_track;
461         pt->poll= nla_track_panel_poll;
462         BLI_addtail(&art->paneltypes, pt);
463         
464         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
465         strcpy(pt->idname, "NLA_PT_properties");
466         strcpy(pt->label, "Active Strip");
467         pt->draw= nla_panel_properties;
468         pt->poll= nla_strip_panel_poll;
469         BLI_addtail(&art->paneltypes, pt);
470         
471         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel properties");
472         strcpy(pt->idname, "NLA_PT_actionclip");
473         strcpy(pt->label, "Action Clip");
474         pt->draw= nla_panel_actclip;
475         pt->poll= nla_strip_actclip_panel_poll;
476         BLI_addtail(&art->paneltypes, pt);
477         
478         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel evaluation");
479         strcpy(pt->idname, "NLA_PT_evaluation");
480         strcpy(pt->label, "Evaluation");
481         pt->draw= nla_panel_evaluation;
482         pt->poll= nla_strip_panel_poll;
483         BLI_addtail(&art->paneltypes, pt);
484         
485         pt= MEM_callocN(sizeof(PanelType), "spacetype nla panel modifiers");
486         strcpy(pt->idname, "NLA_PT_modifiers");
487         strcpy(pt->label, "Modifiers");
488         pt->draw= nla_panel_modifiers;
489         pt->poll= nla_strip_panel_poll;
490         BLI_addtail(&art->paneltypes, pt);
491 }
492
493 static int nla_properties(bContext *C, wmOperator *op)
494 {
495         ScrArea *sa= CTX_wm_area(C);
496         ARegion *ar= nla_has_buttons_region(sa);
497         
498         if(ar)
499                 ED_region_toggle_hidden(C, ar);
500
501         return OPERATOR_FINISHED;
502 }
503
504 void NLA_OT_properties(wmOperatorType *ot)
505 {
506         ot->name= "Properties";
507         ot->idname= "NLA_OT_properties";
508         
509         ot->exec= nla_properties;
510         ot->poll= ED_operator_nla_active;
511         
512         /* flags */
513         ot->flag= 0;
514 }