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